Skip to content

Commit 2c6c3c3

Browse files
authored
fix(typing): Avoid false positives on nw.__getattr__ (#3333)
1 parent 120b617 commit 2c6c3c3

File tree

2 files changed

+33
-8
lines changed

2 files changed

+33
-8
lines changed

narwhals/__init__.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,17 @@
177177
]
178178

179179

180-
def __getattr__(name: _t.Literal["__version__"]) -> str: # type: ignore[misc]
181-
if name == "__version__":
182-
global __version__ # noqa: PLW0603
180+
if not _t.TYPE_CHECKING:
183181

184-
from importlib import metadata
182+
def __getattr__(name: str) -> _t.Any:
183+
if name == "__version__":
184+
global __version__ # noqa: PLW0603
185185

186-
__version__ = metadata.version(__name__)
187-
return __version__
188-
msg = f"module {__name__!r} has no attribute {name!r}"
189-
raise AttributeError(msg)
186+
from importlib import metadata
187+
188+
__version__ = metadata.version(__name__)
189+
return __version__
190+
msg = f"module {__name__!r} has no attribute {name!r}"
191+
raise AttributeError(msg)
192+
else: # pragma: no cover
193+
...

tests/version_test.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
from __future__ import annotations
22

33
import re
4+
from collections.abc import Callable
45
from importlib.metadata import distribution
56
from os import environ
67
from pathlib import Path
8+
from typing import TYPE_CHECKING, Any
9+
10+
import pytest
711

812
import narwhals as nw
913
from narwhals._utils import parse_version
@@ -35,3 +39,20 @@ def test_package_version() -> None:
3539
assert version_comp <= parse_version(pyproject_version)
3640
dist_version = distribution("narwhals").version
3741
assert version == dist_version
42+
43+
44+
def test_package_getattr() -> None:
45+
pytest.importorskip("typing_extensions")
46+
from typing_extensions import assert_type
47+
48+
ok = nw.__version__
49+
assert_type(ok, str)
50+
also_ok = nw.all
51+
assert_type(also_ok, Callable[[], nw.Expr])
52+
53+
if TYPE_CHECKING:
54+
bad = nw.not_real # type: ignore[attr-defined]
55+
assert_type(bad, Any)
56+
57+
with pytest.raises(AttributeError):
58+
very_bad = nw.not_real # type: ignore[attr-defined] # noqa: F841

0 commit comments

Comments
 (0)