[BEAM-7746] Minor typing updates / fixes#10822
Conversation
|
R: @udim |
df9a769 to
35258c7
Compare
|
R: @robertwb |
35258c7 to
9d5ed3e
Compare
e112249 to
19ba9d8
Compare
robertwb
left a comment
There was a problem hiding this comment.
Just some minor comments, and it looks like there's some lint to fix, but other than that looks good to go.
There was a problem hiding this comment.
Why this change? (And below.)
There was a problem hiding this comment.
hmmm... well, at the time that I made this change I think it resolved an error, but either I am mistaken or something changed in the module. I'm rolling this back.
There was a problem hiding this comment.
I prefer the previous format, where there was single assignment rather than re-assignment. Is there any benefit to typing this?
There was a problem hiding this comment.
I completely agree. Unfortunately, this is a syntax error in mypy:
try:
from apache_beam.runners.dataflow.internal import apiclient # type: Optional[types.ModuleType]
except ImportError:
apiclient = NoneAs is this:
try:
import apache_beam.runners.dataflow.internal.apiclient as apiclient # type: Optional[types.ModuleType]
except ImportError:
apiclient = NoneThe reason is that type comments are (by design) not capable of doing anything that the new PEP 526 variable annotations are not. In other words, this is obviously wrong:
try:
Optional[types.ModuleType]: import apache_beam.runners.dataflow.internal.apiclient as apiclient
except ImportError:
apiclient = NoneIn that context, this makes more sense:
apiclient: Optional[types.ModuleType] = None
try:
from apache_beam.runners.dataflow.internal import apiclient
except ImportError:
passThere was a problem hiding this comment.
My question is why we need to type apiclient as types.ModuleType at all.
There was a problem hiding this comment.
My question is why we need to type apiclient as types.ModuleType at all.
Fair question.
If we don't do this (i.e. as with the original code), we get the following error:
apache_beam/transforms/external_java.py:46: error: Incompatible types in assignment (expression has type "None", variable has type Module) [assignment]
To resolve this, we need to mark apiclient as Optional
why can't we save ourselves some headache and leave out of the types.ModuleType part?
apiclient = None # type: Optional
try:
from apache_beam.runners.dataflow.internal import apiclient
except ImportError:
passIf we do this, apiclient will become Optional[Any]
Why can't we ignore the error?
We can, but then mypy will mark the type as non-Optional, and that would remove the added protections that mypy provides against accidentally using the variable when it's None.
Why can't we just add the type comment on the original apiclient = None line?
try:
from apache_beam.runners.dataflow.internal import apiclient
except ImportError:
apiclient = None # type: Optional[types.ModuleType]With this, we get the following error:
apache_beam/transforms/external_java.py:46: error: Name 'apiclient' already defined (by an import) [no-redef]
There is only one opportunity to override/influence the inferred type of a variable: on the first line where it is defined (think of type variable definitions like C/C++, but with python scoping rules). However, apiclient is defined via an import rather than an assignment, which forces us to preface the import with a variable definition.
There was a problem hiding this comment.
I did some more research on this, and I found this mypy issue: python/mypy#1297
It suggests this idiom:
try:
from apache_beam.runners.dataflow.internal import apiclient as _apiclient
except ImportError:
apiclient = None
else:
apiclient = _apiclientThe import is a bit longer and uglier, but it has 2 advantages:
- no need to import
OptionalorModuleType - the idiom I was using was actually making
apiclienta generic ModuleType, dropping all knowledge of the members ofapache_beam.runners.dataflow.internal. That's bad!
The reason this works without explicit Optional annotation that mypy will automatically determine optionality in some cases, like this:
if some_conditional():
x = None
else:
x = 1
reveal_type(x) # Revealed type is 'Union[builtins.int, None]'d16797b to
22b349b
Compare
|
Down to 79 errors! Btw, mypy may have revealed some legitimate errors in a recent change: |
|
Run Python2_PVR_Flink PreCommit |
7852b4b to
b6afeb2
Compare
|
Run Python PreCommit |
|
@robertwb I don't think the test failures are my fault because they were passing before I rebased onto master... |
|
LGTM, tests already failing here: |
b6afeb2 to
1379717
Compare
|
Run PythonLint PreCommit |
|
Do we think this is safe to merge? I've been watching master for something that looks like it could solve the current test problems, and rebasing periodically. |
A few more fixes
f5f4193 to
114bbc4
Compare
|
@udim All tests passing now |
|
Thanks, Chad! merging |
|
Just a quick reminder that we should squash the fixup related commits to keep the history clean based on the committer guide https://beam.apache.org/contribute/committer-guide/#finishing-touches |
|
I want to leave some commits and squash others. There is no way to do that in the GH UI. |
This PR corrects a few problems that have occurred over the past few weeks:
Plus it adds some more type annotations. Nothing too radical or dangerous here.
Thank you for your contribution! Follow this checklist to help us incorporate your contribution quickly and easily:
R: @username).[BEAM-XXX] Fixes bug in ApproximateQuantiles, where you replaceBEAM-XXXwith the appropriate JIRA issue, if applicable. This will automatically link the pull request to the issue.CHANGES.mdwith noteworthy changes.See the Contributor Guide for more tips on how to make review process smoother.
Post-Commit Tests Status (on master branch)
Pre-Commit Tests Status (on master branch)
See .test-infra/jenkins/README for trigger phrase, status and link of all Jenkins jobs.