Skip to content

Commit 3dfc3a3

Browse files
authored
Add type annotations for babel.messages subpackage (#9455)
1 parent 6a6a677 commit 3dfc3a3

File tree

7 files changed

+260
-162
lines changed

7 files changed

+260
-162
lines changed
Lines changed: 98 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,126 @@
1-
from typing import Any
1+
import datetime
2+
from collections import OrderedDict
3+
from collections.abc import Generator, Iterable, Iterator
4+
from typing_extensions import TypeAlias
5+
6+
from babel.core import Locale
7+
8+
__all__ = ["Message", "Catalog", "TranslationError"]
9+
10+
_MessageID: TypeAlias = str | tuple[str, ...] | list[str]
211

312
class Message:
4-
id: Any
5-
string: Any
6-
locations: Any
7-
flags: Any
8-
auto_comments: Any
9-
user_comments: Any
10-
previous_id: Any
11-
lineno: Any
12-
context: Any
13+
id: _MessageID
14+
string: _MessageID
15+
locations: list[tuple[str, int]]
16+
flags: set[str]
17+
auto_comments: list[str]
18+
user_comments: list[str]
19+
previous_id: list[str]
20+
lineno: int | None
21+
context: str | None
1322
def __init__(
1423
self,
15-
id,
24+
id: str,
1625
string: str = ...,
17-
locations=...,
18-
flags=...,
19-
auto_comments=...,
20-
user_comments=...,
21-
previous_id=...,
22-
lineno: Any | None = ...,
23-
context: Any | None = ...,
26+
locations: Iterable[tuple[str, int]] = ...,
27+
flags: Iterable[str] = ...,
28+
auto_comments: Iterable[str] = ...,
29+
user_comments: Iterable[str] = ...,
30+
previous_id: _MessageID = ...,
31+
lineno: int | None = ...,
32+
context: str | None = ...,
2433
) -> None: ...
25-
def __cmp__(self, other): ...
26-
def __gt__(self, other): ...
27-
def __lt__(self, other): ...
28-
def __ge__(self, other): ...
29-
def __le__(self, other): ...
30-
def __eq__(self, other): ...
31-
def __ne__(self, other): ...
34+
def __cmp__(self, other: Message) -> int: ...
35+
def __gt__(self, other: Message) -> bool: ...
36+
def __lt__(self, other: Message) -> bool: ...
37+
def __ge__(self, other: Message) -> bool: ...
38+
def __le__(self, other: Message) -> bool: ...
39+
def __eq__(self, other: object) -> bool: ...
40+
def __ne__(self, other: object) -> bool: ...
3241
def is_identical(self, other: Message) -> bool: ...
33-
def clone(self): ...
34-
def check(self, catalog: Any | None = ...): ...
42+
def clone(self) -> Message: ...
43+
def check(self, catalog: Catalog | None = ...) -> list[TranslationError]: ...
3544
@property
36-
def fuzzy(self): ...
45+
def fuzzy(self) -> bool: ...
3746
@property
38-
def pluralizable(self): ...
47+
def pluralizable(self) -> bool: ...
3948
@property
40-
def python_format(self): ...
49+
def python_format(self) -> bool: ...
4150

4251
class TranslationError(Exception): ...
4352

4453
class Catalog:
45-
domain: Any
46-
locale: Any
47-
project: Any
48-
version: Any
49-
copyright_holder: Any
50-
msgid_bugs_address: Any
51-
last_translator: Any
52-
language_team: Any
53-
charset: Any
54-
creation_date: Any
55-
revision_date: Any
56-
fuzzy: Any
57-
obsolete: Any
54+
domain: str | None
55+
project: str
56+
version: str
57+
copyright_holder: str
58+
msgid_bugs_address: str
59+
last_translator: str
60+
language_team: str
61+
charset: str
62+
creation_date: datetime.datetime | str
63+
revision_date: datetime.datetime | datetime.time | float | str
64+
fuzzy: bool
65+
obsolete: OrderedDict[str | tuple[str, str], Message]
5866
def __init__(
5967
self,
60-
locale: Any | None = ...,
61-
domain: Any | None = ...,
62-
header_comment=...,
63-
project: Any | None = ...,
64-
version: Any | None = ...,
65-
copyright_holder: Any | None = ...,
66-
msgid_bugs_address: Any | None = ...,
67-
creation_date: Any | None = ...,
68-
revision_date: Any | None = ...,
69-
last_translator: Any | None = ...,
70-
language_team: Any | None = ...,
71-
charset: Any | None = ...,
68+
locale: str | Locale | None = ...,
69+
domain: str | None = ...,
70+
header_comment: str | None = ...,
71+
project: str | None = ...,
72+
version: str | None = ...,
73+
copyright_holder: str | None = ...,
74+
msgid_bugs_address: str | None = ...,
75+
creation_date: datetime.datetime | str | None = ...,
76+
revision_date: datetime.datetime | datetime.time | float | str | None = ...,
77+
last_translator: str | None = ...,
78+
language_team: str | None = ...,
79+
charset: str | None = ...,
7280
fuzzy: bool = ...,
7381
) -> None: ...
7482
@property
75-
def locale_identifier(self): ...
76-
header_comment: Any
77-
mime_headers: Any
83+
def locale(self) -> Locale | None: ...
84+
@locale.setter # Assigning a string looks up the right Locale object.
85+
def locale(self, value: Locale | str | None) -> None: ...
86+
@property
87+
def locale_identifier(self) -> str | None: ...
88+
@property
89+
def header_comment(self) -> str: ...
90+
@header_comment.setter
91+
def header_comment(self, value: str) -> None: ...
92+
@property
93+
def mime_headers(self) -> list[tuple[str, str]]: ...
94+
@mime_headers.setter
95+
def mime_headers(self, value: Iterable[tuple[str | bytes, str | bytes]]) -> None: ...
7896
@property
79-
def num_plurals(self): ...
97+
def num_plurals(self) -> int: ...
8098
@property
81-
def plural_expr(self): ...
99+
def plural_expr(self) -> str: ...
82100
@property
83-
def plural_forms(self): ...
84-
def __contains__(self, id): ...
101+
def plural_forms(self) -> str: ...
102+
def __contains__(self, id: _MessageID) -> bool: ...
85103
def __len__(self) -> int: ...
86-
def __iter__(self): ...
87-
def __delitem__(self, id) -> None: ...
88-
def __getitem__(self, id): ...
89-
def __setitem__(self, id, message) -> None: ...
104+
def __iter__(self) -> Iterator[Message]: ...
105+
def __delitem__(self, id: _MessageID) -> None: ...
106+
def __getitem__(self, id: _MessageID) -> Message: ...
107+
def __setitem__(self, id: _MessageID, message: Message) -> None: ...
90108
def add(
91109
self,
92-
id,
93-
string: Any | None = ...,
94-
locations=...,
95-
flags=...,
96-
auto_comments=...,
97-
user_comments=...,
98-
previous_id=...,
99-
lineno: Any | None = ...,
100-
context: Any | None = ...,
101-
): ...
102-
def check(self) -> None: ...
103-
def get(self, id, context: Any | None = ...): ...
104-
def delete(self, id, context: Any | None = ...) -> None: ...
110+
id: _MessageID,
111+
string: _MessageID | None = ...,
112+
locations: Iterable[tuple[str, int]] = ...,
113+
flags: Iterable[str] = ...,
114+
auto_comments: Iterable[str] = ...,
115+
user_comments: Iterable[str] = ...,
116+
previous_id: _MessageID = ...,
117+
lineno: int | None = ...,
118+
context: str | None = ...,
119+
) -> Message: ...
120+
def check(self) -> Generator[tuple[Message, list[TranslationError]], None, None]: ...
121+
def get(self, id: _MessageID, context: str | None = ...): ...
122+
def delete(self, id, context: str | None = ...) -> None: ...
105123
def update(
106-
self, template, no_fuzzy_matching: bool = ..., update_header_comment: bool = ..., keep_user_comments: bool = ...
124+
self, template: Catalog, no_fuzzy_matching: bool = ..., update_header_comment: bool = ..., keep_user_comments: bool = ...
107125
) -> None: ...
108126
def is_identical(self, other: Catalog) -> bool: ...
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
from typing import Any
1+
from collections.abc import Callable
22

3-
def num_plurals(catalog, message) -> None: ...
4-
def python_format(catalog, message) -> None: ...
3+
from babel.messages.catalog import Catalog, Message
54

6-
checkers: Any
5+
def num_plurals(catalog: Catalog | None, message: Message) -> None: ...
6+
def python_format(catalog: Catalog | None, message: Message) -> None: ...
7+
8+
checkers: list[Callable[[Catalog | None, Message], object]]
Lines changed: 75 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,85 @@
1-
from collections.abc import Callable
2-
from typing import Any
1+
from _typeshed import SupportsItems, SupportsRead, SupportsReadline
2+
from collections.abc import Callable, Collection, Generator, Iterable, Mapping
3+
from os import PathLike
4+
from typing import Any, AnyStr, Protocol, overload
5+
from typing_extensions import TypeAlias, TypedDict
6+
7+
_Keyword: TypeAlias = tuple[int | tuple[int, int] | tuple[int, str], ...] | None
38

49
GROUP_NAME: str
5-
DEFAULT_KEYWORDS: Any
6-
DEFAULT_MAPPING: Any
10+
DEFAULT_KEYWORDS: dict[str, _Keyword]
11+
DEFAULT_MAPPING: list[tuple[str, str]]
712
empty_msgid_warning: str
813

14+
@overload
15+
def extract_from_dir(
16+
dirname: AnyStr | PathLike[AnyStr],
17+
method_map: Iterable[tuple[str, str]] = ...,
18+
options_map: SupportsItems[str, dict[str, Any]] | None = ...,
19+
keywords: Mapping[str, _Keyword] = ...,
20+
comment_tags: Collection[str] = ...,
21+
callback: Callable[[AnyStr, str, dict[str, Any]], object] | None = ...,
22+
strip_comment_tags: bool = ...,
23+
directory_filter: Callable[[str], bool] | None = ...,
24+
) -> Generator[tuple[AnyStr, int, str | tuple[str, ...], list[str], str | None], None, None]: ...
25+
@overload
926
def extract_from_dir(
10-
dirname: Any | None = ...,
11-
method_map=...,
12-
options_map: Any | None = ...,
13-
keywords=...,
14-
comment_tags=...,
15-
callback: Any | None = ...,
27+
dirname: None = ..., # No dirname causes os.getcwd() to be used, producing str.
28+
method_map: Iterable[tuple[str, str]] = ...,
29+
options_map: SupportsItems[str, dict[str, Any]] | None = ...,
30+
keywords: Mapping[str, _Keyword] = ...,
31+
comment_tags: Collection[str] = ...,
32+
callback: Callable[[str, str, dict[str, Any]], object] | None = ...,
1633
strip_comment_tags: bool = ...,
1734
directory_filter: Callable[[str], bool] | None = ...,
18-
) -> None: ...
35+
) -> Generator[tuple[str, int, str | tuple[str, ...], list[str], str | None], None, None]: ...
1936
def check_and_call_extract_file(
20-
filepath, method_map, options_map, callback, keywords, comment_tags, strip_comment_tags, dirpath: Any | None = ...
21-
) -> None: ...
37+
filepath: AnyStr | PathLike[AnyStr],
38+
method_map: Iterable[tuple[str, str]],
39+
options_map: SupportsItems[str, dict[str, Any]],
40+
callback: Callable[[AnyStr, str, dict[str, Any]], object] | None,
41+
keywords: Mapping[str, _Keyword],
42+
comment_tags: Collection[str],
43+
strip_comment_tags,
44+
dirpath: Any | None = ...,
45+
) -> Generator[tuple[AnyStr, int, str | tuple[str, ...], list[str], str | None], None, None]: ...
2246
def extract_from_file(
23-
method, filename, keywords=..., comment_tags=..., options: Any | None = ..., strip_comment_tags: bool = ...
24-
): ...
47+
method,
48+
filename: AnyStr | PathLike[AnyStr],
49+
keywords: Mapping[str, _Keyword] = ...,
50+
comment_tags: Collection[str] = ...,
51+
options: dict[str, Any] | None = ...,
52+
strip_comment_tags: bool = ...,
53+
) -> list[tuple[AnyStr, int, str | tuple[str, ...], list[str], str | None]]: ...
54+
55+
class _FileObj(SupportsRead[bytes], SupportsReadline[bytes], Protocol):
56+
def seek(self, __offset: int, __whence: int = ...) -> int: ...
57+
def tell(self) -> int: ...
58+
2559
def extract(
26-
method, fileobj, keywords=..., comment_tags=..., options: Any | None = ..., strip_comment_tags: bool = ...
27-
) -> None: ...
28-
def extract_nothing(fileobj, keywords, comment_tags, options): ...
29-
def extract_python(fileobj, keywords, comment_tags, options): ...
30-
def extract_javascript(fileobj, keywords, comment_tags, options) -> None: ...
60+
method,
61+
fileobj: _FileObj,
62+
keywords: Mapping[str, _Keyword] = ...,
63+
comment_tags: Collection[str] = ...,
64+
options: dict[str, Any] | None = ...,
65+
strip_comment_tags: bool = ...,
66+
) -> Iterable[tuple[int, str | tuple[str, ...], list[str], str | None]]: ...
67+
def extract_nothing(
68+
fileobj: _FileObj, keywords: Mapping[str, _Keyword], comment_tags: Collection[str], options: dict[str, Any]
69+
) -> Iterable[tuple[int, str | tuple[str, ...], list[str], str | None]]: ...
70+
71+
class _PyOptions(TypedDict, total=False):
72+
encoding: str
73+
74+
def extract_python(
75+
fileobj: _FileObj, keywords: Mapping[str, _Keyword], comment_tags: Collection[str], options: _PyOptions
76+
) -> Iterable[tuple[int, str | tuple[str, ...], list[str], str | None]]: ...
77+
78+
class _JSOptions(TypedDict, total=False):
79+
encoding: str
80+
jsx: bool
81+
template_string: bool
82+
83+
def extract_javascript(
84+
fileobj: _FileObj, keywords: Mapping[str, _Keyword], comment_tags: Collection[str], options: _JSOptions
85+
) -> Iterable[tuple[int, str | tuple[str, ...], list[str], str | None]]: ...
Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
1-
from typing import Any, NamedTuple
1+
from collections.abc import Generator, Sequence
2+
from re import Pattern
3+
from typing import NamedTuple
24

3-
operators: Any
4-
escapes: Any
5-
name_re: Any
6-
dotted_name_re: Any
7-
division_re: Any
8-
regex_re: Any
9-
line_re: Any
10-
line_join_re: Any
11-
uni_escape_re: Any
5+
operators: Sequence[str]
6+
escapes: dict[str, str]
7+
name_re: Pattern[str]
8+
dotted_name_re: Pattern[str]
9+
division_re: Pattern[str]
10+
regex_re: Pattern[str]
11+
line_re: Pattern[str]
12+
line_join_re: Pattern[str]
13+
uni_escape_re: Pattern[str]
1214

1315
class Token(NamedTuple):
14-
type: Any
15-
value: Any
16-
lineno: Any
16+
type: str
17+
value: str
18+
lineno: int
1719

18-
def get_rules(jsx, dotted, template_string): ...
19-
def indicates_division(token): ...
20-
def unquote_string(string): ...
21-
def tokenize(source, jsx: bool = ..., dotted: bool = ..., template_string: bool = ...) -> None: ...
20+
# Documented as private
21+
def get_rules(jsx: bool, dotted: bool, template_string: bool) -> list[tuple[str | None, Pattern[str]]]: ... # undocumented
22+
def indicates_division(token: Token) -> bool: ...
23+
def unquote_string(string: str) -> str: ...
24+
def tokenize(source: str, jsx: bool = ..., dotted: bool = ..., template_string: bool = ...) -> Generator[Token, None, None]: ...

stubs/babel/babel/messages/mofile.pyi

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
from _typeshed import SupportsRead, SupportsWrite
2+
3+
from babel.messages.catalog import Catalog
4+
15
LE_MAGIC: int
26
BE_MAGIC: int
37

4-
def read_mo(fileobj): ...
5-
def write_mo(fileobj, catalog, use_fuzzy: bool = ...) -> None: ...
8+
def read_mo(fileobj: SupportsRead[bytes]) -> Catalog: ...
9+
def write_mo(fileobj: SupportsWrite[bytes], catalog: Catalog, use_fuzzy: bool = ...) -> None: ...
Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
from typing import Any
2-
3-
LC_CTYPE: Any
4-
PLURALS: Any
5-
DEFAULT_PLURAL: Any
1+
LC_CTYPE: str
2+
PLURALS: dict[str, tuple[int, str]]
3+
DEFAULT_PLURAL: tuple[int, str]
64

75
class _PluralTuple(tuple[int, str]):
86
@property
@@ -12,4 +10,4 @@ class _PluralTuple(tuple[int, str]):
1210
@property
1311
def plural_forms(self) -> str: ...
1412

15-
def get_plural(locale=...): ...
13+
def get_plural(locale: str = ...) -> _PluralTuple: ...

0 commit comments

Comments
 (0)