Skip to content

Add stubs for docopt package #5248

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

Merged
merged 2 commits into from
Apr 24, 2021
Merged

Add stubs for docopt package #5248

merged 2 commits into from
Apr 24, 2021

Conversation

NickCrews
Copy link
Contributor

Add the single stub for the simple, but fairly well-used
docopt package.
It looks like that project is not very well maintained,
so I thought it would be easier to add the type annotations
here, as opposed to there, upstream. This has even been requested a few
times in docopt/docopt#471. It appeared to me
that only the docopt() function is the public API, so I didn't include
the rest of the module's functions and attributes.

I believe that this stub is totally correct, except for one edge case: In https://github.com/docopt/docopt/blob/20b9c4ffec71d17cee9fd963238c8ec240905b65/docopt.py#L569
you can see that the argv argument can not only be a list, but argv
could also be a type which supports a split() function:

from typing_extensions import Protocol

class _SplittableToStr(Protocol):
    def split(self, *args: Any, **kwargs: Any) -> Iterable[str]: ...

However, I'm not sure I got that correct, and I decided (it's a guess)
that not many users would use anything but a list[str] for argv, so
I just kept it simple and didn't include that Protocol stuff.

@github-actions
Copy link
Contributor

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

@NickCrews
Copy link
Contributor Author

NickCrews commented Apr 24, 2021

Please review and let me know what needs improvement, this is my first time getting into types and typeshed!

For instance, I didn't understand how your tests work (I ran them, but wasn't exactly sure what they did), and I wasn't sure how to actually verify that these definitions are compatible with the actual docopt source. They work in my one test case locally, but that's not particularly rigorous.

Thanks!

@Akuli
Copy link
Collaborator

Akuli commented Apr 24, 2021

They work in my one test case locally, but that's not particularly rigorous.

Don't worry too much about tests. We don't have unit tests for everything, and that's intentional. See #1339 for discussion.

If you know an open-source project that uses mypy and docopt, you can add it to mypy_primer. It runs for all typeshed pull requests, and that way we can be sure that pull requests don't break the docopt stubs.

Personally, I don't run most of typeshed's tests locally, because they run on pull requests anyway.

@github-actions
Copy link
Contributor

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

@Akuli
Copy link
Collaborator

Akuli commented Apr 24, 2021

Nit: If possible, don't --amend or squash your commits. This way I can more easily see what exactly you changed. Everything will be combined into a single commit when merging.

Add the single stub for the simple, but fairly well-used
[docopt](https://github.com/docopt/docopt) package.
It looks like that project is not very well maintained,
so I thought it would be easier to add the type annotations
here, as opposed to there, upstream. This has even been requested a few
times in docopt/docopt#471. It appeared to me
that only the `docopt()` function is the public API, so I didn't include
the rest of the module's functions and attributes.

I believe that this stub is totally correct, except for one edge case: In https://github.com/docopt/docopt/blob/20b9c4ffec71d17cee9fd963238c8ec240905b65/docopt.py#L569
you can see that the `argv` argument can not only be a an `Iterable[str]`,
but `argv` could also be a type which supports a `split()` function:

```
from typing_extensions import Protocol

class _SplittableToStr(Protocol):
    def split(self, *args: Any, **kwargs: Any) -> Iterable[str]: ...
```

However, I'm not sure I got that correct, and I decided (it's a guess)
that not many users would use anything but a `list[str]` for `argv`, so
I just kept it simple and didn't include that Protocol stuff.
@github-actions
Copy link
Contributor

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

@NickCrews
Copy link
Contributor Author

Nit: If possible, don't --amend or squash your commits. This way I can more easily see what exactly you changed. Everything will be combined into a single commit when merging.

Oops, sorry, just did that again. Also makes sense. I'll keep that in mind for next time!

@NickCrews
Copy link
Contributor Author

If you know an open-source project that uses mypy and docopt, you can add it to mypy_primer. It runs for all typeshed pull requests, and that way we can be sure that pull requests don't break the docopt stubs.

(I haven't read #1339 yet) Won't by definition there not be any projects that use mypy and docopt, since docopt doesn't have types? Or does it work for projects that have their own docopt.pyi stubs or have import docopt # ignore: types comments, and then mypy_primer overrides those configs and uses the typeshed stubs instead?

@Akuli
Copy link
Collaborator

Akuli commented Apr 24, 2021

It seems that most people just # type: ignore instead of writing their stubs, which is good for mypy_primer because it handles that correctly. It sometimes warns about unnecessary # type: ignore comments, and even if you # type: ignore an import, mypy will use the .pyi file if it's available.

@Akuli
Copy link
Collaborator

Akuli commented Apr 24, 2021

I found this with Github's code search.

Copy link
Contributor Author

@NickCrews NickCrews left a comment

Choose a reason for hiding this comment

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

I just looked at somebody's fork of docopt that contains hints and thought maybe we should borrow some of their ideas. I left a review on this PR with specifics.

I found this with Github's code search.

Gotcha, that's neat. That project looks tiny/unmaintained, but I see 44 other projects that might be better candidates for mypy_primer, I'll investigate them.


def docopt(
doc: str,
argv: Optional[Iterable[str]] = ...,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe this could be made slightly more accepting (re: the split() method mentioned in the Commit message) if this was Optional[Union[Iterable[str], str]]?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, that would be better. I suggested a type equivalent to that earlier.

Copy link
Member

Choose a reason for hiding this comment

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

str is an Iterable[str]

Copy link
Collaborator

Choose a reason for hiding this comment

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

While Optional[Iterable[str]] is technically correct, it doesn't make it obvious that the hasattr(thing, 'split') was considered when writing the stubs. That's why I preferred to be explicit.

In some cases, mypy specifically disallows relying on that (a, b = some_string doesn't work, for example), but I'm not sure if that applies here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@JelleZijlstra indeed that's true, but do you think that maybe is a bit too clever? I think listing them out separately might be more intuitive to people, e.g. ["--time", "5"] as well as "--time 5" both work?

It can now be a `str` in addition to being a
`Iterable[str]`.
@github-actions
Copy link
Contributor

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

@hauntsaninja
Copy link
Collaborator

FYI, mypy_primer has been broken for third party stubs since modular typeshed. I should get around to fixing it.

@Akuli Akuli merged commit 761bd6e into python:master Apr 24, 2021
@NickCrews
Copy link
Contributor Author

Thanks @Akuli, @hauntsaninja @JelleZijlstra 😄!

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.

4 participants