diff --git a/kallithea/controllers/admin/users.py b/kallithea/controllers/admin/users.py
--- a/kallithea/controllers/admin/users.py
+++ b/kallithea/controllers/admin/users.py
@@ -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
diff --git a/kallithea/controllers/feed.py b/kallithea/controllers/feed.py
--- a/kallithea/controllers/feed.py
+++ b/kallithea/controllers/feed.py
@@ -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))) + '
']
+ % (h.person(cs.author), webutils.fmt_date(cs.date))) + '
']
# branches, tags, bookmarks
for branch in cs.branches:
desc_msg.append('branch: %s
' % branch)
diff --git a/kallithea/lib/helpers.py b/kallithea/lib/helpers.py
--- a/kallithea/lib/helpers.py
+++ b/kallithea/lib/helpers.py
@@ -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
diff --git a/kallithea/lib/utils2.py b/kallithea/lib/utils2.py
--- a/kallithea/lib/utils2.py
+++ b/kallithea/lib/utils2.py
@@ -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
diff --git a/kallithea/lib/webutils.py b/kallithea/lib/webutils.py
--- a/kallithea/lib/webutils.py
+++ b/kallithea/lib/webutils.py
@@ -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('