From: Aarni Koskela Date: Wed, 19 Mar 2025 10:48:41 +0000 (+0200) Subject: Apply manual formatting/fmt:skip to things that would be poorly autoformatted X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9b833bc5df8c145a70c1f4d46bdf6f42356dfeca;p=thirdparty%2Fbabel.git Apply manual formatting/fmt:skip to things that would be poorly autoformatted --- diff --git a/babel/core.py b/babel/core.py index 7386fb37..eb159c31 100644 --- a/babel/core.py +++ b/babel/core.py @@ -119,7 +119,7 @@ LOCALE_ALIASES = { 'mk': 'mk_MK', 'nl': 'nl_NL', 'nn': 'nn_NO', 'no': 'nb_NO', 'pl': 'pl_PL', 'pt': 'pt_PT', 'ro': 'ro_RO', 'ru': 'ru_RU', 'sk': 'sk_SK', 'sl': 'sl_SI', 'sv': 'sv_SE', 'th': 'th_TH', 'tr': 'tr_TR', 'uk': 'uk_UA', -} +} # fmt: skip class UnknownLocaleError(Exception): @@ -346,7 +346,8 @@ class Locale: f"variables for the API you tried to use." ) if isinstance(identifier, str): - raise ValueError(msg) # `parse_locale` would raise a ValueError, so let's do that here + # `parse_locale` would raise a ValueError, so let's do that here + raise ValueError(msg) raise TypeError(msg) if not isinstance(identifier, str): diff --git a/babel/dates.py b/babel/dates.py index 2ec10b5b..8c6e1fd5 100644 --- a/babel/dates.py +++ b/babel/dates.py @@ -41,7 +41,7 @@ if TYPE_CHECKING: _Instant: TypeAlias = datetime.date | datetime.time | float | None _PredefinedTimeFormat: TypeAlias = Literal['full', 'long', 'medium', 'short'] _Context: TypeAlias = Literal['format', 'stand-alone'] - _DtOrTzinfo: TypeAlias = datetime.datetime | datetime.tzinfo | str | int | datetime.time | None + _DtOrTzinfo: TypeAlias = datetime.datetime | datetime.tzinfo | str | int | datetime.time | None # fmt: skip # "If a given short metazone form is known NOT to be understood in a given # locale and the parent locale has this value such that it would normally @@ -1018,9 +1018,17 @@ def _format_fallback_interval( ) -> str: if skeleton in locale.datetime_skeletons: # Use the given skeleton format = lambda dt: format_skeleton(skeleton, dt, tzinfo, locale=locale) - elif all((isinstance(d, datetime.date) and not isinstance(d, datetime.datetime)) for d in (start, end)): # Both are just dates + elif all( + # Both are just dates + (isinstance(d, datetime.date) and not isinstance(d, datetime.datetime)) + for d in (start, end) + ): format = lambda dt: format_date(dt, locale=locale) - elif all((isinstance(d, datetime.time) and not isinstance(d, datetime.date)) for d in (start, end)): # Both are times + elif all( + # Both are times + (isinstance(d, datetime.time) and not isinstance(d, datetime.date)) + for d in (start, end) + ): format = lambda dt: format_time(dt, tzinfo=tzinfo, locale=locale) else: format = lambda dt: format_datetime(dt, tzinfo=tzinfo, locale=locale) @@ -1266,8 +1274,11 @@ def parse_date( use_predefined_format = format in ('full', 'long', 'medium', 'short') # we try ISO-8601 format first, meaning similar to formats # extended YYYY-MM-DD or basic YYYYMMDD - iso_alike = re.match(r'^(\d{4})-?([01]\d)-?([0-3]\d)$', - string, flags=re.ASCII) # allow only ASCII digits + iso_alike = re.match( + r'^(\d{4})-?([01]\d)-?([0-3]\d)$', + string, + flags=re.ASCII, # allow only ASCII digits + ) if iso_alike and use_predefined_format: try: return datetime.date(*map(int, iso_alike.groups())) @@ -1637,35 +1648,24 @@ class DateTimeFormat: return get_timezone_gmt(value, width, locale=self.locale) # TODO: To add support for O:1 elif char == 'v': - return get_timezone_name(value.tzinfo, width, - locale=self.locale) + return get_timezone_name(value.tzinfo, width, locale=self.locale) elif char == 'V': if num == 1: - return get_timezone_name(value.tzinfo, width, - uncommon=True, locale=self.locale) + return get_timezone_name(value.tzinfo, width, locale=self.locale) elif num == 2: return get_timezone_name(value.tzinfo, locale=self.locale, return_zone=True) elif num == 3: - return get_timezone_location(value.tzinfo, locale=self.locale, return_city=True) + return get_timezone_location(value.tzinfo, locale=self.locale, return_city=True) # fmt: skip return get_timezone_location(value.tzinfo, locale=self.locale) - # Included additional elif condition to add support for 'Xx' in timezone format - elif char == 'X': - if num == 1: - return get_timezone_gmt(value, width='iso8601_short', locale=self.locale, - return_z=True) - elif num in (2, 4): - return get_timezone_gmt(value, width='short', locale=self.locale, - return_z=True) - elif num in (3, 5): - return get_timezone_gmt(value, width='iso8601', locale=self.locale, - return_z=True) - elif char == 'x': + elif char in 'Xx': + return_z = char == 'X' if num == 1: - return get_timezone_gmt(value, width='iso8601_short', locale=self.locale) + width = 'iso8601_short' elif num in (2, 4): - return get_timezone_gmt(value, width='short', locale=self.locale) + width = 'short' elif num in (3, 5): - return get_timezone_gmt(value, width='iso8601', locale=self.locale) + width = 'iso8601' + return get_timezone_gmt(value, width=width, locale=self.locale, return_z=return_z) # fmt: skip def format(self, value: SupportsInt, length: int) -> str: return '%0*d' % (length, value) @@ -1739,7 +1739,7 @@ PATTERN_CHARS: dict[str, list[int] | None] = { 's': [1, 2], 'S': None, 'A': None, # second 'z': [1, 2, 3, 4], 'Z': [1, 2, 3, 4, 5], 'O': [1, 4], 'v': [1, 4], # zone 'V': [1, 2, 3, 4], 'x': [1, 2, 3, 4, 5], 'X': [1, 2, 3, 4, 5], # zone -} +} # fmt: skip #: The pattern characters declared in the Date Field Symbol Table #: (https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table) @@ -1967,11 +1967,11 @@ def match_skeleton(skeleton: str, options: Iterable[str], allow_different_fields if 'b' in skeleton and not any('b' in option for option in options): skeleton = skeleton.replace('b', '') - get_input_field_width = dict(t[1] for t in tokenize_pattern(skeleton) if t[0] == "field").get + get_input_field_width = dict(t[1] for t in tokenize_pattern(skeleton) if t[0] == "field").get # fmt: skip best_skeleton = None best_distance = None for option in options: - get_opt_field_width = dict(t[1] for t in tokenize_pattern(option) if t[0] == "field").get + get_opt_field_width = dict(t[1] for t in tokenize_pattern(option) if t[0] == "field").get # fmt: skip distance = 0 for field in PATTERN_CHARS: input_width = get_input_field_width(field, 0) @@ -1982,13 +1982,18 @@ def match_skeleton(skeleton: str, options: Iterable[str], allow_different_fields if not allow_different_fields: # This one is not okay option = None break - distance += 0x1000 # Magic weight constant for "entirely different fields" - elif field == 'M' and ((input_width > 2 and opt_width <= 2) or (input_width <= 2 and opt_width > 2)): - distance += 0x100 # Magic weight for "text turns into a number" + # Magic weight constant for "entirely different fields" + distance += 0x1000 + elif field == 'M' and ( + (input_width > 2 and opt_width <= 2) or (input_width <= 2 and opt_width > 2) + ): + # Magic weight constant for "text turns into a number" + distance += 0x100 else: distance += abs(input_width - opt_width) - if not option: # We lost the option along the way (probably due to "allow_different_fields") + if not option: + # We lost the option along the way (probably due to "allow_different_fields") continue if not best_skeleton or distance < best_distance: diff --git a/babel/localtime/_fallback.py b/babel/localtime/_fallback.py index fab6867c..73def22e 100644 --- a/babel/localtime/_fallback.py +++ b/babel/localtime/_fallback.py @@ -38,7 +38,7 @@ class _FallbackLocalTimezone(datetime.tzinfo): def _isdst(self, dt: datetime.datetime) -> bool: tt = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, - dt.weekday(), 0, -1) + dt.weekday(), 0, -1) # fmt: skip stamp = time.mktime(tt) tt = time.localtime(stamp) return tt.tm_isdst > 0 diff --git a/babel/messages/catalog.py b/babel/messages/catalog.py index e1d61e09..b43edf54 100644 --- a/babel/messages/catalog.py +++ b/babel/messages/catalog.py @@ -516,7 +516,7 @@ class Catalog: ('POT-Creation-Date', format_datetime(self.creation_date, 'yyyy-MM-dd HH:mmZ', locale='en')), ('PO-Revision-Date', revision_date), ('Last-Translator', self.last_translator), - ] + ] # fmt: skip if self.locale_identifier: headers.append(('Language', str(self.locale_identifier))) headers.append(('Language-Team', language_team)) @@ -739,13 +739,13 @@ class Catalog: current.id = message.id current.string = message.string current.locations = list(dict.fromkeys([*current.locations, *message.locations])) - current.auto_comments = list(dict.fromkeys([*current.auto_comments, *message.auto_comments])) - current.user_comments = list(dict.fromkeys([*current.user_comments, *message.user_comments])) + current.auto_comments = list(dict.fromkeys([*current.auto_comments, *message.auto_comments])) # fmt:skip + current.user_comments = list(dict.fromkeys([*current.user_comments, *message.user_comments])) # fmt:skip current.flags |= message.flags elif id == '': # special treatment for the header message self.mime_headers = message_from_string(message.string).items() - self.header_comment = "\n".join([f"# {c}".rstrip() for c in message.user_comments]) + self.header_comment = "\n".join(f"# {c}".rstrip() for c in message.user_comments) self.fuzzy = message.fuzzy else: if isinstance(id, (list, tuple)): diff --git a/babel/messages/checkers.py b/babel/messages/checkers.py index 072a48a9..e56bce9a 100644 --- a/babel/messages/checkers.py +++ b/babel/messages/checkers.py @@ -27,8 +27,7 @@ def num_plurals(catalog: Catalog | None, message: Message) -> None: """Verify the number of plurals in the translation.""" if not message.pluralizable: if not isinstance(message.string, str): - raise TranslationError("Found plural forms for non-pluralizable " - "message") + raise TranslationError("Found plural forms for non-pluralizable message") return # skip further tests if no catalog is provided. @@ -39,8 +38,9 @@ def num_plurals(catalog: Catalog | None, message: Message) -> None: if not isinstance(msgstrs, (list, tuple)): msgstrs = (msgstrs,) if len(msgstrs) != catalog.num_plurals: - raise TranslationError("Wrong number of plural forms (expected %d)" % - catalog.num_plurals) + raise TranslationError( + f"Wrong number of plural forms (expected {catalog.num_plurals})", + ) def python_format(catalog: Catalog | None, message: Message) -> None: @@ -137,13 +137,13 @@ def _validate_format(format: str, alternative: str) -> None: # same number of format chars and those must be compatible if a_positional: if len(a) != len(b): - raise TranslationError('positional format placeholders are ' - 'unbalanced') + raise TranslationError('positional format placeholders are unbalanced') for idx, ((_, first), (_, second)) in enumerate(zip(a, b)): if not _compatible(first, second): - raise TranslationError('incompatible format for placeholder ' - '%d: %r and %r are not compatible' % - (idx + 1, first, second)) + raise TranslationError( + f'incompatible format for placeholder {idx + 1:d}: ' + f'{first!r} and {second!r} are not compatible', + ) # otherwise the second string must not have names the first one # doesn't have and the types of those included must be compatible diff --git a/babel/messages/extract.py b/babel/messages/extract.py index 2c0ccb32..d3ae9da9 100644 --- a/babel/messages/extract.py +++ b/babel/messages/extract.py @@ -62,7 +62,7 @@ if TYPE_CHECKING: _Keyword: TypeAlias = dict[int | None, _SimpleKeyword] | _SimpleKeyword # 5-tuple of (filename, lineno, messages, comments, context) - _FileExtractionResult: TypeAlias = tuple[str, int, str | tuple[str, ...], list[str], str | None] + _FileExtractionResult: TypeAlias = tuple[str, int, str | tuple[str, ...], list[str], str | None] # fmt: skip # 4-tuple of (lineno, message, comments, context) _ExtractionResult: TypeAlias = tuple[int, str | tuple[str, ...], list[str], str | None] @@ -72,7 +72,7 @@ if TYPE_CHECKING: _CallableExtractionMethod: TypeAlias = Callable[ [_FileObj | IO[bytes], Mapping[str, _Keyword], Collection[str], Mapping[str, Any]], Iterable[_ExtractionResult], - ] + ] # fmt: skip _ExtractionMethod: TypeAlias = _CallableExtractionMethod | str @@ -699,9 +699,12 @@ def extract_javascript( lineno=lineno, ): if ( # Turn keyword`foo` expressions into keyword("foo") calls: - funcname and # have a keyword... - (last_token and last_token.type == 'name') and # we've seen nothing after the keyword... - token.type == 'template_string' # this is a template string + # have a keyword... + funcname + # and we've seen nothing after the keyword... + and (last_token and last_token.type == 'name') + # and this is a template string + and token.type == 'template_string' ): message_lineno = token.lineno messages = [unquote_string(token.value)] diff --git a/babel/messages/frontend.py b/babel/messages/frontend.py index be1a82e0..e5d2a113 100644 --- a/babel/messages/frontend.py +++ b/babel/messages/frontend.py @@ -174,7 +174,7 @@ class CompileCatalog(CommandMixin): 'also include fuzzy translations'), ('statistics', None, 'print statistics about translations'), - ] + ] # fmt: skip boolean_options = ['use-fuzzy', 'statistics'] def initialize_options(self): @@ -338,7 +338,7 @@ class ExtractMessages(CommandMixin): 'header comment for the catalog'), ('last-translator=', None, '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', @@ -426,10 +426,9 @@ class ExtractMessages(CommandMixin): if isinstance(self.input_paths, str): self.input_paths = re.split(r',\s*', self.input_paths) elif self.distribution is not None: - self.input_paths = dict.fromkeys([ - k.split('.', 1)[0] - for k in (self.distribution.packages or ()) - ]).keys() + self.input_paths = list( + {k.split('.', 1)[0] for k in (self.distribution.packages or ())}, + ) else: self.input_paths = [] @@ -497,18 +496,25 @@ class ExtractMessages(CommandMixin): if os.path.isfile(path): current_dir = os.getcwd() extracted = check_and_call_extract_file( - path, method_map, options_map, - callback, self.keywords, self.add_comments, - self.strip_comments, current_dir, + path, + method_map, + options_map, + callback=callback, + comment_tags=self.add_comments, + dirpath=current_dir, + keywords=self.keywords, + strip_comment_tags=self.strip_comments, ) else: extracted = extract_from_dir( - path, method_map, options_map, - keywords=self.keywords, - comment_tags=self.add_comments, + path, + method_map, + options_map, callback=callback, - strip_comment_tags=self.strip_comments, + comment_tags=self.add_comments, directory_filter=self.directory_filter, + keywords=self.keywords, + strip_comment_tags=self.strip_comments, ) for filename, lineno, message, comments, context in extracted: if os.path.isfile(path): @@ -520,12 +526,16 @@ class ExtractMessages(CommandMixin): auto_comments=comments, context=context) self.log.info('writing PO template file to %s', self.output_file) - write_po(outfile, catalog, width=self.width, - no_location=self.no_location, - omit_header=self.omit_header, - sort_output=self.sort_output, - sort_by_file=self.sort_by_file, - include_lineno=self.include_lineno) + write_po( + outfile, + catalog, + include_lineno=self.include_lineno, + no_location=self.no_location, + omit_header=self.omit_header, + sort_by_file=self.sort_by_file, + sort_output=self.sort_output, + width=self.width, + ) def _get_mappings(self): mappings = [] @@ -587,7 +597,7 @@ class InitCatalog(CommandMixin): ('no-wrap', None, 'do not break long message lines, longer than the output line width, ' 'into several lines'), - ] + ] # fmt: skip boolean_options = ['no-wrap'] def initialize_options(self): @@ -680,7 +690,7 @@ class UpdateCatalog(CommandMixin): 'would be updated'), ('ignore-pot-creation-date=', None, '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', @@ -789,7 +799,8 @@ class UpdateCatalog(CommandMixin): catalog = read_po(infile, locale=locale, domain=domain) catalog.update( - template, self.no_fuzzy_matching, + template, + no_fuzzy_matching=self.no_fuzzy_matching, update_header_comment=self.update_header_comment, update_creation_date=not self.ignore_pot_creation_date, ) @@ -799,10 +810,14 @@ class UpdateCatalog(CommandMixin): os.path.basename(filename)) try: with open(tmpname, 'wb') as tmpfile: - write_po(tmpfile, catalog, - omit_header=self.omit_header, - ignore_obsolete=self.ignore_obsolete, - include_previous=self.previous, width=self.width) + write_po( + tmpfile, + catalog, + ignore_obsolete=self.ignore_obsolete, + include_previous=self.previous, + omit_header=self.omit_header, + width=self.width, + ) except Exception: os.remove(tmpname) raise @@ -880,15 +895,28 @@ class CommandLineInterface: version=self.version) self.parser.disable_interspersed_args() self.parser.print_help = self._help - self.parser.add_option('--list-locales', dest='list_locales', - action='store_true', - help="print all known locales and exit") - self.parser.add_option('-v', '--verbose', action='store_const', - dest='loglevel', const=logging.DEBUG, - help='print as much as possible') - self.parser.add_option('-q', '--quiet', action='store_const', - dest='loglevel', const=logging.ERROR, - help='print as little as possible') + self.parser.add_option( + "--list-locales", + dest="list_locales", + action="store_true", + help="print all known locales and exit", + ) + self.parser.add_option( + "-v", + "--verbose", + action="store_const", + dest="loglevel", + const=logging.DEBUG, + help="print as much as possible", + ) + self.parser.add_option( + "-q", + "--quiet", + action="store_const", + dest="loglevel", + const=logging.ERROR, + help="print as little as possible", + ) self.parser.set_defaults(list_locales=False, loglevel=logging.INFO) options, args = self.parser.parse_args(argv[1:]) @@ -903,8 +931,10 @@ class CommandLineInterface: return 0 if not args: - self.parser.error('no valid command or option passed. ' - 'Try the -h/--help option for more information.') + self.parser.error( + "no valid command or option passed. " + "Try the -h/--help option for more information.", + ) cmdname = args[0] if cmdname not in self.commands: diff --git a/babel/messages/jslexer.py b/babel/messages/jslexer.py index 7a2ba6a4..4cd79d5d 100644 --- a/babel/messages/jslexer.py +++ b/babel/messages/jslexer.py @@ -19,7 +19,7 @@ operators: list[str] = sorted([ '+=', '-=', '*=', '%=', '<<', '>>', '>>>', '<<=', '>>=', '>>>=', '&', '&=', '|', '|=', '&&', '||', '^', '^=', '(', ')', '[', ']', '{', '}', '!', '--', '++', '~', ',', ';', '.', ':', -], key=len, reverse=True) +], key=len, reverse=True) # fmt: skip escapes: dict[str, str] = {'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t'} @@ -59,7 +59,7 @@ _rules: list[tuple[str | None, re.Pattern[str]]] = [ '(?:[^'\\]*(?:\\.[^'\\]*)*)' | "(?:[^"\\]*(?:\\.[^"\\]*)*)" )''', re.VERBOSE | re.DOTALL)), -] +] # fmt: skip def get_rules(jsx: bool, dotted: bool, template_string: bool) -> list[tuple[str | None, re.Pattern[str]]]: diff --git a/babel/messages/mofile.py b/babel/messages/mofile.py index 3c9fefc4..20c67188 100644 --- a/babel/messages/mofile.py +++ b/babel/messages/mofile.py @@ -164,24 +164,19 @@ def write_mo(fileobj: SupportsWrite[bytes], catalog: Catalog, use_fuzzy: bool = # For each string, we need size and file offset. Each string is NUL # terminated; the NUL does not count into the size. if message.pluralizable: - msgid = b'\x00'.join([ - msgid.encode(catalog.charset) for msgid in message.id - ]) + msgid = b'\x00'.join(msgid.encode(catalog.charset) for msgid in message.id) msgstrs = [] for idx, string in enumerate(message.string): if not string: msgstrs.append(message.id[min(int(idx), 1)]) else: msgstrs.append(string) - msgstr = b'\x00'.join([ - msgstr.encode(catalog.charset) for msgstr in msgstrs - ]) + msgstr = b'\x00'.join(msgstr.encode(catalog.charset) for msgstr in msgstrs) else: msgid = message.id.encode(catalog.charset) msgstr = message.string.encode(catalog.charset) if message.context: - msgid = b'\x04'.join([message.context.encode(catalog.charset), - msgid]) + msgid = b'\x04'.join([message.context.encode(catalog.charset), msgid]) offsets.append((len(ids), len(msgid), len(strs), len(msgstr))) ids += msgid + b'\x00' strs += msgstr + b'\x00' @@ -200,11 +195,15 @@ def write_mo(fileobj: SupportsWrite[bytes], catalog: Catalog, use_fuzzy: bool = voffsets += [l2, o2 + valuestart] offsets = koffsets + voffsets - fileobj.write(struct.pack('Iiiiiii', - LE_MAGIC, # magic - 0, # version - len(messages), # number of entries - 7 * 4, # start of key index - 7 * 4 + len(messages) * 8, # start of value index - 0, 0, # size and offset of hash table - ) + array.array.tobytes(array.array("i", offsets)) + ids + strs) + header = struct.pack( + 'Iiiiiii', + LE_MAGIC, # magic + 0, # version + len(messages), # number of entries + 7 * 4, # start of key index + 7 * 4 + len(messages) * 8, # start of value index + 0, + 0, # size and offset of hash table + ) + + fileobj.write(header + array.array.tobytes(array.array("i", offsets)) + ids + strs) diff --git a/babel/messages/plurals.py b/babel/messages/plurals.py index da336a7b..5eae86dd 100644 --- a/babel/messages/plurals.py +++ b/babel/messages/plurals.py @@ -197,7 +197,7 @@ PLURALS: dict[str, tuple[int, str]] = { 'xh': (2, '(n != 1)'), # Chinese - From Pootle's PO's (modified) 'zh': (1, '0'), -} +} # fmt: skip DEFAULT_PLURAL: tuple[int, str] = (2, '(n != 1)') diff --git a/babel/messages/pofile.py b/babel/messages/pofile.py index 8220637b..e29d8840 100644 --- a/babel/messages/pofile.py +++ b/babel/messages/pofile.py @@ -265,10 +265,10 @@ class PoFileParser: else: self._invalid_pofile(line, lineno, "Got line starting with \" but not in msgid, msgstr or msgctxt") return - s.append(line.strip()) # For performance reasons, `NormalizedString` doesn't strip internally + # For performance reasons, `NormalizedString` doesn't strip internally + s.append(line.strip()) def _process_comment(self, line) -> None: - self._finish_current_message() prefix = line[:2] @@ -407,11 +407,13 @@ def read_po( return catalog -WORD_SEP = re.compile('(' - r'\s+|' # any whitespace - r'[^\s\w]*\w+[a-zA-Z]-(?=\w+[a-zA-Z])|' # hyphenated words - r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w)' # em-dash - ')') +WORD_SEP = re.compile( + '(' + r'\s+|' # any whitespace + r'[^\s\w]*\w+[a-zA-Z]-(?=\w+[a-zA-Z])|' # hyphenated words + r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w)' # em-dash + ')', +) def escape(string: str) -> str: @@ -425,11 +427,10 @@ def escape(string: str) -> str: :param string: the string to escape """ - return '"%s"' % string.replace('\\', '\\\\') \ - .replace('\t', '\\t') \ - .replace('\r', '\\r') \ - .replace('\n', '\\n') \ - .replace('\"', '\\"') + return '"%s"' % string.replace('\\', '\\\\').replace('\t', '\\t').replace( + '\r', + '\\r', + ).replace('\n', '\\n').replace('"', '\\"') def normalize(string: str, prefix: str = '', width: int = 76) -> str: @@ -657,8 +658,10 @@ def generate_po( # if no sorting possible, leave unsorted. # (see issue #606) try: - locations = sorted(message.locations, - key=lambda x: (x[0], isinstance(x[1], int) and x[1] or -1)) + locations = sorted( + message.locations, + key=lambda x: (x[0], isinstance(x[1], int) and x[1] or -1), + ) except TypeError: # e.g. "TypeError: unorderable types: NoneType() < int()" locations = message.locations @@ -696,7 +699,10 @@ def generate_po( yield '\n' -def _sort_messages(messages: Iterable[Message], sort_by: Literal["message", "location"] | None) -> list[Message]: +def _sort_messages( + messages: Iterable[Message], + sort_by: Literal["message", "location"] | None, +) -> list[Message]: """ Sort the given message iterable by the given criteria. diff --git a/babel/numbers.py b/babel/numbers.py index 2737a707..3ea97bcc 100644 --- a/babel/numbers.py +++ b/babel/numbers.py @@ -432,7 +432,7 @@ def get_exponential_symbol( :raise `UnsupportedNumberingSystemError`: if the numbering system is not supported by the locale. """ locale = Locale.parse(locale or LC_NUMERIC) - return _get_number_symbols(locale, numbering_system=numbering_system).get('exponential', 'E') + return _get_number_symbols(locale, numbering_system=numbering_system).get('exponential', 'E') # fmt: skip def get_group_symbol( @@ -1054,9 +1054,12 @@ def parse_number( group_symbol = get_group_symbol(locale, numbering_system=numbering_system) if ( - group_symbol in SPACE_CHARS and # if the grouping symbol is a kind of space, - group_symbol not in string and # and the string to be parsed does not contain it, - SPACE_CHARS_RE.search(string) # but it does contain any other kind of space instead, + # if the grouping symbol is a kind of space, + group_symbol in SPACE_CHARS + # and the string to be parsed does not contain it, + and group_symbol not in string + # but it does contain any other kind of space instead, + and SPACE_CHARS_RE.search(string) ): # ... it's reasonable to assume it is taking the place of the grouping symbol. string = SPACE_CHARS_RE.sub(group_symbol, string) @@ -1120,9 +1123,10 @@ def parse_decimal( decimal_symbol = get_decimal_symbol(locale, numbering_system=numbering_system) if not strict and ( - group_symbol in SPACE_CHARS and # if the grouping symbol is a kind of space, - group_symbol not in string and # and the string to be parsed does not contain it, - SPACE_CHARS_RE.search(string) # but it does contain any other kind of space instead, + group_symbol in SPACE_CHARS # if the grouping symbol is a kind of space, + and group_symbol not in string # and the string to be parsed does not contain it, + # but it does contain any other kind of space instead, + and SPACE_CHARS_RE.search(string) ): # ... it's reasonable to assume it is taking the place of the grouping symbol. string = SPACE_CHARS_RE.sub(group_symbol, string) diff --git a/babel/plural.py b/babel/plural.py index 63a081e8..638dfefe 100644 --- a/babel/plural.py +++ b/babel/plural.py @@ -463,8 +463,8 @@ class _Parser: def relation(self): left = self.expr() if skip_token(self.tokens, 'word', 'is'): - return skip_token(self.tokens, 'word', 'not') and 'isnot' or 'is', \ - (left, self.value()) + op = 'isnot' if skip_token(self.tokens, 'word', 'not') else 'is' + return op, (left, self.value()) negated = skip_token(self.tokens, 'word', 'not') method = 'in' if skip_token(self.tokens, 'word', 'within'): diff --git a/babel/support.py b/babel/support.py index b600bfe2..d181fbd1 100644 --- a/babel/support.py +++ b/babel/support.py @@ -593,19 +593,18 @@ class NullTranslations(gettext.NullTranslations): """ return self._domains.get(domain, self).lpgettext(context, message) - def dnpgettext(self, domain: str, context: str, singular: str, plural: str, num: int) -> str: + def dnpgettext(self, domain: str, context: str, singular: str, plural: str, num: int) -> str: # fmt: skip """Like ``npgettext``, but look the message up in the specified `domain`. """ - return self._domains.get(domain, self).npgettext(context, singular, - plural, num) + return self._domains.get(domain, self).npgettext(context, singular, plural, num) - def udnpgettext(self, domain: str, context: str, singular: str, plural: str, num: int) -> str: + def udnpgettext(self, domain: str, context: str, singular: str, plural: str, num: int) -> str: # fmt: skip """Like ``unpgettext``, but look the message up in the specified `domain`. """ - return self._domains.get(domain, self).unpgettext(context, singular, - plural, num) + return self._domains.get(domain, self).unpgettext(context, singular, plural, num) + # backward compatibility with 0.9 dunpgettext = udnpgettext diff --git a/babel/util.py b/babel/util.py index c91c12b0..c995434f 100644 --- a/babel/util.py +++ b/babel/util.py @@ -1,12 +1,13 @@ """ - babel.util - ~~~~~~~~~~ +babel.util +~~~~~~~~~~ - Various utility classes and functions. +Various utility classes and functions. - :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 codecs @@ -47,7 +48,9 @@ def distinct(iterable: Iterable[_T]) -> Generator[_T, None, None]: # Regexp to match python magic encoding line PYTHON_MAGIC_COMMENT_re = re.compile( - br'[ \t\f]* \# .* coding[=:][ \t]*([-\w.]+)', re.VERBOSE) + rb'[ \t\f]* \# .* coding[=:][ \t]*([-\w.]+)', + flags=re.VERBOSE, +) def parse_encoding(fp: IO[bytes]) -> str | None: @@ -244,10 +247,12 @@ def wraptext(text: str, width: int = 70, initial_indent: str = '', subsequent_in DeprecationWarning, stacklevel=2, ) - wrapper = TextWrapper(width=width, initial_indent=initial_indent, - subsequent_indent=subsequent_indent, - break_long_words=False) - return wrapper.wrap(text) + return TextWrapper( + width=width, + initial_indent=initial_indent, + subsequent_indent=subsequent_indent, + break_long_words=False, + ).wrap(text) # TODO (Babel 3.x): Remove this re-export