Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 twine.commands.check #608
Add type annotations to twine.commands.check #608
Changes from all commits
703414e
4879261
ebd2ada
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
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.
Why are we getting less specific here?
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.
In fa5ba3b, I used a
cast
on one of the dictionary values:Because
cgi.parse_header
expects astr
, not theUnion[...]
. This led me to investigate how theMetadataValue
alias is used. One place isRepository._convert_data_to_list_of_tuples
:twine/twine/repository.py
Lines 105 to 108 in 7111240
However, to my eye, nothing about that code requires the strictness of
MetadataValue
.Also, I've seen the
Dict[str, Any]
idiom recommended by Guido for dictionaries with mixed types(e.g. JSON) and I've used it in at least one other place:twine/twine/repository.py
Lines 74 to 75 in 8765d14
Ultimately, this change feels more readable/comprehensible to me. I think the ideal solution might be
TypedDict
in Py 3.8 and/or type hints forpkginfo
.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 issue seems to be more tied to JSON than anything (by my skimming). I'd argue that
Any
is a barely valuable annotation and its main value is in "I haven't figured out what this should be right now". I don't understand how castingdescription_content_type
to a string led us down this road, because that's exactly one of the values.I would also think that
pkginfo
is popular enough that there should already be some stubs for it, if not, it still seems like a valuable thing to haveThere 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've been trying to avoid
cast
as a smell, though I have used it in a few places where mypy required it, e.g. when we know anOptional[str]
is actually astr
:twine/twine/commands/upload.py
Line 60 in 2cec216
I think it provides value to the reader indicating that "this value could be anything, so be careful". I also think how widely it's used is a matter of style, and it's more common when applying annotations to existing codebases.
https://mypy.readthedocs.io/en/stable/kinds_of_types.html#the-any-type
https://mypy.readthedocs.io/en/stable/casts.html
Do you feel strongly about this? I don't see much value in being so specific here, because it doesn't tell the reader or mypy enough to know what the runtime value of these dictionary keys will actually be. To me, that makes it just another thing that the reader has to look up.
Looking into this (and other missing imports) is on the roadmap for subsequent PR's: #231 (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.
I also have used
cast
in a similar way in https://github.com/pypa/twine/blob/master/twine/commands/register.py#L25 while adding type annotations.I was wondering if assigning a value to
repository_url
if it is None might be a good idea rather than casting it. (I have assigned a value 'any', but I think any other standard value might be applicable here.I also saw a similar approach taking place in
twine/wininst.py
twine/twine/wininst.py
Lines 19 to 25 in d0ccb0c
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 feel strongly enough to block the PR, but I would like us to converge, eventually, on types that are of use to us and anyone else even if they seem to not convey they actual value of a dictionary. In general, I'd say something is better than nothing.
I'm also worried that we've released
MetadataValue
and people are usingtwine.package
(which I think is a documented part of the API) and thus we're causing problems for others usin gmypy and our bare-bones annotationsThere 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.
(One of these days I'll anticipate the API argument)
Just pushed ebd2ada, which feels like a good compromise to me. I kept the relaxed signature of
_convert_data_to_list_of_tuples
:twine/twine/repository.py
Line 106 in ebd2ada
That removed the need for the awkward
Tuple[str, IO, str]
, which is never actually stored inmetadata_dictionary
, but rather appended to the list of tuples:twine/twine/repository.py
Lines 152 to 159 in ebd2ada
Leaving us with:
twine/twine/package.py
Line 48 in ebd2ada
So, yeah, glad I took a closer look at this. Thanks. 😉
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.
So we've had complaints from people that they've uploaded things they didn't intend to as well as to places they didn't intend to. Placing a standard value in
repository_url
to satisfy mypy doesn't seem safe to me. Sorry I didn't see your comment earlier, @deveshksThere 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.
@deveshks I think your use of
cast
is appropriate, and I've used it that way as well.Basically, given
my_dict: Dict[str, Optional[str]]
, withcast(str, my_dict["key"])
, we're saying: "at this point in the code, I'm confident that a) "key" is inmy_dict
and b) it's value is astr
and notNone
". Having that confidence requires us to reason about the logic up to that point, but in the cases I've seen so far, it's seemed safe (and sometimes obvious from the context).