8000 ENH: add type stubs from numpy-stubs by person142 · Pull Request #16515 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

ENH: add type stubs from numpy-stubs #16515

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 8 commits into from
Jun 9, 2020
Merged

Conversation

person142
Copy link
Member
@person142 person142 commented Jun 6, 2020

Add the type stubs and tests from numpy-stubs. See the mailing list discussion about doing this here:

http://numpy-discussion.10968.n7.nabble.com/Put-type-annotations-in-NumPy-proper-tp47996.html

and also the discussion here:

numpy/numpy-stubs#79

Things this entails:

  • Copy over the stubs (numpy/__init__.pyi, numpy/typing.pyi, and numpy/core/_internal.pyi)
    • The only modification made was removing ndarray.tostring since it is deprecated
  • Update some setup.py files to include pyi files
  • Move the tests from numpy-stubs/tests into numpy/tests
    • Skip them if mypy is not installed (planning on setting up CI in a
      future PR)
    • Add a mypy.ini; use it to configure mypy in the tests
      • It tells mypy where to find NumPy in the test env
      • It ignores internal NumPy type errors (since we only want to consider errors from the tests cases)
    • Some small edits were made to fix test cases that were emitting deprecation warnings
  • Add numpy/py.typed so that the types are picked up in an installed version of NumPy

Still to do in follow up PRs:

Add the type stubs and tests from numpy-stubs. Things this entails:

- Copy over the stubs (numpy/__init__.pyi and
  numpy/core/_internal.pyi)
  - The only modification made was removing `ndarray.tostring` since
    it is deprecated
- Update some setup.py files to include pyi files
- Move the tests from numpy-stubs/tests into numpy/tests
  - Skip them if mypy is not installed (planning on setting up CI in a
    future PR)
  - Add a mypy.ini; use it to configure mypy in the tests
    - It tells mypy where to find NumPy in the test env
    - It ignores internal NumPy type errors (since we only want to
      consider errors from the tests cases)
  - Some small edits were made to fix test cases that were emitting
    deprecation warnings
 - Add numpy/py.typed so that the types are picked up in an
   installed version of NumPy
@@ -0,0 +1,1077 @@
import builtins
Copy link
Member Author

Choose a reason for hiding this comment

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

@@ -0,0 +1,18 @@
from typing import Any
Copy link
Member Author

Choose a reason for hiding this comment

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

@@ -0,0 +1,22 @@
from typing import Any, TYPE_CHECKING
Copy link
Member Author

Choose a reason for hiding this comment

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

@@ -0,0 +1,127 @@
import importlib.util
Copy link
Member Author
@person142 person142 Jun 6, 2020

Choose a reason for hiding this comment

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

Test runner is a copy paste from https://github.com/numpy/numpy-stubs/blob/master/tests/test_stubs.py, but with some modifications:

  • In the numpy-stubs repo the tests were run against an installed version of the stubs (because you can't point at a *-stubs package using MYPYPATH)
  • Now we can use MYPYPATH to point at NumPy in the test env, so do that so that the tests can run in the normal way
  • This does mean that mypy is type checking all of NumPy, so we will get complaints about NumPy internals that we don't want to hear
  • To fix that we use a mypy.ini file that silences them
  • By default errors from inside installed third-party libraries are silenced, so those internal type errors shouldn't bother end-users.

)


@pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed")
Copy link
Member Author

Choose a reason for hiding this comment

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

Skip if mypy isn't installed, since we want to keep typing purely opt-in.

@@ -0,0 +1,64 @@
import sys
Copy link
Member Author

Choose a reason for hiding this comment

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

Copy paste of https://github.com/numpy/numpy-stubs/blob/master/numpy-stubs/typing.pyi.

Next step is to make this available at runtime too.

@@ -0,0 +1,2 @@
mypy==0.770
Copy link
Member Author

Choose a reason for hiding this comment

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

If you install these requirements, then the typing tests should run and pass for you locally (I hope).

Copy link
Member
@mattip mattip left a comment

Choose a reason for hiding this comment

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

This is nice, thanks. I am not sure about the test directory structure, since it layers the tests into the already-existing numpy/tests/*. Maybe they should be in a separate directory like numpy/tests/typing/* and only the numpy/tests/test_typing.py left in the upper-level directory?

I think we should add this to the regular CI runs. If it takes too long we could mark it whit @slow. All we need to do then is merge the requirements to the current test_requirements.txt file.

I assume this does not slow down import numpy at all, is that correct?

@@ -0,0 +1,2 @@
mypy==0.770
Copy link
Member
@mattip mattip Jun 7, 2020

Choose a reason for hiding this comment

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

mypy uses parts of the C-API that PyPy has not implemented, so this should be (tested)

Suggested change
mypy==0.770
mypy==0.770; platform_python_implementation != "PyPy"

Edit: tested the qualifier.

Copy link
Member
@rgommers rgommers left a comment

Choose a reason for hiding this comment

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

This approach LGTM, +1 to merge once CI is green.

@person142
Copy link
Member Author
person142 commented Jun 7, 2020

Maybe they should be in a separate directory like numpy/tests/typing/* and only the numpy/tests/test_typing.py left in the upper-level directory?

Done in 3fee17a. Moved the mypy.ini into that dir too.

All we need to do then is merge the requirements to the current test_requirements.txt file.

Done in 744512d.

If it takes too long we could mark it whit @slow

After the cache is warm they aren't too bad, eventually we can pass the cache along as a CI artifact. They also currently invoke mypy once per file, which slows things down (in the stubs this wasn't an issue because there was much less code for mypy to look at). We can speed that up by running mypy once over the entire tests/typing directory in say a pytest module-scoped fixture and then farming the results out to the various checks. tl;dr is they are a little slow right now, but we've got a lot of room for tricks to speed them up.

I assume this does 8000 not slow down import numpy at all, is that correct?

Correct. If you had bunch of annotations not in stubs files then I think it could, though I think that won't be a problem in 3.8 with from __future__ import annotations.

@charris
Copy link
Member
charris commented Jun 7, 2020

Needs a release note.

It currently splits on ":", which causes problems with drives.
@person142
Copy link
Member Author

Needs a release note.

Added in 7c0d99d.

< 579F /td>

@person142
Copy link
Member Author

Ok, getting failures on Python 3.9, but it looks like mypy itself is failing on 3.9 (at least as of writing this):

https://travis-ci.org/github/python/mypy

so I'm probably going to skip these tests on 3.9 for now.

person142 added 2 commits June 7, 2020 18:38
Mypy doesn't work with 3.9 yet, and 3.6 doesn't work because it
doesn't the py.typed marker.
@person142
Copy link
Member Author

Ah, and Python 3.6 doesn't work because py.typed wasn't a thing yet (if you look at the CI failures it is just completely failing to find any type information on the 3.6 run). I've restricted to testing on 3.7 and 3.8.

@person142 person142 added this to the 1.20.0 release milestone Jun 8, 2020
@mattip
Copy link
Member
mattip commented Jun 8, 2020

The travis failure was fixed on master, so restarting this with just the fix for arm64 should get further: no rebase needed.

@person142
Copy link
Member Author

Ok, CI is all green!

@eric-wieser
Copy link
Member

What's the plan for keeping this in sync with numpy-stubs? Is numpy-stubs going to be retired?

@person142
Copy link
Member Author

What's the plan for keeping this in sync with numpy-stubs? Is numpy-stubs going to be retired?

Yes, post-merge I'm planning on updating the numpy-stubs README to point users to the main repo and then archiving numpy-stubs.

@BvB93
Copy link
Member
BvB93 commented Jun 8, 2020

Yes, post-merge I'm planning on updating the numpy-stubs README to point users to the main repo and then archiving numpy-stubs.

If that's the case, might it be an idea to add a dedicated typing label to the numpy repo?

@mattip
Copy link
Member
mattip commented Jun 9, 2020

@BvB93 what is a "dedicated typing label"?

@person142
Copy link
Member Author

I think what is meant is a Github label along the lines of the one @tylerjereddy made for SciPy:

https://github.com/scipy/scipy/pulls?q=label%3A%22static+typing%22+

@mattip mattip merged commit e73c8e5 into numpy:master Jun 9, 2020
@mattip
Copy link
Member
mattip commented Jun 9, 2020

Thanks @person142. Looking forward to seeing how this works

end-users. The currently available types are

- ``ArrayLike``: for objects that can be coerced to an array
- ``DtypeLike``: for objects that can be coerced to a dtype
Copy link
Member

Choose a reason for hiding this comment

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

@person142, sorry for being late to the party. Should we make this DTypeLike with a capital T? I have been using DType for the dtype classes (I guess as a short form of the camel-case DataType. I am happy to use this one as well, would be good to keep it in sync).

Copy link
Member

Choose a reason for hiding this comment

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

That is, unless this actually includes concrete instances, such as strings of specific length. In that case it may actually be better to use different spellings. I would have to review the discussion on that...

Copy link
Member Author

Choose a reason for hiding this comment

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

Hm @seberg could you open an issue? I think “DtypeLike” was originally “things that can be passed into np.dtype“, and with the dtype changes we should think carefully about what makes sense...

@overload
def __array__(self, dtype: DtypeLike = ...) -> ndarray: ...

ArrayLike = Union[bool, int, float, complex, _SupportsArray, Sequence]
Copy link
Member

Choose a reason for hiding this comment

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

do we support __array_interface__ interface for ArrayLike ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants
0