Skip to content

Commit ea8b6d2

Browse files
committed
fix: restore datetime/decimal attributes on python_utils.types
Master leaked datetime and decimal as module attributes via module-level imports; moving the aliases into _aliases dropped them. Re-add them with regression tests, plus a star-import smoke test for the lazy package namespace.
1 parent 841038b commit ea8b6d2

3 files changed

Lines changed: 29 additions & 0 deletions

File tree

_python_utils_tests/test_aliases.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,21 @@ def test_types_reexports_aliases_identically() -> None:
5151
assert getattr(types, name) is getattr(_aliases, name), name
5252

5353

54+
def test_types_still_exposes_datetime_and_decimal() -> None:
55+
"""Keep ``datetime`` and ``decimal`` as ``types`` module attributes."""
56+
# Backwards compatibility: on 3.x these leaked as module attributes via
57+
# module-level imports, so `from python_utils.types import datetime` and
58+
# attribute access both worked. Moving the aliases into _aliases must not
59+
# drop them.
60+
import datetime
61+
import decimal
62+
63+
from python_utils import types
64+
65+
assert types.datetime is datetime
66+
assert types.decimal is decimal
67+
68+
5469
def test_types_still_exposes_typing_extensions_surface() -> None:
5570
"""The ``types`` facade still re-exports ``Self``."""
5671
# The facade must keep re-exporting typing_extensions (e.g. Self).

_python_utils_tests/test_lazy_imports.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@ def test_dir_lists_lazy_submodules() -> None:
8383
assert set(python_utils.__all__) <= names
8484

8585

86+
def test_star_import_resolves_all_names() -> None:
87+
"""Bind every ``__all__`` name via a package star-import."""
88+
# `from python_utils import *` goes through __getattr__ for every name in
89+
# __all__; none may raise AttributeError, and all must be bound.
90+
namespace: dict[str, object] = {}
91+
exec('from python_utils import *', namespace) # noqa: S102
92+
missing = set(python_utils.__all__) - set(namespace)
93+
assert not missing
94+
95+
8696
@pytest.mark.asyncio
8797
async def test_aio_timeout_generator_default_iterable() -> None:
8898
"""Default the iterable to ``aio.acount`` when omitted."""

python_utils/types.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
# pyright: reportWildcardImportFromLibrary=false
1313
# ruff: noqa: F405
1414

15+
# Kept as public module attributes for backwards compatibility:
16+
# `from python_utils.types import datetime, decimal` worked in 3.x.
17+
import datetime as datetime
18+
import decimal as decimal
1519
from re import Match, Pattern
1620
from types import * # pragma: no cover # noqa: F403
1721
from typing import * # pragma: no cover # noqa: F403

0 commit comments

Comments
 (0)