-
Notifications
You must be signed in to change notification settings - Fork 216
Closed
Labels
attribute accessInstance attributes, class attributes, etc.Instance attributes, class attributes, etc.good first issueGood for newcomersGood for newcomers
Description
Summary
When typing unit tests written with pytest, when parametrizing a fixture in the following way:
# /// script
# dependencies = [
# "pytest",
# ]
# ///
import pytest
@pytest.fixture(params=["foo", "bar"])
def foo_fixture(request: pytest.FixtureRequest) -> str:
return request.paramty does not recognize that the pytest.FixtureRequest object does indeed have a param attribute:
uvx ty check .
error[unresolved-attribute]: Type `FixtureRequest` has no attribute `param`
--> main.py:12:12
|
10 | @pytest.fixture(params=["foo", "bar"])
11 | def foo_fixture(request: pytest.FixtureRequest) -> str:
12 | return request.param
| ^^^^^^^^^^^^^
|
info: rule `unresolved-attribute` is enabled by defaultdespite the fact that pytest.FixtureRequest declares this attribute in it's __init__ method:
class FixtureRequest(abc.ABC):
"""The type of the ``request`` fixture.
A request object gives access to the requesting test context and has a
``param`` attribute in case the fixture is parametrized.
"""
def __init__(
self,
pyfuncitem: Function,
fixturename: str | None,
arg2fixturedefs: dict[str, Sequence[FixtureDef[Any]]],
fixture_defs: dict[str, FixtureDef[Any]],
*,
_ispytest: bool = False,
) -> None:
check_ispytest(_ispytest)
#: Fixture for which this request is being performed.
self.fixturename: Final = fixturename
self._pyfuncitem: Final = pyfuncitem
# The FixtureDefs for each fixture name requested by this item.
# Starts from the statically-known fixturedefs resolved during
# collection. Dynamically requested fixtures (using
# `request.getfixturevalue("foo")`) are added dynamically.
self._arg2fixturedefs: Final = arg2fixturedefs
# The evaluated argnames so far, mapping to the FixtureDef they resolved
# to.
self._fixture_defs: Final = fixture_defs
# Notes on the type of `param`:
# -`request.param` is only defined in parametrized fixtures, and will raise
# AttributeError otherwise. Python typing has no notion of "undefined", so
# this cannot be reflected in the type.
# - Technically `param` is only (possibly) defined on SubRequest, not
# FixtureRequest, but the typing of that is still in flux so this cheats.
# - In the future we might consider using a generic for the param type, but
# for now just using Any.
self.param: Any
...Both mypy and pyright do not emit an error for this (mypy does complain about the return annotation being a str and request.param returning Any in strict mode, though).
I guess that attributes assigned in __init__ methods are currently not considered or that there is at least no proper resolution to which __init__ gets called (since this is an ABC)? The comment above self.param may also be relevant here.
Version
ty 0.0.1-alpha.11
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
attribute accessInstance attributes, class attributes, etc.Instance attributes, class attributes, etc.good first issueGood for newcomersGood for newcomers