diff options
25 files changed, 685 insertions, 339 deletions
diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 5f7afdaaf..b56d596a5 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -206,6 +206,11 @@ stages: PYTHON_ARCH: 'x64' TEST_MODE: full BITS: 64 + PyPy37-64bit-full: + PYTHON_VERSION: 'PyPy3.7' + PYTHON_ARCH: 'x64' + TEST_MODE: fast + BITS: 64 Python38-32bit-fast: PYTHON_VERSION: '3.8' PYTHON_ARCH: 'x86' diff --git a/azure-steps-windows.yml b/azure-steps-windows.yml index 28762f5d9..6a69db753 100644 --- a/azure-steps-windows.yml +++ b/azure-steps-windows.yml @@ -6,7 +6,7 @@ steps: architecture: $(PYTHON_ARCH) condition: not(contains(variables['PYTHON_VERSION'], 'PyPy')) - powershell: | - $url = "http://buildbot.pypy.org/nightly/py3.6/pypy-c-jit-latest-win32.zip" + $url = "http://buildbot.pypy.org/nightly/py3.7/pypy-c-jit-latest-win64.zip" $output = "pypy.zip" $wc = New-Object System.Net.WebClient $wc.DownloadFile($url, $output) diff --git a/doc/neps/nep-0046-sponsorship-guidelines.rst b/doc/neps/nep-0046-sponsorship-guidelines.rst new file mode 100644 index 000000000..cc273ce2c --- /dev/null +++ b/doc/neps/nep-0046-sponsorship-guidelines.rst @@ -0,0 +1,255 @@ +.. _NEP46: + +===================================== +NEP 46 — NumPy Sponsorship Guidelines +===================================== + +:Author: Ralf Gommers <ralf.gommers@gmail.com> +:Status: Draft +:Type: Process +:Created: 2020-12-27 +:Resolution: <url> (required for Accepted | Rejected | Withdrawn) + + +Abstract +-------- + +This NEP provides guidelines on how the NumPy project will acknowledge +financial and in-kind support. + + +Motivation and Scope +-------------------- + +In the past few years, the NumPy project has gotten significant financial +support, as well as dedicated work time for maintainers to work on NumPy. There +is a need to acknowledge that support - it's the right thing to do, it's +helpful when looking for new funding, and funders and organizations expect or +require it, Furthermore, having a clear policy for how NumPy acknowledges +support is helpful when searching for new support. Finally, this policy may +help set reasonable expectations for potential funders. + +This NEP is aimed at both the NumPy community - who can use it as a guideline +when looking for support on behalf of the project and when acknowledging +existing support - and at past, current and prospective sponsors, who often +want or need to know what they get in return for their support other than a +healthier NumPy. + +The scope of this proposal includes: + +- direct financial support, employers providing paid time for NumPy maintainers + and regular contributors, and in-kind support such as free hardware resources or + services, +- where and how NumPy acknowledges support (e.g., logo placement on the website), +- the amount and duration of support which leads to acknowledgement, and +- who in the NumPy project is responsible for sponsorship related topics, and + how to contact them. + + +How NumPy will acknowledge support +---------------------------------- + +There will be two different ways to acknowledge financial and in-kind support: +one to recognize significant active support, and another one to recognize +support received in the past and smaller amounts of support. + +Entities who fall under "significant active supporter" we'll call Sponsor. +The minimum level of support given to NumPy to be considered a Sponsor are: + +- $30,000/yr for unrestricted financial contributions (e.g., donations) +- $60,000/yr for financial contributions for a particular purpose (e.g., grants) +- $100,000/yr for in-kind contributions (e.g., time for employees to contribute) + +We define support being active as: + +- for a one-off donation: it was received within the previous 12 months, +- for recurring or financial or in-kind contributions: they should be ongoing. + +After support moves from "active" to "inactive" status, the acknowledgement +will be left in its place for at least another 6 months. If appropriate, the +funding team can discuss opportunities for renewal with the sponsor. After +those 6 months, acknowledgement may be moved to the historical overview. The +exact timing of this move is at the discretion of the funding team, because +there may be reasons to keep it in the more prominent place for longer. + +The rationale for the above funding levels is that unrestricted financial +contributions are typically the most valuable for the project, and the hardest +to obtain. The opposite is true for in-kind contributions. The dollar value of +the levels also reflect that NumPy's needs have grown to the point where we +need multiple paid developers in order to effectively support our user base and +continue to move the project forward. Financial support at or above these +levels is needed to be able to make a significant difference. + +Sponsors will get acknowledged through: + +- a small logo displayed on the front page of the NumPy website +- prominent logo placement on https://numpy.org/about/ +- logos displayed in talks about NumPy by maintainers +- announcements of the sponsorship on the NumPy mailing list and the numpy-team + Twitter account + +In addition to Sponsors, we already have the concept of Institutional Partner +(defined in NumPy's +`governance document <https://numpy.org/devdocs/dev/governance/index.html>`__), +for entities who employ a NumPy maintainer and let them work on NumPy as part +of their official duties. The governance document doesn't currently define a +minimum amount of paid maintainer time needed to be considered for partnership. +Therefore we propose that level here, roughly in line with the sponsorship +levels: + +- 6 person-months/yr of paid work time for one or more NumPy maintainers or + regular contributors to any NumPy team or activity + +Institutional Partners get the same benefits as Sponsors, in addition to what +is specified in the NumPy governance document. + +Finally, a new page on the website (https://numpy.org/funding/, linked from the +About page) will be added to acknowledge all current and previous sponsors, +partners, and any other entities and individuals who provided $5,000 or more of +financial or in-kind support. This page will include relevant details of +support (dates, amounts, names, and purpose); no logos will be used on this +page. The rationale for the $5,000 minimum level is to keep the amount of work +maintaining the page reasonable; the level is the equivalent of, e.g., one GSoC +or a person-week's worth of engineering time in a Western country, which seems +like a reasonable lower limit. + + +Implementation +-------------- + +The following content changes need to be made: + +- Add a section with small logos towards the bottom of the `numpy.org + <https://numpy.org/>`__ website. +- Create a full list of historical and current support and deploy it to + https://numpy.org/funding. +- Update the NumPy governance document for changes to Institutional Partner + eligibility requirements and benefits. +- Update https://numpy.org/about with details on how to get in touch with the + NumPy project about sponsorship related matters (see next section). + + +NumPy Funding Team +~~~~~~~~~~~~~~~~~~ + +At the moment NumPy has only one official body, the Steering Council, and no +good way to get in touch with either that body or any person or group +responsible for funding and sponsorship related matters. The way this is +typically done now is to somehow find the personal email of a maintainer, and +email them in private. There is a need to organize this more transparently - a +potential sponsor isn't likely to inquire through the mailing list, nor is it +easy for a potential sponsor to know if they're reaching out to the right +person in private. + +https://numpy.org/about/ already says that NumPy has a "funding and grants" +team. However that is not the case. We propose to organize this team, name team +members on it, and add the names of those team members plus a dedicated email +address for the team to the About page. + + +Status before this proposal +--------------------------- + +Acknowledgement of support +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +At the time of writing (Dec 2020), the logos of the four largest financial +sponsors and two institutional partners are displayed on +https://numpy.org/about/. The `Nature paper about NumPy <https://www.nature.com/articles/s41586-020-2649-2>`__ +mentions some early funding. No comprehensive list of received funding and +in-kind support is published anywhere. + +Decisions on which logos to list on the website have been made mostly by the +website team. Decisions on which entities to recognize as Institutional Partner +have been made by the NumPy Steering Council. + + +NumPy governance, decision-making, and financial oversight +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +*This section is meant as context for the reader, to help put the rest of this +NEP in perspective, and perhaps answer questions the reader has when reading +this as a potential sponsor.* + +NumPy has a formal governance structure defined in +`this governance document <https://numpy.org/devdocs/dev/governance/index.html>`__). +Decisions are made by consensus among all active participants in a discussion +(typically on the mailing list), and if consensus cannot be reached then the +Steering Council takes the decision (also by consensus). + +NumPy is a sponsored project of NumFOCUS, a US-based 501(c)3 nonprofit. +NumFOCUS administers NumPy funds, and ensures they are spent in accordance with +its mission and nonprofit status. In practice, NumPy has a NumFOCUS +subcommittee (with its members named in the NumPy governance document) who can +authorize financial transactions. Those transactions, for example paying a +contractor for a particular activity or deliverable, are decided on by the +NumPy Steering Council. + + +Alternatives +------------ + +*Tiered sponsorship levels.* We considered using tiered sponsorship levels, and +rejected this alternative because it would be more complex, and not necessarily +communicate the right intent - the minimum levels are for us to determine how +to acknowledge support that we receive, not a commercial value proposition. +Entities typically will support NumPy because they rely on the project or want +to help advance it, and not to get brand awareness through logo placement. + +*Listing all donations*. Note that in the past we have received many smaller +donations, mostly from individuals through NumFOCUS. It would be great to list +all of those contributions, but given the way we receive information on those +donations right now, that would be quite labor-intensive. If we manage to move +to a more suitable platform, such as `Open Collective <https://opencollective.com/>`__, +in the future, we should reconsider listing all individual donations. + + +Related Work +------------ + +Here we provide a few examples of how other projects handle sponsorship +guidelines and acknowledgements. + +*Scikit-learn* has a narrow banner with logos at the bottom of +https://scikit-learn.org, and a list of present funding and past sponsors at +https://scikit-learn.org/stable/about.html#funding. Plus a separate section +"Infrastructure support" at the bottom of that same About page. + +*Jupyter* has logos of sponsors and institutional partners in two sections on +https://jupyter.org/about. Some subprojects have separate approaches, for +example sponsors are listed (by using the `all-contributors +<https://github.com/all-contributors/all-contributors>`__ bot) in the README for +`jupyterlab-git <https://github.com/jupyterlab/jupyterlab-git>`__. For a recent +discussion on that, see `here <jupyterlab-git acknowledgements discussion>`_. + +*NumFOCUS* has a large banner with sponsor logos on its front page at +https://numfocus.org, and a full page with sponsors at different sponsorship +levels listed at https://numfocus.org/sponsors. They also have a +`Corporate Sponsorship Prospectus <https://numfocus.org/blog/introducing-our-newest-corporate-sponsorship-prospectus>`__, +which includes a lot of detail on both sponsorship levels and benefits, as well +as how that helps NumFOCUS-affiliated projects (including NumPy). + + +Discussion +---------- + +Mailing list thread(s) discussing this NEP: TODO + + +References and Footnotes +------------------------ + +- `Inside NumPy: preparing for the next decade <https://github.com/numpy/archive/blob/master/content/inside_numpy_presentation_SciPy2019.pdf>`__ presentation at SciPy'19 discussing the impact of the first NumPy grant. +- `Issue <https://github.com/numpy/numpy/issues/13393>`__ and + `email <https://mail.python.org/pipermail/numpy-discussion/2019-April/079371.html>`__ + where IBM offered a $5,000 bounty for VSX SIMD support +- `JupyterLab Corporate Engagement and Contribution Guide <https://github.com/jupyterlab/jupyterlab/blob/master/CORPORATE.md>`__ + + +.. _jupyterlab-git acknowledgements discussion: https://github.com/jupyterlab/jupyterlab-git/pull/530 + + +Copyright +--------- + +This document has been placed in the public domain. diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index 656048173..dbf807783 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -7,19 +7,28 @@ from contextlib import ContextDecorator from numpy.core._internal import _ctypes from numpy.typing import ( + # Arrays ArrayLike, + + # DTypes DTypeLike, - _Shape, - _ShapeLike, - _CharLike, - _BoolLike, - _IntLike, - _FloatLike, - _ComplexLike, - _TD64Like, - _NumberLike, _SupportsDType, _VoidDTypeLike, + + # Shapes + _Shape, + _ShapeLike, + + # Scalars + _CharLike_co, + _BoolLike_co, + _IntLike_co, + _FloatLike_co, + _ComplexLike_co, + _TD64Like_co, + _NumberLike_co, + + # `number` precision NBitBase, _256Bit, _128Bit, @@ -39,8 +48,8 @@ from numpy.typing import ( _NBitSingle, _NBitDouble, _NBitLongDouble, -) -from numpy.typing import ( + + # Character codes _BoolCodes, _UInt8Codes, _UInt16Codes, @@ -858,11 +867,11 @@ _PartitionKind = Literal["introselect"] _SortKind = Literal["quicksort", "mergesort", "heapsort", "stable"] _SortSide = Literal["left", "right"] -_ArrayLikeBool = Union[_BoolLike, Sequence[_BoolLike], ndarray] +_ArrayLikeBool = Union[_BoolLike_co, Sequence[_BoolLike_co], ndarray] _ArrayLikeIntOrBool = Union[ - _IntLike, + _IntLike_co, ndarray, - Sequence[_IntLike], + Sequence[_IntLike_co], Sequence[Sequence[Any]], # TODO: wait for support for recursive types ] @@ -1073,7 +1082,7 @@ class _ArrayOrScalarCommon: axis: None = ..., out: None = ..., keepdims: Literal[False] = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> number: ... @overload @@ -1082,7 +1091,7 @@ class _ArrayOrScalarCommon: axis: Optional[_ShapeLike] = ..., out: None = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... @overload @@ -1091,7 +1100,7 @@ class _ArrayOrScalarCommon: axis: Optional[_ShapeLike] = ..., out: _NdArraySubClass = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> _NdArraySubClass: ... @overload @@ -1124,7 +1133,7 @@ class _ArrayOrScalarCommon: axis: None = ..., out: None = ..., keepdims: Literal[False] = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> number: ... @overload @@ -1133,7 +1142,7 @@ class _ArrayOrScalarCommon: axis: Optional[_ShapeLike] = ..., out: None = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... @overload @@ -1142,7 +1151,7 @@ class _ArrayOrScalarCommon: axis: Optional[_ShapeLike] = ..., out: _NdArraySubClass = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> _NdArraySubClass: ... def newbyteorder(self: _ArraySelf, __new_order: _ByteOrder = ...) -> _ArraySelf: ... @@ -1153,7 +1162,7 @@ class _ArrayOrScalarCommon: dtype: DTypeLike = ..., out: None = ..., keepdims: Literal[False] = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> number: ... @overload @@ -1163,7 +1172,7 @@ class _ArrayOrScalarCommon: dtype: DTypeLike = ..., out: None = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... @overload @@ -1173,7 +1182,7 @@ class _ArrayOrScalarCommon: dtype: DTypeLike = ..., out: _NdArraySubClass = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> _NdArraySubClass: ... @overload @@ -1234,7 +1243,7 @@ class _ArrayOrScalarCommon: dtype: DTypeLike = ..., out: None = ..., keepdims: Literal[False] = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> number: ... @overload @@ -1244,7 +1253,7 @@ class _ArrayOrScalarCommon: dtype: DTypeLike = ..., out: None = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... @overload @@ -1254,13 +1263,13 @@ class _ArrayOrScalarCommon: dtype: DTypeLike = ..., out: _NdArraySubClass = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> _NdArraySubClass: ... @overload def take( self, - indices: _IntLike, + indices: _IntLike_co, axis: Optional[int] = ..., out: None = ..., mode: _ModeKind = ..., @@ -1518,8 +1527,8 @@ class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType]): # See https://github.com/numpy/numpy-stubs/pull/80 for more details. _ScalarType = TypeVar("_ScalarType", bound=generic) -_NBit_co = TypeVar("_NBit_co", covariant=True, bound=NBitBase) -_NBit_co2 = TypeVar("_NBit_co2", covariant=True, bound=NBitBase) +_NBit1 = TypeVar("_NBit1", bound=NBitBase) +_NBit2 = TypeVar("_NBit2", bound=NBitBase) class generic(_ArrayOrScalarCommon): @abstractmethod @@ -1553,7 +1562,7 @@ class generic(_ArrayOrScalarCommon): @property def dtype(self: _ScalarType) -> dtype[_ScalarType]: ... -class number(generic, Generic[_NBit_co]): # type: ignore +class number(generic, Generic[_NBit1]): # type: ignore @property def real(self: _ArraySelf) -> _ArraySelf: ... @property @@ -1577,10 +1586,10 @@ class number(generic, Generic[_NBit_co]): # type: ignore __rpow__: _NumberOp __truediv__: _NumberOp __rtruediv__: _NumberOp - __lt__: _ComparisonOp[_NumberLike] - __le__: _ComparisonOp[_NumberLike] - __gt__: _ComparisonOp[_NumberLike] - __ge__: _ComparisonOp[_NumberLike] + __lt__: _ComparisonOp[_NumberLike_co] + __le__: _ComparisonOp[_NumberLike_co] + __gt__: _ComparisonOp[_NumberLike_co] + __ge__: _ComparisonOp[_NumberLike_co] class bool_(generic): def __init__(self, __value: object = ...) -> None: ... @@ -1619,10 +1628,10 @@ class bool_(generic): __rmod__: _BoolMod __divmod__: _BoolDivMod __rdivmod__: _BoolDivMod - __lt__: _ComparisonOp[_NumberLike] - __le__: _ComparisonOp[_NumberLike] - __gt__: _ComparisonOp[_NumberLike] - __ge__: _ComparisonOp[_NumberLike] + __lt__: _ComparisonOp[_NumberLike_co] + __le__: _ComparisonOp[_NumberLike_co] + __gt__: _ComparisonOp[_NumberLike_co] + __ge__: _ComparisonOp[_NumberLike_co] class object_(generic): def __init__(self, __value: object = ...) -> None: ... @@ -1635,21 +1644,21 @@ class datetime64(generic): @overload def __init__( self, - __value: Union[None, datetime64, _CharLike, dt.datetime] = ..., - __format: Union[_CharLike, Tuple[_CharLike, _IntLike]] = ..., + __value: Union[None, datetime64, _CharLike_co, dt.datetime] = ..., + __format: Union[_CharLike_co, Tuple[_CharLike_co, _IntLike_co]] = ..., ) -> None: ... @overload def __init__( self, __value: int, - __format: Union[_CharLike, Tuple[_CharLike, _IntLike]] + __format: Union[_CharLike_co, Tuple[_CharLike_co, _IntLike_co]] ) -> None: ... - def __add__(self, other: _TD64Like) -> datetime64: ... - def __radd__(self, other: _TD64Like) -> datetime64: ... + def __add__(self, other: _TD64Like_co) -> datetime64: ... + def __radd__(self, other: _TD64Like_co) -> datetime64: ... @overload def __sub__(self, other: datetime64) -> timedelta64: ... @overload - def __sub__(self, other: _TD64Like) -> datetime64: ... + def __sub__(self, other: _TD64Like_co) -> datetime64: ... def __rsub__(self, other: datetime64) -> timedelta64: ... __lt__: _ComparisonOp[datetime64] __le__: _ComparisonOp[datetime64] @@ -1658,61 +1667,61 @@ class datetime64(generic): # Support for `__index__` was added in python 3.8 (bpo-20092) if sys.version_info >= (3, 8): - _IntValue = Union[SupportsInt, _CharLike, SupportsIndex] - _FloatValue = Union[None, _CharLike, SupportsFloat, SupportsIndex] - _ComplexValue = Union[None, _CharLike, SupportsFloat, SupportsComplex, SupportsIndex] + _IntValue = Union[SupportsInt, _CharLike_co, SupportsIndex] + _FloatValue = Union[None, _CharLike_co, SupportsFloat, SupportsIndex] + _ComplexValue = Union[None, _CharLike_co, SupportsFloat, SupportsComplex, SupportsIndex] else: - _IntValue = Union[SupportsInt, _CharLike] - _FloatValue = Union[None, _CharLike, SupportsFloat] - _ComplexValue = Union[None, _CharLike, SupportsFloat, SupportsComplex] + _IntValue = Union[SupportsInt, _CharLike_co] + _FloatValue = Union[None, _CharLike_co, SupportsFloat] + _ComplexValue = Union[None, _CharLike_co, SupportsFloat, SupportsComplex] -class integer(number[_NBit_co]): # type: ignore +class integer(number[_NBit1]): # type: ignore # NOTE: `__index__` is technically defined in the bottom-most # sub-classes (`int64`, `uint32`, etc) def __index__(self) -> int: ... - __truediv__: _IntTrueDiv[_NBit_co] - __rtruediv__: _IntTrueDiv[_NBit_co] - def __mod__(self, value: _IntLike) -> integer: ... - def __rmod__(self, value: _IntLike) -> integer: ... + __truediv__: _IntTrueDiv[_NBit1] + __rtruediv__: _IntTrueDiv[_NBit1] + def __mod__(self, value: _IntLike_co) -> integer: ... + def __rmod__(self, value: _IntLike_co) -> integer: ... def __invert__(self: _IntType) -> _IntType: ... # Ensure that objects annotated as `integer` support bit-wise operations - def __lshift__(self, other: _IntLike) -> integer: ... - def __rlshift__(self, other: _IntLike) -> integer: ... - def __rshift__(self, other: _IntLike) -> integer: ... - def __rrshift__(self, other: _IntLike) -> integer: ... - def __and__(self, other: _IntLike) -> integer: ... - def __rand__(self, other: _IntLike) -> integer: ... - def __or__(self, other: _IntLike) -> integer: ... - def __ror__(self, other: _IntLike) -> integer: ... - def __xor__(self, other: _IntLike) -> integer: ... - def __rxor__(self, other: _IntLike) -> integer: ... - -class signedinteger(integer[_NBit_co]): + def __lshift__(self, other: _IntLike_co) -> integer: ... + def __rlshift__(self, other: _IntLike_co) -> integer: ... + def __rshift__(self, other: _IntLike_co) -> integer: ... + def __rrshift__(self, other: _IntLike_co) -> integer: ... + def __and__(self, other: _IntLike_co) -> integer: ... + def __rand__(self, other: _IntLike_co) -> integer: ... + def __or__(self, other: _IntLike_co) -> integer: ... + def __ror__(self, other: _IntLike_co) -> integer: ... + def __xor__(self, other: _IntLike_co) -> integer: ... + def __rxor__(self, other: _IntLike_co) -> integer: ... + +class signedinteger(integer[_NBit1]): def __init__(self, __value: _IntValue = ...) -> None: ... - __add__: _SignedIntOp[_NBit_co] - __radd__: _SignedIntOp[_NBit_co] - __sub__: _SignedIntOp[_NBit_co] - __rsub__: _SignedIntOp[_NBit_co] - __mul__: _SignedIntOp[_NBit_co] - __rmul__: _SignedIntOp[_NBit_co] - __floordiv__: _SignedIntOp[_NBit_co] - __rfloordiv__: _SignedIntOp[_NBit_co] - __pow__: _SignedIntOp[_NBit_co] - __rpow__: _SignedIntOp[_NBit_co] - __lshift__: _SignedIntBitOp[_NBit_co] - __rlshift__: _SignedIntBitOp[_NBit_co] - __rshift__: _SignedIntBitOp[_NBit_co] - __rrshift__: _SignedIntBitOp[_NBit_co] - __and__: _SignedIntBitOp[_NBit_co] - __rand__: _SignedIntBitOp[_NBit_co] - __xor__: _SignedIntBitOp[_NBit_co] - __rxor__: _SignedIntBitOp[_NBit_co] - __or__: _SignedIntBitOp[_NBit_co] - __ror__: _SignedIntBitOp[_NBit_co] - __mod__: _SignedIntMod[_NBit_co] - __rmod__: _SignedIntMod[_NBit_co] - __divmod__: _SignedIntDivMod[_NBit_co] - __rdivmod__: _SignedIntDivMod[_NBit_co] + __add__: _SignedIntOp[_NBit1] + __radd__: _SignedIntOp[_NBit1] + __sub__: _SignedIntOp[_NBit1] + __rsub__: _SignedIntOp[_NBit1] + __mul__: _SignedIntOp[_NBit1] + __rmul__: _SignedIntOp[_NBit1] + __floordiv__: _SignedIntOp[_NBit1] + __rfloordiv__: _SignedIntOp[_NBit1] + __pow__: _SignedIntOp[_NBit1] + __rpow__: _SignedIntOp[_NBit1] + __lshift__: _SignedIntBitOp[_NBit1] + __rlshift__: _SignedIntBitOp[_NBit1] + __rshift__: _SignedIntBitOp[_NBit1] + __rrshift__: _SignedIntBitOp[_NBit1] + __and__: _SignedIntBitOp[_NBit1] + __rand__: _SignedIntBitOp[_NBit1] + __xor__: _SignedIntBitOp[_NBit1] + __rxor__: _SignedIntBitOp[_NBit1] + __or__: _SignedIntBitOp[_NBit1] + __ror__: _SignedIntBitOp[_NBit1] + __mod__: _SignedIntMod[_NBit1] + __rmod__: _SignedIntMod[_NBit1] + __divmod__: _SignedIntDivMod[_NBit1] + __rdivmod__: _SignedIntDivMod[_NBit1] int8 = signedinteger[_8Bit] int16 = signedinteger[_16Bit] @@ -1730,8 +1739,8 @@ longlong = signedinteger[_NBitLongLong] class timedelta64(generic): def __init__( self, - __value: Union[None, int, _CharLike, dt.timedelta, timedelta64] = ..., - __format: Union[_CharLike, Tuple[_CharLike, _IntLike]] = ..., + __value: Union[None, int, _CharLike_co, dt.timedelta, timedelta64] = ..., + __format: Union[_CharLike_co, Tuple[_CharLike_co, _IntLike_co]] = ..., ) -> None: ... def __int__(self) -> int: ... def __float__(self) -> float: ... @@ -1739,12 +1748,12 @@ class timedelta64(generic): def __neg__(self: _ArraySelf) -> _ArraySelf: ... def __pos__(self: _ArraySelf) -> _ArraySelf: ... def __abs__(self: _ArraySelf) -> _ArraySelf: ... - def __add__(self, other: _TD64Like) -> timedelta64: ... - def __radd__(self, other: _TD64Like) -> timedelta64: ... - def __sub__(self, other: _TD64Like) -> timedelta64: ... - def __rsub__(self, other: _TD64Like) -> timedelta64: ... - def __mul__(self, other: _FloatLike) -> timedelta64: ... - def __rmul__(self, other: _FloatLike) -> timedelta64: ... + def __add__(self, other: _TD64Like_co) -> timedelta64: ... + def __radd__(self, other: _TD64Like_co) -> timedelta64: ... + def __sub__(self, other: _TD64Like_co) -> timedelta64: ... + def __rsub__(self, other: _TD64Like_co) -> timedelta64: ... + def __mul__(self, other: _FloatLike_co) -> timedelta64: ... + def __rmul__(self, other: _FloatLike_co) -> timedelta64: ... __truediv__: _TD64Div[float64] __floordiv__: _TD64Div[int64] def __rtruediv__(self, other: timedelta64) -> float64: ... @@ -1753,38 +1762,38 @@ class timedelta64(generic): def __rmod__(self, other: timedelta64) -> timedelta64: ... def __divmod__(self, other: timedelta64) -> Tuple[int64, timedelta64]: ... def __rdivmod__(self, other: timedelta64) -> Tuple[int64, timedelta64]: ... - __lt__: _ComparisonOp[Union[timedelta64, _IntLike, _BoolLike]] - __le__: _ComparisonOp[Union[timedelta64, _IntLike, _BoolLike]] - __gt__: _ComparisonOp[Union[timedelta64, _IntLike, _BoolLike]] - __ge__: _ComparisonOp[Union[timedelta64, _IntLike, _BoolLike]] + __lt__: _ComparisonOp[Union[timedelta64, _IntLike_co, _BoolLike_co]] + __le__: _ComparisonOp[Union[timedelta64, _IntLike_co, _BoolLike_co]] + __gt__: _ComparisonOp[Union[timedelta64, _IntLike_co, _BoolLike_co]] + __ge__: _ComparisonOp[Union[timedelta64, _IntLike_co, _BoolLike_co]] -class unsignedinteger(integer[_NBit_co]): +class unsignedinteger(integer[_NBit1]): # NOTE: `uint64 + signedinteger -> float64` def __init__(self, __value: _IntValue = ...) -> None: ... - __add__: _UnsignedIntOp[_NBit_co] - __radd__: _UnsignedIntOp[_NBit_co] - __sub__: _UnsignedIntOp[_NBit_co] - __rsub__: _UnsignedIntOp[_NBit_co] - __mul__: _UnsignedIntOp[_NBit_co] - __rmul__: _UnsignedIntOp[_NBit_co] - __floordiv__: _UnsignedIntOp[_NBit_co] - __rfloordiv__: _UnsignedIntOp[_NBit_co] - __pow__: _UnsignedIntOp[_NBit_co] - __rpow__: _UnsignedIntOp[_NBit_co] - __lshift__: _UnsignedIntBitOp[_NBit_co] - __rlshift__: _UnsignedIntBitOp[_NBit_co] - __rshift__: _UnsignedIntBitOp[_NBit_co] - __rrshift__: _UnsignedIntBitOp[_NBit_co] - __and__: _UnsignedIntBitOp[_NBit_co] - __rand__: _UnsignedIntBitOp[_NBit_co] - __xor__: _UnsignedIntBitOp[_NBit_co] - __rxor__: _UnsignedIntBitOp[_NBit_co] - __or__: _UnsignedIntBitOp[_NBit_co] - __ror__: _UnsignedIntBitOp[_NBit_co] - __mod__: _UnsignedIntMod[_NBit_co] - __rmod__: _UnsignedIntMod[_NBit_co] - __divmod__: _UnsignedIntDivMod[_NBit_co] - __rdivmod__: _UnsignedIntDivMod[_NBit_co] + __add__: _UnsignedIntOp[_NBit1] + __radd__: _UnsignedIntOp[_NBit1] + __sub__: _UnsignedIntOp[_NBit1] + __rsub__: _UnsignedIntOp[_NBit1] + __mul__: _UnsignedIntOp[_NBit1] + __rmul__: _UnsignedIntOp[_NBit1] + __floordiv__: _UnsignedIntOp[_NBit1] + __rfloordiv__: _UnsignedIntOp[_NBit1] + __pow__: _UnsignedIntOp[_NBit1] + __rpow__: _UnsignedIntOp[_NBit1] + __lshift__: _UnsignedIntBitOp[_NBit1] + __rlshift__: _UnsignedIntBitOp[_NBit1] + __rshift__: _UnsignedIntBitOp[_NBit1] + __rrshift__: _UnsignedIntBitOp[_NBit1] + __and__: _UnsignedIntBitOp[_NBit1] + __rand__: _UnsignedIntBitOp[_NBit1] + __xor__: _UnsignedIntBitOp[_NBit1] + __rxor__: _UnsignedIntBitOp[_NBit1] + __or__: _UnsignedIntBitOp[_NBit1] + __ror__: _UnsignedIntBitOp[_NBit1] + __mod__: _UnsignedIntMod[_NBit1] + __rmod__: _UnsignedIntMod[_NBit1] + __divmod__: _UnsignedIntDivMod[_NBit1] + __rdivmod__: _UnsignedIntDivMod[_NBit1] uint8 = unsignedinteger[_8Bit] uint16 = unsignedinteger[_16Bit] @@ -1799,29 +1808,29 @@ uint0 = unsignedinteger[_NBitIntP] uint = unsignedinteger[_NBitInt] ulonglong = unsignedinteger[_NBitLongLong] -class inexact(number[_NBit_co]): ... # type: ignore +class inexact(number[_NBit1]): ... # type: ignore _IntType = TypeVar("_IntType", bound=integer) _FloatType = TypeVar('_FloatType', bound=floating) -class floating(inexact[_NBit_co]): +class floating(inexact[_NBit1]): def __init__(self, __value: _FloatValue = ...) -> None: ... - __add__: _FloatOp[_NBit_co] - __radd__: _FloatOp[_NBit_co] - __sub__: _FloatOp[_NBit_co] - __rsub__: _FloatOp[_NBit_co] - __mul__: _FloatOp[_NBit_co] - __rmul__: _FloatOp[_NBit_co] - __truediv__: _FloatOp[_NBit_co] - __rtruediv__: _FloatOp[_NBit_co] - __floordiv__: _FloatOp[_NBit_co] - __rfloordiv__: _FloatOp[_NBit_co] - __pow__: _FloatOp[_NBit_co] - __rpow__: _FloatOp[_NBit_co] - __mod__: _FloatMod[_NBit_co] - __rmod__: _FloatMod[_NBit_co] - __divmod__: _FloatDivMod[_NBit_co] - __rdivmod__: _FloatDivMod[_NBit_co] + __add__: _FloatOp[_NBit1] + __radd__: _FloatOp[_NBit1] + __sub__: _FloatOp[_NBit1] + __rsub__: _FloatOp[_NBit1] + __mul__: _FloatOp[_NBit1] + __rmul__: _FloatOp[_NBit1] + __truediv__: _FloatOp[_NBit1] + __rtruediv__: _FloatOp[_NBit1] + __floordiv__: _FloatOp[_NBit1] + __rfloordiv__: _FloatOp[_NBit1] + __pow__: _FloatOp[_NBit1] + __rpow__: _FloatOp[_NBit1] + __mod__: _FloatMod[_NBit1] + __rmod__: _FloatMod[_NBit1] + __divmod__: _FloatDivMod[_NBit1] + __rdivmod__: _FloatDivMod[_NBit1] float16 = floating[_16Bit] float32 = floating[_32Bit] @@ -1838,25 +1847,25 @@ longfloat = floating[_NBitLongDouble] # It is used to clarify why `complex128`s precision is `_64Bit`, the latter # describing the two 64 bit floats representing its real and imaginary component -class complexfloating(inexact[_NBit_co], Generic[_NBit_co, _NBit_co2]): +class complexfloating(inexact[_NBit1], Generic[_NBit1, _NBit2]): def __init__(self, __value: _ComplexValue = ...) -> None: ... @property - def real(self) -> floating[_NBit_co]: ... # type: ignore[override] - @property - def imag(self) -> floating[_NBit_co2]: ... # type: ignore[override] - def __abs__(self) -> floating[_NBit_co]: ... # type: ignore[override] - __add__: _ComplexOp[_NBit_co] - __radd__: _ComplexOp[_NBit_co] - __sub__: _ComplexOp[_NBit_co] - __rsub__: _ComplexOp[_NBit_co] - __mul__: _ComplexOp[_NBit_co] - __rmul__: _ComplexOp[_NBit_co] - __truediv__: _ComplexOp[_NBit_co] - __rtruediv__: _ComplexOp[_NBit_co] - __floordiv__: _ComplexOp[_NBit_co] - __rfloordiv__: _ComplexOp[_NBit_co] - __pow__: _ComplexOp[_NBit_co] - __rpow__: _ComplexOp[_NBit_co] + def real(self) -> floating[_NBit1]: ... # type: ignore[override] + @property + def imag(self) -> floating[_NBit2]: ... # type: ignore[override] + def __abs__(self) -> floating[_NBit1]: ... # type: ignore[override] + __add__: _ComplexOp[_NBit1] + __radd__: _ComplexOp[_NBit1] + __sub__: _ComplexOp[_NBit1] + __rsub__: _ComplexOp[_NBit1] + __mul__: _ComplexOp[_NBit1] + __rmul__: _ComplexOp[_NBit1] + __truediv__: _ComplexOp[_NBit1] + __rtruediv__: _ComplexOp[_NBit1] + __floordiv__: _ComplexOp[_NBit1] + __rfloordiv__: _ComplexOp[_NBit1] + __pow__: _ComplexOp[_NBit1] + __rpow__: _ComplexOp[_NBit1] complex64 = complexfloating[_32Bit, _32Bit] complex128 = complexfloating[_64Bit, _64Bit] @@ -1873,7 +1882,7 @@ longcomplex = complexfloating[_NBitLongDouble, _NBitLongDouble] class flexible(generic): ... # type: ignore class void(flexible): - def __init__(self, __value: Union[_IntLike, bytes]): ... + def __init__(self, __value: Union[_IntLike_co, bytes]): ... @property def real(self: _ArraySelf) -> _ArraySelf: ... @property diff --git a/numpy/core/arrayprint.pyi b/numpy/core/arrayprint.pyi index 6aaae0320..b2565b345 100644 --- a/numpy/core/arrayprint.pyi +++ b/numpy/core/arrayprint.pyi @@ -21,7 +21,7 @@ from numpy import ( longdouble, clongdouble, ) -from numpy.typing import ArrayLike, _CharLike, _FloatLike +from numpy.typing import ArrayLike, _CharLike_co, _FloatLike_co if sys.version_info > (3, 8): from typing import Literal, TypedDict @@ -40,13 +40,13 @@ class _FormatDict(TypedDict, total=False): complexfloat: Callable[[complexfloating[Any, Any]], str] longcomplexfloat: Callable[[clongdouble], str] void: Callable[[void], str] - numpystr: Callable[[_CharLike], str] + numpystr: Callable[[_CharLike_co], str] object: Callable[[object], str] all: Callable[[object], str] int_kind: Callable[[integer[Any]], str] float_kind: Callable[[floating[Any]], str] complex_kind: Callable[[complexfloating[Any, Any]], str] - str_kind: Callable[[_CharLike], str] + str_kind: Callable[[_CharLike_co], str] class _FormatOptions(TypedDict): precision: int @@ -96,7 +96,7 @@ def array2string( legacy: Optional[Literal[False, "1.13"]] = ..., ) -> str: ... def format_float_scientific( - x: _FloatLike, + x: _FloatLike_co, precision: Optional[int] = ..., unique: bool = ..., trim: Literal["k", ".", "0", "-"] = ..., @@ -105,7 +105,7 @@ def format_float_scientific( exp_digits: Optional[int] = ..., ) -> str: ... def format_float_positional( - x: _FloatLike, + x: _FloatLike_co, precision: Optional[int] = ..., unique: bool = ..., fractional: bool = ..., diff --git a/numpy/core/fromnumeric.pyi b/numpy/core/fromnumeric.pyi index 3b147e1d7..fc7f28a59 100644 --- a/numpy/core/fromnumeric.pyi +++ b/numpy/core/fromnumeric.pyi @@ -23,9 +23,8 @@ from numpy.typing import ( ArrayLike, _ShapeLike, _Shape, - _IntLike, - _BoolLike, - _NumberLike, + _IntLike_co, + _NumberLike_co, ) if sys.version_info >= (3, 8): @@ -98,7 +97,7 @@ def choose( ) -> _ScalarIntOrBool: ... @overload def choose( - a: Union[_IntLike, _BoolLike], choices: ArrayLike, out: Optional[ndarray] = ..., mode: _ModeKind = ... + a: _IntLike_co, choices: ArrayLike, out: Optional[ndarray] = ..., mode: _ModeKind = ... ) -> Union[integer, bool_]: ... @overload def choose( @@ -250,7 +249,7 @@ def sum( dtype: DTypeLike = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> _Number: ... @overload @@ -260,7 +259,7 @@ def sum( dtype: DTypeLike = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... @overload @@ -324,7 +323,7 @@ def amax( axis: Optional[_ShapeLike] = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> _Number: ... @overload @@ -333,7 +332,7 @@ def amax( axis: None = ..., out: Optional[ndarray] = ..., keepdims: Literal[False] = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> number: ... @overload @@ -342,7 +341,7 @@ def amax( axis: Optional[_ShapeLike] = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... @overload @@ -351,7 +350,7 @@ def amin( axis: Optional[_ShapeLike] = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> _Number: ... @overload @@ -360,7 +359,7 @@ def amin( axis: None = ..., out: Optional[ndarray] = ..., keepdims: Literal[False] = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> number: ... @overload @@ -369,7 +368,7 @@ def amin( axis: Optional[_ShapeLike] = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... @@ -387,7 +386,7 @@ def prod( dtype: DTypeLike = ..., out: None = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> _Number: ... @overload @@ -397,7 +396,7 @@ def prod( dtype: DTypeLike = ..., out: None = ..., keepdims: Literal[False] = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> number: ... @overload @@ -407,7 +406,7 @@ def prod( dtype: DTypeLike = ..., out: Optional[ndarray] = ..., keepdims: bool = ..., - initial: _NumberLike = ..., + initial: _NumberLike_co = ..., where: _ArrayLikeBool = ..., ) -> Union[number, ndarray]: ... def cumprod( @@ -424,7 +423,7 @@ def around( ) -> _Number: ... @overload def around( - a: _NumberLike, decimals: int = ..., out: Optional[ndarray] = ... + a: _NumberLike_co, decimals: int = ..., out: Optional[ndarray] = ... ) -> number: ... @overload def around( diff --git a/numpy/core/function_base.pyi b/numpy/core/function_base.pyi index 1490bed4a..d353543f6 100644 --- a/numpy/core/function_base.pyi +++ b/numpy/core/function_base.pyi @@ -2,7 +2,7 @@ import sys from typing import overload, Tuple, Union, Sequence, Any from numpy import ndarray, inexact -from numpy.typing import ArrayLike, DTypeLike, _SupportsArray, _NumberLike +from numpy.typing import ArrayLike, DTypeLike, _SupportsArray, _NumberLike_co if sys.version_info >= (3, 8): from typing import SupportsIndex, Literal @@ -15,7 +15,7 @@ else: # TODO: wait for support for recursive types _ArrayLikeNested = Sequence[Sequence[Any]] _ArrayLikeNumber = Union[ - _NumberLike, Sequence[_NumberLike], ndarray, _SupportsArray, _ArrayLikeNested + _NumberLike_co, Sequence[_NumberLike_co], ndarray, _SupportsArray, _ArrayLikeNested ] @overload def linspace( diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c index 58571b678..ef105ff2d 100644 --- a/numpy/core/src/multiarray/ctors.c +++ b/numpy/core/src/multiarray/ctors.c @@ -2124,7 +2124,16 @@ PyArray_FromInterface(PyObject *origin) if (iface == NULL) { if (PyErr_Occurred()) { - return NULL; + if (PyErr_ExceptionMatches(PyExc_RecursionError) || + PyErr_ExceptionMatches(PyExc_MemoryError)) { + /* RecursionError and MemoryError are considered fatal */ + return NULL; + } + /* + * This probably be deprecated, but at least shapely raised + * a NotImplementedError expecting it to be cleared (gh-17965) + */ + PyErr_Clear(); } return Py_NotImplemented; } @@ -2392,7 +2401,13 @@ PyArray_FromArrayAttr(PyObject *op, PyArray_Descr *typecode, PyObject *context) array_meth = PyArray_LookupSpecial_OnInstance(op, "__array__"); if (array_meth == NULL) { if (PyErr_Occurred()) { - return NULL; + if (PyErr_ExceptionMatches(PyExc_RecursionError) || + PyErr_ExceptionMatches(PyExc_MemoryError)) { + /* RecursionError and MemoryError are considered fatal */ + return NULL; + } + /* This probably be deprecated. */ + PyErr_Clear(); } return Py_NotImplemented; } diff --git a/numpy/core/tests/test_array_coercion.py b/numpy/core/tests/test_array_coercion.py index 08b32dfcc..8f709dbe1 100644 --- a/numpy/core/tests/test_array_coercion.py +++ b/numpy/core/tests/test_array_coercion.py @@ -702,17 +702,19 @@ class TestArrayLikes: @pytest.mark.parametrize("attribute", ["__array_interface__", "__array__", "__array_struct__"]) - def test_bad_array_like_attributes(self, attribute): - # Check that errors during attribute retrieval are raised unless - # they are Attribute errors. + @pytest.mark.parametrize("error", [RecursionError, MemoryError]) + def test_bad_array_like_attributes(self, attribute, error): + # RecursionError and MemoryError are considered fatal. All errors + # (except AttributeError) should probably be raised in the future, + # but shapely made use of it, so it will require a deprecation. class BadInterface: def __getattr__(self, attr): if attr == attribute: - raise RuntimeError + raise error super().__getattr__(attr) - with pytest.raises(RuntimeError): + with pytest.raises(error): np.array(BadInterface()) @pytest.mark.parametrize("error", [RecursionError, MemoryError]) diff --git a/numpy/distutils/fcompiler/__init__.py b/numpy/distutils/fcompiler/__init__.py index 4730a5a09..812461538 100644 --- a/numpy/distutils/fcompiler/__init__.py +++ b/numpy/distutils/fcompiler/__init__.py @@ -976,7 +976,7 @@ def is_free_format(file): with open(file, encoding='latin1') as f: line = f.readline() n = 10000 # the number of non-comment lines to scan for hints - if _has_f_header(line): + if _has_f_header(line) or _has_fix_header(line): n = 0 elif _has_f90_header(line): n = 0 diff --git a/numpy/f2py/auxfuncs.py b/numpy/f2py/auxfuncs.py index 80b150655..5250fea84 100644 --- a/numpy/f2py/auxfuncs.py +++ b/numpy/f2py/auxfuncs.py @@ -257,6 +257,7 @@ def ismodule(rout): def isfunction(rout): return 'block' in rout and 'function' == rout['block'] + def isfunction_wrap(rout): if isintent_c(rout): return 0 @@ -284,6 +285,10 @@ def hasassumedshape(rout): return False +def requiresf90wrapper(rout): + return ismoduleroutine(rout) or hasassumedshape(rout) + + def isroutine(rout): return isfunction(rout) or issubroutine(rout) diff --git a/numpy/f2py/cfuncs.py b/numpy/f2py/cfuncs.py index 26b43e7e6..40496ccf1 100644 --- a/numpy/f2py/cfuncs.py +++ b/numpy/f2py/cfuncs.py @@ -549,7 +549,12 @@ cppmacros["F2PY_THREAD_LOCAL_DECL"] = """\ #define F2PY_THREAD_LOCAL_DECL __declspec(thread) #elif defined(__STDC_VERSION__) \\ && (__STDC_VERSION__ >= 201112L) \\ - && !defined(__STDC_NO_THREADS__) + && !defined(__STDC_NO_THREADS__) \\ + && (!defined(__GLIBC__) || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 12)) +/* __STDC_NO_THREADS__ was first defined in a maintenance release of glibc 2.12, + see https://lists.gnu.org/archive/html/commit-hurd/2012-07/msg00180.html, + so `!defined(__STDC_NO_THREADS__)` may give false positive for the existence + of `threads.h` when using an older release of glibc 2.12 */ #include <threads.h> #define F2PY_THREAD_LOCAL_DECL thread_local #elif defined(__GNUC__) \\ diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py index d27845796..1149633c0 100755 --- a/numpy/f2py/crackfortran.py +++ b/numpy/f2py/crackfortran.py @@ -3113,7 +3113,7 @@ def crack2fortrangen(block, tab='\n', as_interface=False): result = ' result (%s)' % block['result'] if block['result'] not in argsl: argsl.append(block['result']) - body = crack2fortrangen(block['body'], tab + tabchar) + body = crack2fortrangen(block['body'], tab + tabchar, as_interface=as_interface) vars = vars2fortran( block, block['vars'], argsl, tab + tabchar, as_interface=as_interface) mess = '' @@ -3231,8 +3231,13 @@ def vars2fortran(block, vars, args, tab='', as_interface=False): show(vars) outmess('vars2fortran: No definition for argument "%s".\n' % a) continue - if a == block['name'] and not block['block'] == 'function': - continue + if a == block['name']: + if block['block'] != 'function' or block.get('result'): + # 1) skip declaring a variable that name matches with + # subroutine name + # 2) skip declaring function when its type is + # declared via `result` construction + continue if 'typespec' not in vars[a]: if 'attrspec' in vars[a] and 'external' in vars[a]['attrspec']: if a in args: diff --git a/numpy/f2py/func2subr.py b/numpy/f2py/func2subr.py index e9976f43c..21d4c009c 100644 --- a/numpy/f2py/func2subr.py +++ b/numpy/f2py/func2subr.py @@ -130,7 +130,7 @@ def createfuncwrapper(rout, signature=0): l = l + ', ' + fortranname if need_interface: for line in rout['saved_interface'].split('\n'): - if line.lstrip().startswith('use '): + if line.lstrip().startswith('use ') and '__user__' not in line: add(line) args = args[1:] @@ -222,7 +222,7 @@ def createsubrwrapper(rout, signature=0): if need_interface: for line in rout['saved_interface'].split('\n'): - if line.lstrip().startswith('use '): + if line.lstrip().startswith('use ') and '__user__' not in line: add(line) dumped_args = [] @@ -247,7 +247,10 @@ def createsubrwrapper(rout, signature=0): pass else: add('interface') - add(rout['saved_interface'].lstrip()) + for line in rout['saved_interface'].split('\n'): + if line.lstrip().startswith('use ') and '__user__' in line: + continue + add(line) add('end interface') sargs = ', '.join([a for a in args if a not in extra_args]) diff --git a/numpy/f2py/rules.py b/numpy/f2py/rules.py index f1490527e..4e1cf0c7d 100755 --- a/numpy/f2py/rules.py +++ b/numpy/f2py/rules.py @@ -73,7 +73,7 @@ from .auxfuncs import ( issubroutine, issubroutine_wrap, isthreadsafe, isunsigned, isunsigned_char, isunsigned_chararray, isunsigned_long_long, isunsigned_long_longarray, isunsigned_short, isunsigned_shortarray, - l_and, l_not, l_or, outmess, replace, stripcomma, + l_and, l_not, l_or, outmess, replace, stripcomma, requiresf90wrapper ) from . import capi_maps @@ -1184,9 +1184,12 @@ def buildmodule(m, um): nb1['args'] = a nb_list.append(nb1) for nb in nb_list: + # requiresf90wrapper must be called before buildapi as it + # rewrites assumed shape arrays as automatic arrays. + isf90 = requiresf90wrapper(nb) api, wrap = buildapi(nb) if wrap: - if ismoduleroutine(nb): + if isf90: funcwrappers2.append(wrap) else: funcwrappers.append(wrap) @@ -1288,7 +1291,10 @@ def buildmodule(m, um): 'C It contains Fortran 77 wrappers to fortran functions.\n') lines = [] for l in ('\n\n'.join(funcwrappers) + '\n').split('\n'): - if l and l[0] == ' ': + if 0 <= l.find('!') < 66: + # don't split comment lines + lines.append(l + '\n') + elif l and l[0] == ' ': while len(l) >= 66: lines.append(l[:66] + '\n &') l = l[66:] @@ -1310,7 +1316,10 @@ def buildmodule(m, um): '! It contains Fortran 90 wrappers to fortran functions.\n') lines = [] for l in ('\n\n'.join(funcwrappers2) + '\n').split('\n'): - if len(l) > 72 and l[0] == ' ': + if 0 <= l.find('!') < 72: + # don't split comment lines + lines.append(l + '\n') + elif len(l) > 72 and l[0] == ' ': lines.append(l[:72] + '&\n &') l = l[72:] while len(l) > 66: diff --git a/numpy/f2py/tests/test_callback.py b/numpy/f2py/tests/test_callback.py index 81650a819..37736af21 100644 --- a/numpy/f2py/tests/test_callback.py +++ b/numpy/f2py/tests/test_callback.py @@ -211,3 +211,28 @@ class TestF77CallbackPythonTLS(TestF77Callback): compiler-provided """ options = ["-DF2PY_USE_PYTHON_TLS"] + + +class TestF90Callback(util.F2PyTest): + + suffix = '.f90' + + code = textwrap.dedent( + """ + function gh17797(f, y) result(r) + external f + integer(8) :: r, f + integer(8), dimension(:) :: y + r = f(0) + r = r + sum(y) + end function gh17797 + """) + + def test_gh17797(self): + + def incr(x): + return x + 123 + + y = np.array([1, 2, 3], dtype=np.int64) + r = self.module.gh17797(incr, y) + assert r == 123 + 1 + 2 + 3 diff --git a/numpy/random/_generator.pyx b/numpy/random/_generator.pyx index e00bc4d98..7d652ce89 100644 --- a/numpy/random/_generator.pyx +++ b/numpy/random/_generator.pyx @@ -1092,7 +1092,7 @@ cdef class Generator: 0.0 # may vary >>> abs(sigma - np.std(s, ddof=1)) - 0.1 # may vary + 0.0 # may vary Display the histogram of the samples, along with the probability density function: diff --git a/numpy/typing/__init__.py b/numpy/typing/__init__.py index 86bba57be..a1d943235 100644 --- a/numpy/typing/__init__.py +++ b/numpy/typing/__init__.py @@ -184,13 +184,15 @@ class NBitBase: .. code-block:: python - >>> from typing import TypeVar, TYPE_CHECKING + >>> from __future__ import annotations + >>> from typing import TypeVar, Union, TYPE_CHECKING >>> import numpy as np >>> import numpy.typing as npt - >>> T = TypeVar("T", bound=npt.NBitBase) + >>> T1 = TypeVar("T1", bound=npt.NBitBase) + >>> T2 = TypeVar("T2", bound=npt.NBitBase) - >>> def add(a: "np.floating[T]", b: "np.integer[T]") -> "np.floating[T]": + >>> def add(a: np.floating[T1], b: np.integer[T2]) -> np.floating[Union[T1, T2]]: ... return a + b >>> a = np.float16() @@ -283,35 +285,35 @@ from ._char_codes import ( _ObjectCodes, ) from ._scalars import ( - _CharLike, - _BoolLike, - _UIntLike, - _IntLike, - _FloatLike, - _ComplexLike, - _TD64Like, - _NumberLike, - _ScalarLike, - _VoidLike, + _CharLike_co, + _BoolLike_co, + _UIntLike_co, + _IntLike_co, + _FloatLike_co, + _ComplexLike_co, + _TD64Like_co, + _NumberLike_co, + _ScalarLike_co, + _VoidLike_co, ) from ._shape import _Shape, _ShapeLike -from ._dtype_like import _SupportsDType, _VoidDTypeLike, DTypeLike +from ._dtype_like import _SupportsDType, _VoidDTypeLike, DTypeLike as DTypeLike from ._array_like import ( - ArrayLike, + ArrayLike as ArrayLike, _ArrayLike, _NestedSequence, _SupportsArray, - _ArrayLikeBool, - _ArrayLikeUInt, - _ArrayLikeInt, - _ArrayLikeFloat, - _ArrayLikeComplex, - _ArrayLikeTD64, - _ArrayLikeDT64, - _ArrayLikeObject, - _ArrayLikeVoid, - _ArrayLikeStr, - _ArrayLikeBytes, + _ArrayLikeBool_co, + _ArrayLikeUInt_co, + _ArrayLikeInt_co, + _ArrayLikeFloat_co, + _ArrayLikeComplex_co, + _ArrayLikeTD64_co, + _ArrayLikeDT64_co, + _ArrayLikeObject_co, + _ArrayLikeVoid_co, + _ArrayLikeStr_co, + _ArrayLikeBytes_co, ) if __doc__ is not None: diff --git a/numpy/typing/_array_like.py b/numpy/typing/_array_like.py index d6473442c..35413393c 100644 --- a/numpy/typing/_array_like.py +++ b/numpy/typing/_array_like.py @@ -78,41 +78,41 @@ ArrayLike = Union[ ], ] -# `ArrayLike<X>`: array-like objects that can be coerced into `X` +# `ArrayLike<X>_co`: array-like objects that can be coerced into `X` # given the casting rules `same_kind` -_ArrayLikeBool = _ArrayLike[ +_ArrayLikeBool_co = _ArrayLike[ "dtype[bool_]", bool, ] -_ArrayLikeUInt = _ArrayLike[ +_ArrayLikeUInt_co = _ArrayLike[ "dtype[Union[bool_, unsignedinteger[Any]]]", bool, ] -_ArrayLikeInt = _ArrayLike[ +_ArrayLikeInt_co = _ArrayLike[ "dtype[Union[bool_, integer[Any]]]", Union[bool, int], ] -_ArrayLikeFloat = _ArrayLike[ +_ArrayLikeFloat_co = _ArrayLike[ "dtype[Union[bool_, integer[Any], floating[Any]]]", Union[bool, int, float], ] -_ArrayLikeComplex = _ArrayLike[ +_ArrayLikeComplex_co = _ArrayLike[ "dtype[Union[bool_, integer[Any], floating[Any], complexfloating[Any, Any]]]", Union[bool, int, float, complex], ] -_ArrayLikeTD64 = _ArrayLike[ +_ArrayLikeTD64_co = _ArrayLike[ "dtype[Union[bool_, integer[Any], timedelta64]]", Union[bool, int], ] -_ArrayLikeDT64 = _NestedSequence[_SupportsArray["dtype[datetime64]"]] -_ArrayLikeObject = _NestedSequence[_SupportsArray["dtype[object_]"]] +_ArrayLikeDT64_co = _NestedSequence[_SupportsArray["dtype[datetime64]"]] +_ArrayLikeObject_co = _NestedSequence[_SupportsArray["dtype[object_]"]] -_ArrayLikeVoid = _NestedSequence[_SupportsArray["dtype[void]"]] -_ArrayLikeStr = _ArrayLike[ +_ArrayLikeVoid_co = _NestedSequence[_SupportsArray["dtype[void]"]] +_ArrayLikeStr_co = _ArrayLike[ "dtype[str_]", str, ] -_ArrayLikeBytes = _ArrayLike[ +_ArrayLikeBytes_co = _ArrayLike[ "dtype[bytes_]", bytes, ] diff --git a/numpy/typing/_callable.py b/numpy/typing/_callable.py index 8f464cc75..e1fdee3ba 100644 --- a/numpy/typing/_callable.py +++ b/numpy/typing/_callable.py @@ -37,11 +37,11 @@ from numpy import ( ) from ._nbit import _NBitInt from ._scalars import ( - _BoolLike, - _IntLike, - _FloatLike, - _ComplexLike, - _NumberLike, + _BoolLike_co, + _IntLike_co, + _FloatLike_co, + _ComplexLike_co, + _NumberLike_co, ) from . import NBitBase from ._array_like import ArrayLike @@ -61,8 +61,8 @@ if TYPE_CHECKING or HAVE_PROTOCOL: _T = TypeVar("_T") _2Tuple = Tuple[_T, _T] - _NBit_co = TypeVar("_NBit_co", covariant=True, bound=NBitBase) - _NBit = TypeVar("_NBit", bound=NBitBase) + _NBit1 = TypeVar("_NBit1", bound=NBitBase) + _NBit2 = TypeVar("_NBit2", bound=NBitBase) _IntType = TypeVar("_IntType", bound=integer) _FloatType = TypeVar("_FloatType", bound=floating) @@ -72,7 +72,7 @@ if TYPE_CHECKING or HAVE_PROTOCOL: class _BoolOp(Protocol[_GenericType_co]): @overload - def __call__(self, __other: _BoolLike) -> _GenericType_co: ... + def __call__(self, __other: _BoolLike_co) -> _GenericType_co: ... @overload # platform dependent def __call__(self, __other: int) -> int_: ... @overload @@ -84,7 +84,7 @@ if TYPE_CHECKING or HAVE_PROTOCOL: class _BoolBitOp(Protocol[_GenericType_co]): @overload - def __call__(self, __other: _BoolLike) -> _GenericType_co: ... + def __call__(self, __other: _BoolLike_co) -> _GenericType_co: ... @overload # platform dependent def __call__(self, __other: int) -> int_: ... @overload @@ -105,7 +105,7 @@ if TYPE_CHECKING or HAVE_PROTOCOL: class _BoolTrueDiv(Protocol): @overload - def __call__(self, __other: Union[float, _IntLike]) -> float64: ... + def __call__(self, __other: Union[float, _IntLike_co]) -> float64: ... @overload def __call__(self, __other: complex) -> complex128: ... @overload @@ -113,7 +113,7 @@ if TYPE_CHECKING or HAVE_PROTOCOL: class _BoolMod(Protocol): @overload - def __call__(self, __other: _BoolLike) -> int8: ... + def __call__(self, __other: _BoolLike_co) -> int8: ... @overload # platform dependent def __call__(self, __other: int) -> int_: ... @overload @@ -125,7 +125,7 @@ if TYPE_CHECKING or HAVE_PROTOCOL: class _BoolDivMod(Protocol): @overload - def __call__(self, __other: _BoolLike) -> _2Tuple[int8]: ... + def __call__(self, __other: _BoolLike_co) -> _2Tuple[int8]: ... @overload # platform dependent def __call__(self, __other: int) -> _2Tuple[int_]: ... @overload @@ -139,11 +139,11 @@ if TYPE_CHECKING or HAVE_PROTOCOL: @overload def __call__(self, __other: timedelta64) -> _NumberType_co: ... @overload - def __call__(self, __other: _FloatLike) -> timedelta64: ... + def __call__(self, __other: _FloatLike_co) -> timedelta64: ... - class _IntTrueDiv(Protocol[_NBit_co]): + class _IntTrueDiv(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> floating[_NBit_co]: ... + def __call__(self, __other: bool) -> floating[_NBit1]: ... @overload def __call__(self, __other: int) -> floating[_NBitInt]: ... @overload @@ -151,12 +151,12 @@ if TYPE_CHECKING or HAVE_PROTOCOL: @overload def __call__(self, __other: complex) -> complex128: ... @overload - def __call__(self, __other: integer[_NBit]) -> floating[Union[_NBit_co, _NBit]]: ... + def __call__(self, __other: integer[_NBit2]) -> floating[Union[_NBit1, _NBit2]]: ... - class _UnsignedIntOp(Protocol[_NBit_co]): + class _UnsignedIntOp(Protocol[_NBit1]): # NOTE: `uint64 + signedinteger -> float64` @overload - def __call__(self, __other: bool) -> unsignedinteger[_NBit_co]: ... + def __call__(self, __other: bool) -> unsignedinteger[_NBit1]: ... @overload def __call__( self, __other: Union[int, signedinteger[Any]] @@ -167,24 +167,24 @@ if TYPE_CHECKING or HAVE_PROTOCOL: def __call__(self, __other: complex) -> complex128: ... @overload def __call__( - self, __other: unsignedinteger[_NBit] - ) -> unsignedinteger[Union[_NBit_co, _NBit]]: ... + self, __other: unsignedinteger[_NBit2] + ) -> unsignedinteger[Union[_NBit1, _NBit2]]: ... - class _UnsignedIntBitOp(Protocol[_NBit_co]): + class _UnsignedIntBitOp(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> unsignedinteger[_NBit_co]: ... + def __call__(self, __other: bool) -> unsignedinteger[_NBit1]: ... @overload def __call__(self, __other: int) -> signedinteger[Any]: ... @overload def __call__(self, __other: signedinteger[Any]) -> signedinteger[Any]: ... @overload def __call__( - self, __other: unsignedinteger[_NBit] - ) -> unsignedinteger[Union[_NBit_co, _NBit]]: ... + self, __other: unsignedinteger[_NBit2] + ) -> unsignedinteger[Union[_NBit1, _NBit2]]: ... - class _UnsignedIntMod(Protocol[_NBit_co]): + class _UnsignedIntMod(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> unsignedinteger[_NBit_co]: ... + def __call__(self, __other: bool) -> unsignedinteger[_NBit1]: ... @overload def __call__( self, __other: Union[int, signedinteger[Any]] @@ -193,12 +193,12 @@ if TYPE_CHECKING or HAVE_PROTOCOL: def __call__(self, __other: float) -> float64: ... @overload def __call__( - self, __other: unsignedinteger[_NBit] - ) -> unsignedinteger[Union[_NBit_co, _NBit]]: ... + self, __other: unsignedinteger[_NBit2] + ) -> unsignedinteger[Union[_NBit1, _NBit2]]: ... - class _UnsignedIntDivMod(Protocol[_NBit_co]): + class _UnsignedIntDivMod(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> _2Tuple[signedinteger[_NBit_co]]: ... + def __call__(self, __other: bool) -> _2Tuple[signedinteger[_NBit1]]: ... @overload def __call__( self, __other: Union[int, signedinteger[Any]] @@ -207,114 +207,114 @@ if TYPE_CHECKING or HAVE_PROTOCOL: def __call__(self, __other: float) -> _2Tuple[float64]: ... @overload def __call__( - self, __other: unsignedinteger[_NBit] - ) -> _2Tuple[unsignedinteger[Union[_NBit_co, _NBit]]]: ... + self, __other: unsignedinteger[_NBit2] + ) -> _2Tuple[unsignedinteger[Union[_NBit1, _NBit2]]]: ... - class _SignedIntOp(Protocol[_NBit_co]): + class _SignedIntOp(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> signedinteger[_NBit_co]: ... + def __call__(self, __other: bool) -> signedinteger[_NBit1]: ... @overload - def __call__(self, __other: int) -> signedinteger[Union[_NBit_co, _NBitInt]]: ... + def __call__(self, __other: int) -> signedinteger[Union[_NBit1, _NBitInt]]: ... @overload def __call__(self, __other: float) -> float64: ... @overload def __call__(self, __other: complex) -> complex128: ... @overload def __call__( - self, __other: signedinteger[_NBit] - ) -> signedinteger[Union[_NBit_co, _NBit]]: ... + self, __other: signedinteger[_NBit2] + ) -> signedinteger[Union[_NBit1, _NBit2]]: ... - class _SignedIntBitOp(Protocol[_NBit_co]): + class _SignedIntBitOp(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> signedinteger[_NBit_co]: ... + def __call__(self, __other: bool) -> signedinteger[_NBit1]: ... @overload - def __call__(self, __other: int) -> signedinteger[Union[_NBit_co, _NBitInt]]: ... + def __call__(self, __other: int) -> signedinteger[Union[_NBit1, _NBitInt]]: ... @overload def __call__( - self, __other: signedinteger[_NBit] - ) -> signedinteger[Union[_NBit_co, _NBit]]: ... + self, __other: signedinteger[_NBit2] + ) -> signedinteger[Union[_NBit1, _NBit2]]: ... - class _SignedIntMod(Protocol[_NBit_co]): + class _SignedIntMod(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> signedinteger[_NBit_co]: ... + def __call__(self, __other: bool) -> signedinteger[_NBit1]: ... @overload - def __call__(self, __other: int) -> signedinteger[Union[_NBit_co, _NBitInt]]: ... + def __call__(self, __other: int) -> signedinteger[Union[_NBit1, _NBitInt]]: ... @overload def __call__(self, __other: float) -> float64: ... @overload def __call__( - self, __other: signedinteger[_NBit] - ) -> signedinteger[Union[_NBit_co, _NBit]]: ... + self, __other: signedinteger[_NBit2] + ) -> signedinteger[Union[_NBit1, _NBit2]]: ... - class _SignedIntDivMod(Protocol[_NBit_co]): + class _SignedIntDivMod(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> _2Tuple[signedinteger[_NBit_co]]: ... + def __call__(self, __other: bool) -> _2Tuple[signedinteger[_NBit1]]: ... @overload - def __call__(self, __other: int) -> _2Tuple[signedinteger[Union[_NBit_co, _NBitInt]]]: ... + def __call__(self, __other: int) -> _2Tuple[signedinteger[Union[_NBit1, _NBitInt]]]: ... @overload def __call__(self, __other: float) -> _2Tuple[float64]: ... @overload def __call__( - self, __other: signedinteger[_NBit] - ) -> _2Tuple[signedinteger[Union[_NBit_co, _NBit]]]: ... + self, __other: signedinteger[_NBit2] + ) -> _2Tuple[signedinteger[Union[_NBit1, _NBit2]]]: ... - class _FloatOp(Protocol[_NBit_co]): + class _FloatOp(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> floating[_NBit_co]: ... + def __call__(self, __other: bool) -> floating[_NBit1]: ... @overload - def __call__(self, __other: int) -> floating[Union[_NBit_co, _NBitInt]]: ... + def __call__(self, __other: int) -> floating[Union[_NBit1, _NBitInt]]: ... @overload def __call__(self, __other: float) -> float64: ... @overload def __call__(self, __other: complex) -> complex128: ... @overload def __call__( - self, __other: Union[integer[_NBit], floating[_NBit]] - ) -> floating[Union[_NBit_co, _NBit]]: ... + self, __other: Union[integer[_NBit2], floating[_NBit2]] + ) -> floating[Union[_NBit1, _NBit2]]: ... - class _FloatMod(Protocol[_NBit_co]): + class _FloatMod(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> floating[_NBit_co]: ... + def __call__(self, __other: bool) -> floating[_NBit1]: ... @overload - def __call__(self, __other: int) -> floating[Union[_NBit_co, _NBitInt]]: ... + def __call__(self, __other: int) -> floating[Union[_NBit1, _NBitInt]]: ... @overload def __call__(self, __other: float) -> float64: ... @overload def __call__( - self, __other: Union[integer[_NBit], floating[_NBit]] - ) -> floating[Union[_NBit_co, _NBit]]: ... + self, __other: Union[integer[_NBit2], floating[_NBit2]] + ) -> floating[Union[_NBit1, _NBit2]]: ... - class _FloatDivMod(Protocol[_NBit_co]): + class _FloatDivMod(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> _2Tuple[floating[_NBit_co]]: ... + def __call__(self, __other: bool) -> _2Tuple[floating[_NBit1]]: ... @overload - def __call__(self, __other: int) -> _2Tuple[floating[Union[_NBit_co, _NBitInt]]]: ... + def __call__(self, __other: int) -> _2Tuple[floating[Union[_NBit1, _NBitInt]]]: ... @overload def __call__(self, __other: float) -> _2Tuple[float64]: ... @overload def __call__( - self, __other: Union[integer[_NBit], floating[_NBit]] - ) -> _2Tuple[floating[Union[_NBit_co, _NBit]]]: ... + self, __other: Union[integer[_NBit2], floating[_NBit2]] + ) -> _2Tuple[floating[Union[_NBit1, _NBit2]]]: ... - class _ComplexOp(Protocol[_NBit_co]): + class _ComplexOp(Protocol[_NBit1]): @overload - def __call__(self, __other: bool) -> complexfloating[_NBit_co, _NBit_co]: ... + def __call__(self, __other: bool) -> complexfloating[_NBit1, _NBit1]: ... @overload - def __call__(self, __other: int) -> complexfloating[Union[_NBit_co, _NBitInt], Union[_NBit_co, _NBitInt]]: ... + def __call__(self, __other: int) -> complexfloating[Union[_NBit1, _NBitInt], Union[_NBit1, _NBitInt]]: ... @overload def __call__(self, __other: Union[float, complex]) -> complex128: ... @overload def __call__( self, __other: Union[ - integer[_NBit], - floating[_NBit], - complexfloating[_NBit, _NBit], + integer[_NBit2], + floating[_NBit2], + complexfloating[_NBit2, _NBit2], ] - ) -> complexfloating[Union[_NBit_co, _NBit], Union[_NBit_co, _NBit]]: ... + ) -> complexfloating[Union[_NBit1, _NBit2], Union[_NBit1, _NBit2]]: ... class _NumberOp(Protocol): - def __call__(self, __other: _NumberLike) -> number: ... + def __call__(self, __other: _NumberLike_co) -> Any: ... class _ComparisonOp(Protocol[_T]): @overload diff --git a/numpy/typing/_scalars.py b/numpy/typing/_scalars.py index 90b2eff7b..516b996dc 100644 --- a/numpy/typing/_scalars.py +++ b/numpy/typing/_scalars.py @@ -2,22 +2,22 @@ from typing import Union, Tuple, Any import numpy as np -# NOTE: `_StrLike` and `_BytesLike` are pointless, as `np.str_` and `np.bytes_` -# are already subclasses of their builtin counterpart +# NOTE: `_StrLike_co` and `_BytesLike_co` are pointless, as `np.str_` and +# `np.bytes_` are already subclasses of their builtin counterpart -_CharLike = Union[str, bytes] +_CharLike_co = Union[str, bytes] -# The 6 `<X>Like` type-aliases below represent all scalars that can be +# The 6 `<X>Like_co` type-aliases below represent all scalars that can be # coerced into `<X>` (with the casting rule `same_kind`) -_BoolLike = Union[bool, np.bool_] -_UIntLike = Union[_BoolLike, np.unsignedinteger] -_IntLike = Union[_BoolLike, int, np.integer] -_FloatLike = Union[_IntLike, float, np.floating] -_ComplexLike = Union[_FloatLike, complex, np.complexfloating] -_TD64Like = Union[_IntLike, np.timedelta64] +_BoolLike_co = Union[bool, np.bool_] +_UIntLike_co = Union[_BoolLike_co, np.unsignedinteger] +_IntLike_co = Union[_BoolLike_co, int, np.integer] +_FloatLike_co = Union[_IntLike_co, float, np.floating] +_ComplexLike_co = Union[_FloatLike_co, complex, np.complexfloating] +_TD64Like_co = Union[_IntLike_co, np.timedelta64] -_NumberLike = Union[int, float, complex, np.number, np.bool_] -_ScalarLike = Union[ +_NumberLike_co = Union[int, float, complex, np.number, np.bool_] +_ScalarLike_co = Union[ int, float, complex, @@ -26,5 +26,5 @@ _ScalarLike = Union[ np.generic, ] -# `_VoidLike` is technically not a scalar, but it's close enough -_VoidLike = Union[Tuple[Any, ...], np.void] +# `_VoidLike_co` is technically not a scalar, but it's close enough +_VoidLike_co = Union[Tuple[Any, ...], np.void] diff --git a/numpy/typing/tests/data/fail/scalars.py b/numpy/typing/tests/data/fail/scalars.py index f09740875..0aeff398f 100644 --- a/numpy/typing/tests/data/fail/scalars.py +++ b/numpy/typing/tests/data/fail/scalars.py @@ -1,5 +1,6 @@ import numpy as np +f2: np.float16 f8: np.float64 # Construction @@ -74,3 +75,8 @@ f8.item((0, 1)) # E: incompatible type f8.squeeze(axis=1) # E: incompatible type f8.squeeze(axis=(0, 1)) # E: incompatible type f8.transpose(1) # E: incompatible type + +def func(a: np.float32) -> None: ... + +func(f2) # E: incompatible type +func(f8) # E: incompatible type diff --git a/numpy/typing/tests/data/reveal/nbit_base_example.py b/numpy/typing/tests/data/reveal/nbit_base_example.py index 99fb71560..d34f6f69a 100644 --- a/numpy/typing/tests/data/reveal/nbit_base_example.py +++ b/numpy/typing/tests/data/reveal/nbit_base_example.py @@ -2,9 +2,10 @@ from typing import TypeVar, Union import numpy as np import numpy.typing as npt -T = TypeVar("T", bound=npt.NBitBase) +T1 = TypeVar("T1", bound=npt.NBitBase) +T2 = TypeVar("T2", bound=npt.NBitBase) -def add(a: np.floating[T], b: np.integer[T]) -> np.floating[T]: +def add(a: np.floating[T1], b: np.integer[T2]) -> np.floating[Union[T1, T2]]: return a + b i8: np.int64 diff --git a/test_requirements.txt b/test_requirements.txt index b6aaa8995..52109a5d5 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -1,7 +1,7 @@ cython==0.29.21 wheel<0.36.3 setuptools<49.2.0 -hypothesis==6.0.0 +hypothesis==6.0.2 pytest==6.2.1 pytz==2020.5 pytest-cov==2.10.1 diff --git a/tools/openblas_support.py b/tools/openblas_support.py index dff19274e..1300795bb 100644 --- a/tools/openblas_support.py +++ b/tools/openblas_support.py @@ -13,7 +13,7 @@ from urllib.request import urlopen, Request from urllib.error import HTTPError OPENBLAS_V = '0.3.13' -OPENBLAS_LONG = 'v0.3.13' +OPENBLAS_LONG = 'v0.3.13-62-gaf2b0d02' BASE_LOC = 'https://anaconda.org/multibuild-wheels-staging/openblas-libs' BASEURL = f'{BASE_LOC}/{OPENBLAS_LONG}/download' ARCHITECTURES = ['', 'windows', 'darwin', 'aarch64', 'x86_64', |