Skip to content

Commit 9f3310f

Browse files
authored
Improve dateparser (#13796)
1 parent 09416d0 commit 9f3310f

20 files changed

+166
-129
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
from typing import Any
2-
31
from dateparser.calendars import CalendarBase
2+
from dateparser.calendars.hijri_parser import hijri_parser
43

54
class HijriCalendar(CalendarBase):
6-
parser: Any
5+
parser: type[hijri_parser]
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
from _typeshed import Incomplete
2-
from typing import Any
1+
from typing import Any, SupportsIndex
32

43
from dateparser.calendars import non_gregorian_parser
54

65
class hijri:
76
@classmethod
8-
def to_gregorian(cls, year: Incomplete | None = ..., month: Incomplete | None = ..., day: Incomplete | None = ...): ...
7+
def to_gregorian(cls, year: int | None = None, month: int | None = None, day: int | None = None) -> tuple[int, int, int]: ...
98
@classmethod
10-
def from_gregorian(cls, year: Incomplete | None = ..., month: Incomplete | None = ..., day: Incomplete | None = ...): ...
9+
def from_gregorian(
10+
cls, year: SupportsIndex | None = None, month: SupportsIndex | None = None, day: SupportsIndex | None = None
11+
) -> tuple[int, int, int]: ...
1112
@classmethod
12-
def month_length(cls, year, month): ...
13+
def month_length(cls, year: int, month: int) -> int: ...
1314

1415
class HijriDate:
1516
year: Any
@@ -19,9 +20,9 @@ class HijriDate:
1920
def weekday(self): ...
2021

2122
class hijri_parser(non_gregorian_parser):
22-
calendar_converter: Any
23+
calendar_converter: type[hijri]
2324
default_year: int
2425
default_month: int
2526
default_day: int
26-
non_gregorian_date_cls: Any
27+
non_gregorian_date_cls: type[HijriDate]
2728
def handle_two_digit_year(self, year: int) -> int: ...
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from typing import Any
1+
from dateparser.calendars.jalali_parser import jalali_parser
22

33
from . import CalendarBase
44

55
class JalaliCalendar(CalendarBase):
6-
parser: Any
6+
parser: type[jalali_parser]

stubs/dateparser/dateparser/calendars/jalali_parser.pyi

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ class jalali_parser(non_gregorian_parser):
1414
default_year: int
1515
default_month: int
1616
default_day: int
17-
non_gregorian_date_cls: Any
17+
non_gregorian_date_cls: type[PersianDate]
1818
def handle_two_digit_year(self, year: int) -> int: ...

stubs/dateparser/dateparser/conf.pyi

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
from _typeshed import Incomplete
21
from typing import Any
32
from typing_extensions import Self
43

54
class Settings:
65
def __new__(cls, *args, **kw) -> Self: ...
7-
def __init__(self, settings: Incomplete | None = None) -> None: ...
6+
def __init__(self, settings: dict[str, Any] | None = None) -> None: ...
87
@classmethod
9-
def get_key(cls, settings: Incomplete | None = None): ...
10-
def replace(self, mod_settings: Incomplete | None = None, **kwds): ...
8+
def get_key(cls, settings: dict[str, Any] | None = None) -> str: ...
9+
def replace(self, mod_settings: dict[str, Any] | None = None, **kwds) -> Self: ...
1110

12-
settings: Any
11+
settings: Settings
1312

1413
def apply_settings(f): ...
1514

1615
class SettingValidationError(ValueError): ...
1716

18-
def check_settings(settings) -> None: ...
17+
def check_settings(settings: Settings) -> None: ...
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
language_order: list[str]
2-
language_locale_dict: dict[str, str]
3-
language_map: dict[str, list[str]]
1+
from typing import Final
2+
3+
language_order: Final[list[str]]
4+
language_locale_dict: Final[dict[str, str]]
5+
language_map: Final[dict[str, list[str]]]

stubs/dateparser/dateparser/date.pyi

+18-18
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import collections
22
from collections.abc import Callable, Iterable, Iterator
3-
from datetime import datetime
3+
from datetime import datetime, tzinfo
44
from re import Pattern
5-
from typing import ClassVar, Literal, overload
5+
from typing import ClassVar, Final, Literal, overload
66
from typing_extensions import TypeAlias
77

88
from dateparser import _Settings
@@ -13,23 +13,23 @@ from dateparser.languages.locale import Locale
1313
_DetectLanguagesFunction: TypeAlias = Callable[[str, float], list[str]]
1414
_Period: TypeAlias = Literal["time", "day", "week", "month", "year"]
1515

16-
APOSTROPHE_LOOK_ALIKE_CHARS: list[str]
17-
RE_NBSP: Pattern[str]
18-
RE_SPACES: Pattern[str]
19-
RE_TRIM_SPACES: Pattern[str]
20-
RE_TRIM_COLONS: Pattern[str]
21-
RE_SANITIZE_SKIP: Pattern[str]
22-
RE_SANITIZE_RUSSIAN: Pattern[str]
23-
RE_SANITIZE_PERIOD: Pattern[str]
24-
RE_SANITIZE_ON: Pattern[str]
25-
RE_SANITIZE_APOSTROPHE: Pattern[str]
26-
RE_SEARCH_TIMESTAMP: Pattern[str]
27-
RE_SANITIZE_CROATIAN: Pattern[str]
28-
RE_SEARCH_NEGATIVE_TIMESTAMP: Pattern[str]
16+
APOSTROPHE_LOOK_ALIKE_CHARS: Final[list[str]]
17+
RE_NBSP: Final[Pattern[str]]
18+
RE_SPACES: Final[Pattern[str]]
19+
RE_TRIM_SPACES: Final[Pattern[str]]
20+
RE_TRIM_COLONS: Final[Pattern[str]]
21+
RE_SANITIZE_SKIP: Final[Pattern[str]]
22+
RE_SANITIZE_RUSSIAN: Final[Pattern[str]]
23+
RE_SANITIZE_PERIOD: Final[Pattern[str]]
24+
RE_SANITIZE_ON: Final[Pattern[str]]
25+
RE_SANITIZE_APOSTROPHE: Final[Pattern[str]]
26+
RE_SEARCH_TIMESTAMP: Final[Pattern[str]]
27+
RE_SANITIZE_CROATIAN: Final[Pattern[str]]
28+
RE_SEARCH_NEGATIVE_TIMESTAMP: Final[Pattern[str]]
2929

3030
def sanitize_spaces(date_string: str) -> str: ...
31-
def date_range(begin, end, **kwargs) -> None: ...
32-
def get_intersecting_periods(low, high, period: str = "day") -> None: ...
31+
def date_range(begin: datetime, end: datetime, **kwargs) -> None: ...
32+
def get_intersecting_periods(low: datetime, high: datetime, period: str = "day") -> None: ...
3333
def sanitize_date(date_string: str) -> str: ...
3434
def get_date_from_timestamp(date_string: str, settings: Settings, negative: bool = False) -> datetime | None: ...
3535
def parse_with_formats(date_string: str, date_formats: Iterable[str], settings: Settings) -> DateData: ...
@@ -58,7 +58,7 @@ class _DateLocaleParser:
5858
def _try_freshness_parser(self) -> DateData | None: ...
5959
def _try_absolute_parser(self) -> DateData | None: ...
6060
def _try_nospaces_parser(self) -> DateData | None: ...
61-
def _try_parser(self, parse_method) -> DateData | None: ...
61+
def _try_parser(self, parse_method: Callable[[str, Settings, tzinfo | None], tuple[datetime, str]]) -> DateData | None: ...
6262
def _try_given_formats(self) -> DateData | None: ...
6363
def _get_translated_date(self) -> str: ...
6464
def _get_translated_date_with_formatting(self) -> str: ...
+11-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1-
from _typeshed import Incomplete
2-
from typing import Any
1+
from collections.abc import Callable
2+
from datetime import datetime, tzinfo
3+
4+
from dateparser.conf import Settings
35

46
class DateParser:
5-
def parse(self, date_string, parse_method, settings: Incomplete | None = None): ...
7+
def parse(
8+
self,
9+
date_string: str,
10+
parse_method: Callable[[str, Settings, tzinfo | None], tuple[datetime, str]],
11+
settings: Settings | None = None,
12+
) -> tuple[datetime, str]: ...
613

7-
date_parser: Any
14+
date_parser: DateParser
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1+
import re
12
from _typeshed import Incomplete
2-
from typing import Any
3+
from typing import Final
4+
from zoneinfo import ZoneInfo
35

4-
PATTERN: Any
6+
from dateparser.date import DateData
7+
8+
PATTERN: Final[re.Pattern[str]]
59

610
class FreshnessDateDataParser:
7-
def get_local_tz(self): ...
8-
def parse(self, date_string, settings): ...
9-
def get_kwargs(self, date_string): ...
10-
def get_date_data(self, date_string, settings: Incomplete | None = None): ...
11+
def get_local_tz(self) -> ZoneInfo: ...
12+
def parse(self, date_string: str, settings) -> tuple[Incomplete | None, str | None]: ...
13+
def get_kwargs(self, date_string: str) -> dict[str, float]: ...
14+
def get_date_data(self, date_string: str, settings: Incomplete | None = None) -> DateData: ...
1115

12-
freshness_date_parser: Any
16+
freshness_date_parser: FreshnessDateDataParser
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from .loader import default_loader as default_loader
2+
from .locale import Locale as Locale
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,28 @@
1+
import re
12
from _typeshed import Incomplete
2-
from typing import Any
3+
from typing import Any, Final, overload
34

4-
PARSER_HARDCODED_TOKENS: Any
5-
PARSER_KNOWN_TOKENS: Any
6-
ALWAYS_KEEP_TOKENS: list[str]
7-
KNOWN_WORD_TOKENS: Any
8-
PARENTHESES_PATTERN: Any
9-
NUMERAL_PATTERN: Any
10-
KEEP_TOKEN_PATTERN: Any
5+
PARSER_HARDCODED_TOKENS: Final[list[str]]
6+
PARSER_KNOWN_TOKENS: Final[list[str]]
7+
ALWAYS_KEEP_TOKENS: Final[list[str]]
8+
KNOWN_WORD_TOKENS: Final[list[str]]
9+
PARENTHESES_PATTERN: Final[re.Pattern[str]]
10+
NUMERAL_PATTERN: Final[re.Pattern[str]]
11+
KEEP_TOKEN_PATTERN: Final[re.Pattern[str]]
1112

1213
class UnknownTokenError(Exception): ...
1314

1415
class Dictionary:
1516
info: Any
16-
def __init__(self, locale_info, settings: Incomplete | None = None) -> None: ...
17+
def __init__(self, locale_info: dict[str, Incomplete], settings: Incomplete | None = None) -> None: ...
1718
def __contains__(self, key): ...
1819
def __getitem__(self, key): ...
1920
def __iter__(self) -> Any: ...
20-
def are_tokens_valid(self, tokens): ...
21-
def split(self, string, keep_formatting: bool = False): ...
21+
def are_tokens_valid(self, tokens: list[str]) -> bool: ...
22+
@overload
23+
def split(self, string: None, keep_formatting: bool = False) -> None: ...
24+
@overload
25+
def split(self, string: str, keep_formatting: bool = False) -> list[str]: ...
2226

2327
class NormalizedDictionary(Dictionary):
24-
def __init__(self, locale_info, settings: Incomplete | None = None) -> None: ...
28+
def __init__(self, locale_info: dict[str, Incomplete], settings: Incomplete | None = None) -> None: ...

stubs/dateparser/dateparser/languages/loader.pyi

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
import re
12
from collections import OrderedDict
23
from collections.abc import Iterator
3-
from typing import Any
4+
from typing import Any, Final
45

56
from .locale import Locale
67

7-
LOCALE_SPLIT_PATTERN: Any
8+
LOCALE_SPLIT_PATTERN: Final[re.Pattern[str]]
89

910
class LocaleDataLoader:
1011
def get_locale_map(
@@ -25,4 +26,4 @@ class LocaleDataLoader:
2526
) -> Iterator[Locale]: ...
2627
def get_locale(self, shortname: str) -> Locale: ...
2728

28-
default_loader: Any
29+
default_loader: LocaleDataLoader

stubs/dateparser/dateparser/languages/locale.pyi

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from re import Pattern
2+
from typing import Final
23

34
from dateparser.conf import Settings
45

5-
NUMERAL_PATTERN: Pattern[str]
6+
NUMERAL_PATTERN: Final[Pattern[str]]
67

78
class Locale:
89
shortname: str
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
from typing import Any
1+
from _typeshed import Incomplete
2+
from logging import Logger
23

34
class LanguageValidator:
4-
logger: Any
5-
VALID_KEYS: Any
5+
logger: Logger | None
6+
VALID_KEYS: list[str]
67
@classmethod
7-
def get_logger(cls): ...
8+
def get_logger(cls) -> Logger: ...
89
@classmethod
9-
def validate_info(cls, language_id, info): ...
10+
def validate_info(cls, language_id, info: dict[str, Incomplete]) -> bool: ...
+46-35
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,64 @@
1+
import collections
12
import datetime
3+
import re
24
from _typeshed import Incomplete
3-
from typing import Any
5+
from collections.abc import Callable, Generator
6+
from io import StringIO
7+
from typing import Any, Final, Literal, overload
48

5-
NSP_COMPATIBLE: Any
6-
MERIDIAN: Any
7-
MICROSECOND: Any
8-
EIGHT_DIGIT: Any
9-
HOUR_MINUTE_REGEX: Any
9+
from dateparser.conf import Settings
1010

11-
def no_space_parser_eligibile(datestring): ...
12-
def get_unresolved_attrs(parser_object): ...
11+
NSP_COMPATIBLE: Final[re.Pattern[str]]
12+
MERIDIAN: Final[re.Pattern[str]]
13+
MICROSECOND: Final[re.Pattern[str]]
14+
EIGHT_DIGIT: Final[re.Pattern[str]]
15+
HOUR_MINUTE_REGEX: Final[re.Pattern[str]]
1316

14-
date_order_chart: Any
17+
def no_space_parser_eligibile(datestring: str) -> bool: ...
18+
def get_unresolved_attrs(
19+
parser_object: object,
20+
) -> tuple[list[Literal["year", "month", "day"]], list[Literal["year", "month", "day"]]]: ...
1521

16-
def resolve_date_order(order, lst: Incomplete | None = None): ...
22+
date_order_chart: Final[dict[str, str]]
23+
24+
@overload
25+
def resolve_date_order(order: str, lst: Literal[True]) -> list[str]: ...
26+
@overload
27+
def resolve_date_order(order: str, lst: Literal[False] | None = None) -> str: ...
1728

1829
class _time_parser:
19-
time_directives: Any
20-
def __call__(self, timestring): ...
30+
time_directives: list[str]
31+
def __call__(self, timestring: str) -> datetime.time: ...
2132

22-
time_parser: Any
33+
time_parser: _time_parser
2334

2435
class _no_spaces_parser:
25-
period: Any
26-
date_formats: Any
36+
period: dict[str, list[str]]
37+
date_formats: dict[str, list[str]]
2738
def __init__(self, *args, **kwargs): ...
2839
@classmethod
29-
def parse(cls, datestring, settings): ...
40+
def parse(cls, datestring: str, settings: Settings) -> tuple[datetime.datetime, str]: ...
3041

3142
class _parser:
32-
alpha_directives: Any
33-
num_directives: Any
34-
settings: Any
35-
tokens: Any
36-
filtered_tokens: Any
37-
unset_tokens: Any
38-
day: Any
39-
month: Any
40-
year: Any
41-
time: Any
42-
auto_order: Any
43-
ordered_num_directives: Any
44-
def __init__(self, tokens, settings): ...
43+
alpha_directives: collections.OrderedDict[str, list[str]]
44+
num_directives: dict[str, list[str]]
45+
settings: Settings
46+
tokens: list[tuple[Incomplete, Incomplete]]
47+
filtered_tokens: list[tuple[Incomplete, Incomplete, int]]
48+
unset_tokens: list[Incomplete]
49+
day: int | None
50+
month: int | None
51+
year: int | None
52+
time: Callable[[], datetime.time] | None
53+
auto_order: list[str]
54+
ordered_num_directives: collections.OrderedDict[str, list[str]]
55+
def __init__(self, tokens, settings: Settings): ...
4556
@classmethod
46-
def parse(cls, datestring, settings, tz: datetime.tzinfo | None = None): ...
57+
def parse(cls, datestring: str, settings: Settings, tz: datetime.tzinfo | None = None): ...
4758

4859
class tokenizer:
49-
digits: str
50-
letters: str
51-
instream: Any
52-
def __init__(self, ds) -> None: ...
53-
def tokenize(self) -> None: ...
60+
digits: Literal["0123456789:"]
61+
letters: Literal["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"]
62+
instream: StringIO
63+
def __init__(self, ds: str) -> None: ...
64+
def tokenize(self) -> Generator[tuple[str, Literal[0, 1, 2]], Any, None]: ...

0 commit comments

Comments
 (0)