Skip to content
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

Add type hints to twisted.internet.defer #1448

Merged
merged 62 commits into from Mar 17, 2021
Merged

Add type hints to twisted.internet.defer #1448

merged 62 commits into from Mar 17, 2021

Conversation

wsanchez
Copy link
Member

@wsanchez wsanchez commented Oct 14, 2020

Contributor Checklist:

@wsanchez wsanchez self-assigned this Oct 14, 2020
@wsanchez wsanchez marked this pull request as draft October 14, 2020 17:50
@arnimarj

This comment has been minimized.

@wsanchez

This comment has been minimized.

@wsanchez

This comment has been minimized.

@wsanchez

This comment has been minimized.

Comment on lines +1551 to +1554
gen: Union[
Generator[Deferred[_T], object, None],
Coroutine[Deferred[_T], object, None],
],
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repeating a comment from @mstojcevich in @glyph's suggestion PR here so we don't lose it:

Is None correct for the generator/coroutine return type for these? I think it should be Optional[object] since this handles pulling the value off of StopIteration(x) when the generator returns x.

And I don't think YieldType is necessarily a Deferred when gen is a Generator.

I think the same concerns apply to the original PR fwiw.

@wsanchez
Copy link
Member Author

Regarding code coverage: I've added tests for some new code here in aa46f26. The rest is pre-existing issues that are kind of out-of-scope for this PR.

I did try to address one of those here: #1517

@wsanchez
Copy link
Member Author

Now that Twisted exports type hints, I'm seeing errors in my projects like:

error: Returning Any from function declared to return "Deferred"  [no-any-return]

Because, for example, Deferred.fromFuture() isn't typed, but other parts of Twisted are. It would really be great to move thing PR along…

@glyph
Copy link
Member

glyph commented Mar 15, 2021

Now that Twisted exports type hints

To be honest, I'm wondering if we should roll this back. Our type hints are in pretty rough shape, and are definitely going to be evolving over the next couple of releases. Is there a way to make this easily opt-in for mypy consumers?

Copy link
Member

@glyph glyph left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you could close a couple more of the coverage gaps (mainly the uncovered code, and the _ConcurrencyPrimitive changes) I think this looks good to me! I suspect we'll find some issues once it lives in the wild, but this looks like a solid first cut.

src/twisted/internet/defer.py Outdated Show resolved Hide resolved
src/twisted/internet/defer.py Show resolved Hide resolved
src/twisted/internet/defer.py Show resolved Hide resolved
Comment on lines 920 to 922
# type note: base class "Awaitable" defined the type as:
# Callable[[], Generator[Any, None, _DeferredResultT]]
__await__ = __iter__ # type: ignore[assignment]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the issue being ignored here. Isn't this compatible with Awaitable.__await__ ? That would seem to be the whole point?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the full error message:

src/twisted/internet/defer.py:919:17: error: Incompatible types in assignment (expression has type "Callable[[], Deferred[_DeferredResultT]]", base class "Awaitable" defined the type as
"Callable[[], Generator[Any, None, _DeferredResultT]]")  [assignment]

So the issue seems to be that Awaitable expects __iter__ to return a Generator, and not any Iterable. We could make __await__ a generator function, but that kind of seems gratuitous?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it's gratuitous, and if this were new code I'd probably say "let's just make it compatible" but given that I don't want any more runtime changes than necessary, can you just file a typeshed bug and link it here? Given that this works fine at runtime right now this does seem wrong.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, by "this" I mean the stdlib __await__ stub, not our code

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/twisted/internet/defer.py Outdated Show resolved Hide resolved
src/twisted/internet/defer.py Outdated Show resolved Hide resolved
@@ -1966,16 +2173,15 @@ def __init__(self, name, scheduler=None):
if scheduler is None:
from twisted.internet import reactor

scheduler = reactor
scheduler = cast(IReactorTime, reactor)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. This cast seems like it's a problem, but probably not this PR's problem.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem here is that mypy thinks the reactor is ModuleType. It should be fixed in another PR, though I'm not sure what more module voodoo we can do about it.
My guess is that it would really be better if the normal way to get the installed reactor was via a callable and not a weird module import that's really a reactor.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I'd be very happy if Mypy just encouraged us to get rid of the gross from twisted.internet import reactor idiom entirely.

src/twisted/internet/interfaces.py Show resolved Hide resolved
src/twisted/test/test_defer.py Outdated Show resolved Hide resolved
mypy.ini Show resolved Hide resolved
* trunk: (21 commits)
  Update after review.
  Update after review.
  Use self.failureException.
  Update assertions for .todo tests.
  Remove todo tests.
  Update PR template.
  Update after review.
  Push codecov coverage on Win and macOS.
  Cleanup.
  Show deps as part of normal tox run.
  Refactor after review.
  Fix test_maybeDeferredSyncFailure so that the called function returns a Failure instead of returning a Deferred with an errback,
  Add separate test for identical pass-through
  Remove composite action. Run pip freeze on each env.
  Fix tox name for non-ipv6.
  Add empty value.
  Use lists for matrix values.
  Fix matrix include.
  Refactor GHA to fix ipv6 and add nodeps tests.
  Add news fragment
  ...
@wsanchez wsanchez merged commit df9d19c into trunk Mar 17, 2021
@wsanchez wsanchez deleted the 10017-mypy-defer branch March 17, 2021 00:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants