-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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 annotations to astropy.utils.parsing
#16519
Conversation
Thank you for your contribution to Astropy! 🌌 This checklist is meant to remind the package maintainers who will review this pull request of some common things to look for.
|
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.
Looks all OK to me!
Hmm, the
|
p.s. I added a new |
@@ -37,7 +47,7 @@ def _add_tab_header(filename, package): | |||
|
|||
|
|||
@contextlib.contextmanager | |||
def _patch_get_caller_module_dict(module): | |||
def _patch_get_caller_module_dict(module: ModuleType) -> Generator[None, None, 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.
Can't wait for Python 3.13 (https://docs.python.org/3/library/typing.html#typing.Generator)
Changed in version 3.13: Default values for the send and return types were added.
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.
Agreed.
@@ -27,7 +37,7 @@ | |||
_LOCK = threading.RLock() | |||
|
|||
|
|||
def _add_tab_header(filename, package): | |||
def _add_tab_header(filename: str, package: str) -> 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.
These annotations are correct, but I note that internally, the function binds the name f
twice to objects with different types (file buffers with different permissions), which mypy will flag as soon as we turn it on, so I suggest fixing it now rather than later (it suffices to use 2 different variable names).
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'd prefer to keep type annotation pull requests free from any code changes. If the code should be updated then it's better to do that in a separate pull request. Besides, changing the name of one variable does not sound like a big improvement to me. I would rather rewrite this function in its entirety:
def _add_tab_header(filename: Path, package: str) -> None:
contents = filename.read_text()
filename.write_text(_TAB_HEADER.format(package=package))
filename.open('a').write(contents)
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.
Agreed with @eerovaher here; better to have no code changes in typing PRs (and, really, if mypy
cannot handle temporary variables like here, then perhaps it needs to be fixed...)
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 think any static analyzer handles mutating types without a prior declaration of a type union.
e..g
a: Union[str, int]
a = "a"
a = 1
I also don't think that's something that should be fixed!
Dynamism, like most tools, is both useful and dangerous. I think mutating types in-place is more on the dangerous side than useful. Renaming a variable (out-of place mutation) is both easy and safe. Static type checks should catch this.
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.
Agreed with @nstarman . I mostly wanted to raise awareness that by adding annotations before enabling type-checking would create technical debt in the form of more errors to be fixed to get type-checking started instead of less (well, not sure what the net change will be). But the current approach is still better than not addressing type hints at all, and it reached some kind of consensus.
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 also note, for closure, that @eerovaher's effort in reducing long functions might compensate for this specific kind of new "errors" at type-checking time: the probability that a variable name be used for more than one type is greatly increased in long scopes.
The documentation build failures are indeed related. Usually we would deal with this by adding more exceptions to |
A good example found in the wild. |
But what I don't understand is why it being in the documentation is a problem? I thought the issue elsewhere is that we have two places where classes are documented, and sphinx+typing cannot deal with that. But here we have only one place, don't we? So what actually goes wrong? |
There is more than one reason why type annotation pull requests might have to wrestle with Sphinx, but it looks to me like in this case the problem is our fault. If there are type annotations in a function signature then Sphinx tries to turn them into hyperlinks to the relevant types (see e.g. astropy.units.format.Console.to_string()). Sphinx has a bug which means that (sometimes?) it can't figure out what type an annotation is referring to if the type was imported in an We have two documentation warnings and the causes are similar. One is that Similarly, we seem to have declared |
Ah, thanks for digging into that! I am sure we should not start documenting stuff in p.s. This module is also one of the least public ones of all of |
Adding nitpick exceptions would indeed suppress the warnings during documentation build, but as I've already explained it is a bad solution. To highlight the real problem again (regarding |
Yes, it is not quite right, but do we really care? At some point perfection becomes the enemy of good enough. I don't think it makes sense to remove the module from the documentation, since that effectively makes this PR an API change (and even if we do it separately feels very much like the tail wagging the dog), so one is left with the nitpick exceptions or not adding the relevant typing information. My sense is that a nitpick exception is the best way forward - they can be removed when we get around to unbundling |
I agree that this PR doesn't need to tackle this question and a nitpick exception sounds like a good-enough temporary solution. It's good in and of itself to get this module typed, even if that uncovered some problems. |
1566f33
to
563a219
Compare
563a219
to
1df89ab
Compare
I can agree that this pull request should focus on adding type annotations, but having a paradoxical API is not good. |
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.
Great, let's get this in!
Description
The parsing utilities are used by unit formatters, so I am asking the
units
maintainers to review.