Changeset - 3cef2caf44f3
[Not reviewed]
default
0 9 0
Mads Kiilerich (mads) - 5 years ago 2020-11-13 17:11:20
mads@kiilerich.com
Grafted from: 1e8e18e583df
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.
9 files changed with 155 insertions and 145 deletions:
0 comments (0 inline, 0 general)
kallithea/controllers/admin/users.py
Show inline comments
 
@@ -42,8 +42,8 @@ from kallithea.controllers import base
 
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
kallithea/controllers/feed.py
Show inline comments
 
@@ -39,7 +39,7 @@ from kallithea.controllers import base
 
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 @@ class FeedController(base.BaseRepoContro
 
        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)
kallithea/lib/helpers.py
Show inline comments
 
@@ -34,14 +34,13 @@ from kallithea.lib.annotate import annot
 
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 @@ from kallithea.model.changeset_status im
 
# 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 safeid
 
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 HasPermissionAny
 
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
kallithea/lib/utils2.py
Show inline comments
 
@@ -42,12 +42,9 @@ from distutils.version import StrictVers
 

	
 
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 @@ def remove_prefix(s, prefix):
 
    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
kallithea/lib/webutils.py
Show inline comments
 
@@ -20,12 +20,16 @@ thread-local "global" variables. It shou
 
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 @@ def render_w_mentions(source, repo_name=
 
    """
 
    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]
kallithea/model/comment.py
Show inline comments
 
@@ -30,7 +30,6 @@ from collections import defaultdict
 

	
 
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 @@ class ChangesetCommentsModel(object):
 
                '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 @@ class ChangesetCommentsModel(object):
 
            # 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,
kallithea/model/notification.py
Show inline comments
 
@@ -34,7 +34,6 @@ from tg import tmpl_context as c
 
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 @@ class NotificationModel(object):
 
            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,
kallithea/model/pull_request.py
Show inline comments
 
@@ -34,7 +34,7 @@ from tg.i18n import ugettext as _
 

	
 
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 @@ class PullRequestModel(object):
 
                         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 @@ class CreatePullRequestIterationAction(o
 
            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:"))
kallithea/tests/other/test_libs.py
Show inline comments
 
@@ -141,7 +141,7 @@ class TestLibs(base.TestController):
 
        (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 @@ class TestLibs(base.TestController):
 
        (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 @@ class TestLibs(base.TestController):
 
        (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)
0 comments (0 inline, 0 general)