changeset 8812:3cef2caf44f3

lib: move some template filter functions from utils2 to webutils While quite Kallithea specific, we prefer to have these functions in webutils where they soon can be exposed when templates don't need the whole helpers module.
author Mads Kiilerich <mads@kiilerich.com>
date Fri, 13 Nov 2020 17:11:20 +0100
parents 603876bbf79b
children a36a8804e7be
files kallithea/controllers/admin/users.py kallithea/controllers/feed.py kallithea/lib/helpers.py kallithea/lib/utils2.py kallithea/lib/webutils.py kallithea/model/comment.py kallithea/model/notification.py kallithea/model/pull_request.py kallithea/tests/other/test_libs.py
diffstat 9 files changed, 155 insertions(+), 145 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/controllers/admin/users.py	Fri Dec 18 21:35:51 2020 +0100
+++ b/kallithea/controllers/admin/users.py	Fri Nov 13 17:11:20 2020 +0100
@@ -42,8 +42,8 @@
 from kallithea.lib import auth_modules, webutils
 from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator, LoginRequired
 from kallithea.lib.exceptions import DefaultUserException, UserCreationError, UserOwnsReposException
-from kallithea.lib.utils2 import datetime_to_time, fmt_date, generate_api_key, safe_int
-from kallithea.lib.webutils import url
+from kallithea.lib.utils2 import datetime_to_time, generate_api_key, safe_int
+from kallithea.lib.webutils import fmt_date, url
 from kallithea.model import db, meta, userlog
 from kallithea.model.api_key import ApiKeyModel
 from kallithea.model.forms import CustomDefaultPermissionsForm, UserForm
--- a/kallithea/controllers/feed.py	Fri Dec 18 21:35:51 2020 +0100
+++ b/kallithea/controllers/feed.py	Fri Nov 13 17:11:20 2020 +0100
@@ -39,7 +39,7 @@
 from kallithea.lib import feeds, webutils
 from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
 from kallithea.lib.diffs import DiffProcessor
-from kallithea.lib.utils2 import asbool, fmt_date, safe_int, safe_str, shorter
+from kallithea.lib.utils2 import asbool, safe_int, safe_str
 
 
 log = logging.getLogger(__name__)
@@ -53,11 +53,11 @@
         super(FeedController, self)._before(*args, **kwargs)
 
     def _get_title(self, cs):
-        return shorter(cs.message, 160)
+        return webutils.shorter(cs.message, 160)
 
     def __get_desc(self, cs):
         desc_msg = [(_('%s committed on %s')
-                     % (h.person(cs.author), fmt_date(cs.date))) + '<br/>']
+                     % (h.person(cs.author), webutils.fmt_date(cs.date))) + '<br/>']
         # branches, tags, bookmarks
         for branch in cs.branches:
             desc_msg.append('branch: %s<br/>' % branch)
--- a/kallithea/lib/helpers.py	Fri Dec 18 21:35:51 2020 +0100
+++ b/kallithea/lib/helpers.py	Fri Nov 13 17:11:20 2020 +0100
@@ -34,14 +34,13 @@
 from kallithea.lib.auth import HasPermissionAny, HasRepoGroupPermissionLevel, HasRepoPermissionLevel
 from kallithea.lib.diffs import BIN_FILENODE, CHMOD_FILENODE, DEL_FILENODE, MOD_FILENODE, NEW_FILENODE, RENAMED_FILENODE
 from kallithea.lib.pygmentsutils import get_custom_lexer
-from kallithea.lib.utils2 import (AttributeDict, age, asbool, credentials_filter, fmt_date, link_to_ref, safe_bytes, safe_int, safe_str, shorter,
-                                  time_to_datetime)
+from kallithea.lib.utils2 import AttributeDict, asbool, credentials_filter, link_to_ref, safe_bytes, safe_int, safe_str, time_to_datetime
 from kallithea.lib.vcs.backends.base import BaseChangeset, EmptyChangeset
 from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError
 from kallithea.lib.vcs.utils import author_email, author_name
-from kallithea.lib.webutils import (HTML, Option, canonical_url, checkbox, chop_at, end_form, escape, form, format_byte_size, hidden, js, jshtml, link_to,
-                                    literal, password, pop_flash_messages, radio, render_w_mentions, reset, safeid, select, session_csrf_secret_name,
-                                    session_csrf_secret_token, submit, text, textarea, url, urlify_text, wrap_paragraphs)
+from kallithea.lib.webutils import (HTML, Option, age, canonical_url, checkbox, chop_at, end_form, escape, fmt_date, form, format_byte_size, hidden, js, jshtml,
+                                    link_to, literal, password, pop_flash_messages, radio, render_w_mentions, reset, safeid, select, session_csrf_secret_name,
+                                    session_csrf_secret_token, shorter, submit, text, textarea, url, urlify_text, wrap_paragraphs)
 from kallithea.model import db
 from kallithea.model.changeset_status import ChangesetStatusModel
 
@@ -49,10 +48,12 @@
 # mute pyflakes "imported but unused"
 # from webutils
 assert Option
+assert age
 assert canonical_url
 assert checkbox
 assert chop_at
 assert end_form
+assert fmt_date
 assert form
 assert format_byte_size
 assert hidden
@@ -67,6 +68,7 @@
 assert select
 assert session_csrf_secret_name
 assert session_csrf_secret_token
+assert shorter
 assert submit
 assert text
 assert textarea
@@ -77,11 +79,8 @@
 assert HasRepoGroupPermissionLevel
 assert HasRepoPermissionLevel
 # from utils2
-assert age
 assert credentials_filter
-assert fmt_date
 assert link_to_ref
-assert shorter
 assert time_to_datetime
 # from vcs
 assert EmptyChangeset
--- a/kallithea/lib/utils2.py	Fri Dec 18 21:35:51 2020 +0100
+++ b/kallithea/lib/utils2.py	Fri Nov 13 17:11:20 2020 +0100
@@ -42,12 +42,9 @@
 
 import bcrypt
 import urlobject
-from dateutil import relativedelta
 from sqlalchemy.engine import url as sa_url
 from sqlalchemy.exc import ArgumentError
 from tg import tmpl_context
-from tg.i18n import ugettext as _
-from tg.i18n import ungettext
 from tg.support.converters import asbool, aslist
 from webhelpers2.text import collapse, remove_formatting, strip_tags
 
@@ -171,124 +168,6 @@
     return s
 
 
-def shorter(s, size=20, firstline=False, postfix='...'):
-    """Truncate s to size, including the postfix string if truncating.
-    If firstline, truncate at newline.
-    """
-    if firstline:
-        s = s.split('\n', 1)[0].rstrip()
-    if len(s) > size:
-        return s[:size - len(postfix)] + postfix
-    return s
-
-
-def age(prevdate, show_short_version=False, now=None):
-    """
-    turns a datetime into an age string.
-    If show_short_version is True, then it will generate a not so accurate but shorter string,
-    example: 2days ago, instead of 2 days and 23 hours ago.
-
-    :param prevdate: datetime object
-    :param show_short_version: if it should approximate the date and return a shorter string
-    :rtype: str
-    :returns: str words describing age
-    """
-    now = now or datetime.datetime.now()
-    order = ['year', 'month', 'day', 'hour', 'minute', 'second']
-    deltas = {}
-    future = False
-
-    if prevdate > now:
-        now, prevdate = prevdate, now
-        future = True
-    if future:
-        prevdate = prevdate.replace(microsecond=0)
-    # Get date parts deltas
-    for part in order:
-        d = relativedelta.relativedelta(now, prevdate)
-        deltas[part] = getattr(d, part + 's')
-
-    # Fix negative offsets (there is 1 second between 10:59:59 and 11:00:00,
-    # not 1 hour, -59 minutes and -59 seconds)
-    for num, length in [(5, 60), (4, 60), (3, 24)]:  # seconds, minutes, hours
-        part = order[num]
-        carry_part = order[num - 1]
-
-        if deltas[part] < 0:
-            deltas[part] += length
-            deltas[carry_part] -= 1
-
-    # Same thing for days except that the increment depends on the (variable)
-    # number of days in the month
-    month_lengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
-    if deltas['day'] < 0:
-        if prevdate.month == 2 and (prevdate.year % 4 == 0 and
-            (prevdate.year % 100 != 0 or prevdate.year % 400 == 0)
-        ):
-            deltas['day'] += 29
-        else:
-            deltas['day'] += month_lengths[prevdate.month - 1]
-
-        deltas['month'] -= 1
-
-    if deltas['month'] < 0:
-        deltas['month'] += 12
-        deltas['year'] -= 1
-
-    # In short version, we want nicer handling of ages of more than a year
-    if show_short_version:
-        if deltas['year'] == 1:
-            # ages between 1 and 2 years: show as months
-            deltas['month'] += 12
-            deltas['year'] = 0
-        if deltas['year'] >= 2:
-            # ages 2+ years: round
-            if deltas['month'] > 6:
-                deltas['year'] += 1
-                deltas['month'] = 0
-
-    # Format the result
-    fmt_funcs = {
-        'year': lambda d: ungettext('%d year', '%d years', d) % d,
-        'month': lambda d: ungettext('%d month', '%d months', d) % d,
-        'day': lambda d: ungettext('%d day', '%d days', d) % d,
-        'hour': lambda d: ungettext('%d hour', '%d hours', d) % d,
-        'minute': lambda d: ungettext('%d minute', '%d minutes', d) % d,
-        'second': lambda d: ungettext('%d second', '%d seconds', d) % d,
-    }
-
-    for i, part in enumerate(order):
-        value = deltas[part]
-        if value == 0:
-            continue
-
-        if i < 5:
-            sub_part = order[i + 1]
-            sub_value = deltas[sub_part]
-        else:
-            sub_value = 0
-
-        if sub_value == 0 or show_short_version:
-            if future:
-                return _('in %s') % fmt_funcs[part](value)
-            else:
-                return _('%s ago') % fmt_funcs[part](value)
-        if future:
-            return _('in %s and %s') % (fmt_funcs[part](value),
-                fmt_funcs[sub_part](sub_value))
-        else:
-            return _('%s and %s ago') % (fmt_funcs[part](value),
-                fmt_funcs[sub_part](sub_value))
-
-    return _('just now')
-
-
-def fmt_date(date):
-    if date:
-        return date.strftime("%Y-%m-%d %H:%M:%S")
-    return ""
-
-
 def uri_filter(uri):
     """
     Removes user:password from given url string
--- a/kallithea/lib/webutils.py	Fri Dec 18 21:35:51 2020 +0100
+++ b/kallithea/lib/webutils.py	Fri Nov 13 17:11:20 2020 +0100
@@ -20,12 +20,16 @@
 imported anywhere - just like the global variables can be used everywhere.
 """
 
+import datetime
 import json
 import logging
 import random
 import re
 
+from dateutil import relativedelta
 from tg import request, session
+from tg.i18n import ugettext as _
+from tg.i18n import ungettext
 from webhelpers2.html import HTML, escape, literal
 from webhelpers2.html.tags import NotGiven, Option, Options, _input
 from webhelpers2.html.tags import _make_safe_id_component as safeid
@@ -532,3 +536,133 @@
     """
     s = urlify_text(source, repo_name=repo_name)
     return literal('<div class="formatted-fixed">%s</div>' % s)
+
+
+#
+# Simple filters
+#
+
+def shorter(s, size=20, firstline=False, postfix='...'):
+    """Truncate s to size, including the postfix string if truncating.
+    If firstline, truncate at newline.
+    """
+    if firstline:
+        s = s.split('\n', 1)[0].rstrip()
+    if len(s) > size:
+        return s[:size - len(postfix)] + postfix
+    return s
+
+
+def age(prevdate, show_short_version=False, now=None):
+    """
+    turns a datetime into an age string.
+    If show_short_version is True, then it will generate a not so accurate but shorter string,
+    example: 2days ago, instead of 2 days and 23 hours ago.
+
+    :param prevdate: datetime object
+    :param show_short_version: if it should approximate the date and return a shorter string
+    :rtype: str
+    :returns: str words describing age
+    """
+    now = now or datetime.datetime.now()
+    order = ['year', 'month', 'day', 'hour', 'minute', 'second']
+    deltas = {}
+    future = False
+
+    if prevdate > now:
+        now, prevdate = prevdate, now
+        future = True
+    if future:
+        prevdate = prevdate.replace(microsecond=0)
+    # Get date parts deltas
+    for part in order:
+        d = relativedelta.relativedelta(now, prevdate)
+        deltas[part] = getattr(d, part + 's')
+
+    # Fix negative offsets (there is 1 second between 10:59:59 and 11:00:00,
+    # not 1 hour, -59 minutes and -59 seconds)
+    for num, length in [(5, 60), (4, 60), (3, 24)]:  # seconds, minutes, hours
+        part = order[num]
+        carry_part = order[num - 1]
+
+        if deltas[part] < 0:
+            deltas[part] += length
+            deltas[carry_part] -= 1
+
+    # Same thing for days except that the increment depends on the (variable)
+    # number of days in the month
+    month_lengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+    if deltas['day'] < 0:
+        if prevdate.month == 2 and (prevdate.year % 4 == 0 and
+            (prevdate.year % 100 != 0 or prevdate.year % 400 == 0)
+        ):
+            deltas['day'] += 29
+        else:
+            deltas['day'] += month_lengths[prevdate.month - 1]
+
+        deltas['month'] -= 1
+
+    if deltas['month'] < 0:
+        deltas['month'] += 12
+        deltas['year'] -= 1
+
+    # In short version, we want nicer handling of ages of more than a year
+    if show_short_version:
+        if deltas['year'] == 1:
+            # ages between 1 and 2 years: show as months
+            deltas['month'] += 12
+            deltas['year'] = 0
+        if deltas['year'] >= 2:
+            # ages 2+ years: round
+            if deltas['month'] > 6:
+                deltas['year'] += 1
+                deltas['month'] = 0
+
+    # Format the result
+    fmt_funcs = {
+        'year': lambda d: ungettext('%d year', '%d years', d) % d,
+        'month': lambda d: ungettext('%d month', '%d months', d) % d,
+        'day': lambda d: ungettext('%d day', '%d days', d) % d,
+        'hour': lambda d: ungettext('%d hour', '%d hours', d) % d,
+        'minute': lambda d: ungettext('%d minute', '%d minutes', d) % d,
+        'second': lambda d: ungettext('%d second', '%d seconds', d) % d,
+    }
+
+    for i, part in enumerate(order):
+        value = deltas[part]
+        if value == 0:
+            continue
+
+        if i < 5:
+            sub_part = order[i + 1]
+            sub_value = deltas[sub_part]
+        else:
+            sub_value = 0
+
+        if sub_value == 0 or show_short_version:
+            if future:
+                return _('in %s') % fmt_funcs[part](value)
+            else:
+                return _('%s ago') % fmt_funcs[part](value)
+        if future:
+            return _('in %s and %s') % (fmt_funcs[part](value),
+                fmt_funcs[sub_part](sub_value))
+        else:
+            return _('%s and %s ago') % (fmt_funcs[part](value),
+                fmt_funcs[sub_part](sub_value))
+
+    return _('just now')
+
+
+def fmt_date(date):
+    if date:
+        return date.strftime("%Y-%m-%d %H:%M:%S")
+    return ""
+
+
+def capitalize(x):
+    return x.capitalize()
+
+
+def short_id(x):
+    return x[:12]
--- a/kallithea/model/comment.py	Fri Dec 18 21:35:51 2020 +0100
+++ b/kallithea/model/comment.py	Fri Nov 13 17:11:20 2020 +0100
@@ -30,7 +30,6 @@
 
 from kallithea.lib import webutils
 from kallithea.lib.utils import extract_mentioned_users
-from kallithea.lib.utils2 import shorter
 from kallithea.model import db, meta, notification
 
 
@@ -86,7 +85,7 @@
                 'cs_comment_url': comment_url,
                 'cs_url': webutils.canonical_url('changeset_home', repo_name=repo.repo_name, revision=revision),
                 'message': cs.message,
-                'message_short': shorter(cs.message, 50, firstline=True),
+                'message_short': webutils.shorter(cs.message, 50, firstline=True),
                 'cs_author': cs_author,
                 'cs_author_username': cs_author.username,
                 'repo_name': repo.repo_name,
@@ -116,7 +115,7 @@
             # set some variables for email notification
             email_kwargs = {
                 'pr_title': pull_request.title,
-                'pr_title_short': shorter(pull_request.title, 50),
+                'pr_title_short': webutils.shorter(pull_request.title, 50),
                 'pr_nice_id': pull_request.nice_id(),
                 'status_change': status_change,
                 'closing_pr': closing_pr,
--- a/kallithea/model/notification.py	Fri Dec 18 21:35:51 2020 +0100
+++ b/kallithea/model/notification.py	Fri Nov 13 17:11:20 2020 +0100
@@ -34,7 +34,6 @@
 from tg.i18n import ugettext as _
 
 from kallithea.lib import webutils
-from kallithea.lib.utils2 import fmt_date
 from kallithea.model import async_tasks, db
 
 
@@ -101,7 +100,7 @@
             headers['References'] = ' '.join('<%s>' % x for x in email_kwargs['threading'])
 
         # this is passed into template
-        created_on = fmt_date(datetime.datetime.now())
+        created_on = webutils.fmt_date(datetime.datetime.now())
         html_kwargs = {
                   'body': None if body is None else webutils.render_w_mentions(body, repo_name),
                   'when': created_on,
--- a/kallithea/model/pull_request.py	Fri Dec 18 21:35:51 2020 +0100
+++ b/kallithea/model/pull_request.py	Fri Nov 13 17:11:20 2020 +0100
@@ -34,7 +34,7 @@
 
 from kallithea.lib import auth, hooks, webutils
 from kallithea.lib.utils import extract_mentioned_users
-from kallithea.lib.utils2 import ascii_bytes, short_ref_name, shorter
+from kallithea.lib.utils2 import ascii_bytes, short_ref_name
 from kallithea.model import changeset_status, comment, db, meta, notification
 
 
@@ -85,7 +85,7 @@
                          for x in map(pr.org_repo.get_changeset, pr.revisions)]
         email_kwargs = {
             'pr_title': pr.title,
-            'pr_title_short': shorter(pr.title, 50),
+            'pr_title_short': webutils.shorter(pr.title, 50),
             'pr_user_created': user.full_name_and_username,
             'pr_repo_url': webutils.canonical_url('summary_home', repo_name=pr.other_repo.repo_name),
             'pr_url': pr_url,
@@ -345,7 +345,7 @@
             for r in reversed(revisions):
                 if r in new_revisions:
                     rev_desc = org_repo.get_changeset(r).message.split('\n')[0]
-                    infos.append('  %s %s' % (r[:12], shorter(rev_desc, 80)))
+                    infos.append('  %s %s' % (r[:12], webutils.shorter(rev_desc, 80)))
 
             if self.create_action.other_ref == old_pull_request.other_ref:
                 infos.append(_("Ancestor didn't change - diff since previous iteration:"))
--- a/kallithea/tests/other/test_libs.py	Fri Dec 18 21:35:51 2020 +0100
+++ b/kallithea/tests/other/test_libs.py	Fri Nov 13 17:11:20 2020 +0100
@@ -141,7 +141,7 @@
         (dict(years= -3, months= -2), '3 years and 2 months ago'),
     ])
     def test_age(self, age_args, expected):
-        from kallithea.lib.utils2 import age
+        from kallithea.lib.webutils import age
         with test_context(self.app):
             n = datetime.datetime(year=2012, month=5, day=17)
             delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs)
@@ -165,7 +165,7 @@
         (dict(years= -4, months= -8), '5 years ago'),
     ])
     def test_age_short(self, age_args, expected):
-        from kallithea.lib.utils2 import age
+        from kallithea.lib.webutils import age
         with test_context(self.app):
             n = datetime.datetime(year=2012, month=5, day=17)
             delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs)
@@ -183,7 +183,7 @@
         (dict(years=1, months=1), 'in 1 year and 1 month')
     ])
     def test_age_in_future(self, age_args, expected):
-        from kallithea.lib.utils2 import age
+        from kallithea.lib.webutils import age
         with test_context(self.app):
             n = datetime.datetime(year=2012, month=5, day=17)
             delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs)