]> git.ipfire.org Git - thirdparty/babel.git/commitdiff
Run `ruff format babel` reruff 1202/head
authorRuff <ruff@astral.sh>
Wed, 19 Mar 2025 11:05:15 +0000 (13:05 +0200)
committerAarni Koskela <akx@iki.fi>
Tue, 24 Jun 2025 11:58:02 +0000 (14:58 +0300)
24 files changed:
babel/__init__.py
babel/core.py
babel/dates.py
babel/languages.py
babel/lists.py
babel/localedata.py
babel/localtime/__init__.py
babel/localtime/_fallback.py
babel/localtime/_unix.py
babel/localtime/_win32.py
babel/messages/__init__.py
babel/messages/catalog.py
babel/messages/checkers.py
babel/messages/extract.py
babel/messages/frontend.py
babel/messages/jslexer.py
babel/messages/mofile.py
babel/messages/plurals.py
babel/messages/pofile.py
babel/numbers.py
babel/plural.py
babel/support.py
babel/units.py
babel/util.py

index 7b277455843793778838de76df672d005f41f556..0edfa9a8f3c5ce97977727e1178ff0fcd66d92c6 100644 (file)
@@ -1,19 +1,19 @@
 """
-    babel
-    ~~~~~
+babel
+~~~~~
 
-    Integrated collection of utilities that assist in internationalizing and
-    localizing applications.
+Integrated collection of utilities that assist in internationalizing and
+localizing applications.
 
-    This package is basically composed of two major parts:
+This package is basically composed of two major parts:
 
    * tools to build and work with ``gettext`` message catalogs
    * a Python interface to the CLDR (Common Locale Data Repository), providing
-       access to various locale display names, localized number and date
-       formatting, etc.
+ * tools to build and work with ``gettext`` message catalogs
+ * a Python interface to the CLDR (Common Locale Data Repository), providing
+   access to various locale display names, localized number and date
+   formatting, etc.
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
 
 from babel.core import (
index eb159c310c91f067ba35d20c2b1b9f9ba52a60c1..a59e731281e1182db4f41a197a1d7d0fb0306b94 100644 (file)
@@ -1,11 +1,11 @@
 """
-    babel.core
-    ~~~~~~~~~~
+babel.core
+~~~~~~~~~~
 
-    Core locale representation and locale data access.
+Core locale representation and locale data access.
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
 
 from __future__ import annotations
@@ -56,12 +56,14 @@ _default_plural_rule = PluralRule({})
 
 
 def _raise_no_data_error():
-    raise RuntimeError('The babel data files are not available. '
-                       'This usually happens because you are using '
-                       'a source checkout from Babel and you did '
-                       'not build the data files.  Just make sure '
-                       'to run "python setup.py import_cldr" before '
-                       'installing the library.')
+    raise RuntimeError(
+        'The babel data files are not available. '
+        'This usually happens because you are using '
+        'a source checkout from Babel and you did '
+        'not build the data files.  Just make sure '
+        'to run "python setup.py import_cldr" before '
+        'installing the library.',
+    )
 
 
 def get_global(key: _GLOBAL_KEY) -> Mapping[str, Any]:
@@ -216,7 +218,11 @@ class Locale:
             raise UnknownLocaleError(identifier)
 
     @classmethod
-    def default(cls, category: str | None = None, aliases: Mapping[str, str] = LOCALE_ALIASES) -> Locale:
+    def default(
+        cls,
+        category: str | None = None,
+        aliases: Mapping[str, str] = LOCALE_ALIASES,
+    ) -> Locale:
         """Return the system default locale for the specified category.
 
         >>> for name in ['LANGUAGE', 'LC_ALL', 'LC_CTYPE', 'LC_MESSAGES']:
@@ -268,8 +274,7 @@ class Locale:
         :param aliases: a dictionary of aliases for locale identifiers
         :param sep: separator for parsing; e.g. Windows tends to use '-' instead of '_'.
         """
-        identifier = negotiate_locale(preferred, available, sep=sep,
-                                      aliases=aliases)
+        identifier = negotiate_locale(preferred, available, sep=sep, aliases=aliases)
         if identifier:
             return Locale.parse(identifier, sep=sep)
         return None
@@ -421,7 +426,9 @@ class Locale:
             else:
                 language2, _, script2, variant2 = parts2
                 modifier2 = None
-            locale = _try_load_reducing((language2, territory, script2, variant2, modifier2))
+            locale = _try_load_reducing(
+                (language2, territory, script2, variant2, modifier2),
+            )
             if locale is not None:
                 return locale
 
@@ -432,19 +439,18 @@ class Locale:
             if not hasattr(other, key):
                 return False
         return (
-            self.language == getattr(other, 'language') and  # noqa: B009
-            self.territory == getattr(other, 'territory') and  # noqa: B009
-            self.script == getattr(other, 'script') and  # noqa: B009
-            self.variant == getattr(other, 'variant') and  # noqa: B009
-            self.modifier == getattr(other, 'modifier')  # noqa: B009
+            self.language == getattr(other, 'language')  # noqa: B009
+            and self.territory == getattr(other, 'territory')  # noqa: B009
+            and self.script == getattr(other, 'script')  # noqa: B009
+            and self.variant == getattr(other, 'variant')  # noqa: B009
+            and self.modifier == getattr(other, 'modifier')  # noqa: B009
         )
 
     def __ne__(self, other: object) -> bool:
         return not self.__eq__(other)
 
     def __hash__(self) -> int:
-        return hash((self.language, self.territory, self.script,
-                     self.variant, self.modifier))
+        return hash((self.language, self.territory, self.script, self.variant, self.modifier))
 
     def __repr__(self) -> str:
         parameters = ['']
@@ -455,9 +461,9 @@ class Locale:
         return f"Locale({self.language!r}{', '.join(parameters)})"
 
     def __str__(self) -> str:
-        return get_locale_identifier((self.language, self.territory,
-                                      self.script, self.variant,
-                                      self.modifier))
+        return get_locale_identifier(
+            (self.language, self.territory, self.script, self.variant, self.modifier),
+        )
 
     @property
     def _data(self) -> localedata.LocaleDataDict:
@@ -500,7 +506,9 @@ class Locale:
                 retval += f" ({detail_string})"
         return retval
 
-    display_name = property(get_display_name, doc="""\
+    display_name = property(
+        get_display_name,
+        doc="""\
         The localized display name of the locale.
 
         >>> Locale('en').display_name
@@ -511,7 +519,8 @@ class Locale:
         u'svenska'
 
         :type: `unicode`
-        """)
+        """,
+    )
 
     def get_language_name(self, locale: Locale | str | None = None) -> str | None:
         """Return the language of this locale in the given locale.
@@ -528,12 +537,15 @@ class Locale:
         locale = Locale.parse(locale)
         return locale.languages.get(self.language)
 
-    language_name = property(get_language_name, doc="""\
+    language_name = property(
+        get_language_name,
+        doc="""\
         The localized language name of the locale.
 
         >>> Locale('en', 'US').language_name
         u'English'
-    """)
+    """,
+    )
 
     def get_territory_name(self, locale: Locale | str | None = None) -> str | None:
         """Return the territory name in the given locale."""
@@ -542,12 +554,15 @@ class Locale:
         locale = Locale.parse(locale)
         return locale.territories.get(self.territory or '')
 
-    territory_name = property(get_territory_name, doc="""\
+    territory_name = property(
+        get_territory_name,
+        doc="""\
         The localized territory name of the locale if available.
 
         >>> Locale('de', 'DE').territory_name
         u'Deutschland'
-    """)
+    """,
+    )
 
     def get_script_name(self, locale: Locale | str | None = None) -> str | None:
         """Return the script name in the given locale."""
@@ -556,12 +571,15 @@ class Locale:
         locale = Locale.parse(locale)
         return locale.scripts.get(self.script or '')
 
-    script_name = property(get_script_name, doc="""\
+    script_name = property(
+        get_script_name,
+        doc="""\
         The localized script name of the locale if available.
 
         >>> Locale('sr', 'ME', script='Latn').script_name
         u'latinica'
-    """)
+    """,
+    )
 
     @property
     def english_name(self) -> str | None:
@@ -785,8 +803,7 @@ class Locale:
 
     @property
     def day_period_rules(self) -> localedata.LocaleDataDict:
-        """Day period rules for the locale.  Used by `get_period_id`.
-        """
+        """Day period rules for the locale.  Used by `get_period_id`."""
         return self._data.get('day_period_rules', localedata.LocaleDataDict({}))
 
     @property
@@ -1150,7 +1167,12 @@ def default_locale(
     return None
 
 
-def negotiate_locale(preferred: Iterable[str], available: Iterable[str], sep: str = '_', aliases: Mapping[str, str] = LOCALE_ALIASES) -> str | None:
+def negotiate_locale(
+    preferred: Iterable[str],
+    available: Iterable[str],
+    sep: str = '_',
+    aliases: Mapping[str, str] = LOCALE_ALIASES,
+) -> str | None:
     """Find the best match between available and requested locale strings.
 
     >>> negotiate_locale(['de_DE', 'en_US'], ['de_DE', 'de_AT'])
@@ -1216,7 +1238,10 @@ def negotiate_locale(preferred: Iterable[str], available: Iterable[str], sep: st
 def parse_locale(
     identifier: str,
     sep: str = '_',
-) -> tuple[str, str | None, str | None, str | None] | tuple[str, str | None, str | None, str | None, str | None]:
+) -> (
+    tuple[str, str | None, str | None, str | None]
+    | tuple[str, str | None, str | None, str | None, str | None]
+):
     """Parse a locale identifier into a tuple of the form ``(language,
     territory, script, variant, modifier)``.
 
@@ -1294,8 +1319,10 @@ def parse_locale(
             territory = parts.pop(0)
 
     if parts and (
-        len(parts[0]) == 4 and parts[0][0].isdigit() or
-        len(parts[0]) >= 5 and parts[0][0].isalpha()
+        len(parts[0]) == 4
+        and parts[0][0].isdigit()
+        or len(parts[0]) >= 5
+        and parts[0][0].isalpha()
     ):
         variant = parts.pop().upper()
 
index 8c6e1fd573bef46ac68e76fcc6fbadae3eb81dbc..70b615321795a92eb23db9682146b01403ddbf13 100644 (file)
@@ -1,18 +1,18 @@
 """
-    babel.dates
-    ~~~~~~~~~~~
+babel.dates
+~~~~~~~~~~~
 
-    Locale dependent formatting and parsing of dates and times.
+Locale dependent formatting and parsing of dates and times.
 
-    The default locale for the functions in this module is determined by the
-    following environment variables, in that order:
+The default locale for the functions in this module is determined by the
+following environment variables, in that order:
 
    * ``LC_TIME``,
    * ``LC_ALL``, and
    * ``LANG``
+ * ``LC_TIME``,
+ * ``LC_ALL``, and
+ * ``LANG``
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
 
 from __future__ import annotations
@@ -38,6 +38,7 @@ from babel.localedata import LocaleDataDict
 
 if TYPE_CHECKING:
     from typing_extensions import TypeAlias
+
     _Instant: TypeAlias = datetime.date | datetime.time | float | None
     _PredefinedTimeFormat: TypeAlias = Literal['full', 'long', 'medium', 'short']
     _Context: TypeAlias = Literal['format', 'stand-alone']
@@ -75,7 +76,9 @@ def _localize(tz: datetime.tzinfo, dt: datetime.datetime) -> datetime.datetime:
     return dt.astimezone(tz)
 
 
-def _get_dt_and_tzinfo(dt_or_tzinfo: _DtOrTzinfo) -> tuple[datetime.datetime | None, datetime.tzinfo]:
+def _get_dt_and_tzinfo(
+    dt_or_tzinfo: _DtOrTzinfo,
+) -> tuple[datetime.datetime | None, datetime.tzinfo]:
     """
     Parse a `dt_or_tzinfo` value into a datetime and a tzinfo.
 
@@ -153,13 +156,16 @@ def _get_datetime(instant: _Instant) -> datetime.datetime:
         return datetime.datetime.fromtimestamp(instant, UTC).replace(tzinfo=None)
     elif isinstance(instant, datetime.time):
         return datetime.datetime.combine(datetime.date.today(), instant)
-    elif isinstance(instant, datetime.date) and not isinstance(instant, datetime.datetime):
+    elif isinstance(instant, datetime.date) and not isinstance(instant, datetime.datetime):  # fmt: skip
         return datetime.datetime.combine(instant, datetime.time())
     # TODO (3.x): Add an assertion/type check for this fallthrough branch:
     return instant
 
 
-def _ensure_datetime_tzinfo(dt: datetime.datetime, tzinfo: datetime.tzinfo | None = None) -> datetime.datetime:
+def _ensure_datetime_tzinfo(
+    dt: datetime.datetime,
+    tzinfo: datetime.tzinfo | None = None,
+) -> datetime.datetime:
     """
     Ensure the datetime passed has an attached tzinfo.
 
@@ -524,7 +530,11 @@ def get_timezone_location(
     if territory not in locale.territories:
         territory = 'ZZ'  # invalid/unknown
     territory_name = locale.territories[territory]
-    if not return_city and territory and len(get_global('territory_zones').get(territory, [])) == 1:
+    if (
+        not return_city
+        and territory
+        and len(get_global('territory_zones').get(territory, [])) == 1
+    ):
         return region_format % territory_name
 
     # Otherwise, include the city in the output
@@ -543,10 +553,13 @@ def get_timezone_location(
 
     if return_city:
         return city_name
-    return region_format % (fallback_format % {
-        '0': city_name,
-        '1': territory_name,
-    })
+    return region_format % (
+        fallback_format
+        % {
+            '0': city_name,
+            '1': territory_name,
+        }
+    )
 
 
 def get_timezone_name(
@@ -744,11 +757,12 @@ def format_datetime(
 
     locale = Locale.parse(locale or LC_TIME)
     if format in ('full', 'long', 'medium', 'short'):
-        return get_datetime_format(format, locale=locale) \
-            .replace("'", "") \
-            .replace('{0}', format_time(datetime, format, tzinfo=None,
-                                        locale=locale)) \
+        return (
+            get_datetime_format(format, locale=locale)
+            .replace("'", "")
+            .replace('{0}', format_time(datetime, format, tzinfo=None, locale=locale))
             .replace('{1}', format_date(datetime, format, locale=locale))
+        )
     else:
         return parse_pattern(format).apply(datetime, locale)
 
@@ -890,8 +904,16 @@ TIMEDELTA_UNITS: tuple[tuple[str, int], ...] = (
 
 def format_timedelta(
     delta: datetime.timedelta | int,
-    granularity: Literal['year', 'month', 'week', 'day', 'hour', 'minute', 'second'] = 'second',
-    threshold: float = .85,
+    granularity: Literal[
+        'year',
+        'month',
+        'week',
+        'day',
+        'hour',
+        'minute',
+        'second',
+    ] = 'second',
+    threshold: float = 0.85,
     add_direction: bool = False,
     format: Literal['narrow', 'short', 'medium', 'long'] = 'long',
     locale: Locale | str | None = None,
@@ -955,8 +977,7 @@ def format_timedelta(
         raise TypeError('Format must be one of "narrow", "short" or "long"')
     if format == 'medium':
         warnings.warn(
-            '"medium" value for format param of format_timedelta'
-            ' is deprecated. Use "long" instead',
+            '"medium" value for format param of format_timedelta is deprecated. Use "long" instead',
             category=DeprecationWarning,
             stacklevel=2,
         )
@@ -973,7 +994,7 @@ def format_timedelta(
         if add_direction:
             # Try to find the length variant version first ("year-narrow")
             # before falling back to the default.
-            unit_rel_patterns = (date_fields.get(f"{a_unit}-{format}") or date_fields[a_unit])
+            unit_rel_patterns = date_fields.get(f"{a_unit}-{format}") or date_fields[a_unit]
             if seconds >= 0:
                 yield unit_rel_patterns['future']
             else:
@@ -1040,9 +1061,9 @@ def _format_fallback_interval(
         return format(start)
 
     return (
-        locale.interval_formats.get(None, "{0}-{1}").
-        replace("{0}", formatted_start).
-        replace("{1}", formatted_end)
+        locale.interval_formats.get(None, "{0}-{1}")
+        .replace("{0}", formatted_start)
+        .replace("{1}", formatted_end)
     )
 
 
@@ -1142,8 +1163,7 @@ def format_interval(
             # > format the start and end datetime, as above.
             return "".join(
                 parse_pattern(pattern).apply(instant, locale)
-                for pattern, instant
-                in zip(skel_formats[field], (start, end))
+                for pattern, instant in zip(skel_formats[field], (start, end))
             )
 
     # > Otherwise, format the start and end datetime using the fallback pattern.
@@ -1201,8 +1221,10 @@ def get_period_id(
                         return rule_id
                 else:
                     # e.g. from="21:00" before="06:00"
-                    if rule["from"] <= seconds_past_midnight < 86400 or \
-                            0 <= seconds_past_midnight < rule["before"]:
+                    if (
+                        rule["from"] <= seconds_past_midnight < 86400
+                        or 0 <= seconds_past_midnight < rule["before"]
+                    ):
                         return rule_id
 
             start_ok = end_ok = False
@@ -1377,7 +1399,6 @@ def parse_time(
 
 
 class DateTimePattern:
-
     def __init__(self, pattern: str, format: DateTimeFormat):
         self.pattern = pattern
         self.format = format
@@ -1404,7 +1425,6 @@ class DateTimePattern:
 
 
 class DateTimeFormat:
-
     def __init__(
         self,
         value: datetime.date | datetime.time,
@@ -1485,7 +1505,9 @@ class DateTimeFormat:
         elif char == 'a':
             return int(self.value.hour >= 12)  # 0 for am, 1 for pm
         else:
-            raise NotImplementedError(f"Not implemented: extracting {char!r} from {self.value!r}")
+            raise NotImplementedError(
+                f"Not implemented: extracting {char!r} from {self.value!r}",
+            )
 
     def format_era(self, char: str, num: int) -> str:
         width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[max(3, num)]
@@ -1599,8 +1621,12 @@ class DateTimeFormat:
         :param num: count of format character
 
         """
-        widths = [{3: 'abbreviated', 4: 'wide', 5: 'narrow'}[max(3, num)],
-                  'wide', 'narrow', 'abbreviated']
+        widths = [
+            {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[max(3, num)],
+            'wide',
+            'narrow',
+            'abbreviated',
+        ]
         if char == 'a':
             period = 'pm' if self.value.hour >= 12 else 'am'
             context = 'format'
@@ -1623,8 +1649,12 @@ class DateTimeFormat:
         return self.format(round(value, num) * 10**num, num)
 
     def format_milliseconds_in_day(self, num):
-        msecs = self.value.microsecond // 1000 + self.value.second * 1000 + \
-            self.value.minute * 60000 + self.value.hour * 3600000
+        msecs = (
+            self.value.microsecond // 1000
+            + self.value.second * 1000
+            + self.value.minute * 60000
+            + self.value.hour * 3600000
+        )
         return self.format(msecs, num)
 
     def format_timezone(self, char: str, num: int) -> str:
@@ -1681,12 +1711,13 @@ class DateTimeFormat:
         week = self.get_week_number(day_of_year)
         if week == 0:
             date = datetime.date(self.value.year - 1, 12, 31)
-            week = self.get_week_number(self.get_day_of_year(date),
-                                        date.weekday())
+            week = self.get_week_number(self.get_day_of_year(date), date.weekday())
         elif week > 52:
             weekday = datetime.date(self.value.year + 1, 1, 1).weekday()
-            if self.get_week_number(1, weekday) == 1 and \
-                    32 - (weekday - self.locale.first_week_day) % 7 <= self.value.day:
+            if (
+                self.get_week_number(1, weekday) == 1
+                and 32 - (weekday - self.locale.first_week_day) % 7 <= self.value.day
+            ):
                 week = 1
         return week
 
@@ -1715,8 +1746,7 @@ class DateTimeFormat:
         """
         if day_of_week is None:
             day_of_week = self.value.weekday()
-        first_day = (day_of_week - self.locale.first_week_day -
-                     day_of_period + 1) % 7
+        first_day = (day_of_week - self.locale.first_week_day - day_of_period + 1) % 7
         if first_day < 0:
             first_day += 7
         week_number = (day_of_period + first_day - 1) // 7
@@ -1919,7 +1949,11 @@ def split_interval_pattern(pattern: str) -> list[str]:
     return [untokenize_pattern(tokens) for tokens in parts]
 
 
-def match_skeleton(skeleton: str, options: Iterable[str], allow_different_fields: bool = False) -> str | None:
+def match_skeleton(
+    skeleton: str,
+    options: Iterable[str],
+    allow_different_fields: bool = False,
+) -> str | None:
     """
     Find the closest match for the given datetime skeleton among the options given.
 
index 564f555d2b1f4ef60476aa881ff38f65ebe39b5f..5b2396c84c5233cf1692f842cd471c27fca65512 100644 (file)
@@ -3,7 +3,11 @@ from __future__ import annotations
 from babel.core import get_global
 
 
-def get_official_languages(territory: str, regional: bool = False, de_facto: bool = False) -> tuple[str, ...]:
+def get_official_languages(
+    territory: str,
+    regional: bool = False,
+    de_facto: bool = False,
+) -> tuple[str, ...]:
     """
     Get the official language(s) for the given territory.
 
@@ -43,7 +47,9 @@ def get_official_languages(territory: str, regional: bool = False, de_facto: boo
     return tuple(lang for _, lang in pairs)
 
 
-def get_territory_language_info(territory: str) -> dict[str, dict[str, float | str | None]]:
+def get_territory_language_info(
+    territory: str,
+) -> dict[str, dict[str, float | str | None]]:
     """
     Get a dictionary of language information for a territory.
 
index 353171c71c8cb58702f7229a0c3797cfdf0d7688..0c17f75bf661ce8e7d0d8bb9a99be67ec051f0e4 100644 (file)
@@ -1,18 +1,19 @@
 """
-    babel.lists
-    ~~~~~~~~~~~
+babel.lists
+~~~~~~~~~~~
 
-    Locale dependent formatting of lists.
+Locale dependent formatting of lists.
 
-    The default locale for the functions in this module is determined by the
-    following environment variables, in that order:
+The default locale for the functions in this module is determined by the
+following environment variables, in that order:
 
    * ``LC_ALL``, and
    * ``LANG``
+ * ``LC_ALL``, and
+ * ``LANG``
 
-    :copyright: (c) 2015-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2015-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
+
 from __future__ import annotations
 
 import warnings
@@ -37,7 +38,15 @@ def __getattr__(name):
 
 def format_list(
     lst: Sequence[str],
-    style: Literal['standard', 'standard-short', 'or', 'or-short', 'unit', 'unit-short', 'unit-narrow'] = 'standard',
+    style: Literal[
+        'standard',
+        'standard-short',
+        'or',
+        'or-short',
+        'unit',
+        'unit-short',
+        'unit-narrow',
+    ] = 'standard',
     locale: Locale | str | None = None,
 ) -> str:
     """
index 59f1db09e7972e56f88a14db48269343063559b7..7cff4871e9afdebd4d85763fadfcb2cd18387c6d 100644 (file)
@@ -1,14 +1,14 @@
 """
-    babel.localedata
-    ~~~~~~~~~~~~~~~~
+babel.localedata
+~~~~~~~~~~~~~~~~
 
-    Low-level locale data access.
+Low-level locale data access.
 
-    :note: The `Locale` class, which uses this module under the hood, provides a
-           more convenient interface for accessing the locale data.
+:note: The `Locale` class, which uses this module under the hood, provides a
+       more convenient interface for accessing the locale data.
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
 
 from __future__ import annotations
@@ -89,8 +89,9 @@ def locale_identifiers() -> list[str]:
     """
     return [
         stem
-        for stem, extension in
-        (os.path.splitext(filename) for filename in os.listdir(_dirname))
+        for stem, extension in (
+            os.path.splitext(filename) for filename in os.listdir(_dirname)
+        )
         if extension == '.dat' and stem != 'root'
     ]
 
@@ -151,6 +152,7 @@ def load(name: os.PathLike[str] | str, merge_inherited: bool = True) -> dict[str
                 data = {}
             else:
                 from babel.core import get_global
+
                 parent = get_global('parent_exceptions').get(name)
                 if not parent:
                     if _is_non_likely_script(name):
@@ -242,7 +244,11 @@ class LocaleDataDict(abc.MutableMapping):
     values.
     """
 
-    def __init__(self, data: MutableMapping[str | int | None, Any], base: Mapping[str | int | None, Any] | None = None):
+    def __init__(
+        self,
+        data: MutableMapping[str | int | None, Any],
+        base: Mapping[str | int | None, Any] | None = None,
+    ):
         self._data = data
         if base is None:
             base = data
index 854c07496a10277f5df1b8b6d3d39eb6e851689e..8076516ec7e78306c1b9b09483c80217149c7eb9 100644 (file)
@@ -1,12 +1,12 @@
 """
-    babel.localtime
-    ~~~~~~~~~~~~~~~
+babel.localtime
+~~~~~~~~~~~~~~~
 
-    Babel specific fork of tzlocal to determine the local timezone
-    of the system.
+Babel specific fork of tzlocal to determine the local timezone
+of the system.
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
 
 import datetime
index 73def22e757ba1caa5b11052ad820e9bc911111c..6cd67b5ce078ee3d04e8fd451027740c55f292db 100644 (file)
@@ -1,11 +1,11 @@
 """
-    babel.localtime._fallback
-    ~~~~~~~~~~~~~~~~~~~~~~~~~
+babel.localtime._fallback
+~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    Emulated fallback local timezone when all else fails.
+Emulated fallback local timezone when all else fails.
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
 
 import datetime
@@ -19,7 +19,6 @@ ZERO = datetime.timedelta(0)
 
 
 class _FallbackLocalTimezone(datetime.tzinfo):
-
     def utcoffset(self, dt: datetime.datetime) -> datetime.timedelta:
         if self._isdst(dt):
             return DSTOFFSET
index 782a7d246ce2ca8cf2bb70857f670e11aeeacee0..70dd2322cf3b12c14df15bfab5a72bd7d11b2720 100644 (file)
@@ -51,7 +51,7 @@ def _get_localzone(_root: str = '/') -> datetime.tzinfo:
             # `None` (as a fix for #1092).
             # Instead, let's just "fix" the double slash symlink by stripping
             # leading slashes before passing the assumed zone name forward.
-            zone_name = link_dst[pos + 10:].lstrip("/")
+            zone_name = link_dst[pos + 10 :].lstrip("/")
             tzinfo = _get_tzinfo(zone_name)
             if tzinfo is not None:
                 return tzinfo
index 1a52567bc44cf0f5688cccffa869673b72b8cde7..0fb625ba906b8d9d19f5358e89a88e6882b50c01 100644 (file)
@@ -92,7 +92,6 @@ def get_localzone_name() -> str:
 
 def _get_localzone() -> datetime.tzinfo:
     if winreg is None:
-        raise LookupError(
-            'Runtime support not available')
+        raise LookupError('Runtime support not available')
 
     return _get_tzinfo_or_raise(get_localzone_name())
index ca83faa97dd7e54f6f3681bb5af245da8687a107..6e445e6b0d54f2ea224cf14d4d70ffcd26ba057b 100644 (file)
@@ -1,11 +1,11 @@
 """
-    babel.messages
-    ~~~~~~~~~~~~~~
+babel.messages
+~~~~~~~~~~~~~~
 
-    Support for ``gettext`` message catalogs.
+Support for ``gettext`` message catalogs.
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
 
 from babel.messages.catalog import (
index b43edf54ca1dbff63af0243bdf5a4ff34b1175bf..4317ec9201bbce353c7e446ac39238ef5db51762 100644 (file)
@@ -1,12 +1,13 @@
 """
-    babel.messages.catalog
-    ~~~~~~~~~~~~~~~~~~~~~~
+babel.messages.catalog
+~~~~~~~~~~~~~~~~~~~~~~
 
-    Data structures for message catalogs.
+Data structures for message catalogs.
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
+
 from __future__ import annotations
 
 import datetime
@@ -54,9 +55,11 @@ def get_close_matches(word, possibilities, n=3, cutoff=0.6):
     s.set_seq2(word)
     for x in possibilities:
         s.set_seq1(x)
-        if s.real_quick_ratio() >= cutoff and \
-           s.quick_ratio() >= cutoff and \
-           s.ratio() >= cutoff:
+        if (
+            s.real_quick_ratio() >= cutoff
+            and s.quick_ratio() >= cutoff
+            and s.ratio() >= cutoff
+        ):
             result.append((s.ratio(), x))
 
     # Move the best scorers to head of list
@@ -65,7 +68,8 @@ def get_close_matches(word, possibilities, n=3, cutoff=0.6):
     return [x for score, x in result]
 
 
-PYTHON_FORMAT = re.compile(r'''
+PYTHON_FORMAT = re.compile(
+    r'''
     \%
         (?:\(([\w]*)\))?
         (
@@ -74,7 +78,9 @@ PYTHON_FORMAT = re.compile(r'''
             [hlL]?
         )
         ([diouxXeEfFgGcrs%])
-''', re.VERBOSE)
+''',
+    re.VERBOSE,
+)
 
 
 def _has_python_brace_format(string: str) -> bool:
@@ -191,10 +197,12 @@ class Message:
 
     def __cmp__(self, other: object) -> int:
         """Compare Messages, taking into account plural ids"""
+
         def values_to_compare(obj):
             if isinstance(obj, Message) and obj.pluralizable:
                 return obj.id[0], obj.context or ''
             return obj.id, obj.context or ''
+
         return _cmp(values_to_compare(self), values_to_compare(other))
 
     def __gt__(self, other: object) -> bool:
@@ -246,6 +254,7 @@ class Message:
               in a catalog.
         """
         from babel.messages.checkers import checkers
+
         errors: list[TranslationError] = []
         for checker in checkers:
             try:
@@ -334,6 +343,7 @@ DEFAULT_HEADER = """\
 def parse_separated_header(value: str) -> dict[str, str]:
     # Adapted from https://peps.python.org/pep-0594/#cgi
     from email.message import Message
+
     m = Message()
     m['content-type'] = value
     return dict(m.get_params())
@@ -439,7 +449,9 @@ class Catalog:
                 self._locale = None
             return
 
-        raise TypeError(f"`locale` must be a Locale, a locale identifier string, or None; got {locale!r}")
+        raise TypeError(
+            f"`locale` must be a Locale, a locale identifier string, or None; got {locale!r}",
+        )
 
     def _get_locale(self) -> Locale | None:
         return self._locale
@@ -455,11 +467,13 @@ class Catalog:
         year = datetime.datetime.now(LOCALTZ).strftime('%Y')
         if hasattr(self.revision_date, 'strftime'):
             year = self.revision_date.strftime('%Y')
-        comment = comment.replace('PROJECT', self.project) \
-                         .replace('VERSION', self.version) \
-                         .replace('YEAR', year) \
-                         .replace('ORGANIZATION', self.copyright_holder)
-        locale_name = (self.locale.english_name if self.locale else self.locale_identifier)
+        comment = (
+            comment.replace('PROJECT', self.project)
+            .replace('VERSION', self.version)
+            .replace('YEAR', year)
+            .replace('ORGANIZATION', self.copyright_holder)
+        )
+        locale_name = self.locale.english_name if self.locale else self.locale_identifier
         if locale_name:
             comment = comment.replace("Translations template", f"{locale_name} translations")
         return comment
@@ -467,7 +481,10 @@ class Catalog:
     def _set_header_comment(self, string: str | None) -> None:
         self._header_comment = string
 
-    header_comment = property(_get_header_comment, _set_header_comment, doc="""\
+    header_comment = property(
+        _get_header_comment,
+        _set_header_comment,
+        doc="""\
     The header comment for the catalog.
 
     >>> catalog = Catalog(project='Foobar', version='1.0',
@@ -498,11 +515,16 @@ class Catalog:
     #
 
     :type: `unicode`
-    """)
+    """,
+    )
 
     def _get_mime_headers(self) -> list[tuple[str, str]]:
         if isinstance(self.revision_date, (datetime.datetime, datetime.time, int, float)):
-            revision_date = format_datetime(self.revision_date, 'yyyy-MM-dd HH:mmZ', locale='en')
+            revision_date = format_datetime(
+                self.revision_date,
+                'yyyy-MM-dd HH:mmZ',
+                locale='en',
+            )
         else:
             revision_date = self.revision_date
 
@@ -566,7 +588,10 @@ class Catalog:
                 if 'YEAR' not in value:
                     self.revision_date = _parse_datetime_header(value)
 
-    mime_headers = property(_get_mime_headers, _set_mime_headers, doc="""\
+    mime_headers = property(
+        _get_mime_headers,
+        _set_mime_headers,
+        doc="""\
     The MIME headers of the catalog, used for the special ``msgid ""`` entry.
 
     The behavior of this property changes slightly depending on whether a locale
@@ -616,7 +641,8 @@ class Catalog:
     Generated-By: Babel ...
 
     :type: `list`
-    """)
+    """,
+    )
 
     @property
     def num_plurals(self) -> int:
@@ -749,8 +775,9 @@ class Catalog:
             self.fuzzy = message.fuzzy
         else:
             if isinstance(id, (list, tuple)):
-                assert isinstance(message.string, (list, tuple)), \
+                assert isinstance(message.string, (list, tuple)), (
                     f"Expected sequence but got {type(message.string)}"
+                )
             self._messages[key] = message
 
     def add(
@@ -790,9 +817,17 @@ class Catalog:
                        PO file, if any
         :param context: the message context
         """
-        message = Message(id, string, list(locations), flags, auto_comments,
-                          user_comments, previous_id, lineno=lineno,
-                          context=context)
+        message = Message(
+            id,
+            string,
+            list(locations),
+            flags,
+            auto_comments,
+            user_comments,
+            previous_id,
+            lineno=lineno,
+            context=context,
+        )
         self[id] = message
         return message
 
@@ -905,7 +940,11 @@ class Catalog:
                     fuzzy_candidates[self._to_fuzzy_match_key(key)] = (key, ctxt)
         fuzzy_matches = set()
 
-        def _merge(message: Message, oldkey: tuple[str, str] | str, newkey: tuple[str, str] | str) -> None:
+        def _merge(
+            message: Message,
+            oldkey: tuple[str, str] | str,
+            newkey: tuple[str, str] | str,
+        ) -> None:
             message = message.clone()
             fuzzy = False
             if oldkey != newkey:
@@ -933,7 +972,7 @@ class Catalog:
                     )
                 elif len(message.string) != self.num_plurals:
                     fuzzy = True
-                    message.string = tuple(message.string[:len(oldmsg.string)])
+                    message.string = tuple(message.string[: len(oldmsg.string)])
             elif isinstance(message.string, (list, tuple)):
                 fuzzy = True
                 message.string = message.string[0]
@@ -987,7 +1026,11 @@ class Catalog:
             matchkey = key
         return matchkey.lower().strip()
 
-    def _key_for(self, id: _MessageID, context: str | None = None) -> tuple[str, str] | str:
+    def _key_for(
+        self,
+        id: _MessageID,
+        context: str | None = None,
+    ) -> tuple[str, str] | str:
         """The key for a message is just the singular ID even for pluralizable
         messages, but is a ``(msgid, msgctxt)`` tuple for context-specific
         messages.
@@ -1007,10 +1050,6 @@ class Catalog:
         for key in self._messages.keys() | other._messages.keys():
             message_1 = self.get(key)
             message_2 = other.get(key)
-            if (
-                message_1 is None
-                or message_2 is None
-                or not message_1.is_identical(message_2)
-            ):
+            if message_1 is None or message_2 is None or not message_1.is_identical(message_2):
                 return False
         return dict(self.mime_headers) == dict(other.mime_headers)
index e56bce9a1064d3cc84a28e0d369e24208454c920..28081160f718916a497872b8003a5b48402f8418 100644 (file)
@@ -1,14 +1,15 @@
 """
-    babel.messages.checkers
-    ~~~~~~~~~~~~~~~~~~~~~~~
+babel.messages.checkers
+~~~~~~~~~~~~~~~~~~~~~~~
 
-    Various routines that help with validation of translations.
+Various routines that help with validation of translations.
 
-    :since: version 0.9
+:since: version 0.9
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
+
 from __future__ import annotations
 
 from collections.abc import Callable
@@ -115,8 +116,9 @@ def _validate_format(format: str, alternative: str) -> None:
                 positional = name is None
             else:
                 if (name is None) != positional:
-                    raise TranslationError('format string mixes positional '
-                                           'and named placeholders')
+                    raise TranslationError(
+                        'format string mixes positional and named placeholders',
+                    )
         return bool(positional)
 
     a = _parse(format)
@@ -161,6 +163,7 @@ def _validate_format(format: str, alternative: str) -> None:
 
 def _find_checkers() -> list[Callable[[Catalog | None, Message], object]]:
     from babel.messages._compat import find_entrypoints
+
     checkers: list[Callable[[Catalog | None, Message], object]] = []
     checkers.extend(load() for (name, load) in find_entrypoints('babel.checkers'))
     if len(checkers) == 0:
index d3ae9da9bee290c29f1dce9d0d3d4da95c850832..c4ce46e824c3afa4d1d844f7ef5c9c23eab4ce39 100644 (file)
@@ -1,20 +1,21 @@
 """
-    babel.messages.extract
-    ~~~~~~~~~~~~~~~~~~~~~~
+babel.messages.extract
+~~~~~~~~~~~~~~~~~~~~~~
 
-    Basic infrastructure for extracting localizable messages from source files.
+Basic infrastructure for extracting localizable messages from source files.
 
-    This module defines an extensible system for collecting localizable message
-    strings from a variety of sources. A native extractor for Python source
-    files is builtin, extractors for other sources can be added using very
-    simple plugins.
+This module defines an extensible system for collecting localizable message
+strings from a variety of sources. A native extractor for Python source
+files is builtin, extractors for other sources can be added using very
+simple plugins.
 
-    The main entry points into the extraction functionality are the functions
-    `extract_from_dir` and `extract_from_file`.
+The main entry points into the extraction functionality are the functions
+`extract_from_dir` and `extract_from_file`.
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
+
 from __future__ import annotations
 
 import ast
@@ -103,11 +104,13 @@ def _strip_comment_tags(comments: MutableSequence[str], tags: Iterable[str]):
     """Helper function for `extract` that strips comment tags from strings
     in a list of comment lines.  This functions operates in-place.
     """
+
     def _strip(line: str):
         for tag in tags:
             if line.startswith(tag):
-                return line[len(tag):].strip()
+                return line[len(tag) :].strip()
         return line
+
     comments[:] = [_strip(c) for c in comments]
 
 
@@ -206,8 +209,7 @@ def extract_from_dir(
     absname = os.path.abspath(dirname)
     for root, dirnames, filenames in os.walk(absname):
         dirnames[:] = [
-            subdir for subdir in dirnames
-            if directory_filter(os.path.join(root, subdir))
+            subdir for subdir in dirnames if directory_filter(os.path.join(root, subdir))
         ]
         dirnames.sort()
         filenames.sort()
@@ -280,7 +282,8 @@ def check_and_call_extract_file(
         if callback:
             callback(filename, method, options)
         for message_tuple in extract_from_file(
-            method, filepath,
+            method,
+            filepath,
             keywords=keywords,
             comment_tags=comment_tags,
             options=options,
@@ -321,8 +324,9 @@ def extract_from_file(
         return []
 
     with open(filename, 'rb') as fileobj:
-        return list(extract(method, fileobj, keywords, comment_tags,
-                            options, strip_comment_tags))
+        return list(
+            extract(method, fileobj, keywords, comment_tags, options, strip_comment_tags),
+        )
 
 
 def _match_messages_against_spec(
@@ -357,7 +361,7 @@ def _match_messages_against_spec(
         first_msg_index = spec[0] - 1
     # An empty string msgid isn't valid, emit a warning
     if not messages[first_msg_index]:
-        filename = (getattr(fileobj, "name", None) or "(unknown)")
+        filename = getattr(fileobj, "name", None) or "(unknown)"
         sys.stderr.write(
             f"{filename}:{lineno}: warning: Empty msgid.  It is reserved by GNU gettext: gettext(\"\") "
             f"returns the header entry with meta information, not the empty string.\n",
@@ -431,7 +435,7 @@ def extract(
     elif ':' in method or '.' in method:
         if ':' not in method:
             lastdot = method.rfind('.')
-            module, attrname = method[:lastdot], method[lastdot + 1:]
+            module, attrname = method[:lastdot], method[lastdot + 1 :]
         else:
             module, attrname = method.split(':', 1)
         func = getattr(__import__(module, {}, {}, [attrname]), attrname)
@@ -445,8 +449,7 @@ def extract(
     if func is None:
         raise ValueError(f"Unknown extraction method {method!r}")
 
-    results = func(fileobj, keywords.keys(), comment_tags,
-                   options=options or {})
+    results = func(fileobj, keywords.keys(), comment_tags, options=options or {})
 
     for lineno, funcname, messages, comments in results:
         if not isinstance(messages, (list, tuple)):
@@ -543,8 +546,7 @@ def extract_python(
         elif not call_stack and tok == COMMENT:
             # Strip the comment token from the line
             value = value[1:].strip()
-            if in_translator_comments and \
-                    translator_comments[-1][0] == lineno - 1:
+            if in_translator_comments and translator_comments[-1][0] == lineno - 1:
                 # We're already inside a translator comment, continue appending
                 translator_comments.append((lineno, value))
                 continue
@@ -556,7 +558,7 @@ def extract_python(
                     translator_comments.append((lineno, value))
                     break
         elif funcname and len(call_stack) == 1:
-            nested = (tok == NAME and value in keywords)
+            nested = tok == NAME and value in keywords
             if (tok == OP and value == ')') or nested:
                 if buf:
                     messages.append(''.join(buf))
@@ -574,8 +576,12 @@ def extract_python(
                         # to start this message's translation call is.
                         translator_comments.clear()
 
-                yield (message_lineno, funcname, messages,
-                       [comment[1] for comment in translator_comments])
+                yield (
+                    message_lineno,
+                    funcname,
+                    messages,
+                    [comment[1] for comment in translator_comments],
+                )
 
                 funcname = lineno = message_lineno = None
                 call_stack.clear()
@@ -682,6 +688,7 @@ def extract_javascript(
     :param lineno: line number offset (for parsing embedded fragments)
     """
     from babel.messages.jslexer import Token, tokenize, unquote_string
+
     funcname = message_lineno = None
     messages = []
     last_argument = None
@@ -711,8 +718,18 @@ def extract_javascript(
             call_stack = 0
             token = Token('operator', ')', token.lineno)
 
-        if options.get('parse_template_string') and not funcname and token.type == 'template_string':
-            yield from parse_template_string(token.value, keywords, comment_tags, options, token.lineno)
+        if (
+            options.get('parse_template_string')
+            and not funcname
+            and token.type == 'template_string'
+        ):
+            yield from parse_template_string(
+                token.value,
+                keywords,
+                comment_tags,
+                options,
+                token.lineno,
+            )
 
         elif token.type == 'operator' and token.value == '(':
             if funcname:
@@ -721,8 +738,7 @@ def extract_javascript(
 
         elif call_stack == -1 and token.type == 'linecomment':
             value = token.value[2:].strip()
-            if translator_comments and \
-               translator_comments[-1][0] == token.lineno - 1:
+            if translator_comments and translator_comments[-1][0] == token.lineno - 1:
                 translator_comments.append((token.lineno, value))
                 continue
 
@@ -742,8 +758,7 @@ def extract_javascript(
                         lines[0] = lines[0].strip()
                         lines[1:] = dedent('\n'.join(lines[1:])).splitlines()
                         for offset, line in enumerate(lines):
-                            translator_comments.append((token.lineno + offset,
-                                                        line))
+                            translator_comments.append((token.lineno + offset, line))
                     break
 
         elif funcname and call_stack == 0:
@@ -759,13 +774,16 @@ def extract_javascript(
 
                 # Comments don't apply unless they immediately precede the
                 # message
-                if translator_comments and \
-                   translator_comments[-1][0] < message_lineno - 1:
+                if translator_comments and translator_comments[-1][0] < message_lineno - 1:
                     translator_comments = []
 
                 if messages is not None:
-                    yield (message_lineno, funcname, messages,
-                           [comment[1] for comment in translator_comments])
+                    yield (
+                        message_lineno,
+                        funcname,
+                        messages,
+                        [comment[1] for comment in translator_comments],
+                    )
 
                 funcname = message_lineno = last_argument = None
                 concatenate_next = False
@@ -792,17 +810,22 @@ def extract_javascript(
                 elif token.value == '+':
                     concatenate_next = True
 
-        elif call_stack > 0 and token.type == 'operator' \
-                and token.value == ')':
+        elif call_stack > 0 and token.type == 'operator' and token.value == ')':
             call_stack -= 1
 
         elif funcname and call_stack == -1:
             funcname = None
 
-        elif call_stack == -1 and token.type == 'name' and \
-            token.value in keywords and \
-            (last_token is None or last_token.type != 'name' or
-             last_token.value != 'function'):
+        elif (
+            call_stack == -1
+            and token.type == 'name'
+            and token.value in keywords
+            and (
+                last_token is None
+                or last_token.type != 'name'
+                or last_token.value != 'function'
+            )
+        ):
             funcname = token.value
 
         last_token = token
@@ -826,6 +849,7 @@ def parse_template_string(
     :param lineno: starting line number (optional)
     """
     from babel.messages.jslexer import line_re
+
     prev_character = None
     level = 0
     inside_str = False
@@ -845,7 +869,13 @@ def parse_template_string(
                 if level == 0 and expression_contents:
                     expression_contents = expression_contents[0:-1]
                     fake_file_obj = io.BytesIO(expression_contents.encode())
-                    yield from extract_javascript(fake_file_obj, keywords, comment_tags, options, lineno)
+                    yield from extract_javascript(
+                        fake_file_obj,
+                        keywords,
+                        comment_tags,
+                        options,
+                        lineno,
+                    )
                     lineno += len(line_re.findall(expression_contents))
                     expression_contents = ''
         prev_character = character
index e5d2a113effe104a6e09003c6f55f82aaf6dfb9f..6ef62ec4aca6fb9b82f74fdfb69bbd3237c60c77 100644 (file)
@@ -1,11 +1,11 @@
 """
-    babel.messages.frontend
-    ~~~~~~~~~~~~~~~~~~~~~~~
+babel.messages.frontend
+~~~~~~~~~~~~~~~~~~~~~~~
 
-    Frontends for the message extraction functionality.
+Frontends for the message extraction functionality.
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
 
 from __future__ import annotations
@@ -200,7 +200,7 @@ class CompileCatalog(CommandMixin):
                 n_errors += len(errors)
         if n_errors:
             self.log.error('%d errors encountered.', n_errors)
-        return (1 if n_errors else 0)
+        return 1 if n_errors else 0
 
     def _get_po_mo_triples(self, domain: str):
         if not self.input_file:
@@ -211,7 +211,7 @@ class CompileCatalog(CommandMixin):
                 yield self.locale, po_file, po_file.with_suffix(".mo")
             else:
                 for locale_path in dir_path.iterdir():
-                    po_file = locale_path / "LC_MESSAGES"/ f"{domain}.po"
+                    po_file = locale_path / "LC_MESSAGES" / f"{domain}.po"
                     if po_file.exists():
                         yield locale_path.name, po_file, po_file.with_suffix(".mo")
         else:
@@ -219,7 +219,9 @@ class CompileCatalog(CommandMixin):
             if self.output_file:
                 mo_file = pathlib.Path(self.output_file)
             else:
-                mo_file = pathlib.Path(self.directory) / self.locale / "LC_MESSAGES" / f"{domain}.mo"
+                mo_file = (
+                    pathlib.Path(self.directory) / self.locale / "LC_MESSAGES" / f"{domain}.mo"
+                )
             yield self.locale, po_file, mo_file
 
     def _run_domain(self, domain):
@@ -243,7 +245,10 @@ class CompileCatalog(CommandMixin):
                     percentage = translated * 100 // len(catalog)
                 self.log.info(
                     '%d of %d messages (%d%%) translated in %s',
-                    translated, len(catalog), percentage, po_file,
+                    translated,
+                    len(catalog),
+                    percentage,
+                    po_file,
                 )
 
             if catalog.fuzzy and not self.use_fuzzy:
@@ -253,9 +258,7 @@ class CompileCatalog(CommandMixin):
             catalogs_and_errors[catalog] = catalog_errors = list(catalog.check())
             for message, errors in catalog_errors:
                 for error in errors:
-                    self.log.error(
-                        'error: %s:%d: %s', po_file, message.lineno, error,
-                    )
+                    self.log.error('error: %s:%d: %s', po_file, message.lineno, error)
 
             self.log.info('compiling catalog %s to %s', po_file, mo_file)
 
@@ -273,9 +276,7 @@ def _make_directory_filter(ignore_patterns):
     def cli_directory_filter(dirname):
         basename = os.path.basename(dirname)
         return not any(
-            fnmatch.fnmatch(basename, ignore_pattern)
-            for ignore_pattern
-            in ignore_patterns
+            fnmatch.fnmatch(basename, ignore_pattern) for ignore_pattern in ignore_patterns
         )
 
     return cli_directory_filter
@@ -340,8 +341,13 @@ class ExtractMessages(CommandMixin):
          'set the name and email of the last translator in output'),
     ]  # fmt: skip
     boolean_options = [
-        'no-default-keywords', 'no-location', 'omit-header', 'no-wrap',
-        'sort-output', 'sort-by-file', 'strip-comments',
+        'no-default-keywords',
+        'no-location',
+        'omit-header',
+        'no-wrap',
+        'sort-output',
+        'sort-by-file',
+        'strip-comments',
     ]
     as_args = 'input-paths'
     multiple_value_options = (
@@ -483,13 +489,15 @@ class ExtractMessages(CommandMixin):
     def run(self):
         mappings = self._get_mappings()
         with open(self.output_file, 'wb') as outfile:
-            catalog = Catalog(project=self.project,
-                              version=self.version,
-                              msgid_bugs_address=self.msgid_bugs_address,
-                              copyright_holder=self.copyright_holder,
-                              charset=self.charset,
-                              header_comment=(self.header_comment or DEFAULT_HEADER),
-                              last_translator=self.last_translator)
+            catalog = Catalog(
+                project=self.project,
+                version=self.version,
+                msgid_bugs_address=self.msgid_bugs_address,
+                copyright_holder=self.copyright_holder,
+                charset=self.charset,
+                header_comment=(self.header_comment or DEFAULT_HEADER),
+                last_translator=self.last_translator,
+            )
 
             for path, method_map, options_map in mappings:
                 callback = self._build_callback(path)
@@ -522,8 +530,13 @@ class ExtractMessages(CommandMixin):
                     else:
                         filepath = os.path.normpath(os.path.join(path, filename))
 
-                    catalog.add(message, None, [(filepath, lineno)],
-                                auto_comments=comments, context=context)
+                    catalog.add(
+                        message,
+                        None,
+                        [(filepath, lineno)],
+                        auto_comments=comments,
+                        context=context,
+                    )
 
             self.log.info('writing PO template file to %s', self.output_file)
             write_po(
@@ -555,7 +568,10 @@ class ExtractMessages(CommandMixin):
                     )
             else:
                 with open(self.mapping_file) as fileobj:
-                    method_map, options_map = parse_mapping_cfg(fileobj, filename=self.mapping_file)
+                    method_map, options_map = parse_mapping_cfg(
+                        fileobj,
+                        filename=self.mapping_file,
+                    )
             for path in self.input_paths:
                 mappings.append((path, method_map, options_map))
 
@@ -637,7 +653,9 @@ class InitCatalog(CommandMixin):
 
     def run(self):
         self.log.info(
-            'creating catalog %s based on %s', self.output_file, self.input_file,
+            'creating catalog %s based on %s',
+            self.output_file,
+            self.input_file,
         )
 
         with open(self.input_file, 'rb') as infile:
@@ -692,9 +710,15 @@ class UpdateCatalog(CommandMixin):
          'ignore changes to POT-Creation-Date when updating or checking'),
     ]  # fmt: skip
     boolean_options = [
-        'omit-header', 'no-wrap', 'ignore-obsolete', 'init-missing',
-        'no-fuzzy-matching', 'previous', 'update-header-comment',
-        'check', 'ignore-pot-creation-date',
+        'omit-header',
+        'no-wrap',
+        'ignore-obsolete',
+        'init-missing',
+        'no-fuzzy-matching',
+        'previous',
+        'update-header-comment',
+        'check',
+        'ignore-pot-creation-date',
     ]
 
     def initialize_options(self):
@@ -725,8 +749,7 @@ class UpdateCatalog(CommandMixin):
         if self.init_missing:
             if not self.locale:
                 raise OptionError(
-                    'you must specify the locale for '
-                    'the init-missing option to work',
+                    'you must specify the locale for the init-missing option to work',
                 )
 
             try:
@@ -779,7 +802,9 @@ class UpdateCatalog(CommandMixin):
                     check_status[filename] = False
                     continue
                 self.log.info(
-                    'creating catalog %s based on %s', filename, self.input_file,
+                    'creating catalog %s based on %s',
+                    filename,
+                    self.input_file,
                 )
 
                 with open(self.input_file, 'rb') as infile:
@@ -805,9 +830,10 @@ class UpdateCatalog(CommandMixin):
                 update_creation_date=not self.ignore_pot_creation_date,
             )
 
-            tmpname = os.path.join(os.path.dirname(filename),
-                                   tempfile.gettempprefix() +
-                                   os.path.basename(filename))
+            tmpname = os.path.join(
+                os.path.dirname(filename),
+                tempfile.gettempprefix() + os.path.basename(filename),
+            )
             try:
                 with open(tmpname, 'wb') as tmpfile:
                     write_po(
@@ -891,8 +917,10 @@ class CommandLineInterface:
         if argv is None:
             argv = sys.argv
 
-        self.parser = optparse.OptionParser(usage=self.usage % ('command', '[args]'),
-                                            version=self.version)
+        self.parser = optparse.OptionParser(
+            usage=self.usage % ('command', '[args]'),
+            version=self.version,
+        )
         self.parser.disable_interspersed_args()
         self.parser.print_help = self._help
         self.parser.add_option(
@@ -1065,40 +1093,58 @@ def _parse_config_object(config: dict, *, filename="(unknown)"):
 
     extractors_read = config.get("extractors", {})
     if not isinstance(extractors_read, dict):
-        raise ConfigurationError(f"{filename}: extractors: Expected a dictionary, got {type(extractors_read)!r}")
+        raise ConfigurationError(
+            f"{filename}: extractors: Expected a dictionary, got {type(extractors_read)!r}",
+        )
     for method, callable_spec in extractors_read.items():
         if not isinstance(method, str):
             # Impossible via TOML, but could happen with a custom object.
-            raise ConfigurationError(f"{filename}: extractors: Extraction method must be a string, got {method!r}")
+            raise ConfigurationError(
+                f"{filename}: extractors: Extraction method must be a string, got {method!r}",
+            )
         if not isinstance(callable_spec, str):
-            raise ConfigurationError(f"{filename}: extractors: Callable specification must be a string, got {callable_spec!r}")
+            raise ConfigurationError(
+                f"{filename}: extractors: Callable specification must be a string, got {callable_spec!r}",
+            )
         extractors[method] = callable_spec
 
     if "mapping" in config:
-        raise ConfigurationError(f"{filename}: 'mapping' is not a valid key, did you mean 'mappings'?")
+        raise ConfigurationError(
+            f"{filename}: 'mapping' is not a valid key, did you mean 'mappings'?",
+        )
 
     mappings_read = config.get("mappings", [])
     if not isinstance(mappings_read, list):
-        raise ConfigurationError(f"{filename}: mappings: Expected a list, got {type(mappings_read)!r}")
+        raise ConfigurationError(
+            f"{filename}: mappings: Expected a list, got {type(mappings_read)!r}",
+        )
     for idx, entry in enumerate(mappings_read):
         if not isinstance(entry, dict):
-            raise ConfigurationError(f"{filename}: mappings[{idx}]: Expected a dictionary, got {type(entry)!r}")
+            raise ConfigurationError(
+                f"{filename}: mappings[{idx}]: Expected a dictionary, got {type(entry)!r}",
+            )
         entry = entry.copy()
 
         method = entry.pop("method", None)
         if not isinstance(method, str):
-            raise ConfigurationError(f"{filename}: mappings[{idx}]: 'method' must be a string, got {method!r}")
+            raise ConfigurationError(
+                f"{filename}: mappings[{idx}]: 'method' must be a string, got {method!r}",
+            )
         method = extractors.get(method, method)  # Map the extractor name to the callable now
 
         pattern = entry.pop("pattern", None)
         if not isinstance(pattern, (list, str)):
-            raise ConfigurationError(f"{filename}: mappings[{idx}]: 'pattern' must be a list or a string, got {pattern!r}")
+            raise ConfigurationError(
+                f"{filename}: mappings[{idx}]: 'pattern' must be a list or a string, got {pattern!r}",
+            )
         if not isinstance(pattern, list):
             pattern = [pattern]
 
         for pat in pattern:
             if not isinstance(pat, str):
-                raise ConfigurationError(f"{filename}: mappings[{idx}]: 'pattern' elements must be strings, got {pat!r}")
+                raise ConfigurationError(
+                    f"{filename}: mappings[{idx}]: 'pattern' elements must be strings, got {pat!r}",
+                )
             method_map.append((pat, method))
             options_map[pat] = entry
 
@@ -1135,11 +1181,15 @@ def _parse_mapping_toml(
         try:
             babel_data = parsed_data["tool"]["babel"]
         except (TypeError, KeyError) as e:
-            raise ConfigurationError(f"{filename}: No 'tool.babel' section found in file") from e
+            raise ConfigurationError(
+                f"{filename}: No 'tool.babel' section found in file",
+            ) from e
     elif style == "standalone":
         babel_data = parsed_data
         if "babel" in babel_data:
-            raise ConfigurationError(f"{filename}: 'babel' should not be present in a stand-alone configuration file")
+            raise ConfigurationError(
+                f"{filename}: 'babel' should not be present in a stand-alone configuration file",
+            )
     else:  # pragma: no cover
         raise ValueError(f"Unknown TOML style {style!r}")
 
@@ -1210,7 +1260,13 @@ def parse_keywords(strings: Iterable[str] = ()):
 def __getattr__(name: str):
     # Re-exports for backwards compatibility;
     # `setuptools_frontend` is the canonical import location.
-    if name in {'check_message_extractors', 'compile_catalog', 'extract_messages', 'init_catalog', 'update_catalog'}:
+    if name in {
+        'check_message_extractors',
+        'compile_catalog',
+        'extract_messages',
+        'init_catalog',
+        'update_catalog',
+    }:
         from babel.messages import setuptools_frontend
 
         return getattr(setuptools_frontend, name)
index 4cd79d5d79b6b9fa674a95dcfe9972960ca42c8a..df503e9486a42b9c03ab808982e9f8f8f6853516 100644 (file)
@@ -1,13 +1,14 @@
 """
-    babel.messages.jslexer
-    ~~~~~~~~~~~~~~~~~~~~~~
+babel.messages.jslexer
+~~~~~~~~~~~~~~~~~~~~~~
 
-    A simple JavaScript 1.5 lexer which is used for the JavaScript
-    extractor.
+A simple JavaScript 1.5 lexer which is used for the JavaScript
+extractor.
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
+
 from __future__ import annotations
 
 import re
@@ -62,7 +63,11 @@ _rules: list[tuple[str | None, re.Pattern[str]]] = [
 ]  # fmt: skip
 
 
-def get_rules(jsx: bool, dotted: bool, template_string: bool) -> list[tuple[str | None, re.Pattern[str]]]:
+def get_rules(
+    jsx: bool,
+    dotted: bool,
+    template_string: bool,
+) -> list[tuple[str | None, re.Pattern[str]]]:
     """
     Get a tokenization rule list given the passed syntax options.
 
@@ -95,8 +100,9 @@ def unquote_string(string: str) -> str:
     """Unquote a string with JavaScript rules.  The string has to start with
     string delimiters (``'``, ``"`` or the back-tick/grave accent (for template strings).)
     """
-    assert string and string[0] == string[-1] and string[0] in '"\'`', \
+    assert string and string[0] == string[-1] and string[0] in '"\'`', (
         'string provided is not properly delimited'
+    )
     string = line_join_re.sub('\\1', string[1:-1])
     result: list[str] = []
     add = result.append
@@ -158,7 +164,13 @@ def unquote_string(string: str) -> str:
     return ''.join(result)
 
 
-def tokenize(source: str, jsx: bool = True, dotted: bool = True, template_string: bool = True, lineno: int = 1) -> Generator[Token, None, None]:
+def tokenize(
+    source: str,
+    jsx: bool = True,
+    dotted: bool = True,
+    template_string: bool = True,
+    lineno: int = 1,
+) -> Generator[Token, None, None]:
     """
     Tokenize JavaScript/JSX source.  Returns a generator of tokens.
 
index 20c67188d15ae78ed6bfff6cf11b5ae6a8a46cdd..9ec822b694245c963e03e6fec9b04fa8f9179a5b 100644 (file)
@@ -1,12 +1,13 @@
 """
-    babel.messages.mofile
-    ~~~~~~~~~~~~~~~~~~~~~
+babel.messages.mofile
+~~~~~~~~~~~~~~~~~~~~~
 
-    Writing of files in the ``gettext`` MO (machine object) format.
+Writing of files in the ``gettext`` MO (machine object) format.
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
+
 from __future__ import annotations
 
 import array
@@ -18,8 +19,8 @@ from babel.messages.catalog import Catalog, Message
 if TYPE_CHECKING:
     from _typeshed import SupportsRead, SupportsWrite
 
-LE_MAGIC: int = 0x950412de
-BE_MAGIC: int = 0xde120495
+LE_MAGIC: int = 0x950412DE
+BE_MAGIC: int = 0xDE120495
 
 
 def read_mo(fileobj: SupportsRead[bytes]) -> Catalog:
@@ -56,9 +57,9 @@ def read_mo(fileobj: SupportsRead[bytes]) -> Catalog:
     # Now put all messages from the .mo file buffer into the catalog
     # dictionary
     for _i in range(msgcount):
-        mlen, moff = unpack(ii, buf[origidx:origidx + 8])
+        mlen, moff = unpack(ii, buf[origidx : origidx + 8])
         mend = moff + mlen
-        tlen, toff = unpack(ii, buf[transidx:transidx + 8])
+        tlen, toff = unpack(ii, buf[transidx : transidx + 8])
         tend = toff + tlen
         if mend < buflen and tend < buflen:
             msg = buf[moff:mend]
@@ -153,8 +154,7 @@ def write_mo(fileobj: SupportsWrite[bytes], catalog: Catalog, use_fuzzy: bool =
                       in the output
     """
     messages = list(catalog)
-    messages[1:] = [m for m in messages[1:]
-                    if m.string and (use_fuzzy or not m.fuzzy)]
+    messages[1:] = [m for m in messages[1:] if m.string and (use_fuzzy or not m.fuzzy)]
     messages.sort()
 
     ids = strs = b''
index 5eae86ddda6f2c15373c744de1ccf95f6faaa382..a03fb4eddacda272c5b12e2f0e7257930bfbaa2c 100644 (file)
@@ -1,12 +1,13 @@
 """
-    babel.messages.plurals
-    ~~~~~~~~~~~~~~~~~~~~~~
+babel.messages.plurals
+~~~~~~~~~~~~~~~~~~~~~~
 
-    Plural form definitions.
+Plural form definitions.
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
+
 from __future__ import annotations
 
 from babel.core import Locale, default_locale
index e29d884076de8dcba4793974ac092d35af3b1aba..bffdc87ced357af34c1bf6925d0ffa43beaa50f0 100644 (file)
@@ -1,13 +1,14 @@
 """
-    babel.messages.pofile
-    ~~~~~~~~~~~~~~~~~~~~~
+babel.messages.pofile
+~~~~~~~~~~~~~~~~~~~~~
 
-    Reading and writing of files in the ``gettext`` PO (portable object)
-    format.
+Reading and writing of files in the ``gettext`` PO (portable object)
+format.
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
+
 from __future__ import annotations
 
 import os
@@ -38,6 +39,7 @@ def unescape(string: str) -> str:
 
     :param string: the string to unescape
     """
+
     def replace_escapes(match):
         m = match.group(1)
         if m == 'n':
@@ -100,14 +102,18 @@ def _extract_locations(line: str) -> list[str]:
     for c in line:
         if c == "\u2068":
             if in_filename:
-                raise ValueError("location comment contains more First Strong Isolate "
-                                 "characters, than Pop Directional Isolate characters")
+                raise ValueError(
+                    "location comment contains more First Strong Isolate "
+                    "characters, than Pop Directional Isolate characters",
+                )
             in_filename = True
             continue
         elif c == "\u2069":
             if not in_filename:
-                raise ValueError("location comment contains more Pop Directional Isolate "
-                                 "characters, than First Strong Isolate characters")
+                raise ValueError(
+                    "location comment contains more Pop Directional Isolate "
+                    "characters, than First Strong Isolate characters",
+                )
             in_filename = False
             continue
         elif c == " ":
@@ -121,8 +127,10 @@ def _extract_locations(line: str) -> list[str]:
     else:
         if location:
             if in_filename:
-                raise ValueError("location comment contains more First Strong Isolate "
-                                 "characters, than Pop Directional Isolate characters")
+                raise ValueError(
+                    "location comment contains more First Strong Isolate "
+                    "characters, than Pop Directional Isolate characters",
+                )
             locations.append(location)
 
     return locations
@@ -155,7 +163,12 @@ class PoFileParser:
     See `read_po` for simple cases.
     """
 
-    def __init__(self, catalog: Catalog, ignore_obsolete: bool = False, abort_invalid: bool = False) -> None:
+    def __init__(
+        self,
+        catalog: Catalog,
+        ignore_obsolete: bool = False,
+        abort_invalid: bool = False,
+    ) -> None:
         self.catalog = catalog
         self.ignore_obsolete = ignore_obsolete
         self.counter = 0
@@ -186,7 +199,11 @@ class PoFileParser:
             string = ['' for _ in range(self.catalog.num_plurals)]
             for idx, translation in sorted(self.translations):
                 if idx >= self.catalog.num_plurals:
-                    self._invalid_pofile("", self.offset, "msg has more translations than num_plurals of catalog")
+                    self._invalid_pofile(
+                        "",
+                        self.offset,
+                        "msg has more translations than num_plurals of catalog",
+                    )
                     continue
                 string[idx] = translation.denormalize()
             string = tuple(string)
@@ -194,9 +211,16 @@ class PoFileParser:
             msgid = self.messages[0].denormalize()
             string = self.translations[0][1].denormalize()
         msgctxt = self.context.denormalize() if self.context else None
-        message = Message(msgid, string, self.locations, self.flags,
-                          self.auto_comments, self.user_comments, lineno=self.offset + 1,
-                          context=msgctxt)
+        message = Message(
+            msgid,
+            string,
+            self.locations,
+            self.flags,
+            self.auto_comments,
+            self.user_comments,
+            lineno=self.offset + 1,
+            context=msgctxt,
+        )
         if self.obsolete:
             if not self.ignore_obsolete:
                 self.catalog.obsolete[self.catalog._key_for(msgid, msgctxt)] = message
@@ -208,7 +232,11 @@ class PoFileParser:
     def _finish_current_message(self) -> None:
         if self.messages:
             if not self.translations:
-                self._invalid_pofile("", self.offset, f"missing msgstr for msgid '{self.messages[0].denormalize()}'")
+                self._invalid_pofile(
+                    "",
+                    self.offset,
+                    f"missing msgstr for msgid '{self.messages[0].denormalize()}'",
+                )
                 self.translations.append([0, _NormalizedString()])
             self._add_message()
 
@@ -263,7 +291,11 @@ class PoFileParser:
         elif self.in_msgctxt:
             s = self.context
         else:
-            self._invalid_pofile(line, lineno, "Got line starting with \" but not in msgid, msgstr or msgctxt")
+            self._invalid_pofile(
+                line,
+                lineno,
+                "Got line starting with \" but not in msgid, msgstr or msgctxt",
+            )
             return
         # For performance reasons, `NormalizedString` doesn't strip internally
         s.append(line.strip())
index 3ea97bcc0db0a740bd5f3ce677516b637317766b..8a6e02dd8483f61216abb35366c8582c3d832889 100644 (file)
@@ -1,20 +1,21 @@
 """
-    babel.numbers
-    ~~~~~~~~~~~~~
+babel.numbers
+~~~~~~~~~~~~~
 
-    Locale dependent formatting and parsing of numeric data.
+Locale dependent formatting and parsing of numeric data.
 
-    The default locale for the functions in this module is determined by the
-    following environment variables, in that order:
+The default locale for the functions in this module is determined by the
+following environment variables, in that order:
 
    * ``LC_MONETARY`` for currency related functions,
    * ``LC_NUMERIC``, and
    * ``LC_ALL``, and
    * ``LANG``
+ * ``LC_MONETARY`` for currency related functions,
+ * ``LC_NUMERIC``, and
+ * ``LC_ALL``, and
+ * ``LANG``
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
+
 # TODO:
 #  Padding and rounding increments in pattern:
 #  - https://www.unicode.org/reports/tr35/ (Appendix G.6)
@@ -34,8 +35,7 @@ LC_NUMERIC = default_locale('LC_NUMERIC')
 
 
 class UnknownCurrencyError(Exception):
-    """Exception thrown when a currency is requested for which no data is available.
-    """
+    """Exception thrown when a currency is requested for which no data is available."""
 
     def __init__(self, identifier: str) -> None:
         """Create the exception.
@@ -48,7 +48,7 @@ class UnknownCurrencyError(Exception):
 
 
 def list_currencies(locale: Locale | str | None = None) -> set[str]:
-    """ Return a `set` of normalized currency codes.
+    """Return a `set` of normalized currency codes.
 
     .. versionadded:: 2.5.0
 
@@ -64,7 +64,7 @@ def list_currencies(locale: Locale | str | None = None) -> set[str]:
 
 
 def validate_currency(currency: str, locale: Locale | str | None = None) -> None:
-    """ Check the currency code is recognized by Babel.
+    """Check the currency code is recognized by Babel.
 
     Accepts a ``locale`` parameter for fined-grained validation, working as
     the one defined above in ``list_currencies()`` method.
@@ -76,7 +76,7 @@ def validate_currency(currency: str, locale: Locale | str | None = None) -> None
 
 
 def is_currency(currency: str, locale: Locale | str | None = None) -> bool:
-    """ Returns `True` only if a currency is recognized by Babel.
+    """Returns `True` only if a currency is recognized by Babel.
 
     This method always return a Boolean and never raise.
     """
@@ -208,8 +208,7 @@ def get_territory_currencies(
     tender: bool = ...,
     non_tender: bool = ...,
     include_details: Literal[False] = ...,
-) -> list[str]:
-    ...  # pragma: no cover
+) -> list[str]: ...  # pragma: no cover
 
 
 @overload
@@ -220,8 +219,7 @@ def get_territory_currencies(
     tender: bool = ...,
     non_tender: bool = ...,
     include_details: Literal[True] = ...,
-) -> list[dict[str, Any]]:
-    ...  # pragma: no cover
+) -> list[dict[str, Any]]: ...  # pragma: no cover
 
 
 def get_territory_currencies(
@@ -295,8 +293,7 @@ def get_territory_currencies(
     # TODO: validate that the territory exists
 
     def _is_active(start, end):
-        return (start is None or start <= end_date) and \
-               (end is None or end >= start_date)
+        return (start is None or start <= end_date) and (end is None or end >= start_date)
 
     result = []
     for currency_code, start, end, is_tender in curs:
@@ -304,22 +301,29 @@ def get_territory_currencies(
             start = datetime.date(*start)
         if end:
             end = datetime.date(*end)
-        if ((is_tender and tender) or
-                (not is_tender and non_tender)) and _is_active(start, end):
+        if ((is_tender and tender) or (not is_tender and non_tender)) and _is_active(
+            start,
+            end,
+        ):
             if include_details:
-                result.append({
-                    'currency': currency_code,
-                    'from': start,
-                    'to': end,
-                    'tender': is_tender,
-                })
+                result.append(
+                    {
+                        'currency': currency_code,
+                        'from': start,
+                        'to': end,
+                        'tender': is_tender,
+                    },
+                )
             else:
                 result.append(currency_code)
 
     return result
 
 
-def _get_numbering_system(locale: Locale, numbering_system: Literal["default"] | str = "latn") -> str:
+def _get_numbering_system(
+    locale: Locale,
+    numbering_system: Literal["default"] | str = "latn",
+) -> str:
     if numbering_system == "default":
         return locale.default_numbering_system
     else:
@@ -335,11 +339,14 @@ def _get_number_symbols(
     try:
         return locale.number_symbols[numbering_system]
     except KeyError as error:
-        raise UnsupportedNumberingSystemError(f"Unknown numbering system {numbering_system} for Locale {locale}.") from error
+        raise UnsupportedNumberingSystemError(
+            f"Unknown numbering system {numbering_system} for Locale {locale}.",
+        ) from error
 
 
 class UnsupportedNumberingSystemError(Exception):
     """Exception thrown when an unsupported numbering system is requested for the given Locale."""
+
     pass
 
 
@@ -481,7 +488,10 @@ def get_infinity_symbol(
     return _get_number_symbols(locale, numbering_system=numbering_system).get('infinity', '∞')
 
 
-def format_number(number: float | decimal.Decimal | str, locale: Locale | str | None = None) -> str:
+def format_number(
+    number: float | decimal.Decimal | str,
+    locale: Locale | str | None = None,
+) -> str:
     """Return the given number formatted for a specific locale.
 
     >>> format_number(1099, locale='en_US')  # doctest: +SKIP
@@ -498,7 +508,11 @@ def format_number(number: float | decimal.Decimal | str, locale: Locale | str |
 
 
     """
-    warnings.warn('Use babel.numbers.format_decimal() instead.', DeprecationWarning, stacklevel=2)
+    warnings.warn(
+        'Use babel.numbers.format_decimal() instead.',
+        DeprecationWarning,
+        stacklevel=2,
+    )
     return format_decimal(number, locale=locale)
 
 
@@ -583,7 +597,12 @@ def format_decimal(
         format = locale.decimal_formats[format]
     pattern = parse_pattern(format)
     return pattern.apply(
-        number, locale, decimal_quantization=decimal_quantization, group_separator=group_separator, numbering_system=numbering_system)
+        number,
+        locale,
+        decimal_quantization=decimal_quantization,
+        group_separator=group_separator,
+        numbering_system=numbering_system,
+    )
 
 
 def format_compact_decimal(
@@ -626,7 +645,12 @@ def format_compact_decimal(
     if format is None:
         format = locale.decimal_formats[None]
     pattern = parse_pattern(format)
-    return pattern.apply(number, locale, decimal_quantization=False, numbering_system=numbering_system)
+    return pattern.apply(
+        number,
+        locale,
+        decimal_quantization=False,
+        numbering_system=numbering_system,
+    )
 
 
 def _get_compact_format(
@@ -654,7 +678,10 @@ def _get_compact_format(
                 break
             # otherwise, we need to divide the number by the magnitude but remove zeros
             # equal to the number of 0's in the pattern minus 1
-            number = cast(decimal.Decimal, number / (magnitude // (10 ** (pattern.count("0") - 1))))
+            number = cast(
+                decimal.Decimal,
+                number / (magnitude // (10 ** (pattern.count("0") - 1))),
+            )
             # round to the number of fraction digits requested
             rounded = round(number, fraction_digits)
             # if the remaining number is singular, use the singular format
@@ -797,11 +824,19 @@ def format_currency(
         try:
             pattern = locale.currency_formats[format_type]
         except KeyError:
-            raise UnknownCurrencyFormatError(f"{format_type!r} is not a known currency format type") from None
+            raise UnknownCurrencyFormatError(
+                f"{format_type!r} is not a known currency format type",
+            ) from None
 
     return pattern.apply(
-        number, locale, currency=currency, currency_digits=currency_digits,
-        decimal_quantization=decimal_quantization, group_separator=group_separator, numbering_system=numbering_system)
+        number,
+        locale,
+        currency=currency,
+        currency_digits=currency_digits,
+        decimal_quantization=decimal_quantization,
+        group_separator=group_separator,
+        numbering_system=numbering_system,
+    )
 
 
 def _format_currency_long_name(
@@ -839,8 +874,14 @@ def _format_currency_long_name(
     pattern = parse_pattern(format)
 
     number_part = pattern.apply(
-        number, locale, currency=currency, currency_digits=currency_digits,
-        decimal_quantization=decimal_quantization, group_separator=group_separator, numbering_system=numbering_system)
+        number,
+        locale,
+        currency=currency,
+        currency_digits=currency_digits,
+        decimal_quantization=decimal_quantization,
+        group_separator=group_separator,
+        numbering_system=numbering_system,
+    )
 
     return unit_pattern.format(number_part, display_name)
 
@@ -877,7 +918,9 @@ def format_compact_currency(
     try:
         compact_format = locale.compact_currency_formats[format_type]
     except KeyError as error:
-        raise UnknownCurrencyFormatError(f"{format_type!r} is not a known compact currency format type") from error
+        raise UnknownCurrencyFormatError(
+            f"{format_type!r} is not a known compact currency format type",
+        ) from error
     number, format = _get_compact_format(number, compact_format, locale, fraction_digits)
     # Did not find a format, fall back.
     if format is None or "¤" not in str(format):
@@ -894,8 +937,14 @@ def format_compact_currency(
     if format is None:
         raise ValueError('No compact currency format found for the given number and locale.')
     pattern = parse_pattern(format)
-    return pattern.apply(number, locale, currency=currency, currency_digits=False, decimal_quantization=False,
-                         numbering_system=numbering_system)
+    return pattern.apply(
+        number,
+        locale,
+        currency=currency,
+        currency_digits=False,
+        decimal_quantization=False,
+        numbering_system=numbering_system,
+    )
 
 
 def format_percent(
@@ -954,7 +1003,10 @@ def format_percent(
         format = locale.percent_formats[None]
     pattern = parse_pattern(format)
     return pattern.apply(
-        number, locale, decimal_quantization=decimal_quantization, group_separator=group_separator,
+        number,
+        locale,
+        decimal_quantization=decimal_quantization,
+        group_separator=group_separator,
         numbering_system=numbering_system,
     )
 
@@ -1002,7 +1054,11 @@ def format_scientific(
         format = locale.scientific_formats[None]
     pattern = parse_pattern(format)
     return pattern.apply(
-        number, locale, decimal_quantization=decimal_quantization, numbering_system=numbering_system)
+        number,
+        locale,
+        decimal_quantization=decimal_quantization,
+        numbering_system=numbering_system,
+    )
 
 
 class NumberFormatError(ValueError):
@@ -1132,16 +1188,21 @@ def parse_decimal(
         string = SPACE_CHARS_RE.sub(group_symbol, string)
 
     try:
-        parsed = decimal.Decimal(string.replace(group_symbol, '')
-                                       .replace(decimal_symbol, '.'))
+        parsed = decimal.Decimal(string.replace(group_symbol, '').replace(decimal_symbol, '.'))
     except decimal.InvalidOperation as exc:
         raise NumberFormatError(f"{string!r} is not a valid decimal number") from exc
     if strict and group_symbol in string:
-        proper = format_decimal(parsed, locale=locale, decimal_quantization=False, numbering_system=numbering_system)
-        if string != proper and proper != _remove_trailing_zeros_after_decimal(string, decimal_symbol):
+        proper = format_decimal(
+            parsed,
+            locale=locale,
+            decimal_quantization=False,
+            numbering_system=numbering_system,
+        )
+        if string != proper and proper != _remove_trailing_zeros_after_decimal(string, decimal_symbol):  # fmt: skip
             try:
-                parsed_alt = decimal.Decimal(string.replace(decimal_symbol, '')
-                                                   .replace(group_symbol, '.'))
+                parsed_alt = decimal.Decimal(
+                    string.replace(decimal_symbol, '').replace(group_symbol, '.'),
+                )
             except decimal.InvalidOperation as exc:
                 raise NumberFormatError(
                     f"{string!r} is not a properly formatted decimal number. "
@@ -1230,7 +1291,7 @@ def parse_grouping(p: str) -> tuple[int, int]:
     if g1 == -1:
         return 1000, 1000
     g1 = width - g1 - 1
-    g2 = p[:-g1 - 1].rfind(',')
+    g2 = p[: -g1 - 1].rfind(',')
     if g2 == -1:
         return g1, g1
     g2 = width - g1 - g2 - 2
@@ -1296,14 +1357,20 @@ def parse_pattern(pattern: NumberPattern | str) -> NumberPattern:
         exp_plus = None
         exp_prec = None
     grouping = parse_grouping(integer)
-    return NumberPattern(pattern, (pos_prefix, neg_prefix),
-                         (pos_suffix, neg_suffix), grouping,
-                         int_prec, frac_prec,
-                         exp_prec, exp_plus, number)
+    return NumberPattern(
+        pattern,
+        (pos_prefix, neg_prefix),
+        (pos_suffix, neg_suffix),
+        grouping,
+        int_prec,
+        frac_prec,
+        exp_prec,
+        exp_plus,
+        number,
+    )
 
 
 class NumberPattern:
-
     def __init__(
         self,
         pattern: str,
@@ -1352,8 +1419,7 @@ class NumberPattern:
         *,
         numbering_system: Literal["default"] | str = "latn",
     ) -> tuple[decimal.Decimal, int, str]:
-        """ Returns normalized scientific notation components of a value.
-        """
+        """Returns normalized scientific notation components of a value."""
         # Normalize value to only have one lead digit.
         exp = value.adjusted()
         value = value * get_decimal_quantum(exp)
@@ -1430,7 +1496,11 @@ class NumberPattern:
 
         # Prepare scientific notation metadata.
         if self.exp_prec:
-            value, exp, exp_sign = self.scientific_notation_elements(value, locale, numbering_system=numbering_system)
+            value, exp, exp_sign = self.scientific_notation_elements(
+                value,
+                locale,
+                numbering_system=numbering_system,
+            )
 
         # Adjust the precision of the fractional part and force it to the
         # currency's if necessary.
@@ -1443,7 +1513,7 @@ class NumberPattern:
             )
             frac_prec = force_frac
         elif currency and currency_digits:
-            frac_prec = (get_currency_precision(currency), ) * 2
+            frac_prec = (get_currency_precision(currency),) * 2
         else:
             frac_prec = self.frac_prec
 
@@ -1463,13 +1533,11 @@ class NumberPattern:
                 get_exponential_symbol(locale, numbering_system=numbering_system),
                 exp_sign,  # type: ignore  # exp_sign is always defined here
                 self._format_int(str(exp), self.exp_prec[0], self.exp_prec[1], locale, numbering_system=numbering_system),  # type: ignore  # exp is always defined here
-            ])
+            ])  # fmt: skip
 
         # Is it a significant digits pattern?
         elif '@' in self.pattern:
-            text = self._format_significant(value,
-                                            self.int_prec[0],
-                                            self.int_prec[1])
+            text = self._format_significant(value, self.int_prec[0], self.int_prec[1])
             a, sep, b = text.partition(".")
             number = self._format_int(a, 0, 1000, locale, numbering_system=numbering_system)
             if sep:
@@ -1477,12 +1545,21 @@ class NumberPattern:
 
         # A normal number pattern.
         else:
-            number = self._quantize_value(value, locale, frac_prec, group_separator, numbering_system=numbering_system)
+            number = self._quantize_value(
+                value,
+                locale,
+                frac_prec,
+                group_separator,
+                numbering_system=numbering_system,
+            )
 
-        retval = ''.join([
-            self.prefix[is_negative],
-            number if self.number_pattern != '' else '',
-            self.suffix[is_negative]])
+        retval = ''.join(
+            (
+                self.prefix[is_negative],
+                number if self.number_pattern != '' else '',
+                self.suffix[is_negative],
+            ),
+        )
 
         if '¤' in retval and currency is not None:
             retval = retval.replace('¤¤¤', get_currency_name(currency, value, locale))
@@ -1572,8 +1649,19 @@ class NumberPattern:
         a, sep, b = f"{rounded:f}".partition(".")
         integer_part = a
         if group_separator:
-            integer_part = self._format_int(a, self.int_prec[0], self.int_prec[1], locale, numbering_system=numbering_system)
-        number = integer_part + self._format_frac(b or '0', locale=locale, force_frac=frac_prec, numbering_system=numbering_system)
+            integer_part = self._format_int(
+                a,
+                self.int_prec[0],
+                self.int_prec[1],
+                locale,
+                numbering_system=numbering_system,
+            )
+        number = integer_part + self._format_frac(
+            b or '0',
+            locale=locale,
+            force_frac=frac_prec,
+            numbering_system=numbering_system,
+        )
         return number
 
     def _format_frac(
@@ -1586,7 +1674,7 @@ class NumberPattern:
     ) -> str:
         min, max = force_frac or self.frac_prec
         if len(value) < min:
-            value += ('0' * (min - len(value)))
+            value += '0' * (min - len(value))
         if max == 0 or (min == 0 and int(value) == 0):
             return ''
         while len(value) > min and value[-1] == '0':
index 638dfefe311a69e912d57b6edf73e6194af66ee1..e368b1acf4ffaa77fb9c40310e969fbcb98b116f 100644 (file)
@@ -1,12 +1,13 @@
 """
-    babel.numbers
-    ~~~~~~~~~~~~~
+babel.numbers
+~~~~~~~~~~~~~
 
-    CLDR Plural support.  See UTS #35.
+CLDR Plural support.  See UTS #35.
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
+
 from __future__ import annotations
 
 import decimal
@@ -18,7 +19,9 @@ _plural_tags = ('zero', 'one', 'two', 'few', 'many', 'other')
 _fallback_tag = 'other'
 
 
-def extract_operands(source: float | decimal.Decimal) -> tuple[decimal.Decimal | int, int, int, int, int, int, Literal[0], Literal[0]]:
+def extract_operands(
+    source: float | decimal.Decimal,
+) -> tuple[decimal.Decimal | int, int, int, int, int, int, Literal[0], Literal[0]]:
     """Extract operands from a decimal, a float or an int, according to `CLDR rules`_.
 
     The result is an 8-tuple (n, i, v, w, f, t, c, e), where those symbols are as follows:
@@ -124,11 +127,14 @@ class PluralRule:
 
     def __repr__(self) -> str:
         rules = self.rules
-        args = ", ".join([f"{tag}: {rules[tag]}" for tag in _plural_tags if tag in rules])
+        args = ", ".join(f"{tag}: {rules[tag]}" for tag in _plural_tags if tag in rules)
         return f"<{type(self).__name__} {args!r}>"
 
     @classmethod
-    def parse(cls, rules: Mapping[str, str] | Iterable[tuple[str, str]] | PluralRule) -> PluralRule:
+    def parse(
+        cls,
+        rules: Mapping[str, str] | Iterable[tuple[str, str]] | PluralRule,
+    ) -> PluralRule:
         """Create a `PluralRule` instance for the given rules.  If the rules
         are a `PluralRule` object, that object is returned.
 
@@ -193,7 +199,9 @@ def to_javascript(rule: Mapping[str, str] | Iterable[tuple[str, str]] | PluralRu
     return ''.join(result)
 
 
-def to_python(rule: Mapping[str, str] | Iterable[tuple[str, str]] | PluralRule) -> Callable[[float | decimal.Decimal], str]:
+def to_python(
+    rule: Mapping[str, str] | Iterable[tuple[str, str]] | PluralRule,
+) -> Callable[[float | decimal.Decimal], str]:
     """Convert a list/dict of rules or a `PluralRule` object into a regular
     Python function.  This is useful in situations where you need a real
     function and don't are about the actual rule object:
@@ -256,7 +264,10 @@ def to_gettext(rule: Mapping[str, str] | Iterable[tuple[str, str]] | PluralRule)
     return ''.join(result)
 
 
-def in_range_list(num: float | decimal.Decimal, range_list: Iterable[Iterable[float | decimal.Decimal]]) -> bool:
+def in_range_list(
+    num: float | decimal.Decimal,
+    range_list: Iterable[Iterable[float | decimal.Decimal]],
+) -> bool:
     """Integer range list test.  This is the callback for the "in" operator
     of the UTS #35 pluralization rule language:
 
@@ -276,7 +287,10 @@ def in_range_list(num: float | decimal.Decimal, range_list: Iterable[Iterable[fl
     return num == int(num) and within_range_list(num, range_list)
 
 
-def within_range_list(num: float | decimal.Decimal, range_list: Iterable[Iterable[float | decimal.Decimal]]) -> bool:
+def within_range_list(
+    num: float | decimal.Decimal,
+    range_list: Iterable[Iterable[float | decimal.Decimal]],
+) -> bool:
     """Float range test.  This is the callback for the "within" operator
     of the UTS #35 pluralization rule language:
 
@@ -336,7 +350,7 @@ _VARS = {
 
 _RULES: list[tuple[str | None, re.Pattern[str]]] = [
     (None, re.compile(r'\s+', re.UNICODE)),
-    ('word', re.compile(fr'\b(and|or|is|(?:with)?in|not|mod|[{"".join(_VARS)}])\b')),
+    ('word', re.compile(rf'\b(and|or|is|(?:with)?in|not|mod|[{"".join(_VARS)}])\b')),
     ('value', re.compile(r'\d+')),
     ('symbol', re.compile(r'%|,|!=|=')),
     ('ellipsis', re.compile(r'\.{2,3}|\u2026', re.UNICODE)),  # U+2026: ELLIPSIS
@@ -366,8 +380,7 @@ def test_next_token(
     type_: str,
     value: str | None = None,
 ) -> list[tuple[str, str]] | bool:
-    return tokens and tokens[-1][0] == type_ and \
-        (value is None or tokens[-1][1] == value)
+    return tokens and tokens[-1][0] == type_ and (value is None or tokens[-1][1] == value)
 
 
 def skip_token(tokens: list[tuple[str, str]], type_: str, value: str | None = None):
@@ -376,7 +389,7 @@ def skip_token(tokens: list[tuple[str, str]], type_: str, value: str | None = No
 
 
 def value_node(value: int) -> tuple[Literal['value'], tuple[int]]:
-    return 'value', (value, )
+    return 'value', (value,)
 
 
 def ident_node(name: str) -> tuple[str, tuple[()]]:
@@ -566,7 +579,9 @@ class _PythonCompiler(_Compiler):
     compile_mod = _binary_compiler('MOD(%s, %s)')
 
     def compile_relation(self, method, expr, range_list):
-        ranges = ",".join([f"({self.compile(a)}, {self.compile(b)})" for (a, b) in range_list[1]])
+        ranges = ",".join(
+            f"({self.compile(a)}, {self.compile(b)})" for (a, b) in range_list[1]
+        )
         return f"{method.upper()}({self.compile(expr)}, [{ranges}])"
 
 
@@ -604,8 +619,7 @@ class _JavaScriptCompiler(_GettextCompiler):
     compile_t = compile_zero
 
     def compile_relation(self, method, expr, range_list):
-        code = _GettextCompiler.compile_relation(
-            self, method, expr, range_list)
+        code = _GettextCompiler.compile_relation(self, method, expr, range_list)
         if method == 'in':
             expr = self.compile(expr)
             code = f"(parseInt({expr}, 10) == {expr} && {code})"
index d181fbd1c3aa2819e22417ca1fca5a0fdabdcf8f..dfc7fb6e50d4df60fadb188f16c5f7649f60a9a8 100644 (file)
@@ -1,15 +1,16 @@
 """
-    babel.support
-    ~~~~~~~~~~~~~
+babel.support
+~~~~~~~~~~~~~
 
-    Several classes and functions that help with integrating and using Babel
-    in applications.
+Several classes and functions that help with integrating and using Babel
+in applications.
 
-    .. note: the code in this module is not used by Babel itself
+.. note: the code in this module is not used by Babel itself
 
-    :copyright: (c) 2013-2025 by the Babel Team.
-    :license: BSD, see LICENSE for more details.
+:copyright: (c) 2013-2025 by the Babel Team.
+:license: BSD, see LICENSE for more details.
 """
+
 from __future__ import annotations
 
 import gettext
@@ -114,7 +115,15 @@ class Format:
     def timedelta(
         self,
         delta: _datetime.timedelta | int,
-        granularity: Literal["year", "month", "week", "day", "hour", "minute", "second"] = "second",
+        granularity: Literal[
+            "year",
+            "month",
+            "week",
+            "day",
+            "hour",
+            "minute",
+            "second",
+        ] = "second",
         threshold: float = 0.85,
         format: Literal["narrow", "short", "medium", "long"] = "long",
         add_direction: bool = False,
@@ -126,10 +135,14 @@ class Format:
         >>> fmt.timedelta(timedelta(weeks=11))
         u'3 months'
         """
-        return format_timedelta(delta, granularity=granularity,
-                                threshold=threshold,
-                                format=format, add_direction=add_direction,
-                                locale=self.locale)
+        return format_timedelta(
+            delta,
+            granularity=granularity,
+            threshold=threshold,
+            format=format,
+            add_direction=add_direction,
+            locale=self.locale,
+        )
 
     def number(self, number: float | Decimal | str) -> str:
         """Return an integer number formatted for the locale.
@@ -138,7 +151,11 @@ class Format:
         >>> fmt.number(1099)
         u'1,099'
         """
-        return format_decimal(number, locale=self.locale, numbering_system=self.numbering_system)
+        return format_decimal(
+            number,
+            locale=self.locale,
+            numbering_system=self.numbering_system,
+        )
 
     def decimal(self, number: float | Decimal | str, format: str | None = None) -> str:
         """Return a decimal number formatted for the locale.
@@ -147,7 +164,12 @@ class Format:
         >>> fmt.decimal(1.2345)
         u'1.234'
         """
-        return format_decimal(number, format, locale=self.locale, numbering_system=self.numbering_system)
+        return format_decimal(
+            number,
+            format,
+            locale=self.locale,
+            numbering_system=self.numbering_system,
+        )
 
     def compact_decimal(
         self,
@@ -172,9 +194,13 @@ class Format:
         )
 
     def currency(self, number: float | Decimal | str, currency: str) -> str:
-        """Return a number in the given currency formatted for the locale.
-        """
-        return format_currency(number, currency, locale=self.locale, numbering_system=self.numbering_system)
+        """Return a number in the given currency formatted for the locale."""
+        return format_currency(
+            number,
+            currency,
+            locale=self.locale,
+            numbering_system=self.numbering_system,
+        )
 
     def compact_currency(
         self,
@@ -189,8 +215,14 @@ class Format:
         >>> Format('en_US').compact_currency(1234567, "USD", format_type='short', fraction_digits=2)
         '$1.23M'
         """
-        return format_compact_currency(number, currency, format_type=format_type, fraction_digits=fraction_digits,
-                                       locale=self.locale, numbering_system=self.numbering_system)
+        return format_compact_currency(
+            number,
+            currency,
+            format_type=format_type,
+            fraction_digits=fraction_digits,
+            locale=self.locale,
+            numbering_system=self.numbering_system,
+        )
 
     def percent(self, number: float | Decimal | str, format: str | None = None) -> str:
         """Return a number formatted as percentage for the locale.
@@ -199,12 +231,20 @@ class Format:
         >>> fmt.percent(0.34)
         u'34%'
         """
-        return format_percent(number, format, locale=self.locale, numbering_system=self.numbering_system)
+        return format_percent(
+            number,
+            format,
+            locale=self.locale,
+            numbering_system=self.numbering_system,
+        )
 
     def scientific(self, number: float | Decimal | str) -> str:
-        """Return a number formatted using scientific notation for the locale.
-        """
-        return format_scientific(number, locale=self.locale, numbering_system=self.numbering_system)
+        """Return a number formatted using scientific notation for the locale."""
+        return format_scientific(
+            number,
+            locale=self.locale,
+            numbering_system=self.numbering_system,
+        )
 
 
 class LazyProxy:
@@ -242,7 +282,15 @@ class LazyProxy:
     Hello, universe!
     Hello, world!
     """
-    __slots__ = ['_func', '_args', '_kwargs', '_value', '_is_cache_enabled', '_attribute_error']
+
+    __slots__ = [
+        '_func',
+        '_args',
+        '_kwargs',
+        '_value',
+        '_is_cache_enabled',
+        '_attribute_error',
+    ]
 
     if TYPE_CHECKING:
         _func: Callable[..., Any]
@@ -252,7 +300,13 @@ class LazyProxy:
         _value: Any
         _attribute_error: AttributeError | None
 
-    def __init__(self, func: Callable[..., Any], *args: Any, enable_cache: bool = True, **kwargs: Any) -> None:
+    def __init__(
+        self,
+        func: Callable[..., Any],
+        *args: Any,
+        enable_cache: bool = True,
+        **kwargs: Any,
+    ) -> None:
         # Avoid triggering our own __setattr__ implementation
         object.__setattr__(self, '_func', func)
         object.__setattr__(self, '_args', args)
@@ -362,6 +416,7 @@ class LazyProxy:
 
     def __deepcopy__(self, memo: Any) -> LazyProxy:
         from copy import deepcopy
+
         return LazyProxy(
             deepcopy(self._func, memo),
             enable_cache=deepcopy(self._is_cache_enabled, memo),
@@ -371,7 +426,6 @@ class LazyProxy:
 
 
 class NullTranslations(gettext.NullTranslations):
-
     if TYPE_CHECKING:
         _info: dict[str, str]
         _fallback: NullTranslations | None
@@ -406,6 +460,7 @@ class NullTranslations(gettext.NullTranslations):
         domain.
         """
         import warnings
+
         warnings.warn(
             'ldgettext() is deprecated, use dgettext() instead',
             DeprecationWarning,
@@ -418,6 +473,7 @@ class NullTranslations(gettext.NullTranslations):
         domain.
         """
         return self._domains.get(domain, self).ugettext(message)
+
     # backward compatibility with 0.9
     dugettext = udgettext
 
@@ -432,6 +488,7 @@ class NullTranslations(gettext.NullTranslations):
         domain.
         """
         import warnings
+
         warnings.warn(
             'ldngettext() is deprecated, use dngettext() instead',
             DeprecationWarning,
@@ -444,6 +501,7 @@ class NullTranslations(gettext.NullTranslations):
         domain.
         """
         return self._domains.get(domain, self).ungettext(singular, plural, num)
+
     # backward compatibility with 0.9
     dungettext = udngettext
 
@@ -479,6 +537,7 @@ class NullTranslations(gettext.NullTranslations):
         ``bind_textdomain_codeset()``.
         """
         import warnings
+
         warnings.warn(
             'lpgettext() is deprecated, use pgettext() instead',
             DeprecationWarning,
@@ -517,6 +576,7 @@ class NullTranslations(gettext.NullTranslations):
         ``bind_textdomain_codeset()``.
         """
         import warnings
+
         warnings.warn(
             'lnpgettext() is deprecated, use npgettext() instead',
             DeprecationWarning,
@@ -583,6 +643,7 @@ class NullTranslations(gettext.NullTranslations):
         `domain`.
         """
         return self._domains.get(domain, self).upgettext(context, message)
+
     # backward compatibility with 0.9
     dupgettext = udpgettext
 
@@ -608,13 +669,19 @@ class NullTranslations(gettext.NullTranslations):
     # backward compatibility with 0.9
     dunpgettext = udnpgettext
 
-    def ldnpgettext(self, domain: str, context: str, singular: str, plural: str, num: int) -> str | bytes:
+    def ldnpgettext(
+        self,
+        domain: str,
+        context: str,
+        singular: str,
+        plural: str,
+        num: int,
+    ) -> str | bytes:
         """Equivalent to ``dnpgettext()``, but the translation is returned in
         the preferred system encoding, if no other encoding was explicitly set
         with ``bind_textdomain_codeset()``.
         """
-        return self._domains.get(domain, self).lnpgettext(context, singular,
-                                                          plural, num)
+        return self._domains.get(domain, self).lnpgettext(context, singular, plural, num)
 
     ugettext = gettext.NullTranslations.gettext
     ungettext = gettext.NullTranslations.ngettext
@@ -625,7 +692,11 @@ class Translations(NullTranslations, gettext.GNUTranslations):
 
     DEFAULT_DOMAIN = 'messages'
 
-    def __init__(self, fp: gettext._TranslationsReader | None = None, domain: str | None = None):
+    def __init__(
+        self,
+        fp: gettext._TranslationsReader | None = None,
+        domain: str | None = None,
+    ):
         """Initialize the translations catalog.
 
         :param fp: the file-like object the translation should be read from
index 86ac2abc9ac52aa055cc363ead8def53d04a8958..e66e6b47b5a076b5ade1fdd31d6740e80925c7ad 100644 (file)
@@ -143,7 +143,12 @@ def format_unit(
         formatted_value = value
         plural_form = "one"
     else:
-        formatted_value = format_decimal(value, format, locale, numbering_system=numbering_system)
+        formatted_value = format_decimal(
+            value,
+            format,
+            locale,
+            numbering_system=numbering_system,
+        )
         plural_form = locale.plural_form(value)
 
     if plural_form in unit_patterns:
@@ -151,7 +156,11 @@ def format_unit(
 
     # Fall back to a somewhat bad representation.
     # nb: This is marked as no-cover, as the current CLDR seemingly has no way for this to happen.
-    fallback_name = get_unit_name(measurement_unit, length=length, locale=locale)  # pragma: no cover
+    fallback_name = get_unit_name(  # pragma: no cover
+        measurement_unit,
+        length=length,
+        locale=locale,
+    )
     return f"{formatted_value} {fallback_name or measurement_unit}"  # pragma: no cover
 
 
@@ -204,7 +213,10 @@ def _find_compound_unit(
 
     # Now we can try and rebuild a compound unit specifier, then qualify it:
 
-    return _find_unit_pattern(f"{bare_numerator_unit}-per-{bare_denominator_unit}", locale=locale)
+    return _find_unit_pattern(
+        f"{bare_numerator_unit}-per-{bare_denominator_unit}",
+        locale=locale,
+    )
 
 
 def format_compound_unit(
@@ -310,7 +322,12 @@ def format_compound_unit(
     elif denominator_unit:  # Denominator has unit
         if denominator_value == 1:  # support perUnitPatterns when the denominator is 1
             denominator_unit = _find_unit_pattern(denominator_unit, locale=locale)
-            per_pattern = locale._data["unit_patterns"].get(denominator_unit, {}).get(length, {}).get("per")
+            per_pattern = (
+                locale._data["unit_patterns"]
+                .get(denominator_unit, {})
+                .get(length, {})
+                .get("per")
+            )
             if per_pattern:
                 return per_pattern.format(formatted_numerator)
             # See TR-35's per-unit pattern algorithm, point 3.2.
@@ -335,6 +352,11 @@ def format_compound_unit(
         )
 
     # TODO: this doesn't support "compound_variations" (or "prefix"), and will fall back to the "x/y" representation
-    per_pattern = locale._data["compound_unit_patterns"].get("per", {}).get(length, {}).get("compound", "{0}/{1}")
+    per_pattern = (
+        locale._data["compound_unit_patterns"]
+        .get("per", {})
+        .get(length, {})
+        .get("compound", "{0}/{1}")
+    )
 
     return per_pattern.format(formatted_numerator, formatted_denominator)
index c995434f5d06d96e1c3303e73e13439dde706064..001fd646f852a379b816db1bf0ce7d1ee3f50b06 100644 (file)
@@ -70,12 +70,13 @@ def parse_encoding(fp: IO[bytes]) -> str | None:
         line1 = fp.readline()
         has_bom = line1.startswith(codecs.BOM_UTF8)
         if has_bom:
-            line1 = line1[len(codecs.BOM_UTF8):]
+            line1 = line1[len(codecs.BOM_UTF8) :]
 
         m = PYTHON_MAGIC_COMMENT_re.match(line1)
         if not m:
             try:
                 import ast
+
                 ast.parse(line1.decode('latin-1'))
             except (ImportError, SyntaxError, UnicodeEncodeError):
                 # Either it's a real syntax error, in which case the source is
@@ -101,8 +102,7 @@ def parse_encoding(fp: IO[bytes]) -> str | None:
         fp.seek(pos)
 
 
-PYTHON_FUTURE_IMPORT_re = re.compile(
-    r'from\s+__future__\s+import\s+\(*(.+)\)*')
+PYTHON_FUTURE_IMPORT_re = re.compile(r'from\s+__future__\s+import\s+\(*(.+)\)*')
 
 
 def parse_future_flags(fp: IO[bytes], encoding: str = 'latin-1') -> int:
@@ -110,6 +110,7 @@ def parse_future_flags(fp: IO[bytes], encoding: str = 'latin-1') -> int:
     code.
     """
     import __future__
+
     pos = fp.tell()
     fp.seek(0)
     flags = 0
@@ -204,8 +205,8 @@ def pathmatch(pattern: str, filename: str) -> bool:
 
 class TextWrapper(textwrap.TextWrapper):
     wordsep_re = re.compile(
-        r'(\s+|'                                  # any whitespace
-        r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))',   # em-dash
+        r'(\s+|'  # any whitespace
+        r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))',  # em-dash
     )
 
     # e.g. '\u2068foo bar.py\u2069:42'
@@ -229,7 +230,12 @@ class TextWrapper(textwrap.TextWrapper):
         return [c for c in chunks if c]
 
 
-def wraptext(text: str, width: int = 70, initial_indent: str = '', subsequent_indent: str = '') -> list[str]:
+def wraptext(
+    text: str,
+    width: int = 70,
+    initial_indent: str = '',
+    subsequent_indent: str = '',
+) -> list[str]:
     """Simple wrapper around the ``textwrap.wrap`` function in the standard
     library. This version does not wrap lines on hyphens in words. It also
     does not wrap PO file locations containing spaces.
@@ -265,6 +271,7 @@ class FixedOffsetTimezone(datetime.tzinfo):
 
     DEPRECATED: Use the standard library `datetime.timezone` instead.
     """
+
     # TODO (Babel 3.x): Remove this class
 
     def __init__(self, offset: float, name: str | None = None) -> None: