-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Type annotate fixtures.py & related #6736
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
afad3d8 to
9bda23f
Compare
| # we arrive here because of a dynamic call to | ||
| # getfixturevalue(argname) usage which was naturally | ||
| # not known at parsing/collection time | ||
| assert self._pyfuncitem.parent is not None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is immediately dereferenced below so should be fine.
| """ | ||
| return self._get_active_fixturedef(argname).cached_result[0] | ||
| fixturedef = self._get_active_fixturedef(argname) | ||
| assert fixturedef.cached_result is not None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Immediately dereferenced below.
| values.reverse() | ||
| return values | ||
| values.append(fixturedef) | ||
| assert isinstance(current, SubRequest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This attribute is only set on SubRequest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would make a helpful in-code comment for future maintainers 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know, once the assert is in, the implication is reversed -- the access is legal because of the assert, not the other way :)
|
|
||
|
|
||
| scopes = "session package module class function".split() | ||
| scopes = ["session", "package", "module", "class", "function"] # type: List[_Scope] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to make the type annotation work (_Scope is a Literal).
| """Look up the index of ``scope`` and raise a descriptive value error | ||
| if not defined. | ||
| """ | ||
| strscopes = scopes # type: Sequence[str] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a hack to expand the type of scopes to allow checking against an str rather than _Scope.
| exceptions.append(sys.exc_info()) | ||
| if exceptions: | ||
| _, val, tb = exceptions[0] | ||
| assert val is not None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dereferenced just below.
| # display it now and during the teardown (in .finish()). | ||
| if fixturedef.ids: | ||
| if callable(fixturedef.ids): | ||
| fixturedef.cached_param = fixturedef.ids(request.param) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed so I only need to ignore once.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a helper method FixtureDef.set_cached_param would be appropriate? Though I can see an argument that it's not worth the trouble when we have to maintain the current option for backwards-compatibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm not sure it's worth it.
9bda23f to
3856200
Compare
3856200 to
c0c4ca9
Compare
Zac-HD
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @bluetech! A few questions and suggestions for further annotations below, but overall this looks great to me 😁
| # display it now and during the teardown (in .finish()). | ||
| if fixturedef.ids: | ||
| if callable(fixturedef.ids): | ||
| fixturedef.cached_param = fixturedef.ids(request.param) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a helper method FixtureDef.set_cached_param would be appropriate? Though I can see an argument that it's not worth the trouble when we have to maintain the current option for backwards-compatibility.
|
|
||
| def add_funcarg_pseudo_fixture_def(collector, metafunc, fixturemanager): | ||
| def add_funcarg_pseudo_fixture_def( | ||
| collector, metafunc: "Metafunc", fixturemanager: "FixtureManager" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth annotating collector? AFAICT it's an Optional[Type[nodes.Node]].
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I'm not sure of something, and too lazy to check/verify, I leave it unannotated. Usually some later PR adds it :)
| values.reverse() | ||
| return values | ||
| values.append(fixturedef) | ||
| assert isinstance(current, SubRequest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would make a helpful in-code comment for future maintainers 😄
| self, | ||
| request: "FixtureRequest", | ||
| scope: "_Scope", | ||
| param, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
param: object, ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, this one can also be NOTSET, and I'd like to distinguish it in the type annotation from just an object (although object subsumes everything) just for clarity.
I think there is another PR that does that although I sort of lost track myself already 👣
|
|
||
|
|
||
| def _eval_scope_callable(scope_callable, fixture_name, config): | ||
| def _eval_scope_callable(scope_callable, fixture_name: str, config: Config) -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
scope_callable: Callable[..., str] - speccing keyword arguments is pretty fiddly, but even without the arguments specified this could catch a fair few issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer to leave this one for for later.
|
|
||
| def getfixtureclosure(self, fixturenames, parentnode, ignore_args=()): | ||
| def getfixtureclosure( | ||
| self, fixturenames: Tuple[str, ...], parentnode, ignore_args: Sequence[str] = () |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parentnode: nodes.Node
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure, I prefer to leave this one.
c0c4ca9 to
cba62b6
Compare
bluetech
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review @Zac-HD. I applied (some) of your suggestions. Also rebased.
|
|
||
| def add_funcarg_pseudo_fixture_def(collector, metafunc, fixturemanager): | ||
| def add_funcarg_pseudo_fixture_def( | ||
| collector, metafunc: "Metafunc", fixturemanager: "FixtureManager" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I'm not sure of something, and too lazy to check/verify, I leave it unannotated. Usually some later PR adds it :)
| values.reverse() | ||
| return values | ||
| values.append(fixturedef) | ||
| assert isinstance(current, SubRequest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know, once the assert is in, the implication is reversed -- the access is legal because of the assert, not the other way :)
| self, | ||
| request: "FixtureRequest", | ||
| scope: "_Scope", | ||
| param, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, this one can also be NOTSET, and I'd like to distinguish it in the type annotation from just an object (although object subsumes everything) just for clarity.
I think there is another PR that does that although I sort of lost track myself already 👣
|
|
||
|
|
||
| def _eval_scope_callable(scope_callable, fixture_name, config): | ||
| def _eval_scope_callable(scope_callable, fixture_name: str, config: Config) -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer to leave this one for for later.
|
|
||
| def getfixtureclosure(self, fixturenames, parentnode, ignore_args=()): | ||
| def getfixtureclosure( | ||
| self, fixturenames: Tuple[str, ...], parentnode, ignore_args: Sequence[str] = () |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure, I prefer to leave this one.
| # display it now and during the teardown (in .finish()). | ||
| if fixturedef.ids: | ||
| if callable(fixturedef.ids): | ||
| fixturedef.cached_param = fixturedef.ids(request.param) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm not sure it's worth it.
Extracted from #6717.
Depends/based on #6737.