# Copyright 2008 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Django template library for Gerrit.""" import cgi import logging from google.appengine.api import memcache from google.appengine.api import users import django.template import django.utils.safestring from django.utils.safestring import mark_safe from django.utils.timesince import timesince from memcache import CachedDict import models import view_util register = django.template.Library() class _CachedUser(object): """Important data about an Account, pickled into memcache for faster access when rendering pages to clients. """ email = None real_name = None exists = False def _store_users(emails): def _cache(pair): email, account = pair r = _CachedUser() if account: r.email = account.email r.real_name = account.real_name r.exists = account.real_name_entered else: r.email = email r.real_name = email if '@' in r.real_name: r.real_name = r.real_name.split('@', 1)[0] if r.real_name is None: r.real_name = 'Unknown Person (%s)' % r.email return r all = zip(emails, models.Account.get_accounts_for_emails(emails)) return map(_cache, all) _user_cache = CachedDict(prefix = 'CachedUser:', compute_multi = _store_users, timeout = 300) def _to_email(u): if isinstance(u, users.User): return u.email() return u def prefetch_names(emails): _user_cache.prefetch(map(_to_email, emails)) @register.filter def real_name(email, arg=None): """Render an email address or a User object as a real_name. If the input is a user object that equals the current user, 'me' is returned, unless the filter argument is non-empty. Example: {{foo|real_name}} may render 'me'; {{foo|real_name:"x"}} will never render 'me'. """ return real_names([email], arg) @register.filter def real_names(email_list, arg=None): """Render a list of email addresses or User objects as real_names. Each list item is first formatter via the real_name() filter above, and then the resulting strings are separated by commas. The filter argument is the same as for real_name() above. """ if arg: user = None else: user = users.get_current_user() email_list = map(_to_email, email_list) all = _user_cache.get_multi(email_list) names = [] for email in email_list: if user and user.email() == email: names.append('me') else: names.append(all[email].real_name) return ', '.join(names) @register.filter def show_user(email, arg=None): """Render a link to the user's dashboard, with text being the real_name. """ return show_users([email], arg) @register.filter def show_users(email_list, arg=None): """Render list of links to each user's dashboard, with text being the real_name. """ if arg: user = None else: user = users.get_current_user() email_list = map(_to_email, email_list) all = _user_cache.get_multi(email_list) names = [] for email in email_list: if user and user.email() == email: names.append('me') else: u = all[email] if u.exists: names.append( '' '%(name)s' % {'link': cgi.escape(u.email.replace('@',',,')), 'name': cgi.escape(u.real_name)} ) else: names.append(cgi.escape(u.real_name)) return mark_safe(', '.join(names)) def _init_lgtm_text(): r = {} for key, value in models.LGTM_CHOICES: r[key] = value return r _lgtm_text = _init_lgtm_text() @register.filter def review_status_text(status, arg=None): try: return _lgtm_text[status] except KeyError: return '' _lgtm_icon = { 'lgtm': mark_safe(''), 'yes': mark_safe('+1'), 'abstain': '', 'no': mark_safe('-1'), 'reject': mark_safe(''), } @register.filter def review_status_icons(status, arg=None): try: return _lgtm_icon[status] except KeyError: return '' @register.filter def form_xsrf(url, arg=None): x = view_util.xsrf_for(url) return mark_safe('' % x) @register.filter def bare_xsrf(url, arg=None): return mark_safe(view_util.xsrf_for(url)) _abbrev_units = { 'year': 'y', 'years': 'y', 'month': 'mo', 'months': 'm', 'week': 'w', 'weeks': 'w', 'day': 'd', 'days': 'd', 'hour': 'h', 'hours': 'h', 'minute': 'min', 'minutes': 'mins', } @register.filter def abbrevtimesince(d, arg=None): r = [] for p in timesince(d).split(', '): cnt, unit = p.split(' ', 2) try: r.append('%s %s' % (cnt, _abbrev_units[unit])) except KeyError: r.append(p) return ', '.join(r)