Skip to content

Commit

Permalink
Merge pull request #1899 from liberapay/undefined
Browse files Browse the repository at this point in the history
  • Loading branch information
Changaco authored Dec 20, 2021
2 parents 7cde12f + 5eefbe3 commit 1f1a4b6
Show file tree
Hide file tree
Showing 37 changed files with 144 additions and 103 deletions.
4 changes: 2 additions & 2 deletions error.spt
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ user_agent = request.headers.get(b'User-Agent')
[----------------------------------------] text/html
% extends "templates/layouts/base.html"

% set title = '' if response.html_template else msg
% set title = '' if response.html_template is defined else msg

% block content
% if response.html_template
% if response.html_template is defined
% include response.html_template
% else
% if code >= 400 and code <= 499
Expand Down
1 change: 1 addition & 0 deletions liberapay/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def render_in_english(self):

class AuthRequired(LazyResponse):
html_template = 'templates/exceptions/AuthRequired.html'
no_navbar_sign_in = True

def __init__(self):
Response.__init__(self, 403, '')
Expand Down
33 changes: 16 additions & 17 deletions liberapay/models/participant.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
NormalizedEmailAddress, EmailVerificationResult, check_email_blacklist,
normalize_email_address,
)
from liberapay.utils.types import Object
from liberapay.utils.types import LocalizedString, Object
from liberapay.website import website


Expand Down Expand Up @@ -672,29 +672,28 @@ def require_reauthentication(self):
def get_statement(self, langs, type='profile'):
"""Get the participant's statement in the language that best matches
the list provided, or the participant's "primary" statement if there
are no matches. Returns a tuple `(content, lang)`.
If langs isn't a list but a string, then it's assumed to be a language
code and the corresponding statement content will be returned, or None.
are no matches. Returns a `LocalizedString` object.
"""
p_id = self.id
if not isinstance(langs, list):
return self.db.one("""
SELECT content
if isinstance(langs, str):
row = self.db.one("""
SELECT content, lang
FROM statements
WHERE participant = %(p_id)s
AND type = %(type)s
AND lang = %(langs)s
""", locals())
return self.db.one("""
SELECT content, lang
FROM statements
LEFT JOIN enumerate(%(langs)s::text[]) langs ON langs.value = statements.lang
WHERE participant = %(p_id)s
AND type = %(type)s
ORDER BY langs.rank NULLS LAST, statements.id
LIMIT 1
""", locals(), default=(None, None))
else:
row = self.db.one("""
SELECT content, lang
FROM statements
LEFT JOIN enumerate(%(langs)s::text[]) langs ON langs.value = statements.lang
WHERE participant = %(p_id)s
AND type = %(type)s
ORDER BY langs.rank NULLS LAST, statements.id
LIMIT 1
""", locals())
return LocalizedString(*row) if row else None

def get_statement_langs(self, type='profile'):
return self.db.all("""
Expand Down
3 changes: 1 addition & 2 deletions liberapay/utils/emails.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
InvalidEmailDomain, NonEmailDomain, TooManyAttempts,
)
from liberapay.utils import deserialize
from liberapay.website import website, CustomUndefined, JINJA_ENV_COMMON
from liberapay.website import website, JINJA_ENV_COMMON


class EmailVerificationResult(Enum):
Expand All @@ -34,7 +34,6 @@ class EmailVerificationResult(Enum):
SUCCEEDED = auto()


JINJA_ENV_COMMON = dict(JINJA_ENV_COMMON, undefined=CustomUndefined)
jinja_env = Environment(**JINJA_ENV_COMMON)
jinja_env_html = Environment(**dict(
JINJA_ENV_COMMON,
Expand Down
12 changes: 12 additions & 0 deletions liberapay/utils/types.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
from types import SimpleNamespace


class LocalizedString(str):
"""A string with a `lang` attribute containing an ISO language code.
"""

__slots__ = ('lang',)

def __new__(cls, obj, lang):
r = str.__new__(cls, obj)
r.lang = lang
return r


class Object(SimpleNamespace):
"""
A namespace that supports both attribute-style and dict-style lookups and
Expand Down
4 changes: 2 additions & 2 deletions liberapay/website.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def f(self, *a, **kw):
try:
self._fail_with_undefined_error()
except Exception as e:
website.tell_sentry(e)
website.tell_sentry(e, level='warning')
return method(self, *a, **kw)
return f

Expand All @@ -146,5 +146,5 @@ class CustomUndefined(Undefined):
line_statement_prefix='%',
auto_reload=env.aspen_changes_reload,
extensions=['jinja2.ext.do'],
# undefined=CustomUndefined,
undefined=CustomUndefined,
)
4 changes: 2 additions & 2 deletions simplates/confirm.spt
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
% extends "templates/layouts/base.html"

% block content
% set cls = cls or 'danger'
% set cls = cls|default('danger', true)
<form action="" method="POST">
% include "templates/form-repost.html"
<input type="hidden" name="confirmed" value="true" />
<div class="alert alert-{{ cls }}">{{ escape(msg).replace('\n', '<br>'|safe) }}</div>
<a class="btn btn-default" href="{{ response.sanitize_untrusted_url(back_to) if back_to else '' }}">{{ _("Cancel") }}</a>
<a class="btn btn-default" href="{{ response.sanitize_untrusted_url(back_to) if back_to|default('') }}">{{ _("Cancel") }}</a>
&nbsp;&nbsp;
<button class="btn btn-{{ cls }}">{{ _("Confirm") }}</button>
</form>
Expand Down
2 changes: 1 addition & 1 deletion templates/layouts/about.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
% from "templates/macros/nav.html" import nav_about with context
<nav class="nav-col">
<input id="subnav-about" class="subnav-toggler sr-only" type="checkbox" />
<label for="subnav-about">{{ title + (': ' + subhead if subhead else '') }} <span class="caret"></span></label>
<label for="subnav-about">{{ title + (': ' + subhead if subhead is defined else '') }} <span class="caret"></span></label>
<ul class="nav nav-tabs-left text-center">{{ nav_about() }}</ul>
</nav>
<div class="content-col">{% block content %}{% endblock %}</div>
Expand Down
2 changes: 1 addition & 1 deletion templates/layouts/admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<div class="content-col">{% block content %}{% endblock %}</div>
<nav class="nav-col">
<input id="subnav-admin" class="subnav-toggler sr-only" type="checkbox" />
<label for="subnav-admin">{{ title + (': ' + subhead if subhead else '') }} <span class="caret"></span></label>
<label for="subnav-admin">{{ title + (': ' + subhead if subhead is defined else '') }} <span class="caret"></span></label>
<ul class="nav nav-aside text-center">{{ nav_admin() }}</ul>
</nav>
</div>
Expand Down
6 changes: 5 additions & 1 deletion templates/layouts/base-thin.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
% block content
<div class="row">
<div class="col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2">
{% block heading %}<h1 class="main-title thin-title">{{ title }}</h1>{% endblock %}
% block heading
% if title is defined
<h1 class="main-title thin-title">{{ title }}</h1>
% endif
% endblock
{% block thin_content %}{% endblock %}
</div>
</div>
Expand Down
18 changes: 10 additions & 8 deletions templates/layouts/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
% if locale.completion < 0.5
<meta name="robots" content="noindex,nofollow" />
% endif
% set full_title = full_title or ' - '.join(map(str, filter(None, (subhead, title, 'Liberapay'))))
% if full_title is undefined
% set full_title = ' - '.join(map(str, filter(None, (subhead|default(''), title|default(''), 'Liberapay'))))
% endif
{% block head_early %}{% endblock %}
<title>{{ full_title }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Expand All @@ -30,14 +32,14 @@
% from "templates/macros/icons.html" import fontawesome, glyphicon
% from 'templates/macros/nav.html' import nav, nav_about, nav_explore with context
% from 'templates/macros/search.html' import search_form with context
<body id="{{ page_id or '' }}">
<body{% if page_id is defined %} id="{{ page_id }}"{% endif %}>

% if not website.db
<div class="notification notification-error">{{ _(
"We're currently experiencing technical failures. As a result most things don't work. "
"Sorry for the inconvenience, we'll get everything back to normal ASAP."
) }}</div>
% elif db_is_readonly
% elif db_is_readonly|default(False)
<div class="notification notification-error">{{ _(
"Liberapay is currently in read-only mode as we are migrating the database. "
"This shouldn't take more than a few minutes."
Expand All @@ -61,14 +63,14 @@
% endblock
% if user
% include "templates/layouts/components/navbar-logged-in.html"
% elif response.html_template != 'templates/exceptions/AuthRequired.html' and not no_navbar_sign_in
% elif response.no_navbar_sign_in|default(false)
% from "templates/macros/sign-in-link.html" import sign_in_link with context
<li>{{ sign_in_link('glyphicon glyphicon-log-in', 'navbar-btn') }}</li>
% endif
</ul>
<div class="collapse navbar-collapse navbar-left" id="navbar-liberapay-collapse">
<ul class="nav navbar-nav">
% if page_id != 'homepage'
% if page_id|default('') != 'homepage'
<li class="hidden-xs">
<a class="navbar-brand" href="/">{{ fontawesome('liberapay', _("Homepage")) }}</a></li>
<li class="visible-xs">
Expand Down Expand Up @@ -101,8 +103,8 @@
<div class="container">
% block before_content
% block heading
% if title
<h1 class="main-title {{ 'hidden-xs hidden-sm' if subhead else '' }}">{{ title }}</h1>
% if title is defined
<h1 class="main-title {{ 'hidden-xs hidden-sm' if subhead is defined else '' }}">{{ title }}</h1>
% endif
% endblock
<div id="subnav">{% block subnav %}{% endblock %}</div>
Expand Down Expand Up @@ -146,7 +148,7 @@ <h1 class="main-title {{ 'hidden-xs hidden-sm' if subhead else '' }}">{{ title }
</div>
% endif

% if state['partial_translation']
% if state.get('partial_translation')
% include "_i18n_warning.html"
% endif

Expand Down
2 changes: 1 addition & 1 deletion templates/layouts/explore.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
% from "templates/macros/nav.html" import nav_explore with context
<nav class="nav-col">
<input id="subnav-explore" class="subnav-toggler sr-only" type="checkbox" />
<label for="subnav-explore">{{ title + (': ' + subhead if subhead else '') }} <span class="caret"></span></label>
<label for="subnav-explore">{{ title + (': ' + subhead if subhead is defined else '') }} <span class="caret"></span></label>
<ul class="nav nav-tabs-left text-center">{{ nav_explore() }}</ul>
</nav>
% endif
Expand Down
2 changes: 1 addition & 1 deletion templates/layouts/profile.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ <h1>{{ participant.public_name }}<br><small>@{{ participant.username }}</small><
% else
<h1>{{ participant.username }}</h1>
% endif
<p class="summary" lang="{{ lang or '' }}">{{ summary or '' }}</p>
<p class="summary" lang="{{ lang|default('') }}">{{ summary|default('') }}</p>
</div>
</div>
<div class="col-md-offset-1 col-md-10 col-lg-offset-0 col-lg-2">{% block profile_btn %}{% endblock %}</div>
Expand Down
4 changes: 2 additions & 2 deletions templates/layouts/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
<div class="content-with-nav nav-left">
<nav class="nav-col">
<input id="subnav-settings" class="subnav-toggler sr-only" type="checkbox" />
<label for="subnav-settings">{{ title + (': ' + subhead if subhead else '') }} <span class="caret"></span></label>
<label for="subnav-settings">{{ title + (': ' + subhead if subhead is defined else '') }} <span class="caret"></span></label>
<ul class="nav nav-aside">
<li class="header">
% if state['can_switch_account'] and user.team_names
% if state.get('can_switch_account') and user.team_names
<div class="flex">
<h1>{{ participant.username }}</h1>
<label for="subnav-accounts" title="{{ _('Switch to a different account') }}" aria-hidden="true"><span class="caret"></span></label>
Expand Down
4 changes: 2 additions & 2 deletions templates/macros/identity.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ <h3>{{ _("Personal Information") }}</h3>

% if 'postal_address.country' in wanted
<label>
% set country = identity.postal_address['country'] or request.country
% set country = identity.postal_address.get('country') or request.country
<span>{{ _("Country (residence)") }}</span>
<select name="postal_address.country" class="form-control country" {{ required }}>
<option></option>
Expand Down Expand Up @@ -67,7 +67,7 @@ <h3>{{ _("Personal Information") }}</h3>
}}</span>
</span>
<input name="occupation" {{ required }} maxlength=200
class="form-control" value="{{ identity.occupation or '' }}" />
class="form-control" value="{{ identity.occupation }}" />
</label>
% endif

Expand Down
30 changes: 17 additions & 13 deletions templates/macros/nav.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,42 @@
% set current = request.path.raw[len(base):].strip('/')
% for item in items
% set slug = item[0].strip('/')
% set options = item[2] or {}
% set icon = options['icon']
% set options = item[2] if len(item) > 2 else {}
% set icon = options.get('icon')
% set icon = icon_span(icon) if icon else ''
% set dropdown = options.get('dropdown')
% set subnav = options.get('subnav')
% set togglable = options.get('togglable')
% set active = (
current == slug or
slug and current.startswith(slug) and (options['togglable'] or not options['subnav'])
slug and current.startswith(slug) and (togglable or not subnav)
)
% set classes = (options['class'] or '') + (' active' if active else '')
% set classes = (options.get('class') or '') + (' active' if active else '')
<li{% if classes %} class="{{ classes }}"{% endif %}>
% if options['dropdown']
% set button_extra_cls = 'dropdown-toggle-form' if options['form'] else ''
% if dropdown
% set button_extra_cls = 'dropdown-toggle-form' if options.get('form') else ''
<div class="dropdown dropdown-hover">
<a class="dropdown-toggle navbar-btn {{ button_extra_cls }}"
href="{{ base }}/{{ slug }}" data-toggle="dropdown" aria-expanded="true">
{{ icon }}
<span>{{ item[1] }}</span>
</a>
% if options['role']
<div class="dropdown-menu" role="{{ options['role'] }}">{{ options['dropdown'] }}</div>
% set role = options.get('role')
% if role
<div class="dropdown-menu" role="{{ role }}">{{ dropdown }}</div>
% else
<ul class="dropdown-menu">{{ options['dropdown'] }}</ul>
<ul class="dropdown-menu">{{ dropdown }}</ul>
% endif
</div>
% elif options['subnav']
% if options['togglable']
% elif subnav
% if togglable
<input id="subnav-{{ id(item) }}" class="subnav-toggler sr-only" type="checkbox" {% if active %} checked {% endif %}
aria-label="{{ _('Show the {submenu_label} submenu', submenu_label=item[1]) }}" />
<label for="subnav-{{ id(item) }}">{{ icon }} {{ item[1] }} <span class="caret"></span></label>
<ul class="nav level2 togglable">{{ options['subnav'] }}</ul>
<ul class="nav level2 togglable">{{ subnav }}</ul>
% else
<a href="{{ base }}/{{ slug }}">{{ icon }} {{ item[1] }}</a>
<ul class="nav level2">{{ options['subnav'] }}</ul>
<ul class="nav level2">{{ subnav }}</ul>
% endif
% elif slug != None
<a href="{{ base }}/{{ slug }}">{{ icon }} {{ item[1] }}</a>
Expand Down
10 changes: 5 additions & 5 deletions templates/macros/postal-addresses.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<span>{{ _("Country") }}</span>
<select name="{{ prefix }}.country" class="form-control country" {{ required }}>
<option></option>
% set country = saved.country or request.country
% set country = saved.country|default('') or request.country
% for code, name in locale.countries.items()
<option value="{{ code }}" {{ 'selected' if code == country }}>{{ name }}</option>
% endfor
Expand All @@ -24,25 +24,25 @@
}}</span>
</span>
<input name="{{ prefix }}.region" class="form-control" maxlength=100
value="{{ saved.region or '' }}" />
value="{{ saved.region|default('') }}" />
</label>

<label>
<span>{{ _("City") }}</span>
<input name="{{ prefix }}.city" class="form-control" {{ required }} maxlength=100
value="{{ saved.city or '' }}" />
value="{{ saved.city|default('') }}" />
</label>

<label>
<span>{{ _("Postal code") }}</span>
<input name="{{ prefix }}.postal_code" class="form-control" {{ required }} maxlength=50
size=6 value="{{ saved.postal_code or '' }}" />
size=6 value="{{ saved.postal_code|default('') }}" />
</label>

<label>
<span>{{ _("Address within the city") }}</span>
<textarea name="{{ prefix }}.local_address" class="form-control" {{ required }} rows=2 maxlength=200>{{
saved.local_address
saved.local_address|default('')
}}</textarea>
</label>

Expand Down
2 changes: 1 addition & 1 deletion templates/macros/search.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<div class="input-group">
<input type="text" name="q" class="form-control search"
placeholder="{{ _('Search Liberapay') }}"
value="{{ query or '' }}"
value="{{ query|default('', true) }}"
{{ 'autofocus' if autofocus else '' }}
{% if not autocomplete %} autocomplete="off" {% endif %} />
<div class="input-group-btn">
Expand Down
Loading

0 comments on commit 1f1a4b6

Please sign in to comment.