Show More
@@ -42,8 +42,8 b' from kallithea.controllers import base' | |||||
42 | from kallithea.lib import auth_modules, webutils |
|
42 | from kallithea.lib import auth_modules, webutils | |
43 | from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator, LoginRequired |
|
43 | from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator, LoginRequired | |
44 | from kallithea.lib.exceptions import DefaultUserException, UserCreationError, UserOwnsReposException |
|
44 | from kallithea.lib.exceptions import DefaultUserException, UserCreationError, UserOwnsReposException | |
45 |
from kallithea.lib.utils2 import datetime_to_time, |
|
45 | from kallithea.lib.utils2 import datetime_to_time, generate_api_key, safe_int | |
46 | from kallithea.lib.webutils import url |
|
46 | from kallithea.lib.webutils import fmt_date, url | |
47 | from kallithea.model import db, meta, userlog |
|
47 | from kallithea.model import db, meta, userlog | |
48 | from kallithea.model.api_key import ApiKeyModel |
|
48 | from kallithea.model.api_key import ApiKeyModel | |
49 | from kallithea.model.forms import CustomDefaultPermissionsForm, UserForm |
|
49 | from kallithea.model.forms import CustomDefaultPermissionsForm, UserForm |
@@ -39,7 +39,7 b' from kallithea.controllers import base' | |||||
39 | from kallithea.lib import feeds, webutils |
|
39 | from kallithea.lib import feeds, webutils | |
40 | from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired |
|
40 | from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired | |
41 | from kallithea.lib.diffs import DiffProcessor |
|
41 | from kallithea.lib.diffs import DiffProcessor | |
42 |
from kallithea.lib.utils2 import asbool, |
|
42 | from kallithea.lib.utils2 import asbool, safe_int, safe_str | |
43 |
|
43 | |||
44 |
|
44 | |||
45 | log = logging.getLogger(__name__) |
|
45 | log = logging.getLogger(__name__) | |
@@ -53,11 +53,11 b' class FeedController(base.BaseRepoContro' | |||||
53 | super(FeedController, self)._before(*args, **kwargs) |
|
53 | super(FeedController, self)._before(*args, **kwargs) | |
54 |
|
54 | |||
55 | def _get_title(self, cs): |
|
55 | def _get_title(self, cs): | |
56 | return shorter(cs.message, 160) |
|
56 | return webutils.shorter(cs.message, 160) | |
57 |
|
57 | |||
58 | def __get_desc(self, cs): |
|
58 | def __get_desc(self, cs): | |
59 | desc_msg = [(_('%s committed on %s') |
|
59 | desc_msg = [(_('%s committed on %s') | |
60 | % (h.person(cs.author), fmt_date(cs.date))) + '<br/>'] |
|
60 | % (h.person(cs.author), webutils.fmt_date(cs.date))) + '<br/>'] | |
61 | # branches, tags, bookmarks |
|
61 | # branches, tags, bookmarks | |
62 | for branch in cs.branches: |
|
62 | for branch in cs.branches: | |
63 | desc_msg.append('branch: %s<br/>' % branch) |
|
63 | desc_msg.append('branch: %s<br/>' % branch) |
@@ -34,14 +34,13 b' from kallithea.lib.annotate import annot' | |||||
34 | from kallithea.lib.auth import HasPermissionAny, HasRepoGroupPermissionLevel, HasRepoPermissionLevel |
|
34 | from kallithea.lib.auth import HasPermissionAny, HasRepoGroupPermissionLevel, HasRepoPermissionLevel | |
35 | from kallithea.lib.diffs import BIN_FILENODE, CHMOD_FILENODE, DEL_FILENODE, MOD_FILENODE, NEW_FILENODE, RENAMED_FILENODE |
|
35 | from kallithea.lib.diffs import BIN_FILENODE, CHMOD_FILENODE, DEL_FILENODE, MOD_FILENODE, NEW_FILENODE, RENAMED_FILENODE | |
36 | from kallithea.lib.pygmentsutils import get_custom_lexer |
|
36 | from kallithea.lib.pygmentsutils import get_custom_lexer | |
37 |
from kallithea.lib.utils2 import |
|
37 | from kallithea.lib.utils2 import AttributeDict, asbool, credentials_filter, link_to_ref, safe_bytes, safe_int, safe_str, time_to_datetime | |
38 | time_to_datetime) |
|
|||
39 | from kallithea.lib.vcs.backends.base import BaseChangeset, EmptyChangeset |
|
38 | from kallithea.lib.vcs.backends.base import BaseChangeset, EmptyChangeset | |
40 | from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError |
|
39 | from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError | |
41 | from kallithea.lib.vcs.utils import author_email, author_name |
|
40 | from kallithea.lib.vcs.utils import author_email, author_name | |
42 |
from kallithea.lib.webutils import (HTML, Option, canonical_url, checkbox, chop_at, end_form, escape, form, format_byte_size, hidden, js, jshtml, |
|
41 | 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, | |
43 | literal, password, pop_flash_messages, radio, render_w_mentions, reset, safeid, select, session_csrf_secret_name, |
|
42 | link_to, literal, password, pop_flash_messages, radio, render_w_mentions, reset, safeid, select, session_csrf_secret_name, | |
44 | session_csrf_secret_token, submit, text, textarea, url, urlify_text, wrap_paragraphs) |
|
43 | session_csrf_secret_token, shorter, submit, text, textarea, url, urlify_text, wrap_paragraphs) | |
45 | from kallithea.model import db |
|
44 | from kallithea.model import db | |
46 | from kallithea.model.changeset_status import ChangesetStatusModel |
|
45 | from kallithea.model.changeset_status import ChangesetStatusModel | |
47 |
|
46 | |||
@@ -49,10 +48,12 b' from kallithea.model.changeset_status im' | |||||
49 | # mute pyflakes "imported but unused" |
|
48 | # mute pyflakes "imported but unused" | |
50 | # from webutils |
|
49 | # from webutils | |
51 | assert Option |
|
50 | assert Option | |
|
51 | assert age | |||
52 | assert canonical_url |
|
52 | assert canonical_url | |
53 | assert checkbox |
|
53 | assert checkbox | |
54 | assert chop_at |
|
54 | assert chop_at | |
55 | assert end_form |
|
55 | assert end_form | |
|
56 | assert fmt_date | |||
56 | assert form |
|
57 | assert form | |
57 | assert format_byte_size |
|
58 | assert format_byte_size | |
58 | assert hidden |
|
59 | assert hidden | |
@@ -67,6 +68,7 b' assert safeid' | |||||
67 | assert select |
|
68 | assert select | |
68 | assert session_csrf_secret_name |
|
69 | assert session_csrf_secret_name | |
69 | assert session_csrf_secret_token |
|
70 | assert session_csrf_secret_token | |
|
71 | assert shorter | |||
70 | assert submit |
|
72 | assert submit | |
71 | assert text |
|
73 | assert text | |
72 | assert textarea |
|
74 | assert textarea | |
@@ -77,11 +79,8 b' assert HasPermissionAny' | |||||
77 | assert HasRepoGroupPermissionLevel |
|
79 | assert HasRepoGroupPermissionLevel | |
78 | assert HasRepoPermissionLevel |
|
80 | assert HasRepoPermissionLevel | |
79 | # from utils2 |
|
81 | # from utils2 | |
80 | assert age |
|
|||
81 | assert credentials_filter |
|
82 | assert credentials_filter | |
82 | assert fmt_date |
|
|||
83 | assert link_to_ref |
|
83 | assert link_to_ref | |
84 | assert shorter |
|
|||
85 | assert time_to_datetime |
|
84 | assert time_to_datetime | |
86 | # from vcs |
|
85 | # from vcs | |
87 | assert EmptyChangeset |
|
86 | assert EmptyChangeset |
@@ -42,12 +42,9 b' from distutils.version import StrictVers' | |||||
42 |
|
42 | |||
43 | import bcrypt |
|
43 | import bcrypt | |
44 | import urlobject |
|
44 | import urlobject | |
45 | from dateutil import relativedelta |
|
|||
46 | from sqlalchemy.engine import url as sa_url |
|
45 | from sqlalchemy.engine import url as sa_url | |
47 | from sqlalchemy.exc import ArgumentError |
|
46 | from sqlalchemy.exc import ArgumentError | |
48 | from tg import tmpl_context |
|
47 | from tg import tmpl_context | |
49 | from tg.i18n import ugettext as _ |
|
|||
50 | from tg.i18n import ungettext |
|
|||
51 | from tg.support.converters import asbool, aslist |
|
48 | from tg.support.converters import asbool, aslist | |
52 | from webhelpers2.text import collapse, remove_formatting, strip_tags |
|
49 | from webhelpers2.text import collapse, remove_formatting, strip_tags | |
53 |
|
50 | |||
@@ -171,124 +168,6 b' def remove_prefix(s, prefix):' | |||||
171 | return s |
|
168 | return s | |
172 |
|
169 | |||
173 |
|
170 | |||
174 | def shorter(s, size=20, firstline=False, postfix='...'): |
|
|||
175 | """Truncate s to size, including the postfix string if truncating. |
|
|||
176 | If firstline, truncate at newline. |
|
|||
177 | """ |
|
|||
178 | if firstline: |
|
|||
179 | s = s.split('\n', 1)[0].rstrip() |
|
|||
180 | if len(s) > size: |
|
|||
181 | return s[:size - len(postfix)] + postfix |
|
|||
182 | return s |
|
|||
183 |
|
||||
184 |
|
||||
185 | def age(prevdate, show_short_version=False, now=None): |
|
|||
186 | """ |
|
|||
187 | turns a datetime into an age string. |
|
|||
188 | If show_short_version is True, then it will generate a not so accurate but shorter string, |
|
|||
189 | example: 2days ago, instead of 2 days and 23 hours ago. |
|
|||
190 |
|
||||
191 | :param prevdate: datetime object |
|
|||
192 | :param show_short_version: if it should approximate the date and return a shorter string |
|
|||
193 | :rtype: str |
|
|||
194 | :returns: str words describing age |
|
|||
195 | """ |
|
|||
196 | now = now or datetime.datetime.now() |
|
|||
197 | order = ['year', 'month', 'day', 'hour', 'minute', 'second'] |
|
|||
198 | deltas = {} |
|
|||
199 | future = False |
|
|||
200 |
|
||||
201 | if prevdate > now: |
|
|||
202 | now, prevdate = prevdate, now |
|
|||
203 | future = True |
|
|||
204 | if future: |
|
|||
205 | prevdate = prevdate.replace(microsecond=0) |
|
|||
206 | # Get date parts deltas |
|
|||
207 | for part in order: |
|
|||
208 | d = relativedelta.relativedelta(now, prevdate) |
|
|||
209 | deltas[part] = getattr(d, part + 's') |
|
|||
210 |
|
||||
211 | # Fix negative offsets (there is 1 second between 10:59:59 and 11:00:00, |
|
|||
212 | # not 1 hour, -59 minutes and -59 seconds) |
|
|||
213 | for num, length in [(5, 60), (4, 60), (3, 24)]: # seconds, minutes, hours |
|
|||
214 | part = order[num] |
|
|||
215 | carry_part = order[num - 1] |
|
|||
216 |
|
||||
217 | if deltas[part] < 0: |
|
|||
218 | deltas[part] += length |
|
|||
219 | deltas[carry_part] -= 1 |
|
|||
220 |
|
||||
221 | # Same thing for days except that the increment depends on the (variable) |
|
|||
222 | # number of days in the month |
|
|||
223 | month_lengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] |
|
|||
224 | if deltas['day'] < 0: |
|
|||
225 | if prevdate.month == 2 and (prevdate.year % 4 == 0 and |
|
|||
226 | (prevdate.year % 100 != 0 or prevdate.year % 400 == 0) |
|
|||
227 | ): |
|
|||
228 | deltas['day'] += 29 |
|
|||
229 | else: |
|
|||
230 | deltas['day'] += month_lengths[prevdate.month - 1] |
|
|||
231 |
|
||||
232 | deltas['month'] -= 1 |
|
|||
233 |
|
||||
234 | if deltas['month'] < 0: |
|
|||
235 | deltas['month'] += 12 |
|
|||
236 | deltas['year'] -= 1 |
|
|||
237 |
|
||||
238 | # In short version, we want nicer handling of ages of more than a year |
|
|||
239 | if show_short_version: |
|
|||
240 | if deltas['year'] == 1: |
|
|||
241 | # ages between 1 and 2 years: show as months |
|
|||
242 | deltas['month'] += 12 |
|
|||
243 | deltas['year'] = 0 |
|
|||
244 | if deltas['year'] >= 2: |
|
|||
245 | # ages 2+ years: round |
|
|||
246 | if deltas['month'] > 6: |
|
|||
247 | deltas['year'] += 1 |
|
|||
248 | deltas['month'] = 0 |
|
|||
249 |
|
||||
250 | # Format the result |
|
|||
251 | fmt_funcs = { |
|
|||
252 | 'year': lambda d: ungettext('%d year', '%d years', d) % d, |
|
|||
253 | 'month': lambda d: ungettext('%d month', '%d months', d) % d, |
|
|||
254 | 'day': lambda d: ungettext('%d day', '%d days', d) % d, |
|
|||
255 | 'hour': lambda d: ungettext('%d hour', '%d hours', d) % d, |
|
|||
256 | 'minute': lambda d: ungettext('%d minute', '%d minutes', d) % d, |
|
|||
257 | 'second': lambda d: ungettext('%d second', '%d seconds', d) % d, |
|
|||
258 | } |
|
|||
259 |
|
||||
260 | for i, part in enumerate(order): |
|
|||
261 | value = deltas[part] |
|
|||
262 | if value == 0: |
|
|||
263 | continue |
|
|||
264 |
|
||||
265 | if i < 5: |
|
|||
266 | sub_part = order[i + 1] |
|
|||
267 | sub_value = deltas[sub_part] |
|
|||
268 | else: |
|
|||
269 | sub_value = 0 |
|
|||
270 |
|
||||
271 | if sub_value == 0 or show_short_version: |
|
|||
272 | if future: |
|
|||
273 | return _('in %s') % fmt_funcs[part](value) |
|
|||
274 | else: |
|
|||
275 | return _('%s ago') % fmt_funcs[part](value) |
|
|||
276 | if future: |
|
|||
277 | return _('in %s and %s') % (fmt_funcs[part](value), |
|
|||
278 | fmt_funcs[sub_part](sub_value)) |
|
|||
279 | else: |
|
|||
280 | return _('%s and %s ago') % (fmt_funcs[part](value), |
|
|||
281 | fmt_funcs[sub_part](sub_value)) |
|
|||
282 |
|
||||
283 | return _('just now') |
|
|||
284 |
|
||||
285 |
|
||||
286 | def fmt_date(date): |
|
|||
287 | if date: |
|
|||
288 | return date.strftime("%Y-%m-%d %H:%M:%S") |
|
|||
289 | return "" |
|
|||
290 |
|
||||
291 |
|
||||
292 | def uri_filter(uri): |
|
171 | def uri_filter(uri): | |
293 | """ |
|
172 | """ | |
294 | Removes user:password from given url string |
|
173 | Removes user:password from given url string |
@@ -20,12 +20,16 b' thread-local "global" variables. It shou' | |||||
20 | imported anywhere - just like the global variables can be used everywhere. |
|
20 | imported anywhere - just like the global variables can be used everywhere. | |
21 | """ |
|
21 | """ | |
22 |
|
22 | |||
|
23 | import datetime | |||
23 | import json |
|
24 | import json | |
24 | import logging |
|
25 | import logging | |
25 | import random |
|
26 | import random | |
26 | import re |
|
27 | import re | |
27 |
|
28 | |||
|
29 | from dateutil import relativedelta | |||
28 | from tg import request, session |
|
30 | from tg import request, session | |
|
31 | from tg.i18n import ugettext as _ | |||
|
32 | from tg.i18n import ungettext | |||
29 | from webhelpers2.html import HTML, escape, literal |
|
33 | from webhelpers2.html import HTML, escape, literal | |
30 | from webhelpers2.html.tags import NotGiven, Option, Options, _input |
|
34 | from webhelpers2.html.tags import NotGiven, Option, Options, _input | |
31 | from webhelpers2.html.tags import _make_safe_id_component as safeid |
|
35 | from webhelpers2.html.tags import _make_safe_id_component as safeid | |
@@ -532,3 +536,133 b' def render_w_mentions(source, repo_name=' | |||||
532 | """ |
|
536 | """ | |
533 | s = urlify_text(source, repo_name=repo_name) |
|
537 | s = urlify_text(source, repo_name=repo_name) | |
534 | return literal('<div class="formatted-fixed">%s</div>' % s) |
|
538 | return literal('<div class="formatted-fixed">%s</div>' % s) | |
|
539 | ||||
|
540 | ||||
|
541 | # | |||
|
542 | # Simple filters | |||
|
543 | # | |||
|
544 | ||||
|
545 | def shorter(s, size=20, firstline=False, postfix='...'): | |||
|
546 | """Truncate s to size, including the postfix string if truncating. | |||
|
547 | If firstline, truncate at newline. | |||
|
548 | """ | |||
|
549 | if firstline: | |||
|
550 | s = s.split('\n', 1)[0].rstrip() | |||
|
551 | if len(s) > size: | |||
|
552 | return s[:size - len(postfix)] + postfix | |||
|
553 | return s | |||
|
554 | ||||
|
555 | ||||
|
556 | def age(prevdate, show_short_version=False, now=None): | |||
|
557 | """ | |||
|
558 | turns a datetime into an age string. | |||
|
559 | If show_short_version is True, then it will generate a not so accurate but shorter string, | |||
|
560 | example: 2days ago, instead of 2 days and 23 hours ago. | |||
|
561 | ||||
|
562 | :param prevdate: datetime object | |||
|
563 | :param show_short_version: if it should approximate the date and return a shorter string | |||
|
564 | :rtype: str | |||
|
565 | :returns: str words describing age | |||
|
566 | """ | |||
|
567 | now = now or datetime.datetime.now() | |||
|
568 | order = ['year', 'month', 'day', 'hour', 'minute', 'second'] | |||
|
569 | deltas = {} | |||
|
570 | future = False | |||
|
571 | ||||
|
572 | if prevdate > now: | |||
|
573 | now, prevdate = prevdate, now | |||
|
574 | future = True | |||
|
575 | if future: | |||
|
576 | prevdate = prevdate.replace(microsecond=0) | |||
|
577 | # Get date parts deltas | |||
|
578 | for part in order: | |||
|
579 | d = relativedelta.relativedelta(now, prevdate) | |||
|
580 | deltas[part] = getattr(d, part + 's') | |||
|
581 | ||||
|
582 | # Fix negative offsets (there is 1 second between 10:59:59 and 11:00:00, | |||
|
583 | # not 1 hour, -59 minutes and -59 seconds) | |||
|
584 | for num, length in [(5, 60), (4, 60), (3, 24)]: # seconds, minutes, hours | |||
|
585 | part = order[num] | |||
|
586 | carry_part = order[num - 1] | |||
|
587 | ||||
|
588 | if deltas[part] < 0: | |||
|
589 | deltas[part] += length | |||
|
590 | deltas[carry_part] -= 1 | |||
|
591 | ||||
|
592 | # Same thing for days except that the increment depends on the (variable) | |||
|
593 | # number of days in the month | |||
|
594 | month_lengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] | |||
|
595 | if deltas['day'] < 0: | |||
|
596 | if prevdate.month == 2 and (prevdate.year % 4 == 0 and | |||
|
597 | (prevdate.year % 100 != 0 or prevdate.year % 400 == 0) | |||
|
598 | ): | |||
|
599 | deltas['day'] += 29 | |||
|
600 | else: | |||
|
601 | deltas['day'] += month_lengths[prevdate.month - 1] | |||
|
602 | ||||
|
603 | deltas['month'] -= 1 | |||
|
604 | ||||
|
605 | if deltas['month'] < 0: | |||
|
606 | deltas['month'] += 12 | |||
|
607 | deltas['year'] -= 1 | |||
|
608 | ||||
|
609 | # In short version, we want nicer handling of ages of more than a year | |||
|
610 | if show_short_version: | |||
|
611 | if deltas['year'] == 1: | |||
|
612 | # ages between 1 and 2 years: show as months | |||
|
613 | deltas['month'] += 12 | |||
|
614 | deltas['year'] = 0 | |||
|
615 | if deltas['year'] >= 2: | |||
|
616 | # ages 2+ years: round | |||
|
617 | if deltas['month'] > 6: | |||
|
618 | deltas['year'] += 1 | |||
|
619 | deltas['month'] = 0 | |||
|
620 | ||||
|
621 | # Format the result | |||
|
622 | fmt_funcs = { | |||
|
623 | 'year': lambda d: ungettext('%d year', '%d years', d) % d, | |||
|
624 | 'month': lambda d: ungettext('%d month', '%d months', d) % d, | |||
|
625 | 'day': lambda d: ungettext('%d day', '%d days', d) % d, | |||
|
626 | 'hour': lambda d: ungettext('%d hour', '%d hours', d) % d, | |||
|
627 | 'minute': lambda d: ungettext('%d minute', '%d minutes', d) % d, | |||
|
628 | 'second': lambda d: ungettext('%d second', '%d seconds', d) % d, | |||
|
629 | } | |||
|
630 | ||||
|
631 | for i, part in enumerate(order): | |||
|
632 | value = deltas[part] | |||
|
633 | if value == 0: | |||
|
634 | continue | |||
|
635 | ||||
|
636 | if i < 5: | |||
|
637 | sub_part = order[i + 1] | |||
|
638 | sub_value = deltas[sub_part] | |||
|
639 | else: | |||
|
640 | sub_value = 0 | |||
|
641 | ||||
|
642 | if sub_value == 0 or show_short_version: | |||
|
643 | if future: | |||
|
644 | return _('in %s') % fmt_funcs[part](value) | |||
|
645 | else: | |||
|
646 | return _('%s ago') % fmt_funcs[part](value) | |||
|
647 | if future: | |||
|
648 | return _('in %s and %s') % (fmt_funcs[part](value), | |||
|
649 | fmt_funcs[sub_part](sub_value)) | |||
|
650 | else: | |||
|
651 | return _('%s and %s ago') % (fmt_funcs[part](value), | |||
|
652 | fmt_funcs[sub_part](sub_value)) | |||
|
653 | ||||
|
654 | return _('just now') | |||
|
655 | ||||
|
656 | ||||
|
657 | def fmt_date(date): | |||
|
658 | if date: | |||
|
659 | return date.strftime("%Y-%m-%d %H:%M:%S") | |||
|
660 | return "" | |||
|
661 | ||||
|
662 | ||||
|
663 | def capitalize(x): | |||
|
664 | return x.capitalize() | |||
|
665 | ||||
|
666 | ||||
|
667 | def short_id(x): | |||
|
668 | return x[:12] |
@@ -30,7 +30,6 b' from collections import defaultdict' | |||||
30 |
|
30 | |||
31 | from kallithea.lib import webutils |
|
31 | from kallithea.lib import webutils | |
32 | from kallithea.lib.utils import extract_mentioned_users |
|
32 | from kallithea.lib.utils import extract_mentioned_users | |
33 | from kallithea.lib.utils2 import shorter |
|
|||
34 | from kallithea.model import db, meta, notification |
|
33 | from kallithea.model import db, meta, notification | |
35 |
|
34 | |||
36 |
|
35 | |||
@@ -86,7 +85,7 b' class ChangesetCommentsModel(object):' | |||||
86 | 'cs_comment_url': comment_url, |
|
85 | 'cs_comment_url': comment_url, | |
87 | 'cs_url': webutils.canonical_url('changeset_home', repo_name=repo.repo_name, revision=revision), |
|
86 | 'cs_url': webutils.canonical_url('changeset_home', repo_name=repo.repo_name, revision=revision), | |
88 | 'message': cs.message, |
|
87 | 'message': cs.message, | |
89 | 'message_short': shorter(cs.message, 50, firstline=True), |
|
88 | 'message_short': webutils.shorter(cs.message, 50, firstline=True), | |
90 | 'cs_author': cs_author, |
|
89 | 'cs_author': cs_author, | |
91 | 'cs_author_username': cs_author.username, |
|
90 | 'cs_author_username': cs_author.username, | |
92 | 'repo_name': repo.repo_name, |
|
91 | 'repo_name': repo.repo_name, | |
@@ -116,7 +115,7 b' class ChangesetCommentsModel(object):' | |||||
116 | # set some variables for email notification |
|
115 | # set some variables for email notification | |
117 | email_kwargs = { |
|
116 | email_kwargs = { | |
118 | 'pr_title': pull_request.title, |
|
117 | 'pr_title': pull_request.title, | |
119 | 'pr_title_short': shorter(pull_request.title, 50), |
|
118 | 'pr_title_short': webutils.shorter(pull_request.title, 50), | |
120 | 'pr_nice_id': pull_request.nice_id(), |
|
119 | 'pr_nice_id': pull_request.nice_id(), | |
121 | 'status_change': status_change, |
|
120 | 'status_change': status_change, | |
122 | 'closing_pr': closing_pr, |
|
121 | 'closing_pr': closing_pr, |
@@ -34,7 +34,6 b' from tg import tmpl_context as c' | |||||
34 | from tg.i18n import ugettext as _ |
|
34 | from tg.i18n import ugettext as _ | |
35 |
|
35 | |||
36 | from kallithea.lib import webutils |
|
36 | from kallithea.lib import webutils | |
37 | from kallithea.lib.utils2 import fmt_date |
|
|||
38 | from kallithea.model import async_tasks, db |
|
37 | from kallithea.model import async_tasks, db | |
39 |
|
38 | |||
40 |
|
39 | |||
@@ -101,7 +100,7 b' class NotificationModel(object):' | |||||
101 | headers['References'] = ' '.join('<%s>' % x for x in email_kwargs['threading']) |
|
100 | headers['References'] = ' '.join('<%s>' % x for x in email_kwargs['threading']) | |
102 |
|
101 | |||
103 | # this is passed into template |
|
102 | # this is passed into template | |
104 | created_on = fmt_date(datetime.datetime.now()) |
|
103 | created_on = webutils.fmt_date(datetime.datetime.now()) | |
105 | html_kwargs = { |
|
104 | html_kwargs = { | |
106 | 'body': None if body is None else webutils.render_w_mentions(body, repo_name), |
|
105 | 'body': None if body is None else webutils.render_w_mentions(body, repo_name), | |
107 | 'when': created_on, |
|
106 | 'when': created_on, |
@@ -34,7 +34,7 b' from tg.i18n import ugettext as _' | |||||
34 |
|
34 | |||
35 | from kallithea.lib import auth, hooks, webutils |
|
35 | from kallithea.lib import auth, hooks, webutils | |
36 | from kallithea.lib.utils import extract_mentioned_users |
|
36 | from kallithea.lib.utils import extract_mentioned_users | |
37 |
from kallithea.lib.utils2 import ascii_bytes, short_ref_name |
|
37 | from kallithea.lib.utils2 import ascii_bytes, short_ref_name | |
38 | from kallithea.model import changeset_status, comment, db, meta, notification |
|
38 | from kallithea.model import changeset_status, comment, db, meta, notification | |
39 |
|
39 | |||
40 |
|
40 | |||
@@ -85,7 +85,7 b' class PullRequestModel(object):' | |||||
85 | for x in map(pr.org_repo.get_changeset, pr.revisions)] |
|
85 | for x in map(pr.org_repo.get_changeset, pr.revisions)] | |
86 | email_kwargs = { |
|
86 | email_kwargs = { | |
87 | 'pr_title': pr.title, |
|
87 | 'pr_title': pr.title, | |
88 | 'pr_title_short': shorter(pr.title, 50), |
|
88 | 'pr_title_short': webutils.shorter(pr.title, 50), | |
89 | 'pr_user_created': user.full_name_and_username, |
|
89 | 'pr_user_created': user.full_name_and_username, | |
90 | 'pr_repo_url': webutils.canonical_url('summary_home', repo_name=pr.other_repo.repo_name), |
|
90 | 'pr_repo_url': webutils.canonical_url('summary_home', repo_name=pr.other_repo.repo_name), | |
91 | 'pr_url': pr_url, |
|
91 | 'pr_url': pr_url, | |
@@ -345,7 +345,7 b' class CreatePullRequestIterationAction(o' | |||||
345 | for r in reversed(revisions): |
|
345 | for r in reversed(revisions): | |
346 | if r in new_revisions: |
|
346 | if r in new_revisions: | |
347 | rev_desc = org_repo.get_changeset(r).message.split('\n')[0] |
|
347 | rev_desc = org_repo.get_changeset(r).message.split('\n')[0] | |
348 | infos.append(' %s %s' % (r[:12], shorter(rev_desc, 80))) |
|
348 | infos.append(' %s %s' % (r[:12], webutils.shorter(rev_desc, 80))) | |
349 |
|
349 | |||
350 | if self.create_action.other_ref == old_pull_request.other_ref: |
|
350 | if self.create_action.other_ref == old_pull_request.other_ref: | |
351 | infos.append(_("Ancestor didn't change - diff since previous iteration:")) |
|
351 | infos.append(_("Ancestor didn't change - diff since previous iteration:")) |
@@ -141,7 +141,7 b' class TestLibs(base.TestController):' | |||||
141 | (dict(years= -3, months= -2), '3 years and 2 months ago'), |
|
141 | (dict(years= -3, months= -2), '3 years and 2 months ago'), | |
142 | ]) |
|
142 | ]) | |
143 | def test_age(self, age_args, expected): |
|
143 | def test_age(self, age_args, expected): | |
144 |
from kallithea.lib.utils |
|
144 | from kallithea.lib.webutils import age | |
145 | with test_context(self.app): |
|
145 | with test_context(self.app): | |
146 | n = datetime.datetime(year=2012, month=5, day=17) |
|
146 | n = datetime.datetime(year=2012, month=5, day=17) | |
147 | delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs) |
|
147 | delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs) | |
@@ -165,7 +165,7 b' class TestLibs(base.TestController):' | |||||
165 | (dict(years= -4, months= -8), '5 years ago'), |
|
165 | (dict(years= -4, months= -8), '5 years ago'), | |
166 | ]) |
|
166 | ]) | |
167 | def test_age_short(self, age_args, expected): |
|
167 | def test_age_short(self, age_args, expected): | |
168 |
from kallithea.lib.utils |
|
168 | from kallithea.lib.webutils import age | |
169 | with test_context(self.app): |
|
169 | with test_context(self.app): | |
170 | n = datetime.datetime(year=2012, month=5, day=17) |
|
170 | n = datetime.datetime(year=2012, month=5, day=17) | |
171 | delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs) |
|
171 | delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs) | |
@@ -183,7 +183,7 b' class TestLibs(base.TestController):' | |||||
183 | (dict(years=1, months=1), 'in 1 year and 1 month') |
|
183 | (dict(years=1, months=1), 'in 1 year and 1 month') | |
184 | ]) |
|
184 | ]) | |
185 | def test_age_in_future(self, age_args, expected): |
|
185 | def test_age_in_future(self, age_args, expected): | |
186 |
from kallithea.lib.utils |
|
186 | from kallithea.lib.webutils import age | |
187 | with test_context(self.app): |
|
187 | with test_context(self.app): | |
188 | n = datetime.datetime(year=2012, month=5, day=17) |
|
188 | n = datetime.datetime(year=2012, month=5, day=17) | |
189 | delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs) |
|
189 | delt = lambda *args, **kwargs: relativedelta.relativedelta(*args, **kwargs) |
General Comments 0
You need to be logged in to leave comments.
Login now