-
-
Notifications
You must be signed in to change notification settings - Fork 51
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
Cannot use numpy.typing.NDArray type hints #42
Comments
Fantastic find. Thanks so much for the heads up on this, Antyos. Tensor typing is in our critical section, which makes this a high-priority feature request for us. Fortunately, NumPy developers sensibly implemented their high-level
Unfortunately, NumPy developers kinda non-sensibly reimplemented the same
If they'd just made But... that's mostly okay. Under:
Curious Bear hopes that sounds like a reasonable compromise. |
This sounds great! Glad to see this will be supported! It's unfortunate that this won't work with Python < 3.9, but I understand why and agree with your decision. Is there a Unfortunately, the project I'm working on is stuck on 3.8 due to certain dependencies but being compatible with later versions. However, I'm looking forward to implementing beartype in future projects or when my current project can be updated. |
...I share this disappointment. Gatekeeping Come to think, there might actually be a circuitous way for us to slyly detect
My eyes... they bleed. So,
Sadly, no! But at least I get to blame someone else again. In this case, PEP 585 authors are to blame; they failed to backport support for the But this must be your lucky GitHub day.
I definitely get that and feel your radiating dev pain. Would We aim to please data scientists here. If we ever stop doing that, we have failed in our primary mission... and the bear doesn't tolerate failure. Let me know what you need and we'll make it so. |
You weren't kidding about this being my lucky GitHub day, wow! All of this sounds amazing and will absolutely be adding beartype to this project and probably all my future projects too. I'm looking forward to the update! P.S. Why are you so amazing??? 🤩 |
awwww 🤗 Why are you so incredibly nice, that's what I want to know! Relatedly, I actually thought of an even
I horrify even myself. 🙀 |
That has to be one of the most elegant hideous line of code I have ever laid eyes on. 😂 |
This commit is the first in a commit chain adding portable support for the third-party PEP-noncompliant `numpy.typing.NDArray` type hint newly introduced with NumPy >= 1.21.0, en route to resolving issue #42 kindly submitted by NumPy extraordinaire @Antyos. Specifically, this commit improves the robustness of type hint classification performed by the `beartype._util.hint.pep.utilhintpepget.get_hint_pep_sign_or_none()` getter, which now supports classification of third-party type hints in general `numpy.typing.NDArray` type hints in specific. (*Disastrous asters!*)
So... It Begins. fcb24d3 now detects We don't. Yes, the solution is both brilliant and yet stupid at the same time! We just internally map
The last trick up my hipster flannel will be differentiating between:
Let's see how much caffeine I can inject straight into my varicose veins this Friday evening. ☕ ☕ ☕ |
This commit is the next in a commit chain adding portable support for the third-party PEP-noncompliant `numpy.typing.NDArray` type hint newly introduced with NumPy >= 1.21.0, en route to resolving issue #42 kindly submitted by NumPy extraordinaire @Antyos. Specifically, this commit defines a new `beartype._util.hint.pep.utilpepattr` submodule and `import_typing_attr()` function dynamically importing and returning type hint factories like `Annotated` from whichever of the `typing` and `typing_extensions` modules (in that order) declare those factories. (*Basic acidification edifies efficacious eddies!*)
This commit is the next in a commit chain adding portable support for the third-party PEP-noncompliant `numpy.typing.NDArray` type hint newly introduced with NumPy >= 1.21.0, en route to resolving issue #42 kindly submitted by NumPy extraordinaire @Antyos. Specifically, this commit refactors the pivotal `beartype._util.hint.pep.utilpeptest.is_hint_pep()` tester to defer to the even-more-pivotal `beartype._util.hint.pep.utilpeptest.get_hint_pep_sign_or_none()` getter, dramatically streamlining detection of PEP-compliant type hints. (*Misbegotten hierophants misfire triumphantly!*)
This commit is the next in a commit chain adding portable support for the third-party PEP-noncompliant `numpy.typing.NDArray` type hint newly introduced with NumPy >= 1.21.0, en route to resolving issue #42 kindly submitted by NumPy extraordinaire @Antyos. Specifically, this commit defines a new `beartype._util.hint.get_hint_reduced()` function centralizing type hint reduction logic previously duplicated (*gulp*) throughout the codebase as well as declaring a new `beartype._util.hint.nonpep.mod` subpackage, `beartype._util.hint.nonpep.mod.utilnonpepnumpy` submodule, and `get_hint_numpy_ndarray_dtype()` getter in that submodule safely retrieving the dtype subscripting `numpy.typing.NDArray` type hints. (*Quixotic coterie!*)
Great success. I accidentally closed this with a commit message yesterday, but that's possibly okay because I'm fairly certain that ...at least, we would rejoice if I hadn't used weasel words like "accidentally," "possibly okay", and "fairly certain" above. I should really exhaustively test this a bit more and then write readable documentation. Why is that always a challenge? ...the struggle is real I'm aiming to release both this and #34 – yup, it's full |
This commit is the next in a commit chain adding portable support for the third-party PEP-noncompliant `numpy.typing.NDArray` type hint newly introduced with NumPy >= 1.21.0, en route to resolving issue #42 kindly submitted by NumPy extraordinaire @Antyos. Specifically, this commit resolves all pending issues in our private `beartype._util.hint.nonpep.mod.utilmodnumpy.reduce_hint_numpy_ndarray()` function as well as testing this function with a rudimentary unit test. Additional testing and documentation is still warranted, because safety first saves codebases. (*Scorched excoriation!*)
This commit is the next in a commit chain adding portable support for the third-party PEP-noncompliant `numpy.typing.NDArray` type hint newly introduced with NumPy >= 1.21.0, en route to resolving issue #42 kindly submitted by NumPy extraordinaire @Antyos. Specifically, this commit significantly improves testing of our private `beartype._util.hint.nonpep.mod.utilmodnumpy.reduce_hint_numpy_ndarray()` function. Additional testing and documentation is still warranted, because safety first saves codebases. (*Decorative oratory!*)
This commit is the next in a commit chain adding portable support for the third-party PEP-noncompliant `numpy.typing.NDArray` type hint newly introduced with NumPy >= 1.21.0, en route to resolving issue #42 kindly submitted by NumPy extraordinaire @Antyos. Specifically, this commit finalizes improves testing of our private `beartype._util.hint.nonpep.mod.utilmodnumpy.reduce_hint_numpy_ndarray()` function. Additional documentation is still warranted, because safety first saves codebears. (*Betides eventide!*)
This commit is the next in a commit chain adding portable support for the third-party PEP-noncompliant `numpy.typing.NDArray` type hint newly introduced with NumPy >= 1.21.0, en route to resolving issue #42 kindly submitted by NumPy extraordinaire @Antyos. Specifically, this commit safeguards our critical `beartype._util.mod.utilmodimport.import_module_attr_or_none()` importer against common edge cases, including the unimportability of the passed module – which now safely emits the new non-fatal `BeartypeModuleUnimportableWarning` rather than unsafely raising a fatal exception. Additional documentation is still warranted, because safety first saves codebears. (*Dramatically rambling llamas!*)
This release brings undeniable support for **typed NumPy arrays** (i.e., `numpy.typed.NDArray` type hints), **typing backports** (i.e., public public attributes of the third-party `typing_extensions` package, enabling typing_ types introduced by newer Python versions to be used under older Python versions), and **portable beartype validators** (i.e., `beartype.vale` type hints usable under *all* Python versions via the `typing_extensions.Annotated` backport). This release resolves **4 issues** and merges **2 pull requests.** Changes include: ## Compatibility Improved * **Typed NumPy arrays** (i.e., `numpy.typed.NDArray` type hints). The `@beartype` decorator now transparently supports the third-party `numpy.typing.NDArray` type hint newly introduced by NumPy >= 1.21.0, resolving issue #42 kindly submitted by NumPy extraordinaire @Antyos. Note that usage of typed NumPy arrays under Python < 3.9.0 requires installation of the third-party `typing-extensions` package, which `@beartype` will then automagically detect and leverage internally. * **Typing backports** (i.e., `typing_extensions` type hints). The `@beartype` decorator now transparently supports all public type hints of the third-party `typing_extensions` package, resolving issue #34 kindly submitted by Ryan Soklaski (@rsokl) of considerable *MIT Beaver Works Summer Institute* and *Python Like You Mean It* fame. Note that usage of typed NumPy arrays under Python < 3.9.0 requires installation of the third-party `typing-extensions` package, which `@beartype` will then automagically detect and leverage internally. * **Python < 3.9.0 beartype validators.** The `@beartype` decorator now portably supports **beartype validators** (i.e., `beartype.vale` objects annotating `typing{_extensions}.Annotated` type hints) across all Python versions, *also* resolving issue #34 kindly submitted by Ryan Soklaski (@rsokl). <sup>hallowed be his username</sup> Note that usage of beartype validators under Python < 3.9.0 requires: * Installation of the third-party `typing-extensions` package. * Annotation of `beartype.vale` objects by `typing_extensions.Annotated` (rather than `typing.Annotated`). * **Python >= 3.10.0 `typing.NewType` type hints.** This release resolves a minor incompatibility recently introduced by Python 3.10.0rc1, which (*waitforit*) broke backward compatibility with prior implementations of the public `typing.NewType` type hint. Previously, that hint was implemented as a closure; Python ≥ 3.10 fundamentally refactored that hint to a pure-Python class instance – significantly complicating cross-version detection. *yuwastemytime,* CPython? * **Binary dunder method return annotations** (i.e., dunder methods accepting exactly two arguments). Previously, `@beartype` adopted mypy's permissive approach of implicitly coercing the return annotations of binary dunder methods returning only booleans to instead return `typing.Union[bool, type(NotImplemented)]`. `beartype` now expands that approach to *all* binary dunder methods regardless of return annotation. Thanks to pull request #40 from Matt Bogosian (@posita), Dropbox's positive code genius! ## Compatibility Broken * **None.** This release preserves backward compatibility with the prior stable release. ## Issues Resolved * **#44,** documenting beartype's new project shield generously ginned up by Matt Bogosian (@posita), Dropbox's positive code genius. * **#42,** enabling typed NumPy arrays to be used under both Python ≥ 3.9.0 natively *and* Python < 3.9.0 via the `typing_extensions.Annotated` backport. * **#40,** including: * **Fake builtin types** (i.e., non-builtin classes erroneously masquerading as builtin). Previously, `@beartype` incorrectly generated syntactically invalid code for decorated callables annotated by one or more fake builtin types – which, miraculously, there are hardly any of. Still... *it's not a good look, beartype.* Thanks to Matt Bogosian (@posita), Dropbox's positive code genius, for first detecting this horrifying edge case in pull request #40. * **#34,** enabling beartype validators to be used under Python < 3.9.0 via the `typing_extensions.Annotated` backport. ## Documentation Revised * **Badge** (i.e., shield intended for display by downstream projects). Our front-facing `README.rst` documentation now provides a post-installation advisory suggesting public declaration of @beartype project compatibility with reST- and Markdown-friendly text exhibiting a beautiful @beartype badge. Unsurprisingly, @posita made that too... because what doesn't @posita do? Nuthin'! I'm pretty sure that means @posita does everything. ## Tests Improved * **Optional dependencies.** Our GitHub Actions-based continuous integration (CI) configuration now installs optional test-time dependencies. Although `beartype` has *no* mandatory runtime dependencies, fully exercising all tests necessitates installing these test-time dependencies: * mypy, enabling tests for mypy-based PEP 561 compliance. * NumPy, enabling tests for `numpy.typing.NDArray` type hints. This proved surprisingly non-trivial. Apple's patently broken "Accelerate" BLAS replacement (as documented at numpy/numpy#15947) blocks NumPy ≥ 1.18.0 installation under default CI configurations, necessitating that we: * Only conditionally install `pip` packages with `--force-reinstall` under macOS. CI gonna CI. * Avoid installing NumPy altogether under macOS + PyPy, where even the `--force-reinstall` option fails to improve matters. You can only do so much when your core platform is fundamentally broken. Thanks, Apple. * `typing_extensions`, enabling tests for `typing` attributes unavailable under the active Python interpreter. Thanks yet again to Badge Connoisseur @posita for his tremendous efforts – which we are now eternally indebted to and can only repay across the span of several gruelling lifetimes. "It will all be worth it," I tell my future self. (*Clogged clogs and unlogged cogs!*)
It is so nice to see the impressive pace at which beartype is developing! Now that NDArray is supported by the latest release, one could add the support of ArrayLike to the roadmap. Just in case you are running out of todos ;) Here an example code executed with py3.8 and beartype 0.8.0: import numpy as np
from beartype import beartype
from numpy.typing import ArrayLike
@beartype
def foo(arr: ArrayLike[np.float64]) -> None:
return
foo(np.zeros(3).astype(np.float64)) Raises following error: Traceback (most recent call last):
File "asarray.py", line 6, in <module>
def foo(arr: ArrayLike[np.float64]) -> None:
File "/home/***/anaconda3/envs/py3.8/lib/python3.8/typing.py", line 261, in inner
return func(*args, **kwds)
File "/home/***/anaconda3/envs/py3.8/lib/python3.8/typing.py", line 686, in __getitem__
_check_generic(self, params)
File "/home/***/anaconda3/envs/py3.8/lib/python3.8/typing.py", line 211, in _check_generic
raise TypeError(f"{cls} is not a generic class")
TypeError: typing.Union[typing.Sequence[typing.Sequence[typing.Sequence[typing.Sequence[typing.Sequence[typing.Any]]]]], numpy.typing._array_like._SupportsArray[ForwardRef('dtype[Any]')], typing.Sequence[numpy.typing._array_like._SupportsArray[ForwardRef('dtype[Any]')]], typing.Sequence[typing.Sequence[numpy.typing._array_like._SupportsArray[ForwardRef('dtype[Any]')]]], typing.Sequence[typing.Sequence[typing.Sequence[numpy.typing._array_like._SupportsArray[ForwardRef('dtype[Any]')]]]], typing.Sequence[typing.Sequence[typing.Sequence[typing.Sequence[numpy.typing._array_like._SupportsArray[ForwardRef('dtype[Any]')]]]]], bool, int, float, complex, str, bytes, typing.Sequence[typing.Union[bool, int, float, complex, str, bytes]], typing.Sequence[typing.Sequence[typing.Union[bool, int, float, complex, str, bytes]]], typing.Sequence[typing.Sequence[typing.Sequence[typing.Union[bool, int, float, complex, str, bytes]]]], typing.Sequence[typing.Sequence[typing.Sequence[typing.Sequence[typing.Union[bool, int, float, complex, str, bytes]]]]]] is not a generic class |
aww, u so nice! 😊
Yes. Let's add ever more back-breaking features onto my drooping shoulders. Actually, I think that's just my bursitis acting up. Curse this geriatric body. 👴 In all seriousness, this is a great idea. So it shall be! I was hoping the remainder of the Lucky for me, the traceback is suggestive of an upstream issue.
Yikes. Let's grep around the NumPy issue tracker and see if we can't find anyone shouting vociferously about similar issues. That exception scares me like only grizzly bears snuffling through our compost pile in October can. 😮 |
👋 Has this support been added to the awesome DOOR api? >>> from beartype import beartype
>>> @beartype
... def foo(t: npt.NDArray[np.float64]):
... print(t)
...
>>> n = np.array([1, 2, 3], dtype=np.float64)
>>> foo(n)
[1. 2. 3.] works great! but... >>> from beartype.door import TypeHint
>>> TypeHint(npt.NDArray[np.float64])
Traceback (most recent call last):
Cell In[40], line 1
TypeHint(npt.NDArray[np.float64])
...
BeartypeDoorNonpepException: Type hint numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]] invalid
(i.e., either PEP-noncompliant or PEP-compliant but currently unsupported by "beartype.door.TypeHint"). Thanks for the great library! |
Agh! Your astute observation is correct; the Fortunately, we already have an issue tracking this feature request! That's the good news. Unfortunately, I'm inclined to play Japanese role-playing games rather than do actual work... That's the bad news. Tune in to issue #212 to see which wins. 🐻 |
…ping and pre Python3.9 in tandem with typing_extensions Annotation Source information: beartype/beartype#42 Annotated checks against instances of _GenericAlias to see if you can support Data[type_info], e.g. NDArray[int] (in Python types since 3.9, and kinda of as _GenricAlias before that.) Prior to 3.9, Numpy implemented their own version of _GenericAlias which isn't Python _GenericAlias, so the types are not considered "Generic" when Annotated[NDArray, Metadata][type_info] does its thing. So. This fix code does the heavy lifting to re-cast the NDArray type with _GenericAlias from python typing. I've tried to reuse as much data from NDArray as I possibly can and still use np.ndarray (which is not np.typing.NDArray) to still correctly type hint np.ndarrays.
Numpy v1.21.0 introduced runtime subscriptable aliases for ndarrays. The feature is really cool and I really like the direction that it seems to be headed in.
However, these new annotations do not seem compatible with the
@beartype
decorator.System info
OS: Windows 10, 20H2
Python: 3.8.10
Beartype: 0.71.0
Numpy: 1.21.0
Sample Code
Running this sample code:
Yields this error:
Knowing that Beartype leverages the Python built-in
Annotated
type, it roughly makes sense why this error would be occurring. While creating a Beartype numpy array usingAnnotated
andlambda
still has its uses, static type checkers such as Pylance/Pyright are now equipped to recognize this new Numpy typing syntax (that's how I initially found out about this change; my code had a ton of new errors I didn't understand), but I don't know if they can recognize the Beartype version in the same way.The text was updated successfully, but these errors were encountered: