Skip to content

Commit ede1bd3

Browse files
authored
chore: Add _typing_compat module (#2578)
* chore(typing): Add `_typing_compat.py` - Mentioned in (#2391 (comment)) - Needed again for #2572 * refactor: Reuse `TypeVar` import * refactor: Reuse `@deprecated` import * refactor: Reuse `Protocol38` import * docs: Add module-level docstring
1 parent bf190cc commit ede1bd3

File tree

9 files changed

+90
-97
lines changed

9 files changed

+90
-97
lines changed

narwhals/_compliant/dataframe.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
from narwhals._translate import NumpyConvertible
2727
from narwhals._translate import ToNarwhals
2828
from narwhals._translate import ToNarwhalsT_co
29+
from narwhals._typing_compat import deprecated
2930
from narwhals.utils import Version
3031
from narwhals.utils import _StoresNative
31-
from narwhals.utils import deprecated
3232
from narwhals.utils import is_compliant_series
3333
from narwhals.utils import is_index_selector
3434
from narwhals.utils import is_range

narwhals/_compliant/expr.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import annotations
22

3-
import sys
43
from functools import partial
54
from operator import methodcaller
65
from typing import TYPE_CHECKING
@@ -30,23 +29,14 @@
3029
from narwhals._compliant.typing import EagerSeriesT
3130
from narwhals._compliant.typing import LazyExprT
3231
from narwhals._compliant.typing import NativeExprT
32+
from narwhals._typing_compat import Protocol38
33+
from narwhals._typing_compat import deprecated
3334
from narwhals.dependencies import get_numpy
3435
from narwhals.dependencies import is_numpy_array
3536
from narwhals.dtypes import DType
3637
from narwhals.utils import _StoresCompliant
37-
from narwhals.utils import deprecated
3838
from narwhals.utils import not_implemented
3939

40-
if not TYPE_CHECKING: # pragma: no cover
41-
if sys.version_info >= (3, 9):
42-
from typing import Protocol as Protocol38
43-
else:
44-
from typing import Generic as Protocol38
45-
else: # pragma: no cover
46-
# TODO @dangotbanned: Remove after dropping `3.8` (#2084)
47-
# - https://github.com/narwhals-dev/narwhals/pull/2064#discussion_r1965921386
48-
from typing import Protocol as Protocol38
49-
5040
if TYPE_CHECKING:
5141
from typing import Mapping
5242

narwhals/_compliant/group_by.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from __future__ import annotations
22

33
import re
4-
import sys
54
from typing import TYPE_CHECKING
65
from typing import Any
76
from typing import Callable
@@ -26,6 +25,7 @@
2625
from narwhals._compliant.typing import EagerExprT_contra
2726
from narwhals._compliant.typing import LazyExprT_contra
2827
from narwhals._compliant.typing import NativeExprT_co
28+
from narwhals._typing_compat import Protocol38
2929
from narwhals.utils import is_sequence_of
3030

3131
if TYPE_CHECKING:
@@ -34,16 +34,6 @@
3434
_SameFrameT = TypeVar("_SameFrameT", CompliantDataFrameAny, CompliantLazyFrameAny)
3535

3636

37-
if not TYPE_CHECKING: # pragma: no cover
38-
if sys.version_info >= (3, 9):
39-
from typing import Protocol as Protocol38
40-
else:
41-
from typing import Generic as Protocol38
42-
else: # pragma: no cover
43-
# TODO @dangotbanned: Remove after dropping `3.8` (#2084)
44-
# - https://github.com/narwhals-dev/narwhals/pull/2064#discussion_r1965921386
45-
from typing import Protocol as Protocol38
46-
4737
__all__ = [
4838
"CompliantGroupBy",
4939
"DepthTrackingGroupBy",

narwhals/_compliant/selectors.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,12 @@
1414
from typing import overload
1515

1616
from narwhals._compliant.expr import CompliantExpr
17+
from narwhals._typing_compat import Protocol38
1718
from narwhals.utils import _parse_time_unit_and_time_zone
1819
from narwhals.utils import dtype_matches_time_unit_and_time_zone
1920
from narwhals.utils import get_column_names
2021
from narwhals.utils import is_compliant_dataframe
2122

22-
if not TYPE_CHECKING: # pragma: no cover
23-
# TODO @dangotbanned: Remove after dropping `3.8` (#2084)
24-
# - https://github.com/narwhals-dev/narwhals/pull/2064#discussion_r1965921386
25-
import sys
26-
27-
if sys.version_info >= (3, 9):
28-
from typing import Protocol as Protocol38
29-
else:
30-
from typing import Generic as Protocol38
31-
32-
else: # pragma: no cover
33-
from typing import Protocol as Protocol38
34-
3523
if TYPE_CHECKING:
3624
from datetime import timezone
3725

narwhals/_compliant/when_then.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import annotations
22

3-
import sys
43
from typing import TYPE_CHECKING
54
from typing import Any
65
from typing import Callable
@@ -19,6 +18,7 @@
1918
from narwhals._compliant.typing import LazyExprAny
2019
from narwhals._compliant.typing import NativeExprT
2120
from narwhals._compliant.typing import NativeSeriesT
21+
from narwhals._typing_compat import Protocol38
2222

2323
if TYPE_CHECKING:
2424
from typing_extensions import Self
@@ -31,15 +31,6 @@
3131
from narwhals.utils import Version
3232
from narwhals.utils import _FullContext
3333

34-
if not TYPE_CHECKING: # pragma: no cover
35-
if sys.version_info >= (3, 9):
36-
from typing import Protocol as Protocol38
37-
else:
38-
from typing import Generic as Protocol38
39-
else: # pragma: no cover
40-
# TODO @dangotbanned: Remove after dropping `3.8` (#2084)
41-
# - https://github.com/narwhals-dev/narwhals/pull/2064#discussion_r1965921386
42-
from typing import Protocol as Protocol38
4334

4435
__all__ = ["CompliantThen", "CompliantWhen", "EagerWhen", "LazyWhen"]
4536

narwhals/_translate.py

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -68,37 +68,13 @@ class OtherConvertible(
6868
from typing import Mapping
6969
from typing import Protocol
7070

71+
from narwhals._typing_compat import TypeVar
72+
7173
if TYPE_CHECKING:
7274
import pyarrow as pa
7375
from typing_extensions import Self
7476
from typing_extensions import TypeAlias
7577
from typing_extensions import TypeIs
76-
from typing_extensions import TypeVar
77-
78-
79-
else: # pragma: no cover
80-
import sys
81-
82-
if sys.version_info >= (3, 13):
83-
from typing import TypeVar
84-
else:
85-
from typing import TypeVar as _TypeVar
86-
87-
def TypeVar( # noqa: ANN202, N802
88-
name: str,
89-
*constraints: Any,
90-
bound: Any | None = None,
91-
covariant: bool = False,
92-
contravariant: bool = False,
93-
**kwds: Any, # noqa: ARG001
94-
):
95-
return _TypeVar(
96-
name,
97-
*constraints,
98-
bound=bound,
99-
covariant=covariant,
100-
contravariant=contravariant,
101-
)
10278

10379

10480
class ArrowStreamExportable(Protocol):

narwhals/_typing_compat.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"""Backward compatibility for newer/less buggy typing features.
2+
3+
## Important
4+
Import from here to avoid introducing a runtime dependency on [`typing_extensions`]
5+
6+
## Notes
7+
- `Protocol38`
8+
- https://github.com/narwhals-dev/narwhals/pull/2064#discussion_r1965921386
9+
- https://github.com/narwhals-dev/narwhals/pull/2294#discussion_r2014534830
10+
- `TypeVar` defaults
11+
- https://typing.python.org/en/latest/spec/generics.html#type-parameter-defaults
12+
- https://peps.python.org/pep-0696/
13+
- `@deprecated`
14+
- https://docs.python.org/3/library/warnings.html#warnings.deprecated
15+
- https://typing.python.org/en/latest/spec/directives.html#deprecated
16+
- https://peps.python.org/pep-0702/
17+
18+
[`typing_extensions`]: https://github.com/python/typing_extensions
19+
"""
20+
21+
from __future__ import annotations
22+
23+
# ruff: noqa: ARG001, ANN202, N802
24+
import sys
25+
from typing import TYPE_CHECKING
26+
from typing import Any
27+
28+
if TYPE_CHECKING:
29+
from typing import Callable
30+
from typing import Protocol as Protocol38
31+
32+
if sys.version_info >= (3, 13):
33+
from typing import TypeVar
34+
from warnings import deprecated
35+
else:
36+
from typing_extensions import TypeVar
37+
from typing_extensions import deprecated
38+
39+
_Fn = TypeVar("_Fn", bound=Callable[..., Any])
40+
41+
42+
else: # pragma: no cover
43+
if sys.version_info >= (3, 13):
44+
from typing import TypeVar
45+
from warnings import deprecated
46+
else:
47+
from typing import TypeVar as _TypeVar
48+
49+
def TypeVar(
50+
name: str,
51+
*constraints: Any,
52+
bound: Any | None = None,
53+
covariant: bool = False,
54+
contravariant: bool = False,
55+
**kwds: Any,
56+
):
57+
return _TypeVar(
58+
name,
59+
*constraints,
60+
bound=bound,
61+
covariant=covariant,
62+
contravariant=contravariant,
63+
)
64+
65+
def deprecated(message: str, /) -> Callable[[_Fn], _Fn]:
66+
def wrapper(func: _Fn, /) -> _Fn:
67+
return func
68+
69+
return wrapper
70+
71+
# TODO @dangotbanned: Remove after dropping `3.8` (#2084)
72+
# - https://github.com/narwhals-dev/narwhals/pull/2064#discussion_r1965921386
73+
if sys.version_info >= (3, 9):
74+
from typing import Protocol as Protocol38
75+
else:
76+
from typing import Generic as Protocol38
77+
78+
79+
__all__ = ["Protocol38", "TypeVar", "deprecated"]

narwhals/stable/v1/__init__.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from narwhals import dependencies
1616
from narwhals import exceptions
1717
from narwhals import selectors
18+
from narwhals._typing_compat import TypeVar
1819
from narwhals.dataframe import DataFrame as NwDataFrame
1920
from narwhals.dataframe import LazyFrame as NwLazyFrame
2021
from narwhals.dependencies import get_polars
@@ -89,7 +90,6 @@
8990

9091
from typing_extensions import ParamSpec
9192
from typing_extensions import Self
92-
from typing_extensions import TypeVar
9393

9494
from narwhals._translate import IntoArrowTable
9595
from narwhals.dataframe import MultiColSelector
@@ -110,15 +110,11 @@
110110
DataFrameT = TypeVar("DataFrameT", bound="DataFrame[Any]")
111111
LazyFrameT = TypeVar("LazyFrameT", bound="LazyFrame[Any]")
112112
SeriesT = TypeVar("SeriesT", bound="Series[Any]")
113-
IntoSeriesT = TypeVar("IntoSeriesT", bound="IntoSeries", default=Any)
114113
T = TypeVar("T", default=Any)
115114
P = ParamSpec("P")
116115
R = TypeVar("R")
117-
else:
118-
from typing import TypeVar
119116

120-
IntoSeriesT = TypeVar("IntoSeriesT", bound="IntoSeries")
121-
T = TypeVar("T")
117+
IntoSeriesT = TypeVar("IntoSeriesT", bound="IntoSeries", default=Any)
122118

123119

124120
class DataFrame(NwDataFrame[IntoDataFrameT]):

narwhals/utils.py

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from warnings import warn
2828

2929
from narwhals._enum import NoAutoEnum
30+
from narwhals._typing_compat import deprecated
3031
from narwhals.dependencies import get_cudf
3132
from narwhals.dependencies import get_dask
3233
from narwhals.dependencies import get_dask_dataframe
@@ -1759,24 +1760,6 @@ def _is_naive_format(format: str) -> bool:
17591760
return not any(x in format for x in ("%s", "%z", "Z"))
17601761

17611762

1762-
if TYPE_CHECKING:
1763-
import sys
1764-
1765-
if sys.version_info >= (3, 13):
1766-
# NOTE: avoids `mypy`
1767-
# error: Module "narwhals.utils" does not explicitly export attribute "deprecated" [attr-defined]
1768-
from warnings import deprecated as deprecated # noqa: PLC0414
1769-
else:
1770-
from typing_extensions import deprecated as deprecated # noqa: PLC0414
1771-
else:
1772-
1773-
def deprecated(message: str, /) -> Callable[[_Fn], _Fn]: # noqa: ARG001
1774-
def wrapper(func: _Fn, /) -> _Fn:
1775-
return func
1776-
1777-
return wrapper
1778-
1779-
17801763
class not_implemented: # noqa: N801
17811764
"""Mark some functionality as unsupported.
17821765

0 commit comments

Comments
 (0)