Skip to content

Commit 1871bcf

Browse files
authored
Merge branch 'master' into master
2 parents 01f3793 + 69c5db8 commit 1871bcf

File tree

19 files changed

+526
-421
lines changed

19 files changed

+526
-421
lines changed

babel/core.py

Lines changed: 62 additions & 62 deletions
Large diffs are not rendered by default.

babel/dates.py

Lines changed: 85 additions & 85 deletions
Large diffs are not rendered by default.

babel/lists.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ def format_list(
4444
Format the items in `lst` as a list.
4545
4646
>>> format_list(['apples', 'oranges', 'pears'], locale='en')
47-
u'apples, oranges, and pears'
47+
'apples, oranges, and pears'
4848
>>> format_list(['apples', 'oranges', 'pears'], locale='zh')
49-
u'apples\u3001oranges\u548cpears'
49+
'apples、oranges和pears'
5050
>>> format_list(['omena', 'peruna', 'aplari'], style='or', locale='fi')
51-
u'omena, peruna tai aplari'
51+
'omena, peruna tai aplari'
5252
5353
Not all styles are necessarily available in all locales.
5454
The function will attempt to fall back to replacement styles according to the rules

babel/localedata.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def load(name: os.PathLike[str] | str, merge_inherited: bool = True) -> dict[str
125125
126126
>>> d = load('en_US')
127127
>>> d['languages']['sv']
128-
u'Swedish'
128+
'Swedish'
129129
130130
Note that the results are cached, and subsequent requests for the same
131131
locale return the same dictionary:

babel/messages/catalog.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -722,19 +722,19 @@ def __setitem__(self, id: _MessageID, message: Message) -> None:
722722
"""Add or update the message with the specified ID.
723723
724724
>>> catalog = Catalog()
725-
>>> catalog[u'foo'] = Message(u'foo')
726-
>>> catalog[u'foo']
727-
<Message u'foo' (flags: [])>
725+
>>> catalog['foo'] = Message('foo')
726+
>>> catalog['foo']
727+
<Message 'foo' (flags: [])>
728728
729729
If a message with that ID is already in the catalog, it is updated
730730
to include the locations and flags of the new message.
731731
732732
>>> catalog = Catalog()
733-
>>> catalog[u'foo'] = Message(u'foo', locations=[('main.py', 1)])
734-
>>> catalog[u'foo'].locations
733+
>>> catalog['foo'] = Message('foo', locations=[('main.py', 1)])
734+
>>> catalog['foo'].locations
735735
[('main.py', 1)]
736-
>>> catalog[u'foo'] = Message(u'foo', locations=[('utils.py', 5)])
737-
>>> catalog[u'foo'].locations
736+
>>> catalog['foo'] = Message('foo', locations=[('utils.py', 5)])
737+
>>> catalog['foo'].locations
738738
[('main.py', 1), ('utils.py', 5)]
739739
740740
:param id: the message ID
@@ -793,10 +793,10 @@ def add(
793793
"""Add or update the message with the specified ID.
794794
795795
>>> catalog = Catalog()
796-
>>> catalog.add(u'foo')
796+
>>> catalog.add('foo')
797797
<Message ...>
798-
>>> catalog[u'foo']
799-
<Message u'foo' (flags: [])>
798+
>>> catalog['foo']
799+
<Message 'foo' (flags: [])>
800800
801801
This method simply constructs a `Message` object with the given
802802
arguments and invokes `__setitem__` with that object.
@@ -872,11 +872,11 @@ def update(
872872
>>> template.add(('salad', 'salads'), locations=[('util.py', 42)])
873873
<Message ...>
874874
>>> catalog = Catalog(locale='de_DE')
875-
>>> catalog.add('blue', u'blau', locations=[('main.py', 98)])
875+
>>> catalog.add('blue', 'blau', locations=[('main.py', 98)])
876876
<Message ...>
877-
>>> catalog.add('head', u'Kopf', locations=[('util.py', 33)])
877+
>>> catalog.add('head', 'Kopf', locations=[('util.py', 33)])
878878
<Message ...>
879-
>>> catalog.add(('salad', 'salads'), (u'Salat', u'Salate'),
879+
>>> catalog.add(('salad', 'salads'), ('Salat', 'Salate'),
880880
... locations=[('util.py', 38)])
881881
<Message ...>
882882
@@ -891,13 +891,13 @@ def update(
891891
892892
>>> msg2 = catalog['blue']
893893
>>> msg2.string
894-
u'blau'
894+
'blau'
895895
>>> msg2.locations
896896
[('main.py', 100)]
897897
898898
>>> msg3 = catalog['salad']
899899
>>> msg3.string
900-
(u'Salat', u'Salate')
900+
('Salat', 'Salate')
901901
>>> msg3.locations
902902
[('util.py', 42)]
903903

babel/messages/extract.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ def extract(
403403
>>> from io import BytesIO
404404
>>> for message in extract('python', BytesIO(source)):
405405
... print(message)
406-
(3, u'Hello, world!', [], None)
406+
(3, 'Hello, world!', [], None)
407407
408408
:param method: an extraction method (a callable), or
409409
a string specifying the extraction method (.e.g. "python");
@@ -508,7 +508,7 @@ def extract_python(
508508
:rtype: ``iterator``
509509
"""
510510
funcname = lineno = message_lineno = None
511-
call_stack = -1
511+
call_stack = [] # line numbers of calls
512512
buf = []
513513
messages = []
514514
translator_comments = []
@@ -526,7 +526,7 @@ def extract_python(
526526
current_fstring_start = None
527527

528528
for tok, value, (lineno, _), _, _ in tokens:
529-
if call_stack == -1 and tok == NAME and value in ('def', 'class'):
529+
if not call_stack and tok == NAME and value in ('def', 'class'):
530530
in_def = True
531531
elif tok == OP and value == '(':
532532
if in_def:
@@ -535,12 +535,12 @@ def extract_python(
535535
in_def = False
536536
continue
537537
if funcname:
538-
call_stack += 1
538+
call_stack.append(lineno)
539539
elif in_def and tok == OP and value == ':':
540540
# End of a class definition without parens
541541
in_def = False
542542
continue
543-
elif call_stack == -1 and tok == COMMENT:
543+
elif not call_stack and tok == COMMENT:
544544
# Strip the comment token from the line
545545
value = value[1:].strip()
546546
if in_translator_comments and \
@@ -555,7 +555,7 @@ def extract_python(
555555
in_translator_comments = True
556556
translator_comments.append((lineno, value))
557557
break
558-
elif funcname and call_stack == 0:
558+
elif funcname and len(call_stack) == 1:
559559
nested = (tok == NAME and value in keywords)
560560
if (tok == OP and value == ')') or nested:
561561
if buf:
@@ -565,17 +565,20 @@ def extract_python(
565565
messages.append(None)
566566

567567
messages = tuple(messages) if len(messages) > 1 else messages[0]
568-
# Comments don't apply unless they immediately
569-
# precede the message
570-
if translator_comments and \
571-
translator_comments[-1][0] < message_lineno - 1:
572-
translator_comments = []
568+
569+
if translator_comments:
570+
last_comment_lineno = translator_comments[-1][0]
571+
if last_comment_lineno < min(message_lineno, call_stack[-1]) - 1:
572+
# Comments don't apply unless they immediately
573+
# precede the message, or the line where the parenthesis token
574+
# to start this message's translation call is.
575+
translator_comments.clear()
573576

574577
yield (message_lineno, funcname, messages,
575578
[comment[1] for comment in translator_comments])
576579

577580
funcname = lineno = message_lineno = None
578-
call_stack = -1
581+
call_stack.clear()
579582
messages = []
580583
translator_comments = []
581584
in_translator_comments = False
@@ -619,9 +622,9 @@ def extract_python(
619622

620623
elif tok != NL and not message_lineno:
621624
message_lineno = lineno
622-
elif call_stack > 0 and tok == OP and value == ')':
623-
call_stack -= 1
624-
elif funcname and call_stack == -1:
625+
elif len(call_stack) > 1 and tok == OP and value == ')':
626+
call_stack.pop()
627+
elif funcname and not call_stack:
625628
funcname = None
626629
elif tok == NAME and value in keywords:
627630
funcname = value

babel/messages/frontend.py

Lines changed: 38 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import logging
1616
import optparse
1717
import os
18+
import pathlib
1819
import re
1920
import shutil
2021
import sys
@@ -202,44 +203,34 @@ def run(self):
202203
self.log.error('%d errors encountered.', n_errors)
203204
return (1 if n_errors else 0)
204205

205-
def _run_domain(self, domain):
206-
po_files = []
207-
mo_files = []
208-
206+
def _get_po_mo_triples(self, domain: str):
209207
if not self.input_file:
208+
dir_path = pathlib.Path(self.directory)
210209
if self.locale:
211-
po_files.append((self.locale,
212-
os.path.join(self.directory, self.locale,
213-
'LC_MESSAGES',
214-
f"{domain}.po")))
215-
mo_files.append(os.path.join(self.directory, self.locale,
216-
'LC_MESSAGES',
217-
f"{domain}.mo"))
210+
lc_messages_path = dir_path / self.locale / "LC_MESSAGES"
211+
po_file = lc_messages_path / f"{domain}.po"
212+
yield self.locale, po_file, po_file.with_suffix(".mo")
218213
else:
219-
for locale in os.listdir(self.directory):
220-
po_file = os.path.join(self.directory, locale,
221-
'LC_MESSAGES', f"{domain}.po")
222-
if os.path.exists(po_file):
223-
po_files.append((locale, po_file))
224-
mo_files.append(os.path.join(self.directory, locale,
225-
'LC_MESSAGES',
226-
f"{domain}.mo"))
214+
for locale_path in dir_path.iterdir():
215+
po_file = locale_path / "LC_MESSAGES"/ f"{domain}.po"
216+
if po_file.exists():
217+
yield locale_path.name, po_file, po_file.with_suffix(".mo")
227218
else:
228-
po_files.append((self.locale, self.input_file))
219+
po_file = pathlib.Path(self.input_file)
229220
if self.output_file:
230-
mo_files.append(self.output_file)
221+
mo_file = pathlib.Path(self.output_file)
231222
else:
232-
mo_files.append(os.path.join(self.directory, self.locale,
233-
'LC_MESSAGES',
234-
f"{domain}.mo"))
223+
mo_file = pathlib.Path(self.directory) / self.locale / "LC_MESSAGES" / f"{domain}.mo"
224+
yield self.locale, po_file, mo_file
235225

236-
if not po_files:
237-
raise OptionError('no message catalogs found')
226+
def _run_domain(self, domain):
227+
locale_po_mo_triples = list(self._get_po_mo_triples(domain))
228+
if not locale_po_mo_triples:
229+
raise OptionError(f'no message catalogs found for domain {domain!r}')
238230

239231
catalogs_and_errors = {}
240232

241-
for idx, (locale, po_file) in enumerate(po_files):
242-
mo_file = mo_files[idx]
233+
for locale, po_file, mo_file in locale_po_mo_triples:
243234
with open(po_file, 'rb') as infile:
244235
catalog = read_po(infile, locale)
245236

@@ -623,8 +614,8 @@ def finalize_options(self):
623614
if not self.output_file and not self.output_dir:
624615
raise OptionError('you must specify the output directory')
625616
if not self.output_file:
626-
self.output_file = os.path.join(self.output_dir, self.locale,
627-
'LC_MESSAGES', f"{self.domain}.po")
617+
lc_messages_path = pathlib.Path(self.output_dir) / self.locale / "LC_MESSAGES"
618+
self.output_file = str(lc_messages_path / f"{self.domain}.po")
628619

629620
if not os.path.exists(os.path.dirname(self.output_file)):
630621
os.makedirs(os.path.dirname(self.output_file))
@@ -745,36 +736,35 @@ def finalize_options(self):
745736
if self.no_fuzzy_matching and self.previous:
746737
self.previous = False
747738

748-
def run(self):
749-
check_status = {}
750-
po_files = []
739+
def _get_locale_po_file_tuples(self):
751740
if not self.output_file:
741+
output_path = pathlib.Path(self.output_dir)
752742
if self.locale:
753-
po_files.append((self.locale,
754-
os.path.join(self.output_dir, self.locale,
755-
'LC_MESSAGES',
756-
f"{self.domain}.po")))
743+
lc_messages_path = output_path / self.locale / "LC_MESSAGES"
744+
yield self.locale, str(lc_messages_path / f"{self.domain}.po")
757745
else:
758-
for locale in os.listdir(self.output_dir):
759-
po_file = os.path.join(self.output_dir, locale,
760-
'LC_MESSAGES',
761-
f"{self.domain}.po")
762-
if os.path.exists(po_file):
763-
po_files.append((locale, po_file))
746+
for locale_path in output_path.iterdir():
747+
po_file = locale_path / "LC_MESSAGES" / f"{self.domain}.po"
748+
if po_file.exists():
749+
yield locale_path.stem, po_file
764750
else:
765-
po_files.append((self.locale, self.output_file))
766-
767-
if not po_files:
768-
raise OptionError('no message catalogs found')
751+
yield self.locale, self.output_file
769752

753+
def run(self):
770754
domain = self.domain
771755
if not domain:
772756
domain = os.path.splitext(os.path.basename(self.input_file))[0]
773757

758+
check_status = {}
759+
locale_po_file_tuples = list(self._get_locale_po_file_tuples())
760+
761+
if not locale_po_file_tuples:
762+
raise OptionError(f'no message catalogs found for domain {domain!r}')
763+
774764
with open(self.input_file, 'rb') as infile:
775765
template = read_po(infile)
776766

777-
for locale, filename in po_files:
767+
for locale, filename in locale_po_file_tuples:
778768
if self.init_missing and not os.path.exists(filename):
779769
if self.check:
780770
check_status[filename] = False

babel/messages/mofile.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def write_mo(fileobj: SupportsWrite[bytes], catalog: Catalog, use_fuzzy: bool =
116116
>>> catalog = Catalog(locale='en_US')
117117
>>> catalog.add('foo', 'Voh')
118118
<Message ...>
119-
>>> catalog.add((u'bar', u'baz'), (u'Bahr', u'Batz'))
119+
>>> catalog.add(('bar', 'baz'), ('Bahr', 'Batz'))
120120
<Message ...>
121121
>>> catalog.add('fuz', 'Futz', flags=['fuzzy'])
122122
<Message ...>
@@ -133,19 +133,19 @@ def write_mo(fileobj: SupportsWrite[bytes], catalog: Catalog, use_fuzzy: bool =
133133
... translations.ugettext = translations.gettext
134134
... translations.ungettext = translations.ngettext
135135
>>> translations.ugettext('foo')
136-
u'Voh'
136+
'Voh'
137137
>>> translations.ungettext('bar', 'baz', 1)
138-
u'Bahr'
138+
'Bahr'
139139
>>> translations.ungettext('bar', 'baz', 2)
140-
u'Batz'
140+
'Batz'
141141
>>> translations.ugettext('fuz')
142-
u'fuz'
142+
'fuz'
143143
>>> translations.ugettext('Fizz')
144-
u'Fizz'
144+
'Fizz'
145145
>>> translations.ugettext('Fuzz')
146-
u'Fuzz'
146+
'Fuzz'
147147
>>> translations.ugettext('Fuzzes')
148-
u'Fuzzes'
148+
'Fuzzes'
149149
150150
:param fileobj: the file-like object to write to
151151
:param catalog: the `Catalog` instance

babel/messages/pofile.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -385,12 +385,12 @@ def read_po(
385385
... print((message.id, message.string))
386386
... print(' ', (message.locations, sorted(list(message.flags))))
387387
... print(' ', (message.user_comments, message.auto_comments))
388-
(u'foo %(name)s', u'quux %(name)s')
389-
([(u'main.py', 1)], [u'fuzzy', u'python-format'])
388+
('foo %(name)s', 'quux %(name)s')
389+
([('main.py', 1)], ['fuzzy', 'python-format'])
390390
([], [])
391-
((u'bar', u'baz'), (u'bar', u'baaz'))
392-
([(u'main.py', 3)], [])
393-
([u'A user comment'], [u'An auto comment'])
391+
(('bar', 'baz'), ('bar', 'baaz'))
392+
([('main.py', 3)], [])
393+
(['A user comment'], ['An auto comment'])
394394
395395
.. versionadded:: 1.0
396396
Added support for explicit charset argument.
@@ -529,10 +529,10 @@ def write_po(
529529
message catalog to the provided file-like object.
530530
531531
>>> catalog = Catalog()
532-
>>> catalog.add(u'foo %(name)s', locations=[('main.py', 1)],
532+
>>> catalog.add('foo %(name)s', locations=[('main.py', 1)],
533533
... flags=('fuzzy',))
534534
<Message...>
535-
>>> catalog.add((u'bar', u'baz'), locations=[('main.py', 3)])
535+
>>> catalog.add(('bar', 'baz'), locations=[('main.py', 3)])
536536
<Message...>
537537
>>> from io import BytesIO
538538
>>> buf = BytesIO()

0 commit comments

Comments
 (0)