git: d2bdf27e2221 - main - www/trac: fix issues with Babel 2.10.1+

From: Oleksii Samorukov <samm_at_FreeBSD.org>
Date: Sat, 04 May 2024 07:54:16 UTC
The branch main has been updated by samm:

URL: https://cgit.FreeBSD.org/ports/commit/?id=d2bdf27e2221e45c9242da2ccda51202c6b888c5

commit d2bdf27e2221e45c9242da2ccda51202c6b888c5
Author:     Oleksii Samorukov <samm@FreeBSD.org>
AuthorDate: 2024-05-04 07:50:29 +0000
Commit:     Oleksii Samorukov <samm@FreeBSD.org>
CommitDate: 2024-05-04 07:53:59 +0000

    www/trac: fix issues with Babel 2.10.1+
    
    Fix obtained from https://trac.edgewall.org/ticket/13482
---
 www/trac/Makefile                         |   2 +-
 www/trac/files/patch-trac_util_datefmt.py | 143 ++++++++++++++++++++++++++++++
 2 files changed, 144 insertions(+), 1 deletion(-)

diff --git a/www/trac/Makefile b/www/trac/Makefile
index 76c75200cb0f..70fd402b2014 100644
--- a/www/trac/Makefile
+++ b/www/trac/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	trac
 DISTVERSION=	1.6
-PORTREVISION=	2
+PORTREVISION=	3
 CATEGORIES=	www devel python
 MASTER_SITES=	http://ftp.edgewall.com/pub/trac/ \
 		ftp://ftp.edgewall.com/pub/trac/
diff --git a/www/trac/files/patch-trac_util_datefmt.py b/www/trac/files/patch-trac_util_datefmt.py
new file mode 100644
index 000000000000..e4788ec355b6
--- /dev/null
+++ b/www/trac/files/patch-trac_util_datefmt.py
@@ -0,0 +1,143 @@
+--- trac/util/datefmt.py.orig	2023-09-22 23:00:43 UTC
++++ trac/util/datefmt.py
+@@ -34,6 +34,7 @@ else:
+     from babel import Locale
+     from babel.core import LOCALE_ALIASES, UnknownLocaleError
+     from babel.dates import (
++        DateTimeFormat,
+         format_datetime as babel_format_datetime,
+         format_date as babel_format_date,
+         format_time as babel_format_time,
+@@ -44,8 +45,9 @@ else:
+     )
+     # 'context' parameter was added in Babel 2.3.1
+     if 'context' in inspect.signature(babel_get_period_names).parameters:
+-        def get_period_names(locale=None):
+-            return babel_get_period_names(context='format', locale=locale)
++        def get_period_names(width='wide', locale=None):
++            return babel_get_period_names(width=width, context='format',
++                                          locale=locale)
+     else:
+         get_period_names = babel_get_period_names
+ 
+@@ -292,16 +294,40 @@ def _format_datetime(t, format, tzinfo, locale, hint):
+             hint = _STRFTIME_HINTS[format]
+             format = 'medium'
+         if format in ('short', 'medium', 'long', 'full'):
+-            if hint == 'datetime':
+-                return babel_format_datetime(t, format, None, locale)
+-            if hint == 'date':
+-                return babel_format_date(t, format, locale)
+-            if hint == 'time':
+-                return babel_format_time(t, format, None, locale)
++            return _format_datetime_babel(t, format, locale, hint)
+ 
+     format = _BABEL_FORMATS[hint].get(format, format)
+     return _format_datetime_without_babel(t, format)
+ 
++if babel:
++    class _DateTimeFormatFixup(DateTimeFormat):
++        def __getitem__(self, name):
++            if name.startswith(('b', 'B')):
++                return self.format_period('a', len(name))
++            else:
++                return super().__getitem__(name)
++
++def _format_datetime_babel(t, format, locale, hint):
++    if hint in ('datetime', 'date'):
++        datepart = babel_format_date(t, format, locale)
++        if hint == 'date':
++            return datepart
++    if hint in ('datetime', 'time'):
++        time_format = get_time_format(format, locale)
++        # Use `a` period instead of `b` and `B` periods because `parse_date`
++        # and jQuery timepicker addon don't support the periods
++        if '%(b' in time_format.format or '%(B' in time_format.format:
++            timepart = time_format.format % _DateTimeFormatFixup(t, locale)
++        else:
++            timepart = babel_format_time(t, format, None, locale)
++        if hint == 'time':
++            return timepart
++    if hint == 'datetime':
++        return get_datetime_format(format, locale=locale) \
++               .replace("'", '') \
++               .replace('{0}', timepart) \
++               .replace('{1}', datepart)
++
+ def format_datetime(t=None, format='%x %X', tzinfo=None, locale=None):
+     """Format the `datetime` object `t` into a `str` string
+ 
+@@ -439,24 +465,29 @@ def get_time_format_jquery_ui(locale):
+     """Get the time format for the jQuery UI timepicker addon."""
+     if locale == 'iso8601':
+         return 'HH:mm:ssZ'
++
++    t = datetime(1999, 10, 29, 23, 59, 58, tzinfo=utc)
+     if babel and locale:
+         values = {'h': 'h', 'hh': 'hh', 'H': 'H', 'HH': 'HH',
+                   'm': 'm', 'mm': 'mm', 's': 's', 'ss': 'ss'}
+-        f = get_time_format('medium', locale=locale).format
+-        if '%(a)s' in f:
+-            t = datetime(1999, 10, 29, 23, 59, 58, tzinfo=utc)
++        # Use `a` period instead of `b` and `B` periods, because jQuery
++        # timepicker addon doesn't support the periods.
++        tmpl = babel_format_time(t, tzinfo=utc, locale=locale)
++        if '23' not in tmpl:
+             ampm = babel_format_datetime(t, 'a', None, locale)
+-            values['a'] = 'TT' if ampm[0].isupper() else 'tt'
++            ampm = 'TT' if ampm[0].isupper() else 'tt'
++            values.update((period * n, ampm) for period in ('a', 'b', 'B')
++                                             for n in range(1, 6))
++        f = get_time_format('medium', locale=locale).format
+         return f % values
++    else:
++        tmpl = format_time(t, tzinfo=utc)
++        ampm = format_time(t, '%p', tzinfo=utc)
++        if ampm:
++            tmpl = tmpl.replace(ampm, 'TT' if ampm[0].isupper() else 'tt', 1)
++        return tmpl.replace('23', 'HH', 1).replace('11', 'hh', 1) \
++                   .replace('59', 'mm', 1).replace('58', 'ss', 1)
+ 
+-    t = datetime(1999, 10, 29, 23, 59, 58, tzinfo=utc)
+-    tmpl = format_time(t, tzinfo=utc)
+-    ampm = format_time(t, '%p', tzinfo=utc)
+-    if ampm:
+-        tmpl = tmpl.replace(ampm, 'TT' if ampm[0].isupper() else 'tt', 1)
+-    return tmpl.replace('23', 'HH', 1).replace('11', 'hh', 1) \
+-               .replace('59', 'mm', 1).replace('58', 'ss', 1)
+-
+ def get_timezone_list_jquery_ui(t=None):
+     """Get timezone list for jQuery timepicker addon"""
+     def utcoffset(tz, t):  # in minutes
+@@ -701,20 +732,21 @@ def _i18n_parse_date_pattern(locale):
+             if name:
+                 period_names[name.lower()] = period
+     else:
+-        if formats[0].find('%(MMM)s') != -1:
+-            for width in ('wide', 'abbreviated'):
+-                names = get_month_names(width, locale=locale)
+-                month_names.update((name.lower(), num)
+-                                   for num, name in names.items())
+-        if formats[0].find('%(a)s') != -1:
+-            names = get_period_names(locale=locale)
++        for width in ('wide', 'abbreviated'):
++            names = get_month_names(width=width, locale=locale)
++            month_names.update((name.lower(), num)
++                               for num, name in names.items())
++            names = get_period_names(width=width, locale=locale)
+             period_names.update((name.lower(), period)
+                                 for period, name in names.items()
+                                 if period in ('am', 'pm'))
+ 
+-    regexp = ['[0-9]+']
+-    regexp.extend(re.escape(name) for name in month_names)
+-    regexp.extend(re.escape(name) for name in period_names)
++    regexp = []
++    regexp.extend(month_names)
++    regexp.extend(period_names)
++    regexp.sort(key=lambda v: len(v), reverse=True)
++    regexp = list(map(re.escape, regexp))
++    regexp.append('[0-9]+')
+ 
+     return {
+         'orders': orders,