typeshed
typeshed copied to clipboard
Document mypy version requirement in third-party stubs
Change #6685 switched to using tuple[Any, ...] instead of Tuple[Any, ...] (and list instead of List) in the types-mock package. This feature is only available in python3.9+ (see: https://mypy.readthedocs.io/en/stable/builtin_types.html#generic-types), leading to spurious error: Tuple index out of range when type-checking under python3.8
Do you use mypy==0.930?
Do you use
mypy==0.930?
Using mypy==0.910.
If you upgrade to 0.930, mypy should be fine with the new syntax in stub files, even if you're running Python 3.8. Stub files have different rules to .py files.
Thanks, mypy==0.930 seems to fix this issue. Might be worth calling out in documentation somewhere?
I think it would be reasonable to document this somewhere, either stub-specifically or in a way that applies to all stubs. Even though mypy is just one of the tools that use typeshed, it is important.
stub_uploader could add a line "These stubs have been tested with mypy A.BCD, pytype YYYY.MM.DD, and pyright A.B.CDE." (gathered from requirements.txt and tests/pyright_test.py) to the description.
When we edit requirements-tests.txt, should the uploader reupload all stubs only because the versions changed?
That shouldn't be necessary, I think, but I don't particularly mind either way.
Per #9690, I think it would be reasonable to have a grace period following a mypy release during which breaking changes in third-party stubs aren't released yet. Otherwise the breaking changes may make it harder to actually upgrade mypy in downstream projects.
It would be great if we could somehow encode breaking changes in the type stub version numbers, but I unfortunately don't see a good way to do that with the version number formats Python allows.
I think you could have an interleaved (upstream major).(typeshed major).(upstream minor).(typeshed minor)... version, and that would likely let you do pins that have semantic meaning. But such a versioning scheme would be very confusing for users, so they probably wouldn't do such pins in practice. It's also a little unclear what a semantic version would be for a type stub. So I'm -1 on my own idea.
npm/node has optionalDependencies that can be specified in package.json. Allowing you to specify ranges on other co-installed dependencies, without forcing them to be installed.
Does python's requirements system / pip have a way to specify such dependencies? Maybe as extras? The same idea could generally be useful in stubs to type and test optional dependencies without having the stubsuploader mark them as required dependencies of the stubs.
It wouldn't cover pyright, but honnestly there's not much that can be done there anyway given it's a node module. (and the only non-python-based python type checker afaik). Edit: actually there's a python wrapper for pyright, so there's that.
I think people who care about not having new type checking failures from a stub version should pin their stubs exactly / this knowledge is somewhat widespread. Extras is worth thinking about, but I don't think there's a trick to be found that isn't horribly surprising and/or does the wrong thing a lot of the time.
To me, the most actionable things are:
- Document support. We should change stub_uploader to mention which type checker versions typeshed is currently testing with.
- Have a grace period for changing which type checker versions typeshed is testing third party stubs with.
In today's world, I'm fine with this being an aggressively short grace period, maybe of say 1-2 weeks. I think even such a short grace period would help dependent typing projects or people like me who don't pin stubs. As the ecosystem matures, we can consider extending that period if it proves a persistent painpoint.
Finally, we shouldn't have third party stubs depend on a type checker bundled _typeshed, but instead a separate PEP 561 package. _typeshed should only be used in standard library. But we can discuss that on https://github.com/python/typing_extensions/issues/6
We now include the latest type checker version a type package has been tested with in the long description. This is probably the best we can do at this point.
This is probably the best we can do at this point.
Another thing we could possibly also do would be to define "compatible-mypy", "compatible-pyright" and "compatible-pytype" extras for our stubs packages. This is something django-stubs does: https://github.com/typeddjango/django-stubs/blob/deae5eebd10b88c66bdca25e8fc6f7e332fcc510/setup.py#L34-L36
The idea is that if users opt into the compatible-mypy extra, it'll be impossible to install the stubs unless it's installed into the same environment as a mypy version that's known to be compatible with these stubs.
@sobolevn, do you know how popular the compatible-mypy extra is with users of django-stubs? If it would just be extra maintenance work for us and not very useful for users, we obviously shouldn't do it
I don't know. This stat is not available: https://pypistats.org/packages/django-stubs But, it is the default, so I guess it is widely used.
Determining the minimum and maximum mypy version supported isn't straightforward though. So in django-stubs we just support one mypy major version at a time (e.g. mypy 1.3.x). But I suspect this approach won't scale when lots of stubs packages are in use and they have different mypy requirements.