././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.2367241 Cython-3.0.8/0000755000175100001770000000000000000000000013574 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880490.8167238 Cython-3.0.8/.gitrev0000644000175100001770000000005100000000000015071 0ustar00runnerdocker00000000000000a1b79a6bc5326406ad73af73f5b41e3bb5f8da6e ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3087223 Cython-3.0.8/CHANGES.rst0000644000175100001770000101675700000000000015417 0ustar00runnerdocker00000000000000================ Cython Changelog ================ 3.0.8 (2024-01-10) ================== Bugs fixed ---------- * Using ``const`` together with defined fused types could fail to compile. (Github issue :issue:`5230`) * A "use after free" bug was fixed in parallel sections. (Github issue :issue:`5922`) * Several types were not available as ``cython.*`` types in pure Python code. * The generated code is now correct C89 again, removing some C++ style ``//`` comments and C99-style declaration-after-code code ordering. This is still relevant for some ols C compilers, specifically ones that match old Python 2.7 installations. 3.0.7 (2023-12-19) ================== Bugs fixed ---------- * In the iterator of generator expressions, ``await`` and ``yield`` were not correctly analysed. (Github issue :issue:`5851`) * ``cpdef`` enums with the same name cimported from different modules could lead to invalid C code. (Github issue :issue:`5887`) * Some declarations in ``cpython.unicode`` were fixed and extended. (Github issue :issue:`5902`) * Compiling fused types used in pxd files could crash Cython in Python 3.11+. (Github issues :issue:`5894`, :issue:`5588`) * Source files with non-ASCII file names could crash Cython. (Github issue :issue:`5873`) * Includes all bug-fixes and features from the 0.29 maintenance branch up to the :ref:`0.29.37` release. 3.0.6 (2023-11-26) ================== Features added -------------- * Fused def function dispatch is a bit faster. * Declarations for the ``wchar`` PyUnicode API were added. (Github issue :issue:`5836`) * The Python "nogil" fork is now also detected with the new ``Py_GIL_DISABLED`` macro. Patch by Hugo van Kemenade. (Github issue :issue:`5852`) Bugs fixed ---------- * Comparing dataclasses could give different results than Python. (Github issue :issue:`5857`) * ``float(std::string)`` generated invalid C code. (Github issue :issue:`5818`) * Using ``cpdef`` functions with ``cimport_from_pyx`` failed. (Github issue :issue:`5795`) * A crash was fixed when string-formatting a Python value fails. (Github issue :issue:`5787`) * On item access, Cython could try the sequence protocol before the mapping protocol in some cases if an object supports both. (Github issue :issue:`5776`) * A C compiler warning was resolved. (Github issue :issue:`5794`) * Complex numbers failed to compile in MSVC with C11. Patch by Lysandros Nikolaou. (Github issue :issue:`5809`) * Some issues with the Limited API and with PyPy were resolved. (Github issues :issue:`5695`, :issue:`5696`) * A C++ issue in Python 3.13 was resolved. (Github issue :issue:`5790`) * Several directives are now also available (as no-ops) in Python code. (Github issue :issue:`5803`) * An error message was corrected. Patch by Mads Ynddal. (Github issue :issue:`5805`) 3.0.5 (2023-10-31) ================== Features added -------------- * Preliminary support for CPython 3.13a1 was added to allow early testing. (Github issue :issue:`5767`) Bugs fixed ---------- * A compiler crash was fixed. (Github issue :issue:`5771`) * A typo in the ``always_allow_keywords`` directive for Python code was fixed. Patch by lk-1984. (Github issue :issue:`5772`) * Some C compiler warnings were resolved. Patch by Pierre Jolivet. (Github issue :issue:`5780`) 3.0.4 (2023-10-17) ================== Features added -------------- * A new compiler directive ``show_performance_hints`` was added to disable the newly added performance hint output. (Github issue :issue:`5748`) Bugs fixed ---------- * ```cythonize` required ``distutils`` even for operations that did not build binaries. (Github issue :issue:`5751`) * A regression in 3.0.3 was fixed that prevented calling inline functions from another inline function in ``.pxd`` files. (Github issue :issue:`5748`) * Some C compiler warnings were resolved. Patch by Pierre Jolivet. (Github issue :issue:`5756`) 3.0.3 (2023-10-05) ================== Features added -------------- * More warnings were added to help users migrate and avoid bugs. (Github issue :issue:`5650`) * A warning-like category for performance hints was added that bypasses ``-Werror``. (Github issue :issue:`5673`) * FastGIL now uses standard ``thread_local`` in C++. (Github issue :issue:`5640`) * ``reference_wrapper`` was added to ``libcpp.functional``. Patch by Vyas Ramasubramani. (Github issue :issue:`5671`) * The ``cythonize`` command now supports the ``--cplus`` option known from the ``cython`` command. (Github issue :issue:`5736`) Bugs fixed ---------- * Performance regressions where the GIL was needlessly acquired were fixed. (Github issues :issue:`5670`, :issue:`5700`) * A reference leak for exceptions in Python 3.12 was resolved. Patch by Eric Johnson. (Github issue :issue:`5724`) * ``fastcall`` calls with keyword arguments generated incorrect C code. (Github issue :issue:`5665`) * Assigning the type converted result of a conditional (if-else) expression to ``int`` or ``bool`` variables could lead to incorrect C code. (Github issue :issue:`5731`) * Early (unlikely) failures in Python function wrappers no longer set a traceback in order to simplify the C code flow. Being mostly memory allocation errors, they probably would never have created a traceback anyway. (Github issue :issue:`5681`) * Relative cimports from packages with ``__init__.py`` files could fail. (Github issue :issue:`5715`) * Several issues with the Limited API support were resolved. (Github issues :issue:`5641`, :issue:`5648`, :issue:`5689`) * The code generated for special-casing both Cython functions and PyCFunctions was cleaned up to avoid calling C-API functions that were not meant for the other type respectively. This could previously trigger assertions in CPython debug builds and now also plays better with the Limited API. (Github issues :issue:`4804`, :issue:`5739`) * Fix some C compiler warnings. Patches by Ralf Gommers, Oleksandr Pavlyk, Sebastian Koslowski et al. (Github issues :issue:`5651`, :issue:`5663`, :issue:`5668`, :issue:`5717`, :issue:`5726`, :issue:`5734`) * Generating gdb debugging information failed when using generator expressions. Patch by Oleksandr Pavlyk. (Github issue :issue:`5552`) * Passing a ``setuptools.Extension`` into ``cythonize()`` instead of a ``distutils.Extension`` could make it miss the matching extensions. * ``cython -M`` needlessly required ``distutils``, which made it fail in Python 3.12. (Github issue :issue:`5681`) Other changes ------------- * The visible deprecation warning for ``DEF`` was removed again since it proved difficult for some users to migrate away from it. The statement is still meant to be removed at some point (and thus, like ``IF``, should not be used in new code), but the time for sunset is probably not around the corner. (Github issue :issue:`4310`) * The ``np_pythran`` option raise a ``DeprecationWarning`` if it receives other values than ``True`` and ``False``. This will eventually be disallowed (in line with all other boolean options). 3.0.2 (2023-08-27) ================== Bugs fixed ---------- * Using ``None`` as default value for arguments annotated as ``int`` could crash Cython. (Github issue :issue:`5643`) * Default values of fused types that include ``complex`` could generate invalid C code with ``-DCYTHON_CCOMPLEX=0``. (Github issue :issue:`5644`) * Using C++ enum class types in extension type method signatures could generate invalid C code. (Github issue :issue:`5637`) 3.0.1 (2023-08-25) ================== Features added -------------- * The error messages regarding exception declarations were improved in order to give better help about possible reasons and fixes. (Github issue :issue:`5547`) Bugs fixed ---------- * Memory view types in Python argument annotations no longer accept ``None``. They now require an explicit ``Optional[]`` or a ``None`` default value in order to allow ``None`` to be passed. This was an oversight in the 3.0.0 release and is a BACKWARDS INCOMPATIBLE change. However, since it only applies to code using Python syntax, it probably only applies to newly written code that was written for Cython 3.0 and can easily be adapted. In most cases, we expect that this change will avoid bugs in user code rather than produce problems. (Github issue :issue:`5612`) * ``nogil`` functions using parallel code could freeze when called with the GIL held. (Github issues :issue:`5564`, :issue:`5573`) * Relative cimports could end up searching globally and find the same package installed elsewhere, potentially in another version. (Github issue :issue:`5511`) * Attribute lookups on known standard library modules could accidentally search in the module namespace instead. (Github issue :issue:`5536`) * Using constructed C++ default arguments could generate invalid C++ code. (Github issue :issue:`5553`) * ``libcpp.memory.make_unique()`` was lacking C++ exception handling. (Github issue :issue:`5560`) * Some non-public and deprecated CAPI usages were replaced by public (and thus more future proof) API code. * Many issues with the Limited API support were resolved. Patches by Lisandro Dalcin et al. (Github issues :issue:`5549`, :issue:`5550`, :issue:`5556`, :issue:`5605`, :issue:`5617`) * Some C compiler warnings were resolved. Patches by Matti Picus et al. (Github issues :issue:`5557`, :issue:`5555`) * Large Python integers are now stored in hex instead of decimal strings to work around security limits in Python and generally speed up their Python object creation. * ``NULL`` could not be used as default for fused type pointer arguments. (Github issue :issue:`5554`) * C functions that return pointer types now return ``NULL`` as default exception value. Previously, calling code wasn't aware of this and always tested for raised exceptions. (Github issue :issue:`5554`) * Untyped literal default arguments in fused functions could generate invalid C code. (Github issue :issue:`5614`) * C variables declared as ``const`` could generate invalid C code when used in closures, generator expressions, ctuples, etc. (Github issues :issue:`5558`, :issue:`5333`) * Enums could not refer to previously defined enums in their definition. (Github issue :issue:`5602`) * The Python conversion code for anonymous C enums conflicted with regular int conversion. (Github issue :issue:`5623`) * Using memory views for property methods (and other special methods) could lead to refcounting problems. (Github issue :issue:`5571`) * Star-imports could generate code that tried to assign to constant C macros like ``PY_SSIZE_T_MAX`` and ``PY_SSIZE_T_MIN``. Patch by Philipp Wagner. (Github issue :issue:`5562`) * ``CYTHON_USE_TYPE_SPECS`` can now be (explicitly) enabled in PyPy. * The template parameter "delimeters" in the Tempita ``Template`` class was corrected to "delimiters". The old spelling is still available in the main template API but now issues a ``DeprecationWarning``. (Github issue :issue:`5608`) * The ``cython --version`` output is now less likely to reach both stdout and stderr. Patch by Eli Schwartz. (Github issue :issue:`5504`) * The sdist was missing the `Shadow.pyi` stub file. 3.0.0 unified release notes =========================== Cython 3.0.0 has been a very large effort that cleaned up many old warts, introduced many new features, and introduces a couple of intentional behaviour changes, even though the goal remained to stay compatible as much as possible with Cython 0.29.x. For details, see the `migration guide`_. .. _`migration guide`: https://cython.readthedocs.io/en/latest/src/userguide/migrating_to_cy30.html As the development was spread out over several years, a lot of things have happened in the meantime. Many crucial bugfixes and some features were backported to 0.29.x and are not strictly speaking "new" in Cython 3.0.0. Major themes in 3.0.0 ===================== Compatibility with CPython and the Python C API ----------------------------------------------- Since Cython 3.0.0 started development, CPython 3.8-3.11 were released. All these are supported in Cython, including experimental support for the in-development CPython 3.12. On the other end of the spectrum, support for Python 2.6 was dropped. Cython interacts very closely with the C-API of Python, which is where most of the adaptation work happens. Related changes ^^^^^^^^^^^^^^^ * The long deprecated include files ``python_*``, ``stdio``, ``stdlib`` and ``stl`` in ``Cython/Includes/Deprecated/`` were removed. Use the ``libc.*`` and ``cpython.*`` pxd modules instead. Patch by Jeroen Demeyer. (Github issue :issue:`2904`) * The ``Py_hash_t`` type failed to accept arbitrary "index" values. (Github issue :issue:`2752`) * ``@cython.trashcan(True)`` can be used on an extension type to enable the CPython :ref:`trashcan`. This allows deallocating deeply recursive objects without overflowing the stack. Patch by Jeroen Demeyer. (Github issue :issue:`2842`) * ``PyEval_InitThreads()`` is no longer used in Py3.7+ where it is a no-op. * A low-level inline function ``total_seconds(timedelta)`` was added to ``cpython.datetime`` to bypass the Python method call. Note that this function is not guaranteed to give exactly the same results for very large time intervals. Patch by Brock Mendel. (Github issue :issue:`3616`) * The internal CPython macro ``Py_ISSPACE()`` is no longer used. Original patch by Andrew Jones. (Github issue :issue:`4111`) * The value ``PyBUF_MAX_NDIM`` was added to the ``cpython.buffer`` module. Patch by John Kirkham. (Github issue :issue:`3811`) * A new module ``cpython.time`` was added with some low-level alternatives to Python's ``time`` module. Patch by Brock Mendel. (Github issue :issue:`3767`) * More C-API declarations for ``cpython.datetime`` were added. Patch by Bluenix2. (Github issue :issue:`4128`) * C-API declarations for context variables in Python 3.7 were added. Original patch by Zolisa Bleki. (Github issue :issue:`2281`) * C-API declarations for ``cpython.fileobject`` were added. Patch by Zackery Spytz. (Github issue :issue:`3906`) * The signature of ``PyFloat_FromString()`` in ``cpython.float`` was changed to match the signature in Py3. It still has an automatic fallback for Py2. (Github issue :issue:`3909`) * ``PyMem_[Raw]Calloc()`` was added to the ``cpython.mem`` declarations. Note that the ``Raw`` versions are no longer #defined by Cython. The previous macros were not considered safe. Patch by William Schwartz and David Woods. (Github issue :issue:`3047`) * The runtime size check for imported ``PyVarObject`` types was improved to reduce false positives and adapt to Python 3.11. Patch by David Woods. (Github issues :issue:`4827`, :issue:`4894`) * The generated C code failed to compile in CPython 3.11a4 and later. (Github issue :issue:`4500`) * ``pyximport`` no longer uses the deprecated ``imp`` module. Patch by Matúš Valo. (Github issue :issue:`4560`) * Improvements to ``PyTypeObject`` definitions in pxd wrapping of libpython. Patch by John Kirkham. (Github issue :issue:`4699`) * Some old usages of the deprecated Python ``imp`` module were replaced with ``importlib``. Patch by Matúš Valo. (Github issue :issue:`4640`) * ``cpdef`` enums no longer use ``OrderedDict`` but ``dict`` in Python 3.6 and later. Patch by GalaxySnail. (Github issue :issue:`5180`) * Several problems with CPython 3.12 were resolved. (Github issue :issue:`5238`) * The exception handling code was adapted to CPython 3.12. (Github issue :issue:`5442`) * The Python ``int`` handling code was adapted to make use of the new ``PyLong`` internals in CPython 3.12. (Github issue :issue:`5353`) * A compile error when using ``__debug__`` was resolved. * The deprecated ``_PyGC_FINALIZED()`` C-API macro is no longer used. Patch by Thomas Caswell and Matúš Valo. (Github issue :issue:`5481`) * A crash in Python 2.7 was fixed when cleaning up extension type instances at program end. Compatibility with other Python implementations ----------------------------------------------- Cython tries to support other Python implementations, largely on a best-effort basis. The most advanced support exists for PyPy, which is tested in our CI and considered supported. Related changes ^^^^^^^^^^^^^^^ * An unsupported C-API call in PyPy was fixed. Patch by Max Bachmann. (Github issue :issue:`4055`) * Support for the now unsupported Pyston V1 was removed in favour of Pyston V2. Patch by Marius Wachtler. (Github issue :issue:`4211`) * A C compiler warning in PyPy3 regarding ``PyEval_EvalCode()`` was resolved. * Some compatibility issues with PyPy were resolved. Patches by Max Bachmann, Matti Picus. (Github issues :issue:`4454`, :issue:`4477`, :issue:`4478`, :issue:`4509`, :issue:`4517`) * An initial set of adaptations for GraalVM Python was implemented. Note that this does not imply any general support for this target or that your code will work at all in this environment. But testing should be possible now. Patch by David Woods. (Github issue :issue:`4328`) * A work-around for StacklessPython < 3.8 was disabled in Py3.8 and later. (Github issue :issue:`4329`) Initial support for Limited API ------------------------------- CPython provides a stable, limited subset of its C-API as the so-called Limited API. This C-API comes with the guarantee of a stable ABI, meaning that extensions modules that were compiled for one version of CPython can also be imported in later versions without recompilation. There is initial support for this in Cython. By defining the ``CYTHON_LIMITED_API`` macro, Cython cuts down its C-API usage and tries to adhere to the Limited C-API, probably at the cost of a bit of performance. In order to get full benefit from the limited API you will also need to define the CPython macro ``Py_LIMITED_API`` to a specific CPython compatibility version, which additionally restricts the C-API during the C compilation, thus enforcing the forward compatibility of the extension module. Note that "initial support" in Cython really means that setting the ``Py_LIMITED_API`` macro will almost certainly not yet work for your specific code. There are limitations in the Limited C-API that are difficult for Cython to generate C code for, so some advanced Python features (like async code) may not lead to C code that cannot adhere to the Limited C-API, or where Cython simply does not know yet how to adhere to it. Basically, if you get your code to compile with both macros set, and it passes your test suite, then it should be possible to import the extension module also in later CPython versions. The experimental feature flags ``CYTHON_USE_MODULE_STATE`` and ``CYTHON_USE_TYPE_SPECS`` enable some individual aspects of the Limited API implementation independently. Related changes ^^^^^^^^^^^^^^^ * Preliminary support for the CPython's ``Py_LIMITED_API`` (stable ABI) is available by setting the ``CYTHON_LIMITED_API`` C macro. Note that the support is currently in an early stage and many features do not yet work. You currently still have to define ``Py_LIMITED_API`` externally in order to restrict the API usage. This will change when the feature stabilises. Patches by Eddie Elizondo and David Woods. (Github issues :issue:`3223`, :issue:`3311`, :issue:`3501`) * Limited API support was improved. Patches by Matthias Braun. (Github issues :issue:`3693`, :issue:`3707`) * New C feature flags: ``CYTHON_USE_MODULE_STATE``, ``CYTHON_USE_TYPE_SPECS`` Both are currently considered experimental. (Github issue :issue:`3611`) * ``_Py_TPFLAGS_HAVE_VECTORCALL`` was always set on extension types when using the limited API. Patch by David Woods. (Github issue :issue:`4453`) * Limited API C preprocessor warning is compatible with MSVC. Patch by Victor Molina Garcia. (Github issue :issue:`4826`) * The embedding code no longer calls deprecated C-API functions but uses the new ``PyConfig`` API instead on CPython versions that support it (3.8+). Patch by Alexander Shadchin. (Github issue :issue:`4895`) * Some C code issue were resolved for the Limited API target. (Github issues :issue:`5264`, :issue:`5265`, :issue:`5266`) * Conversion of Python ints to C ``int128`` is now always supported, although slow if dedicated C-API support is missing (``_PyLong_AsByteArray()``), specifically in the Limited C-API. (Github issue :issue:`5419`) * Custom buffer slot methods are now supported in the Limited C-API of Python 3.9+. Patch by Lisandro Dalcin. (Github issue :issue:`5422`) Improved fidelity to Python semantics ------------------------------------- Implemented PEPs ^^^^^^^^^^^^^^^^ * `PEP-3131`_: Supporting Non-ASCII Identifiers (Github issue :issue:`2601`) * `PEP-479`_: `generator_stop` (enabled by default for `language_level=3`) (Github issue :issue:`2580`) * `PEP-487`_: Simpler customisation of class creation (Github issue :issue:`2781`) * `PEP-563`_: Postponed Evaluation of Annotations (Github issue :issue:`3285`) * `PEP-570`_: Positional-Only Parameters (Github issue :issue:`2915`) * `PEP-572`_: Assignment Expressions (a.k.a. the walrus operator `:=`) (Github issue :issue:`2636`) * `PEP-590`_: Vectorcall protocol (Github issue :issue:`2263`) * `PEP-614`_: Relaxing Grammar Restrictions On Decorators (Github issue :issue:`4570`) Typing support in the sense of `PEP-484`_ (Github issues :issue:`3949`, :issue:`4243`) and `PEP-560`_ (Github issues :issue:`2753`, :issue:`3537`, :issue:`3764`) was also improved. .. _`PEP-3131`: https://www.python.org/dev/peps/pep-3131 .. _`PEP-479`: https://www.python.org/dev/peps/pep-0479 .. _`PEP-484`: https://www.python.org/dev/peps/pep-0484 .. _`PEP-487`: https://www.python.org/dev/peps/pep-0487 .. _`PEP-560`: https://www.python.org/dev/peps/pep-0560 .. _`PEP-563`: https://www.python.org/dev/peps/pep-0563 .. _`PEP-570`: https://www.python.org/dev/peps/pep-0570 .. _`PEP-572`: https://www.python.org/dev/peps/pep-0572 .. _`PEP-590`: https://www.python.org/dev/peps/pep-0590 .. _`PEP-614`: https://www.python.org/dev/peps/pep-0614 The default language level was changed to ``3str``, i.e. Python 3 semantics, but with ``str`` literals (also in Python 2.7). This is a backwards incompatible change from the previous default of Python 2 semantics. The previous behaviour is available through the directive ``language_level=2``. (Github issue :issue:`2565`). This covers changes such as using the ``print``-function instead of the ``print``-statement, and integer-integer division giving a floating point answer. Most of these changes were available in earlier versions of Cython but are now the default. Cython 3.0.0 also aligns its own language semantics more closely with Python, in particular: * the power operator has changed to give a result matching what Python does rather than keeping the same types as the input (as in C), * operator overloading of ``cdef classes`` behaves much more like Python classes, * Cython's behaviour when using type annotations aligns more closely with their standard use in Python. Related changes ^^^^^^^^^^^^^^^ * Cython no longer generates ``__qualname__`` attributes for classes in Python 2.x since they are problematic there and not correctly maintained for subclasses. Patch by Jeroen Demeyer. (Github issue :issue:`2772`) * Binding staticmethods of Cython functions were not behaving like Python methods. Patch by Jeroen Demeyer. (Github issue :issue:`3106`, :issue:`3102`) * Compiling package ``__init__`` files could fail under Windows due to an undefined export symbol. (Github issue :issue:`2968`) * ``__init__.pyx`` files were not always considered as package indicators. (Github issue :issue:`2665`) * Setting ``language_level=2`` in a file did not work if ``language_level=3`` was enabled globally before. Patch by Jeroen Demeyer. (Github issue :issue:`2791`) * ``__doc__`` was not available inside of the class body during class creation. (Github issue :issue:`1635`) * The first function line number of functions with decorators pointed to the signature line and not the first decorator line, as in Python. Patch by Felix Kohlgrüber. (Github issue :issue:`2536`) * Pickling unbound methods of Python classes failed. Patch by Pierre Glaser. (Github issue :issue:`2972`) * Item access (subscripting) with integer indices/keys always tried the Sequence protocol before the Mapping protocol, which diverged from Python semantics. It now passes through the Mapping protocol first when supported. (Github issue :issue:`1807`) * Nested dict literals in function call kwargs could incorrectly raise an error about duplicate keyword arguments, which are allowed when passing them from dict literals. (Github issue :issue:`2963`) * Diverging from the usual behaviour, ``len(memoryview)``, ``len(char*)`` and ``len(Py_UNICODE*)`` returned an unsigned ``size_t`` value. They now return a signed ``Py_ssize_t``, like other usages of ``len()``. * The unicode methods ``.upper()``, ``.lower()`` and ``.title()`` were incorrectly optimised for single character input values and only returned the first character if multiple characters should have been returned. They now use the original Python methods again. * The ``cython.view.array`` type supports inheritance. Patch by David Woods. (Github issue :issue:`3413`) * The builtin ``abs()`` function can now be used on C numbers in nogil code. Patch by Elliott Sales de Andrade. (Github issue :issue:`2748`) * The attributes ``gen.gi_frame`` and ``coro.cr_frame`` of Cython compiled generators and coroutines now return an actual frame object for introspection. (Github issue :issue:`2306`) * Inlined properties can be defined for external extension types. Patch by Matti Picus. (Github issue :issue:`2640`, redone later in :issue:`3571`) * Unicode module names and imports are supported. Patch by David Woods. (Github issue :issue:`3119`) * ``__arg`` argument names in methods were not mangled with the class name. Patch by David Woods. (Github issue :issue:`1382`) * With ``language_level=3/3str``, Python classes without explicit base class are now new-style (type) classes also in Py2. Previously, they were created as old-style (non-type) classes. (Github issue :issue:`3530`) * Conditional blocks in Python code that depend on ``cython.compiled`` are eliminated at an earlier stage, which gives more freedom in writing replacement Python code. Patch by David Woods. (Github issue :issue:`3507`) * Python private name mangling now falls back to unmangled names for non-Python globals, since double-underscore names are not uncommon in C. Unmangled Python names are also still found as a legacy fallback but produce a warning. Patch by David Woods. (Github issue :issue:`3548`) * The ``print`` statement (not the ``print()`` function) is allowed in ``nogil`` code without an explicit ``with gil`` section. * ``repr()`` was assumed to return ``str`` instead of ``unicode`` with ``language_level=3``. (Github issue :issue:`3736`) * Type inference now understands that ``a, *b = x`` assigns a list to ``b``. * No/single argument functions now accept keyword arguments by default in order to comply with Python semantics. The marginally faster calling conventions ``METH_NOARGS`` and ``METH_O`` that reject keyword arguments are still available with the directive ``@cython.always_allow_keywords(False)``. (Github issue :issue:`3090`) * Special methods for binary operators now follow Python semantics. Rather than e.g. a single ``__add__`` method for cdef classes, where "self" can be either the first or second argument, one can now define both ``__add__`` and ``__radd__`` as for standard Python classes. This behavior can be disabled with the ``c_api_binop_methods`` directive to return to the previous semantics in Cython code (available from Cython 0.29.20), or the reversed method (``__radd__``) can be implemented in addition to an existing two-sided operator method (``__add__``) to get a backwards compatible implementation. (Github issue :issue:`2056`) * Generator expressions in pxd-overridden ``cdef`` functions could fail to compile. Patch by Matúš Valo. (Github issue :issue:`3477`) * Calls to ``.__class__()`` of a known extension type failed. Patch by David Woods. (Github issue :issue:`3954`) * Structs could not be instantiated with positional arguments in pure Python mode. * Annotations were not exposed on annotated (data-)classes. Patch by matsjoyce. (Github issue :issue:`4151`) * Docstrings of ``cpdef`` enums are now copied to the enum class. Patch by matham. (Github issue :issue:`3805`) * ``asyncio.iscoroutinefunction()`` now recognises coroutine functions also when compiled by Cython. Patch by Pedro Marques da Luz. (Github issue :issue:`2273`) * Self-documenting f-strings (``=``) were implemented. Patch by davfsa. (Github issue :issue:`3796`) * ``cython.array`` supports simple, non-strided views. (Github issue :issue:`3775`) * Attribute annotations in Python classes are now ignored, because they are just Python objects in a dict (as opposed to the fields of extension types). Patch by David Woods. (Github issues :issue:`4196`, :issue:`4198`) * A warning was added when ``__defaults__`` or ``__kwdefaults__`` of Cython compiled functions were re-assigned, since this does not current have an effect. Patch by David Woods. (Github issue :issue:`2650`) * The ``self`` argument of static methods in .pxd files was incorrectly typed. Patch by David Woods. (Github issue :issue:`3174`) * Default values for memory views arguments were not properly supported. Patch by Corentin Cadiou. (Github issue :issue:`4313`) * Python object types were not allowed as ``->`` return type annotations. Patch by Matúš Valo. (Github issue :issue:`4433`) * The excess arguments in a for-in-range loop with more than 3 arguments to `range()` were silently ignored. Original patch by Max Bachmann. (Github issue :issue:`4550`) * Unsupported decorators on cdef functions were not rejected in recent releases. Patch by David Woods. (Github issue :issue:`4322`) * Fused functions were binding unnecessarily, which prevented them from being pickled. Patch by David Woods. (Github issue :issue:`4370`) * Decorators on inner functions were not evaluated in the right scope. Patch by David Woods. (Github issue :issue:`4367`) * Cython did not type the ``self`` argument in special binary methods. Patch by David Woods. (Github issue :issue:`4434`) * Circular imports of compiled modules could fail needlessly even when the import could already be resolved from ``sys.modules``. Patch by Syam Gadde. (Github issue :issue:`4390`) * ``__del__(self)`` on extension types now maps to ``tp_finalize`` in Python 3. Original patch by ax487. (Github issue :issue:`3612`) * Reusing an extension type attribute name as a method name is now an error. Patch by 0dminnimda. (Github issue :issue:`4661`) * When using type annotations, ``func(x: list)`` or ``func(x: ExtType)`` (and other Python builtin or extension types) no longer allow ``None`` as input argument to ``x``. This is consistent with the normal typing semantics in Python, and was a common gotcha for users who did not expect ``None`` to be allowed as input. To allow ``None``, use ``typing.Optional`` as in ``func(x: Optional[list])``. ``None`` is also automatically allowed when it is used as default argument, i.e. ``func(x: list = None)``. ``int`` and ``float`` are now also recognised in type annotations and restrict the value type at runtime. They were previously ignored. Note that, for backwards compatibility reasons, the new behaviour does not apply when using Cython's C notation, as in ``func(list x)``. Here, ``None`` is still allowed, as always. Also, the ``annotation_typing`` directive can now be enabled and disabled more finely within the module. (Github issues :issue:`2696`, :issue:`3883`, :issue:`4606`, :issue:`4669`, :issue:`4886`) * The parser allowed some invalid spellings of ``...``. Patch by 0dminnimda. (Github issue :issue:`4868`) * The ``__self__`` attribute of fused functions reports its availability correctly with ``hasattr()``. Patch by David Woods. (Github issue :issue:`4808`) * Several optimised string methods failed to accept ``None`` as arguments to their options. Test patch by Kirill Smelkov. (Github issue :issue:`4737`) * Cython generators and coroutines now identify as ``CO_ASYNC_GENERATOR``, ``CO_COROUTINE`` and ``CO_GENERATOR`` accordingly. (Github issue :issue:`4902`) * Memory views and the internal Cython array type now identify as ``collections.abc.Sequence``. Patch by David Woods. (Github issue :issue:`4817`) * Context managers can be written in parentheses. Patch by David Woods. (Github issue :issue:`4814`) * Some parser issues were resolved. (Github issue :issue:`4992`) * Unused ``**kwargs`` arguments did not show up in ``locals()``. (Github issue :issue:`4899`) * Relative imports failed in compiled ``__init__.py`` package modules. Patch by Matúš Valo. (Github issue :issue:`3442`) * Extension types are now explicitly marked as immutable types to prevent them from being considered mutable. Patch by Max Bachmann. (Github issue :issue:`5023`) * ``int(Py_UCS4)`` returned the code point instead of the parsed digit value. (Github issue :issue:`5216`) * Calling bound classmethods of builtin types could fail trying to call the unbound method. (Github issue :issue:`5051`) * Generator expressions and comprehensions now look up their outer-most iterable on creation, as Python does, and not later on start, as they did previously. (Github issue :issue:`1159`) * Bound C methods can now coerce to Python objects. (Github issues :issue:`4890`, :issue:`5062`) * ``cpdef`` enums can now be pickled. (Github issue :issue:`5120`) * The Python Enum of a ``cpdef enum`` now inherits from ``IntFlag`` to better match both Python and C semantics of enums. (Github issue :issue:`2732`) * The special ``__*pow__`` methods now support the 2- and 3-argument variants. (Github issue :issue:`5160`) * The ``**`` power operator now behaves more like in Python by returning the correct complex result if required by math. A new ``cpow`` directive was added to turn on the previous C-like behaviour. (Github issue :issue:`4936`) * With ``language_level=2``, imports of modules in packages could return the wrong module in Python 3. (Github issue :issue:`5308`) * Function signatures containing a type like `tuple[()]` could not be printed. Patch by Lisandro Dalcin. (Github issue :issue:`5355`) * ``__qualname__`` and ``__module__`` were not available inside of class bodies. (Github issue :issue:`4447`) * A new directive ``embedsignature.format`` was added to select the format of the docstring embedded signatures between ``python``, ``c`` and argument ``clinic``. Patch by Lisandro Dalcin. (Github issue :issue:`5415`) * ctuples can now be assigned from arbitrary sequences, not just Python tuples. Improvements in Pure Python mode -------------------------------- Cython strives to be able to parse newer Python constructs for use with its `pure python`_ mode, which has been a focus. In short, this allows to compile a wider range of Python code into optimized C code. .. _`pure python`: https://cython.readthedocs.io/en/latest/src/tutorial/pure.html Pure python mode gained many new features and was generally overhauled to make it as capable as the Cython syntax. Except for using external C/C++ libraries, it should now be possible to express all Cython code and use all features in regular Python syntax. The very few remaining exceptions or bugs are noted in the documentation. Additionally, the documentation has been substantially updated (primarily by Matúš Valo and 0dminnimda) to show both the older Cython syntax and pure Python syntax. Related changes ^^^^^^^^^^^^^^^ * The ``cython.declare()`` and ``cython.cast()`` functions could fail in pure mode. Patch by Dmitry Shesterkin. (Github issue :issue:`3244`) * Fused argument types were not correctly handled in type annotations and ``cython.locals()``. Patch by David Woods. (Github issues :issue:`3391`, :issue:`3142`) * ``nogil`` functions now avoid acquiring the GIL on function exit if possible even if they contain ``with gil`` blocks. (Github issue :issue:`3554`) * The ``@returns()`` decorator propagates exceptions by default for suitable C return types when no ``@exceptval()`` is defined. (Github issues :issue:`3625`, :issue:`3664`) * Extension types inheriting from Python classes could not safely be exposed in ``.pxd`` files. (Github issue :issue:`4106`) * Default arguments of methods were not exposed for introspection. Patch by Vladimir Matveev. (Github issue :issue:`4061`) * Literal list assignments to pointer variables declared in PEP-526 notation failed to compile. * The type ``cython.Py_hash_t`` is available in Python mode. * A ``cimport`` is now supported in pure Python code by prefixing the imported module name with ``cython.cimports.``, e.g. ``from cython.cimports.libc.math import sin``. (GIthub issue :issue:`4190`) * Directives starting with ``optimization.*`` in pure Python mode were incorrectly named. It should have been ``optimize.*``. Patch by David Woods. (Github issue :issue:`4258`) * Invalid and misspelled ``cython.*`` module names were not reported as errors. (Github issue :issue:`4947`) * The ``annotation_typing`` directive was missing in pure Python mode. Patch by 0dminnimda. (Github issue :issue:`5194`) * Memoryviews with ``object`` item type were not supported in Python type declarations. (Github issue :issue:`4907`) * Subscripted builtin types in type declarations (like ``list[float]``) are now better supported. (Github issue :issue:`5058`) * Unknown type annotations (e.g. because of typos) now emit a warning at compile time. Patch by Matúš Valo. (Github issue :issue:`5070`) * ``typing.Optional`` could fail on tuple types. (Github issue :issue:`5263`) * ``from cython cimport … as …`` could lead to imported names not being found in annotations. Patch by Chia-Hsiang Cheng. (Github issue :issue:`5235`) * Simple tuple types like ``(int, int)`` are no longer accepted in Python annotations and require the Python notation instead (e.g. ``tuple[cython.int, cython.int]``). (Github issue :issue:`5397`) * The Python implementation of ``cimport cython.cimports…`` could raise an ``ImportError`` instead of an ``AttributeError`` when looking up package variable names. Patch by Matti Picus. (Github issue :issue:`5411`) * A new decorator ``@cython.with_gil`` is available in Python code to match the ``with gil`` function declaration in Cython syntax. * ``with gil`` and ``with nogil(flag)`` now accept their flag argument also in Python code. Patch by Matúš Valo. (Github issue :issue:`5113`) Code generation changes ----------------------- Cython has gained several major new features that speed up both the development and the code. Dataclasses have gained an extension type equivalent that implements the dataclass features in C code. Similarly, the ``@functools.total_ordering`` decorator to an extension type will implement the comparison functions in C. Finally, NumPy ufuncs can be generated from simple computation functions with the new ``@cython.ufunc`` decorator. Related changes ^^^^^^^^^^^^^^^ * ``with gil/nogil`` statements can be conditional based on compile-time constants, e.g. fused type checks. Patch by Noam Hershtig. (Github issue :issue:`2579`) * The names of Cython's internal types (functions, generator, coroutine, etc.) are now qualified with the module name of the internal Cython module that is used for sharing them across Cython implemented modules, for example ``_cython_3_0a5.coroutine``. This was done to avoid making them look like homeless builtins, to help with debugging, and in order to avoid a CPython warning according to https://bugs.python.org/issue20204 * A ``@cython.total_ordering`` decorator has been added to automatically implement all comparison operators, similar to ``functools.total_ordering``. Patch by Spencer Brown. (Github issue :issue:`2090`) * A new decorator ``@cython.dataclasses.dataclass`` was implemented that provides compile time dataclass generation capabilities to ``cdef`` classes (extension types). Patch by David Woods. (Github issue :issue:`2903`). ``kw_only`` dataclasses added by Yury Sokov. (Github issue :issue:`4794`) * A new function decorator ``@cython.ufunc`` automatically generates a (NumPy) ufunc that applies the calculation function to an entire memoryview. (Github issue :issue:`4758`) * Generated NumPy ufuncs could crash for large arrays due to incorrect GIL handling. (Github issue :issue:`5328`) * Some invalid directive usages are now detected and rejected, e.g. using ``@ccall`` together with ``@cfunc``, and applying ``@cfunc`` to a ``@ufunc``. Cython also warns now when a directive is applied needlessly. (Github issue :issue:`5399` et al.) * The normal ``@dataclasses.dataclass`` and ``@functools.total_ordering`` decorators can now be used on extension types. Using the corresponding ``@cython.*`` decorator will automatically turn a Python class into an extension type (no need for ``@cclass``). (Github issue :issue:`5292`) Interaction with numpy ---------------------- The NumPy declarations (``cimport numpy``) were moved over to the NumPy project in order to allow version specific changes on their side. One effect is that Cython does not use deprecated NumPy C-APIs any more. Thus, you can define the respective NumPy C macro to get rid of the compatibility warning at C compile time. Related changes ^^^^^^^^^^^^^^^ * ``cython.inline()`` now sets the ``NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION`` C macro automatically when ``numpy`` is imported in the code, to avoid C compiler warnings about deprecated NumPy C-API usage. * Deprecated NumPy API usages were removed from ``numpy.pxd``. Patch by Matti Picus. (Github issue :issue:`3365`) * ``numpy.import_array()`` is automatically called if ``numpy`` has been cimported and it has not been called in the module code. This is intended as a hidden fail-safe so user code should continue to call ``numpy.import_array``. Patch by David Woods. (Github issue :issue:`3524`) * The outdated getbuffer/releasebuffer implementations in the NumPy declarations were removed so that buffers declared as ``ndarray`` now use the normal implementation in NumPy. * Several macros/functions declared in the NumPy API are now usable without holding the GIL. * The ``numpy`` declarations were updated. Patch by Brock Mendel. (Github issue :issue:`3630`) * ``ndarray.shape`` failed to compile with Pythran and recent NumPy. Patch by Serge Guelton. (Github issue :issue:`3762`) * A C-level compatibility issue with recent NumPy versions was resolved. Patch by David Woods. (Github issue :issue:`4396`) * The generated modules no longer import NumPy internally when using fused types but no memoryviews. Patch by David Woods. (Github issue :issue:`4935`) * ``np.long_t`` and ``np.ulong_t`` were removed from the NumPy declarations, syncing Cython with upstream NumPy v1.25.0. The aliases were confusing since they could mean different things on different platforms. Exception handling ------------------ Cython-implemented C functions now propagate exceptions by default, rather than swallowing them in non-object returning function if the user forgot to add an ``except`` declaration to the signature. This was a long-standing source of bugs, but can require adding the ``noexcept`` declaration to existing functions if exception propagation is really undesired. (Github issue :issue:`4280`) To ease the transition for this break in behaviour, it is possible to set ``legacy_implicit_noexcept=True``. Related changes ^^^^^^^^^^^^^^^ * The ``assert`` statement is allowed in ``nogil`` sections. Here, the GIL is only acquired if the ``AssertionError`` is really raised, which means that the evaluation of the asserted condition only allows C expressions. * The exception handling annotation ``except +*`` was broken. Patch by David Woods. (Github issues :issue:`3065`, :issue:`3066`) * Improve conversion between function pointers with non-identical but compatible exception specifications. Patches by David Woods. (Github issues :issue:`4770`, :issue:`4689`) * Exceptions within for-loops that run over memoryviews could lead to a ref-counting error. Patch by David Woods. (Github issue :issue:`4662`) * To opt out of the new, safer exception handling behaviour, legacy code can set the new directive ``legacy_implicit_noexcept=True`` for a transition period to keep the previous, unsafe behaviour. This directive will eventually be removed in a later release. Patch by Matúš Valo. (Github issue :issue:`5094`) * Cython implemented C functions now propagate exceptions by default, rather than swallowing them in non-object returning function if the user forgot to add an ``except`` declaration to the signature. This was a long-standing source of bugs, but can require adding the ``noexcept`` declaration to existing functions if exception propagation is really undesired. (Github issue :issue:`4280`) * The code ``except +nogil`` (declaring a C++ exception handler function called ``nogil``) is now rejected because it is almost certainly a typo from ``except + nogil``. (Github issue :issue:`5430`) * Handling freshly raised exceptions that didn't have a traceback yet could crash. (Github issue :issue:`5495`) Optimizations ------------- Generating efficient code has long been a goal of Cython, and 3.0 continues that. Probably the most significant change is that Cython functions use the PEP-590 vectorcall protocol on Python 3.7 and higher. Related changes ^^^^^^^^^^^^^^^ * Name lookups in class bodies no longer go through an attribute lookup. Patch by Jeroen Demeyer. (Github issue :issue:`3100`) * Extension types that do not need their own ``tp_new`` implementation (because they have no object attributes etc.) directly inherit the implementation of their parent type if possible. (Github issue :issue:`1555`) * Some list copying is avoided internally when a new list needs to be created but we already have a fresh one. (Github issue :issue:`3494`) * Multiplication of Python numbers with small constant integers is faster. (Github issue :issue:`2808`) * String concatenation can now happen in place if possible, by extending the existing string rather than always creating a new one. Patch by David Woods. (Github issue :issue:`3453`) * The ``str()`` builtin now calls ``PyObject_Str()`` instead of going through a Python call. Patch by William Ayd. (Github issue :issue:`3279`) * Reimports of already imported modules are substantially faster. (Github issue :issue:`2854`) * The dispatch to fused functions is now linear in the number of arguments, which makes it much faster, often 2x or more, and several times faster for larger fused types with many specialisations. Patch by will-ca. (Github issue :issue:`1385`) * The fastcall/vectorcall protocols are used for several internal Python calls. (Github issue :issue:`3540`) * ``nogil`` functions now avoid acquiring the GIL on function exit if possible even if they contain ``with gil`` blocks. (Github issue :issue:`3554`) * Type inference now works for memory views and slices. Patch by David Woods. (Github issue :issue:`2227`) * For-in-loop iteration over ``bytearray`` and memory views is optimised. Patch by David Woods. (Github issue :issue:`2227`) * For-in-loop iteration over ``bytearray`` and memory views is optimised. Patch by David Woods. (Github issue :issue:`2227`) * ``float(…)`` is optimised for string arguments (str/bytes/bytearray). * ``[...] * N`` is optimised for C integer multipliers ``N``. (Github issue :issue:`3922`) * Some constant tuples containing strings were not deduplicated. Patch by David Woods. (Github issue :issue:`4353`) * Memory views can use atomic CPU instructions instead of locks in more cases. Patch by Sam Gross. (Github issue :issue:`4912`) * Cython avoids raising ``StopIteration`` in ``__next__`` methods when possible. Patch by David Woods. (Github issue :issue:`3447`) * Larger numbers of extension types with multiple subclasses could take very long to compile. Patch by Scott Wolchok. (Github issue :issue:`5139`) * Integer comparisons avoid Python coercions if possible. (Github issue :issue:`4821`) * The call-time dispatch for fused memoryview types is less slow. (Github issue :issue:`5073`) * Python's ``memoryview`` is now a known builtin type with optimised properties. (Github issue :issue:`3798`) * Multiplying a sequence by a C integer avoids creating and intermediate Python integer. * The reference counting of memory views involved useless overhead. (Github issue :issue:`5510`) Compatibility with C -------------------- The support for C features like ``const`` or ``volatile`` was substantially improved. The generated code has been cleared up to reduce the number of C compiler warnings emitted. Related changes ^^^^^^^^^^^^^^^ * A C compiler cast warning was resolved. Patch by Michael Buesch. (Github issue :issue:`2775`) * Constant integer expressions that used a negative exponent were evaluated as integer 0 instead of the expected float value. Patch by Kryštof Pilnáček. (Github issue :issue:`2133`) * Several declarations in ``cpython.*``, ``libc.*`` and ``libcpp.*`` were added. Patches by Jeroen Demeyer, Matthew Edwards, Chris Gyurgyik, Jerome Kieffer and Zackery Spytz. (Github issues :issue:`3468`, :issue:`3332`, :issue:`3202`, :issue:`3188`, :issue:`3179`, :issue:`2891`, :issue:`2826`, :issue:`2713`) * The ``volatile`` C modifier is supported in Cython code. Patch by Jeroen Demeyer. (Github issue :issue:`1667`) * ``const`` can be used together with fused types. Patch by Thomas Vincent. (Github issue :issue:`1772`) * Temporary buffer indexing variables were not released and could show up in C compiler warnings, e.g. in generators. Patch by David Woods. (Github issues :issue:`3430`, :issue:`3522`) * The C property feature has been rewritten and now requires C property methods to be declared ``inline`` (:issue:`3571`). * Cython generates C compiler branch hints for unlikely user defined if-clauses in more cases, when they end up raising exceptions unconditionally. This now includes exceptions being raised in ``nogil``/``with gil`` sections. * Several issues with arithmetic overflow handling were resolved, including undefined behaviour in C. Patch by Sam Sneddon. (Github issue :issue:`3588`) * `libc.math` was extended to include all C99 function declarations. Patch by Dean Scarff. (Github issue :issue:`3570`) * Some C compiler warninge were resolved. Patches by Max Bachmann. (Github issue :issue:`4053`, :issue:`4059`, :issue:`4054`, :issue:`4148`, :issue:`4162`) * A C compiler warning about enum value casting was resolved in GCC. (Github issue :issue:`2749`) * A C compiler warning about unused code was resolved. (Github issue :issue:`3763`) * Some compiler problems and warnings were resolved. Patches by David Woods, 0dminnimda, Nicolas Pauss and others. (Github issues :issue:`4317`, :issue:`4324`, :issue:`4361`, :issue:`4357`) * Some C compiler warnings were fixed. Patch by mwtian. (Github issue :issue:`4831`) * A case of undefined C behaviour was resolved in the list slicing code. Patch by Richard Barnes. (Github issue :issue:`4734`) * Typedefs for the ``bint`` type did not always behave like ``bint``. Patch by Nathan Manville and 0dminnimda. (Github issue :issue:`4660`) * Intel C compilers could complain about unsupported gcc pragmas. Patch by Ralf Gommers. (Github issue :issue:`5052`) * Structs that contained an array field resulted in incorrect C code. Their initialisation now uses ``memcpy()``. Patch by Chia-Hsiang Cheng. (Github issue :issue:`5178`) * The module state struct was not initialised in correct C (before C23), leading to compile errors on Windows. Patch by yudonglin. (Github issue :issue:`5169`) * ``cdef public`` functions declared in .pxd files could use an incorrectly mangled C name. Patch by EpigeneMax. (Github issue :issue:`2940`) * ``const`` types could not be returned from functions. Patch by Mike Graham. (Github issue :issue:`5135`) * C11 ``complex.h`` is now properly detected. (Github issue :issue:`2513`) * Standard C/C++ atomic operations are now used for memory views, if available. (Github issue :issue:`4925`) * C arrays can be initialised inside of nogil functions. Patch by Matúš Valo. (Github issue :issue:`1662`) * Very long Python integer constants could exceed the maximum C name length of MSVC. Patch by 0dminnimda. (Github issue :issue:`5290`) * Some C compiler warnings were resolved. Patches by Matt Tyson, Lisandro Dalcin, Philipp Wagner, Matti Picus et al. (Github issues :issue:`5417`, :issue:`5418`, :issue:`5421`, :issue:`5437`, :issue:`5438`, :issue:`5443`) * Some typedef declarations for libc function types were fixed. (Github issue :issue:`5498`) * With MSVC, Cython no longer enables C-Complex support by accident (which is not supported there). (Github issue :issue:`5512`) Compatibility with C++ ---------------------- Many C++ features like forwarding references or ``std::move`` are now supported or even used internally, if possible. Cython's wrapping of the C++ standard library has been extended. A new `cpp_locals`` directive enables C++ local variables to initialized when assigned to rather than at the start of the function, making them behave more like Python variables, and also removing the requirement for them to be default constructible. Related changes ^^^^^^^^^^^^^^^ * C++ ``typeid()`` failed for fused types. Patch by David Woods. (Github issue :issue:`3203`) * ``std::move()`` is now used in C++ mode for internal temp variables to make them work without copying values. Patch by David Woods. (Github issues :issue:`3253`, :issue:`1612`) * The C++ ``typeid()`` function was allowed in C mode. Patch by Celelibi. (Github issue :issue:`3637`) * C++ references failed to compile when used as Python object indexes. Patch by David Woods. (Github issue :issue:`3754`) * The construct ``for x in cpp_function_call()`` failed to compile. Patch by David Woods. (Github issue :issue:`3663`) * Some C++ STL methods did not propagate exceptions. Patch by Max Bachmann. (Github issue :issue:`4079`) * A compile failure for C++ enums in Py3.4 / MSVC was resolved. Patch by Ashwin Srinath. (Github issue :issue:`3782`) * Cython compiled functions always provided a ``__self__`` attribute, regardless of being used as a method or not. Patch by David Woods. (Github issue :issue:`4036`) * Overloaded C++ static methods were lost. Patch by Ashwin Srinath. (Github :issue:`1851`) * Nested C++ types were not usable through ctypedefs. Patch by Vadim Pushtaev. (Github issue :issue:`4039`) * More declarations for C++ string methods were added. * Converting C++ containers to Python lists uses less memory allocations. Patch by Max Bachmann. (Github issue :issue:`4081`) * ``std::move()`` is now also called for temps during ``yield``. Patch by Yu Feng. (Github issue :issue:`4154`) * The destructor is now called for fields in C++ structs. Patch by David Woods. (Github issue :issue:`3226`) * Conversion from Python dicts to ``std::map`` was broken. Patch by David Woods and Mikkel Skofelt. (Github issues :issue:`4228`, :issue:`4231`) * Code optimisations were not applied to methods of Cython implemented C++ classes. Patch by David Woods. (Github issue :issue:`4212`) * C++17 execution policies are supported in ``libcpp.algorithm``. Patch by Ashwin Srinath. (Github issue :issue:`3790`) * A new directive ``cpp_locals`` was added that allows local C++ variables to be lazily initialised (without default constructor), thus making them behave more like Python variables. Patch by David Woods. (Github issue :issue:`4160`) * Generated utility code for C++ conversions no longer depends on several user definable directives that may make it behave incorrectly. Patch by David Woods. (Github issue :issue:`4206`) * Several issues with the new ``cpp_locals`` directive were resolved and its test coverage improved. Patch by David Woods. (Github issues :issue:`4265`, :issue:`4266`) * Declarations for ``libcpp.algorithms``, ``libcpp.set`` and ``libcpp.unordered_set`` were extended. Patch by David Woods. (Github issues :issue:`4271`, :issue:`4273`) * Several C++ library declarations were added and fixed. Patches by Dobatymo, account-login, Jonathan Helgert, Evgeny Yakimov, GalaxySnail, Max Bachmann. (Github issues :issue:`4408`, :issue:`4419`, :issue:`4410`, :issue:`4395`, :issue:`4423`, :issue:`4448`, :issue:`4462`, :issue:`3293`, :issue:`4522`, :issue:`2171`, :issue:`4531`) * Templating C++ classes with memory view types lead to buggy code and is now rejected. Patch by David Woods. (Github issue :issue:`3085`) * ``prange`` loops generated incorrect code when ``cpp_locals`` is enabled. Patch by David Woods. (Github issue :issue:`4354`) * Direct assignments to C++ references are now allowed. Patch by David Woods. (Github issue :issue:`1863`) * Conversion from Python dict to C++ map now supports arbitrary Python mappings, not just dicts. * Some C++ and CPython library declarations were extended and fixed. Patches by Max Bachmann, Till Hoffmann, Julien Jerphanion, Wenjun Si. (Github issues :issue:`4530`, :issue:`4528`, :issue:`4710`, :issue:`4746`, :issue:`4751`, :issue:`4818`, :issue:`4762`, :issue:`4910`) * Some C/C++ warnings were resolved. Patches by Max Bachmann, Alexander Shadchin, at al. (Github issues :issue:`5004`, :issue:`5005`, :issue:`5019`, :issue:`5029`, :issue:`5096`) * C++ references did not work on fused types. (Github issue :issue:`4717`) * C++ iteration more safely stores the iterable in temporary variables. Patch by Xavier. (Github issue :issue:`3828`) * C++ post-increment/-decrement operators were not correctly looked up on declared C++ classes, thus allowing Cython declarations to be missing for them and incorrect C++ code to be generated. Patch by Max Bachmann. (Github issue :issue:`4536`) * ``cdef public`` functions used an incorrect linkage declaration in C++. Patch by Maximilien Colange. (Github issue :issue:`1839`) * Declarations were added for the C++ bit operations, some other parts of C++20 and CPython APIs. Patches by Jonathan Helgert, Dobatymo, William Ayd and Max Bachmann. (Github issues :issue:`4962`, :issue:`5101`, :issue:`5157`, :issue:`5163`, :issue:`5257`) * ``cpp_locals`` no longer have to be "assignable". (Github issue :issue:`4558`) * Nested ``cppclass`` definitions are supported. Patch by samaingw. (Github issue :issue:`1218`) * ``reversed()`` can now be used together with C++ iteration. Patch by Chia-Hsiang Cheng. (Github issue :issue:`5002`) * Some C++ warnings regarding ``const`` usage in internally generated utility code were resolved. Patch by Max Bachmann. (Github issue :issue:`5301`) * Cython generated C++ code accidentally used C++11 features in some cases. (Github issue :issue:`5316`) * Fully qualified C++ names prefixed by a cimported module name could fail to compile. Patch by Chia-Hsiang Cheng. (Github issue :issue:`5229`) * C++ declarations for ````, ```` and ``std::any`` were added. Patches by Jonathan Helgert and Maximilien Colange. (Github issues :issue:`5262`, :issue:`5309`, :issue:`5314`) * The ``extern "C"`` and ``extern "C++"`` markers that Cython generates for ``public`` functions can now be controlled by setting the C macro ``CYTHON_EXTERN_C``. * C++ containers of item type ``bint`` could conflict with those of item type ``int``. (Github issue :issue:`5516`) * Reverse iteration in C++ no longer removes the ``const`` qualifier from the item type. Patch by Isuru Fernando. (Github issue :issue:`5478`) Commandline Interface --------------------- A number of new options were added to the ``cython`` and ``cythonize`` commands. Related changes ^^^^^^^^^^^^^^^ * The command line parser was rewritten and modernised using ``argparse``. Patch by Egor Dranischnikow. (Github issue :issue:`2952`, :issue:`3001`) * ``cygdb`` gives better error messages when it fails to initialise the Python runtime support in gdb. Patch by Volker Weissmann. (Github issue :issue:`3489`) * ``--no-docstrings`` option added to ``cythonize`` script. Original patch by mo-han. (Github issue :issue:`2889`) * Code annotation accepts a new debugging argument ``--annotate-fullc`` that will include the complete syntax highlighted C file in the HTML output. (Github issue :issue:`2855`) * ``cygdb`` has a new option ``--skip-interpreter`` that allows using a different Python runtime than the one used to generate the debugging information. Patch by Alessandro Molina. (Github issue :issue:`4186`) * ``cythonize()`` and the corresponding CLI command now regenerate the output files also when they already exist but were generated by a different Cython version. * The ``cython`` and ``cythonize`` commands ignored non-existing input files without error. Patch by Matúš Valo. (Github issue :issue:`4629`) * ``cythonize --help`` now also prints information about the supported environment variables. Patch by Matúš Valo. (Github issue :issue:`1711`) * Using the ``--working`` option could lead to sources not being found. Patch by Lisandro Dalcin. (Github issue :issue:`5365`) * Passing a language level and directives on the command line lost the language level setting. Patch by Matúš Valo. (Github issue :issue:`5484`) * ``cython --version`` now prints the version to both stdout and stderr (unless that is a TTY). (Github issue :issue:`5504`) Build integration ----------------- Cython has made a number of improvements both to how it compiles itself and how it integrates with external build tools. Most notably Cython has been moving to use ``setuptools`` instead of the deprecated/removed ``distutils`` where possible. The new ``--depfile`` option generates dependency files to help integrate Cython with other build tools. Related changes ^^^^^^^^^^^^^^^ * Binary Linux wheels now follow the manylinux2010 standard. Patch by Alexey Stepanov. (Github issue :issue:`3355`) * The search order for include files was changed. Previously it was ``include_directories``, ``Cython/Includes``, ``sys.path``. Now it is ``include_directories``, ``sys.path``, ``Cython/Includes``. This was done to allow third-party ``*.pxd`` files to override the ones in Cython. Patch by Matti Picus. (Github issue :issue:`2905`) * Source file fingerprinting now uses SHA-1 instead of MD5 since the latter tends to be slower and less widely supported these days. (Github issue :issue:`2790`) * The Cython AST code serialiser class ``CodeWriter`` in ``Cython.CodeWriter`` supports more syntax nodes. * Parallel builds of Cython itself (``setup.py build_ext -j N``) failed on Windows. * When importing the old Cython ``build_ext`` integration with distutils, the additional command line arguments leaked into the regular command. Patch by Kamekameha. (Github issue :issue:`2209`) * ``.pxd`` files can now be :ref:`versioned ` by adding an extension like "``.cython-30.pxd``" to prevent older Cython versions (than 3.0 in this case) from picking them up. (Github issue :issue:`3577`) * The Cython ``CodeWriter`` can now handle more syntax constructs. Patch by Tao He. (Github issue :issue:`3514`) * The Cython ``CodeWriter`` mishandled no-argument ``return`` statements. Patch by Tao He. (Github issue :issue:`3795`) * Cython now detects when existing output files were not previously generated by itself and refuses to overwrite them. It is a common mistake to name the module file of a wrapper after the library (source file) that it wraps, which can lead to surprising errors when the file gets overwritten. * The ``Cython.Build.BuildExecutable`` tool no longer executes the program automatically. Use ``cythonrun`` for that. * Python modules were not automatically recompiled when only their ``.pxd`` file changed. Patch by Golden Rockefeller. (Github issue :issue:`1428`) * An unnecessary slow-down at import time was removed from ``Cython.Distutils``. Original patch by Anthony Sottile. (Github issue :issue:`4224`) * A compiler crash when running Cython thread-parallel from distutils was resolved. (Github issue :issue:`4503`) * An incompatibility with recent coverage.py versions was resolved. Patch by David Woods. (Github issue :issue:`4440`) * ``pyximport`` now uses ``cythonize()`` internally. Patch by Matúš Valo. (Github issue :issue:`2304`) * ``Cython.Distutils.build_ext`` now uses ``cythonize()`` internally (previously known as ``new_build_ext``), while still supporting the options that were available in the old implementation (``old_build_ext``). Patch by Matúš Valo. (Github issue :issue:`3541`) * Improve compatibility between classes pickled in Cython 3.0 and 0.29.x by accepting MD5, SHA-1 and SHA-256 checksums. (Github issue :issue:`4680`) * ``pyximport`` failed for long filenames on Windows. Patch by Matti Picus. (Github issue :issue:`4630`) * A new Cython build option ``--cython-compile-minimal`` was added to compile only a smaller set of Cython's own modules, which can be used to reduce the package and install size. * The environment variable ``CYTHON_FORCE_REGEN=1`` can be used to force ``cythonize`` to regenerate the output files regardless of modification times and changes. * The ``cythonize`` and ``cython`` commands have a new option ``-M`` / ``--depfile`` to generate ``.dep`` dependency files for the compilation unit. This can be used by external build tools to track these dependencies. The ``cythonize`` option was already available in Cython :ref:`0.29.27`. Patches by Evgeni Burovski and Eli Schwartz. (Github issue :issue:`1214`) * Wheels now include a compiled parser again, which increases their size a little but gives about a 10% speed-up when running Cython. * The wheel building process was migrated to use the ``cibuildwheel`` tool. Patch by Thomas Li. (Github issue :issue:`4736`) * ``setup.cfg`` was missing from the source distribution. (Github issue :issue:`5199`) * Extended glob paths with ``/**/`` and ``\**\`` for finding source files failed on Windows. * Coverage analysis failed in projects with a separate source subdirectory. Patch by Sviatoslav Sydorenko and Ruben Vorderman. (Github issue :issue:`3636`) * Cython could crash when finding import files with dots in their names. Patch by Matúš Valo. (Github issue :issue:`5396`) * A module loading problem with ``cython.inline()`` on Windows was resolved. Deprecations ------------ Some older features of Cython have been deprecated. Most notable are the compile time ``DEF`` and ``IF`` statements, although we emphasise that they will remain until a good alternative exists for all their use-cases. Related changes ^^^^^^^^^^^^^^^ * Dotted filenames for qualified module names (``pkg.mod.pyx``) are deprecated. Use the normal Python package directory layout instead. (Github issue :issue:`2686`) * "Declaration after use" is now an error for variables. Patch by David Woods. (Github issue :issue:`3976`) * Variables can no longer be declared with ``cpdef``. Patch by David Woods. (Github issue :issue:`887`) * The compile-time ``DEF`` and ``IF`` statements are deprecated and generate a warning. They should be replaced with normal constants, code generation or C macros. (Github issue :issue:`4310`) * C-style array declarations (``cdef int a[4]``) are now (silently) deprecated in favour of the Java-style ``cdef int[4] a`` form. The latter was always available and the Python type declaration syntax already used it exclusively (``a: int[4]``). Patch by Matúš Valo. (Github issue :issue:`5248`) * The undocumented, untested and apparently useless syntax ``from somemodule cimport class/struct/union somename`` was removed. The type modifier is not needed here and a plain ``cimport`` of the name will do. (Github issue :issue:`4904`) Editor support -------------- Related changes ^^^^^^^^^^^^^^^ * C compiler warnings and errors are now shown in Jupyter notebooks. Patch by Egor Dranischnikow. (Github issue :issue:`3751`) * An endless loop in ``cython-mode.el`` was resolved. Patch by Johannes Mueller. (Github issue :issue:`3218`) * The Emacs Cython mode file ``cython-mode.el`` is now maintained in a separate repo: https://github.com/cython/emacs-cython-mode * The C code shown in the annotated HTML output could lack the last C code line(s). Other changes ------------- * Memoryviews failed to compile when the ``cache_builtins`` feature was disabled. Patch by David Woods. (Github issue :issue:`3406`) * Broadcast assignments to a multi-dimensional memory view slice could end up in the wrong places when the underlying memory view is known to be contiguous but the slice is not. (Github issue :issue:`2941`) * The Pythran ``shape`` attribute is supported. Patch by Serge Guelton. (Github issue :issue:`3307`) * ``--no-capture`` added to ``runtests.py`` to prevent stdout/stderr capturing during srctree tests. Patch by Matti Picus. (Github issue :issue:`2701`) * Decoding an empty bytes/char* slice with large bounds could crash. Patch by Sam Sneddon. (Github issue :issue:`3534`) * Creating an empty unicode slice with large bounds could crash. Patch by Sam Sneddon. (Github issue :issue:`3531`) * Complex buffer item types of structs of arrays could fail to validate. Patch by Leo and smutch. (Github issue :issue:`1407`) * Error handling in ``cython.array`` creation was improved to avoid calling C-API functions with an error held. * Error handling early in the module init code could lead to a crash. * Exception position reporting could run into race conditions on threaded code. It now uses function-local variables again. * A reference leak on import failures was resolved. Patch by Max Bachmann. (Github issue :issue:`4056`) * Casting to ctuples is now allowed. Patch by David Woods. (Github issue :issue:`3808`) * Some issues were resolved that could lead to duplicated C names. Patch by David Woods. (Github issue :issue:`3716`, :issue:`3741`, :issue:`3734`) * Inline functions and other code in ``.pxd`` files could accidentally inherit the compiler directives of the ``.pyx`` file that imported them. Patch by David Woods. (Github issue :issue:`1071`) * Parts of the documentation were (and are being) rewritten to show the Cython language syntax next to the equivalent Python syntax. Patches by 0dminnimda and Matúš Valo. (Github issue :issue:`4187`) * A name collision when including multiple generated API header files was resolved. Patch by David Woods. (Github issue :issue:`4308`) * Very early errors during module initialisation could lead to crashes. Patch by David Woods. (Github issue :issue:`4377`) * Type errors when passing memory view arguments could leak buffer references. Patch by David Woods. (Github issue :issue:`4296`) * The GIL can now safely be released inside of ``nogil`` functions (which may actually be called with the GIL held at runtime). Patch by David Woods. (Github issue :issue:`4137`) * The return type of a fused function is no longer ignored for function pointers, since it is relevant when passing them e.g. as argument into other fused functions. Patch by David Woods. (Github issue :issue:`4644`) * Using memoryview arguments in closures of inner functions could lead to ref-counting errors. Patch by David Woods. (Github issue :issue:`4798`) * Decorators like ``@cfunc`` and ``@ccall`` could leak into nested functions and classes. Patch by David Woods. (Github issue :issue:`4092`) * Cython now uses a ``.dev0`` version suffix for unreleased source installations. * The ``Tempita`` module no longer contains HTML processing capabilities, which were found to be broken in Python 3.8 and later. Patch by Marcel Stimberg. (Github issue :issue:`3309`) * Nesting fused types in other fused types could fail to specialise the inner type. (Github issue :issue:`4725`) * Iterating over memoryviews in generator expressions could leak a buffer reference. (Github issue :issue:`4968`) * The C ``float`` type was not inferred on assignments. (Github issue :issue:`5234`) * Type checks for Python's ``memoryview`` type generated incorrect C code. (Github issues :issue:`5268`, :issue:`5270`) * Auto-generated utility code didn't always have all required user defined types available. (Github issue :issue:`5269`) * ``cimport_from_pyx`` could miss some declarations. Patch by Chia-Hsiang Cheng. (Github issue :issue:`5318`) * For-loops now release the internal reference to their list/tuple iterable before instead of after the ``else:`` clause. This probably has no practical impact. (Github issue :issue:`5347`) * Extension type hierarchies were generated in the wrong order, thus leading to compile issues. Patch by Lisandro Dalcin. (Github issue :issue:`5395`) * The FAQ page was moved from the GitHub Wiki to the regular documentation to make it more visible. 3.0.0 (2023-07-17) ================== Bugs fixed ---------- * A crash in Python 2.7 was fixed when cleaning up extension type instances at program end. 3.0.0 rc 2 (2023-07-13) ======================= Bugs fixed ---------- * Parser crash on hex/oct enum values. (Github issue :issue:`5524`) * ``cython --version`` now prints the version to both stdout and stderr (unless that is a TTY). (Github issue :issue:`5504`) 3.0.0 rc 1 (2023-07-12) ======================= Features added -------------- * ``with gil`` and ``with nogil(flag)`` now accept their flag argument also in Python code. Patch by Matúš Valo. (Github issue :issue:`5113`) * A new decorator ``@cython.with_gil`` is available in Python code to match the ``with gil`` function declaration in Cython syntax. * Assigning a list to a ctuple is slightly faster. Bugs fixed ---------- * The reference counting of memory views involved useless overhead. (Github issue :issue:`5510`) * Duplicate values in a ``cpdef`` enum could lead to invalid switch statements. (Github issue :issue:`5400`) * Handling freshly raised exceptions that didn't have a traceback yet could crash. (Github issue :issue:`5495`) * Reverse iteration in C++ no longer removes the ``const`` qualifier from the item type. Patch by Isuru Fernando. (Github issue :issue:`5478`) * C++ containers of item type ``bint`` could conflict with those of item type ``int``. (Github issue :issue:`5516`) * With MSVC, Cython no longer enables C-Complex support by accident (which is not supported there). (Github issue :issue:`5512`) * The Python implementation of ``cimport cython.cimports…`` could raise an ``ImportError`` instead of an ``AttributeError`` when looking up package variable names. Patch by Matti Picus. (Github issue :issue:`5411`) * Passing a language level and directives on the command line lost the language level setting. Patch by Matúš Valo. (Github issue :issue:`5484`) * Some typedef declarations for libc function types were fixed. (Github issue :issue:`5498`) * Some C compiler warnings and errors in CPython 3.12 were resolved. * The deprecated ``_PyGC_FINALIZED()`` C-API macro is no longer used. Patch by Thomas Caswell and Matúš Valo. (Github issue :issue:`5481`) * A compile error when using ``__debug__`` was resolved. * A module loading problem with ``cython.inline()`` on Windows was resolved. * ``cython --version`` now prints the version to stdout instead of stderr. (Github issue :issue:`5504`) * Includes all bug-fixes and features from the 0.29 maintenance branch up to the :ref:`0.29.36` release. Other changes ------------- * The FAQ page was moved from the GitHub Wiki to the regular documentation to make it more visible. * ``np.long_t`` and ``np.ulong_t`` were removed from the NumPy declarations, syncing Cython with upstream NumPy v1.25.0. The aliases were confusing since they could mean different things on different platforms. 3.0.0 beta 3 (2023-05-24) ========================= Features added -------------- * Custom buffer slot methods are now supported in the Limited C-API of Python 3.9+. Patch by Lisandro Dalcin. (Github issue :issue:`5422`) * The ``extern "C"`` and ``extern "C++"`` markers that Cython generates for ``public`` functions can now be controlled by setting the C macro ``CYTHON_EXTERN_C``. * The Python ``int`` handling code was adapted to make use of the new ``PyLong`` internals in CPython 3.12. (Github issue :issue:`5353`) * Conversion of Python ints to C ``int128`` is now always supported, although slow if dedicated C-API support is missing (``_PyLong_AsByteArray()``), specifically in the Limited C-API. (Github issue :issue:`5419`) * The exception handling code was adapted to CPython 3.12. (Github issue :issue:`5442`) * The dataclass implementation was adapted to support Python 3.12. (Github issue :issue:`5346`) * The normal ``@dataclasses.dataclass`` and ``@functools.total_ordering`` decorators can now be used on extension types. Using the corresponding ``@cython.*`` decorator will automatically turn a Python class into an extension type (no need for ``@cclass``). (Github issue :issue:`5292`) * Multiplying a sequence by a C integer avoids creating and intermediate Python integer. * ctuples can now be assigned from arbitrary sequences, not just Python tuples. * A new directive ``embedsignature.format`` was added to select the format of the docstring embedded signatures between ``python``, ``c`` and argument ``clinic``. Patch by Lisandro Dalcin. (Github issue :issue:`5415`) * Some invalid directive usages are now detected and rejected, e.g. using ``@ccall`` together with ``@cfunc``, and applying ``@cfunc`` to a ``@ufunc``. Cython also warns now when a directive is applied needlessly. (Github issue :issue:`5399` et al.) * Unicode identifier names now allow all letters defined in CPython 3.12. Bugs fixed ---------- * Some C compile failures in CPython 3.12.0a6/a7 were resolved. * Cascaded comparisons between integer constants and Python types could fail to compile. (Github issue :issue:`5354`) * The internal macro ``__PYX_IS_UNSIGNED`` was accidentally duplicated in beta 2 which lead to C compile errors. Patch by 0dminnimda. (Github issue :issue:`5356`) * Memoryviews with typedef item types could fail to match the non-typedef item types. Patch by Yue Yang. (Github issue :issue:`5373`) * Fused memory views could raise a ``TypeError`` instead of a ``ValueError`` on creation. Patch by Matúš Valo. (Github issue :issue:`5401`) * Cython could crash when finding import files with dots in their names. Patch by Matúš Valo. (Github issue :issue:`5396`) * Selecting a context manager in parentheses and then calling it directly failed to parse. (Github issue :issue:`5403`) * ``__qualname__`` and ``__module__`` were not available inside of class bodies. (Github issue :issue:`4447`) * ``noexcept`` was not automatically applied to function pointer attributes in extern structs. Patch by Matúš Valo. (Github issue :issue:`5359`) * Function signatures containing a type like `tuple[()]` could not be printed. Patch by Lisandro Dalcin. (Github issue :issue:`5355`) * Extension type hierarchies were generated in the wrong order, thus leading to compile issues. Patch by Lisandro Dalcin. (Github issue :issue:`5395`) * Using the ``--working`` option could lead to sources not being found. Patch by Lisandro Dalcin. (Github issue :issue:`5365`) * Some C compiler warnings were resolved. Patches by Matt Tyson, Lisandro Dalcin, Philipp Wagner, Matti Picus et al. (Github issues :issue:`5417`, :issue:`5418`, :issue:`5421`, :issue:`5437`, :issue:`5438`, :issue:`5443`) * Includes all bug-fixes and features from the 0.29 maintenance branch up to the :ref:`0.29.35` release. Other changes ------------- * For-loops now release the internal reference to their list/tuple iterable before instead of after the ``else:`` clause. This probably has no practical impact. (Github issue :issue:`5347`) * Simple tuple types like ``(int, int)`` are no longer accepted in Python annotations and require the Python notation instead (e.g. ``tuple[cython.int, cython.int]``). (Github issue :issue:`5397`) * The code ``except +nogil`` (declaring a C++ exception handler function called ``nogil``) is now rejected because it is almost certainly a typo from ``except + nogil``. (Github issue :issue:`5430`) 3.0.0 beta 2 (2023-03-27) ========================= Features added -------------- * C++ declarations for ````, ```` and ``std::any`` were added. Patches by Jonathan Helgert and Maximilien Colange. (Github issues :issue:`5262`, :issue:`5309`, :issue:`5314`) Bugs fixed ---------- * Unintended internal exception handling lead to a visible performance regression for ``nogil`` memoryview code in 3.0.0b1. (Github issue :issue:`5324`) * ``None`` default arguments for arguments with fused memoryview types could select a different implementation in 3.0 than in 0.29.x. The selection behaviour is generally considered suboptimal but was at least reverted to the old behaviour for now. (Github issue :issue:`5297`) * The new complex vs. floating point behaviour of the ``**`` power operator accidentally added a dependency on the GIL, which was really only required on failures. (Github issue :issue:`5287`) * ``from cython cimport … as …`` could lead to imported names not being found in annotations. Patch by Chia-Hsiang Cheng. (Github issue :issue:`5235`) * Generated NumPy ufuncs could crash for large arrays due to incorrect GIL handling. (Github issue :issue:`5328`) * Very long Python integer constants could exceed the maximum C name length of MSVC. Patch by 0dminnimda. (Github issue :issue:`5290`) * ``cimport_from_pyx`` could miss some declarations. Patch by Chia-Hsiang Cheng. (Github issue :issue:`5318`) * Fully qualified C++ names prefixed by a cimported module name could fail to compile. Patch by Chia-Hsiang Cheng. (Github issue :issue:`5229`) * Cython generated C++ code accidentally used C++11 features in some cases. (Github issue :issue:`5316`) * Some C++ warnings regarding ``const`` usage in internally generated utility code were resolved. Patch by Max Bachmann. (Github issue :issue:`5301`) * With ``language_level=2``, imports of modules in packages could return the wrong module in Python 3. (Github issue :issue:`5308`) * ``typing.Optional`` could fail on tuple types. (Github issue :issue:`5263`) * Auto-generated utility code didn't always have all required user defined types available. (Github issue :issue:`5269`) * Type checks for Python's ``memoryview`` type generated incorrect C code. (Github issues :issue:`5268`, :issue:`5270`) * Some issues with ``depfile`` generation were resolved. Patches by Eli Schwartz. (Github issues :issue:`5279`, :issue:`5291`) * Some C code issue were resolved for the Limited API target. (Github issues :issue:`5264`, :issue:`5265`, :issue:`5266`) * The C code shown in the annotated HTML output could lack the last C code line(s). 3.0.0 beta 1 (2023-02-25) ========================= Features added -------------- * Cython implemented C functions now propagate exceptions by default, rather than swallowing them in non-object returning function if the user forgot to add an ``except`` declaration to the signature. This was a long-standing source of bugs, but can require adding the ``noexcept`` declaration to existing functions if exception propagation is really undesired. (Github issue :issue:`4280`) * To opt out of the new, safer exception handling behaviour, legacy code can set the new directive ``legacy_implicit_noexcept=True`` for a transition period to keep the previous, unsafe behaviour. This directive will eventually be removed in a later release. Patch by Matúš Valo. (Github issue :issue:`5094`) * A new function decorator ``@cython.ufunc`` automatically generates a (NumPy) ufunc that applies the calculation function to an entire memoryview. (Github issue :issue:`4758`) * The ``**`` power operator now behaves more like in Python by returning the correct complex result if required by math. A new ``cpow`` directive was added to turn on the previous C-like behaviour. (Github issue :issue:`4936`) * The special ``__*pow__`` methods now support the 2- and 3-argument variants. (Github issue :issue:`5160`) * Unknown type annotations (e.g. because of typos) now emit a warning at compile time. Patch by Matúš Valo. (Github issue :issue:`5070`) * Subscripted builtin types in type declarations (like ``list[float]``) are now better supported. (Github issue :issue:`5058`) * Python's ``memoryview`` is now a known builtin type with optimised properties. (Github issue :issue:`3798`) * The call-time dispatch for fused memoryview types is less slow. (Github issue :issue:`5073`) * Integer comparisons avoid Python coercions if possible. (Github issue :issue:`4821`) * The Python Enum of a ``cpdef enum`` now inherits from ``IntFlag`` to better match both Python and C semantics of enums. (Github issue :issue:`2732`) * `PEP-614 `_: decorators can now be arbitrary Python expressions. (Github issue :issue:`4570`) * ``cpdef`` enums can now be pickled. (Github issue :issue:`5120`) * Bound C methods can now coerce to Python objects. (Github issues :issue:`4890`, :issue:`5062`) * C arrays can be initialised inside of nogil functions. Patch by Matúš Valo. (Github issue :issue:`1662`) * ``reversed()`` can now be used together with C++ iteration. Patch by Chia-Hsiang Cheng. (Github issue :issue:`5002`) * Standard C/C++ atomic operations are now used for memory views, if available. (Github issue :issue:`4925`) * C11 ``complex.h`` is now properly detected. (Github issue :issue:`2513`) * Nested ``cppclass`` definitions are supported. Patch by samaingw. (Github issue :issue:`1218`) * ``cpp_locals`` no longer have to be "assignable". (Github issue :issue:`4558`) * ``cythonize --help`` now also prints information about the supported environment variables. Patch by Matúš Valo. (Github issue :issue:`1711`) * Declarations were added for the C++ bit operations, some other parts of C++20 and CPython APIs. Patches by Jonathan Helgert, Dobatymo, William Ayd and Max Bachmann. (Github issues :issue:`4962`, :issue:`5101`, :issue:`5157`, :issue:`5163`, :issue:`5257`) Bugs fixed ---------- * Generator expressions and comprehensions now look up their outer-most iterable on creation, as Python does, and not later on start, as they did previously. (Github issue :issue:`1159`) * Type annotations for Python ``int`` rejected ``long`` under Py2 in the alpha-11 release. They are now ignored again (as always before) when ``language_level=2``, and accept both ``int`` and ``long`` in Py2 (and only ``int`` in Py3) otherwise. (Github issue :issue:`4944`) * Calling bound classmethods of builtin types could fail trying to call the unbound method. (Github issue :issue:`5051`) * ``int(Py_UCS4)`` returned the code point instead of the parsed digit value. (Github issue :issue:`5216`) * Several problems with CPython 3.12 were resolved. (Github issue :issue:`5238`) * The C ``float`` type was not inferred on assignments. (Github issue :issue:`5234`) * Memoryviews with ``object`` item type were not supported in Python type declarations. (Github issue :issue:`4907`) * Iterating over memoryviews in generator expressions could leak a buffer reference. (Github issue :issue:`4968`) * Memory views and the internal Cython array type now identify as ``collections.abc.Sequence`` by setting the ``Py_TPFLAGS_SEQUENCE`` type flag directly. (Github issue :issue:`5187`) * ``__del__`` finaliser methods were not always called if they were only inherited. (Github issue :issue:`4995`) * Extension types are now explicitly marked as immutable types to prevent them from being considered mutable. Patch by Max Bachmann. (Github issue :issue:`5023`) * ``const`` types could not be returned from functions. Patch by Mike Graham. (Github issue :issue:`5135`) * ``cdef public`` functions declared in .pxd files could use an incorrectly mangled C name. Patch by EpigeneMax. (Github issue :issue:`2940`) * ``cdef public`` functions used an incorrect linkage declaration in C++. Patch by Maximilien Colange. (Github issue :issue:`1839`) * C++ post-increment/-decrement operators were not correctly looked up on declared C++ classes, thus allowing Cython declarations to be missing for them and incorrect C++ code to be generated. Patch by Max Bachmann. (Github issue :issue:`4536`) * C++ iteration more safely stores the iterable in temporary variables. Patch by Xavier. (Github issue :issue:`3828`) * C++ references did not work on fused types. (Github issue :issue:`4717`) * The module state struct was not initialised in correct C (before C23), leading to compile errors on Windows. Patch by yudonglin. (Github issue :issue:`5169`) * Structs that contained an array field resulted in incorrect C code. Their initialisation now uses ``memcpy()``. Patch by Chia-Hsiang Cheng. (Github issue :issue:`5178`) * Nesting fused types in other fused types could fail to specialise the inner type. (Github issue :issue:`4725`) * The special methods ``__matmul__``, ``__truediv__``, ``__floordiv__`` failed to type their ``self`` argument. (Github issue :issue:`5067`) * Coverage analysis failed in projects with a separate source subdirectory. Patch by Sviatoslav Sydorenko and Ruben Vorderman. (Github issue :issue:`3636`) * The ``annotation_typing`` directive was missing in pure Python mode. Patch by 0dminnimda. (Github issue :issue:`5194`) * The ``@dataclass`` directive was accidentally inherited by methods and subclasses. (Github issue :issue:`4953`) * Some issues with Cython ``@dataclass`` arguments, hashing, inheritance and ``repr()`` were resolved. (Github issues :issue:`4956`, :issue:`5046`) * ``cpdef`` enums no longer use ``OrderedDict`` but ``dict`` in Python 3.6 and later. Patch by GalaxySnail. (Github issue :issue:`5180`) * Larger numbers of extension types with multiple subclasses could take very long to compile. Patch by Scott Wolchok. (Github issue :issue:`5139`) * Relative imports failed in compiled ``__init__.py`` package modules. Patch by Matúš Valo. (Github issue :issue:`3442`) * Some old usages of the deprecated Python ``imp`` module were replaced with ``importlib``. Patch by Matúš Valo. (Github issue :issue:`4640`) * The ``cython`` and ``cythonize`` commands ignored non-existing input files without error. Patch by Matúš Valo. (Github issue :issue:`4629`) * Invalid and misspelled ``cython.*`` module names were not reported as errors. (Github issue :issue:`4947`) * Unused ``**kwargs`` arguments did not show up in ``locals()``. (Github issue :issue:`4899`) * Extended glob paths with ``/**/`` and ``\**\`` for finding source files failed on Windows. * Annotated HTML generation was missing newlines in 3.0.0a11. (Github issue :issue:`4945`) * Some parser issues were resolved. (Github issue :issue:`4992`) * ``setup.cfg`` was missing from the source distribution. (Github issue :issue:`5199`) * Some C/C++ warnings were resolved. Patches by Max Bachmann, Alexander Shadchin, at al. (Github issues :issue:`5004`, :issue:`5005`, :issue:`5019`, :issue:`5029`, :issue:`5096`) * The embedding code no longer calls deprecated C-API functions but uses the new ``PyConfig`` API instead on CPython versions that support it (3.8+). Patch by Alexander Shadchin. (Github issue :issue:`4895`) * Intel C compilers could complain about unsupported gcc pragmas. Patch by Ralf Gommers. (Github issue :issue:`5052`) * Includes all bug-fixes and features from the 0.29 maintenance branch up to the :ref:`0.29.33` release. Other changes ------------- * The undocumented, untested and apparently useless syntax ``from somemodule cimport class/struct/union somename`` was removed. The type modifier is not needed here and a plain ``cimport`` of the name will do. (Github issue :issue:`4904`) * C-style array declarations (``cdef int a[4]``) are now (silently) deprecated in favour of the Java-style ``cdef int[4] a`` form. The latter was always available and the Python type declaration syntax already used it exclusively (``a: int[4]``). Patch by Matúš Valo. (Github issue :issue:`5248`) * The wheel building process was migrated to use the ``cibuildwheel`` tool. Patch by Thomas Li. (Github issue :issue:`4736`) * Wheels now include a compiled parser again, which increases their size a little but gives about a 10% speed-up when running Cython. * The ``Tempita`` module no longer contains HTML processing capabilities, which were found to be broken in Python 3.8 and later. Patch by Marcel Stimberg. (Github issue :issue:`3309`) * The Emacs Cython mode file ``cython-mode.el`` is now maintained in a separate repo: https://github.com/cython/emacs-cython-mode * Cython now uses a ``.dev0`` version suffix for unreleased source installations. 3.0.0 alpha 11 (2022-07-31) =========================== Features added -------------- * A new decorator ``@cython.dataclasses.dataclass`` was implemented that provides compile time dataclass generation capabilities to ``cdef`` classes (extension types). Patch by David Woods. (Github issue :issue:`2903`). ``kw_only`` dataclasses added by Yury Sokov. (Github issue :issue:`4794`) * Named expressions (PEP 572) aka. assignment expressions (aka. the walrus operator ``:=``) were implemented. Patch by David Woods. (Github issue :issue:`2636`) * Context managers can be written in parentheses. Patch by David Woods. (Github issue :issue:`4814`) * Cython avoids raising ``StopIteration`` in ``__next__`` methods when possible. Patch by David Woods. (Github issue :issue:`3447`) * Some C++ and CPython library declarations were extended and fixed. Patches by Max Bachmann, Till Hoffmann, Julien Jerphanion, Wenjun Si. (Github issues :issue:`4530`, :issue:`4528`, :issue:`4710`, :issue:`4746`, :issue:`4751`, :issue:`4818`, :issue:`4762`, :issue:`4910`) * The ``cythonize`` and ``cython`` commands have a new option ``-M`` / ``--depfile`` to generate ``.dep`` dependency files for the compilation unit. This can be used by external build tools to track these dependencies. The ``cythonize`` option was already available in Cython :ref:`0.29.27`. Patches by Evgeni Burovski and Eli Schwartz. (Github issue :issue:`1214`) * ``cythonize()`` and the corresponding CLI command now regenerate the output files also when they already exist but were generated by a different Cython version. * Memory views and the internal Cython array type now identify as ``collections.abc.Sequence``. Patch by David Woods. (Github issue :issue:`4817`) * Cython generators and coroutines now identify as ``CO_ASYNC_GENERATOR``, ``CO_COROUTINE`` and ``CO_GENERATOR`` accordingly. (Github issue :issue:`4902`) * Memory views can use atomic CPU instructions instead of locks in more cases. Patch by Sam Gross. (Github issue :issue:`4912`) * The environment variable ``CYTHON_FORCE_REGEN=1`` can be used to force ``cythonize`` to regenerate the output files regardless of modification times and changes. * A new Cython build option ``--cython-compile-minimal`` was added to compile only a smaller set of Cython's own modules, which can be used to reduce the package and install size. * Improvements to ``PyTypeObject`` definitions in pxd wrapping of libpython. Patch by John Kirkham. (Github issue :issue:`4699`) Bugs fixed ---------- * Decorators like ``@cfunc`` and ``@ccall`` could leak into nested functions and classes. Patch by David Woods. (Github issue :issue:`4092`) * Exceptions within for-loops that run over memoryviews could lead to a ref-counting error. Patch by David Woods. (Github issue :issue:`4662`) * Using memoryview arguments in closures of inner functions could lead to ref-counting errors. Patch by David Woods. (Github issue :issue:`4798`) * Several optimised string methods failed to accept ``None`` as arguments to their options. Test patch by Kirill Smelkov. (Github issue :issue:`4737`) * A regression in 3.0.0a10 was resolved that prevented property setter methods from having the same name as their value argument. Patch by David Woods. (Github issue :issue:`4836`) * Typedefs for the ``bint`` type did not always behave like ``bint``. Patch by Nathan Manville and 0dminnimda. (Github issue :issue:`4660`) * The return type of a fused function is no longer ignored for function pointers, since it is relevant when passing them e.g. as argument into other fused functions. Patch by David Woods. (Github issue :issue:`4644`) * The ``__self__`` attribute of fused functions reports its availability correctly with ``hasattr()``. Patch by David Woods. (Github issue :issue:`4808`) * ``pyximport`` no longer uses the deprecated ``imp`` module. Patch by Matúš Valo. (Github issue :issue:`4560`) * ``pyximport`` failed for long filenames on Windows. Patch by Matti Picus. (Github issue :issue:`4630`) * The generated C code failed to compile in CPython 3.11a4 and later. (Github issue :issue:`4500`) * A case of undefined C behaviour was resolved in the list slicing code. Patch by Richard Barnes. (Github issue :issue:`4734`) * Using the Limited API could report incorrect line numbers in tracebacks. * A work-around for StacklessPython < 3.8 was disabled in Py3.8 and later. (Github issue :issue:`4329`) * Improve conversion between function pointers with non-identical but compatible exception specifications. Patches by David Woods. (Github issues :issue:`4770`, :issue:`4689`) * The runtime size check for imported ``PyVarObject`` types was improved to reduce false positives and adapt to Python 3.11. Patch by David Woods. (Github issues :issue:`4827`, :issue:`4894`) * The generated modules no longer import NumPy internally when using fused types but no memoryviews. Patch by David Woods. (Github issue :issue:`4935`) * Improve compatibility with forthcoming CPython 3.12 release. * Limited API C preprocessor warning is compatible with MSVC. Patch by Victor Molina Garcia. (Github issue :issue:`4826`) * Some C compiler warnings were fixed. Patch by mwtian. (Github issue :issue:`4831`) * The parser allowed some invalid spellings of ``...``. Patch by 0dminnimda. (Github issue :issue:`4868`) * Includes all bug-fixes and features from the 0.29 maintenance branch up to the :ref:`0.29.32` release. Other changes ------------- * When using type annotations, ``func(x: list)`` or ``func(x: ExtType)`` (and other Python builtin or extension types) no longer allow ``None`` as input argument to ``x``. This is consistent with the normal typing semantics in Python, and was a common gotcha for users who did not expect ``None`` to be allowed as input. To allow ``None``, use ``typing.Optional`` as in ``func(x: Optional[list])``. ``None`` is also automatically allowed when it is used as default argument, i.e. ``func(x: list = None)``. ``int`` and ``float`` are now also recognised in type annotations and restrict the value type at runtime. They were previously ignored. Note that, for backwards compatibility reasons, the new behaviour does not apply when using Cython's C notation, as in ``func(list x)``. Here, ``None`` is still allowed, as always. Also, the ``annotation_typing`` directive can now be enabled and disabled more finely within the module. (Github issues :issue:`3883`, :issue:`2696`, :issue:`4669`, :issue:`4606`, :issue:`4886`) * The compile-time ``DEF`` and ``IF`` statements are deprecated and generate a warning. They should be replaced with normal constants, code generation or C macros. (Github issue :issue:`4310`) * Reusing an extension type attribute name as a method name is now an error. Patch by 0dminnimda. (Github issue :issue:`4661`) * Improve compatibility between classes pickled in Cython 3.0 and 0.29.x by accepting MD5, SHA-1 and SHA-256 checksums. (Github issue :issue:`4680`) 3.0.0 alpha 10 (2022-01-06) =========================== Features added -------------- * ``Cython.Distutils.build_ext`` now uses ``cythonize()`` internally (previously known as ``new_build_ext``), while still supporting the options that were available in the old implementation (``old_build_ext``). Patch by Matúš Valo. (Github issue :issue:`3541`) * ``pyximport`` now uses ``cythonize()`` internally. Patch by Matúš Valo. (Github issue :issue:`2304`) * ``__del__(self)`` on extension types now maps to ``tp_finalize`` in Python 3. Original patch by ax487. (Github issue :issue:`3612`) * Conversion from Python dict to C++ map now supports arbitrary Python mappings, not just dicts. * Direct assignments to C++ references are now allowed. Patch by David Woods. (Github issue :issue:`1863`) * An initial set of adaptations for GraalVM Python was implemented. Note that this does not imply any general support for this target or that your code will work at all in this environment. But testing should be possible now. Patch by David Woods. (Github issue :issue:`4328`) * ``PyMem_[Raw]Calloc()`` was added to the ``cpython.mem`` declarations. Note that the ``Raw`` versions are no longer #defined by Cython. The previous macros were not considered safe. Patch by William Schwartz and David Woods. (Github issue :issue:`3047`) Bugs fixed ---------- * Circular imports of compiled modules could fail needlessly even when the import could already be resolved from ``sys.modules``. Patch by Syam Gadde. (Github issue :issue:`4390`) * The GIL can now safely be released inside of ``nogil`` functions (which may actually be called with the GIL held at runtime). Patch by David Woods. (Github issue :issue:`4137`) * Type errors when passing memory view arguments could leak buffer references. Patch by David Woods. (Github issue :issue:`4296`) * Cython did not type the ``self`` argument in special binary methods. Patch by David Woods. (Github issue :issue:`4434`) * An incompatibility with recent coverage.py versions was resolved. Patch by David Woods. (Github issue :issue:`4440`) * Fused typed default arguments generated incorrect code. Patch by David Woods. (Github issue :issue:`4413`) * ``prange`` loops generated incorrect code when ``cpp_locals`` is enabled. Patch by David Woods. (Github issue :issue:`4354`) * A C-level compatibility issue with recent NumPy versions was resolved. Patch by David Woods. (Github issue :issue:`4396`) * Decorators on inner functions were not evaluated in the right scope. Patch by David Woods. (Github issue :issue:`4367`) * Very early errors during module initialisation could lead to crashes. Patch by David Woods. (Github issue :issue:`4377`) * Fused functions were binding unnecessarily, which prevented them from being pickled. Patch by David Woods. (Github issue :issue:`4370`) * Some constant tuples containing strings were not deduplicated. Patch by David Woods. (Github issue :issue:`4353`) * Unsupported decorators on cdef functions were not rejected in recent releases. Patch by David Woods. (Github issue :issue:`4322`) * The excess arguments in a for-in-range loop with more than 3 arguments to `range()` were silently ignored. Original patch by Max Bachmann. (Github issue :issue:`4550`) * Python object types were not allowed as ``->`` return type annotations. Patch by Matúš Valo. (Github issue :issue:`4433`) * Default values for memory views arguments were not properly supported. Patch by Corentin Cadiou. (Github issue :issue:`4313`) * Templating C++ classes with memory view types lead to buggy code and is now rejected. Patch by David Woods. (Github issue :issue:`3085`) * Several C++ library declarations were added and fixed. Patches by Dobatymo, account-login, Jonathan Helgert, Evgeny Yakimov, GalaxySnail, Max Bachmann. (Github issues :issue:`4408`, :issue:`4419`, :issue:`4410`, :issue:`4395`, :issue:`4423`, :issue:`4448`, :issue:`4462`, :issue:`3293`, :issue:`4522`, :issue:`2171`, :issue:`4531`) * Some compiler problems and warnings were resolved. Patches by David Woods, 0dminnimda, Nicolas Pauss and others. (Github issues :issue:`4317`, :issue:`4324`, :issue:`4361`, :issue:`4357`) * The ``self`` argument of static methods in .pxd files was incorrectly typed. Patch by David Woods. (Github issue :issue:`3174`) * A name collision when including multiple generated API header files was resolved. Patch by David Woods. (Github issue :issue:`4308`) * An endless loop in ``cython-mode.el`` was resolved. Patch by Johannes Mueller. (Github issue :issue:`3218`) * ``_Py_TPFLAGS_HAVE_VECTORCALL`` was always set on extension types when using the limited API. Patch by David Woods. (Github issue :issue:`4453`) * Some compatibility issues with PyPy were resolved. Patches by Max Bachmann, Matti Picus. (Github issues :issue:`4454`, :issue:`4477`, :issue:`4478`, :issue:`4509`, :issue:`4517`) * A compiler crash when running Cython thread-parallel from distutils was resolved. (Github issue :issue:`4503`) * Includes all bug-fixes from the :ref:`0.29.26` release. Other changes ------------- * A warning was added when ``__defaults__`` or ``__kwdefaults__`` of Cython compiled functions were re-assigned, since this does not current have an effect. Patch by David Woods. (Github issue :issue:`2650`) 3.0.0 alpha 9 (2021-07-21) ========================== Features added -------------- * Declarations for ``libcpp.algorithms``, ``libcpp.set`` and ``libcpp.unordered_set`` were extended. Patch by David Woods. (Github issues :issue:`4271`, :issue:`4273`) * ``cygdb`` has a new option ``--skip-interpreter`` that allows using a different Python runtime than the one used to generate the debugging information. Patch by Alessandro Molina. (Github issue :issue:`4186`) Bugs fixed ---------- * Several issues with the new ``cpp_locals`` directive were resolved and its test coverage improved. Patch by David Woods. (Github issues :issue:`4266`, :issue:`4265`) * Generated utility code for C++ conversions no longer depends on several user definable directives that may make it behave incorrectly. Patch by David Woods. (Github issue :issue:`4206`) * A reference counting bug in the new ``@cython.total_ordering`` decorator was fixed. * Includes all bug-fixes from the :ref:`0.29.24` release. Other changes ------------- * Parts of the documentation were (and are being) rewritten to show the Cython language syntax next to the equivalent Python syntax. Patches by 0dminnimda and Matúš Valo. (Github issue :issue:`4187`) 3.0.0 alpha 8 (2021-07-02) ========================== Features added -------------- * A ``@cython.total_ordering`` decorator has been added to automatically implement all comparison operators, similar to ``functools.total_ordering``. Patch by Spencer Brown. (Github issue :issue:`2090`) * A new directive ``cpp_locals`` was added that allows local C++ variables to be lazily initialised (without default constructor), thus making them behave more like Python variables. Patch by David Woods. (Github issue :issue:`4160`) * C++17 execution policies are supported in ``libcpp.algorithm``. Patch by Ashwin Srinath. (Github issue :issue:`3790`) * New C feature flags: ``CYTHON_USE_MODULE_STATE``, ``CYTHON_USE_TYPE_SPECS`` Both are currently considered experimental. (Github issue :issue:`3611`) * ``[...] * N`` is optimised for C integer multipliers ``N``. (Github issue :issue:`3922`) Bugs fixed ---------- * The dispatch code for binary operators to special methods could run into infinite recursion. Patch by David Woods. (Github issue :issue:`4172`) * Code optimisations were not applied to methods of Cython implemented C++ classes. Patch by David Woods. (Github issue :issue:`4212`) * The special ``cython`` module was not always detected in PEP-484 type annotations. Patch by David Woods. (Github issue :issue:`4243`) * Conversion from Python dicts to ``std::map`` was broken. Patch by David Woods and Mikkel Skofelt. (Github issues :issue:`4231`, :issue:`4228`) * The exception handling annotation ``except +*`` was broken. Patch by David Woods. (Github issues :issue:`3065`, :issue:`3066`) * Attribute annotations in Python classes are now ignored, because they are just Python objects in a dict (as opposed to the fields of extension types). Patch by David Woods. (Github issues :issue:`4196`, :issue:`4198`) * An unnecessary slow-down at import time was removed from ``Cython.Distutils``. Original patch by Anthony Sottile. (Github issue :issue:`4224`) * Python modules were not automatically recompiled when only their ``.pxd`` file changed. Patch by Golden Rockefeller. (Github issue :issue:`1428`) * The signature of ``PyFloat_FromString()`` in ``cpython.float`` was changed to match the signature in Py3. It still has an automatic fallback for Py2. (Github issue :issue:`3909`) * A compile error on MSVC was resolved. Patch by David Woods. (Github issue :issue:`4202`) * A C compiler warning in PyPy3 regarding ``PyEval_EvalCode()`` was resolved. * Directives starting with ``optimization.*`` in pure Python mode were incorrectly named. It should have been ``optimize.*``. Patch by David Woods. (Github issue :issue:`4258`) Other changes ------------- * Variables can no longer be declared with ``cpdef``. Patch by David Woods. (Github issue :issue:`887`) * Support for the now unsupported Pyston V1 was removed in favour of Pyston V2. Patch by Marius Wachtler. (Github issue :issue:`4211`) * The ``Cython.Build.BuildExecutable`` tool no longer executes the program automatically. Use ``cythonrun`` for that. 3.0.0 alpha 7 (2021-05-24) ========================== Features added -------------- * A ``cimport`` is now supported in pure Python code by prefixing the imported module name with ``cython.cimports.``, e.g. ``from cython.cimports.libc.math import sin``. (GIthub issue :issue:`4190`) * ``__class_getitem__`` (`PEP-560`_) is supported for cdef classes. Patch by Kmol Yuan. (Github issue :issue:`3764`) * ``__mro_entries__`` (`PEP-560`_) is supported for Python classes. Patch by David Woods. (Github issue :issue:`3537`) * ``cython.array`` supports simple, non-strided views. (Github issue :issue:`3775`) * Self-documenting f-strings (``=``) were implemented. Patch by davfsa. (Github issue :issue:`3796`) * The destructor is now called for fields in C++ structs. Patch by David Woods. (Github issue :issue:`3226`) * ``std::move()`` is now also called for temps during ``yield``. Patch by Yu Feng. (Github issue :issue:`4154`) * ``asyncio.iscoroutinefunction()`` now recognises coroutine functions also when compiled by Cython. Patch by Pedro Marques da Luz. (Github issue :issue:`2273`) * C compiler warnings and errors are now shown in Jupyter notebooks. Patch by Egor Dranischnikow. (Github issue :issue:`3751`) * ``float(…)`` is optimised for string arguments (str/bytes/bytearray). * Converting C++ containers to Python lists uses less memory allocations. Patch by Max Bachmann. (Github issue :issue:`4081`) * Docstrings of ``cpdef`` enums are now copied to the enum class. Patch by matham. (Github issue :issue:`3805`) * The type ``cython.Py_hash_t`` is available in Python mode. * C-API declarations for ``cpython.fileobject`` were added. Patch by Zackery Spytz. (Github issue :issue:`3906`) * C-API declarations for context variables in Python 3.7 were added. Original patch by Zolisa Bleki. (Github issue :issue:`2281`) * More C-API declarations for ``cpython.datetime`` were added. Patch by Bluenix2. (Github issue :issue:`4128`) * A new module ``cpython.time`` was added with some low-level alternatives to Python's ``time`` module. Patch by Brock Mendel. (Github issue :issue:`3767`) * The value ``PyBUF_MAX_NDIM`` was added to the ``cpython.buffer`` module. Patch by John Kirkham. (Github issue :issue:`3811`) * "Declaration after use" is now an error for variables. Patch by David Woods. (Github issue :issue:`3976`) * More declarations for C++ string methods were added. * Cython now detects when existing output files were not previously generated by itself and refuses to overwrite them. It is a common mistake to name the module file of a wrapper after the library (source file) that it wraps, which can lead to surprising errors when the file gets overwritten. Bugs fixed ---------- * Annotations were not exposed on annotated (data-)classes. Patch by matsjoyce. (Github issue :issue:`4151`) * Inline functions and other code in ``.pxd`` files could accidentally inherit the compiler directives of the ``.pyx`` file that imported them. Patch by David Woods. (Github issue :issue:`1071`) * Some issues were resolved that could lead to duplicated C names. Patch by David Woods. (Github issue :issue:`3716`, :issue:`3741`, :issue:`3734`) * Modules with unicode names failed to build on Windows. Patch by David Woods. (Github issue :issue:`4125`) * ``ndarray.shape`` failed to compile with Pythran and recent NumPy. Patch by Serge Guelton. (Github issue :issue:`3762`) * Casting to ctuples is now allowed. Patch by David Woods. (Github issue :issue:`3808`) * Structs could not be instantiated with positional arguments in pure Python mode. * Literal list assignments to pointer variables declared in PEP-526 notation failed to compile. * Nested C++ types were not usable through ctypedefs. Patch by Vadim Pushtaev. (Github issue :issue:`4039`) * Overloaded C++ static methods were lost. Patch by Ashwin Srinath. (Github :issue:`1851`) * Cython compiled functions always provided a ``__self__`` attribute, regardless of being used as a method or not. Patch by David Woods. (Github issue :issue:`4036`) * Calls to ``.__class__()`` of a known extension type failed. Patch by David Woods. (Github issue :issue:`3954`) * Generator expressions in pxd-overridden ``cdef`` functions could fail to compile. Patch by Matúš Valo. (Github issue :issue:`3477`) * A reference leak on import failures was resolved. Patch by Max Bachmann. (Github issue :issue:`4056`) * A C compiler warning about unused code was resolved. (Github issue :issue:`3763`) * A C compiler warning about enum value casting was resolved in GCC. (Github issue :issue:`2749`) * Some C compiler warninge were resolved. Patches by Max Bachmann. (Github issue :issue:`4053`, :issue:`4059`, :issue:`4054`, :issue:`4148`, :issue:`4162`) * A compile failure for C++ enums in Py3.4 / MSVC was resolved. Patch by Ashwin Srinath. (Github issue :issue:`3782`) * Some C++ STL methods did not propagate exceptions. Patch by Max Bachmann. (Github issue :issue:`4079`) * An unsupported C-API call in PyPy was fixed. Patch by Max Bachmann. (Github issue :issue:`4055`) * The Cython ``CodeWriter`` mishandled no-argument ``return`` statements. Patch by Tao He. (Github issue :issue:`3795`) * ``complex`` wasn't supported in PEP-484 type annotations. Patch by David Woods. (Github issue :issue:`3949`) * Default arguments of methods were not exposed for introspection. Patch by Vladimir Matveev. (Github issue :issue:`4061`) * Extension types inheriting from Python classes could not safely be exposed in ``.pxd`` files. (Github issue :issue:`4106`) * The profiling/tracing code was adapted to work with Python 3.10b1. * The internal CPython macro ``Py_ISSPACE()`` is no longer used. Original patch by Andrew Jones. (Github issue :issue:`4111`) * Includes all bug-fixes from the :ref:`0.29.23` release. 3.0.0 alpha 6 (2020-07-31) ========================== Features added -------------- * Special methods for binary operators now follow Python semantics. Rather than e.g. a single ``__add__`` method for cdef classes, where "self" can be either the first or second argument, one can now define both ``__add__`` and ``__radd__`` as for standard Python classes. This behavior can be disabled with the ``c_api_binop_methods`` directive to return to the previous semantics in Cython code (available from Cython 0.29.20), or the reversed method (``__radd__``) can be implemented in addition to an existing two-sided operator method (``__add__``) to get a backwards compatible implementation. (Github issue :issue:`2056`) * No/single argument functions now accept keyword arguments by default in order to comply with Python semantics. The marginally faster calling conventions ``METH_NOARGS`` and ``METH_O`` that reject keyword arguments are still available with the directive ``@cython.always_allow_keywords(False)``. (Github issue :issue:`3090`) * For-in-loop iteration over ``bytearray`` and memory views is optimised. Patch by David Woods. (Github issue :issue:`2227`) * Type inference now works for memory views and slices. Patch by David Woods. (Github issue :issue:`2227`) * The ``@returns()`` decorator propagates exceptions by default for suitable C return types when no ``@exceptval()`` is defined. (Github issues :issue:`3625`, :issue:`3664`) * A low-level inline function ``total_seconds(timedelta)`` was added to ``cpython.datetime`` to bypass the Python method call. Note that this function is not guaranteed to give exactly the same results for very large time intervals. Patch by Brock Mendel. (Github issue :issue:`3616`) * Type inference now understands that ``a, *b = x`` assigns a list to ``b``. * Limited API support was improved. Patches by Matthias Braun. (Github issues :issue:`3693`, :issue:`3707`) * The Cython ``CodeWriter`` can now handle more syntax constructs. Patch by Tao He. (Github issue :issue:`3514`) Bugs fixed ---------- * The construct ``for x in cpp_function_call()`` failed to compile. Patch by David Woods. (Github issue :issue:`3663`) * C++ references failed to compile when used as Python object indexes. Patch by David Woods. (Github issue :issue:`3754`) * The C++ ``typeid()`` function was allowed in C mode. Patch by Celelibi. (Github issue :issue:`3637`) * ``repr()`` was assumed to return ``str`` instead of ``unicode`` with ``language_level=3``. (Github issue :issue:`3736`) * Includes all bug-fixes from the :ref:`0.29.21` release. Other changes ------------- * The ``numpy`` declarations were updated. Patch by Brock Mendel. (Github issue :issue:`3630`) * The names of Cython's internal types (functions, generator, coroutine, etc.) are now qualified with the module name of the internal Cython module that is used for sharing them across Cython implemented modules, for example ``_cython_3_0a5.coroutine``. This was done to avoid making them look like homeless builtins, to help with debugging, and in order to avoid a CPython warning according to https://bugs.python.org/issue20204 3.0.0 alpha 5 (2020-05-19) ========================== Features added -------------- * ``.pxd`` files can now be :ref:`versioned ` by adding an extension like "``.cython-30.pxd``" to prevent older Cython versions (than 3.0 in this case) from picking them up. (Github issue :issue:`3577`) * Several macros/functions declared in the NumPy API are now usable without holding the GIL. * `libc.math` was extended to include all C99 function declarations. Patch by Dean Scarff. (Github issue :issue:`3570`) Bugs fixed ---------- * Several issues with arithmetic overflow handling were resolved, including undefined behaviour in C. Patch by Sam Sneddon. (Github issue :issue:`3588`) * The improved GIL handling in ``nogil`` functions introduced in 3.0a3 could fail to acquire the GIL in some cases on function exit. (Github issue :issue:`3590` etc.) * A reference leak when processing keyword arguments in Py2 was resolved, that appeared in 3.0a1. (Github issue :issue:`3578`) * The outdated getbuffer/releasebuffer implementations in the NumPy declarations were removed so that buffers declared as ``ndarray`` now use the normal implementation in NumPy. * Includes all bug-fixes from the :ref:`0.29.18` release. 3.0.0 alpha 4 (2020-05-05) ========================== Features added -------------- * The ``print`` statement (not the ``print()`` function) is allowed in ``nogil`` code without an explicit ``with gil`` section. * The ``assert`` statement is allowed in ``nogil`` sections. Here, the GIL is only acquired if the ``AssertionError`` is really raised, which means that the evaluation of the asserted condition only allows C expressions. * Cython generates C compiler branch hints for unlikely user defined if-clauses in more cases, when they end up raising exceptions unconditionally. This now includes exceptions being raised in ``nogil``/``with gil`` sections. * Some internal memoryview functions were tuned to reduce object overhead. Bugs fixed ---------- * Exception position reporting could run into race conditions on threaded code. It now uses function-local variables again. * Error handling early in the module init code could lead to a crash. * Error handling in ``cython.array`` creation was improved to avoid calling C-API functions with an error held. * Complex buffer item types of structs of arrays could fail to validate. Patch by Leo and smutch. (Github issue :issue:`1407`) * When importing the old Cython ``build_ext`` integration with distutils, the additional command line arguments leaked into the regular command. Patch by Kamekameha. (Github issue :issue:`2209`) * The improved GIL handling in ``nogil`` functions introduced in 3.0a3 could generate invalid C code. (Github issue :issue:`3558`) * ``PyEval_InitThreads()`` is no longer used in Py3.7+ where it is a no-op. * Parallel builds of Cython itself (``setup.py build_ext -j N``) failed on Windows. Other changes ------------- * The C property feature has been rewritten and now requires C property methods to be declared ``inline`` (:issue:`3571`). 3.0.0 alpha 3 (2020-04-27) ========================== Features added -------------- * ``nogil`` functions now avoid acquiring the GIL on function exit if possible even if they contain ``with gil`` blocks. (Github issue :issue:`3554`) * Python private name mangling now falls back to unmangled names for non-Python globals, since double-underscore names are not uncommon in C. Unmangled Python names are also still found as a legacy fallback but produce a warning. Patch by David Woods. (Github issue :issue:`3548`) Bugs fixed ---------- * Includes all bug-fixes from the :ref:`0.29.17` release. 3.0.0 alpha 2 (2020-04-23) ========================== Features added -------------- * ``std::move()`` is now used in C++ mode for internal temp variables to make them work without copying values. Patch by David Woods. (Github issues :issue:`3253`, :issue:`1612`) * ``__class_getitem__`` is supported for types on item access (`PEP-560`_). Patch by msg555. (Github issue :issue:`2753`) * The simplified Py3.6 customisation of class creation is implemented (`PEP-487`_). (Github issue :issue:`2781`) * Conditional blocks in Python code that depend on ``cython.compiled`` are eliminated at an earlier stage, which gives more freedom in writing replacement Python code. Patch by David Woods. (Github issue :issue:`3507`) * ``numpy.import_array()`` is automatically called if ``numpy`` has been cimported and it has not been called in the module code. This is intended as a hidden fail-safe so user code should continue to call ``numpy.import_array``. Patch by David Woods. (Github issue :issue:`3524`) * The Cython AST code serialiser class ``CodeWriter`` in ``Cython.CodeWriter`` supports more syntax nodes. * The fastcall/vectorcall protocols are used for several internal Python calls. (Github issue :issue:`3540`) Bugs fixed ---------- * With ``language_level=3/3str``, Python classes without explicit base class are now new-style (type) classes also in Py2. Previously, they were created as old-style (non-type) classes. (Github issue :issue:`3530`) * C++ ``typeid()`` failed for fused types. Patch by David Woods. (Github issue :issue:`3203`) * ``__arg`` argument names in methods were not mangled with the class name. Patch by David Woods. (Github issue :issue:`1382`) * Creating an empty unicode slice with large bounds could crash. Patch by Sam Sneddon. (Github issue :issue:`3531`) * Decoding an empty bytes/char* slice with large bounds could crash. Patch by Sam Sneddon. (Github issue :issue:`3534`) * Temporary buffer indexing variables were not released and could show up in C compiler warnings, e.g. in generators. Patch by David Woods. (Github issues :issue:`3430`, :issue:`3522`) * Several C compiler warnings were fixed. 3.0.0 alpha 1 (2020-04-12) ========================== Features added -------------- * Cython functions now use the `PEP-590`_ vectorcall protocol in Py3.7+. Patch by Jeroen Demeyer. (Github issue :issue:`2263`) * Unicode identifiers are supported in Cython code (`PEP-3131`_). Patch by David Woods. (Github issue :issue:`2601`) * Unicode module names and imports are supported. Patch by David Woods. (Github issue :issue:`3119`) * Annotations are no longer parsed, keeping them as strings following `PEP-563`_. Patch by David Woods. (Github issue :issue:`3285`) * Preliminary support for the CPython's ``Py_LIMITED_API`` (stable ABI) is available by setting the ``CYTHON_LIMITED_API`` C macro. Note that the support is currently in an early stage and many features do not yet work. You currently still have to define ``Py_LIMITED_API`` externally in order to restrict the API usage. This will change when the feature stabilises. Patches by Eddie Elizondo and David Woods. (Github issues :issue:`3223`, :issue:`3311`, :issue:`3501`) * The dispatch to fused functions is now linear in the number of arguments, which makes it much faster, often 2x or more, and several times faster for larger fused types with many specialisations. Patch by will-ca. (Github issue :issue:`1385`) * ``with gil/nogil`` statements can be conditional based on compile-time constants, e.g. fused type checks. Patch by Noam Hershtig. (Github issue :issue:`2579`) * ``const`` can be used together with fused types. Patch by Thomas Vincent. (Github issue :issue:`1772`) * Reimports of already imported modules are substantially faster. (Github issue :issue:`2854`) * Positional-only arguments are supported in Python functions (`PEP-570`_). Patch by Josh Tobin. (Github issue :issue:`2915`) * The ``volatile`` C modifier is supported in Cython code. Patch by Jeroen Demeyer. (Github issue :issue:`1667`) * ``@cython.trashcan(True)`` can be used on an extension type to enable the CPython :ref:`trashcan`. This allows deallocating deeply recursive objects without overflowing the stack. Patch by Jeroen Demeyer. (Github issue :issue:`2842`) * Inlined properties can be defined for external extension types. Patch by Matti Picus. (Github issue :issue:`2640`, redone later in :issue:`3571`) * The ``str()`` builtin now calls ``PyObject_Str()`` instead of going through a Python call. Patch by William Ayd. (Github issue :issue:`3279`) * String concatenation can now happen in place if possible, by extending the existing string rather than always creating a new one. Patch by David Woods. (Github issue :issue:`3453`) * Multiplication of Python numbers with small constant integers is faster. (Github issue :issue:`2808`) * Some list copying is avoided internally when a new list needs to be created but we already have a fresh one. (Github issue :issue:`3494`) * Extension types that do not need their own ``tp_new`` implementation (because they have no object attributes etc.) directly inherit the implementation of their parent type if possible. (Github issue :issue:`1555`) * The attributes ``gen.gi_frame`` and ``coro.cr_frame`` of Cython compiled generators and coroutines now return an actual frame object for introspection. (Github issue :issue:`2306`) * Several declarations in ``cpython.*``, ``libc.*`` and ``libcpp.*`` were added. Patches by Jeroen Demeyer, Matthew Edwards, Chris Gyurgyik, Jerome Kieffer and Zackery Spytz. (Github issues :issue:`3468`, :issue:`3332`, :issue:`3202`, :issue:`3188`, :issue:`3179`, :issue:`2891`, :issue:`2826`, :issue:`2713`) * Deprecated NumPy API usages were removed from ``numpy.pxd``. Patch by Matti Picus. (Github issue :issue:`3365`) * ``cython.inline()`` now sets the ``NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION`` C macro automatically when ``numpy`` is imported in the code, to avoid C compiler warnings about deprecated NumPy C-API usage. * The builtin ``abs()`` function can now be used on C numbers in nogil code. Patch by Elliott Sales de Andrade. (Github issue :issue:`2748`) * `PEP-479`_ (``generator_stop``) is now enabled by default with language level 3. (Github issue :issue:`2580`) * The ``cython.view.array`` type supports inheritance. Patch by David Woods. (Github issue :issue:`3413`) * Code annotation accepts a new debugging argument ``--annotate-fullc`` that will include the complete syntax highlighted C file in the HTML output. (Github issue :issue:`2855`) * ``--no-capture`` added to ``runtests.py`` to prevent stdout/stderr capturing during srctree tests. Patch by Matti Picus. (Github issue :issue:`2701`) * ``--no-docstrings`` option added to ``cythonize`` script. Original patch by mo-han. (Github issue :issue:`2889`) * ``cygdb`` gives better error messages when it fails to initialise the Python runtime support in gdb. Patch by Volker Weissmann. (Github issue :issue:`3489`) * The Pythran ``shape`` attribute is supported. Patch by Serge Guelton. (Github issue :issue:`3307`) Bugs fixed ---------- * The unicode methods ``.upper()``, ``.lower()`` and ``.title()`` were incorrectly optimised for single character input values and only returned the first character if multiple characters should have been returned. They now use the original Python methods again. * Fused argument types were not correctly handled in type annotations and ``cython.locals()``. Patch by David Woods. (Github issues :issue:`3391`, :issue:`3142`) * Diverging from the usual behaviour, ``len(memoryview)``, ``len(char*)`` and ``len(Py_UNICODE*)`` returned an unsigned ``size_t`` value. They now return a signed ``Py_ssize_t``, like other usages of ``len()``. * Nested dict literals in function call kwargs could incorrectly raise an error about duplicate keyword arguments, which are allowed when passing them from dict literals. (Github issue :issue:`2963`) * Item access (subscripting) with integer indices/keys always tried the Sequence protocol before the Mapping protocol, which diverged from Python semantics. It now passes through the Mapping protocol first when supported. (Github issue :issue:`1807`) * Name lookups in class bodies no longer go through an attribute lookup. Patch by Jeroen Demeyer. (Github issue :issue:`3100`) * Broadcast assignments to a multi-dimensional memory view slice could end up in the wrong places when the underlying memory view is known to be contiguous but the slice is not. (Github issue :issue:`2941`) * Pickling unbound methods of Python classes failed. Patch by Pierre Glaser. (Github issue :issue:`2972`) * The ``Py_hash_t`` type failed to accept arbitrary "index" values. (Github issue :issue:`2752`) * The first function line number of functions with decorators pointed to the signature line and not the first decorator line, as in Python. Patch by Felix Kohlgrüber. (Github issue :issue:`2536`) * Constant integer expressions that used a negative exponent were evaluated as integer 0 instead of the expected float value. Patch by Kryštof Pilnáček. (Github issue :issue:`2133`) * The ``cython.declare()`` and ``cython.cast()`` functions could fail in pure mode. Patch by Dmitry Shesterkin. (Github issue :issue:`3244`) * ``__doc__`` was not available inside of the class body during class creation. (Github issue :issue:`1635`) * Setting ``language_level=2`` in a file did not work if ``language_level=3`` was enabled globally before. Patch by Jeroen Demeyer. (Github issue :issue:`2791`) * ``__init__.pyx`` files were not always considered as package indicators. (Github issue :issue:`2665`) * Compiling package ``__init__`` files could fail under Windows due to an undefined export symbol. (Github issue :issue:`2968`) * A C compiler cast warning was resolved. Patch by Michael Buesch. (Github issue :issue:`2775`) * Binding staticmethods of Cython functions were not behaving like Python methods. Patch by Jeroen Demeyer. (Github issue :issue:`3106`, :issue:`3102`) * Memoryviews failed to compile when the ``cache_builtins`` feature was disabled. Patch by David Woods. (Github issue :issue:`3406`) Other changes ------------- * The default language level was changed to ``3str``, i.e. Python 3 semantics, but with ``str`` literals (also in Python 2.7). This is a backwards incompatible change from the previous default of Python 2 semantics. The previous behaviour is available through the directive ``language_level=2``. (Github issue :issue:`2565`) * Cython no longer generates ``__qualname__`` attributes for classes in Python 2.x since they are problematic there and not correctly maintained for subclasses. Patch by Jeroen Demeyer. (Github issue :issue:`2772`) * Source file fingerprinting now uses SHA-1 instead of MD5 since the latter tends to be slower and less widely supported these days. (Github issue :issue:`2790`) * The long deprecated include files ``python_*``, ``stdio``, ``stdlib`` and ``stl`` in ``Cython/Includes/Deprecated/`` were removed. Use the ``libc.*`` and ``cpython.*`` pxd modules instead. Patch by Jeroen Demeyer. (Github issue :issue:`2904`) * The search order for include files was changed. Previously it was ``include_directories``, ``Cython/Includes``, ``sys.path``. Now it is ``include_directories``, ``sys.path``, ``Cython/Includes``. This was done to allow third-party ``*.pxd`` files to override the ones in Cython. Patch by Matti Picus. (Github issue :issue:`2905`) * The command line parser was rewritten and modernised using ``argparse``. Patch by Egor Dranischnikow. (Github issue :issue:`2952`, :issue:`3001`) * Dotted filenames for qualified module names (``pkg.mod.pyx``) are deprecated. Use the normal Python package directory layout instead. (Github issue :issue:`2686`) * Binary Linux wheels now follow the manylinux2010 standard. Patch by Alexey Stepanov. (Github issue :issue:`3355`) * Support for Python 2.6 was removed. .. _`PEP-560`: https://www.python.org/dev/peps/pep-0560 .. _`PEP-570`: https://www.python.org/dev/peps/pep-0570 .. _`PEP-487`: https://www.python.org/dev/peps/pep-0487 .. _`PEP-590`: https://www.python.org/dev/peps/pep-0590 .. _`PEP-3131`: https://www.python.org/dev/peps/pep-3131 .. _`PEP-563`: https://www.python.org/dev/peps/pep-0563 .. _`PEP-479`: https://www.python.org/dev/peps/pep-0479 .. _0.29.37: 0.29.37 (2023-12-18) ==================== Bugs fixed ---------- * Fix a potential crash while cleaning up subtypes of externally imported extension types when terminating Python. This was introduced in Cython 0.29.35. * Fix a ``complex`` related compile error on Windows. (Github issue :issue:`5512`) * Compiling fused types used in pxd files could crash Cython in Python 3.11+. (Github issues :issue:`5894`, :issue:`5588`) * ``cythonize`` failed to consider the ``CYTHON_FORCE_REGEN`` env variable. Patch by Harmen Stoppels. (Github issue :issue:`5712`) .. _0.29.36: 0.29.36 (2023-07-04) ==================== Bugs fixed ---------- * Async generators lost their return value in PyPy. (Github issue :issue:`5465`) * The outdated C macro ``_PyGC_FINALIZED()`` is no longer used in Py3.9+. * The deprecated ``Py_OptimizeFlag`` is no longer used in Python 3.9+. (Github issue :issue:`5343`) * Using the global ``__debug__`` variable but not assertions could lead to compile errors. * The broken HTML template support was removed from Tempita. (Github issue :issue:`3309`) .. _0.29.35: 0.29.35 (2023-05-24) ==================== Bugs fixed ---------- * A garbage collection enabled subtype of a non-GC extension type could call into the deallocation function of the super type with GC tracking enabled. This could lead to crashes during deallocation if GC was triggered on the type at the same time. (Github issue :issue:`5432`) * Some C compile failures and crashes in CPython 3.12 were resolved. * ``except + nogil`` was syntactically not allowed. ``except +nogil`` (i.e. defining a C++ exception handling function called ``nogil``) is now disallowed to prevent typos. (Github issue :issue:`5430`) * A C compile failure in PyPy 3.10 was resolved. Patch by Matti Picus. (Github issue :issue:`5408`) * Cython modules now use PEP-489 multi-phase init by default in PyPy 3.9 and later. Original patch by Matti Picus. (Github issue :issue:`5413`) * API header files generated by different Cython versions can now be included in the same C file. (Github issue :issue:`5383`) * Function signatures containing a type like `tuple[()]` could not be printed. Patch by Lisandro Dalcin. (Github issue :issue:`5355`) .. _0.29.34: 0.29.34 (2023-04-02) ==================== Bugs fixed ---------- * A reference leak of the for-loop list/tuple iterable was resolved if the for-loop's ``else:`` branch executes a ``break`` for an outer loop. (Github issue :issue:`5347`) * Some C compile failures in CPython 3.12 were resolved. * Some old usages of the deprecated Python ``imp`` module were replaced with ``importlib``. Patch by Matúš Valo. (Github issue :issue:`5300`) * Some issues with ``depfile`` generation were resolved. Patches by Eli Schwartz. (Github issues :issue:`5279`, :issue:`5291`) .. _0.29.33: 0.29.33 (2023-01-06) ==================== Features added -------------- * The ``cythonize`` and ``cython`` commands have a new option ``-M`` / ``--depfile`` to generate ``.dep`` dependency files for the compilation unit. This can be used by external build tools to track these dependencies. The ``cythonize`` option was already available in Cython :ref:`0.29.27`. Patches by Evgeni Burovski and Eli Schwartz. (Github issue :issue:`1214`) Bugs fixed ---------- * ``const`` fused types could not be used with memory views. Patch by Thomas Vincent. (Github issue :issue:`1772`) * ``wstr`` usage was removed in Python 3.12 and later (PEP-623). (Github issue :issue:`5145`) * A type check assertion for Cython functions failed in debug Python builds. (Github issue :issue:`5031`) * Fixed various compiler warnings. Patches by Lisandro Dalcin et al. (Github issues :issue:`4948`, :issue:`5086`) * Fixed error when calculating complex powers of negative numbers. (Github issue :issue:`5014`) * Corrected a small mis-formatting of exception messages on Python 2. (Github issue :issue:`5018`) * The ``PyUnicode_AsUTF8AndSize()`` C-API function was missing from the CPython declarations. (Github issue :issue:`5163`) * A performance problem in the compiler was resolved when nesting conditional expressions. (Github issue :issue:`5197`) * Test suite problems with recent NumPy and CPython versions were resolved. (Github issues :issue:`5183`, :issue:`5190`) Other changes ------------- * The undocumented, untested and apparently useless syntax ``from somemodule cimport class/struct/union somename`` was deprecated in anticipation of its removal in Cython 3. The type modifier is not needed here and a plain ``cimport`` of the name will do. (Github issue :issue:`4905`) * Properly disable generation of descriptor docstrings on PyPy since they cause crashes. It was previously disabled, but only accidentally via a typo. Patch by Matti Picus. (Github issue :issue:`5083`) * The ``cpow`` directive of Cython 3.0 is available as a no-op. (Github issue :issue:`5016`) .. _0.29.32: 0.29.32 (2022-07-29) ==================== Bugs fixed ---------- * Revert "Using memoryview typed arguments in inner functions is now rejected as unsupported." Patch by David Woods. (Github issue :issue:`4798`) * ``from module import *`` failed in 0.29.31 when using memoryviews. Patch by David Woods. (Github issue :issue:`4927`) .. _0.29.31: 0.29.31 (2022-07-27) ==================== Features added -------------- * A new argument ``--module-name`` was added to the ``cython`` command to provide the (one) exact target module name from the command line. Patch by Matthew Brett and h-vetinari. (Github issue :issue:`4906`) * A new keyword ``noexcept`` was added for forward compatibility with Cython 3. Patch by David Woods. (Github issue :issue:`4903`) Bugs fixed ---------- * Use ``importlib.util.find_spec()`` instead of the deprecated ``importlib.find_loader()`` function when setting up the package path at import-time. Patch by Matti Picus. (Github issue :issue:`4764`) * Require the C compiler to support the two-arg form of ``va_start`` on Python 3.10 and higher. Patch by Thomas Caswell. (Github issue :issue:`4820`) * Make ``fused_type`` subscriptable in Shadow.py. Patch by Pfebrer. (Github issue :issue:`4842`) * Fix the incorrect code generation of the target type in ``bytearray`` loops. Patch by Kenrick Everett. (Github issue :issue:`4108`) * Atomic refcounts for memoryviews were not used on some GCC versions by accident. Patch by Sam Gross. (Github issue :issue:`4915`) * Silence some GCC ``-Wconversion`` warnings in C utility code. Patch by Lisandro Dalcin. (Github issue :issue:`4854`) * Tuple multiplication was ignored in expressions such as ``[*(1,) * 2]``. Patch by David Woods. (Github issue :issue:`4864`) * Calling ``append`` methods on extension types could fail to find the method in some cases. Patch by David Woods. (Github issue :issue:`4828`) * Ensure that object buffers (e.g. ``ndarray[object, ndim=1]``) containing ``NULL`` pointers are safe to use, returning ``None`` instead of the ``NULL`` pointer. Patch by Sebastian Berg. (Github issue :issue:`4859`) * Using memoryview typed arguments in inner functions is now rejected as unsupported. Patch by David Woods. (Github issue :issue:`4798`) * Compilation could fail on systems (e.g. FIPS) that block MD5 checksums at runtime. (Github issue :issue:`4909`) * Experimental adaptations for the CPython "nogil" fork was added. Note that there is no official support for this in Cython 0.x. Patch by Sam Gross. (Github issue :issue:`4912`) .. _0.29.30: 0.29.30 (2022-05-16) ==================== Bugs fixed ---------- * The GIL handling changes in 0.29.29 introduced a regression where objects could be deallocated without holding the GIL. (Github issue :issue:`4796`) .. _0.29.29: 0.29.29 (2022-05-16) ==================== Features added -------------- * Avoid acquiring the GIL at the end of nogil functions. This change was backported in order to avoid generating wrong C code that would trigger C compiler warnings with tracing support enabled. Backport by Oleksandr Pavlyk. (Github issue :issue:`4637`) Bugs fixed ---------- * Function definitions in ``finally:`` clauses were not correctly generated. Patch by David Woods. (Github issue :issue:`4651`) * A case where C-API functions could be called with a live exception set was fixed. Patch by Jakub Kulík. (Github issue :issue:`4722`) * Pickles can now be exchanged again with those generated from Cython 3.0 modules. (Github issue :issue:`4680`) * Cython now correctly generates Python methods for both the provided regular and reversed special numeric methods of extension types. Patch by David Woods. (Github issue :issue:`4750`) * Calling unbound extension type methods without arguments could raise an ``IndexError`` instead of a ``TypeError``. Patch by David Woods. (Github issue :issue:`4779`) * Calling unbound ``.__contains__()`` super class methods on some builtin base types could trigger an infinite recursion. Patch by David Woods. (Github issue :issue:`4785`) * The C union type in pure Python mode mishandled some field names. Patch by Jordan Brière. (Github issue :issue:`4727`) * Allow users to overwrite the C macro ``_USE_MATH_DEFINES``. Patch by Yuriy Chernyshov. (Github issue :issue:`4690`) * Improved compatibility with CPython 3.10/11. Patches by Thomas Caswell, David Woods. (Github issues :issue:`4609`, :issue:`4667`, :issue:`4721`, :issue:`4730`, :issue:`4777`) * Docstrings of descriptors are now provided in PyPy 7.3.9. Patch by Matti Picus. (Github issue :issue:`4701`) .. _0.29.28: 0.29.28 (2022-02-17) ==================== Bugs fixed ---------- * Due to backwards incompatible changes in CPython 3.11a4, the feature flags ``CYTHON_FAST_THREAD_STATE`` and ``CYTHON_USE_EXC_INFO_STACK`` are now disabled in Python 3.11 and later. They are enabled again in Cython 3.0. Patch by David Woods. (Github issue :issue:`4610`) * A C compiler warning in older PyPy versions was resolved. Patch by Matti Picus. (Github issue :issue:`4236`) .. _0.29.27: 0.29.27 (2022-01-28) ==================== Features added -------------- * The ``cythonize`` command has a new option ``-M`` to generate ``.dep`` dependency files for the compilation unit. This can be used by external build tools to track these dependencies. Patch by Evgeni Burovski. (Github issue :issue:`1214`) Bugs fixed ---------- * Compilation failures on PyPy were resolved. Patches by Matti Picus. (Github issues :issue:`4509`, :issue:`4517`) * Calls to ``range()`` with more than three arguments did not fail. Original patch by Max Bachmann. (Github issue :issue:`4550`) * Some C compiler warnings about missing type struct initialisers in Py3.10 were resolved. * Cython no longer warns about using OpenMP 3.0 features since they are now considered generally available. .. _0.29.26: 0.29.26 (2021-12-16) ==================== Bugs fixed ---------- * An incompatibility with CPython 3.11.0a3 was resolved. (Github issue :issue:`4499`) * The ``in`` operator failed on literal lists with starred expressions. Patch by Arvind Natarajan. (Github issue :issue:`3938`) * A C compiler warning in PyPy about a missing struct field initialisation was resolved. .. _0.29.25: 0.29.25 (2021-12-06) ==================== Bugs fixed ---------- * Several incompatibilities with CPython 3.11 were resolved. Patches by David Woods, Victor Stinner, Thomas Caswell. (Github issues :issue:`4411`, :issue:`4414`, :issue:`4415`, :issue:`4416`, :issue:`4420`, :issue:`4428`, :issue:`4473`, :issue:`4479`, :issue:`4480`) * Some C compiler warnings were resolved. Patches by Lisandro Dalcin and others. (Github issue :issue:`4439`) * C++ ``std::move()`` should only be used automatically in MSVC versions that support it. Patch by Max Bachmann. (Github issue :issue:`4191`) * The ``Py_hash_t`` type failed to accept arbitrary "index" values. (Github issue :issue:`2752`) * Avoid copying unaligned 16-bit values since some platforms require them to be aligned. Use memcpy() instead to let the C compiler decide how to do it. (Github issue :issue:`4343`) * Cython crashed on invalid truthiness tests on C++ types without ``operator bool``. Patch by David Woods. (Github issue :issue:`4348`) * The declaration of ``PyUnicode_CompareWithASCIIString()`` in ``cpython.unicode`` was incorrect. Patch by Max Bachmann. (Github issue :issue:`4344`) .. _0.29.24: 0.29.24 (2021-07-14) ==================== Bugs fixed ---------- * Inline functions in pxd files that used memory views could lead to invalid C code if the module that imported from them does not use memory views. Patch by David Woods. (Github issue :issue:`1415`) * Several declarations in ``libcpp.string`` were added and corrected. Patch by Janek Bevendorff. (Github issue :issue:`4268`) * Pickling unbound Cython compiled methods failed. Patch by Pierre Glaser. (Github issue :issue:`2972`) * The tracing code was adapted to work with CPython 3.10. * The optimised ``in`` operator failed on unicode strings in Py3.9 and later that were constructed from an external ``wchar_t`` source. Also, related C compiler warnings about deprecated C-API usage were resolved. (Github issue :issue:`3925`) * Some compiler crashes were resolved. Patch by David Woods. (Github issues :issue:`4214`, :issue:`2811`) * An incorrect warning about 'unused' generator expressions was removed. (GIthub issue :issue:`1699`) * The attributes ``gen.gi_frame`` and ``coro.cr_frame`` of Cython compiled generators and coroutines now return an actual frame object for introspection, instead of ``None``. (Github issue :issue:`2306`) .. _0.29.23: 0.29.23 (2021-04-14) ==================== Bugs fixed ---------- * Some problems with Python 3.10 were resolved. Patches by Victor Stinner and David Woods. (Github issues :issue:`4046`, :issue:`4100`) * An incorrect "optimisation" was removed that allowed changes to a keyword dict to leak into keyword arguments passed into a function. Patch by Peng Weikang. (Github issue :issue:`3227`) * Multiplied str constants could end up as bytes constants with language_level=2. Patch by Alphadelta14 and David Woods. (Github issue :issue:`3951`) * ``PY_SSIZE_T_CLEAN`` does not get defined any more if it is already defined. Patch by Andrew Jones. (Github issue :issue:`4104`) .. _0.29.22: 0.29.22 (2021-02-20) ==================== Features added -------------- * Some declarations were added to the provided pxd includes. Patches by Zackery Spytz and John Kirkham. (Github issues :issue:`3811`, :issue:`3882`, :issue:`3899`, :issue:`3901`) Bugs fixed ---------- * A crash when calling certain functions in Py3.9 and later was resolved. (Github issue :issue:`3917`) * ``const`` memory views of structs failed to compile. (Github issue :issue:`2251`) * ``const`` template declarations could not be nested. Patch by Ashwin Srinath. (Github issue :issue:`1355`) * The declarations in the ``cpython.pycapsule`` module were missing their ``const`` modifiers and generated incorrect C code. Patch by Warren Weckesser. (Github issue :issue:`3964`) * Casts to memory views failed for fused dtypes. Patch by David Woods. (Github issue :issue:`3881`) * ``repr()`` was assumed to return ``str`` instead of ``unicode`` with ``language_level=3``. (Github issue :issue:`3736`) * Calling ``cpdef`` functions from cimported modules crashed the compiler. Patch by David Woods. (Github issue :issue:`4000`) * Cython no longer validates the ABI size of the NumPy classes it compiled against. See the discussion in https://github.com/numpy/numpy/pull/432 * A C compiler warning about enum value casting was resolved in GCC. (Github issue :issue:`2749`) * Coverage reporting in the annotated HTML file failed in Py3.9. Patch by Nick Pope. (Github issue :issue:`3865`) * The embedding code now reports Python errors as exit status. * Long type declarations could lead to (harmless) random changes in the C file when used in auto-generated Python wrappers or pickled classes. Other changes ------------- * Variables defined as ``cpdef`` now generate a warning since this is currently useless and thus does not do what users would expect. Patch by David Woods. (Github issue :issue:`3959`) .. _0.29.21: 0.29.21 (2020-07-09) ==================== Bugs fixed ---------- * Fix a regression in 0.29.20 where ``__div__`` failed to be found in extension types. (Github issue :issue:`3688`) * Fix a regression in 0.29.20 where a call inside of a finally clause could fail to compile. Patch by David Woods. (Github issue :issue:`3712`) * Zero-sized buffers could fail to validate as C/Fortran-contiguous. Patch by Clemens Hofreither. (Github issue :issue:`2093`) * ``exec()`` did not allow recent Python syntax features in Py3.8+ due to https://bugs.python.org/issue35975. (Github issue :issue:`3695`) * Binding staticmethods of Cython functions were not behaving like Python methods in Py3. Patch by Jeroen Demeyer and Michał Górny. (Github issue :issue:`3106`) * Pythran calls to NumPy methods no longer generate useless method lookup code. * The ``PyUnicode_GET_LENGTH()`` macro was missing from the ``cpython.*`` declarations. Patch by Thomas Caswell. (Github issue :issue:`3692`) * The deprecated ``PyUnicode_*()`` C-API functions are no longer used, except for Unicode strings that contain lone surrogates. Unicode strings that contain non-BMP characters or surrogate pairs now generate different C code on 16-bit Python 2.x Unicode deployments (such as MS-Windows). Generating the C code on Python 3.x is recommended in this case. Original patches by Inada Naoki and Victor Stinner. (Github issues :issue:`3677`, :issue:`3721`, :issue:`3697`) * Some template parameters were missing from the C++ ``std::unordered_map`` declaration. Patch by will. (Github issue :issue:`3685`) * Several internal code generation issues regarding temporary variables were resolved. (Github issue :issue:`3708`) .. _0.29.20: 0.29.20 (2020-06-10) ==================== Bugs fixed ---------- * Nested try-except statements with multiple ``return`` statements could crash due to incorrect deletion of the ``except as`` target variable. (Github issue :issue:`3666`) * The ``@classmethod`` decorator no longer rejects unknown input from other decorators. Patch by David Woods. (Github issue :issue:`3660`) * Fused types could leak into unrelated usages. Patch by David Woods. (Github issue :issue:`3642`) * Now uses ``Py_SET_SIZE()`` and ``Py_SET_REFCNT()`` in Py3.9+ to avoid low-level write access to these object fields. Patch by Victor Stinner. (Github issue :issue:`3639`) * The built-in ``abs()`` function could lead to undefined behaviour when used on the negative-most value of a signed C integer type. Patch by Serge Guelton. (Github issue :issue:`1911`) * Usages of ``sizeof()`` and ``typeid()`` on uninitialised variables no longer produce a warning. Patch by Celelibi. (Github issue :issue:`3575`) * The C++ ``typeid()`` function was allowed in C mode. Patch by Celelibi. (Github issue :issue:`3637`) * The error position reported for errors found in f-strings was misleading. (Github issue :issue:`3674`) * The new ``c_api_binop_methods`` directive was added for forward compatibility, but can only be set to True (the current default value). It can be disabled in Cython 3.0. .. _0.29.19: 0.29.19 (2020-05-20) ==================== Bugs fixed ---------- * A typo in Windows specific code in 0.29.18 was fixed that broke "libc.math". (Github issue :issue:`3622`) * A platform specific test failure in 0.29.18 was fixed. Patch by smutch. (Github issue :issue:`3620`) .. _0.29.18: 0.29.18 (2020-05-18) ==================== Bugs fixed ---------- * Exception position reporting could run into race conditions on threaded code. It now uses function-local variables again. * Error handling early in the module init code could lead to a crash. * Error handling in ``cython.array`` creation was improved to avoid calling C-API functions with an error held. * A memory corruption was fixed when garbage collection was triggered during calls to ``PyType_Ready()`` of extension type subclasses. (Github issue :issue:`3603`) * Memory view slicing generated unused error handling code which could negatively impact the C compiler optimisations for parallel OpenMP code etc. Also, it is now helped by static branch hints. (Github issue :issue:`2987`) * Cython's built-in OpenMP functions were not translated inside of call arguments. Original patch by Celelibi and David Woods. (Github issue :issue:`3594`) * Complex buffer item types of structs of arrays could fail to validate. Patch by Leo and smutch. (Github issue :issue:`1407`) * Decorators were not allowed on nested `async def` functions. (Github issue :issue:`1462`) * C-tuples could use invalid C struct casting. Patch by MegaIng. (Github issue :issue:`3038`) * Optimised ``%d`` string formatting into f-strings failed on float values. (Github issue :issue:`3092`) * Optimised aligned string formatting (``%05s``, ``%-5s``) failed. (Github issue :issue:`3476`) * When importing the old Cython ``build_ext`` integration with distutils, the additional command line arguments leaked into the regular command. Patch by Kamekameha. (Github issue :issue:`2209`) * When using the ``CYTHON_NO_PYINIT_EXPORT`` option in C++, the module init function was not declared as ``extern "C"``. (Github issue :issue:`3414`) * Three missing timedelta access macros were added in ``cpython.datetime``. * The signature of the NumPy C-API function ``PyArray_SearchSorted()`` was fixed. Patch by Brock Mendel. (Github issue :issue:`3606`) .. _0.29.17: 0.29.17 (2020-04-26) ==================== Features added -------------- * ``std::move()`` is now available from ``libcpp.utility``. Patch by Omer Ozarslan. (Github issue :issue:`2169`) * The ``@cython.binding`` decorator is available in Python code. (Github issue :issue:`3505`) Bugs fixed ---------- * Creating an empty unicode slice with large bounds could crash. Patch by Sam Sneddon. (Github issue :issue:`3531`) * Decoding an empty bytes/char* slice with large bounds could crash. Patch by Sam Sneddon. (Github issue :issue:`3534`) * Re-importing a Cython extension no longer raises the error "``__reduce_cython__ not found``". (Github issue :issue:`3545`) * Unused C-tuples could generate incorrect code in 0.29.16. Patch by Kirk Meyer. (Github issue :issue:`3543`) * Creating a fused function attached it to the garbage collector before it was fully initialised, thus risking crashes in rare failure cases. Original patch by achernomorov. (Github issue :issue:`3215`) * Temporary buffer indexing variables were not released and could show up in C compiler warnings, e.g. in generators. Patch by David Woods. (Github issues :issue:`3430`, :issue:`3522`) * The compilation cache in ``cython.inline("…")`` failed to take the language level into account. Patch by will-ca. (Github issue :issue:`3419`) * The deprecated ``PyUnicode_GET_SIZE()`` function is no longer used in Py3. .. _0.29.16: 0.29.16 (2020-03-24) ==================== Bugs fixed ---------- * Temporary internal variables in nested prange loops could leak into other threads. Patch by Frank Schlimbach. (Github issue :issue:`3348`) * Default arguments on fused functions could crash. Patch by David Woods. (Github issue :issue:`3370`) * C-tuples declared in ``.pxd`` files could generate incomplete C code. Patch by Kirk Meyer. (Github issue :issue:`1427`) * Fused functions were not always detected and optimised as Cython implemented functions. Patch by David Woods. (Github issue :issue:`3384`) * Valid Python object concatenation of (iterable) strings to non-strings could fail with an exception. Patch by David Woods. (Github issue :issue:`3433`) * Using C functions as temporary values lead to invalid C code. Original patch by David Woods. (Github issue :issue:`3418`) * Fix an unhandled C++ exception in comparisons. Patch by David Woods. (Github issue :issue:`3361`) * Fix deprecated import of "imp" module. Patch by Matti Picus. (Github issue :issue:`3350`) * Fix compatibility with Pythran 0.9.6 and later. Patch by Serge Guelton. (Github issue :issue:`3308`) * The ``_Py_PyAtExit()`` function in ``cpython.pylifecycle`` was misdeclared. Patch by Zackery Spytz. (Github issue :issue:`3382`) * Several missing declarations in ``cpython.*`` were added. Patches by Zackery Spytz. (Github issue :issue:`3452`, :issue:`3421`, :issue:`3411`, :issue:`3402`) * A declaration for ``libc.math.fpclassify()`` was added. Patch by Zackery Spytz. (Github issue :issue:`2514`) * Avoid "undeclared" warning about automatically generated pickle methods. Patch by David Woods. (Github issue :issue:`3353`) * Avoid C compiler warning about unreachable code in ``prange()``. * Some C compiler warnings in PyPy were resolved. Patch by Matti Picus. (Github issue :issue:`3437`) .. _0.29.15: 0.29.15 (2020-02-06) ==================== Bugs fixed ---------- * Crash when returning a temporary Python object from an async-def function. (Github issue :issue:`3337`) * Crash when using ``**kwargs`` in generators. Patch by David Woods. (Github issue :issue:`3265`) * Double reference free in ``__class__`` cell handling for ``super()`` calls. (Github issue :issue:`3246`) * Compile error when using ``*args`` as Python class bases. (Github issue :issue:`3338`) * Import failure in IPython 7.11. (Github issue :issue:`3297`) * Fixed C name collision in the auto-pickle code. Patch by ThePrez. (Github issue :issue:`3238`) * Deprecated import failed in Python 3.9. (Github issue :issue:`3266`) .. _0.29.14: 0.29.14 (2019-11-01) ==================== Bugs fixed ---------- * The generated code failed to initialise the ``tp_print`` slot in CPython 3.8. Patches by Pablo Galindo and Orivej Desh. (Github issues :issue:`3171`, :issue:`3201`) * ``?`` for ``bool`` was missing from the supported NumPy dtypes. Patch by Max Klein. (Github issue :issue:`2675`) * ``await`` was not allowed inside of f-strings. Patch by Dmitro Getz. (Github issue :issue:`2877`) * Coverage analysis failed for projects where the code resides in separate source sub-directories. Patch by Antonio Valentino. (Github issue :issue:`1985`) * An incorrect compiler warning was fixed in automatic C++ string conversions. Patch by Gerion Entrup. (Github issue :issue:`3108`) * Error reports in the Jupyter notebook showed unhelpful stack traces. Patch by Matthew Edwards (Github issue :issue:`3196`). * ``Python.h`` is now also included explicitly from ``public`` header files. (Github issue :issue:`3133`). * Distutils builds with ``--parallel`` did not work when using Cython's deprecated ``build_ext`` command. Patch by Alphadelta14 (Github issue :issue:`3187`). Other changes ------------- * The ``PyMemoryView_*()`` C-API is available in ``cpython.memoryview``. Patch by Nathan Manville. (Github issue :issue:`2541`) 0.29.13 (2019-07-26) ==================== Bugs fixed ---------- * A reference leak for ``None`` was fixed when converting a memoryview to a Python object. (Github issue :issue:`3023`) * The declaration of ``PyGILState_STATE`` in ``cpython.pystate`` was unusable. Patch by Kirill Smelkov. (Github issue :issue:`2997`) Other changes ------------- * The declarations in ``posix.mman`` were extended. Patches by Kirill Smelkov. (Github issues :issue:`2893`, :issue:`2894`, :issue:`3012`) 0.29.12 (2019-07-07) ==================== Bugs fixed ---------- * Fix compile error in CPython 3.8b2 regarding the ``PyCode_New()`` signature. (Github issue :issue:`3031`) * Fix a C compiler warning about a missing ``int`` downcast. (Github issue :issue:`3028`) * Fix reported error positions of undefined builtins and constants. Patch by Orivej Desh. (Github issue :issue:`3030`) * A 32 bit issue in the Pythran support was resolved. Patch by Serge Guelton. (Github issue :issue:`3032`) 0.29.11 (2019-06-30) ==================== Bugs fixed ---------- * Fix compile error in CPython 3.8b2 regarding the ``PyCode_New()`` signature. Patch by Nick Coghlan. (Github issue :issue:`3009`) * Invalid C code generated for lambda functions in cdef methods. Patch by Josh Tobin. (Github issue :issue:`2967`) * Support slice handling in newer Pythran versions. Patch by Serge Guelton. (Github issue :issue:`2989`) * A reference leak in power-of-2 calculation was fixed. Patch by Sebastian Berg. (Github issue :issue:`3022`) * The search order for include files was changed. Previously it was ``include_directories``, ``Cython/Includes``, ``sys.path``. Now it is ``include_directories``, ``sys.path``, ``Cython/Includes``. This was done to allow third-party ``*.pxd`` files to override the ones in Cython. Original patch by Matti Picus. (Github issue :issue:`2905`) * Setting ``language_level=2`` in a file did not work if ``language_level=3`` was enabled globally before. Patch by Jeroen Demeyer. (Github issue :issue:`2791`) 0.29.10 (2019-06-02) ==================== Bugs fixed ---------- * Fix compile errors in CPython 3.8b1 due to the new "tp_vectorcall" slots. (Github issue :issue:`2976`) 0.29.9 (2019-05-29) =================== Bugs fixed ---------- * Fix a crash regression in 0.29.8 when creating code objects fails. * Remove an incorrect cast when using true-division in C++ operations. (Github issue :issue:`1950`) 0.29.8 (2019-05-28) =================== Bugs fixed ---------- * C compile errors with CPython 3.8 were resolved. Patch by Marcel Plch. (Github issue :issue:`2938`) * Python tuple constants that compare equal but have different item types could incorrectly be merged into a single constant. (Github issue :issue:`2919`) * Non-ASCII characters in unprefixed strings could crash the compiler when used with language level ``3str``. * Starred expressions in %-formatting tuples could fail to compile for unicode strings. (Github issue :issue:`2939`) * Passing Python class references through ``cython.inline()`` was broken. (Github issue :issue:`2936`) 0.29.7 (2019-04-14) =================== Bugs fixed ---------- * Crash when the shared Cython config module gets unloaded and another Cython module reports an exceptions. Cython now makes sure it keeps an owned reference to the module. (Github issue :issue:`2885`) * Resolved a C89 compilation problem when enabling the fast-gil sharing feature. * Coverage reporting did not include the signature line of ``cdef`` functions. (Github issue :issue:`1461`) * Casting a GIL-requiring function into a nogil function now issues a warning. (Github issue :issue:`2879`) * Generators and coroutines were missing their return type annotation. (Github issue :issue:`2884`) 0.29.6 (2019-02-27) =================== Bugs fixed ---------- * Fix a crash when accessing the ``__kwdefaults__`` special attribute of fused functions. (Github issue :issue:`1470`) * Fix the parsing of buffer format strings that contain numeric sizes, which could lead to incorrect input rejections. (Github issue :issue:`2845`) * Avoid a C #pragma in old gcc versions that was only added in GCC 4.6. Patch by Michael Anselmi. (Github issue :issue:`2838`) * Auto-encoding of Unicode strings to UTF-8 C/C++ strings failed in Python 3, even though the default encoding there is UTF-8. (Github issue :issue:`2819`) 0.29.5 (2019-02-09) =================== Bugs fixed ---------- * Crash when defining a Python subclass of an extension type and repeatedly calling a cpdef method on it. (Github issue :issue:`2823`) * Compiler crash when ``prange()`` loops appear inside of with-statements. (Github issue :issue:`2780`) * Some C compiler warnings were resolved. Patches by Christoph Gohlke. (Github issues :issue:`2815`, :issue:`2816`, :issue:`2817`, :issue:`2822`) * Python conversion of C++ enums failed in 0.29. Patch by Orivej Desh. (Github issue :issue:`2767`) 0.29.4 (2019-02-01) =================== Bugs fixed ---------- * Division of numeric constants by a runtime value of 0 could fail to raise a ``ZeroDivisionError``. (Github issue :issue:`2820`) 0.29.3 (2019-01-19) =================== Bugs fixed ---------- * Some C code for memoryviews was generated in a non-deterministic order. Patch by Martijn van Steenbergen. (Github issue :issue:`2779`) * C89 compatibility was accidentally lost since 0.28. Patches by gastineau and true-pasky. (Github issues :issue:`2778`, :issue:`2801`) * A C compiler cast warning was resolved. Patch by Michael Buesch. (Github issue :issue:`2774`) * An compilation failure with complex numbers under MSVC++ was resolved. (Github issue :issue:`2797`) * Coverage reporting could fail when modules were moved around after the build. Patch by Wenjun Si. (Github issue :issue:`2776`) 0.29.2 (2018-12-14) =================== Bugs fixed ---------- * The code generated for deduplicated constants leaked some references. (Github issue :issue:`2750`) * The declaration of ``sigismember()`` in ``libc.signal`` was corrected. (Github issue :issue:`2756`) * Crashes in compiler and test runner were fixed. (Github issue :issue:`2736`, :issue:`2755`) * A C compiler warning about an invalid safety check was resolved. (Github issue :issue:`2731`) 0.29.1 (2018-11-24) =================== Bugs fixed ---------- * Extensions compiled with MinGW-64 under Windows could misinterpret integer objects larger than 15 bit and return incorrect results. (Github issue :issue:`2670`) * Cython no longer requires the source to be writable when copying its data into a memory view slice. Patch by Andrey Paramonov. (Github issue :issue:`2644`) * Line tracing of ``try``-statements generated invalid C code. (Github issue :issue:`2274`) * When using the ``warn.undeclared`` directive, Cython's own code generated warnings that are now fixed. Patch by Nicolas Pauss. (Github issue :issue:`2685`) * Cython's memoryviews no longer require strides for setting the shape field but only the ``PyBUF_ND`` flag to be set. Patch by John Kirkham. (Github issue :issue:`2716`) * Some C compiler warnings about unused memoryview code were fixed. Patch by Ho Cheuk Ting. (Github issue :issue:`2588`) * A C compiler warning about implicit signed/unsigned conversion was fixed. (Github issue :issue:`2729`) * Assignments to C++ references returned by ``operator[]`` could fail to compile. (Github issue :issue:`2671`) * The power operator and the support for NumPy math functions were fixed in Pythran expressions. Patch by Serge Guelton. (Github issues :issue:`2702`, :issue:`2709`) * Signatures with memory view arguments now show the expected type when embedded in docstrings. Patch by Matthew Chan and Benjamin Weigel. (Github issue :issue:`2634`) * Some ``from ... cimport ...`` constructs were not correctly considered when searching modified dependencies in ``cythonize()`` to decide whether to recompile a module. Patch by Kryštof Pilnáček. (Github issue :issue:`2638`) * A struct field type in the ``cpython.array`` declarations was corrected. Patch by John Kirkham. (Github issue :issue:`2712`) 0.29 (2018-10-14) ================= Features added -------------- * PEP-489 multi-phase module initialisation has been enabled again. Module reloads in other subinterpreters raise an exception to prevent corruption of the static module state. * A set of ``mypy`` compatible PEP-484 declarations were added for Cython's C data types to integrate with static analysers in typed Python code. They are available in the ``Cython/Shadow.pyi`` module and describe the types in the special ``cython`` module that can be used for typing in Python code. Original patch by Julian Gethmann. (Github issue :issue:`1965`) * Memoryviews are supported in PEP-484/526 style type declarations. (Github issue :issue:`2529`) * ``@cython.nogil`` is supported as a C-function decorator in Python code. (Github issue :issue:`2557`) * Raising exceptions from nogil code will automatically acquire the GIL, instead of requiring an explicit ``with gil`` block. * C++ functions can now be declared as potentially raising both C++ and Python exceptions, so that Cython can handle both correctly. (Github issue :issue:`2615`) * ``cython.inline()`` supports a direct ``language_level`` keyword argument that was previously only available via a directive. * A new language level name ``3str`` was added that mostly corresponds to language level 3, but keeps unprefixed string literals as type 'str' in both Py2 and Py3, and the builtin 'str' type unchanged. This will become the default in the next Cython release and is meant to help user code a) transition more easily to this new default and b) migrate to Python 3 source code semantics without making support for Python 2.x difficult. * In CPython 3.6 and later, looking up globals in the module dict is almost as fast as looking up C globals. (Github issue :issue:`2313`) * For a Python subclass of an extension type, repeated method calls to non-overridden cpdef methods can avoid the attribute lookup in Py3.6+, which makes them 4x faster. (Github issue :issue:`2313`) * (In-)equality comparisons of objects to integer literals are faster. (Github issue :issue:`2188`) * Some internal and 1-argument method calls are faster. * Modules that cimport many external extension types from other Cython modules execute less import requests during module initialisation. * Constant tuples and slices are deduplicated and only created once per module. (Github issue :issue:`2292`) * The coverage plugin considers more C file extensions such as ``.cc`` and ``.cxx``. (Github issue :issue:`2266`) * The ``cythonize`` command accepts compile time variable values (as set by ``DEF``) through the new ``-E`` option. Patch by Jerome Kieffer. (Github issue :issue:`2315`) * ``pyximport`` can import from namespace packages. Patch by Prakhar Goel. (Github issue :issue:`2294`) * Some missing numpy and CPython C-API declarations were added. Patch by John Kirkham. (Github issues :issue:`2523`, :issue:`2520`, :issue:`2537`) * Declarations for the ``pylifecycle`` C-API functions were added in a new .pxd file ``cpython.pylifecycle``. * The Pythran support was updated to work with the latest Pythran 0.8.7. Original patch by Adrien Guinet. (Github issue :issue:`2600`) * ``%a`` is included in the string formatting types that are optimised into f-strings. In this case, it is also automatically mapped to ``%r`` in Python 2.x. * New C macro ``CYTHON_HEX_VERSION`` to access Cython's version in the same style as ``PY_VERSION_HEX``. * Constants in ``libc.math`` are now declared as ``const`` to simplify their handling. * An additional ``check_size`` clause was added to the ``ctypedef class`` name specification to allow suppressing warnings when importing modules with backwards-compatible ``PyTypeObject`` size changes. Patch by Matti Picus. (Github issue :issue:`2627`) Bugs fixed ---------- * The exception handling in generators and coroutines under CPython 3.7 was adapted to the newly introduced exception stack. Users of Cython 0.28 who want to support Python 3.7 are encouraged to upgrade to 0.29 to avoid potentially incorrect error reporting and tracebacks. (Github issue :issue:`1958`) * Crash when importing a module under Stackless Python that was built for CPython. Patch by Anselm Kruis. (Github issue :issue:`2534`) * 2-value slicing of typed sequences failed if the start or stop index was None. Patch by Christian Gibson. (Github issue :issue:`2508`) * Multiplied string literals lost their factor when they are part of another constant expression (e.g. 'x' * 10 + 'y' => 'xy'). * String formatting with the '%' operator didn't call the special ``__rmod__()`` method if the right side is a string subclass that implements it. (Python issue 28598) * The directive ``language_level=3`` did not apply to the first token in the source file. (Github issue :issue:`2230`) * Overriding cpdef methods did not work in Python subclasses with slots. Note that this can have a performance impact on calls from Cython code. (Github issue :issue:`1771`) * Fix declarations of builtin or C types using strings in pure python mode. (Github issue :issue:`2046`) * Generator expressions and lambdas failed to compile in ``@cfunc`` functions. (Github issue :issue:`459`) * Global names with ``const`` types were not excluded from star-import assignments which could lead to invalid C code. (Github issue :issue:`2621`) * Several internal function signatures were fixed that lead to warnings in gcc-8. (Github issue :issue:`2363`) * The numpy helper functions ``set_array_base()`` and ``get_array_base()`` were adapted to the current numpy C-API recommendations. Patch by Matti Picus. (Github issue :issue:`2528`) * Some NumPy related code was updated to avoid deprecated API usage. Original patch by jbrockmendel. (Github issue :issue:`2559`) * Several C++ STL declarations were extended and corrected. Patch by Valentin Valls. (Github issue :issue:`2207`) * C lines of the module init function were unconditionally not reported in exception stack traces. Patch by Jeroen Demeyer. (Github issue :issue:`2492`) * When PEP-489 support is enabled, reloading the module overwrote any static module state. It now raises an exception instead, given that reloading is not actually supported. * Object-returning, C++ exception throwing functions were not checking that the return value was non-null. Original patch by Matt Wozniski (Github issue :issue:`2603`) * The source file encoding detection could get confused if the ``c_string_encoding`` directive appeared within the first two lines. (Github issue :issue:`2632`) * Cython generated modules no longer emit a warning during import when the size of the NumPy array type is larger than what was found at compile time. Instead, this is assumed to be a backwards compatible change on NumPy side. Other changes ------------- * Cython now emits a warning when no ``language_level`` (2, 3 or '3str') is set explicitly, neither as a ``cythonize()`` option nor as a compiler directive. This is meant to prepare the transition of the default language level from currently Py2 to Py3, since that is what most new users will expect these days. The future default will, however, not enforce unicode literals, because this has proven a major obstacle in the support for both Python 2.x and 3.x. The next major release is intended to make this change, so that it will parse all code that does not request a specific language level as Python 3 code, but with ``str`` literals. The language level 2 will continue to be supported for an indefinite time. * The documentation was restructured, cleaned up and examples are now tested. The NumPy tutorial was also rewritten to simplify the running example. Contributed by Gabriel de Marmiesse. (Github issue :issue:`2245`) * Cython compiles less of its own modules at build time to reduce the installed package size to about half of its previous size. This makes the compiler slightly slower, by about 5-7%. 0.28.6 (2018-11-01) =================== Bugs fixed ---------- * Extensions compiled with MinGW-64 under Windows could misinterpret integer objects larger than 15 bit and return incorrect results. (Github issue :issue:`2670`) * Multiplied string literals lost their factor when they are part of another constant expression (e.g. 'x' * 10 + 'y' => 'xy'). 0.28.5 (2018-08-03) =================== Bugs fixed ---------- * The discouraged usage of GCC's attribute ``optimize("Os")`` was replaced by the similar attribute ``cold`` to reduce the code impact of the module init functions. (Github issue :issue:`2494`) * A reference leak in Py2.x was fixed when comparing str to unicode for equality. 0.28.4 (2018-07-08) =================== Bugs fixed ---------- * Reallowing ``tp_clear()`` in a subtype of an ``@no_gc_clear`` extension type generated an invalid C function call to the (non-existent) base type implementation. (Github issue :issue:`2309`) * Exception catching based on a non-literal (runtime) tuple could fail to match the exception. (Github issue :issue:`2425`) * Compile fix for CPython 3.7.0a2. (Github issue :issue:`2477`) 0.28.3 (2018-05-27) =================== Bugs fixed ---------- * Set iteration was broken in non-CPython since 0.28. * ``UnicodeEncodeError`` in Py2 when ``%s`` formatting is optimised for unicode strings. (Github issue :issue:`2276`) * Work around a crash bug in g++ 4.4.x by disabling the size reduction setting of the module init function in this version. (Github issue :issue:`2235`) * Crash when exceptions occur early during module initialisation. (Github issue :issue:`2199`) 0.28.2 (2018-04-13) =================== Features added -------------- * ``abs()`` is faster for Python long objects. * The C++11 methods ``front()`` and ``end()`` were added to the declaration of ``libcpp.string``. Patch by Alex Huszagh. (Github issue :issue:`2123`) * The C++11 methods ``reserve()`` and ``bucket_count()`` are declared for ``libcpp.unordered_map``. Patch by Valentin Valls. (Github issue :issue:`2168`) Bugs fixed ---------- * The copy of a read-only memoryview was considered read-only as well, whereas a common reason to copy a read-only view is to make it writable. The result of the copying is now a writable buffer by default. (Github issue :issue:`2134`) * The ``switch`` statement generation failed to apply recursively to the body of converted if-statements. * ``NULL`` was sometimes rejected as exception return value when the returned type is a fused pointer type. Patch by Callie LeFave. (Github issue :issue:`2177`) * Fixed compatibility with PyPy 5.11. Patch by Matti Picus. (Github issue :issue:`2165`) Other changes ------------- * The NumPy tutorial was rewritten to use memoryviews instead of the older buffer declaration syntax. Contributed by Gabriel de Marmiesse. (Github issue :issue:`2162`) 0.28.1 (2018-03-18) =================== Bugs fixed ---------- * ``PyFrozenSet_New()`` was accidentally used in PyPy where it is missing from the C-API. * Assignment between some C++ templated types were incorrectly rejected when the templates mix ``const`` with ``ctypedef``. (Github issue :issue:`2148`) * Undeclared C++ no-args constructors in subclasses could make the compilation fail if the base class constructor was declared without ``nogil``. (Github issue :issue:`2157`) * Bytes %-formatting inferred ``basestring`` (bytes or unicode) as result type in some cases where ``bytes`` would have been safe to infer. (Github issue :issue:`2153`) * ``None`` was accidentally disallowed as typed return value of ``dict.pop()``. (Github issue :issue:`2152`) 0.28 (2018-03-13) ================= Features added -------------- * Cdef classes can now multiply inherit from ordinary Python classes. (The primary base must still be a c class, possibly ``object``, and the other bases must *not* be cdef classes.) * Type inference is now supported for Pythran compiled NumPy expressions. Patch by Nils Braun. (Github issue :issue:`1954`) * The ``const`` modifier can be applied to memoryview declarations to allow read-only buffers as input. (Github issues :issue:`1605`, :issue:`1869`) * C code in the docstring of a ``cdef extern`` block is copied verbatimly into the generated file. Patch by Jeroen Demeyer. (Github issue :issue:`1915`) * When compiling with gcc, the module init function is now tuned for small code size instead of whatever compile flags were provided externally. Cython now also disables some code intensive optimisations in that function to further reduce the code size. (Github issue :issue:`2102`) * Decorating an async coroutine with ``@cython.iterable_coroutine`` changes its type at compile time to make it iterable. While this is not strictly in line with PEP-492, it improves the interoperability with old-style coroutines that use ``yield from`` instead of ``await``. * The IPython magic has preliminary support for JupyterLab. (Github issue :issue:`1775`) * The new TSS C-API in CPython 3.7 is supported and has been backported. Patch by Naotoshi Seo. (Github issue :issue:`1932`) * Cython knows the new ``Py_tss_t`` type defined in PEP-539 and automatically initialises variables declared with that type to ``Py_tss_NEEDS_INIT``, a value which cannot be used outside of static assignments. * The set methods ``.remove()`` and ``.discard()`` are optimised. Patch by Antoine Pitrou. (Github issue :issue:`2042`) * ``dict.pop()`` is optimised. Original patch by Antoine Pitrou. (Github issue :issue:`2047`) * Iteration over sets and frozensets is optimised. (Github issue :issue:`2048`) * Safe integer loops (< range(2^30)) are automatically optimised into C loops. * ``alist.extend([a,b,c])`` is optimised into sequential ``list.append()`` calls for short literal sequences. * Calls to builtin methods that are not specifically optimised into C-API calls now use a cache that avoids repeated lookups of the underlying C function. (Github issue :issue:`2054`) * Single argument function calls can avoid the argument tuple creation in some cases. * Some redundant extension type checks are avoided. * Formatting C enum values in f-strings is faster, as well as some other special cases. * String formatting with the '%' operator is optimised into f-strings in simple cases. * Subscripting (item access) is faster in some cases. * Some ``bytearray`` operations have been optimised similar to ``bytes``. * Some PEP-484/526 container type declarations are now considered for loop optimisations. * Indexing into memoryview slices with ``view[i][j]`` is now optimised into ``view[i, j]``. * Python compatible ``cython.*`` types can now be mixed with type declarations in Cython syntax. * Name lookups in the module and in classes are faster. * Python attribute lookups on extension types without instance dict are faster. * Some missing signals were added to ``libc/signal.pxd``. Patch by Jeroen Demeyer. (Github issue :issue:`1914`) * The warning about repeated extern declarations is now visible by default. (Github issue :issue:`1874`) * The exception handling of the function types used by CPython's type slot functions was corrected to match the de-facto standard behaviour, so that code that uses them directly benefits from automatic and correct exception propagation. Patch by Jeroen Demeyer. (Github issue :issue:`1980`) * Defining the macro ``CYTHON_NO_PYINIT_EXPORT`` will prevent the module init function from being exported as symbol, e.g. when linking modules statically in an embedding setup. Patch by AraHaan. (Github issue :issue:`1944`) Bugs fixed ---------- * If a module name is explicitly provided for an ``Extension()`` that is compiled via ``cythonize()``, it was previously ignored and replaced by the source file name. It can now be used to override the target module name, e.g. for compiling prefixed accelerator modules from Python files. (Github issue :issue:`2038`) * The arguments of the ``num_threads`` parameter of parallel sections were not sufficiently validated and could lead to invalid C code. (Github issue :issue:`1957`) * Catching exceptions with a non-trivial exception pattern could call into CPython with a live exception set. This triggered incorrect behaviour and crashes, especially in CPython 3.7. * The signature of the special ``__richcmp__()`` method was corrected to recognise the type of the first argument as ``self``. It was previously treated as plain object, but CPython actually guarantees that it always has the correct type. Note: this can change the semantics of user code that previously relied on ``self`` being untyped. * Some Python 3 exceptions were not recognised as builtins when running Cython under Python 2. * Some async helper functions were not defined in the generated C code when compiling simple async code. (Github issue :issue:`2075`) * Line tracing did not include generators and coroutines. (Github issue :issue:`1949`) * C++ declarations for ``unordered_map`` were corrected. Patch by Michael Schatzow. (Github issue :issue:`1484`) * Iterator declarations in C++ ``deque`` and ``vector`` were corrected. Patch by Alex Huszagh. (Github issue :issue:`1870`) * The const modifiers in the C++ ``string`` declarations were corrected, together with the coercion behaviour of string literals into C++ strings. (Github issue :issue:`2132`) * Some declaration types in ``libc.limits`` were corrected. Patch by Jeroen Demeyer. (Github issue :issue:`2016`) * ``@cython.final`` was not accepted on Python classes with an ``@cython.cclass`` decorator. (Github issue :issue:`2040`) * Cython no longer creates useless and incorrect ``PyInstanceMethod`` wrappers for methods in Python 3. Patch by Jeroen Demeyer. (Github issue :issue:`2105`) * The builtin ``bytearray`` type could not be used as base type of cdef classes. (Github issue :issue:`2106`) Other changes ------------- 0.27.3 (2017-11-03) =================== Bugs fixed ---------- * String forward references to extension types like ``@cython.locals(x="ExtType")`` failed to find the named type. (Github issue :issue:`1962`) * NumPy slicing generated incorrect results when compiled with Pythran. Original patch by Serge Guelton (Github issue :issue:`1946`). * Fix "undefined reference" linker error for generators on Windows in Py3.3-3.5. (Github issue :issue:`1968`) * Adapt to recent C-API change of ``PyThreadState`` in CPython 3.7. * Fix signature of ``PyWeakref_GetObject()`` API declaration. Patch by Jeroen Demeyer (Github issue :issue:`1975`). 0.27.2 (2017-10-22) =================== Bugs fixed ---------- * Comprehensions could incorrectly be optimised away when they appeared in boolean test contexts. (Github issue :issue:`1920`) * The special methods ``__eq__``, ``__lt__`` etc. in extension types did not type their first argument as the type of the class but ``object``. (Github issue :issue:`1935`) * Crash on first lookup of "cline_in_traceback" option during exception handling. (Github issue :issue:`1907`) * Some nested module level comprehensions failed to compile. (Github issue :issue:`1906`) * Compiler crash on some complex type declarations in pure mode. (Github issue :issue:`1908`) * ``std::unordered_map.erase()`` was declared with an incorrect ``void`` return type in ``libcpp.unordered_map``. (Github issue :issue:`1484`) * Invalid use of C++ ``fallthrough`` attribute before C++11 and similar issue in clang. (Github issue :issue:`1930`) * Compiler crash on misnamed properties. (Github issue :issue:`1905`) 0.27.1 (2017-10-01) =================== Features added -------------- * The Jupyter magic has a new debug option ``--verbose`` that shows details about the distutils invocation. Patch by Boris Filippov (Github issue :issue:`1881`). Bugs fixed ---------- * Py3 list comprehensions in class bodies resulted in invalid C code. (Github issue :issue:`1889`) * Modules built for later CPython 3.5.x versions failed to import in 3.5.0/3.5.1. (Github issue :issue:`1880`) * Deallocating fused types functions and methods kept their GC tracking enabled, which could potentially lead to recursive deallocation attempts. * Crash when compiling in C++ mode with old setuptools versions. (Github issue :issue:`1879`) * C++ object arguments for the constructor of Cython implemented C++ are now passed by reference and not by value to allow for non-copyable arguments, such as ``unique_ptr``. * API-exported C++ classes with Python object members failed to compile. (Github issue :issue:`1866`) * Some issues with the new relaxed exception value handling were resolved. * Python classes as annotation types could prevent compilation. (Github issue :issue:`1887`) * Cython annotation types in Python files could lead to import failures with a "cython undefined" error. Recognised types are now turned into strings. * Coverage analysis could fail to report on extension modules on some platforms. * Annotations could be parsed (and rejected) as types even with ``annotation_typing=False``. Other changes ------------- * PEP 489 support has been disabled by default to counter incompatibilities with import setups that try to reload or reinitialise modules. 0.27 (2017-09-23) ================= Features added -------------- * Extension module initialisation follows `PEP 489 `_ in CPython 3.5+, which resolves several differences with regard to normal Python modules. This makes the global names ``__file__`` and ``__path__`` correctly available to module level code and improves the support for module-level relative imports. (Github issues :issue:`1715`, :issue:`1753`, :issue:`1035`) * Asynchronous generators (`PEP 525 `_) and asynchronous comprehensions (`PEP 530 `_) have been implemented. Note that async generators require finalisation support in order to allow for asynchronous operations during cleanup, which is only available in CPython 3.6+. All other functionality has been backported as usual. * Variable annotations are now parsed according to `PEP 526 `_. Cython types (e.g. ``cython.int``) are evaluated as C type declarations and everything else as Python types. This can be disabled with the directive ``annotation_typing=False``. Note that most complex PEP-484 style annotations are currently ignored. This will change in future releases. (Github issue :issue:`1850`) * Extension types (also in pure Python mode) can implement the normal special methods ``__eq__``, ``__lt__`` etc. for comparisons instead of the low-level ``__richcmp__`` method. (Github issue :issue:`690`) * New decorator ``@cython.exceptval(x=None, check=False)`` that makes the signature declarations ``except x``, ``except? x`` and ``except *`` available to pure Python code. Original patch by Antonio Cuni. (Github issue :issue:`1653`) * Signature annotations are now included in the signature docstring generated by the ``embedsignature`` directive. Patch by Lisandro Dalcin (Github issue :issue:`1781`). * The gdb support for Python code (``libpython.py``) was updated to the latest version in CPython 3.7 (git rev 5fe59f8). * The compiler tries to find a usable exception return value for cdef functions with ``except *`` if the returned type allows it. Note that this feature is subject to safety limitations, so it is still better to provide an explicit declaration. * C functions can be assigned to function pointers with a compatible exception declaration, not only with exact matches. A side-effect is that certain compatible signature overrides are now allowed and some more mismatches of exception signatures are now detected and rejected as errors that were not detected before. * The IPython/Jupyter magic integration has a new option ``%%cython --pgo`` for profile guided optimisation. It compiles the cell with PGO settings for the C compiler, executes it to generate a runtime profile, and then compiles it again using that profile for C compiler optimisation. Currently only tested with gcc. * ``len(memoryview)`` can be used in nogil sections to get the size of the first dimension of a memory view (``shape[0]``). (Github issue :issue:`1733`) * C++ classes can now contain (properly refcounted) Python objects. * NumPy dtype subarrays are now accessible through the C-API. Patch by Gerald Dalley (Github issue :issue:`245`). * Resolves several issues with PyPy and uses faster async slots in PyPy3. Patch by Ronan Lamy (Github issues :issue:`1871`, :issue:`1878`). Bugs fixed ---------- * Extension types that were cimported from other Cython modules could disagree about the order of fused cdef methods in their call table. This could lead to wrong methods being called and potentially also crashes. The fix required changes to the ordering of fused methods in the call table, which may break existing compiled modules that call fused cdef methods across module boundaries, if these methods were implemented in a different order than they were declared in the corresponding .pxd file. (Github issue :issue:`1873`) * The exception state handling in generators and coroutines could lead to exceptions in the caller being lost if an exception was raised and handled inside of the coroutine when yielding. (Github issue :issue:`1731`) * Loops over ``range(enum)`` were not converted into C for-loops. Note that it is still recommended to use an explicit cast to a C integer type in this case. * Error positions of names (e.g. variables) were incorrectly reported after the name and not at the beginning of the name. * Compile time ``DEF`` assignments were evaluated even when they occur inside of falsy ``IF`` blocks. (Github issue :issue:`1796`) * Disabling the line tracing from a trace function could fail. Original patch by Dmitry Trofimov. (Github issue :issue:`1769`) * Several issues with the Pythran integration were resolved. * abs(signed int) now returns a signed rather than unsigned int. (Github issue :issue:`1837`) * Reading ``frame.f_locals`` of a Cython function (e.g. from a debugger or profiler could modify the module globals. (Github issue :issue:`1836`) * Buffer type mismatches in the NumPy buffer support could leak a reference to the buffer owner. * Using the "is_f_contig" and "is_c_contig" memoryview methods together could leave one of them undeclared. (Github issue :issue:`1872`) * Compilation failed if the for-in-range loop target was not a variable but a more complex expression, e.g. an item assignment. (Github issue :issue:`1831`) * Compile time evaluations of (partially) constant f-strings could show incorrect results. * Escape sequences in raw f-strings (``fr'...'``) were resolved instead of passing them through as expected. * Some ref-counting issues in buffer error handling have been resolved. Other changes ------------- * Type declarations in signature annotations are now parsed according to `PEP 484 `_ typing. Only Cython types (e.g. ``cython.int``) and Python builtin types are currently considered as type declarations. Everything else is ignored, but this will change in a future Cython release. (Github issue :issue:`1672`) * The directive ``annotation_typing`` is now ``True`` by default, which enables parsing type declarations from annotations. * This release no longer supports Python 3.2. 0.26.1 (2017-08-29) =================== Features added -------------- Bugs fixed ---------- * ``cython.view.array`` was missing ``.__len__()``. * Extension types with a ``.pxd`` override for their ``__releasebuffer__`` slot (e.g. as provided by Cython for the Python ``array.array`` type) could leak a reference to the buffer owner on release, thus not freeing the memory. (Github issue :issue:`1638`) * Auto-decoding failed in 0.26 for strings inside of C++ containers. (Github issue :issue:`1790`) * Compile error when inheriting from C++ container types. (Github issue :issue:`1788`) * Invalid C code in generators (declaration after code). (Github issue :issue:`1801`) * Arithmetic operations on ``const`` integer variables could generate invalid code. (Github issue :issue:`1798`) * Local variables with names of special Python methods failed to compile inside of closures. (Github issue :issue:`1797`) * Problem with indirect Emacs buffers in cython-mode. Patch by Martin Albrecht (Github issue :issue:`1743`). * Extension types named ``result`` or ``PickleError`` generated invalid unpickling code. Patch by Jason Madden (Github issue :issue:`1786`). * Bazel integration failed to compile ``.py`` files. Patch by Guro Bokum (Github issue :issue:`1784`). * Some include directories and dependencies were referenced with their absolute paths in the generated files despite lying within the project directory. * Failure to compile in Py3.7 due to a modified signature of ``_PyCFunctionFast()`` 0.26 (2017-07-19) ================= Features added -------------- * Pythran can be used as a backend for evaluating NumPy array expressions. Patch by Adrien Guinet (Github issue :issue:`1607`). * cdef classes now support pickling by default when possible. This can be disabled with the ``auto_pickle`` directive. * Speed up comparisons of strings if their hash value is available. Patch by Claudio Freire (Github issue :issue:`1571`). * Support pyximport from zip files. Patch by Sergei Lebedev (Github issue :issue:`1485`). * IPython magic now respects the ``__all__`` variable and ignores names with leading-underscore (like ``import *`` does). Patch by Syrtis Major (Github issue :issue:`1625`). * ``abs()`` is optimised for C complex numbers. Patch by David Woods (Github issue :issue:`1648`). * The display of C lines in Cython tracebacks can now be enabled at runtime via ``import cython_runtime; cython_runtime.cline_in_traceback=True``. The default has been changed to False. * The overhead of calling fused types generic functions was reduced. * "cdef extern" include files are now also searched relative to the current file. Patch by Jeroen Demeyer (Github issue :issue:`1654`). * Optional optimization for re-acquiring the GIL, controlled by the `fast_gil` directive. Bugs fixed ---------- * Item lookup/assignment with a unicode character as index that is typed (explicitly or implicitly) as ``Py_UCS4`` or ``Py_UNICODE`` used the integer value instead of the Unicode string value. Code that relied on the previous behaviour now triggers a warning that can be disabled by applying an explicit cast. (Github issue :issue:`1602`) * f-string processing was adapted to changes in PEP 498 and CPython 3.6. * Invalid C code when decoding from UTF-16(LE/BE) byte strings. (Github issue :issue:`1696`) * Unicode escapes in 'ur' raw-unicode strings were not resolved in Py2 code. Original patch by Aaron Gallagher (Github issue :issue:`1594`). * File paths of code objects are now relative. Original patch by Jelmer Vernooij (Github issue :issue:`1565`). * Decorators of cdef class methods could be executed twice. Patch by Jeroen Demeyer (Github issue :issue:`1724`). * Dict iteration using the Py2 ``iter*`` methods failed in PyPy3. Patch by Armin Rigo (Github issue :issue:`1631`). * Several warnings in the generated code are now suppressed. Other changes ------------- * The ``unraisable_tracebacks`` option now defaults to ``True``. * Coercion of C++ containers to Python is no longer automatic on attribute access (Github issue :issue:`1521`). * Access to Python attributes of cimported modules without the corresponding import is now a compile-time (rather than runtime) error. * Do not use special dll linkage for "cdef public" functions. Patch by Jeroen Demeyer (Github issue :issue:`1687`). * cdef/cpdef methods must match their declarations. See Github issue :issue:`1732`. This is now a warning and will be an error in future releases. 0.25.2 (2016-12-08) =================== Bugs fixed ---------- * Fixes several issues with C++ template deduction. * Fixes a issue with bound method type inference (Github issue :issue:`551`). * Fixes a bug with cascaded tuple assignment (Github issue :issue:`1523`). * Fixed or silenced many Clang warnings. * Fixes bug with powers of pure real complex numbers (Github issue :issue:`1538`). 0.25.1 (2016-10-26) =================== Bugs fixed ---------- * Fixes a bug with ``isinstance(o, Exception)`` (Github issue :issue:`1496`). * Fixes bug with ``cython.view.array`` missing utility code in some cases (Github issue :issue:`1502`). Other changes ------------- * The distutils extension ``Cython.Distutils.build_ext`` has been reverted, temporarily, to be ``old_build_ext`` to give projects time to migrate. The new build_ext is available as ``new_build_ext``. 0.25 (2016-10-25) ================= Features added -------------- * def/cpdef methods of cdef classes benefit from Cython's internal function implementation, which enables introspection and line profiling for them. Implementation sponsored by Turbostream (www.turbostream-cfd.com). * Calls to Python functions are faster, following the recent "FastCall" optimisations that Victor Stinner implemented for CPython 3.6. See https://bugs.python.org/issue27128 and related issues. * The new METH_FASTCALL calling convention for PyCFunctions is supported in CPython 3.6. See https://bugs.python.org/issue27810 * Initial support for using Cython modules in Pyston. Patch by Boxiang Sun. * Dynamic Python attributes are allowed on cdef classes if an attribute ``cdef dict __dict__`` is declared in the class. Patch by empyrical. * Cython implemented C++ classes can make direct calls to base class methods. Patch by empyrical. * C++ classes can now have typedef members. STL containers updated with value_type. * New directive ``cython.no_gc`` to fully disable GC for a cdef class. Patch by Claudio Freire. * Buffer variables are no longer excluded from ``locals()``. Patch by David Woods. * Building f-strings is faster, especially when formatting C integers. * for-loop iteration over "std::string". * ``libc/math.pxd`` provides ``e`` and ``pi`` as alias constants to simplify usage as a drop-in replacement for Python's math module. * Speed up cython.inline(). * Binary lshift operations with small constant Python integers are faster. * Some integer operations on Python long objects are faster in Python 2.7. * Support for the C++ ``typeid`` operator. * Support for bazel using a the pyx_library rule in //Tools:rules.bzl. Significant Bugs fixed ---------------------- * Division of complex numbers avoids overflow by using Smith's method. * Some function signatures in ``libc.math`` and ``numpy.pxd`` were incorrect. Patch by Michael Seifert. Other changes ------------- * The "%%cython" IPython/jupyter magic now defaults to the language level of the current jupyter kernel. The language level can be set explicitly with "%%cython -2" or "%%cython -3". * The distutils extension ``Cython.Distutils.build_ext`` has now been updated to use cythonize which properly handles dependencies. The old extension can still be found in ``Cython.Distutils.old_build_ext`` and is now deprecated. * ``directive_defaults`` is no longer available in ``Cython.Compiler.Options``, use ``get_directive_defaults()`` instead. 0.24.1 (2016-07-15) =================== Bugs fixed ---------- * IPython cell magic was lacking a good way to enable Python 3 code semantics. It can now be used as "%%cython -3". * Follow a recent change in `PEP 492 `_ and CPython 3.5.2 that now requires the ``__aiter__()`` method of asynchronous iterators to be a simple ``def`` method instead of an ``async def`` method. * Coroutines and generators were lacking the ``__module__`` special attribute. * C++ ``std::complex`` values failed to auto-convert from and to Python complex objects. * Namespaced C++ types could not be used as memory view types due to lack of name mangling. Patch by Ivan Smirnov. * Assignments between identical C++ types that were declared with differently typedefed template types could fail. * Rebuilds could fail to evaluate dependency timestamps in C++ mode. Patch by Ian Henriksen. * Macros defined in the ``distutils`` compiler option do not require values anymore. Patch by Ian Henriksen. * Minor fixes for MSVC, Cygwin and PyPy. 0.24 (2016-04-04) ================= Features added -------------- * `PEP 498 `_: Literal String Formatting (f-strings). Original patch by Jelle Zijlstra. * `PEP 515 `_: Underscores as visual separators in number literals. * Parser was adapted to some minor syntax changes in Py3.6, e.g. https://bugs.python.org/issue9232 * The embedded C code comments that show the original source code can be discarded with the new directive ``emit_code_comments=False``. * Cpdef enums are now first-class iterable, callable types in Python. * Ctuples can now be declared in pure Python code. * Posix declarations for DLL loading and stdio extensions were added. Patch by Lars Buitinck. * The Py2-only builtins ``unicode()``, ``xrange()``, ``reduce()`` and ``long`` are now also available in compile time ``DEF`` expressions when compiling with Py3. * Exception type tests have slightly lower overhead. This fixes ticket 868. * @property syntax fully supported in cdef classes, old syntax deprecated. * C++ classes can now be declared with default template parameters. Bugs fixed ---------- * C++ exceptions raised by overloaded C++ operators were not always handled. Patch by Ian Henriksen. * C string literals were previously always stored as non-const global variables in the module. They are now stored as global constants when possible, and otherwise as non-const C string literals in the generated code that uses them. This improves compatibility with strict C compiler options and prevents non-const strings literals with the same content from being incorrectly merged. * Compile time evaluated ``str`` expressions (``DEF``) now behave in a more useful way by turning into Unicode strings when compiling under Python 3. This allows using them as intermediate values in expressions. Previously, they always evaluated to bytes objects. * ``isinf()`` declarations in ``libc/math.pxd`` and ``numpy/math.pxd`` now reflect the actual tristate ``int`` return value instead of using ``bint``. * Literal assignments to ctuples avoid Python tuple round-trips in some more corner cases. * Iteration over ``dict(...).items()`` failed to get optimised when dict arguments included keyword arguments. * cProfile now correctly profiles cpdef functions and methods. 0.23.5 (2016-03-26) =================== * Compile errors and warnings in integer type conversion code. This fixes ticket 877. Patches by Christian Neukirchen, Nikolaus Rath, Ian Henriksen. * Reference leak when ``*args`` argument was reassigned in closures. * Truth-testing Unicode strings could waste time and memory in Py3.3+. * Return values of async functions could be ignored and replaced by ``None``. * Compiler crash in CPython 3.6. * Fix prange() to behave identically to range(). The end condition was miscalculated when the range was not exactly divisible by the step. * Optimised ``all(genexpr)``/``any(genexpr)`` calls could warn about unused code. This fixes ticket 876. 0.23.4 (2015-10-10) =================== Bugs fixed ---------- * Memory leak when calling Python functions in PyPy. * Compilation problem with MSVC in C99-ish mode. * Warning about unused values in a helper macro. 0.23.3 (2015-09-29) =================== Bugs fixed ---------- * Invalid C code for some builtin methods. This fixes ticket 856 again. * Incorrect C code in helper functions for PyLong conversion and string decoding. This fixes ticket 863, ticket 864 and ticket 865. Original patch by Nikolaus Rath. * Large folded or inserted integer constants could use too small C integer types and thus trigger a value wrap-around. Other changes ------------- * The coroutine and generator types of Cython now also register directly with the ``Coroutine`` and ``Generator`` ABCs in the ``backports_abc`` module if it can be imported. This fixes ticket 870. 0.23.2 (2015-09-11) =================== Bugs fixed ---------- * Compiler crash when analysing some optimised expressions. * Coverage plugin was adapted to coverage.py 4.0 beta 2. * C++ destructor calls could fail when '&' operator is overwritten. * Incorrect C literal generation for large integers in compile-time evaluated DEF expressions and constant folded expressions. * Byte string constants could end up as Unicode strings when originating from compile-time evaluated DEF expressions. * Invalid C code when caching known builtin methods. This fixes ticket 860. * ``ino_t`` in ``posix.types`` was not declared as ``unsigned``. * Declarations in ``libcpp/memory.pxd`` were missing ``operator!()``. Patch by Leo Razoumov. * Static cdef methods can now be declared in .pxd files. 0.23.1 (2015-08-22) =================== Bugs fixed ---------- * Invalid C code for generators. This fixes ticket 858. * Invalid C code for some builtin methods. This fixes ticket 856. * Invalid C code for unused local buffer variables. This fixes ticket 154. * Test failures on 32bit systems. This fixes ticket 857. * Code that uses ``from xyz import *`` and global C struct/union/array variables could fail to compile due to missing helper functions. This fixes ticket 851. * Misnamed PEP 492 coroutine property ``cr_yieldfrom`` renamed to ``cr_await`` to match CPython. * Missing deallocation code for C++ object attributes in certain extension class hierarchies. * Crash when async coroutine was not awaited. * Compiler crash on ``yield`` in signature annotations and default argument values. Both are forbidden now. * Compiler crash on certain constructs in ``finally`` clauses. * Cython failed to build when CPython's pgen is installed. 0.23 (2015-08-08) ================= Features added -------------- * `PEP 492 `_ (async/await) was implemented. * `PEP 448 `_ (Additional Unpacking Generalizations) was implemented. * Support for coverage.py 4.0+ can be enabled by adding the plugin "Cython.Coverage" to the ".coveragerc" config file. * Annotated HTML source pages can integrate (XML) coverage reports. * Tracing is supported in ``nogil`` functions/sections and module init code. * When generators are used in a Cython module and the module imports the modules "inspect" and/or "asyncio", Cython enables interoperability by patching these modules during the import to recognise Cython's internal generator and coroutine types. This can be disabled by C compiling the module with "-D CYTHON_PATCH_ASYNCIO=0" or "-D CYTHON_PATCH_INSPECT=0" * When generators or coroutines are used in a Cython module, their types are registered with the ``Generator`` and ``Coroutine`` ABCs in the ``collections`` or ``collections.abc`` stdlib module at import time to enable interoperability with code that needs to detect and process Python generators/coroutines. These ABCs were added in CPython 3.5 and are available for older Python versions through the ``backports_abc`` module on PyPI. See https://bugs.python.org/issue24018 * Adding/subtracting/dividing/modulus and equality comparisons with constant Python floats and small integers are faster. * Binary and/or/xor/rshift operations with small constant Python integers are faster. * When called on generator expressions, the builtins ``all()``, ``any()``, ``dict()``, ``list()``, ``set()``, ``sorted()`` and ``unicode.join()`` avoid the generator iteration overhead by inlining a part of their functionality into the for-loop. * Keyword argument dicts are no longer copied on function entry when they are not being used or only passed through to other function calls (e.g. in wrapper functions). * The ``PyTypeObject`` declaration in ``cpython.object`` was extended. * The builtin ``type`` type is now declared as PyTypeObject in source, allowing for extern functions taking type parameters to have the correct C signatures. Note that this might break code that uses ``type`` just for passing around Python types in typed variables. Removing the type declaration provides a backwards compatible fix. * ``wraparound()`` and ``boundscheck()`` are available as no-ops in pure Python mode. * Const iterators were added to the provided C++ STL declarations. * Smart pointers were added to the provided C++ STL declarations. Patch by Daniel Filonik. * ``NULL`` is allowed as default argument when embedding signatures. This fixes ticket 843. * When compiling with ``--embed``, the internal module name is changed to ``__main__`` to allow arbitrary program names, including those that would be invalid for modules. Note that this prevents reuse of the generated C code as an importable module. * External C++ classes that overload the assignment operator can be used. Patch by Ian Henriksen. * Support operator bool() for C++ classes so they can be used in if statements. Bugs fixed ---------- * Calling "yield from" from Python on a Cython generator that returned a value triggered a crash in CPython. This is now being worked around. See https://bugs.python.org/issue23996 * Language level 3 did not enable true division (a.k.a. float division) for integer operands. * Functions with fused argument types that included a generic 'object' fallback could end up using that fallback also for other explicitly listed object types. * Relative cimports could accidentally fall back to trying an absolute cimport on failure. * The result of calling a C struct constructor no longer requires an intermediate assignment when coercing to a Python dict. * C++ exception declarations with mapping functions could fail to compile when pre-declared in .pxd files. * ``cpdef void`` methods are now permitted. * ``abs(cint)`` could fail to compile in MSVC and used sub-optimal code in C++. Patch by David Vierra, original patch by Michael Enßlin. * Buffer index calculations using index variables with small C integer types could overflow for large buffer sizes. Original patch by David Vierra. * C unions use a saner way to coerce from and to Python dicts. * When compiling a module ``foo.pyx``, the directories in ``sys.path`` are no longer searched when looking for ``foo.pxd``. Patch by Jeroen Demeyer. * Memory leaks in the embedding main function were fixed. Original patch by Michael Enßlin. * Some complex Python expressions could fail to compile inside of finally clauses. * Unprefixed 'str' literals were not supported as C varargs arguments. * Fixed type errors in conversion enum types to/from Python. Note that this imposes stricter correctness requirements on enum declarations. Other changes ------------- * Changed mangling scheme in header files generated by ``cdef api`` declarations. * Installation under CPython 3.3+ no longer requires a pass of the 2to3 tool. This also makes it possible to run Cython in Python 3.3+ from a source checkout without installing it first. Patch by Petr Viktorin. * ``jedi-typer.py`` (in ``Tools/``) was extended and renamed to ``jedityper.py`` (to make it importable) and now works with and requires Jedi 0.9. Patch by Tzer-jen Wei. 0.22.1 (2015-06-20) =================== Bugs fixed ---------- * Crash when returning values on generator termination. * In some cases, exceptions raised during internal isinstance() checks were not propagated. * Runtime reported file paths of source files (e.g for profiling and tracing) are now relative to the build root directory instead of the main source file. * Tracing exception handling code could enter the trace function with an active exception set. * The internal generator function type was not shared across modules. * Comparisons of (inferred) ctuples failed to compile. * Closures inside of cdef functions returning ``void`` failed to compile. * Using ``const`` C++ references in intermediate parts of longer expressions could fail to compile. * C++ exception declarations with mapping functions could fail to compile when pre-declared in .pxd files. * C++ compilation could fail with an ambiguity error in recent MacOS-X Xcode versions. * C compilation could fail in pypy3. * Fixed a memory leak in the compiler when compiling multiple modules. * When compiling multiple modules, external library dependencies could leak into later compiler runs. Fix by Jeroen Demeyer. This fixes ticket 845. 0.22 (2015-02-11) ================= Features added -------------- * C functions can coerce to Python functions, which allows passing them around as callable objects. * C arrays can be assigned by value and auto-coerce from Python iterables and to Python lists (and tuples). * Extern C functions can now be declared as cpdef to export them to the module's Python namespace. Extern C functions in pxd files export their values to their own module, iff it exists. * Anonymous C tuple types can be declared as (ctype1, ctype2, ...). * `PEP 479 `_: turn accidental StopIteration exceptions that exit generators into a RuntimeError, activated with future import "generator_stop". * Looping over ``reversed(range())`` is optimised in the same way as ``range()``. Patch by Favian Contreras. Bugs fixed ---------- * Mismatching 'except' declarations on signatures in .pxd and .pyx files failed to produce a compile error. * Failure to find any files for the path pattern(s) passed into ``cythonize()`` is now an error to more easily detect accidental typos. * The ``logaddexp`` family of functions in ``numpy.math`` now has correct declarations. * In Py2.6/7 and Py3.2, simple Cython memory views could accidentally be interpreted as non-contiguous by CPython, which could trigger a CPython bug when copying data from them, thus leading to data corruption. See CPython issues 12834 and 23349. Other changes ------------- * Preliminary support for defining the Cython language with a formal grammar. To try parsing your files against this grammar, use the --formal_grammar directive. Experimental. * ``_`` is no longer considered a cacheable builtin as it could interfere with gettext. * Cythonize-computed metadata now cached in the generated C files. * Several corrections and extensions in numpy, cpython, and libcpp pxd files. 0.21.2 (2014-12-27) =================== Bugs fixed ---------- * Crash when assigning a C value to both a Python and C target at the same time. * Automatic coercion from C++ strings to ``str`` generated incomplete code that failed to compile. * Declaring a constructor in a C++ child class erroneously required a default constructor declaration in the super class. * ``resize_smart()`` in ``cpython.array`` was broken. * Functions in ``libcpp.cast`` are now declared as ``nogil``. * Some missing C-API declarations were added. * Py3 main code in embedding program code was lacking casts. * Exception related to distutils "Distribution" class type in pyximport under latest CPython 2.7 and 3.4 releases when setuptools is being imported later. 0.21.1 (2014-10-18) =================== Features added -------------- * New ``cythonize`` option ``-a`` to generate the annotated HTML source view. * Missing C-API declarations in ``cpython.unicode`` were added. * Passing ``language='c++'`` into cythonize() globally enables C++ mode for all modules that were not passed as Extension objects (i.e. only source files and file patterns). * ``Py_hash_t`` is a known type (used in CPython for hash values). * ``PySlice_*()`` C-API functions are available from the ``cpython.slice`` module. * Allow arrays of C++ classes. Bugs fixed ---------- * Reference leak for non-simple Python expressions in boolean and/or expressions. * To fix a name collision and to reflect availability on host platforms, standard C declarations [ clock(), time(), struct tm and tm* functions ] were moved from posix/time.pxd to a new libc/time.pxd. Patch by Charles Blake. * Rerunning unmodified modules in IPython's cython support failed. Patch by Matthias Bussonier. * Casting C++ ``std::string`` to Python byte strings failed when auto-decoding was enabled. * Fatal exceptions in global module init code could lead to crashes if the already created module was used later on (e.g. through a stale reference in sys.modules or elsewhere). * ``cythonize.py`` script was not installed on MS-Windows. Other changes ------------- * Compilation no longer fails hard when unknown compilation options are passed. Instead, it raises a warning and ignores them (as it did silently before 0.21). This will be changed back to an error in a future release. 0.21 (2014-09-10) ================= Features added -------------- * C (cdef) functions allow inner Python functions. * Enums can now be declared as cpdef to export their values to the module's Python namespace. Cpdef enums in pxd files export their values to their own module, iff it exists. * Allow @staticmethod decorator to declare static cdef methods. This is especially useful for declaring "constructors" for cdef classes that can take non-Python arguments. * Taking a ``char*`` from a temporary Python string object is safer in more cases and can be done inside of non-trivial expressions, including arguments of a function call. A compile time error is raised only when such a pointer is assigned to a variable and would thus exceed the lifetime of the string itself. * Generators have new properties ``__name__`` and ``__qualname__`` that provide the plain/qualified name of the generator function (following CPython 3.5). See https://bugs.python.org/issue21205 * The ``inline`` function modifier is available as a decorator ``@cython.inline`` in pure mode. * When cygdb is run in a virtualenv, it enables the same virtualenv inside of the debugger. Patch by Marc Abramowitz. * PEP 465: dedicated infix operator for matrix multiplication (A @ B). * HTML output of annotated code uses Pygments for code highlighting and generally received a major overhaul by Matthias Bussonier. * IPython magic support is now available directly from Cython with the command "%load_ext cython". Cython code can directly be executed in a cell when marked with "%%cython". Code analysis is available with "%%cython -a". Patch by Martín Gaitán. * Simple support for declaring Python object types in Python signature annotations. Currently requires setting the compiler directive ``annotation_typing=True``. * New directive ``use_switch`` (defaults to True) to optionally disable the optimization of chained if statement to C switch statements. * Defines dynamic_cast et al. in ``libcpp.cast`` and C++ heap data structure operations in ``libcpp.algorithm``. * Shipped header declarations in ``posix.*`` were extended to cover more of the POSIX API. Patches by Lars Buitinck and Mark Peek. Optimizations ------------- * Simple calls to C implemented Python functions/methods are faster. This also speeds up many operations on builtins that Cython cannot otherwise optimise. * The "and"/"or" operators try to avoid unnecessary coercions of their arguments. They now evaluate the truth value of each argument independently and only coerce the final result of the whole expression to the target type (e.g. the type on the left side of an assignment). This also avoids reference counting overhead for Python values during evaluation and generally improves the code flow in the generated C code. * The Python expression "2 ** N" is optimised into bit shifting. See https://bugs.python.org/issue21420 * Cascaded assignments (a = b = ...) try to minimise the number of type coercions. * Calls to ``slice()`` are translated to a straight C-API call. Bugs fixed ---------- * Crash when assigning memory views from ternary conditional expressions. * Nested C++ templates could lead to unseparated ">>" characters being generated into the C++ declarations, which older C++ compilers could not parse. * Sending SIGINT (Ctrl-C) during parallel cythonize() builds could hang the child processes. * No longer ignore local setup.cfg files for distutils in pyximport. Patch by Martin Teichmann. * Taking a ``char*`` from an indexed Python string generated unsafe reference counting code. * Set literals now create all of their items before trying to add them to the set, following the behaviour in CPython. This makes a difference in the rare case that the item creation has side effects and some items are not hashable (or if hashing them has side effects, too). * Cython no longer generates the cross product of C functions for code that uses memory views of fused types in function signatures (e.g. ``cdef func(floating[:] a, floating[:] b)``). This is considered the expected behaviour by most users and was previously inconsistent with other structured types like C arrays. Code that really wants all type combinations can create the same fused memoryview type under different names and use those in the signature to make it clear which types are independent. * Names that were unknown at compile time were looked up as builtins at runtime but not as global module names. Trying both lookups helps with globals() manipulation. * Fixed stl container conversion for typedef element types. * ``obj.pop(x)`` truncated large C integer values of x to ``Py_ssize_t``. * ``__init__.pyc`` is recognised as marking a package directory (in addition to .py, .pyx and .pxd). * Syntax highlighting in ``cython-mode.el`` for Emacs no longer incorrectly highlights keywords found as part of longer names. * Correctly handle ``from cython.submodule cimport name``. * Fix infinite recursion when using super with cpdef methods. * No-args ``dir()`` was not guaranteed to return a sorted list. Other changes ------------- * The header line in the generated C files no longer contains the timestamp but only the Cython version that wrote it. This was changed to make builds more reproducible. * Removed support for CPython 2.4, 2.5 and 3.1. * The licensing implications on the generated code were clarified to avoid legal constraints for users. 0.20.2 (2014-06-16) =================== Features added -------------- * Some optimisations for set/frozenset instantiation. * Support for C++ unordered_set and unordered_map. Bugs fixed ---------- * Access to attributes of optimised builtin methods (e.g. ``[].append.__name__``) could fail to compile. * Memory leak when extension subtypes add a memory view as attribute to those of the parent type without having Python object attributes or a user provided dealloc method. * Compiler crash on readonly properties in "binding" mode. * Auto-encoding with ``c_string_encoding=ascii`` failed in Py3.3. * Crash when subtyping freelist enabled Cython extension types with Python classes that use ``__slots__``. * Freelist usage is restricted to CPython to avoid problems with other Python implementations. * Memory leak in memory views when copying overlapping, contiguous slices. * Format checking when requesting non-contiguous buffers from ``cython.array`` objects was accidentally omitted in Py3. * C++ destructor calls in extension types could fail to compile in clang. * Buffer format validation failed for sequences of strings in structs. * Docstrings on extension type attributes in .pxd files were rejected. 0.20.1 (2014-02-11) =================== Bugs fixed ---------- * Build error under recent MacOS-X versions where ``isspace()`` could not be resolved by clang. * List/Tuple literals multiplied by more than one factor were only multiplied by the last factor instead of all. * Lookups of special methods (specifically for context managers) could fail in Python <= 2.6/3.1. * Local variables were erroneously appended to the signature introspection of Cython implemented functions with keyword-only arguments under Python 3. * In-place assignments to variables with inferred Python builtin/extension types could fail with type errors if the result value type was incompatible with the type of the previous value. * The C code generation order of cdef classes, closures, helper code, etc. was not deterministic, thus leading to high code churn. * Type inference could fail to deduce C enum types. * Type inference could deduce unsafe or inefficient types from integer assignments within a mix of inferred Python variables and integer variables. 0.20 (2014-01-18) ================= Features added -------------- * Support for CPython 3.4. * Support for calling C++ template functions. * ``yield`` is supported in ``finally`` clauses. * The C code generated for finally blocks is duplicated for each exit case to allow for better optimisations by the C compiler. * Cython tries to undo the Python optimisationism of assigning a bound method to a local variable when it can generate better code for the direct call. * Constant Python float values are cached. * String equality comparisons can use faster type specific code in more cases than before. * String/Unicode formatting using the '%' operator uses a faster C-API call. * ``bytearray`` has become a known type and supports coercion from and to C strings. Indexing, slicing and decoding is optimised. Note that this may have an impact on existing code due to type inference. * Using ``cdef basestring stringvar`` and function arguments typed as ``basestring`` is now meaningful and allows assigning exactly ``str`` and ``unicode`` objects, but no subtypes of these types. * Support for the ``__debug__`` builtin. * Assertions in Cython compiled modules are disabled if the running Python interpreter was started with the "-O" option. * Some types that Cython provides internally, such as functions and generators, are now shared across modules if more than one Cython implemented module is imported. * The type inference algorithm works more fine granular by taking the results of the control flow analysis into account. * A new script in ``bin/cythonize`` provides a command line frontend to the cythonize() compilation function (including distutils build). * The new extension type decorator ``@cython.no_gc_clear`` prevents objects from being cleared during cyclic garbage collection, thus making sure that object attributes are kept alive until deallocation. * During cyclic garbage collection, attributes of extension types that cannot create reference cycles due to their type (e.g. strings) are no longer considered for traversal or clearing. This can reduce the processing overhead when searching for or cleaning up reference cycles. * Package compilation (i.e. ``__init__.py`` files) now works, starting with Python 3.3. * The cython-mode.el script for Emacs was updated. Patch by Ivan Andrus. * An option common_utility_include_dir was added to cythonize() to save oft-used utility code once in a separate directory rather than as part of each generated file. * ``unraisable_tracebacks`` directive added to control printing of tracebacks of unraisable exceptions. Bugs fixed ---------- * Abstract Python classes that subtyped a Cython extension type failed to raise an exception on instantiation, and thus ended up being instantiated. * ``set.add(a_tuple)`` and ``set.discard(a_tuple)`` failed with a TypeError in Py2.4. * The PEP 3155 ``__qualname__`` was incorrect for nested classes and inner classes/functions declared as ``global``. * Several corner cases in the try-finally statement were fixed. * The metaclass of a Python class was not inherited from its parent class(es). It is now extracted from the list of base classes if not provided explicitly using the Py3 ``metaclass`` keyword argument. In Py2 compilation mode, a ``__metaclass__`` entry in the class dict will still take precedence if not using Py3 metaclass syntax, but only *after* creating the class dict (which may have been done by a metaclass of a base class, see PEP 3115). It is generally recommended to use the explicit Py3 syntax to define metaclasses for Python types at compile time. * The automatic C switch statement generation behaves more safely for heterogeneous value types (e.g. mixing enum and char), allowing for a slightly wider application and reducing corner cases. It now always generates a 'default' clause to avoid C compiler warnings about unmatched enum values. * Fixed a bug where class hierarchies declared out-of-order could result in broken generated code. * Fixed a bug which prevented overriding const methods of C++ classes. * Fixed a crash when converting Python objects to C++ strings fails. Other changes ------------- * In Py3 compilation mode, Python2-style metaclasses declared by a ``__metaclass__`` class dict entry are ignored. * In Py3.4+, the Cython generator type uses ``tp_finalize()`` for safer cleanup instead of ``tp_del()``. 0.19.2 (2013-10-13) =================== Features added -------------- Bugs fixed ---------- * Some standard declarations were fixed or updated, including the previously incorrect declaration of ``PyBuffer_FillInfo()`` and some missing bits in ``libc.math``. * Heap allocated subtypes of ``type`` used the wrong base type struct at the C level. * Calling the unbound method dict.keys/value/items() in dict subtypes could call the bound object method instead of the unbound supertype method. * "yield" wasn't supported in "return" value expressions. * Using the "bint" type in memory views lead to unexpected results. It is now an error. * Assignments to global/closure variables could catch them in an illegal state while deallocating the old value. Other changes ------------- 0.19.1 (2013-05-11) =================== Features added -------------- * Completely empty C-API structs for extension type slots (protocols like number/mapping/sequence) are no longer generated into the C code. * Docstrings that directly follow a public/readonly attribute declaration in a cdef class will be used as docstring of the auto-generated property. This fixes ticket 206. * The automatic signature documentation tries to preserve more semantics of default arguments and argument types. Specifically, ``bint`` arguments now appear as type ``bool``. * A warning is emitted when negative literal indices are found inside of a code section that disables ``wraparound`` handling. This helps with fixing invalid code that might fail in the face of future compiler optimisations. * Constant folding for boolean expressions (and/or) was improved. * Added a build_dir option to cythonize() which allows one to place the generated .c files outside the source tree. Bugs fixed ---------- * ``isinstance(X, type)`` failed to get optimised into a call to ``PyType_Check()``, as done for other builtin types. * A spurious ``from datetime cimport *`` was removed from the "cpython" declaration package. This means that the "datetime" declarations (added in 0.19) are no longer available directly from the "cpython" namespace, but only from "cpython.datetime". This is the correct way of doing it because the declarations refer to a standard library module, not the core CPython C-API itself. * The C code for extension types is now generated in topological order instead of source code order to avoid C compiler errors about missing declarations for subtypes that are defined before their parent. * The ``memoryview`` type name no longer shows up in the module dict of modules that use memory views. This fixes trac ticket 775. * Regression in 0.19 that rejected valid C expressions from being used in C array size declarations. * In C++ mode, the C99-only keyword ``restrict`` could accidentally be seen by the GNU C++ compiler. It is now specially handled for both GCC and MSVC. * Testing large (> int) C integer values for their truth value could fail due to integer wrap-around. Other changes ------------- 0.19 (2013-04-19) ================= Features added -------------- * New directives ``c_string_type`` and ``c_string_encoding`` to more easily and automatically convert between C strings and the different Python string types. * The extension type flag ``Py_TPFLAGS_HAVE_VERSION_TAG`` is enabled by default on extension types and can be disabled using the ``type_version_tag`` compiler directive. * EXPERIMENTAL support for simple Cython code level line tracing. Enabled by the "linetrace" compiler directive. * Cython implemented functions make their argument and return type annotations available through the ``__annotations__`` attribute (PEP 3107). * Access to non-cdef module globals and Python object attributes is faster. * ``Py_UNICODE*`` coerces from and to Python unicode strings. This is helpful when talking to Windows APIs, which use compatible wchar_t arrays for strings. Note that the ``Py_UNICODE`` type is otherwise deprecated as of CPython 3.3. * ``isinstance(obj, basestring)`` is optimised. In Python 3 it only tests for instances of ``str`` (i.e. Py2 ``unicode``). * The ``basestring`` builtin is mapped to ``str`` (i.e. Py2 ``unicode``) when compiling the generated C code under Python 3. * Closures use freelists, which can speed up their creation quite substantially. This is also visible for short running generator expressions, for example. * A new class decorator ``@cython.freelist(N)`` creates a static freelist of N instances for an extension type, thus avoiding the costly allocation step if possible. This can speed up object instantiation by 20-30% in suitable scenarios. Note that freelists are currently only supported for base types, not for types that inherit from others. * Fast extension type instantiation using the ``Type.__new__(Type)`` idiom has gained support for passing arguments. It is also a bit faster for types defined inside of the module. * The Python2-only dict methods ``.iter*()`` and ``.view*()`` (requires Python 2.7) are automatically mapped to the equivalent keys/values/items methods in Python 3 for typed dictionaries. * Slicing unicode strings, lists and tuples is faster. * list.append() is faster on average. * ``raise Exception() from None`` suppresses the exception context in Py3.3. * Py3 compatible ``exec(tuple)`` syntax is supported in Py2 code. * Keyword arguments are supported for cdef functions. * External C++ classes can be declared nogil. Patch by John Stumpo. This fixes trac ticket 805. Bugs fixed ---------- * 2-value slicing of unknown objects passes the correct slice when the ``getitem`` protocol is used instead of the ``getslice`` protocol (especially in Python 3), i.e. ``None`` values for missing bounds instead of ``[0,maxsize]``. It is also a bit faster in some cases, e.g. for constant bounds. This fixes trac ticket 636. * Cascaded assignments of None values to extension type variables failed with a ``TypeError`` at runtime. * The ``__defaults__`` attribute was not writable for Cython implemented functions. * Default values of keyword-only arguments showed up in ``__defaults__`` instead of ``__kwdefaults__`` (which was not implemented). Both are available for Cython implemented functions now, as specified in Python 3.x. * ``yield`` works inside of ``with gil`` sections. It previously lead to a crash. This fixes trac ticket 803. * Static methods without explicitly named positional arguments (e.g. having only ``*args``) crashed when being called. This fixes trac ticket 804. * ``dir()`` without arguments previously returned an unsorted list, which now gets sorted as expected. * ``dict.items()``, ``dict.keys()`` and ``dict.values()`` no longer return lists in Python 3. * Exiting from an ``except-as`` clause now deletes the exception in Python 3 mode. * The declarations of ``frexp()`` and ``ldexp()`` in ``math.pxd`` were incorrect. Other changes ------------- 0.18 (2013-01-28) ================= Features added -------------- * Named Unicode escapes ("\N{...}") are supported. * Python functions/classes provide the special attribute "__qualname__" as defined by PEP 3155. * Added a directive ``overflowcheck`` which raises an OverflowException when arithmetic with C ints overflow. This has a modest performance penalty, but is much faster than using Python ints. * Calls to nested Python functions are resolved at compile time. * Type inference works across nested functions. * ``py_bytes_string.decode(...)`` is optimised. * C ``const`` declarations are supported in the language. Bugs fixed ---------- * Automatic C++ exception mapping didn't work in nogil functions (only in "with nogil" blocks). Other changes ------------- 0.17.4 (2013-01-03) =================== Bugs fixed ---------- * Garbage collection triggered during deallocation of container classes could lead to a double-deallocation. 0.17.3 (2012-12-14) =================== Features added -------------- Bugs fixed ---------- * During final interpreter cleanup (with types cleanup enabled at compile time), extension types that inherit from base types over more than one level that were cimported from other modules could lead to a crash. * Weak-reference support in extension types (with a ``cdef __weakref__`` attribute) generated incorrect deallocation code. * In CPython 3.3, converting a Unicode character to the Py_UNICODE type could fail to raise an overflow for non-BMP characters that do not fit into a wchar_t on the current platform. * Negative C integer constants lost their longness suffix in the generated C code. Other changes ------------- 0.17.2 (2012-11-20) =================== Features added -------------- * ``cythonize()`` gained a best effort compile mode that can be used to simply ignore .py files that fail to compile. Bugs fixed ---------- * Replacing an object reference with the value of one of its cdef attributes could generate incorrect C code that accessed the object after deleting its last reference. * C-to-Python type coercions during cascaded comparisons could generate invalid C code, specifically when using the 'in' operator. * "obj[1,]" passed a single integer into the item getter instead of a tuple. * Cyclic imports at module init time did not work in Py3. * The names of C++ destructors for template classes were built incorrectly. * In pure mode, type casts in Cython syntax and the C ampersand operator are now rejected. Use the pure mode replacements instead. * In pure mode, C type names and the sizeof() function are no longer recognised as such and can be used as normal Python names. * The extended C level support for the CPython array type was declared too late to be used by user defined classes. * C++ class nesting was broken. * Better checking for required nullary constructors for stack-allocated C++ instances. * Remove module docstring in no-docstring mode. * Fix specialization for varargs function signatures. * Fix several compiler crashes. Other changes ------------- * An experimental distutils script for compiling the CPython standard library was added as Tools/cystdlib.py. 0.17.1 (2012-09-26) =================== Features added -------------- Bugs fixed ---------- * A reference leak was fixed in the new dict iteration code when the loop target was not a plain variable but an unpacked tuple. * Memory views did not handle the special case of a NULL buffer strides value, as allowed by PEP3118. Other changes ------------- 0.17 (2012-09-01) ================= Features added -------------- * Alpha quality support for compiling and running Cython generated extension modules in PyPy (through cpyext). Note that this requires at least PyPy 1.9 and in many cases also adaptations in user code, especially to avoid borrowed references when no owned reference is being held directly in C space (a reference in a Python list or dict is not enough, for example). See the documentation on porting Cython code to PyPy. * "yield from" is supported (PEP 380) and a couple of minor problems with generators were fixed. * C++ STL container classes automatically coerce from and to the equivalent Python container types on typed assignments and casts. Note that the data in the containers is copied during this conversion. * C++ iterators can now be iterated over using "for x in cpp_container" whenever cpp_container has begin() and end() methods returning objects satisfying the iterator pattern (that is, it can be incremented, dereferenced, and compared (for non-equality)). * cdef classes can now have C++ class members (provided a zero-argument constructor exists) * A new cpython.array standard cimport file allows to efficiently talk to the stdlib array.array data type in Python 2. Since CPython does not export an official C-API for this module, it receives special casing by the compiler in order to avoid setup overhead on user side. In Python 3, both buffers and memory views on the array type already worked out of the box with earlier versions of Cython due to the native support for the buffer interface in the Py3 array module. * Fast dict iteration is now enabled optimistically also for untyped variables when the common iteration methods are used. * The unicode string processing code was adapted for the upcoming CPython 3.3 (PEP 393, new Unicode buffer layout). * Buffer arguments and memory view arguments in Python functions can be declared "not None" to raise a TypeError on None input. * c(p)def functions in pure mode can specify their return type with "@cython.returns()". * Automatic dispatch for fused functions with memoryview arguments * Support newaxis indexing for memoryviews * Support decorators for fused functions Bugs fixed ---------- * Old-style Py2 imports did not work reliably in Python 3.x and were broken in Python 3.3. Regardless of this fix, it's generally best to be explicit about relative and global imports in Cython code because old-style imports have a higher overhead. To this end, "from __future__ import absolute_import" is supported in Python/Cython 2.x code now (previous versions of Cython already used it when compiling Python 3 code). * Stricter constraints on the "inline" and "final" modifiers. If your code does not compile due to this change, chances are these modifiers were previously being ignored by the compiler and can be removed without any performance regression. * Exceptions are always instantiated while raising them (as in Python), instead of risking to instantiate them in potentially unsafe situations when they need to be handled or otherwise processed. * locals() properly ignores names that do not have Python compatible types (including automatically inferred types). * Some garbage collection issues of memory views were fixed. * numpy.pxd compiles in Python 3 mode. * Several C compiler warnings were fixed. * Several bugs related to memoryviews and fused types were fixed. * Several bug-fixes and improvements related to cythonize(), including ccache-style caching. Other changes ------------- * libc.string provides a convenience declaration for const uchar in addition to const char. * User declared char* types are now recognised as such and auto-coerce to and from Python bytes strings. * callable() and next() compile to more efficient C code. * list.append() is faster on average. * Modules generated by @cython.inline() are written into the directory pointed to by the environment variable CYTHON_CACHE_DIR if set. 0.16 (2012-04-21) ================= Features added -------------- * Enhancements to Cython's function type (support for weak references, default arguments, code objects, dynamic attributes, classmethods, staticmethods, and more) * Fused Types - Template-like support for functions and methods CEP 522 (docs) * Typed views on memory - Support for efficient direct and indirect buffers (indexing, slicing, transposing, ...) CEP 517 (docs) * super() without arguments * Final cdef methods (which translate into direct calls on known instances) Bugs fixed ---------- * fix alignment handling for record types in buffer support Other changes ------------- * support default arguments for closures * search sys.path for pxd files * support C++ template casting * faster traceback building and faster generator termination * support inplace operators on indexed buffers * allow nested prange sections 0.15.1 (2011-09-19) =================== Features added -------------- Bugs fixed ---------- Other changes ------------- 0.15 (2011-08-05) ================= Features added -------------- * Generators (yield) - Cython has full support for generators, generator expressions and PEP 342 coroutines. * The nonlocal keyword is supported. * Re-acquiring the gil: with gil - works as expected within a nogil context. * OpenMP support: prange. * Control flow analysis prunes dead code and emits warnings and errors about uninitialised variables. * Debugger command cy set to assign values of expressions to Cython variables and cy exec counterpart $cy_eval(). * Exception chaining PEP 3134. * Relative imports PEP 328. * Improved pure syntax including cython.cclass, cython.cfunc, and cython.ccall. * The with statement has its own dedicated and faster C implementation. * Support for del. * Boundschecking directives implemented for builtin Python sequence types. * Several updates and additions to the shipped standard library .pxd files. * Forward declaration of types is no longer required for circular references. Bugs fixed ---------- Other changes ------------- * Uninitialized variables are no longer initialized to None and accessing them has the same semantics as standard Python. * globals() now returns a read-only dict of the Cython module's globals, rather than the globals of the first non-Cython module in the stack * Many C++ exceptions are now special cased to give closer Python counterparts. This means that except+ functions that formerly raised generic RuntimeErrors may raise something else such as ArithmeticError. * The inlined generator expressions (introduced in Cython 0.13) were disabled in favour of full generator expression support. This breaks code that previously used them inside of cdef functions (usage in def functions continues to work) and induces a performance regression for cases that continue to work but that were previously inlined. We hope to reinstate this feature in the near future. 0.14.1 (2011-02-04) =================== Features added -------------- * The gdb debugging support was extended to include all major Cython features, including closures. * raise MemoryError() is now safe to use as Cython replaces it with the correct C-API call. Bugs fixed ---------- Other changes ------------- * Decorators on special methods of cdef classes now raise a compile time error rather than being ignored. * In Python 3 language level mode (-3 option), the 'str' type is now mapped to 'unicode', so that cdef str s declares a Unicode string even when running in Python 2. 0.14 (2010-12-14) ================= Features added -------------- * Python classes can now be nested and receive a proper closure at definition time. * Redefinition is supported for Python functions, even within the same scope. * Lambda expressions are supported in class bodies and at the module level. * Metaclasses are supported for Python classes, both in Python 2 and Python 3 syntax. The Python 3 syntax (using a keyword argument in the type declaration) is preferred and optimised at compile time. * "final" extension classes prevent inheritance in Python space. This feature is available through the new "cython.final" decorator. In the future, these classes may receive further optimisations. * "internal" extension classes do not show up in the module dictionary. This feature is available through the new "cython.internal" decorator. * Extension type inheritance from builtin types, such as "cdef class MyUnicode(unicode)", now works without further external type redeclarations (which are also strongly discouraged now and continue to issue a warning). * GDB support. https://docs.cython.org/src/userguide/debugging.html * A new build system with support for inline distutils directives, correct dependency tracking, and parallel compilation. https://github.com/cython/cython/wiki/enhancements-distutils_preprocessing * Support for dynamic compilation at runtime via the new cython.inline function and cython.compile decorator. https://github.com/cython/cython/wiki/enhancements-inline * "nogil" blocks are supported when compiling pure Python code by writing "with cython.nogil". * Iterating over arbitrary pointer types is now supported, as is an optimized version of the in operator, e.g. x in ptr[a:b]. Bugs fixed ---------- * In parallel assignments, the right side was evaluated in reverse order in 0.13. This could result in errors if it had side effects (e.g. function calls). * In some cases, methods of builtin types would raise a SystemError instead of an AttributeError when called on None. Other changes ------------- * Constant tuples are now cached over the lifetime of an extension module, just like CPython does. Constant argument tuples of Python function calls are also cached. * Closures have tightened to include exactly the names used in the inner functions and classes. Previously, they held the complete locals of the defining function. * The builtin "next()" function in Python 2.6 and later is now implemented internally and therefore available in all Python versions. This makes it the preferred and portable way of manually advancing an iterator. * In addition to the previously supported inlined generator expressions in 0.13, "sorted(genexpr)" can now be used as well. Typing issues were fixed in "sum(genexpr)" that could lead to invalid C code being generated. Other known issues with inlined generator expressions were also fixed that make upgrading to 0.14 a strong recommendation for code that uses them. Note that general generators and generator expressions continue to be not supported. * Inplace arithmetic operators now respect the cdivision directive and are supported for complex types. * Typing a variable as type "complex" previously gave it the Python object type. It now uses the appropriate C/C++ double complex type. A side-effect is that assignments and typed function parameters now accept anything that Python can coerce to a complex, including integers and floats, and not only complex instances. * Large integer literals pass through the compiler in a safer way. To prevent truncation in C code, non 32-bit literals are turned into Python objects if not used in a C context. This context can either be given by a clear C literal suffix such as "UL" or "LL" (or "L" in Python 3 code), or it can be an assignment to a typed variable or a typed function argument, in which case it is up to the user to take care of a sufficiently large value space of the target. * Python functions are declared in the order they appear in the file, rather than all being created at module creation time. This is consistent with Python and needed to support, for example, conditional or repeated declarations of functions. In the face of circular imports this may cause code to break, so a new --disable-function-redefinition flag was added to revert to the old behavior. This flag will be removed in a future release, so should only be used as a stopgap until old code can be fixed. 0.13 (2010-08-25) ================= Features added -------------- * Closures are fully supported for Python functions. Cython supports inner functions and lambda expressions. Generators and generator expressions are not supported in this release. * Proper C++ support. Cython knows about C++ classes, templates and overloaded function signatures, so that Cython code can interact with them in a straight forward way. * Type inference is enabled by default for safe C types (e.g. double, bint, C++ classes) and known extension types. This reduces the need for explicit type declarations and can improve the performance of untyped code in some cases. There is also a verbose compile mode for testing the impact on user code. * Cython's for-in-loop can iterate over C arrays and sliced pointers. The type of the loop variable will be inferred automatically in this case. * The Py_UNICODE integer type for Unicode code points is fully supported, including for-loops and 'in' tests on unicode strings. It coerces from and to single character unicode strings. Note that untyped for-loop variables will automatically be inferred as Py_UNICODE when iterating over a unicode string. In most cases, this will be much more efficient than yielding sliced string objects, but can also have a negative performance impact when the variable is used in a Python context multiple times, so that it needs to coerce to a unicode string object more than once. If this happens, typing the loop variable as unicode or object will help. * The built-in functions any(), all(), sum(), list(), set() and dict() are inlined as plain for loops when called on generator expressions. Note that generator expressions are not generally supported apart from this feature. Also, tuple(genexpr) is not currently supported - use tuple([listcomp]) instead. * More shipped standard library declarations. The python_* and stdlib/stdio .pxd files have been deprecated in favor of clib.* and cpython[.*] and may get removed in a future release. * Pure Python mode no longer disallows non-Python keywords like 'cdef', 'include' or 'cimport'. It also no longer recognises syntax extensions like the for-from loop. * Parsing has improved for Python 3 syntax in Python code, although not all features are correctly supported. The missing Python 3 features are being worked on for the next release. * from __future__ import print_function is supported in Python 2.6 and later. Note that there is currently no emulation for earlier Python versions, so code that uses print() with this future import will require at least Python 2.6. * New compiler directive language_level (valid values: 2 or 3) with corresponding command line options -2 and -3 requests source code compatibility with Python 2.x or Python 3.x respectively. Language level 3 currently enforces unicode literals for unprefixed string literals, enables the print function (requires Python 2.6 or later) and keeps loop variables in list comprehensions from leaking. * Loop variables in set/dict comprehensions no longer leak into the surrounding scope (following Python 2.7). List comprehensions are unchanged in language level 2. * print >> stream Bugs fixed ---------- Other changes ------------- * The availability of type inference by default means that Cython will also infer the type of pointers on assignments. Previously, code like this:: cdef char* s = ... untyped_variable = s would convert the char* to a Python bytes string and assign that. This is no longer the case and no coercion will happen in the example above. The correct way of doing this is through an explicit cast or by typing the target variable, i.e. :: cdef char* s = ... untyped_variable1 = s untyped_variable2 = s cdef object py_object = s cdef bytes bytes_string = s * bool is no longer a valid type name by default. The problem is that it's not clear whether bool should refer to the Python type or the C++ type, and expecting one and finding the other has already led to several hard-to-find bugs. Both types are available for importing: you can use from cpython cimport bool for the Python bool type, and from libcpp cimport bool for the C++ type. bool is still a valid object by default, so one can still write bool(x). * ``__getsegcount__`` is now correctly typed to take a ``Py_size_t*`` rather than an ``int*``. 0.12.1 (2010-02-02) =================== Features added -------------- * Type inference improvements. * There have been several bug fixes and improvements to the type inferencer. * Notably, there is now a "safe" mode enabled by setting the infer_types directive to None. (The None here refers to the "default" mode, which will be the default in 0.13.) This safe mode limits inference to Python object types and C doubles, which should speed up execution without affecting any semantics such as integer overflow behavior like infer_types=True might. There is also an infer_types.verbose option which allows one to see what types are inferred. * The boundscheck directive works for lists and tuples as well as buffers. * len(s) and s.decode("encoding") are efficiently supported for char* s. * Cython's INLINE macro has been renamed to CYTHON_INLINE to reduce conflict and has better support for the MSVC compiler on Windows. It is no longer clobbered if externally defined. * Revision history is now omitted from the source package, resulting in a 85% size reduction. Running make repo will download the history and turn the directory into a complete Mercurial working repository. * Cython modules don't need to be recompiled when the size of an external type grows. (A warning, rather than an error, is produced.) This should be helpful for binary distributions relying on NumPy. Bugs fixed ---------- * Several other bugs and minor improvements have been made. This release should be fully backwards compatible with 0.12. Other changes ------------- 0.12 (2009-11-23) ================= Features added -------------- * Type inference with the infer_types directive * Seamless C++ complex support * Fast extension type instantiation using the normal Python meme obj = MyType.__new__(MyType) * Improved support for Py3.1 * Cython now runs under Python 3.x using the 2to3 tool * unittest support for doctests in Cython modules * Optimised handling of C strings (char*): for c in cstring[2:50] and cstring.decode() * Looping over c pointers: for i in intptr[:50]. * pyximport improvements * cython_freeze improvements Bugs fixed ---------- * Many bug fixes Other changes ------------- * Many other optimisation, e.g. enumerate() loops, parallel swap assignments (a,b = b,a), and unicode.encode() * More complete numpy.pxd 0.11.2 (2009-05-20) =================== Features added -------------- * There's now native complex floating point support! C99 complex will be used if complex.h is included, otherwise explicit complex arithmetic working on all C compilers is used. [Robert Bradshaw] :: cdef double complex a = 1 + 0.3j cdef np.ndarray[np.complex128_t, ndim=2] arr = \ np.zeros(10, np.complex128) * Cython can now generate a main()-method for embedding of the Python interpreter into an executable (see :issue:`289`) [Robert Bradshaw] * @wraparound directive (another way to disable arr[idx] for negative idx) [Dag Sverre Seljebotn] * Correct support for NumPy record dtypes with different alignments, and "cdef packed struct" support [Dag Sverre Seljebotn] * @callspec directive, allowing custom calling convention macros [Lisandro Dalcin] Bugs fixed ---------- Other changes ------------- * Bug fixes and smaller improvements. For the full list, see [1]. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3087223 Cython-3.0.8/COPYING.txt0000644000175100001770000000136400000000000015451 0ustar00runnerdocker00000000000000The original Pyrex code as of 2006-04 is licensed under the following license: "Copyright stuff: Pyrex is free of restrictions. You may use, redistribute, modify and distribute modified versions." ------------------ Cython, which derives from Pyrex, is licensed under the Apache 2.0 Software License. More precisely, all modifications and new code made to go from Pyrex to Cython are so licensed. See LICENSE.txt for more details. ------------------ The output of a Cython compilation is NOT considered a derivative work of Cython. Specifically, though the compilation process may embed snippets of varying lengths into the final output, these snippets, as embedded in the output, do not encumber the resulting output with any license restrictions. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880490.988724 Cython-3.0.8/Cython/0000755000175100001770000000000000000000000015040 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880490.988724 Cython-3.0.8/Cython/Build/0000755000175100001770000000000000000000000016077 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3087223 Cython-3.0.8/Cython/Build/BuildExecutable.py0000644000175100001770000001126500000000000021517 0ustar00runnerdocker00000000000000""" Compile a Python script into an executable that embeds CPython. Requires CPython to be built as a shared library ('libpythonX.Y'). Basic usage: python -m Cython.Build.BuildExecutable [ARGS] somefile.py """ from __future__ import absolute_import DEBUG = True import sys import os if sys.version_info < (3, 9): from distutils import sysconfig as _sysconfig class sysconfig(object): @staticmethod def get_path(name): assert name == 'include' return _sysconfig.get_python_inc() get_config_var = staticmethod(_sysconfig.get_config_var) else: # sysconfig can be trusted from cpython >= 3.8.7 import sysconfig def get_config_var(name, default=''): return sysconfig.get_config_var(name) or default INCDIR = sysconfig.get_path('include') LIBDIR1 = get_config_var('LIBDIR') LIBDIR2 = get_config_var('LIBPL') PYLIB = get_config_var('LIBRARY') PYLIB_DYN = get_config_var('LDLIBRARY') if PYLIB_DYN == PYLIB: # no shared library PYLIB_DYN = '' else: PYLIB_DYN = os.path.splitext(PYLIB_DYN[3:])[0] # 'lib(XYZ).so' -> XYZ CC = get_config_var('CC', os.environ.get('CC', '')) CFLAGS = get_config_var('CFLAGS') + ' ' + os.environ.get('CFLAGS', '') LINKCC = get_config_var('LINKCC', os.environ.get('LINKCC', CC)) LINKFORSHARED = get_config_var('LINKFORSHARED') LIBS = get_config_var('LIBS') SYSLIBS = get_config_var('SYSLIBS') EXE_EXT = sysconfig.get_config_var('EXE') def _debug(msg, *args): if DEBUG: if args: msg = msg % args sys.stderr.write(msg + '\n') def dump_config(): _debug('INCDIR: %s', INCDIR) _debug('LIBDIR1: %s', LIBDIR1) _debug('LIBDIR2: %s', LIBDIR2) _debug('PYLIB: %s', PYLIB) _debug('PYLIB_DYN: %s', PYLIB_DYN) _debug('CC: %s', CC) _debug('CFLAGS: %s', CFLAGS) _debug('LINKCC: %s', LINKCC) _debug('LINKFORSHARED: %s', LINKFORSHARED) _debug('LIBS: %s', LIBS) _debug('SYSLIBS: %s', SYSLIBS) _debug('EXE_EXT: %s', EXE_EXT) def _parse_args(args): cy_args = [] last_arg = None for i, arg in enumerate(args): if arg.startswith('-'): cy_args.append(arg) elif last_arg in ('-X', '--directive'): cy_args.append(arg) else: input_file = arg args = args[i+1:] break last_arg = arg else: raise ValueError('no input file provided') return input_file, cy_args, args def runcmd(cmd, shell=True): if shell: cmd = ' '.join(cmd) _debug(cmd) else: _debug(' '.join(cmd)) import subprocess returncode = subprocess.call(cmd, shell=shell) if returncode: sys.exit(returncode) def clink(basename): runcmd([LINKCC, '-o', basename + EXE_EXT, basename+'.o', '-L'+LIBDIR1, '-L'+LIBDIR2] + [PYLIB_DYN and ('-l'+PYLIB_DYN) or os.path.join(LIBDIR1, PYLIB)] + LIBS.split() + SYSLIBS.split() + LINKFORSHARED.split()) def ccompile(basename): runcmd([CC, '-c', '-o', basename+'.o', basename+'.c', '-I' + INCDIR] + CFLAGS.split()) def cycompile(input_file, options=()): from ..Compiler import Version, CmdLine, Main options, sources = CmdLine.parse_command_line(list(options or ()) + ['--embed', input_file]) _debug('Using Cython %s to compile %s', Version.version, input_file) result = Main.compile(sources, options) if result.num_errors > 0: sys.exit(1) def exec_file(program_name, args=()): runcmd([os.path.abspath(program_name)] + list(args), shell=False) def build(input_file, compiler_args=(), force=False): """ Build an executable program from a Cython module. Returns the name of the executable file. """ basename = os.path.splitext(input_file)[0] exe_file = basename + EXE_EXT if not force and os.path.abspath(exe_file) == os.path.abspath(input_file): raise ValueError("Input and output file names are the same, refusing to overwrite") if (not force and os.path.exists(exe_file) and os.path.exists(input_file) and os.path.getmtime(input_file) <= os.path.getmtime(exe_file)): _debug("File is up to date, not regenerating %s", exe_file) return exe_file cycompile(input_file, compiler_args) ccompile(basename) clink(basename) return exe_file def build_and_run(args): """ Build an executable program from a Cython module and run it. Arguments after the module name will be passed verbatimly to the program. """ program_name, args = _build(args) exec_file(program_name, args) def _build(args): input_file, cy_args, args = _parse_args(args) program_name = build(input_file, cy_args) return program_name, args if __name__ == '__main__': _build(sys.argv[1:]) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3087223 Cython-3.0.8/Cython/Build/Cythonize.py0000644000175100001770000002314600000000000020433 0ustar00runnerdocker00000000000000from __future__ import absolute_import, print_function import os import shutil import tempfile from .Dependencies import cythonize, extended_iglob from ..Utils import is_package_dir from ..Compiler import Options try: import multiprocessing parallel_compiles = int(multiprocessing.cpu_count() * 1.5) except ImportError: multiprocessing = None parallel_compiles = 0 class _FakePool(object): def map_async(self, func, args): try: from itertools import imap except ImportError: imap=map for _ in imap(func, args): pass def close(self): pass def terminate(self): pass def join(self): pass def find_package_base(path): base_dir, package_path = os.path.split(path) while is_package_dir(base_dir): base_dir, parent = os.path.split(base_dir) package_path = '%s/%s' % (parent, package_path) return base_dir, package_path def cython_compile(path_pattern, options): all_paths = map(os.path.abspath, extended_iglob(path_pattern)) _cython_compile_files(all_paths, options) def _cython_compile_files(all_paths, options): pool = None try: for path in all_paths: if options.build_inplace: base_dir = path while not os.path.isdir(base_dir) or is_package_dir(base_dir): base_dir = os.path.dirname(base_dir) else: base_dir = None if os.path.isdir(path): # recursively compiling a package paths = [os.path.join(path, '**', '*.{py,pyx}')] else: # assume it's a file(-like thing) paths = [path] ext_modules = cythonize( paths, nthreads=options.parallel, exclude_failures=options.keep_going, exclude=options.excludes, compiler_directives=options.directives, compile_time_env=options.compile_time_env, force=options.force, quiet=options.quiet, depfile=options.depfile, language=options.language, **options.options) if ext_modules and options.build: if len(ext_modules) > 1 and options.parallel > 1: if pool is None: try: pool = multiprocessing.Pool(options.parallel) except OSError: pool = _FakePool() pool.map_async(run_distutils, [ (base_dir, [ext]) for ext in ext_modules]) else: run_distutils((base_dir, ext_modules)) except: if pool is not None: pool.terminate() raise else: if pool is not None: pool.close() pool.join() def run_distutils(args): try: from distutils.core import setup except ImportError: try: from setuptools import setup except ImportError: raise ImportError("'distutils' is not available. Please install 'setuptools' for binary builds.") base_dir, ext_modules = args script_args = ['build_ext', '-i'] cwd = os.getcwd() temp_dir = None try: if base_dir: os.chdir(base_dir) temp_dir = tempfile.mkdtemp(dir=base_dir) script_args.extend(['--build-temp', temp_dir]) setup( script_name='setup.py', script_args=script_args, ext_modules=ext_modules, ) finally: if base_dir: os.chdir(cwd) if temp_dir and os.path.isdir(temp_dir): shutil.rmtree(temp_dir) def create_args_parser(): from argparse import ArgumentParser, RawDescriptionHelpFormatter from ..Compiler.CmdLine import ParseDirectivesAction, ParseOptionsAction, ParseCompileTimeEnvAction parser = ArgumentParser( formatter_class=RawDescriptionHelpFormatter, epilog="""\ Environment variables: CYTHON_FORCE_REGEN: if set to 1, forces cythonize to regenerate the output files regardless of modification times and changes. Environment variables accepted by setuptools are supported to configure the C compiler and build: https://setuptools.pypa.io/en/latest/userguide/ext_modules.html#compiler-and-linker-options""" ) parser.add_argument('-X', '--directive', metavar='NAME=VALUE,...', dest='directives', default={}, type=str, action=ParseDirectivesAction, help='set a compiler directive') parser.add_argument('-E', '--compile-time-env', metavar='NAME=VALUE,...', dest='compile_time_env', default={}, type=str, action=ParseCompileTimeEnvAction, help='set a compile time environment variable') parser.add_argument('-s', '--option', metavar='NAME=VALUE', dest='options', default={}, type=str, action=ParseOptionsAction, help='set a cythonize option') parser.add_argument('-2', dest='language_level', action='store_const', const=2, default=None, help='use Python 2 syntax mode by default') parser.add_argument('-3', dest='language_level', action='store_const', const=3, help='use Python 3 syntax mode by default') parser.add_argument('--3str', dest='language_level', action='store_const', const='3str', help='use Python 3 syntax mode by default') parser.add_argument('-+', '--cplus', dest='language', action='store_const', const='c++', default=None, help='Compile as C++ rather than C') parser.add_argument('-a', '--annotate', action='store_const', const='default', dest='annotate', help='Produce a colorized HTML version of the source.') parser.add_argument('--annotate-fullc', action='store_const', const='fullc', dest='annotate', help='Produce a colorized HTML version of the source ' 'which includes entire generated C/C++-code.') parser.add_argument('-x', '--exclude', metavar='PATTERN', dest='excludes', action='append', default=[], help='exclude certain file patterns from the compilation') parser.add_argument('-b', '--build', dest='build', action='store_true', default=None, help='build extension modules using distutils/setuptools') parser.add_argument('-i', '--inplace', dest='build_inplace', action='store_true', default=None, help='build extension modules in place using distutils/setuptools (implies -b)') parser.add_argument('-j', '--parallel', dest='parallel', metavar='N', type=int, default=parallel_compiles, help=('run builds in N parallel jobs (default: %d)' % parallel_compiles or 1)) parser.add_argument('-f', '--force', dest='force', action='store_true', default=None, help='force recompilation') parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', default=None, help='be less verbose during compilation') parser.add_argument('--lenient', dest='lenient', action='store_true', default=None, help='increase Python compatibility by ignoring some compile time errors') parser.add_argument('-k', '--keep-going', dest='keep_going', action='store_true', default=None, help='compile as much as possible, ignore compilation failures') parser.add_argument('--no-docstrings', dest='no_docstrings', action='store_true', default=None, help='strip docstrings') parser.add_argument('-M', '--depfile', action='store_true', help='produce depfiles for the sources') parser.add_argument('sources', nargs='*') return parser def parse_args_raw(parser, args): options, unknown = parser.parse_known_args(args) sources = options.sources # if positional arguments were interspersed # some of them are in unknown for option in unknown: if option.startswith('-'): parser.error("unknown option "+option) else: sources.append(option) del options.sources return (options, sources) def parse_args(args): parser = create_args_parser() options, args = parse_args_raw(parser, args) if not args: parser.error("no source files provided") if options.build_inplace: options.build = True if multiprocessing is None: options.parallel = 0 if options.language_level: assert options.language_level in (2, 3, '3str') options.options['language_level'] = options.language_level if options.lenient: # increase Python compatibility by ignoring compile time errors Options.error_on_unknown_names = False Options.error_on_uninitialized = False if options.annotate: Options.annotate = options.annotate if options.no_docstrings: Options.docstrings = False return options, args def main(args=None): options, paths = parse_args(args) all_paths = [] for path in paths: expanded_path = [os.path.abspath(p) for p in extended_iglob(path)] if not expanded_path: import sys print("{}: No such file or directory: '{}'".format(sys.argv[0], path), file=sys.stderr) sys.exit(1) all_paths.extend(expanded_path) _cython_compile_files(all_paths, options) if __name__ == '__main__': main() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3087223 Cython-3.0.8/Cython/Build/Dependencies.py0000644000175100001770000014730200000000000021046 0ustar00runnerdocker00000000000000from __future__ import absolute_import, print_function import cython from .. import __version__ import collections import contextlib import hashlib import os import shutil import subprocess import re, sys, time from glob import iglob from io import open as io_open from os.path import relpath as _relpath import zipfile try: from collections.abc import Iterable except ImportError: from collections import Iterable try: import gzip gzip_open = gzip.open gzip_ext = '.gz' except ImportError: gzip_open = open gzip_ext = '' try: import zlib zipfile_compression_mode = zipfile.ZIP_DEFLATED except ImportError: zipfile_compression_mode = zipfile.ZIP_STORED try: import pythran except: pythran = None from .. import Utils from ..Utils import (cached_function, cached_method, path_exists, safe_makedirs, copy_file_to_dir_if_newer, is_package_dir, write_depfile) from ..Compiler import Errors from ..Compiler.Main import Context from ..Compiler.Options import (CompilationOptions, default_options, get_directive_defaults) join_path = cached_function(os.path.join) copy_once_if_newer = cached_function(copy_file_to_dir_if_newer) safe_makedirs_once = cached_function(safe_makedirs) if sys.version_info[0] < 3: # stupid Py2 distutils enforces str type in list of sources _fs_encoding = sys.getfilesystemencoding() if _fs_encoding is None: _fs_encoding = sys.getdefaultencoding() def encode_filename_in_py2(filename): if not isinstance(filename, bytes): return filename.encode(_fs_encoding) return filename else: def encode_filename_in_py2(filename): return filename basestring = str def _make_relative(file_paths, base=None): if not base: base = os.getcwd() if base[-1] != os.path.sep: base += os.path.sep return [_relpath(path, base) if path.startswith(base) else path for path in file_paths] def extended_iglob(pattern): if '{' in pattern: m = re.match('(.*){([^}]+)}(.*)', pattern) if m: before, switch, after = m.groups() for case in switch.split(','): for path in extended_iglob(before + case + after): yield path return # We always accept '/' and also '\' on Windows, # because '/' is generally common for relative paths. if '**/' in pattern or os.sep == '\\' and '**\\' in pattern: seen = set() first, rest = re.split(r'\*\*[%s]' % ('/\\\\' if os.sep == '\\' else '/'), pattern, 1) if first: first = iglob(first + os.sep) else: first = [''] for root in first: for path in extended_iglob(join_path(root, rest)): if path not in seen: seen.add(path) yield path for path in extended_iglob(join_path(root, '*', '**', rest)): if path not in seen: seen.add(path) yield path else: for path in iglob(pattern): yield path def nonempty(it, error_msg="expected non-empty iterator"): empty = True for value in it: empty = False yield value if empty: raise ValueError(error_msg) @cached_function def file_hash(filename): path = os.path.normpath(filename) prefix = ('%d:%s' % (len(path), path)).encode("UTF-8") m = hashlib.sha1(prefix) with open(path, 'rb') as f: data = f.read(65000) while data: m.update(data) data = f.read(65000) return m.hexdigest() def update_pythran_extension(ext): if pythran is None: raise RuntimeError("You first need to install Pythran to use the np_pythran directive.") try: pythran_ext = pythran.config.make_extension(python=True) except TypeError: # older pythran version only pythran_ext = pythran.config.make_extension() ext.include_dirs.extend(pythran_ext['include_dirs']) ext.extra_compile_args.extend(pythran_ext['extra_compile_args']) ext.extra_link_args.extend(pythran_ext['extra_link_args']) ext.define_macros.extend(pythran_ext['define_macros']) ext.undef_macros.extend(pythran_ext['undef_macros']) ext.library_dirs.extend(pythran_ext['library_dirs']) ext.libraries.extend(pythran_ext['libraries']) ext.language = 'c++' # These options are not compatible with the way normal Cython extensions work for bad_option in ["-fwhole-program", "-fvisibility=hidden"]: try: ext.extra_compile_args.remove(bad_option) except ValueError: pass def parse_list(s): """ >>> parse_list("") [] >>> parse_list("a") ['a'] >>> parse_list("a b c") ['a', 'b', 'c'] >>> parse_list("[a, b, c]") ['a', 'b', 'c'] >>> parse_list('a " " b') ['a', ' ', 'b'] >>> parse_list('[a, ",a", "a,", ",", ]') ['a', ',a', 'a,', ','] """ if len(s) >= 2 and s[0] == '[' and s[-1] == ']': s = s[1:-1] delimiter = ',' else: delimiter = ' ' s, literals = strip_string_literals(s) def unquote(literal): literal = literal.strip() if literal[0] in "'\"": return literals[literal[1:-1]] else: return literal return [unquote(item) for item in s.split(delimiter) if item.strip()] transitive_str = object() transitive_list = object() bool_or = object() distutils_settings = { 'name': str, 'sources': list, 'define_macros': list, 'undef_macros': list, 'libraries': transitive_list, 'library_dirs': transitive_list, 'runtime_library_dirs': transitive_list, 'include_dirs': transitive_list, 'extra_objects': list, 'extra_compile_args': transitive_list, 'extra_link_args': transitive_list, 'export_symbols': list, 'depends': transitive_list, 'language': transitive_str, 'np_pythran': bool_or } def _legacy_strtobool(val): # Used to be "distutils.util.strtobool", adapted for deprecation warnings. if val == "True": return True elif val == "False": return False import warnings warnings.warn("The 'np_python' option requires 'True' or 'False'", category=DeprecationWarning) val = val.lower() if val in ('y', 'yes', 't', 'true', 'on', '1'): return True elif val in ('n', 'no', 'f', 'false', 'off', '0'): return False else: raise ValueError("invalid truth value %r" % (val,)) @cython.locals(start=cython.Py_ssize_t, end=cython.Py_ssize_t) def line_iter(source): if isinstance(source, basestring): start = 0 while True: end = source.find('\n', start) if end == -1: yield source[start:] return yield source[start:end] start = end+1 else: for line in source: yield line class DistutilsInfo(object): def __init__(self, source=None, exn=None): self.values = {} if source is not None: for line in line_iter(source): line = line.lstrip() if not line: continue if line[0] != '#': break line = line[1:].lstrip() kind = next((k for k in ("distutils:","cython:") if line.startswith(k)), None) if kind is not None: key, _, value = [s.strip() for s in line[len(kind):].partition('=')] type = distutils_settings.get(key, None) if line.startswith("cython:") and type is None: continue if type in (list, transitive_list): value = parse_list(value) if key == 'define_macros': value = [tuple(macro.split('=', 1)) if '=' in macro else (macro, None) for macro in value] if type is bool_or: value = _legacy_strtobool(value) self.values[key] = value elif exn is not None: for key in distutils_settings: if key in ('name', 'sources','np_pythran'): continue value = getattr(exn, key, None) if value: self.values[key] = value def merge(self, other): if other is None: return self for key, value in other.values.items(): type = distutils_settings[key] if type is transitive_str and key not in self.values: self.values[key] = value elif type is transitive_list: if key in self.values: # Change a *copy* of the list (Trac #845) all = self.values[key][:] for v in value: if v not in all: all.append(v) value = all self.values[key] = value elif type is bool_or: self.values[key] = self.values.get(key, False) | value return self def subs(self, aliases): if aliases is None: return self resolved = DistutilsInfo() for key, value in self.values.items(): type = distutils_settings[key] if type in [list, transitive_list]: new_value_list = [] for v in value: if v in aliases: v = aliases[v] if isinstance(v, list): new_value_list += v else: new_value_list.append(v) value = new_value_list else: if value in aliases: value = aliases[value] resolved.values[key] = value return resolved def apply(self, extension): for key, value in self.values.items(): type = distutils_settings[key] if type in [list, transitive_list]: value = getattr(extension, key) + list(value) setattr(extension, key, value) @cython.locals(start=cython.Py_ssize_t, q=cython.Py_ssize_t, single_q=cython.Py_ssize_t, double_q=cython.Py_ssize_t, hash_mark=cython.Py_ssize_t, end=cython.Py_ssize_t, k=cython.Py_ssize_t, counter=cython.Py_ssize_t, quote_len=cython.Py_ssize_t) def strip_string_literals(code, prefix='__Pyx_L'): """ Normalizes every string literal to be of the form '__Pyx_Lxxx', returning the normalized code and a mapping of labels to string literals. """ new_code = [] literals = {} counter = 0 start = q = 0 in_quote = False hash_mark = single_q = double_q = -1 code_len = len(code) quote_type = None quote_len = -1 while True: if hash_mark < q: hash_mark = code.find('#', q) if single_q < q: single_q = code.find("'", q) if double_q < q: double_q = code.find('"', q) q = min(single_q, double_q) if q == -1: q = max(single_q, double_q) # We're done. if q == -1 and hash_mark == -1: new_code.append(code[start:]) break # Try to close the quote. elif in_quote: if code[q-1] == u'\\': k = 2 while q >= k and code[q-k] == u'\\': k += 1 if k % 2 == 0: q += 1 continue if code[q] == quote_type and ( quote_len == 1 or (code_len > q + 2 and quote_type == code[q+1] == code[q+2])): counter += 1 label = "%s%s_" % (prefix, counter) literals[label] = code[start+quote_len:q] full_quote = code[q:q+quote_len] new_code.append(full_quote) new_code.append(label) new_code.append(full_quote) q += quote_len in_quote = False start = q else: q += 1 # Process comment. elif -1 != hash_mark and (hash_mark < q or q == -1): new_code.append(code[start:hash_mark+1]) end = code.find('\n', hash_mark) counter += 1 label = "%s%s_" % (prefix, counter) if end == -1: end_or_none = None else: end_or_none = end literals[label] = code[hash_mark+1:end_or_none] new_code.append(label) if end == -1: break start = q = end # Open the quote. else: if code_len >= q+3 and (code[q] == code[q+1] == code[q+2]): quote_len = 3 else: quote_len = 1 in_quote = True quote_type = code[q] new_code.append(code[start:q]) start = q q += quote_len return "".join(new_code), literals # We need to allow spaces to allow for conditional compilation like # IF ...: # cimport ... dependency_regex = re.compile(r"(?:^\s*from +([0-9a-zA-Z_.]+) +cimport)|" r"(?:^\s*cimport +([0-9a-zA-Z_.]+(?: *, *[0-9a-zA-Z_.]+)*))|" r"(?:^\s*cdef +extern +from +['\"]([^'\"]+)['\"])|" r"(?:^\s*include +['\"]([^'\"]+)['\"])", re.M) dependency_after_from_regex = re.compile( r"(?:^\s+\(([0-9a-zA-Z_., ]*)\)[#\n])|" r"(?:^\s+([0-9a-zA-Z_., ]*)[#\n])", re.M) def normalize_existing(base_path, rel_paths): return normalize_existing0(os.path.dirname(base_path), tuple(set(rel_paths))) @cached_function def normalize_existing0(base_dir, rel_paths): """ Given some base directory ``base_dir`` and a list of path names ``rel_paths``, normalize each relative path name ``rel`` by replacing it by ``os.path.join(base, rel)`` if that file exists. Return a couple ``(normalized, needed_base)`` where ``normalized`` if the list of normalized file names and ``needed_base`` is ``base_dir`` if we actually needed ``base_dir``. If no paths were changed (for example, if all paths were already absolute), then ``needed_base`` is ``None``. """ normalized = [] needed_base = None for rel in rel_paths: if os.path.isabs(rel): normalized.append(rel) continue path = join_path(base_dir, rel) if path_exists(path): normalized.append(os.path.normpath(path)) needed_base = base_dir else: normalized.append(rel) return (normalized, needed_base) def resolve_depends(depends, include_dirs): include_dirs = tuple(include_dirs) resolved = [] for depend in depends: path = resolve_depend(depend, include_dirs) if path is not None: resolved.append(path) return resolved @cached_function def resolve_depend(depend, include_dirs): if depend[0] == '<' and depend[-1] == '>': return None for dir in include_dirs: path = join_path(dir, depend) if path_exists(path): return os.path.normpath(path) return None @cached_function def package(filename): dir = os.path.dirname(os.path.abspath(str(filename))) if dir != filename and is_package_dir(dir): return package(dir) + (os.path.basename(dir),) else: return () @cached_function def fully_qualified_name(filename): module = os.path.splitext(os.path.basename(filename))[0] return '.'.join(package(filename) + (module,)) @cached_function def parse_dependencies(source_filename): # Actual parsing is way too slow, so we use regular expressions. # The only catch is that we must strip comments and string # literals ahead of time. with Utils.open_source_file(source_filename, error_handling='ignore') as fh: source = fh.read() distutils_info = DistutilsInfo(source) source, literals = strip_string_literals(source) source = source.replace('\\\n', ' ').replace('\t', ' ') # TODO: pure mode cimports = [] includes = [] externs = [] for m in dependency_regex.finditer(source): cimport_from, cimport_list, extern, include = m.groups() if cimport_from: cimports.append(cimport_from) m_after_from = dependency_after_from_regex.search(source, pos=m.end()) if m_after_from: multiline, one_line = m_after_from.groups() subimports = multiline or one_line cimports.extend("{0}.{1}".format(cimport_from, s.strip()) for s in subimports.split(',')) elif cimport_list: cimports.extend(x.strip() for x in cimport_list.split(",")) elif extern: externs.append(literals[extern]) else: includes.append(literals[include]) return cimports, includes, externs, distutils_info class DependencyTree(object): def __init__(self, context, quiet=False): self.context = context self.quiet = quiet self._transitive_cache = {} def parse_dependencies(self, source_filename): if path_exists(source_filename): source_filename = os.path.normpath(source_filename) return parse_dependencies(source_filename) @cached_method def included_files(self, filename): # This is messy because included files are textually included, resolving # cimports (but not includes) relative to the including file. all = set() for include in self.parse_dependencies(filename)[1]: include_path = join_path(os.path.dirname(filename), include) if not path_exists(include_path): include_path = self.context.find_include_file(include, source_file_path=filename) if include_path: if '.' + os.path.sep in include_path: include_path = os.path.normpath(include_path) all.add(include_path) all.update(self.included_files(include_path)) elif not self.quiet: print(u"Unable to locate '%s' referenced from '%s'" % (filename, include)) return all @cached_method def cimports_externs_incdirs(self, filename): # This is really ugly. Nested cimports are resolved with respect to the # includer, but includes are resolved with respect to the includee. cimports, includes, externs = self.parse_dependencies(filename)[:3] cimports = set(cimports) externs = set(externs) incdirs = set() for include in self.included_files(filename): included_cimports, included_externs, included_incdirs = self.cimports_externs_incdirs(include) cimports.update(included_cimports) externs.update(included_externs) incdirs.update(included_incdirs) externs, incdir = normalize_existing(filename, externs) if incdir: incdirs.add(incdir) return tuple(cimports), externs, incdirs def cimports(self, filename): return self.cimports_externs_incdirs(filename)[0] def package(self, filename): return package(filename) def fully_qualified_name(self, filename): return fully_qualified_name(filename) @cached_method def find_pxd(self, module, filename=None): is_relative = module[0] == '.' if is_relative and not filename: raise NotImplementedError("New relative imports.") if filename is not None: module_path = module.split('.') if is_relative: module_path.pop(0) # just explicitly relative package_path = list(self.package(filename)) while module_path and not module_path[0]: try: package_path.pop() except IndexError: return None # FIXME: error? module_path.pop(0) relative = '.'.join(package_path + module_path) pxd = self.context.find_pxd_file(relative, source_file_path=filename) if pxd: return pxd if is_relative: return None # FIXME: error? return self.context.find_pxd_file(module, source_file_path=filename) @cached_method def cimported_files(self, filename): filename_root, filename_ext = os.path.splitext(filename) if filename_ext in ('.pyx', '.py') and path_exists(filename_root + '.pxd'): pxd_list = [filename_root + '.pxd'] else: pxd_list = [] # Cimports generates all possible combinations package.module # when imported as from package cimport module. for module in self.cimports(filename): if module[:7] == 'cython.' or module == 'cython': continue pxd_file = self.find_pxd(module, filename) if pxd_file is not None: pxd_list.append(pxd_file) return tuple(pxd_list) @cached_method def immediate_dependencies(self, filename): all_deps = {filename} all_deps.update(self.cimported_files(filename)) all_deps.update(self.included_files(filename)) return all_deps def all_dependencies(self, filename): return self.transitive_merge(filename, self.immediate_dependencies, set.union) @cached_method def timestamp(self, filename): return os.path.getmtime(filename) def extract_timestamp(self, filename): return self.timestamp(filename), filename def newest_dependency(self, filename): return max([self.extract_timestamp(f) for f in self.all_dependencies(filename)]) def transitive_fingerprint(self, filename, module, compilation_options): r""" Return a fingerprint of a cython file that is about to be cythonized. Fingerprints are looked up in future compilations. If the fingerprint is found, the cythonization can be skipped. The fingerprint must incorporate everything that has an influence on the generated code. """ try: m = hashlib.sha1(__version__.encode('UTF-8')) m.update(file_hash(filename).encode('UTF-8')) for x in sorted(self.all_dependencies(filename)): if os.path.splitext(x)[1] not in ('.c', '.cpp', '.h'): m.update(file_hash(x).encode('UTF-8')) # Include the module attributes that change the compilation result # in the fingerprint. We do not iterate over module.__dict__ and # include almost everything here as users might extend Extension # with arbitrary (random) attributes that would lead to cache # misses. m.update(str(( module.language, getattr(module, 'py_limited_api', False), getattr(module, 'np_pythran', False) )).encode('UTF-8')) m.update(compilation_options.get_fingerprint().encode('UTF-8')) return m.hexdigest() except IOError: return None def distutils_info0(self, filename): info = self.parse_dependencies(filename)[3] kwds = info.values cimports, externs, incdirs = self.cimports_externs_incdirs(filename) basedir = os.getcwd() # Add dependencies on "cdef extern from ..." files if externs: externs = _make_relative(externs, basedir) if 'depends' in kwds: kwds['depends'] = list(set(kwds['depends']).union(externs)) else: kwds['depends'] = list(externs) # Add include_dirs to ensure that the C compiler will find the # "cdef extern from ..." files if incdirs: include_dirs = list(kwds.get('include_dirs', [])) for inc in _make_relative(incdirs, basedir): if inc not in include_dirs: include_dirs.append(inc) kwds['include_dirs'] = include_dirs return info def distutils_info(self, filename, aliases=None, base=None): return (self.transitive_merge(filename, self.distutils_info0, DistutilsInfo.merge) .subs(aliases) .merge(base)) def transitive_merge(self, node, extract, merge): try: seen = self._transitive_cache[extract, merge] except KeyError: seen = self._transitive_cache[extract, merge] = {} return self.transitive_merge_helper( node, extract, merge, seen, {}, self.cimported_files)[0] def transitive_merge_helper(self, node, extract, merge, seen, stack, outgoing): if node in seen: return seen[node], None deps = extract(node) if node in stack: return deps, node try: stack[node] = len(stack) loop = None for next in outgoing(node): sub_deps, sub_loop = self.transitive_merge_helper(next, extract, merge, seen, stack, outgoing) if sub_loop is not None: if loop is not None and stack[loop] < stack[sub_loop]: pass else: loop = sub_loop deps = merge(deps, sub_deps) if loop == node: loop = None if loop is None: seen[node] = deps return deps, loop finally: del stack[node] _dep_tree = None def create_dependency_tree(ctx=None, quiet=False): global _dep_tree if _dep_tree is None: if ctx is None: ctx = Context(["."], get_directive_defaults(), options=CompilationOptions(default_options)) _dep_tree = DependencyTree(ctx, quiet=quiet) return _dep_tree # If this changes, change also docs/src/reference/compilation.rst # which mentions this function def default_create_extension(template, kwds): if 'depends' in kwds: include_dirs = kwds.get('include_dirs', []) + ["."] depends = resolve_depends(kwds['depends'], include_dirs) kwds['depends'] = sorted(set(depends + template.depends)) t = template.__class__ ext = t(**kwds) metadata = dict(distutils=kwds, module_name=kwds['name']) return (ext, metadata) # This may be useful for advanced users? def create_extension_list(patterns, exclude=None, ctx=None, aliases=None, quiet=False, language=None, exclude_failures=False): if language is not None: print('Warning: passing language={0!r} to cythonize() is deprecated. ' 'Instead, put "# distutils: language={0}" in your .pyx or .pxd file(s)'.format(language)) if exclude is None: exclude = [] if patterns is None: return [], {} elif isinstance(patterns, basestring) or not isinstance(patterns, Iterable): patterns = [patterns] from distutils.extension import Extension if 'setuptools' in sys.modules: # Support setuptools Extension instances as well. extension_classes = ( Extension, # should normally be the same as 'setuptools.extension._Extension' sys.modules['setuptools.extension']._Extension, sys.modules['setuptools'].Extension, ) else: extension_classes = (Extension,) explicit_modules = {m.name for m in patterns if isinstance(m, extension_classes)} deps = create_dependency_tree(ctx, quiet=quiet) to_exclude = set() if not isinstance(exclude, list): exclude = [exclude] for pattern in exclude: to_exclude.update(map(os.path.abspath, extended_iglob(pattern))) module_list = [] module_metadata = {} # if no create_extension() function is defined, use a simple # default function. create_extension = ctx.options.create_extension or default_create_extension seen = set() for pattern in patterns: if not isinstance(pattern, extension_classes): pattern = encode_filename_in_py2(pattern) if isinstance(pattern, str): filepattern = pattern template = Extension(pattern, []) # Fake Extension without sources name = '*' base = None ext_language = language elif isinstance(pattern, extension_classes): cython_sources = [s for s in pattern.sources if os.path.splitext(s)[1] in ('.py', '.pyx')] if cython_sources: filepattern = cython_sources[0] if len(cython_sources) > 1: print(u"Warning: Multiple cython sources found for extension '%s': %s\n" u"See https://cython.readthedocs.io/en/latest/src/userguide/sharing_declarations.html " u"for sharing declarations among Cython files." % (pattern.name, cython_sources)) else: # ignore non-cython modules module_list.append(pattern) continue template = pattern name = template.name base = DistutilsInfo(exn=template) ext_language = None # do not override whatever the Extension says else: msg = str("pattern is not of type str nor subclass of Extension (%s)" " but of type %s and class %s" % (repr(Extension), type(pattern), pattern.__class__)) raise TypeError(msg) for file in nonempty(sorted(extended_iglob(filepattern)), "'%s' doesn't match any files" % filepattern): if os.path.abspath(file) in to_exclude: continue module_name = deps.fully_qualified_name(file) if '*' in name: if module_name in explicit_modules: continue elif name: module_name = name Utils.raise_error_if_module_name_forbidden(module_name) if module_name not in seen: try: kwds = deps.distutils_info(file, aliases, base).values except Exception: if exclude_failures: continue raise if base is not None: for key, value in base.values.items(): if key not in kwds: kwds[key] = value kwds['name'] = module_name sources = [file] + [m for m in template.sources if m != filepattern] if 'sources' in kwds: # allow users to add .c files etc. for source in kwds['sources']: source = encode_filename_in_py2(source) if source not in sources: sources.append(source) kwds['sources'] = sources if ext_language and 'language' not in kwds: kwds['language'] = ext_language np_pythran = kwds.pop('np_pythran', False) # Create the new extension m, metadata = create_extension(template, kwds) m.np_pythran = np_pythran or getattr(m, 'np_pythran', False) if m.np_pythran: update_pythran_extension(m) module_list.append(m) # Store metadata (this will be written as JSON in the # generated C file but otherwise has no purpose) module_metadata[module_name] = metadata if file not in m.sources: # Old setuptools unconditionally replaces .pyx with .c/.cpp target_file = os.path.splitext(file)[0] + ('.cpp' if m.language == 'c++' else '.c') try: m.sources.remove(target_file) except ValueError: # never seen this in the wild, but probably better to warn about this unexpected case print(u"Warning: Cython source file not found in sources list, adding %s" % file) m.sources.insert(0, file) seen.add(name) return module_list, module_metadata # This is the user-exposed entry point. def cythonize(module_list, exclude=None, nthreads=0, aliases=None, quiet=False, force=None, language=None, exclude_failures=False, show_all_warnings=False, **options): """ Compile a set of source modules into C/C++ files and return a list of distutils Extension objects for them. :param module_list: As module list, pass either a glob pattern, a list of glob patterns or a list of Extension objects. The latter allows you to configure the extensions separately through the normal distutils options. You can also pass Extension objects that have glob patterns as their sources. Then, cythonize will resolve the pattern and create a copy of the Extension for every matching file. :param exclude: When passing glob patterns as ``module_list``, you can exclude certain module names explicitly by passing them into the ``exclude`` option. :param nthreads: The number of concurrent builds for parallel compilation (requires the ``multiprocessing`` module). :param aliases: If you want to use compiler directives like ``# distutils: ...`` but can only know at compile time (when running the ``setup.py``) which values to use, you can use aliases and pass a dictionary mapping those aliases to Python strings when calling :func:`cythonize`. As an example, say you want to use the compiler directive ``# distutils: include_dirs = ../static_libs/include/`` but this path isn't always fixed and you want to find it when running the ``setup.py``. You can then do ``# distutils: include_dirs = MY_HEADERS``, find the value of ``MY_HEADERS`` in the ``setup.py``, put it in a python variable called ``foo`` as a string, and then call ``cythonize(..., aliases={'MY_HEADERS': foo})``. :param quiet: If True, Cython won't print error, warning, or status messages during the compilation. :param force: Forces the recompilation of the Cython modules, even if the timestamps don't indicate that a recompilation is necessary. :param language: To globally enable C++ mode, you can pass ``language='c++'``. Otherwise, this will be determined at a per-file level based on compiler directives. This affects only modules found based on file names. Extension instances passed into :func:`cythonize` will not be changed. It is recommended to rather use the compiler directive ``# distutils: language = c++`` than this option. :param exclude_failures: For a broad 'try to compile' mode that ignores compilation failures and simply excludes the failed extensions, pass ``exclude_failures=True``. Note that this only really makes sense for compiling ``.py`` files which can also be used without compilation. :param show_all_warnings: By default, not all Cython warnings are printed. Set to true to show all warnings. :param annotate: If ``True``, will produce a HTML file for each of the ``.pyx`` or ``.py`` files compiled. The HTML file gives an indication of how much Python interaction there is in each of the source code lines, compared to plain C code. It also allows you to see the C/C++ code generated for each line of Cython code. This report is invaluable when optimizing a function for speed, and for determining when to :ref:`release the GIL `: in general, a ``nogil`` block may contain only "white" code. See examples in :ref:`determining_where_to_add_types` or :ref:`primes`. :param annotate-fullc: If ``True`` will produce a colorized HTML version of the source which includes entire generated C/C++-code. :param compiler_directives: Allow to set compiler directives in the ``setup.py`` like this: ``compiler_directives={'embedsignature': True}``. See :ref:`compiler-directives`. :param depfile: produce depfiles for the sources if True. """ if exclude is None: exclude = [] if 'include_path' not in options: options['include_path'] = ['.'] if 'common_utility_include_dir' in options: safe_makedirs(options['common_utility_include_dir']) depfile = options.pop('depfile', None) if pythran is None: pythran_options = None else: pythran_options = CompilationOptions(**options) pythran_options.cplus = True pythran_options.np_pythran = True if force is None: force = os.environ.get("CYTHON_FORCE_REGEN") == "1" # allow global overrides for build systems c_options = CompilationOptions(**options) cpp_options = CompilationOptions(**options); cpp_options.cplus = True ctx = Context.from_options(c_options) options = c_options module_list, module_metadata = create_extension_list( module_list, exclude=exclude, ctx=ctx, quiet=quiet, exclude_failures=exclude_failures, language=language, aliases=aliases) fix_windows_unicode_modules(module_list) deps = create_dependency_tree(ctx, quiet=quiet) build_dir = getattr(options, 'build_dir', None) def copy_to_build_dir(filepath, root=os.getcwd()): filepath_abs = os.path.abspath(filepath) if os.path.isabs(filepath): filepath = filepath_abs if filepath_abs.startswith(root): # distutil extension depends are relative to cwd mod_dir = join_path(build_dir, os.path.dirname(_relpath(filepath, root))) copy_once_if_newer(filepath_abs, mod_dir) modules_by_cfile = collections.defaultdict(list) to_compile = [] for m in module_list: if build_dir: for dep in m.depends: copy_to_build_dir(dep) cy_sources = [ source for source in m.sources if os.path.splitext(source)[1] in ('.pyx', '.py')] if len(cy_sources) == 1: # normal "special" case: believe the Extension module name to allow user overrides full_module_name = m.name else: # infer FQMN from source files full_module_name = None new_sources = [] for source in m.sources: base, ext = os.path.splitext(source) if ext in ('.pyx', '.py'): if m.np_pythran: c_file = base + '.cpp' options = pythran_options elif m.language == 'c++': c_file = base + '.cpp' options = cpp_options else: c_file = base + '.c' options = c_options # setup for out of place build directory if enabled if build_dir: if os.path.isabs(c_file): c_file = os.path.splitdrive(c_file)[1] c_file = c_file.split(os.sep, 1)[1] c_file = os.path.join(build_dir, c_file) dir = os.path.dirname(c_file) safe_makedirs_once(dir) # write out the depfile, if requested if depfile: dependencies = deps.all_dependencies(source) write_depfile(c_file, source, dependencies) # Missing files and those generated by other Cython versions should always be recreated. if Utils.file_generated_by_this_cython(c_file): c_timestamp = os.path.getmtime(c_file) else: c_timestamp = -1 # Priority goes first to modified files, second to direct # dependents, and finally to indirect dependents. if c_timestamp < deps.timestamp(source): dep_timestamp, dep = deps.timestamp(source), source priority = 0 else: dep_timestamp, dep = deps.newest_dependency(source) priority = 2 - (dep in deps.immediate_dependencies(source)) if force or c_timestamp < dep_timestamp: if not quiet and not force: if source == dep: print(u"Compiling %s because it changed." % Utils.decode_filename(source)) else: print(u"Compiling %s because it depends on %s." % ( Utils.decode_filename(source), Utils.decode_filename(dep), )) if not force and options.cache: fingerprint = deps.transitive_fingerprint(source, m, options) else: fingerprint = None to_compile.append(( priority, source, c_file, fingerprint, quiet, options, not exclude_failures, module_metadata.get(m.name), full_module_name, show_all_warnings)) new_sources.append(c_file) modules_by_cfile[c_file].append(m) else: new_sources.append(source) if build_dir: copy_to_build_dir(source) m.sources = new_sources if options.cache: if not os.path.exists(options.cache): os.makedirs(options.cache) to_compile.sort() # Drop "priority" component of "to_compile" entries and add a # simple progress indicator. N = len(to_compile) progress_fmt = "[{0:%d}/{1}] " % len(str(N)) for i in range(N): progress = progress_fmt.format(i+1, N) to_compile[i] = to_compile[i][1:] + (progress,) if N <= 1: nthreads = 0 if nthreads: import multiprocessing pool = multiprocessing.Pool( nthreads, initializer=_init_multiprocessing_helper) # This is a bit more involved than it should be, because KeyboardInterrupts # break the multiprocessing workers when using a normal pool.map(). # See, for example: # https://noswap.com/blog/python-multiprocessing-keyboardinterrupt try: result = pool.map_async(cythonize_one_helper, to_compile, chunksize=1) pool.close() while not result.ready(): try: result.get(99999) # seconds except multiprocessing.TimeoutError: pass except KeyboardInterrupt: pool.terminate() raise pool.join() else: for args in to_compile: cythonize_one(*args) if exclude_failures: failed_modules = set() for c_file, modules in modules_by_cfile.items(): if not os.path.exists(c_file): failed_modules.update(modules) elif os.path.getsize(c_file) < 200: f = io_open(c_file, 'r', encoding='iso8859-1') try: if f.read(len('#error ')) == '#error ': # dead compilation result failed_modules.update(modules) finally: f.close() if failed_modules: for module in failed_modules: module_list.remove(module) print(u"Failed compilations: %s" % ', '.join(sorted([ module.name for module in failed_modules]))) if options.cache: cleanup_cache(options.cache, getattr(options, 'cache_size', 1024 * 1024 * 100)) # cythonize() is often followed by the (non-Python-buffered) # compiler output, flush now to avoid interleaving output. sys.stdout.flush() return module_list def fix_windows_unicode_modules(module_list): # Hack around a distutils 3.[5678] bug on Windows for unicode module names. # https://bugs.python.org/issue39432 if sys.platform != "win32": return if sys.version_info < (3, 5) or sys.version_info >= (3, 8, 2): return def make_filtered_list(ignored_symbol, old_entries): class FilteredExportSymbols(list): # export_symbols for unicode filename cause link errors on Windows # Cython doesn't need them (it already defines PyInit with the correct linkage) # so use this class as a temporary fix to stop them from being generated def __contains__(self, val): # so distutils doesn't "helpfully" add PyInit_ return val == ignored_symbol or list.__contains__(self, val) filtered_list = FilteredExportSymbols(old_entries) if old_entries: filtered_list.extend(name for name in old_entries if name != ignored_symbol) return filtered_list for m in module_list: # TODO: use m.name.isascii() in Py3.7+ try: m.name.encode("ascii") continue except UnicodeEncodeError: pass m.export_symbols = make_filtered_list( "PyInit_" + m.name.rsplit(".", 1)[-1], m.export_symbols, ) if os.environ.get('XML_RESULTS'): compile_result_dir = os.environ['XML_RESULTS'] def record_results(func): def with_record(*args): t = time.time() success = True try: try: func(*args) except: success = False finally: t = time.time() - t module = fully_qualified_name(args[0]) name = "cythonize." + module failures = 1 - success if success: failure_item = "" else: failure_item = "failure" output = open(os.path.join(compile_result_dir, name + ".xml"), "w") output.write(""" %(failure_item)s """.strip() % locals()) output.close() return with_record else: def record_results(func): return func # TODO: Share context? Issue: pyx processing leaks into pxd module @record_results def cythonize_one(pyx_file, c_file, fingerprint, quiet, options=None, raise_on_failure=True, embedded_metadata=None, full_module_name=None, show_all_warnings=False, progress=""): from ..Compiler.Main import compile_single, default_options from ..Compiler.Errors import CompileError, PyrexError if fingerprint: if not os.path.exists(options.cache): safe_makedirs(options.cache) # Cython-generated c files are highly compressible. # (E.g. a compression ratio of about 10 for Sage). fingerprint_file_base = join_path( options.cache, "%s-%s" % (os.path.basename(c_file), fingerprint)) gz_fingerprint_file = fingerprint_file_base + gzip_ext zip_fingerprint_file = fingerprint_file_base + '.zip' if os.path.exists(gz_fingerprint_file) or os.path.exists(zip_fingerprint_file): if not quiet: print(u"%sFound compiled %s in cache" % (progress, pyx_file)) if os.path.exists(gz_fingerprint_file): os.utime(gz_fingerprint_file, None) with contextlib.closing(gzip_open(gz_fingerprint_file, 'rb')) as g: with contextlib.closing(open(c_file, 'wb')) as f: shutil.copyfileobj(g, f) else: os.utime(zip_fingerprint_file, None) dirname = os.path.dirname(c_file) with contextlib.closing(zipfile.ZipFile(zip_fingerprint_file)) as z: for artifact in z.namelist(): z.extract(artifact, os.path.join(dirname, artifact)) return if not quiet: print(u"%sCythonizing %s" % (progress, Utils.decode_filename(pyx_file))) if options is None: options = CompilationOptions(default_options) options.output_file = c_file options.embedded_metadata = embedded_metadata old_warning_level = Errors.LEVEL if show_all_warnings: Errors.LEVEL = 0 any_failures = 0 try: result = compile_single(pyx_file, options, full_module_name=full_module_name) if result.num_errors > 0: any_failures = 1 except (EnvironmentError, PyrexError) as e: sys.stderr.write('%s\n' % e) any_failures = 1 # XXX import traceback traceback.print_exc() except Exception: if raise_on_failure: raise import traceback traceback.print_exc() any_failures = 1 finally: if show_all_warnings: Errors.LEVEL = old_warning_level if any_failures: if raise_on_failure: raise CompileError(None, pyx_file) elif os.path.exists(c_file): os.remove(c_file) elif fingerprint: artifacts = list(filter(None, [ getattr(result, attr, None) for attr in ('c_file', 'h_file', 'api_file', 'i_file')])) if len(artifacts) == 1: fingerprint_file = gz_fingerprint_file with contextlib.closing(open(c_file, 'rb')) as f: with contextlib.closing(gzip_open(fingerprint_file + '.tmp', 'wb')) as g: shutil.copyfileobj(f, g) else: fingerprint_file = zip_fingerprint_file with contextlib.closing(zipfile.ZipFile( fingerprint_file + '.tmp', 'w', zipfile_compression_mode)) as zip: for artifact in artifacts: zip.write(artifact, os.path.basename(artifact)) os.rename(fingerprint_file + '.tmp', fingerprint_file) def cythonize_one_helper(m): import traceback try: return cythonize_one(*m) except Exception: traceback.print_exc() raise def _init_multiprocessing_helper(): # KeyboardInterrupt kills workers, so don't let them get it import signal signal.signal(signal.SIGINT, signal.SIG_IGN) def cleanup_cache(cache, target_size, ratio=.85): try: p = subprocess.Popen(['du', '-s', '-k', os.path.abspath(cache)], stdout=subprocess.PIPE) stdout, _ = p.communicate() res = p.wait() if res == 0: total_size = 1024 * int(stdout.strip().split()[0]) if total_size < target_size: return except (OSError, ValueError): pass total_size = 0 all = [] for file in os.listdir(cache): path = join_path(cache, file) s = os.stat(path) total_size += s.st_size all.append((s.st_atime, s.st_size, path)) if total_size > target_size: for time, size, file in reversed(sorted(all)): os.unlink(file) total_size -= size if total_size < target_size * ratio: break ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3087223 Cython-3.0.8/Cython/Build/Distutils.py0000644000175100001770000000006100000000000020432 0ustar00runnerdocker00000000000000from Cython.Distutils.build_ext import build_ext ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3087223 Cython-3.0.8/Cython/Build/Inline.py0000644000175100001770000003144500000000000017676 0ustar00runnerdocker00000000000000from __future__ import absolute_import import hashlib import inspect import os import re import sys from distutils.core import Distribution, Extension from distutils.command.build_ext import build_ext import Cython from ..Compiler.Main import Context from ..Compiler.Options import (default_options, CompilationOptions, get_directive_defaults) from ..Compiler.Visitor import CythonTransform, EnvTransform from ..Compiler.ParseTreeTransforms import SkipDeclarations from ..Compiler.TreeFragment import parse_from_strings from ..Compiler.StringEncoding import _unicode from .Dependencies import strip_string_literals, cythonize, cached_function from ..Compiler import Pipeline from ..Utils import get_cython_cache_dir import cython as cython_module IS_PY3 = sys.version_info >= (3,) # A utility function to convert user-supplied ASCII strings to unicode. if not IS_PY3: def to_unicode(s): if isinstance(s, bytes): return s.decode('ascii') else: return s else: to_unicode = lambda x: x if sys.version_info < (3, 5): import imp def load_dynamic(name, module_path): return imp.load_dynamic(name, module_path) else: import importlib.util from importlib.machinery import ExtensionFileLoader def load_dynamic(name, path): spec = importlib.util.spec_from_file_location(name, loader=ExtensionFileLoader(name, path)) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module class UnboundSymbols(EnvTransform, SkipDeclarations): def __init__(self): super(EnvTransform, self).__init__(context=None) self.unbound = set() def visit_NameNode(self, node): if not self.current_env().lookup(node.name): self.unbound.add(node.name) return node def __call__(self, node): super(UnboundSymbols, self).__call__(node) return self.unbound @cached_function def unbound_symbols(code, context=None): code = to_unicode(code) if context is None: context = Context([], get_directive_defaults(), options=CompilationOptions(default_options)) from ..Compiler.ParseTreeTransforms import AnalyseDeclarationsTransform tree = parse_from_strings('(tree fragment)', code) for phase in Pipeline.create_pipeline(context, 'pyx'): if phase is None: continue tree = phase(tree) if isinstance(phase, AnalyseDeclarationsTransform): break try: import builtins except ImportError: import __builtin__ as builtins return tuple(UnboundSymbols()(tree) - set(dir(builtins))) def unsafe_type(arg, context=None): py_type = type(arg) if py_type is int: return 'long' else: return safe_type(arg, context) def safe_type(arg, context=None): py_type = type(arg) if py_type in (list, tuple, dict, str): return py_type.__name__ elif py_type is complex: return 'double complex' elif py_type is float: return 'double' elif py_type is bool: return 'bint' elif 'numpy' in sys.modules and isinstance(arg, sys.modules['numpy'].ndarray): return 'numpy.ndarray[numpy.%s_t, ndim=%s]' % (arg.dtype.name, arg.ndim) else: for base_type in py_type.__mro__: if base_type.__module__ in ('__builtin__', 'builtins'): return 'object' module = context.find_module(base_type.__module__, need_pxd=False) if module: entry = module.lookup(base_type.__name__) if entry.is_type: return '%s.%s' % (base_type.__module__, base_type.__name__) return 'object' def _get_build_extension(): dist = Distribution() # Ensure the build respects distutils configuration by parsing # the configuration files config_files = dist.find_config_files() dist.parse_config_files(config_files) build_extension = build_ext(dist) build_extension.finalize_options() return build_extension @cached_function def _create_context(cython_include_dirs): return Context( list(cython_include_dirs), get_directive_defaults(), options=CompilationOptions(default_options) ) _cython_inline_cache = {} _cython_inline_default_context = _create_context(('.',)) def _populate_unbound(kwds, unbound_symbols, locals=None, globals=None): for symbol in unbound_symbols: if symbol not in kwds: if locals is None or globals is None: calling_frame = inspect.currentframe().f_back.f_back.f_back if locals is None: locals = calling_frame.f_locals if globals is None: globals = calling_frame.f_globals if symbol in locals: kwds[symbol] = locals[symbol] elif symbol in globals: kwds[symbol] = globals[symbol] else: print("Couldn't find %r" % symbol) def _inline_key(orig_code, arg_sigs, language_level): key = orig_code, arg_sigs, sys.version_info, sys.executable, language_level, Cython.__version__ return hashlib.sha1(_unicode(key).encode('utf-8')).hexdigest() def cython_inline(code, get_type=unsafe_type, lib_dir=os.path.join(get_cython_cache_dir(), 'inline'), cython_include_dirs=None, cython_compiler_directives=None, force=False, quiet=False, locals=None, globals=None, language_level=None, **kwds): if get_type is None: get_type = lambda x: 'object' ctx = _create_context(tuple(cython_include_dirs)) if cython_include_dirs else _cython_inline_default_context cython_compiler_directives = dict(cython_compiler_directives) if cython_compiler_directives else {} if language_level is None and 'language_level' not in cython_compiler_directives: language_level = '3str' if language_level is not None: cython_compiler_directives['language_level'] = language_level key_hash = None # Fast path if this has been called in this session. _unbound_symbols = _cython_inline_cache.get(code) if _unbound_symbols is not None: _populate_unbound(kwds, _unbound_symbols, locals, globals) args = sorted(kwds.items()) arg_sigs = tuple([(get_type(value, ctx), arg) for arg, value in args]) key_hash = _inline_key(code, arg_sigs, language_level) invoke = _cython_inline_cache.get((code, arg_sigs, key_hash)) if invoke is not None: arg_list = [arg[1] for arg in args] return invoke(*arg_list) orig_code = code code = to_unicode(code) code, literals = strip_string_literals(code) code = strip_common_indent(code) if locals is None: locals = inspect.currentframe().f_back.f_back.f_locals if globals is None: globals = inspect.currentframe().f_back.f_back.f_globals try: _cython_inline_cache[orig_code] = _unbound_symbols = unbound_symbols(code) _populate_unbound(kwds, _unbound_symbols, locals, globals) except AssertionError: if not quiet: # Parsing from strings not fully supported (e.g. cimports). print("Could not parse code as a string (to extract unbound symbols).") cimports = [] for name, arg in list(kwds.items()): if arg is cython_module: cimports.append('\ncimport cython as %s' % name) del kwds[name] arg_names = sorted(kwds) arg_sigs = tuple([(get_type(kwds[arg], ctx), arg) for arg in arg_names]) if key_hash is None: key_hash = _inline_key(orig_code, arg_sigs, language_level) module_name = "_cython_inline_" + key_hash if module_name in sys.modules: module = sys.modules[module_name] else: build_extension = None if cython_inline.so_ext is None: # Figure out and cache current extension suffix build_extension = _get_build_extension() cython_inline.so_ext = build_extension.get_ext_filename('') lib_dir = os.path.abspath(lib_dir) module_path = os.path.join(lib_dir, module_name + cython_inline.so_ext) if not os.path.exists(lib_dir): os.makedirs(lib_dir) if force or not os.path.isfile(module_path): cflags = [] define_macros = [] c_include_dirs = [] qualified = re.compile(r'([.\w]+)[.]') for type, _ in arg_sigs: m = qualified.match(type) if m: cimports.append('\ncimport %s' % m.groups()[0]) # one special case if m.groups()[0] == 'numpy': import numpy c_include_dirs.append(numpy.get_include()) define_macros.append(("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")) # cflags.append('-Wno-unused') module_body, func_body = extract_func_code(code) params = ', '.join(['%s %s' % a for a in arg_sigs]) module_code = """ %(module_body)s %(cimports)s def __invoke(%(params)s): %(func_body)s return locals() """ % {'cimports': '\n'.join(cimports), 'module_body': module_body, 'params': params, 'func_body': func_body } for key, value in literals.items(): module_code = module_code.replace(key, value) pyx_file = os.path.join(lib_dir, module_name + '.pyx') fh = open(pyx_file, 'w') try: fh.write(module_code) finally: fh.close() extension = Extension( name=module_name, sources=[pyx_file], include_dirs=c_include_dirs or None, extra_compile_args=cflags or None, define_macros=define_macros or None, ) if build_extension is None: build_extension = _get_build_extension() build_extension.extensions = cythonize( [extension], include_path=cython_include_dirs or ['.'], compiler_directives=cython_compiler_directives, quiet=quiet) build_extension.build_temp = os.path.dirname(pyx_file) build_extension.build_lib = lib_dir build_extension.run() if sys.platform == 'win32' and sys.version_info >= (3, 8): with os.add_dll_directory(os.path.abspath(lib_dir)): module = load_dynamic(module_name, module_path) else: module = load_dynamic(module_name, module_path) _cython_inline_cache[orig_code, arg_sigs, key_hash] = module.__invoke arg_list = [kwds[arg] for arg in arg_names] return module.__invoke(*arg_list) # Cached suffix used by cython_inline above. None should get # overridden with actual value upon the first cython_inline invocation cython_inline.so_ext = None _find_non_space = re.compile('[^ ]').search def strip_common_indent(code): min_indent = None lines = code.splitlines() for line in lines: match = _find_non_space(line) if not match: continue # blank indent = match.start() if line[indent] == '#': continue # comment if min_indent is None or min_indent > indent: min_indent = indent for ix, line in enumerate(lines): match = _find_non_space(line) if not match or not line or line[indent:indent+1] == '#': continue lines[ix] = line[min_indent:] return '\n'.join(lines) module_statement = re.compile(r'^((cdef +(extern|class))|cimport|(from .+ cimport)|(from .+ import +[*]))') def extract_func_code(code): module = [] function = [] current = function code = code.replace('\t', ' ') lines = code.split('\n') for line in lines: if not line.startswith(' '): if module_statement.match(line): current = module else: current = function current.append(line) return '\n'.join(module), ' ' + '\n '.join(function) def get_body(source): ix = source.index(':') if source[:5] == 'lambda': return "return %s" % source[ix+1:] else: return source[ix+1:] # Lots to be done here... It would be especially cool if compiled functions # could invoke each other quickly. class RuntimeCompiledFunction(object): def __init__(self, f): self._f = f self._body = get_body(inspect.getsource(f)) def __call__(self, *args, **kwds): all = inspect.getcallargs(self._f, *args, **kwds) if IS_PY3: return cython_inline(self._body, locals=self._f.__globals__, globals=self._f.__globals__, **all) else: return cython_inline(self._body, locals=self._f.func_globals, globals=self._f.func_globals, **all) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3087223 Cython-3.0.8/Cython/Build/IpythonMagic.py0000644000175100001770000005271700000000000021060 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*- """ ===================== Cython related magics ===================== Magic command interface for interactive work with Cython .. note:: The ``Cython`` package needs to be installed separately. It can be obtained using ``easy_install`` or ``pip``. Usage ===== To enable the magics below, execute ``%load_ext cython``. ``%%cython`` {CYTHON_DOC} ``%%cython_inline`` {CYTHON_INLINE_DOC} ``%%cython_pyximport`` {CYTHON_PYXIMPORT_DOC} Author: * Brian Granger Code moved from IPython and adapted by: * Martín Gaitán Parts of this code were taken from Cython.inline. """ #----------------------------------------------------------------------------- # Copyright (C) 2010-2011, IPython Development Team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file ipython-COPYING.rst, distributed with this software. #----------------------------------------------------------------------------- from __future__ import absolute_import, print_function import io import os import re import sys import time import copy import distutils.log import textwrap IO_ENCODING = sys.getfilesystemencoding() IS_PY2 = sys.version_info[0] < 3 import hashlib from distutils.core import Distribution, Extension from distutils.command.build_ext import build_ext from IPython.core import display from IPython.core import magic_arguments from IPython.core.magic import Magics, magics_class, cell_magic try: from IPython.paths import get_ipython_cache_dir except ImportError: # older IPython version from IPython.utils.path import get_ipython_cache_dir from IPython.utils.text import dedent from ..Shadow import __version__ as cython_version from ..Compiler.Errors import CompileError from .Inline import cython_inline, load_dynamic from .Dependencies import cythonize from ..Utils import captured_fd, print_captured PGO_CONFIG = { 'gcc': { 'gen': ['-fprofile-generate', '-fprofile-dir={TEMPDIR}'], 'use': ['-fprofile-use', '-fprofile-correction', '-fprofile-dir={TEMPDIR}'], }, # blind copy from 'configure' script in CPython 3.7 'icc': { 'gen': ['-prof-gen'], 'use': ['-prof-use'], } } PGO_CONFIG['mingw32'] = PGO_CONFIG['gcc'] if IS_PY2: def encode_fs(name): return name if isinstance(name, bytes) else name.encode(IO_ENCODING) else: def encode_fs(name): return name @magics_class class CythonMagics(Magics): def __init__(self, shell): super(CythonMagics, self).__init__(shell) self._reloads = {} self._code_cache = {} self._pyximport_installed = False def _import_all(self, module): mdict = module.__dict__ if '__all__' in mdict: keys = mdict['__all__'] else: keys = [k for k in mdict if not k.startswith('_')] for k in keys: try: self.shell.push({k: mdict[k]}) except KeyError: msg = "'module' object has no attribute '%s'" % k raise AttributeError(msg) @cell_magic def cython_inline(self, line, cell): """Compile and run a Cython code cell using Cython.inline. This magic simply passes the body of the cell to Cython.inline and returns the result. If the variables `a` and `b` are defined in the user's namespace, here is a simple example that returns their sum:: %%cython_inline return a+b For most purposes, we recommend the usage of the `%%cython` magic. """ locs = self.shell.user_global_ns globs = self.shell.user_ns return cython_inline(cell, locals=locs, globals=globs) @cell_magic def cython_pyximport(self, line, cell): """Compile and import a Cython code cell using pyximport. The contents of the cell are written to a `.pyx` file in the current working directory, which is then imported using `pyximport`. This magic requires a module name to be passed:: %%cython_pyximport modulename def f(x): return 2.0*x The compiled module is then imported and all of its symbols are injected into the user's namespace. For most purposes, we recommend the usage of the `%%cython` magic. """ module_name = line.strip() if not module_name: raise ValueError('module name must be given') fname = module_name + '.pyx' with io.open(fname, 'w', encoding='utf-8') as f: f.write(cell) if 'pyximport' not in sys.modules or not self._pyximport_installed: import pyximport pyximport.install() self._pyximport_installed = True if module_name in self._reloads: module = self._reloads[module_name] # Note: reloading extension modules is not actually supported # (requires PEP-489 reinitialisation support). # Don't know why this should ever have worked as it reads here. # All we really need to do is to update the globals below. #reload(module) else: __import__(module_name) module = sys.modules[module_name] self._reloads[module_name] = module self._import_all(module) @magic_arguments.magic_arguments() @magic_arguments.argument( '-a', '--annotate', action='store_const', const='default', dest='annotate', help="Produce a colorized HTML version of the source." ) @magic_arguments.argument( '--annotate-fullc', action='store_const', const='fullc', dest='annotate', help="Produce a colorized HTML version of the source " "which includes entire generated C/C++-code." ) @magic_arguments.argument( '-+', '--cplus', action='store_true', default=False, help="Output a C++ rather than C file." ) @magic_arguments.argument( '-3', dest='language_level', action='store_const', const=3, default=None, help="Select Python 3 syntax." ) @magic_arguments.argument( '-2', dest='language_level', action='store_const', const=2, default=None, help="Select Python 2 syntax." ) @magic_arguments.argument( '-f', '--force', action='store_true', default=False, help="Force the compilation of a new module, even if the source has been " "previously compiled." ) @magic_arguments.argument( '-c', '--compile-args', action='append', default=[], help="Extra flags to pass to compiler via the `extra_compile_args` " "Extension flag (can be specified multiple times)." ) @magic_arguments.argument( '--link-args', action='append', default=[], help="Extra flags to pass to linker via the `extra_link_args` " "Extension flag (can be specified multiple times)." ) @magic_arguments.argument( '-l', '--lib', action='append', default=[], help="Add a library to link the extension against (can be specified " "multiple times)." ) @magic_arguments.argument( '-n', '--name', help="Specify a name for the Cython module." ) @magic_arguments.argument( '-L', dest='library_dirs', metavar='dir', action='append', default=[], help="Add a path to the list of library directories (can be specified " "multiple times)." ) @magic_arguments.argument( '-I', '--include', action='append', default=[], help="Add a path to the list of include directories (can be specified " "multiple times)." ) @magic_arguments.argument( '-S', '--src', action='append', default=[], help="Add a path to the list of src files (can be specified " "multiple times)." ) @magic_arguments.argument( '--pgo', dest='pgo', action='store_true', default=False, help=("Enable profile guided optimisation in the C compiler. " "Compiles the cell twice and executes it in between to generate a runtime profile.") ) @magic_arguments.argument( '--verbose', dest='quiet', action='store_false', default=True, help=("Print debug information like generated .c/.cpp file location " "and exact gcc/g++ command invoked.") ) @cell_magic def cython(self, line, cell): """Compile and import everything from a Cython code cell. The contents of the cell are written to a `.pyx` file in the directory `IPYTHONDIR/cython` using a filename with the hash of the code. This file is then cythonized and compiled. The resulting module is imported and all of its symbols are injected into the user's namespace. The usage is similar to that of `%%cython_pyximport` but you don't have to pass a module name:: %%cython def f(x): return 2.0*x To compile OpenMP codes, pass the required `--compile-args` and `--link-args`. For example with gcc:: %%cython --compile-args=-fopenmp --link-args=-fopenmp ... To enable profile guided optimisation, pass the ``--pgo`` option. Note that the cell itself needs to take care of establishing a suitable profile when executed. This can be done by implementing the functions to optimise, and then calling them directly in the same cell on some realistic training data like this:: %%cython --pgo def critical_function(data): for item in data: ... # execute function several times to build profile from somewhere import some_typical_data for _ in range(100): critical_function(some_typical_data) In Python 3.5 and later, you can distinguish between the profile and non-profile runs as follows:: if "_pgo_" in __name__: ... # execute critical code here """ args = magic_arguments.parse_argstring(self.cython, line) code = cell if cell.endswith('\n') else cell + '\n' lib_dir = os.path.join(get_ipython_cache_dir(), 'cython') key = (code, line, sys.version_info, sys.executable, cython_version) if not os.path.exists(lib_dir): os.makedirs(lib_dir) if args.pgo: key += ('pgo',) if args.force: # Force a new module name by adding the current time to the # key which is hashed to determine the module name. key += (time.time(),) if args.name: module_name = str(args.name) # no-op in Py3 else: module_name = "_cython_magic_" + hashlib.sha1(str(key).encode('utf-8')).hexdigest() html_file = os.path.join(lib_dir, module_name + '.html') module_path = os.path.join(lib_dir, module_name + self.so_ext) have_module = os.path.isfile(module_path) need_cythonize = args.pgo or not have_module if args.annotate: if not os.path.isfile(html_file): need_cythonize = True extension = None if need_cythonize: extensions = self._cythonize(module_name, code, lib_dir, args, quiet=args.quiet) if extensions is None: # Compilation failed and printed error message return None assert len(extensions) == 1 extension = extensions[0] self._code_cache[key] = module_name if args.pgo: self._profile_pgo_wrapper(extension, lib_dir) def print_compiler_output(stdout, stderr, where): # On windows, errors are printed to stdout, we redirect both to sys.stderr. print_captured(stdout, where, u"Content of stdout:\n") print_captured(stderr, where, u"Content of stderr:\n") get_stderr = get_stdout = None try: with captured_fd(1) as get_stdout: with captured_fd(2) as get_stderr: self._build_extension( extension, lib_dir, pgo_step_name='use' if args.pgo else None, quiet=args.quiet) except (distutils.errors.CompileError, distutils.errors.LinkError): # Build failed, print error message from compiler/linker print_compiler_output(get_stdout(), get_stderr(), sys.stderr) return None # Build seems ok, but we might still want to show any warnings that occurred print_compiler_output(get_stdout(), get_stderr(), sys.stdout) module = load_dynamic(module_name, module_path) self._import_all(module) if args.annotate: try: with io.open(html_file, encoding='utf-8') as f: annotated_html = f.read() except IOError as e: # File could not be opened. Most likely the user has a version # of Cython before 0.15.1 (when `cythonize` learned the # `force` keyword argument) and has already compiled this # exact source without annotation. print('Cython completed successfully but the annotated ' 'source could not be read.', file=sys.stderr) print(e, file=sys.stderr) else: return display.HTML(self.clean_annotated_html(annotated_html)) def _profile_pgo_wrapper(self, extension, lib_dir): """ Generate a .c file for a separate extension module that calls the module init function of the original module. This makes sure that the PGO profiler sees the correct .o file of the final module, but it still allows us to import the module under a different name for profiling, before recompiling it into the PGO optimised module. Overwriting and reimporting the same shared library is not portable. """ extension = copy.copy(extension) # shallow copy, do not modify sources in place! module_name = extension.name pgo_module_name = '_pgo_' + module_name pgo_wrapper_c_file = os.path.join(lib_dir, pgo_module_name + '.c') with io.open(pgo_wrapper_c_file, 'w', encoding='utf-8') as f: f.write(textwrap.dedent(u""" #include "Python.h" #if PY_MAJOR_VERSION < 3 extern PyMODINIT_FUNC init%(module_name)s(void); PyMODINIT_FUNC init%(pgo_module_name)s(void); /*proto*/ PyMODINIT_FUNC init%(pgo_module_name)s(void) { PyObject *sys_modules; init%(module_name)s(); if (PyErr_Occurred()) return; sys_modules = PyImport_GetModuleDict(); /* borrowed, no exception, "never" fails */ if (sys_modules) { PyObject *module = PyDict_GetItemString(sys_modules, "%(module_name)s"); if (!module) return; PyDict_SetItemString(sys_modules, "%(pgo_module_name)s", module); Py_DECREF(module); } } #else extern PyMODINIT_FUNC PyInit_%(module_name)s(void); PyMODINIT_FUNC PyInit_%(pgo_module_name)s(void); /*proto*/ PyMODINIT_FUNC PyInit_%(pgo_module_name)s(void) { return PyInit_%(module_name)s(); } #endif """ % {'module_name': module_name, 'pgo_module_name': pgo_module_name})) extension.sources = extension.sources + [pgo_wrapper_c_file] # do not modify in place! extension.name = pgo_module_name self._build_extension(extension, lib_dir, pgo_step_name='gen') # import and execute module code to generate profile so_module_path = os.path.join(lib_dir, pgo_module_name + self.so_ext) load_dynamic(pgo_module_name, so_module_path) def _cythonize(self, module_name, code, lib_dir, args, quiet=True): pyx_file = os.path.join(lib_dir, module_name + '.pyx') pyx_file = encode_fs(pyx_file) c_include_dirs = args.include c_src_files = list(map(str, args.src)) if 'numpy' in code: import numpy c_include_dirs.append(numpy.get_include()) with io.open(pyx_file, 'w', encoding='utf-8') as f: f.write(code) extension = Extension( name=module_name, sources=[pyx_file] + c_src_files, include_dirs=c_include_dirs, library_dirs=args.library_dirs, extra_compile_args=args.compile_args, extra_link_args=args.link_args, libraries=args.lib, language='c++' if args.cplus else 'c', ) try: opts = dict( quiet=quiet, annotate=args.annotate, force=True, language_level=min(3, sys.version_info[0]), ) if args.language_level is not None: assert args.language_level in (2, 3) opts['language_level'] = args.language_level return cythonize([extension], **opts) except CompileError: return None def _build_extension(self, extension, lib_dir, temp_dir=None, pgo_step_name=None, quiet=True): build_extension = self._get_build_extension( extension, lib_dir=lib_dir, temp_dir=temp_dir, pgo_step_name=pgo_step_name) old_threshold = None try: if not quiet: old_threshold = distutils.log.set_threshold(distutils.log.DEBUG) build_extension.run() finally: if not quiet and old_threshold is not None: distutils.log.set_threshold(old_threshold) def _add_pgo_flags(self, build_extension, step_name, temp_dir): compiler_type = build_extension.compiler.compiler_type if compiler_type == 'unix': compiler_cmd = build_extension.compiler.compiler_so # TODO: we could try to call "[cmd] --version" for better insights if not compiler_cmd: pass elif 'clang' in compiler_cmd or 'clang' in compiler_cmd[0]: compiler_type = 'clang' elif 'icc' in compiler_cmd or 'icc' in compiler_cmd[0]: compiler_type = 'icc' elif 'gcc' in compiler_cmd or 'gcc' in compiler_cmd[0]: compiler_type = 'gcc' elif 'g++' in compiler_cmd or 'g++' in compiler_cmd[0]: compiler_type = 'gcc' config = PGO_CONFIG.get(compiler_type) orig_flags = [] if config and step_name in config: flags = [f.format(TEMPDIR=temp_dir) for f in config[step_name]] for extension in build_extension.extensions: orig_flags.append((extension.extra_compile_args, extension.extra_link_args)) extension.extra_compile_args = extension.extra_compile_args + flags extension.extra_link_args = extension.extra_link_args + flags else: print("No PGO %s configuration known for C compiler type '%s'" % (step_name, compiler_type), file=sys.stderr) return orig_flags @property def so_ext(self): """The extension suffix for compiled modules.""" try: return self._so_ext except AttributeError: self._so_ext = self._get_build_extension().get_ext_filename('') return self._so_ext def _clear_distutils_mkpath_cache(self): """clear distutils mkpath cache prevents distutils from skipping re-creation of dirs that have been removed """ try: from distutils.dir_util import _path_created except ImportError: pass else: _path_created.clear() def _get_build_extension(self, extension=None, lib_dir=None, temp_dir=None, pgo_step_name=None, _build_ext=build_ext): self._clear_distutils_mkpath_cache() dist = Distribution() config_files = dist.find_config_files() try: config_files.remove('setup.cfg') except ValueError: pass dist.parse_config_files(config_files) if not temp_dir: temp_dir = lib_dir add_pgo_flags = self._add_pgo_flags if pgo_step_name: base_build_ext = _build_ext class _build_ext(_build_ext): def build_extensions(self): add_pgo_flags(self, pgo_step_name, temp_dir) base_build_ext.build_extensions(self) build_extension = _build_ext(dist) build_extension.finalize_options() if temp_dir: temp_dir = encode_fs(temp_dir) build_extension.build_temp = temp_dir if lib_dir: lib_dir = encode_fs(lib_dir) build_extension.build_lib = lib_dir if extension is not None: build_extension.extensions = [extension] return build_extension @staticmethod def clean_annotated_html(html): """Clean up the annotated HTML source. Strips the link to the generated C or C++ file, which we do not present to the user. """ r = re.compile('

Raw output: (.*)') html = '\n'.join(l for l in html.splitlines() if not r.match(l)) return html __doc__ = __doc__.format( # rST doesn't see the -+ flag as part of an option list, so we # hide it from the module-level docstring. CYTHON_DOC=dedent(CythonMagics.cython.__doc__\ .replace('-+, --cplus', '--cplus ')), CYTHON_INLINE_DOC=dedent(CythonMagics.cython_inline.__doc__), CYTHON_PYXIMPORT_DOC=dedent(CythonMagics.cython_pyximport.__doc__), ) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880490.992724 Cython-3.0.8/Cython/Build/Tests/0000755000175100001770000000000000000000000017201 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3087223 Cython-3.0.8/Cython/Build/Tests/TestCyCache.py0000644000175100001770000001107000000000000021711 0ustar00runnerdocker00000000000000import difflib import glob import gzip import os import sys import tempfile import unittest import Cython.Build.Dependencies import Cython.Utils from Cython.TestUtils import CythonTest class TestCyCache(CythonTest): def setUp(self): CythonTest.setUp(self) self.temp_dir = tempfile.mkdtemp( prefix='cycache-test', dir='TEST_TMP' if os.path.isdir('TEST_TMP') else None) self.src_dir = tempfile.mkdtemp(prefix='src', dir=self.temp_dir) self.cache_dir = tempfile.mkdtemp(prefix='cache', dir=self.temp_dir) def cache_files(self, file_glob): return glob.glob(os.path.join(self.cache_dir, file_glob)) def fresh_cythonize(self, *args, **kwargs): Cython.Utils.clear_function_caches() Cython.Build.Dependencies._dep_tree = None # discard method caches Cython.Build.Dependencies.cythonize(*args, **kwargs) def test_cycache_switch(self): content1 = 'value = 1\n' content2 = 'value = 2\n' a_pyx = os.path.join(self.src_dir, 'a.pyx') a_c = a_pyx[:-4] + '.c' with open(a_pyx, 'w') as f: f.write(content1) self.fresh_cythonize(a_pyx, cache=self.cache_dir) self.fresh_cythonize(a_pyx, cache=self.cache_dir) self.assertEqual(1, len(self.cache_files('a.c*'))) with open(a_c) as f: a_contents1 = f.read() os.unlink(a_c) with open(a_pyx, 'w') as f: f.write(content2) self.fresh_cythonize(a_pyx, cache=self.cache_dir) with open(a_c) as f: a_contents2 = f.read() os.unlink(a_c) self.assertNotEqual(a_contents1, a_contents2, 'C file not changed!') self.assertEqual(2, len(self.cache_files('a.c*'))) with open(a_pyx, 'w') as f: f.write(content1) self.fresh_cythonize(a_pyx, cache=self.cache_dir) self.assertEqual(2, len(self.cache_files('a.c*'))) with open(a_c) as f: a_contents = f.read() self.assertEqual( a_contents, a_contents1, msg='\n'.join(list(difflib.unified_diff( a_contents.split('\n'), a_contents1.split('\n')))[:10])) @unittest.skipIf(sys.version_info[:2] == (3, 12) and sys.platform == "win32", "This test is mysteriously broken on Windows on the CI only " "(https://github.com/cython/cython/issues/5825)") def test_cycache_uses_cache(self): a_pyx = os.path.join(self.src_dir, 'a.pyx') a_c = a_pyx[:-4] + '.c' with open(a_pyx, 'w') as f: f.write('pass') self.fresh_cythonize(a_pyx, cache=self.cache_dir) a_cache = os.path.join(self.cache_dir, os.listdir(self.cache_dir)[0]) gzip.GzipFile(a_cache, 'wb').write('fake stuff'.encode('ascii')) os.unlink(a_c) self.fresh_cythonize(a_pyx, cache=self.cache_dir) with open(a_c) as f: a_contents = f.read() self.assertEqual(a_contents, 'fake stuff', 'Unexpected contents: %s...' % a_contents[:100]) def test_multi_file_output(self): a_pyx = os.path.join(self.src_dir, 'a.pyx') a_c = a_pyx[:-4] + '.c' a_h = a_pyx[:-4] + '.h' a_api_h = a_pyx[:-4] + '_api.h' with open(a_pyx, 'w') as f: f.write('cdef public api int foo(int x): return x\n') self.fresh_cythonize(a_pyx, cache=self.cache_dir) expected = [a_c, a_h, a_api_h] for output in expected: self.assertTrue(os.path.exists(output), output) os.unlink(output) self.fresh_cythonize(a_pyx, cache=self.cache_dir) for output in expected: self.assertTrue(os.path.exists(output), output) def test_options_invalidation(self): hash_pyx = os.path.join(self.src_dir, 'options.pyx') hash_c = hash_pyx[:-len('.pyx')] + '.c' with open(hash_pyx, 'w') as f: f.write('pass') self.fresh_cythonize(hash_pyx, cache=self.cache_dir, cplus=False) self.assertEqual(1, len(self.cache_files('options.c*'))) os.unlink(hash_c) self.fresh_cythonize(hash_pyx, cache=self.cache_dir, cplus=True) self.assertEqual(2, len(self.cache_files('options.c*'))) os.unlink(hash_c) self.fresh_cythonize(hash_pyx, cache=self.cache_dir, cplus=False, show_version=False) self.assertEqual(2, len(self.cache_files('options.c*'))) os.unlink(hash_c) self.fresh_cythonize(hash_pyx, cache=self.cache_dir, cplus=False, show_version=True) self.assertEqual(2, len(self.cache_files('options.c*'))) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3087223 Cython-3.0.8/Cython/Build/Tests/TestCythonizeArgsParser.py0000644000175100001770000004757200000000000024400 0ustar00runnerdocker00000000000000from Cython.Build.Cythonize import ( create_args_parser, parse_args_raw, parse_args, parallel_compiles ) from Cython.Compiler import Options from Cython.Compiler.Tests.Utils import backup_Options, restore_Options, check_global_options from unittest import TestCase import sys try: from StringIO import StringIO except ImportError: from io import StringIO # doesn't accept 'str' in Py2 class TestCythonizeArgsParser(TestCase): def setUp(self): TestCase.setUp(self) self.parse_args = lambda x, parser=create_args_parser() : parse_args_raw(parser, x) def are_default(self, options, skip): # empty containers empty_containers = ['directives', 'compile_time_env', 'options', 'excludes'] are_none = ['language_level', 'annotate', 'build', 'build_inplace', 'force', 'quiet', 'lenient', 'keep_going', 'no_docstrings'] for opt_name in empty_containers: if len(getattr(options, opt_name))!=0 and (opt_name not in skip): self.assertEqual(opt_name,"", msg="For option "+opt_name) return False for opt_name in are_none: if (getattr(options, opt_name) is not None) and (opt_name not in skip): self.assertEqual(opt_name,"", msg="For option "+opt_name) return False if options.parallel!=parallel_compiles and ('parallel' not in skip): return False return True # testing directives: def test_directive_short(self): options, args = self.parse_args(['-X', 'cdivision=True']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['directives'])) self.assertEqual(options.directives['cdivision'], True) def test_directive_long(self): options, args = self.parse_args(['--directive', 'cdivision=True']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['directives'])) self.assertEqual(options.directives['cdivision'], True) def test_directive_multiple(self): options, args = self.parse_args(['-X', 'cdivision=True', '-X', 'c_string_type=bytes']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['directives'])) self.assertEqual(options.directives['cdivision'], True) self.assertEqual(options.directives['c_string_type'], 'bytes') def test_directive_multiple_v2(self): options, args = self.parse_args(['-X', 'cdivision=True,c_string_type=bytes']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['directives'])) self.assertEqual(options.directives['cdivision'], True) self.assertEqual(options.directives['c_string_type'], 'bytes') def test_directive_value_yes(self): options, args = self.parse_args(['-X', 'cdivision=YeS']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['directives'])) self.assertEqual(options.directives['cdivision'], True) def test_directive_value_no(self): options, args = self.parse_args(['-X', 'cdivision=no']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['directives'])) self.assertEqual(options.directives['cdivision'], False) def test_directive_value_invalid(self): with self.assertRaises(ValueError) as context: options, args = self.parse_args(['-X', 'cdivision=sadfasd']) def test_directive_key_invalid(self): with self.assertRaises(ValueError) as context: options, args = self.parse_args(['-X', 'abracadabra']) def test_directive_no_value(self): with self.assertRaises(ValueError) as context: options, args = self.parse_args(['-X', 'cdivision']) def test_directives_types(self): directives = { 'auto_pickle': True, 'c_string_type': 'bytearray', 'c_string_type': 'bytes', 'c_string_type': 'str', 'c_string_type': 'bytearray', 'c_string_type': 'unicode', 'c_string_encoding' : 'ascii', 'language_level' : 2, 'language_level' : 3, 'language_level' : '3str', 'set_initial_path' : 'my_initial_path', } for key, value in directives.items(): cmd = '{key}={value}'.format(key=key, value=str(value)) options, args = self.parse_args(['-X', cmd]) self.assertFalse(args) self.assertTrue(self.are_default(options, ['directives']), msg = "Error for option: "+cmd) self.assertEqual(options.directives[key], value, msg = "Error for option: "+cmd) def test_directives_wrong(self): directives = { 'auto_pickle': 42, # for bool type 'auto_pickle': 'NONONO', # for bool type 'c_string_type': 'bites', #'c_string_encoding' : 'a', #'language_level' : 4, } for key, value in directives.items(): cmd = '{key}={value}'.format(key=key, value=str(value)) with self.assertRaises(ValueError, msg = "Error for option: "+cmd) as context: options, args = self.parse_args(['-X', cmd]) def test_compile_time_env_short(self): options, args = self.parse_args(['-E', 'MYSIZE=10']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['compile_time_env'])) self.assertEqual(options.compile_time_env['MYSIZE'], 10) def test_compile_time_env_long(self): options, args = self.parse_args(['--compile-time-env', 'MYSIZE=10']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['compile_time_env'])) self.assertEqual(options.compile_time_env['MYSIZE'], 10) def test_compile_time_env_multiple(self): options, args = self.parse_args(['-E', 'MYSIZE=10', '-E', 'ARRSIZE=11']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['compile_time_env'])) self.assertEqual(options.compile_time_env['MYSIZE'], 10) self.assertEqual(options.compile_time_env['ARRSIZE'], 11) def test_compile_time_env_multiple_v2(self): options, args = self.parse_args(['-E', 'MYSIZE=10,ARRSIZE=11']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['compile_time_env'])) self.assertEqual(options.compile_time_env['MYSIZE'], 10) self.assertEqual(options.compile_time_env['ARRSIZE'], 11) #testing options def test_option_short(self): options, args = self.parse_args(['-s', 'docstrings=True']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['options'])) self.assertEqual(options.options['docstrings'], True) def test_option_long(self): options, args = self.parse_args(['--option', 'docstrings=True']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['options'])) self.assertEqual(options.options['docstrings'], True) def test_option_multiple(self): options, args = self.parse_args(['-s', 'docstrings=True', '-s', 'buffer_max_dims=8']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['options'])) self.assertEqual(options.options['docstrings'], True) self.assertEqual(options.options['buffer_max_dims'], True) # really? def test_option_multiple_v2(self): options, args = self.parse_args(['-s', 'docstrings=True,buffer_max_dims=8']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['options'])) self.assertEqual(options.options['docstrings'], True) self.assertEqual(options.options['buffer_max_dims'], True) # really? def test_option_value_yes(self): options, args = self.parse_args(['-s', 'docstrings=YeS']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['options'])) self.assertEqual(options.options['docstrings'], True) def test_option_value_4242(self): options, args = self.parse_args(['-s', 'docstrings=4242']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['options'])) self.assertEqual(options.options['docstrings'], True) def test_option_value_0(self): options, args = self.parse_args(['-s', 'docstrings=0']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['options'])) self.assertEqual(options.options['docstrings'], False) def test_option_value_emptystr(self): options, args = self.parse_args(['-s', 'docstrings=']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['options'])) self.assertEqual(options.options['docstrings'], True) def test_option_value_a_str(self): options, args = self.parse_args(['-s', 'docstrings=BB']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['options'])) self.assertEqual(options.options['docstrings'], True) def test_option_value_no(self): options, args = self.parse_args(['-s', 'docstrings=nO']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['options'])) self.assertEqual(options.options['docstrings'], False) def test_option_no_value(self): options, args = self.parse_args(['-s', 'docstrings']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['options'])) self.assertEqual(options.options['docstrings'], True) def test_option_any_key(self): options, args = self.parse_args(['-s', 'abracadabra']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['options'])) self.assertEqual(options.options['abracadabra'], True) def test_language_level_2(self): options, args = self.parse_args(['-2']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['language_level'])) self.assertEqual(options.language_level, 2) def test_language_level_3(self): options, args = self.parse_args(['-3']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['language_level'])) self.assertEqual(options.language_level, 3) def test_language_level_3str(self): options, args = self.parse_args(['--3str']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['language_level'])) self.assertEqual(options.language_level, '3str') def test_annotate_short(self): options, args = self.parse_args(['-a']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['annotate'])) self.assertEqual(options.annotate, 'default') def test_annotate_long(self): options, args = self.parse_args(['--annotate']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['annotate'])) self.assertEqual(options.annotate, 'default') def test_annotate_fullc(self): options, args = self.parse_args(['--annotate-fullc']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['annotate'])) self.assertEqual(options.annotate, 'fullc') def test_annotate_and_positional(self): options, args = self.parse_args(['-a', 'foo.pyx']) self.assertEqual(args, ['foo.pyx']) self.assertTrue(self.are_default(options, ['annotate'])) self.assertEqual(options.annotate, 'default') def test_annotate_and_optional(self): options, args = self.parse_args(['-a', '--3str']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['annotate', 'language_level'])) self.assertEqual(options.annotate, 'default') self.assertEqual(options.language_level, '3str') def test_exclude_short(self): options, args = self.parse_args(['-x', '*.pyx']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['excludes'])) self.assertTrue('*.pyx' in options.excludes) def test_exclude_long(self): options, args = self.parse_args(['--exclude', '*.pyx']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['excludes'])) self.assertTrue('*.pyx' in options.excludes) def test_exclude_multiple(self): options, args = self.parse_args(['--exclude', '*.pyx', '--exclude', '*.py', ]) self.assertFalse(args) self.assertTrue(self.are_default(options, ['excludes'])) self.assertEqual(options.excludes, ['*.pyx', '*.py']) def test_build_short(self): options, args = self.parse_args(['-b']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['build'])) self.assertEqual(options.build, True) def test_build_long(self): options, args = self.parse_args(['--build']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['build'])) self.assertEqual(options.build, True) def test_inplace_short(self): options, args = self.parse_args(['-i']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['build_inplace'])) self.assertEqual(options.build_inplace, True) def test_inplace_long(self): options, args = self.parse_args(['--inplace']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['build_inplace'])) self.assertEqual(options.build_inplace, True) def test_parallel_short(self): options, args = self.parse_args(['-j', '42']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['parallel'])) self.assertEqual(options.parallel, 42) def test_parallel_long(self): options, args = self.parse_args(['--parallel', '42']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['parallel'])) self.assertEqual(options.parallel, 42) def test_force_short(self): options, args = self.parse_args(['-f']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['force'])) self.assertEqual(options.force, True) def test_force_long(self): options, args = self.parse_args(['--force']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['force'])) self.assertEqual(options.force, True) def test_quite_short(self): options, args = self.parse_args(['-q']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['quiet'])) self.assertEqual(options.quiet, True) def test_quite_long(self): options, args = self.parse_args(['--quiet']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['quiet'])) self.assertEqual(options.quiet, True) def test_lenient_long(self): options, args = self.parse_args(['--lenient']) self.assertTrue(self.are_default(options, ['lenient'])) self.assertFalse(args) self.assertEqual(options.lenient, True) def test_keep_going_short(self): options, args = self.parse_args(['-k']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['keep_going'])) self.assertEqual(options.keep_going, True) def test_keep_going_long(self): options, args = self.parse_args(['--keep-going']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['keep_going'])) self.assertEqual(options.keep_going, True) def test_no_docstrings_long(self): options, args = self.parse_args(['--no-docstrings']) self.assertFalse(args) self.assertTrue(self.are_default(options, ['no_docstrings'])) self.assertEqual(options.no_docstrings, True) def test_file_name(self): options, args = self.parse_args(['file1.pyx', 'file2.pyx']) self.assertEqual(len(args), 2) self.assertEqual(args[0], 'file1.pyx') self.assertEqual(args[1], 'file2.pyx') self.assertTrue(self.are_default(options, [])) def test_option_first(self): options, args = self.parse_args(['-i', 'file.pyx']) self.assertEqual(args, ['file.pyx']) self.assertEqual(options.build_inplace, True) self.assertTrue(self.are_default(options, ['build_inplace'])) def test_file_inbetween(self): options, args = self.parse_args(['-i', 'file.pyx', '-a']) self.assertEqual(args, ['file.pyx']) self.assertEqual(options.build_inplace, True) self.assertEqual(options.annotate, 'default') self.assertTrue(self.are_default(options, ['build_inplace', 'annotate'])) def test_option_trailing(self): options, args = self.parse_args(['file.pyx', '-i']) self.assertEqual(args, ['file.pyx']) self.assertEqual(options.build_inplace, True) self.assertTrue(self.are_default(options, ['build_inplace'])) def test_interspersed_positional(self): options, sources = self.parse_args([ 'file1.pyx', '-a', 'file2.pyx' ]) self.assertEqual(sources, ['file1.pyx', 'file2.pyx']) self.assertEqual(options.annotate, 'default') self.assertTrue(self.are_default(options, ['annotate'])) def test_interspersed_positional2(self): options, sources = self.parse_args([ 'file1.pyx', '-a', 'file2.pyx', '-a', 'file3.pyx' ]) self.assertEqual(sources, ['file1.pyx', 'file2.pyx', 'file3.pyx']) self.assertEqual(options.annotate, 'default') self.assertTrue(self.are_default(options, ['annotate'])) def test_interspersed_positional3(self): options, sources = self.parse_args([ '-f', 'f1', 'f2', '-a', 'f3', 'f4', '-a', 'f5' ]) self.assertEqual(sources, ['f1', 'f2', 'f3', 'f4', 'f5']) self.assertEqual(options.annotate, 'default') self.assertEqual(options.force, True) self.assertTrue(self.are_default(options, ['annotate', 'force'])) def test_wrong_option(self): old_stderr = sys.stderr stderr = sys.stderr = StringIO() try: self.assertRaises(SystemExit, self.parse_args, ['--unknown-option'] ) finally: sys.stderr = old_stderr self.assertTrue(stderr.getvalue()) class TestParseArgs(TestCase): def setUp(self): self._options_backup = backup_Options() def tearDown(self): restore_Options(self._options_backup) def check_default_global_options(self, white_list=[]): self.assertEqual(check_global_options(self._options_backup, white_list), "") def test_build_set_for_inplace(self): options, args = parse_args(['foo.pyx', '-i']) self.assertEqual(options.build, True) self.check_default_global_options() def test_lenient(self): options, sources = parse_args(['foo.pyx', '--lenient']) self.assertEqual(sources, ['foo.pyx']) self.assertEqual(Options.error_on_unknown_names, False) self.assertEqual(Options.error_on_uninitialized, False) self.check_default_global_options(['error_on_unknown_names', 'error_on_uninitialized']) def test_annotate(self): options, sources = parse_args(['foo.pyx', '--annotate']) self.assertEqual(sources, ['foo.pyx']) self.assertEqual(Options.annotate, 'default') self.check_default_global_options(['annotate']) def test_annotate_fullc(self): options, sources = parse_args(['foo.pyx', '--annotate-fullc']) self.assertEqual(sources, ['foo.pyx']) self.assertEqual(Options.annotate, 'fullc') self.check_default_global_options(['annotate']) def test_no_docstrings(self): options, sources = parse_args(['foo.pyx', '--no-docstrings']) self.assertEqual(sources, ['foo.pyx']) self.assertEqual(Options.docstrings, False) self.check_default_global_options(['docstrings']) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3087223 Cython-3.0.8/Cython/Build/Tests/TestDependencies.py0000644000175100001770000001331300000000000023002 0ustar00runnerdocker00000000000000import contextlib import os.path import sys import tempfile import unittest from io import open from os.path import join as pjoin from ..Dependencies import extended_iglob @contextlib.contextmanager def writable_file(dir_path, filename): with open(pjoin(dir_path, filename), "w", encoding="utf8") as f: yield f class TestGlobbing(unittest.TestCase): @classmethod def setUpClass(cls): cls._orig_dir = os.getcwd() if sys.version_info[0] < 3: temp_path = cls._tmpdir = tempfile.mkdtemp() else: cls._tmpdir = tempfile.TemporaryDirectory() temp_path = cls._tmpdir.name os.chdir(temp_path) for dir1 in "abcd": for dir1x in [dir1, dir1 + 'x']: for dir2 in "xyz": dir_path = pjoin(dir1x, dir2) os.makedirs(dir_path) with writable_file(dir_path, "file2_pyx.pyx") as f: f.write(u'""" PYX """') with writable_file(dir_path, "file2_py.py") as f: f.write(u'""" PY """') with writable_file(dir1x, "file1_pyx.pyx") as f: f.write(u'""" PYX """') with writable_file(dir1x, "file1_py.py") as f: f.write(u'""" PY """') @classmethod def tearDownClass(cls): os.chdir(cls._orig_dir) if sys.version_info[0] < 3: import shutil shutil.rmtree(cls._tmpdir) else: cls._tmpdir.cleanup() def files_equal(self, pattern, expected_files): expected_files = sorted(expected_files) # It's the users's choice whether '/' will appear on Windows. matched_files = sorted(path.replace('/', os.sep) for path in extended_iglob(pattern)) self.assertListEqual(matched_files, expected_files) # / # Special case for Windows: also support '\' in patterns. if os.sep == '\\' and '/' in pattern: matched_files = sorted(extended_iglob(pattern.replace('/', '\\'))) self.assertListEqual(matched_files, expected_files) # \ def test_extended_iglob_simple(self): ax_files = [pjoin("a", "x", "file2_pyx.pyx"), pjoin("a", "x", "file2_py.py")] self.files_equal("a/x/*", ax_files) self.files_equal("a/x/*.c12", []) self.files_equal("a/x/*.{py,pyx,c12}", ax_files) self.files_equal("a/x/*.{py,pyx}", ax_files) self.files_equal("a/x/*.{pyx}", ax_files[:1]) self.files_equal("a/x/*.pyx", ax_files[:1]) self.files_equal("a/x/*.{py}", ax_files[1:]) self.files_equal("a/x/*.py", ax_files[1:]) def test_extended_iglob_simple_star(self): for basedir in "ad": files = [ pjoin(basedir, dirname, filename) for dirname in "xyz" for filename in ["file2_pyx.pyx", "file2_py.py"] ] self.files_equal(basedir + "/*/*", files) self.files_equal(basedir + "/*/*.c12", []) self.files_equal(basedir + "/*/*.{py,pyx,c12}", files) self.files_equal(basedir + "/*/*.{py,pyx}", files) self.files_equal(basedir + "/*/*.{pyx}", files[::2]) self.files_equal(basedir + "/*/*.pyx", files[::2]) self.files_equal(basedir + "/*/*.{py}", files[1::2]) self.files_equal(basedir + "/*/*.py", files[1::2]) for subdir in "xy*": files = [ pjoin(basedir, dirname, filename) for dirname in "xyz" if subdir in ('*', dirname) for filename in ["file2_pyx.pyx", "file2_py.py"] ] path = basedir + '/' + subdir + '/' self.files_equal(path + "*", files) self.files_equal(path + "*.{py,pyx}", files) self.files_equal(path + "*.{pyx}", files[::2]) self.files_equal(path + "*.pyx", files[::2]) self.files_equal(path + "*.{py}", files[1::2]) self.files_equal(path + "*.py", files[1::2]) def test_extended_iglob_double_star(self): basedirs = os.listdir(".") files = [ pjoin(basedir, dirname, filename) for basedir in basedirs for dirname in "xyz" for filename in ["file2_pyx.pyx", "file2_py.py"] ] all_files = [ pjoin(basedir, filename) for basedir in basedirs for filename in ["file1_pyx.pyx", "file1_py.py"] ] + files self.files_equal("*/*/*", files) self.files_equal("*/*/**/*", files) self.files_equal("*/**/*.*", all_files) self.files_equal("**/*.*", all_files) self.files_equal("*/**/*.c12", []) self.files_equal("**/*.c12", []) self.files_equal("*/*/*.{py,pyx,c12}", files) self.files_equal("*/*/**/*.{py,pyx,c12}", files) self.files_equal("*/**/*/*.{py,pyx,c12}", files) self.files_equal("**/*/*/*.{py,pyx,c12}", files) self.files_equal("**/*.{py,pyx,c12}", all_files) self.files_equal("*/*/*.{py,pyx}", files) self.files_equal("**/*/*/*.{py,pyx}", files) self.files_equal("*/**/*/*.{py,pyx}", files) self.files_equal("**/*.{py,pyx}", all_files) self.files_equal("*/*/*.{pyx}", files[::2]) self.files_equal("**/*.{pyx}", all_files[::2]) self.files_equal("*/**/*/*.pyx", files[::2]) self.files_equal("*/*/*.pyx", files[::2]) self.files_equal("**/*.pyx", all_files[::2]) self.files_equal("*/*/*.{py}", files[1::2]) self.files_equal("**/*.{py}", all_files[1::2]) self.files_equal("*/*/*.py", files[1::2]) self.files_equal("**/*.py", all_files[1::2]) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3087223 Cython-3.0.8/Cython/Build/Tests/TestInline.py0000644000175100001770000000663700000000000021645 0ustar00runnerdocker00000000000000import os import tempfile import unittest from Cython.Shadow import inline from Cython.Build.Inline import safe_type from Cython.TestUtils import CythonTest try: import numpy has_numpy = True except: has_numpy = False test_kwds = dict(force=True, quiet=True) global_value = 100 class TestInline(CythonTest): def setUp(self): CythonTest.setUp(self) self._call_kwds = dict(test_kwds) if os.path.isdir('TEST_TMP'): lib_dir = os.path.join('TEST_TMP','inline') else: lib_dir = tempfile.mkdtemp(prefix='cython_inline_') self._call_kwds['lib_dir'] = lib_dir def test_simple(self): self.assertEqual(inline("return 1+2", **self._call_kwds), 3) def test_types(self): self.assertEqual(inline(""" cimport cython return cython.typeof(a), cython.typeof(b) """, a=1.0, b=[], **self._call_kwds), ('double', 'list object')) def test_locals(self): a = 1 b = 2 self.assertEqual(inline("return a+b", **self._call_kwds), 3) def test_globals(self): self.assertEqual(inline("return global_value + 1", **self._call_kwds), global_value + 1) def test_no_return(self): self.assertEqual(inline(""" a = 1 cdef double b = 2 cdef c = [] """, **self._call_kwds), dict(a=1, b=2.0, c=[])) def test_def_node(self): foo = inline("def foo(x): return x * x", **self._call_kwds)['foo'] self.assertEqual(foo(7), 49) def test_class_ref(self): class Type(object): pass tp = inline("Type")['Type'] self.assertEqual(tp, Type) def test_pure(self): import cython as cy b = inline(""" b = cy.declare(float, a) c = cy.declare(cy.pointer(cy.float), &b) return b """, a=3, **self._call_kwds) self.assertEqual(type(b), float) def test_compiler_directives(self): self.assertEqual( inline('return sum(x)', x=[1, 2, 3], cython_compiler_directives={'boundscheck': False}), 6 ) def test_lang_version(self): # GH-3419. Caching for inline code didn't always respect compiler directives. inline_divcode = "def f(int a, int b): return a/b" self.assertEqual( inline(inline_divcode, language_level=2)['f'](5,2), 2 ) self.assertEqual( inline(inline_divcode, language_level=3)['f'](5,2), 2.5 ) self.assertEqual( inline(inline_divcode, language_level=2)['f'](5,2), 2 ) def test_repeated_use(self): inline_mulcode = "def f(int a, int b): return a * b" self.assertEqual(inline(inline_mulcode)['f'](5, 2), 10) self.assertEqual(inline(inline_mulcode)['f'](5, 3), 15) self.assertEqual(inline(inline_mulcode)['f'](6, 2), 12) self.assertEqual(inline(inline_mulcode)['f'](5, 2), 10) f = inline(inline_mulcode)['f'] self.assertEqual(f(5, 2), 10) self.assertEqual(f(5, 3), 15) @unittest.skipIf(not has_numpy, "NumPy is not available") def test_numpy(self): import numpy a = numpy.ndarray((10, 20)) a[0,0] = 10 self.assertEqual(safe_type(a), 'numpy.ndarray[numpy.float64_t, ndim=2]') self.assertEqual(inline("return a[0,0]", a=a, **self._call_kwds), 10.0) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Build/Tests/TestIpythonMagic.py0000644000175100001770000002230300000000000023006 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*- # tag: ipython """Tests for the Cython magics extension.""" from __future__ import absolute_import import os import io import sys from contextlib import contextmanager from unittest import skipIf from Cython.Build import IpythonMagic from Cython.TestUtils import CythonTest from Cython.Compiler.Annotate import AnnotationCCodeWriter try: import IPython.testing.globalipapp except ImportError: # Disable tests and fake helpers for initialisation below. def skip_if_not_installed(_): return None else: def skip_if_not_installed(c): return c # not using IPython's decorators here because they depend on "nose" skip_win32 = skipIf(sys.platform == 'win32', "Skip on Windows") skip_py27 = skipIf(sys.version_info[:2] == (2,7), "Disabled in Py2.7") try: # disable IPython history thread before it gets started to avoid having to clean it up from IPython.core.history import HistoryManager HistoryManager.enabled = False except ImportError: pass @contextmanager def capture_output(): backup = sys.stdout, sys.stderr try: replacement = [ io.TextIOWrapper(io.BytesIO(), encoding=sys.stdout.encoding), io.TextIOWrapper(io.BytesIO(), encoding=sys.stderr.encoding), ] sys.stdout, sys.stderr = replacement output = [] yield output finally: sys.stdout, sys.stderr = backup for wrapper in replacement: wrapper.seek(0) # rewind output.append(wrapper.read()) wrapper.close() code = u"""\ def f(x): return 2*x """ cython3_code = u"""\ def f(int x): return 2 / x def call(x): return f(*(x,)) """ pgo_cython3_code = cython3_code + u"""\ def main(): for _ in range(100): call(5) main() """ compile_error_code = u'''\ cdef extern from *: """ xxx a=1; """ int a; def doit(): return a ''' compile_warning_code = u'''\ cdef extern from *: """ #pragma message ( "CWarning" ) int a = 42; """ int a; def doit(): return a ''' @skip_if_not_installed class TestIPythonMagic(CythonTest): @classmethod def setUpClass(cls): CythonTest.setUpClass() cls._ip = IPython.testing.globalipapp.get_ipython() def setUp(self): CythonTest.setUp(self) self._ip.extension_manager.load_extension('cython') def test_cython_inline(self): ip = self._ip ip.ex('a=10; b=20') result = ip.run_cell_magic('cython_inline', '', 'return a+b') self.assertEqual(result, 30) @skip_win32 def test_cython_pyximport(self): ip = self._ip module_name = '_test_cython_pyximport' ip.run_cell_magic('cython_pyximport', module_name, code) ip.ex('g = f(10)') self.assertEqual(ip.user_ns['g'], 20.0) ip.run_cell_magic('cython_pyximport', module_name, code) ip.ex('h = f(-10)') self.assertEqual(ip.user_ns['h'], -20.0) try: os.remove(module_name + '.pyx') except OSError: pass def test_cython(self): ip = self._ip ip.run_cell_magic('cython', '', code) ip.ex('g = f(10)') self.assertEqual(ip.user_ns['g'], 20.0) def test_cython_name(self): # The Cython module named 'mymodule' defines the function f. ip = self._ip ip.run_cell_magic('cython', '--name=mymodule', code) # This module can now be imported in the interactive namespace. ip.ex('import mymodule; g = mymodule.f(10)') self.assertEqual(ip.user_ns['g'], 20.0) def test_cython_language_level(self): # The Cython cell defines the functions f() and call(). ip = self._ip ip.run_cell_magic('cython', '', cython3_code) ip.ex('g = f(10); h = call(10)') if sys.version_info[0] < 3: self.assertEqual(ip.user_ns['g'], 2 // 10) self.assertEqual(ip.user_ns['h'], 2 // 10) else: self.assertEqual(ip.user_ns['g'], 2.0 / 10.0) self.assertEqual(ip.user_ns['h'], 2.0 / 10.0) def test_cython3(self): # The Cython cell defines the functions f() and call(). ip = self._ip ip.run_cell_magic('cython', '-3', cython3_code) ip.ex('g = f(10); h = call(10)') self.assertEqual(ip.user_ns['g'], 2.0 / 10.0) self.assertEqual(ip.user_ns['h'], 2.0 / 10.0) def test_cython2(self): # The Cython cell defines the functions f() and call(). ip = self._ip ip.run_cell_magic('cython', '-2', cython3_code) ip.ex('g = f(10); h = call(10)') self.assertEqual(ip.user_ns['g'], 2 // 10) self.assertEqual(ip.user_ns['h'], 2 // 10) def test_cython_compile_error_shown(self): ip = self._ip with capture_output() as out: ip.run_cell_magic('cython', '-3', compile_error_code) captured_out, captured_err = out # it could be that c-level output is captured by distutil-extension # (and not by us) and is printed to stdout: captured_all = captured_out + "\n" + captured_err self.assertTrue("error" in captured_all, msg="error in " + captured_all) def test_cython_link_error_shown(self): ip = self._ip with capture_output() as out: ip.run_cell_magic('cython', '-3 -l=xxxxxxxx', code) captured_out, captured_err = out # it could be that c-level output is captured by distutil-extension # (and not by us) and is printed to stdout: captured_all = captured_out + "\n!" + captured_err self.assertTrue("error" in captured_all, msg="error in " + captured_all) def test_cython_warning_shown(self): ip = self._ip with capture_output() as out: # force rebuild, otherwise no warning as after the first success # no build step is performed ip.run_cell_magic('cython', '-3 -f', compile_warning_code) captured_out, captured_err = out # check that warning was printed to stdout even if build hasn't failed self.assertTrue("CWarning" in captured_out) @skip_py27 # Not strictly broken in Py2.7 but currently fails in CI due to C compiler issues. @skip_win32 def test_cython3_pgo(self): # The Cython cell defines the functions f() and call(). ip = self._ip ip.run_cell_magic('cython', '-3 --pgo', pgo_cython3_code) ip.ex('g = f(10); h = call(10); main()') self.assertEqual(ip.user_ns['g'], 2.0 / 10.0) self.assertEqual(ip.user_ns['h'], 2.0 / 10.0) @skip_win32 def test_extlibs(self): ip = self._ip code = u""" from libc.math cimport sin x = sin(0.0) """ ip.user_ns['x'] = 1 ip.run_cell_magic('cython', '-l m', code) self.assertEqual(ip.user_ns['x'], 0) def test_cython_verbose(self): ip = self._ip ip.run_cell_magic('cython', '--verbose', code) ip.ex('g = f(10)') self.assertEqual(ip.user_ns['g'], 20.0) def test_cython_verbose_thresholds(self): @contextmanager def mock_distutils(): class MockLog: DEBUG = 1 INFO = 2 thresholds = [INFO] def set_threshold(self, val): self.thresholds.append(val) return self.thresholds[-2] new_log = MockLog() old_log = IpythonMagic.distutils.log try: IpythonMagic.distutils.log = new_log yield new_log finally: IpythonMagic.distutils.log = old_log ip = self._ip with mock_distutils() as verbose_log: ip.run_cell_magic('cython', '--verbose', code) ip.ex('g = f(10)') self.assertEqual(ip.user_ns['g'], 20.0) self.assertEqual([verbose_log.INFO, verbose_log.DEBUG, verbose_log.INFO], verbose_log.thresholds) with mock_distutils() as normal_log: ip.run_cell_magic('cython', '', code) ip.ex('g = f(10)') self.assertEqual(ip.user_ns['g'], 20.0) self.assertEqual([normal_log.INFO], normal_log.thresholds) def test_cython_no_annotate(self): ip = self._ip html = ip.run_cell_magic('cython', '', code) self.assertTrue(html is None) def test_cython_annotate(self): ip = self._ip html = ip.run_cell_magic('cython', '--annotate', code) # somewhat brittle way to differentiate between annotated htmls # with/without complete source code: self.assertTrue(AnnotationCCodeWriter.COMPLETE_CODE_TITLE not in html.data) def test_cython_annotate_default(self): ip = self._ip html = ip.run_cell_magic('cython', '-a', code) # somewhat brittle way to differentiate between annotated htmls # with/without complete source code: self.assertTrue(AnnotationCCodeWriter.COMPLETE_CODE_TITLE not in html.data) def test_cython_annotate_complete_c_code(self): ip = self._ip html = ip.run_cell_magic('cython', '--annotate-fullc', code) # somewhat brittle way to differentiate between annotated htmls # with/without complete source code: self.assertTrue(AnnotationCCodeWriter.COMPLETE_CODE_TITLE in html.data) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Build/Tests/TestRecythonize.py0000644000175100001770000001420400000000000022717 0ustar00runnerdocker00000000000000import shutil import os import tempfile import time import Cython.Build.Dependencies import Cython.Utils from Cython.TestUtils import CythonTest def fresh_cythonize(*args, **kwargs): Cython.Utils.clear_function_caches() Cython.Build.Dependencies._dep_tree = None # discard method caches Cython.Build.Dependencies.cythonize(*args, **kwargs) class TestRecythonize(CythonTest): def setUp(self): CythonTest.setUp(self) self.temp_dir = ( tempfile.mkdtemp( prefix='recythonize-test', dir='TEST_TMP' if os.path.isdir('TEST_TMP') else None ) ) def tearDown(self): CythonTest.tearDown(self) shutil.rmtree(self.temp_dir) def test_recythonize_pyx_on_pxd_change(self): src_dir = tempfile.mkdtemp(prefix='src', dir=self.temp_dir) a_pxd = os.path.join(src_dir, 'a.pxd') a_pyx = os.path.join(src_dir, 'a.pyx') a_c = os.path.join(src_dir, 'a.c') dep_tree = Cython.Build.Dependencies.create_dependency_tree() with open(a_pxd, 'w') as f: f.write('cdef int value\n') with open(a_pyx, 'w') as f: f.write('value = 1\n') # The dependencies for "a.pyx" are "a.pxd" and "a.pyx". self.assertEqual({a_pxd, a_pyx}, dep_tree.all_dependencies(a_pyx)) # Cythonize to create a.c fresh_cythonize(a_pyx) # Sleep to address coarse time-stamp precision. time.sleep(1) with open(a_c) as f: a_c_contents1 = f.read() with open(a_pxd, 'w') as f: f.write('cdef double value\n') fresh_cythonize(a_pyx) with open(a_c) as f: a_c_contents2 = f.read() self.assertTrue("__pyx_v_1a_value = 1;" in a_c_contents1) self.assertFalse("__pyx_v_1a_value = 1;" in a_c_contents2) self.assertTrue("__pyx_v_1a_value = 1.0;" in a_c_contents2) self.assertFalse("__pyx_v_1a_value = 1.0;" in a_c_contents1) def test_recythonize_py_on_pxd_change(self): src_dir = tempfile.mkdtemp(prefix='src', dir=self.temp_dir) a_pxd = os.path.join(src_dir, 'a.pxd') a_py = os.path.join(src_dir, 'a.py') a_c = os.path.join(src_dir, 'a.c') dep_tree = Cython.Build.Dependencies.create_dependency_tree() with open(a_pxd, 'w') as f: f.write('cdef int value\n') with open(a_py, 'w') as f: f.write('value = 1\n') # The dependencies for "a.py" are "a.pxd" and "a.py". self.assertEqual({a_pxd, a_py}, dep_tree.all_dependencies(a_py)) # Cythonize to create a.c fresh_cythonize(a_py) # Sleep to address coarse time-stamp precision. time.sleep(1) with open(a_c) as f: a_c_contents1 = f.read() with open(a_pxd, 'w') as f: f.write('cdef double value\n') fresh_cythonize(a_py) with open(a_c) as f: a_c_contents2 = f.read() self.assertTrue("__pyx_v_1a_value = 1;" in a_c_contents1) self.assertFalse("__pyx_v_1a_value = 1;" in a_c_contents2) self.assertTrue("__pyx_v_1a_value = 1.0;" in a_c_contents2) self.assertFalse("__pyx_v_1a_value = 1.0;" in a_c_contents1) def test_recythonize_pyx_on_dep_pxd_change(self): src_dir = tempfile.mkdtemp(prefix='src', dir=self.temp_dir) a_pxd = os.path.join(src_dir, 'a.pxd') a_pyx = os.path.join(src_dir, 'a.pyx') b_pyx = os.path.join(src_dir, 'b.pyx') b_c = os.path.join(src_dir, 'b.c') dep_tree = Cython.Build.Dependencies.create_dependency_tree() with open(a_pxd, 'w') as f: f.write('cdef int value\n') with open(a_pyx, 'w') as f: f.write('value = 1\n') with open(b_pyx, 'w') as f: f.write('cimport a\n' + 'a.value = 2\n') # The dependencies for "b.pyx" are "a.pxd" and "b.pyx". self.assertEqual({a_pxd, b_pyx}, dep_tree.all_dependencies(b_pyx)) # Cythonize to create b.c fresh_cythonize([a_pyx, b_pyx]) # Sleep to address coarse time-stamp precision. time.sleep(1) with open(b_c) as f: b_c_contents1 = f.read() with open(a_pxd, 'w') as f: f.write('cdef double value\n') fresh_cythonize([a_pyx, b_pyx]) with open(b_c) as f: b_c_contents2 = f.read() self.assertTrue("__pyx_v_1a_value = 2;" in b_c_contents1) self.assertFalse("__pyx_v_1a_value = 2;" in b_c_contents2) self.assertTrue("__pyx_v_1a_value = 2.0;" in b_c_contents2) self.assertFalse("__pyx_v_1a_value = 2.0;" in b_c_contents1) def test_recythonize_py_on_dep_pxd_change(self): src_dir = tempfile.mkdtemp(prefix='src', dir=self.temp_dir) a_pxd = os.path.join(src_dir, 'a.pxd') a_pyx = os.path.join(src_dir, 'a.pyx') b_pxd = os.path.join(src_dir, 'b.pxd') b_py = os.path.join(src_dir, 'b.py') b_c = os.path.join(src_dir, 'b.c') dep_tree = Cython.Build.Dependencies.create_dependency_tree() with open(a_pxd, 'w') as f: f.write('cdef int value\n') with open(a_pyx, 'w') as f: f.write('value = 1\n') with open(b_pxd, 'w') as f: f.write('cimport a\n') with open(b_py, 'w') as f: f.write('a.value = 2\n') # The dependencies for b.py are "a.pxd", "b.pxd" and "b.py". self.assertEqual({a_pxd, b_pxd, b_py}, dep_tree.all_dependencies(b_py)) # Cythonize to create b.c fresh_cythonize([a_pyx, b_py]) # Sleep to address coarse time-stamp precision. time.sleep(1) with open(b_c) as f: b_c_contents1 = f.read() with open(a_pxd, 'w') as f: f.write('cdef double value\n') fresh_cythonize([a_pyx, b_py]) with open(b_c) as f: b_c_contents2 = f.read() self.assertTrue("__pyx_v_1a_value = 2;" in b_c_contents1) self.assertFalse("__pyx_v_1a_value = 2;" in b_c_contents2) self.assertTrue("__pyx_v_1a_value = 2.0;" in b_c_contents2) self.assertFalse("__pyx_v_1a_value = 2.0;" in b_c_contents1) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Build/Tests/TestStripLiterals.py0000644000175100001770000000301500000000000023213 0ustar00runnerdocker00000000000000from Cython.Build.Dependencies import strip_string_literals from Cython.TestUtils import CythonTest class TestStripLiterals(CythonTest): def t(self, before, expected): actual, literals = strip_string_literals(before, prefix="_L") self.assertEqual(expected, actual) for key, value in literals.items(): actual = actual.replace(key, value) self.assertEqual(before, actual) def test_empty(self): self.t("", "") def test_single_quote(self): self.t("'x'", "'_L1_'") def test_double_quote(self): self.t('"x"', '"_L1_"') def test_nested_quotes(self): self.t(""" '"' "'" """, """ '_L1_' "_L2_" """) def test_triple_quote(self): self.t(" '''a\n''' ", " '''_L1_''' ") def test_backslash(self): self.t(r"'a\'b'", "'_L1_'") self.t(r"'a\\'", "'_L1_'") self.t(r"'a\\\'b'", "'_L1_'") def test_unicode(self): self.t("u'abc'", "u'_L1_'") def test_raw(self): self.t(r"r'abc\\'", "r'_L1_'") def test_raw_unicode(self): self.t(r"ru'abc\\'", "ru'_L1_'") def test_comment(self): self.t("abc # foo", "abc #_L1_") def test_comment_and_quote(self): self.t("abc # 'x'", "abc #_L1_") self.t("'abc#'", "'_L1_'") def test_include(self): self.t("include 'a.pxi' # something here", "include '_L1_' #_L2_") def test_extern(self): self.t("cdef extern from 'a.h': # comment", "cdef extern from '_L1_': #_L2_") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Build/Tests/__init__.py0000644000175100001770000000001500000000000021306 0ustar00runnerdocker00000000000000# empty file ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Build/__init__.py0000644000175100001770000000062100000000000020207 0ustar00runnerdocker00000000000000from .Dependencies import cythonize import sys if sys.version_info < (3, 7): from .Distutils import build_ext del sys def __getattr__(name): if name == 'build_ext': # Lazy import, fails if distutils is not available (in Python 3.12+). from .Distutils import build_ext return build_ext raise AttributeError("module '%s' has no attribute '%s'" % (__name__, name)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/CodeWriter.py0000644000175100001770000005774200000000000017500 0ustar00runnerdocker00000000000000""" Serializes a Cython code tree to Cython code. This is primarily useful for debugging and testing purposes. The output is in a strict format, no whitespace or comments from the input is preserved (and it could not be as it is not present in the code tree). """ from __future__ import absolute_import, print_function from .Compiler.Visitor import TreeVisitor from .Compiler.ExprNodes import * from .Compiler.Nodes import CSimpleBaseTypeNode class LinesResult(object): def __init__(self): self.lines = [] self.s = u"" def put(self, s): self.s += s def newline(self): self.lines.append(self.s) self.s = u"" def putline(self, s): self.put(s) self.newline() class DeclarationWriter(TreeVisitor): """ A Cython code writer that is limited to declarations nodes. """ indent_string = u" " def __init__(self, result=None): super(DeclarationWriter, self).__init__() if result is None: result = LinesResult() self.result = result self.numindents = 0 self.tempnames = {} self.tempblockindex = 0 def write(self, tree): self.visit(tree) return self.result def indent(self): self.numindents += 1 def dedent(self): self.numindents -= 1 def startline(self, s=u""): self.result.put(self.indent_string * self.numindents + s) def put(self, s): self.result.put(s) def putline(self, s): self.result.putline(self.indent_string * self.numindents + s) def endline(self, s=u""): self.result.putline(s) def line(self, s): self.startline(s) self.endline() def comma_separated_list(self, items, output_rhs=False): if len(items) > 0: for item in items[:-1]: self.visit(item) if output_rhs and item.default is not None: self.put(u" = ") self.visit(item.default) self.put(u", ") self.visit(items[-1]) if output_rhs and items[-1].default is not None: self.put(u" = ") self.visit(items[-1].default) def _visit_indented(self, node): self.indent() self.visit(node) self.dedent() def visit_Node(self, node): raise AssertionError("Node not handled by serializer: %r" % node) def visit_ModuleNode(self, node): self.visitchildren(node) def visit_StatListNode(self, node): self.visitchildren(node) def visit_CDefExternNode(self, node): if node.include_file is None: file = u'*' else: file = u'"%s"' % node.include_file self.putline(u"cdef extern from %s:" % file) self._visit_indented(node.body) def visit_CPtrDeclaratorNode(self, node): self.put('*') self.visit(node.base) def visit_CReferenceDeclaratorNode(self, node): self.put('&') self.visit(node.base) def visit_CArrayDeclaratorNode(self, node): self.visit(node.base) self.put(u'[') if node.dimension is not None: self.visit(node.dimension) self.put(u']') def visit_CFuncDeclaratorNode(self, node): # TODO: except, gil, etc. self.visit(node.base) self.put(u'(') self.comma_separated_list(node.args) self.endline(u')') def visit_CNameDeclaratorNode(self, node): self.put(node.name) def visit_CSimpleBaseTypeNode(self, node): # See Parsing.p_sign_and_longness if node.is_basic_c_type: self.put(("unsigned ", "", "signed ")[node.signed]) if node.longness < 0: self.put("short " * -node.longness) elif node.longness > 0: self.put("long " * node.longness) if node.name is not None: self.put(node.name) def visit_CComplexBaseTypeNode(self, node): self.visit(node.base_type) self.visit(node.declarator) def visit_CNestedBaseTypeNode(self, node): self.visit(node.base_type) self.put(u'.') self.put(node.name) def visit_TemplatedTypeNode(self, node): self.visit(node.base_type_node) self.put(u'[') self.comma_separated_list(node.positional_args + node.keyword_args.key_value_pairs) self.put(u']') def visit_CVarDefNode(self, node): self.startline(u"cdef ") self.visit(node.base_type) self.put(u" ") self.comma_separated_list(node.declarators, output_rhs=True) self.endline() def _visit_container_node(self, node, decl, extras, attributes): # TODO: visibility self.startline(decl) if node.name: self.put(u' ') self.put(node.name) if node.cname is not None: self.put(u' "%s"' % node.cname) if extras: self.put(extras) self.endline(':') self.indent() if not attributes: self.putline('pass') else: for attribute in attributes: self.visit(attribute) self.dedent() def visit_CStructOrUnionDefNode(self, node): if node.typedef_flag: decl = u'ctypedef ' else: decl = u'cdef ' if node.visibility == 'public': decl += u'public ' if node.packed: decl += u'packed ' decl += node.kind self._visit_container_node(node, decl, None, node.attributes) def visit_CppClassNode(self, node): extras = "" if node.templates: extras = u"[%s]" % ", ".join(node.templates) if node.base_classes: extras += "(%s)" % ", ".join(node.base_classes) self._visit_container_node(node, u"cdef cppclass", extras, node.attributes) def visit_CEnumDefNode(self, node): self._visit_container_node(node, u"cdef enum", None, node.items) def visit_CEnumDefItemNode(self, node): self.startline(node.name) if node.cname: self.put(u' "%s"' % node.cname) if node.value: self.put(u" = ") self.visit(node.value) self.endline() def visit_CClassDefNode(self, node): assert not node.module_name if node.decorators: for decorator in node.decorators: self.visit(decorator) self.startline(u"cdef class ") self.put(node.class_name) if node.base_class_name: self.put(u"(") if node.base_class_module: self.put(node.base_class_module) self.put(u".") self.put(node.base_class_name) self.put(u")") self.endline(u":") self._visit_indented(node.body) def visit_CTypeDefNode(self, node): self.startline(u"ctypedef ") self.visit(node.base_type) self.put(u" ") self.visit(node.declarator) self.endline() def visit_FuncDefNode(self, node): # TODO: support cdef + cpdef functions self.startline(u"def %s(" % node.name) self.comma_separated_list(node.args) self.endline(u"):") self._visit_indented(node.body) def visit_CFuncDefNode(self, node): self.startline(u'cpdef ' if node.overridable else u'cdef ') if node.modifiers: self.put(' '.join(node.modifiers)) self.put(' ') if node.visibility != 'private': self.put(node.visibility) self.put(u' ') if node.api: self.put(u'api ') if node.base_type: self.visit(node.base_type) if node.base_type.name is not None: self.put(u' ') # visit the CFuncDeclaratorNode, but put a `:` at the end of line self.visit(node.declarator.base) self.put(u'(') self.comma_separated_list(node.declarator.args) self.endline(u'):') self._visit_indented(node.body) def visit_CArgDeclNode(self, node): # For "CSimpleBaseTypeNode", the variable type may have been parsed as type. # For other node types, the "name" is always None. if not isinstance(node.base_type, CSimpleBaseTypeNode) or \ node.base_type.name is not None: self.visit(node.base_type) # If we printed something for "node.base_type", we may need to print an extra ' '. # # Special case: if "node.declarator" is a "CNameDeclaratorNode", # its "name" might be an empty string, for example, for "cdef f(x)". if node.declarator.declared_name(): self.put(u" ") self.visit(node.declarator) if node.default is not None: self.put(u" = ") self.visit(node.default) def visit_CImportStatNode(self, node): self.startline(u"cimport ") self.put(node.module_name) if node.as_name: self.put(u" as ") self.put(node.as_name) self.endline() def visit_FromCImportStatNode(self, node): self.startline(u"from ") self.put(node.module_name) self.put(u" cimport ") first = True for pos, name, as_name, kind in node.imported_names: assert kind is None if first: first = False else: self.put(u", ") self.put(name) if as_name: self.put(u" as ") self.put(as_name) self.endline() def visit_NameNode(self, node): self.put(node.name) def visit_DecoratorNode(self, node): self.startline("@") self.visit(node.decorator) self.endline() def visit_PassStatNode(self, node): self.startline(u"pass") self.endline() class StatementWriter(DeclarationWriter): """ A Cython code writer for most language statement features. """ def visit_SingleAssignmentNode(self, node): self.startline() self.visit(node.lhs) self.put(u" = ") self.visit(node.rhs) self.endline() def visit_CascadedAssignmentNode(self, node): self.startline() for lhs in node.lhs_list: self.visit(lhs) self.put(u" = ") self.visit(node.rhs) self.endline() def visit_PrintStatNode(self, node): self.startline(u"print ") self.comma_separated_list(node.arg_tuple.args) if not node.append_newline: self.put(u",") self.endline() def visit_ForInStatNode(self, node): self.startline(u"for ") if node.target.is_sequence_constructor: self.comma_separated_list(node.target.args) else: self.visit(node.target) self.put(u" in ") self.visit(node.iterator.sequence) self.endline(u":") self._visit_indented(node.body) if node.else_clause is not None: self.line(u"else:") self._visit_indented(node.else_clause) def visit_IfStatNode(self, node): # The IfClauseNode is handled directly without a separate match # for clariy. self.startline(u"if ") self.visit(node.if_clauses[0].condition) self.endline(":") self._visit_indented(node.if_clauses[0].body) for clause in node.if_clauses[1:]: self.startline("elif ") self.visit(clause.condition) self.endline(":") self._visit_indented(clause.body) if node.else_clause is not None: self.line("else:") self._visit_indented(node.else_clause) def visit_WhileStatNode(self, node): self.startline(u"while ") self.visit(node.condition) self.endline(u":") self._visit_indented(node.body) if node.else_clause is not None: self.line("else:") self._visit_indented(node.else_clause) def visit_ContinueStatNode(self, node): self.line(u"continue") def visit_BreakStatNode(self, node): self.line(u"break") def visit_SequenceNode(self, node): self.comma_separated_list(node.args) # Might need to discover whether we need () around tuples...hmm... def visit_ExprStatNode(self, node): self.startline() self.visit(node.expr) self.endline() def visit_InPlaceAssignmentNode(self, node): self.startline() self.visit(node.lhs) self.put(u" %s= " % node.operator) self.visit(node.rhs) self.endline() def visit_WithStatNode(self, node): self.startline() self.put(u"with ") self.visit(node.manager) if node.target is not None: self.put(u" as ") self.visit(node.target) self.endline(u":") self._visit_indented(node.body) def visit_TryFinallyStatNode(self, node): self.line(u"try:") self._visit_indented(node.body) self.line(u"finally:") self._visit_indented(node.finally_clause) def visit_TryExceptStatNode(self, node): self.line(u"try:") self._visit_indented(node.body) for x in node.except_clauses: self.visit(x) if node.else_clause is not None: self.visit(node.else_clause) def visit_ExceptClauseNode(self, node): self.startline(u"except") if node.pattern is not None: self.put(u" ") self.visit(node.pattern) if node.target is not None: self.put(u", ") self.visit(node.target) self.endline(":") self._visit_indented(node.body) def visit_ReturnStatNode(self, node): self.startline("return") if node.value is not None: self.put(u" ") self.visit(node.value) self.endline() def visit_ReraiseStatNode(self, node): self.line("raise") def visit_ImportNode(self, node): self.put(u"(import %s)" % node.module_name.value) def visit_TempsBlockNode(self, node): """ Temporaries are output like $1_1', where the first number is an index of the TempsBlockNode and the second number is an index of the temporary which that block allocates. """ idx = 0 for handle in node.temps: self.tempnames[handle] = "$%d_%d" % (self.tempblockindex, idx) idx += 1 self.tempblockindex += 1 self.visit(node.body) def visit_TempRefNode(self, node): self.put(self.tempnames[node.handle]) class ExpressionWriter(TreeVisitor): """ A Cython code writer that is intentionally limited to expressions. """ def __init__(self, result=None): super(ExpressionWriter, self).__init__() if result is None: result = u"" self.result = result self.precedence = [0] def write(self, tree): self.visit(tree) return self.result def put(self, s): self.result += s def remove(self, s): if self.result.endswith(s): self.result = self.result[:-len(s)] def comma_separated_list(self, items): if len(items) > 0: for item in items[:-1]: self.visit(item) self.put(u", ") self.visit(items[-1]) def visit_Node(self, node): raise AssertionError("Node not handled by serializer: %r" % node) def visit_IntNode(self, node): self.put(node.value) def visit_FloatNode(self, node): self.put(node.value) def visit_NoneNode(self, node): self.put(u"None") def visit_NameNode(self, node): self.put(node.name) def visit_EllipsisNode(self, node): self.put(u"...") def visit_BoolNode(self, node): self.put(str(node.value)) def visit_ConstNode(self, node): self.put(str(node.value)) def visit_ImagNode(self, node): self.put(node.value) self.put(u"j") def emit_string(self, node, prefix=u""): repr_val = repr(node.value) if repr_val[0] in 'ub': repr_val = repr_val[1:] self.put(u"%s%s" % (prefix, repr_val)) def visit_BytesNode(self, node): self.emit_string(node, u"b") def visit_StringNode(self, node): self.emit_string(node) def visit_UnicodeNode(self, node): self.emit_string(node, u"u") def emit_sequence(self, node, parens=(u"", u"")): open_paren, close_paren = parens items = node.subexpr_nodes() self.put(open_paren) self.comma_separated_list(items) self.put(close_paren) def visit_ListNode(self, node): self.emit_sequence(node, u"[]") def visit_TupleNode(self, node): self.emit_sequence(node, u"()") def visit_SetNode(self, node): if len(node.subexpr_nodes()) > 0: self.emit_sequence(node, u"{}") else: self.put(u"set()") def visit_DictNode(self, node): self.emit_sequence(node, u"{}") def visit_DictItemNode(self, node): self.visit(node.key) self.put(u": ") self.visit(node.value) unop_precedence = { 'not': 3, '!': 3, '+': 11, '-': 11, '~': 11, } binop_precedence = { 'or': 1, 'and': 2, # unary: 'not': 3, '!': 3, 'in': 4, 'not_in': 4, 'is': 4, 'is_not': 4, '<': 4, '<=': 4, '>': 4, '>=': 4, '!=': 4, '==': 4, '|': 5, '^': 6, '&': 7, '<<': 8, '>>': 8, '+': 9, '-': 9, '*': 10, '@': 10, '/': 10, '//': 10, '%': 10, # unary: '+': 11, '-': 11, '~': 11 '**': 12, } def operator_enter(self, new_prec): old_prec = self.precedence[-1] if old_prec > new_prec: self.put(u"(") self.precedence.append(new_prec) def operator_exit(self): old_prec, new_prec = self.precedence[-2:] if old_prec > new_prec: self.put(u")") self.precedence.pop() def visit_NotNode(self, node): op = 'not' prec = self.unop_precedence[op] self.operator_enter(prec) self.put(u"not ") self.visit(node.operand) self.operator_exit() def visit_UnopNode(self, node): op = node.operator prec = self.unop_precedence[op] self.operator_enter(prec) self.put(u"%s" % node.operator) self.visit(node.operand) self.operator_exit() def visit_BinopNode(self, node): op = node.operator prec = self.binop_precedence.get(op, 0) self.operator_enter(prec) self.visit(node.operand1) self.put(u" %s " % op.replace('_', ' ')) self.visit(node.operand2) self.operator_exit() def visit_BoolBinopNode(self, node): self.visit_BinopNode(node) def visit_PrimaryCmpNode(self, node): self.visit_BinopNode(node) def visit_IndexNode(self, node): self.visit(node.base) self.put(u"[") if isinstance(node.index, TupleNode): if node.index.subexpr_nodes(): self.emit_sequence(node.index) else: self.put(u"()") else: self.visit(node.index) self.put(u"]") def visit_SliceIndexNode(self, node): self.visit(node.base) self.put(u"[") if node.start: self.visit(node.start) self.put(u":") if node.stop: self.visit(node.stop) if node.slice: self.put(u":") self.visit(node.slice) self.put(u"]") def visit_SliceNode(self, node): if not node.start.is_none: self.visit(node.start) self.put(u":") if not node.stop.is_none: self.visit(node.stop) if not node.step.is_none: self.put(u":") self.visit(node.step) def visit_CondExprNode(self, node): self.visit(node.true_val) self.put(u" if ") self.visit(node.test) self.put(u" else ") self.visit(node.false_val) def visit_AttributeNode(self, node): self.visit(node.obj) self.put(u".%s" % node.attribute) def visit_SimpleCallNode(self, node): self.visit(node.function) self.put(u"(") self.comma_separated_list(node.args) self.put(")") def emit_pos_args(self, node): if node is None: return if isinstance(node, AddNode): self.emit_pos_args(node.operand1) self.emit_pos_args(node.operand2) elif isinstance(node, TupleNode): for expr in node.subexpr_nodes(): self.visit(expr) self.put(u", ") elif isinstance(node, AsTupleNode): self.put("*") self.visit(node.arg) self.put(u", ") else: self.visit(node) self.put(u", ") def emit_kwd_args(self, node): if node is None: return if isinstance(node, MergedDictNode): for expr in node.subexpr_nodes(): self.emit_kwd_args(expr) elif isinstance(node, DictNode): for expr in node.subexpr_nodes(): self.put(u"%s=" % expr.key.value) self.visit(expr.value) self.put(u", ") else: self.put(u"**") self.visit(node) self.put(u", ") def visit_GeneralCallNode(self, node): self.visit(node.function) self.put(u"(") self.emit_pos_args(node.positional_args) self.emit_kwd_args(node.keyword_args) self.remove(u", ") self.put(")") def emit_comprehension(self, body, target, sequence, condition, parens=(u"", u"")): open_paren, close_paren = parens self.put(open_paren) self.visit(body) self.put(u" for ") self.visit(target) self.put(u" in ") self.visit(sequence) if condition: self.put(u" if ") self.visit(condition) self.put(close_paren) def visit_ComprehensionAppendNode(self, node): self.visit(node.expr) def visit_DictComprehensionAppendNode(self, node): self.visit(node.key_expr) self.put(u": ") self.visit(node.value_expr) def visit_ComprehensionNode(self, node): tpmap = {'list': u"[]", 'dict': u"{}", 'set': u"{}"} parens = tpmap[node.type.py_type_name()] body = node.loop.body target = node.loop.target sequence = node.loop.iterator.sequence condition = None if hasattr(body, 'if_clauses'): # type(body) is Nodes.IfStatNode condition = body.if_clauses[0].condition body = body.if_clauses[0].body self.emit_comprehension(body, target, sequence, condition, parens) def visit_GeneratorExpressionNode(self, node): body = node.loop.body target = node.loop.target sequence = node.loop.iterator.sequence condition = None if hasattr(body, 'if_clauses'): # type(body) is Nodes.IfStatNode condition = body.if_clauses[0].condition body = body.if_clauses[0].body.expr.arg elif hasattr(body, 'expr'): # type(body) is Nodes.ExprStatNode body = body.expr.arg self.emit_comprehension(body, target, sequence, condition, u"()") class PxdWriter(DeclarationWriter, ExpressionWriter): """ A Cython code writer for everything supported in pxd files. (currently unused) """ def __call__(self, node): print(u'\n'.join(self.write(node).lines)) return node def visit_CFuncDefNode(self, node): if node.overridable: self.startline(u'cpdef ') else: self.startline(u'cdef ') if node.modifiers: self.put(' '.join(node.modifiers)) self.put(' ') if node.visibility != 'private': self.put(node.visibility) self.put(u' ') if node.api: self.put(u'api ') self.visit(node.declarator) def visit_StatNode(self, node): pass class CodeWriter(StatementWriter, ExpressionWriter): """ A complete Cython code writer. """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880490.9967241 Cython-3.0.8/Cython/Compiler/0000755000175100001770000000000000000000000016612 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Compiler/AnalysedTreeTransforms.py0000644000175100001770000000737200000000000023634 0ustar00runnerdocker00000000000000from __future__ import absolute_import from .Visitor import ScopeTrackingTransform from .Nodes import StatListNode, SingleAssignmentNode, CFuncDefNode, DefNode from .ExprNodes import DictNode, DictItemNode, NameNode, UnicodeNode from .PyrexTypes import py_object_type from .StringEncoding import EncodedString from . import Symtab class AutoTestDictTransform(ScopeTrackingTransform): # Handles autotestdict directive excludelist = ['__cinit__', '__dealloc__', '__richcmp__', '__nonzero__', '__bool__', '__len__', '__contains__'] def visit_ModuleNode(self, node): if node.is_pxd: return node self.scope_type = 'module' self.scope_node = node if not self.current_directives['autotestdict']: return node self.all_docstrings = self.current_directives['autotestdict.all'] self.cdef_docstrings = self.all_docstrings or self.current_directives['autotestdict.cdef'] assert isinstance(node.body, StatListNode) # First see if __test__ is already created if u'__test__' in node.scope.entries: # Do nothing return node pos = node.pos self.tests = [] self.testspos = node.pos test_dict_entry = node.scope.declare_var(EncodedString(u'__test__'), py_object_type, pos, visibility='public') create_test_dict_assignment = SingleAssignmentNode(pos, lhs=NameNode(pos, name=EncodedString(u'__test__'), entry=test_dict_entry), rhs=DictNode(pos, key_value_pairs=self.tests)) self.visitchildren(node) node.body.stats.append(create_test_dict_assignment) return node def add_test(self, testpos, path, doctest): pos = self.testspos keystr = u'%s (line %d)' % (path, testpos[1]) key = UnicodeNode(pos, value=EncodedString(keystr)) value = UnicodeNode(pos, value=doctest) self.tests.append(DictItemNode(pos, key=key, value=value)) def visit_ExprNode(self, node): # expressions cannot contain functions and lambda expressions # do not have a docstring return node def visit_FuncDefNode(self, node): if not node.doc or (isinstance(node, DefNode) and node.fused_py_func): return node if not self.cdef_docstrings: if isinstance(node, CFuncDefNode) and not node.py_func: return node if not self.all_docstrings and '>>>' not in node.doc: return node pos = self.testspos if self.scope_type == 'module': path = node.entry.name elif self.scope_type in ('pyclass', 'cclass'): if isinstance(node, CFuncDefNode): if node.py_func is not None: name = node.py_func.name else: name = node.entry.name else: name = node.name if self.scope_type == 'cclass' and name in self.excludelist: return node if self.scope_type == 'pyclass': class_name = self.scope_node.name else: class_name = self.scope_node.class_name if isinstance(node.entry.scope, Symtab.PropertyScope): property_method_name = node.entry.scope.name path = "%s.%s.%s" % (class_name, node.entry.scope.name, node.entry.name) else: path = "%s.%s" % (class_name, node.entry.name) else: assert False self.add_test(node.pos, path, node.doc) return node ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Compiler/Annotate.py0000644000175100001770000003351100000000000020740 0ustar00runnerdocker00000000000000# Note: Work in progress from __future__ import absolute_import import os import os.path import re import codecs import textwrap from datetime import datetime from functools import partial from collections import defaultdict from xml.sax.saxutils import escape as html_escape try: from StringIO import StringIO except ImportError: from io import StringIO # does not support writing 'str' in Py2 from . import Version from .Code import CCodeWriter from .. import Utils class AnnotationCCodeWriter(CCodeWriter): # also used as marker for detection of complete code emission in tests COMPLETE_CODE_TITLE = "Complete cythonized code" def __init__(self, create_from=None, buffer=None, copy_formatting=True, show_entire_c_code=False, source_desc=None): CCodeWriter.__init__(self, create_from, buffer, copy_formatting=copy_formatting) self.show_entire_c_code = show_entire_c_code if create_from is None: self.annotation_buffer = StringIO() self.last_annotated_pos = None # annotations[filename][line] -> [(column, AnnotationItem)*] self.annotations = defaultdict(partial(defaultdict, list)) # code[filename][line] -> str self.code = defaultdict(partial(defaultdict, str)) # scopes[filename][line] -> set(scopes) self.scopes = defaultdict(partial(defaultdict, set)) else: # When creating an insertion point, keep references to the same database self.annotation_buffer = create_from.annotation_buffer self.annotations = create_from.annotations self.code = create_from.code self.scopes = create_from.scopes self.last_annotated_pos = create_from.last_annotated_pos def create_new(self, create_from, buffer, copy_formatting): return AnnotationCCodeWriter(create_from, buffer, copy_formatting) def _write_to_buffer(self, s): self.buffer.write(s) self.annotation_buffer.write(s) def mark_pos(self, pos, trace=True): if pos is not None: CCodeWriter.mark_pos(self, pos, trace) if self.funcstate and self.funcstate.scope: # lambdas and genexprs can result in multiple scopes per line => keep them in a set self.scopes[pos[0].filename][pos[1]].add(self.funcstate.scope) if self.last_annotated_pos: source_desc, line, _ = self.last_annotated_pos pos_code = self.code[source_desc.filename] pos_code[line] += self.annotation_buffer.getvalue() self.annotation_buffer = StringIO() self.last_annotated_pos = pos def annotate(self, pos, item): self.annotations[pos[0].filename][pos[1]].append((pos[2], item)) def _css(self): """css template will later allow to choose a colormap""" css = [self._css_template] for i in range(255): color = u"FFFF%02x" % int(255.0 // (1.0 + i/10.0)) css.append('.cython.score-%d {background-color: #%s;}' % (i, color)) try: from pygments.formatters import HtmlFormatter except ImportError: pass else: css.append(HtmlFormatter().get_style_defs('.cython')) return '\n'.join(css) _css_template = textwrap.dedent(""" body.cython { font-family: courier; font-size: 12; } .cython.tag { } .cython.line { color: #000000; margin: 0em } .cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; } .cython.line .run { background-color: #B0FFB0; } .cython.line .mis { background-color: #FFB0B0; } .cython.code.run { border-left: 8px solid #B0FFB0; } .cython.code.mis { border-left: 8px solid #FFB0B0; } .cython.code .py_c_api { color: red; } .cython.code .py_macro_api { color: #FF7000; } .cython.code .pyx_c_api { color: #FF3000; } .cython.code .pyx_macro_api { color: #FF7000; } .cython.code .refnanny { color: #FFA000; } .cython.code .trace { color: #FFA000; } .cython.code .error_goto { color: #FFA000; } .cython.code .coerce { color: #008000; border: 1px dotted #008000 } .cython.code .py_attr { color: #FF0000; font-weight: bold; } .cython.code .c_attr { color: #0000FF; } .cython.code .py_call { color: #FF0000; font-weight: bold; } .cython.code .c_call { color: #0000FF; } """) # on-click toggle function to show/hide C source code _onclick_attr = ' onclick="{0}"'.format(( "(function(s){" " s.display = s.display === 'block' ? 'none' : 'block'" "})(this.nextElementSibling.style)" ).replace(' ', '') # poor dev's JS minification ) def save_annotation(self, source_filename, target_filename, coverage_xml=None): with Utils.open_source_file(source_filename) as f: code = f.read() generated_code = self.code.get(source_filename, {}) c_file = Utils.decode_filename(os.path.basename(target_filename)) html_filename = os.path.splitext(target_filename)[0] + ".html" with codecs.open(html_filename, "w", encoding="UTF-8") as out_buffer: out_buffer.write(self._save_annotation(code, generated_code, c_file, source_filename, coverage_xml)) def _save_annotation_header(self, c_file, source_filename, coverage_timestamp=None): coverage_info = '' if coverage_timestamp: coverage_info = u' with coverage data from {timestamp}'.format( timestamp=datetime.fromtimestamp(int(coverage_timestamp) // 1000)) outlist = [ textwrap.dedent(u'''\ Cython: {filename}

Generated by Cython {watermark}{more_info}

Yellow lines hint at Python interaction.
Click on a line that starts with a "+" to see the C code that Cython generated for it.

''').format(css=self._css(), watermark=Version.watermark, filename=os.path.basename(source_filename) if source_filename else '', more_info=coverage_info) ] if c_file: outlist.append(u'

Raw output: %s

\n' % (c_file, c_file)) return outlist def _save_annotation_footer(self): return (u'\n',) def _save_annotation(self, code, generated_code, c_file=None, source_filename=None, coverage_xml=None): """ lines : original cython source code split by lines generated_code : generated c code keyed by line number in original file target filename : name of the file in which to store the generated html c_file : filename in which the c_code has been written """ if coverage_xml is not None and source_filename: coverage_timestamp = coverage_xml.get('timestamp', '').strip() covered_lines = self._get_line_coverage(coverage_xml, source_filename) else: coverage_timestamp = covered_lines = None annotation_items = dict(self.annotations[source_filename]) scopes = dict(self.scopes[source_filename]) outlist = [] outlist.extend(self._save_annotation_header(c_file, source_filename, coverage_timestamp)) outlist.extend(self._save_annotation_body(code, generated_code, annotation_items, scopes, covered_lines)) outlist.extend(self._save_annotation_footer()) return ''.join(outlist) def _get_line_coverage(self, coverage_xml, source_filename): coverage_data = None for entry in coverage_xml.iterfind('.//class'): if not entry.get('filename'): continue if (entry.get('filename') == source_filename or os.path.abspath(entry.get('filename')) == source_filename): coverage_data = entry break elif source_filename.endswith(entry.get('filename')): coverage_data = entry # but we might still find a better match... if coverage_data is None: return None return dict( (int(line.get('number')), int(line.get('hits'))) for line in coverage_data.iterfind('lines/line') ) def _htmlify_code(self, code, language): try: from pygments import highlight from pygments.lexers import CythonLexer, CppLexer from pygments.formatters import HtmlFormatter except ImportError: # no Pygments, just escape the code return html_escape(code) if language == "cython": lexer = CythonLexer(stripnl=False, stripall=False) elif language == "c/cpp": lexer = CppLexer(stripnl=False, stripall=False) else: # unknown language, use fallback return html_escape(code) html_code = highlight( code, lexer, HtmlFormatter(nowrap=True)) return html_code def _save_annotation_body(self, cython_code, generated_code, annotation_items, scopes, covered_lines=None): outlist = [u'
'] pos_comment_marker = u'/* \N{HORIZONTAL ELLIPSIS} */\n' new_calls_map = dict( (name, 0) for name in 'refnanny trace py_macro_api py_c_api pyx_macro_api pyx_c_api error_goto'.split() ).copy self.mark_pos(None) def annotate(match): group_name = match.lastgroup calls[group_name] += 1 return u"%s" % ( group_name, match.group(group_name)) lines = self._htmlify_code(cython_code, "cython").splitlines() lineno_width = len(str(len(lines))) if not covered_lines: covered_lines = None for k, line in enumerate(lines, 1): try: c_code = generated_code[k] except KeyError: c_code = '' else: c_code = _replace_pos_comment(pos_comment_marker, c_code) if c_code.startswith(pos_comment_marker): c_code = c_code[len(pos_comment_marker):] c_code = html_escape(c_code) calls = new_calls_map() c_code = _parse_code(annotate, c_code) score = (5 * calls['py_c_api'] + 2 * calls['pyx_c_api'] + calls['py_macro_api'] + calls['pyx_macro_api']) if c_code: onclick = self._onclick_attr expandsymbol = '+' else: onclick = '' expandsymbol = ' ' covered = '' if covered_lines is not None and k in covered_lines: hits = covered_lines[k] if hits is not None: covered = 'run' if hits else 'mis' outlist.append( u'
'
                # generate line number with expand symbol in front,
                # and the right  number of digit
                u'{expandsymbol}{line:0{lineno_width}d}: {code}
\n'.format( score=score, expandsymbol=expandsymbol, covered=covered, lineno_width=lineno_width, line=k, code=line.rstrip(), onclick=onclick, )) if c_code: outlist.append(u"
{code}
".format( score=score, covered=covered, code=c_code)) outlist.append(u"
") # now the whole c-code if needed: if self.show_entire_c_code: outlist.append(u'

') onclick_title = u"
+ {title}
\n" outlist.append(onclick_title.format( onclick=self._onclick_attr, title=AnnotationCCodeWriter.COMPLETE_CODE_TITLE, )) complete_code_as_html = self._htmlify_code(self.buffer.getvalue(), "c/cpp") outlist.append(u"
{code}
".format(code=complete_code_as_html)) outlist.append(u"

") return outlist _parse_code = re.compile(( br'(?P__Pyx_X?(?:GOT|GIVE)REF|__Pyx_RefNanny[A-Za-z]+)|' br'(?P__Pyx_Trace[A-Za-z]+)|' br'(?:' br'(?P__Pyx_[A-Z][A-Z_]+)|' br'(?P(?:__Pyx_[A-Z][a-z_][A-Za-z_]*)|__pyx_convert_[A-Za-z_]*)|' br'(?PPy[A-Z][a-z]+_[A-Z][A-Z_]+)|' br'(?PPy[A-Z][a-z]+_[A-Z][a-z][A-Za-z_]*)' br')(?=\()|' # look-ahead to exclude subsequent '(' from replacement br'(?P(?:(?<=;) *if [^;]* +)?__PYX_ERR\([^)]+\))' ).decode('ascii')).sub _replace_pos_comment = re.compile( # this matches what Cython generates as code line marker comment br'^\s*/\*(?:(?:[^*]|\*[^/])*\n)+\s*\*/\s*\n'.decode('ascii'), re.M ).sub class AnnotationItem(object): def __init__(self, style, text, tag="", size=0): self.style = style self.text = text self.tag = tag self.size = size def start(self): return u"%s" % (self.style, self.text, self.tag) def end(self): return self.size, u"" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Compiler/AutoDocTransforms.py0000644000175100001770000002673200000000000022613 0ustar00runnerdocker00000000000000from __future__ import absolute_import, print_function from .Visitor import CythonTransform from .StringEncoding import EncodedString from . import Options from . import PyrexTypes from ..CodeWriter import ExpressionWriter from .Errors import warning class AnnotationWriter(ExpressionWriter): """ A Cython code writer for Python expressions in argument/variable annotations. """ def __init__(self, description=None): """description is optional. If specified it is used in warning messages for the nodes that don't convert to string properly. If not specified then no messages are generated. """ ExpressionWriter.__init__(self) self.description = description self.incomplete = False def visit_Node(self, node): self.put(u"") self.incomplete = True if self.description: warning(node.pos, "Failed to convert code to string representation in {0}".format( self.description), level=1) def visit_LambdaNode(self, node): # XXX Should we do better? self.put("") self.incomplete = True if self.description: warning(node.pos, "Failed to convert lambda to string representation in {0}".format( self.description), level=1) def visit_UnicodeNode(self, node): # Discard Unicode prefix in annotations. Any tool looking at them # would probably expect Py3 string semantics. self.emit_string(node, "") def visit_AnnotationNode(self, node): self.put(node.string.unicode_value) class EmbedSignature(CythonTransform): def __init__(self, context): super(EmbedSignature, self).__init__(context) self.class_name = None self.class_node = None def _fmt_expr(self, node): writer = ExpressionWriter() result = writer.write(node) # print(type(node).__name__, '-->', result) return result def _fmt_annotation(self, node): writer = AnnotationWriter() result = writer.write(node) # print(type(node).__name__, '-->', result) return result def _setup_format(self): signature_format = self.current_directives['embedsignature.format'] self.is_format_c = signature_format == 'c' self.is_format_python = signature_format == 'python' self.is_format_clinic = signature_format == 'clinic' def _fmt_arg(self, arg): arg_doc = arg.name annotation = None defaultval = None if arg.is_self_arg: if self.is_format_clinic: arg_doc = '$self' elif arg.is_type_arg: if self.is_format_clinic: arg_doc = '$type' elif self.is_format_c: if arg.type is not PyrexTypes.py_object_type: arg_doc = arg.type.declaration_code(arg.name, for_display=1) elif self.is_format_python: if not arg.annotation: annotation = self._fmt_type(arg.type) if arg.annotation: if not self.is_format_clinic: annotation = self._fmt_annotation(arg.annotation) if arg.default: defaultval = self._fmt_expr(arg.default) if annotation: arg_doc = arg_doc + (': %s' % annotation) if defaultval: arg_doc = arg_doc + (' = %s' % defaultval) elif defaultval: arg_doc = arg_doc + ('=%s' % defaultval) return arg_doc def _fmt_star_arg(self, arg): arg_doc = arg.name if arg.annotation: if not self.is_format_clinic: annotation = self._fmt_annotation(arg.annotation) arg_doc = arg_doc + (': %s' % annotation) return arg_doc def _fmt_arglist(self, args, npoargs=0, npargs=0, pargs=None, nkargs=0, kargs=None, hide_self=False): arglist = [] for arg in args: if not hide_self or not arg.entry.is_self_arg: arg_doc = self._fmt_arg(arg) arglist.append(arg_doc) if pargs: arg_doc = self._fmt_star_arg(pargs) arglist.insert(npargs + npoargs, '*%s' % arg_doc) elif nkargs: arglist.insert(npargs + npoargs, '*') if npoargs: arglist.insert(npoargs, '/') if kargs: arg_doc = self._fmt_star_arg(kargs) arglist.append('**%s' % arg_doc) return arglist def _fmt_type(self, type): if type is PyrexTypes.py_object_type: return None elif self.is_format_c: code = type.declaration_code("", for_display=1) return code elif self.is_format_python: annotation = None if type.is_string: annotation = self.current_directives['c_string_type'] elif type.is_numeric: annotation = type.py_type_name() if annotation is None: code = type.declaration_code('', for_display=1) annotation = code.replace(' ', '_').replace('*', 'p') return annotation return None def _fmt_signature(self, cls_name, func_name, args, npoargs=0, npargs=0, pargs=None, nkargs=0, kargs=None, return_expr=None, return_type=None, hide_self=False): arglist = self._fmt_arglist( args, npoargs, npargs, pargs, nkargs, kargs, hide_self=hide_self, ) arglist_doc = ', '.join(arglist) func_doc = '%s(%s)' % (func_name, arglist_doc) if self.is_format_c and cls_name: func_doc = '%s.%s' % (cls_name, func_doc) if not self.is_format_clinic: ret_doc = None if return_expr: ret_doc = self._fmt_annotation(return_expr) elif return_type: ret_doc = self._fmt_type(return_type) if ret_doc: func_doc = '%s -> %s' % (func_doc, ret_doc) return func_doc def _embed_signature(self, signature, node_doc): if self.is_format_clinic and self.current_directives['binding']: return node_doc if node_doc: if self.is_format_clinic: docfmt = "%s\n--\n\n%s" else: docfmt = "%s\n%s" return docfmt % (signature, node_doc) else: if self.is_format_clinic: docfmt = "%s\n--\n\n" else: docfmt = "%s" return docfmt % signature def __call__(self, node): if not Options.docstrings: return node else: return super(EmbedSignature, self).__call__(node) def visit_ClassDefNode(self, node): oldname = self.class_name oldclass = self.class_node self.class_node = node try: # PyClassDefNode self.class_name = node.name except AttributeError: # CClassDefNode self.class_name = node.class_name self.visitchildren(node) self.class_name = oldname self.class_node = oldclass return node def visit_LambdaNode(self, node): # lambda expressions so not have signature or inner functions return node def visit_DefNode(self, node): if not self.current_directives['embedsignature']: return node self._setup_format() is_constructor = False hide_self = False if node.entry.is_special: is_constructor = self.class_node and node.name == '__init__' if not is_constructor: return node class_name = None func_name = node.name if self.is_format_c: func_name = self.class_name hide_self = True else: class_name, func_name = self.class_name, node.name npoargs = getattr(node, 'num_posonly_args', 0) nkargs = getattr(node, 'num_kwonly_args', 0) npargs = len(node.args) - nkargs - npoargs signature = self._fmt_signature( class_name, func_name, node.args, npoargs, npargs, node.star_arg, nkargs, node.starstar_arg, return_expr=node.return_type_annotation, return_type=None, hide_self=hide_self) if signature: if is_constructor and self.is_format_c: doc_holder = self.class_node.entry.type.scope else: doc_holder = node.entry if doc_holder.doc is not None: old_doc = doc_holder.doc elif not is_constructor and getattr(node, 'py_func', None) is not None: old_doc = node.py_func.entry.doc else: old_doc = None new_doc = self._embed_signature(signature, old_doc) doc_holder.doc = EncodedString(new_doc) if not is_constructor and getattr(node, 'py_func', None) is not None: node.py_func.entry.doc = EncodedString(new_doc) return node def visit_CFuncDefNode(self, node): if not node.overridable: # not cpdef FOO(...): return node if not self.current_directives['embedsignature']: return node self._setup_format() signature = self._fmt_signature( self.class_name, node.declarator.base.name, node.declarator.args, return_type=node.return_type) if signature: if node.entry.doc is not None: old_doc = node.entry.doc elif getattr(node, 'py_func', None) is not None: old_doc = node.py_func.entry.doc else: old_doc = None new_doc = self._embed_signature(signature, old_doc) node.entry.doc = EncodedString(new_doc) py_func = getattr(node, 'py_func', None) if py_func is not None: py_func.entry.doc = EncodedString(new_doc) return node def visit_PropertyNode(self, node): if not self.current_directives['embedsignature']: return node self._setup_format() entry = node.entry body = node.body prop_name = entry.name type_name = None if entry.visibility == 'public': if self.is_format_c: # property synthesised from a cdef public attribute type_name = entry.type.declaration_code("", for_display=1) if not entry.type.is_pyobject: type_name = "'%s'" % type_name elif entry.type.is_extension_type: type_name = entry.type.module_name + '.' + type_name elif self.is_format_python: type_name = self._fmt_type(entry.type) if type_name is None: for stat in body.stats: if stat.name != '__get__': continue if self.is_format_c: prop_name = '%s.%s' % (self.class_name, prop_name) ret_annotation = stat.return_type_annotation if ret_annotation: type_name = self._fmt_annotation(ret_annotation) if type_name is not None : signature = '%s: %s' % (prop_name, type_name) new_doc = self._embed_signature(signature, entry.doc) if not self.is_format_clinic: entry.doc = EncodedString(new_doc) return node ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Compiler/Buffer.py0000644000175100001770000007117000000000000020403 0ustar00runnerdocker00000000000000from __future__ import absolute_import from .Visitor import CythonTransform from .ModuleNode import ModuleNode from .Errors import CompileError from .UtilityCode import CythonUtilityCode from .Code import UtilityCode, TempitaUtilityCode from . import Options from . import Interpreter from . import PyrexTypes from . import Naming from . import Symtab def dedent(text, reindent=0): from textwrap import dedent text = dedent(text) if reindent > 0: indent = " " * reindent text = '\n'.join([indent + x for x in text.split('\n')]) return text class IntroduceBufferAuxiliaryVars(CythonTransform): # # Entry point # buffers_exists = False using_memoryview = False def __call__(self, node): assert isinstance(node, ModuleNode) self.max_ndim = 0 result = super(IntroduceBufferAuxiliaryVars, self).__call__(node) if self.buffers_exists: use_bufstruct_declare_code(node.scope) use_py2_buffer_functions(node.scope) return result # # Basic operations for transforms # def handle_scope(self, node, scope): # For all buffers, insert extra variables in the scope. # The variables are also accessible from the buffer_info # on the buffer entry scope_items = scope.entries.items() bufvars = [entry for name, entry in scope_items if entry.type.is_buffer] if len(bufvars) > 0: bufvars.sort(key=lambda entry: entry.name) self.buffers_exists = True memviewslicevars = [entry for name, entry in scope_items if entry.type.is_memoryviewslice] if len(memviewslicevars) > 0: self.buffers_exists = True for (name, entry) in scope_items: if name == 'memoryview' and isinstance(entry.utility_code_definition, CythonUtilityCode): self.using_memoryview = True break del scope_items if isinstance(node, ModuleNode) and len(bufvars) > 0: # for now...note that pos is wrong raise CompileError(node.pos, "Buffer vars not allowed in module scope") for entry in bufvars: if entry.type.dtype.is_ptr: raise CompileError(node.pos, "Buffers with pointer types not yet supported.") name = entry.name buftype = entry.type if buftype.ndim > Options.buffer_max_dims: raise CompileError(node.pos, "Buffer ndims exceeds Options.buffer_max_dims = %d" % Options.buffer_max_dims) if buftype.ndim > self.max_ndim: self.max_ndim = buftype.ndim # Declare auxiliary vars def decvar(type, prefix): cname = scope.mangle(prefix, name) aux_var = scope.declare_var(name=None, cname=cname, type=type, pos=node.pos) if entry.is_arg: aux_var.used = True # otherwise, NameNode will mark whether it is used return aux_var auxvars = ((PyrexTypes.c_pyx_buffer_nd_type, Naming.pybuffernd_prefix), (PyrexTypes.c_pyx_buffer_type, Naming.pybufferstruct_prefix)) pybuffernd, rcbuffer = [decvar(type, prefix) for (type, prefix) in auxvars] entry.buffer_aux = Symtab.BufferAux(pybuffernd, rcbuffer) scope.buffer_entries = bufvars self.scope = scope def visit_ModuleNode(self, node): self.handle_scope(node, node.scope) self.visitchildren(node) return node def visit_FuncDefNode(self, node): self.handle_scope(node, node.local_scope) self.visitchildren(node) return node # # Analysis # buffer_options = ("dtype", "ndim", "mode", "negative_indices", "cast") # ordered! buffer_defaults = {"ndim": 1, "mode": "full", "negative_indices": True, "cast": False} buffer_positional_options_count = 1 # anything beyond this needs keyword argument ERR_BUF_OPTION_UNKNOWN = '"%s" is not a buffer option' ERR_BUF_TOO_MANY = 'Too many buffer options' ERR_BUF_DUP = '"%s" buffer option already supplied' ERR_BUF_MISSING = '"%s" missing' ERR_BUF_MODE = 'Only allowed buffer modes are: "c", "fortran", "full", "strided" (as a compile-time string)' ERR_BUF_NDIM = 'ndim must be a non-negative integer' ERR_BUF_DTYPE = 'dtype must be "object", numeric type or a struct' ERR_BUF_BOOL = '"%s" must be a boolean' def analyse_buffer_options(globalpos, env, posargs, dictargs, defaults=None, need_complete=True): """ Must be called during type analysis, as analyse is called on the dtype argument. posargs and dictargs should consist of a list and a dict of tuples (value, pos). Defaults should be a dict of values. Returns a dict containing all the options a buffer can have and its value (with the positions stripped). """ if defaults is None: defaults = buffer_defaults posargs, dictargs = Interpreter.interpret_compiletime_options( posargs, dictargs, type_env=env, type_args=(0, 'dtype')) if len(posargs) > buffer_positional_options_count: raise CompileError(posargs[-1][1], ERR_BUF_TOO_MANY) options = {} for name, (value, pos) in dictargs.items(): if name not in buffer_options: raise CompileError(pos, ERR_BUF_OPTION_UNKNOWN % name) options[name] = value for name, (value, pos) in zip(buffer_options, posargs): if name not in buffer_options: raise CompileError(pos, ERR_BUF_OPTION_UNKNOWN % name) if name in options: raise CompileError(pos, ERR_BUF_DUP % name) options[name] = value # Check that they are all there and copy defaults for name in buffer_options: if name not in options: try: options[name] = defaults[name] except KeyError: if need_complete: raise CompileError(globalpos, ERR_BUF_MISSING % name) dtype = options.get("dtype") if dtype and dtype.is_extension_type: raise CompileError(globalpos, ERR_BUF_DTYPE) ndim = options.get("ndim") if ndim and (not isinstance(ndim, int) or ndim < 0): raise CompileError(globalpos, ERR_BUF_NDIM) mode = options.get("mode") if mode and not (mode in ('full', 'strided', 'c', 'fortran')): raise CompileError(globalpos, ERR_BUF_MODE) def assert_bool(name): x = options.get(name) if not isinstance(x, bool): raise CompileError(globalpos, ERR_BUF_BOOL % name) assert_bool('negative_indices') assert_bool('cast') return options # # Code generation # class BufferEntry(object): def __init__(self, entry): self.entry = entry self.type = entry.type self.cname = entry.buffer_aux.buflocal_nd_var.cname self.buf_ptr = "%s.rcbuffer->pybuffer.buf" % self.cname self.buf_ptr_type = entry.type.buffer_ptr_type self.init_attributes() def init_attributes(self): self.shape = self.get_buf_shapevars() self.strides = self.get_buf_stridevars() self.suboffsets = self.get_buf_suboffsetvars() def get_buf_suboffsetvars(self): return self._for_all_ndim("%s.diminfo[%d].suboffsets") def get_buf_stridevars(self): return self._for_all_ndim("%s.diminfo[%d].strides") def get_buf_shapevars(self): return self._for_all_ndim("%s.diminfo[%d].shape") def _for_all_ndim(self, s): return [s % (self.cname, i) for i in range(self.type.ndim)] def generate_buffer_lookup_code(self, code, index_cnames): # Create buffer lookup and return it # This is done via utility macros/inline functions, which vary # according to the access mode used. params = [] nd = self.type.ndim mode = self.type.mode if mode == 'full': for i, s, o in zip(index_cnames, self.get_buf_stridevars(), self.get_buf_suboffsetvars()): params.append(i) params.append(s) params.append(o) funcname = "__Pyx_BufPtrFull%dd" % nd funcgen = buf_lookup_full_code else: if mode == 'strided': funcname = "__Pyx_BufPtrStrided%dd" % nd funcgen = buf_lookup_strided_code elif mode == 'c': funcname = "__Pyx_BufPtrCContig%dd" % nd funcgen = buf_lookup_c_code elif mode == 'fortran': funcname = "__Pyx_BufPtrFortranContig%dd" % nd funcgen = buf_lookup_fortran_code else: assert False for i, s in zip(index_cnames, self.get_buf_stridevars()): params.append(i) params.append(s) # Make sure the utility code is available if funcname not in code.globalstate.utility_codes: code.globalstate.utility_codes.add(funcname) protocode = code.globalstate['utility_code_proto'] defcode = code.globalstate['utility_code_def'] funcgen(protocode, defcode, name=funcname, nd=nd) buf_ptr_type_code = self.buf_ptr_type.empty_declaration_code() ptrcode = "%s(%s, %s, %s)" % (funcname, buf_ptr_type_code, self.buf_ptr, ", ".join(params)) return ptrcode def get_flags(buffer_aux, buffer_type): flags = 'PyBUF_FORMAT' mode = buffer_type.mode if mode == 'full': flags += '| PyBUF_INDIRECT' elif mode == 'strided': flags += '| PyBUF_STRIDES' elif mode == 'c': flags += '| PyBUF_C_CONTIGUOUS' elif mode == 'fortran': flags += '| PyBUF_F_CONTIGUOUS' else: assert False if buffer_aux.writable_needed: flags += "| PyBUF_WRITABLE" return flags def used_buffer_aux_vars(entry): buffer_aux = entry.buffer_aux buffer_aux.buflocal_nd_var.used = True buffer_aux.rcbuf_var.used = True def put_unpack_buffer_aux_into_scope(buf_entry, code): # Generate code to copy the needed struct info into local # variables. buffer_aux, mode = buf_entry.buffer_aux, buf_entry.type.mode pybuffernd_struct = buffer_aux.buflocal_nd_var.cname fldnames = ['strides', 'shape'] if mode == 'full': fldnames.append('suboffsets') ln = [] for i in range(buf_entry.type.ndim): for fldname in fldnames: ln.append("%s.diminfo[%d].%s = %s.rcbuffer->pybuffer.%s[%d];" % ( pybuffernd_struct, i, fldname, pybuffernd_struct, fldname, i, )) code.putln(' '.join(ln)) def put_init_vars(entry, code): bufaux = entry.buffer_aux pybuffernd_struct = bufaux.buflocal_nd_var.cname pybuffer_struct = bufaux.rcbuf_var.cname # init pybuffer_struct code.putln("%s.pybuffer.buf = NULL;" % pybuffer_struct) code.putln("%s.refcount = 0;" % pybuffer_struct) # init the buffer object # code.put_init_var_to_py_none(entry) # init the pybuffernd_struct code.putln("%s.data = NULL;" % pybuffernd_struct) code.putln("%s.rcbuffer = &%s;" % (pybuffernd_struct, pybuffer_struct)) def put_acquire_arg_buffer(entry, code, pos): buffer_aux = entry.buffer_aux getbuffer = get_getbuffer_call(code, entry.cname, buffer_aux, entry.type) # Acquire any new buffer code.putln("{") code.putln("__Pyx_BufFmt_StackElem __pyx_stack[%d];" % entry.type.dtype.struct_nesting_depth()) code.putln(code.error_goto_if("%s == -1" % getbuffer, pos)) code.putln("}") # An exception raised in arg parsing cannot be caught, so no # need to care about the buffer then. put_unpack_buffer_aux_into_scope(entry, code) def put_release_buffer_code(code, entry): code.globalstate.use_utility_code(acquire_utility_code) code.putln("__Pyx_SafeReleaseBuffer(&%s.rcbuffer->pybuffer);" % entry.buffer_aux.buflocal_nd_var.cname) def get_getbuffer_call(code, obj_cname, buffer_aux, buffer_type): ndim = buffer_type.ndim cast = int(buffer_type.cast) flags = get_flags(buffer_aux, buffer_type) pybuffernd_struct = buffer_aux.buflocal_nd_var.cname dtype_typeinfo = get_type_information_cname(code, buffer_type.dtype) code.globalstate.use_utility_code(acquire_utility_code) return ("__Pyx_GetBufferAndValidate(&%(pybuffernd_struct)s.rcbuffer->pybuffer, " "(PyObject*)%(obj_cname)s, &%(dtype_typeinfo)s, %(flags)s, %(ndim)d, " "%(cast)d, __pyx_stack)" % locals()) def put_assign_to_buffer(lhs_cname, rhs_cname, buf_entry, is_initialized, pos, code): """ Generate code for reassigning a buffer variables. This only deals with getting the buffer auxiliary structure and variables set up correctly, the assignment itself and refcounting is the responsibility of the caller. However, the assignment operation may throw an exception so that the reassignment never happens. Depending on the circumstances there are two possible outcomes: - Old buffer released, new acquired, rhs assigned to lhs - Old buffer released, new acquired which fails, reaqcuire old lhs buffer (which may or may not succeed). """ buffer_aux, buffer_type = buf_entry.buffer_aux, buf_entry.type pybuffernd_struct = buffer_aux.buflocal_nd_var.cname flags = get_flags(buffer_aux, buffer_type) code.putln("{") # Set up necessary stack for getbuffer code.putln("__Pyx_BufFmt_StackElem __pyx_stack[%d];" % buffer_type.dtype.struct_nesting_depth()) getbuffer = get_getbuffer_call(code, "%s", buffer_aux, buffer_type) # fill in object below if is_initialized: # Release any existing buffer code.putln('__Pyx_SafeReleaseBuffer(&%s.rcbuffer->pybuffer);' % pybuffernd_struct) # Acquire retcode_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False) code.putln("%s = %s;" % (retcode_cname, getbuffer % rhs_cname)) code.putln('if (%s) {' % (code.unlikely("%s < 0" % retcode_cname))) # If acquisition failed, attempt to reacquire the old buffer # before raising the exception. A failure of reacquisition # will cause the reacquisition exception to be reported, one # can consider working around this later. exc_temps = tuple(code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=False) for _ in range(3)) code.putln('PyErr_Fetch(&%s, &%s, &%s);' % exc_temps) code.putln('if (%s) {' % code.unlikely("%s == -1" % (getbuffer % lhs_cname))) code.putln('Py_XDECREF(%s); Py_XDECREF(%s); Py_XDECREF(%s);' % exc_temps) # Do not refnanny these! code.globalstate.use_utility_code(raise_buffer_fallback_code) code.putln('__Pyx_RaiseBufferFallbackError();') code.putln('} else {') code.putln('PyErr_Restore(%s, %s, %s);' % exc_temps) code.putln('}') code.putln('%s = %s = %s = 0;' % exc_temps) for t in exc_temps: code.funcstate.release_temp(t) code.putln('}') # Unpack indices put_unpack_buffer_aux_into_scope(buf_entry, code) code.putln(code.error_goto_if_neg(retcode_cname, pos)) code.funcstate.release_temp(retcode_cname) else: # Our entry had no previous value, so set to None when acquisition fails. # In this case, auxiliary vars should be set up right in initialization to a zero-buffer, # so it suffices to set the buf field to NULL. code.putln('if (%s) {' % code.unlikely("%s == -1" % (getbuffer % rhs_cname))) code.putln('%s = %s; __Pyx_INCREF(Py_None); %s.rcbuffer->pybuffer.buf = NULL;' % (lhs_cname, PyrexTypes.typecast(buffer_type, PyrexTypes.py_object_type, "Py_None"), pybuffernd_struct)) code.putln(code.error_goto(pos)) code.put('} else {') # Unpack indices put_unpack_buffer_aux_into_scope(buf_entry, code) code.putln('}') code.putln("}") # Release stack def put_buffer_lookup_code(entry, index_signeds, index_cnames, directives, pos, code, negative_indices, in_nogil_context): """ Generates code to process indices and calculate an offset into a buffer. Returns a C string which gives a pointer which can be read from or written to at will (it is an expression so caller should store it in a temporary if it is used more than once). As the bounds checking can have any number of combinations of unsigned arguments, smart optimizations etc. we insert it directly in the function body. The lookup however is delegated to a inline function that is instantiated once per ndim (lookup with suboffsets tend to get quite complicated). entry is a BufferEntry """ negative_indices = directives['wraparound'] and negative_indices if directives['boundscheck']: # Check bounds and fix negative indices. # We allocate a temporary which is initialized to -1, meaning OK (!). # If an error occurs, the temp is set to the index dimension the # error is occurring at. failed_dim_temp = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False) code.putln("%s = -1;" % failed_dim_temp) for dim, (signed, cname, shape) in enumerate(zip(index_signeds, index_cnames, entry.get_buf_shapevars())): if signed != 0: # not unsigned, deal with negative index code.putln("if (%s < 0) {" % cname) if negative_indices: code.putln("%s += %s;" % (cname, shape)) code.putln("if (%s) %s = %d;" % ( code.unlikely("%s < 0" % cname), failed_dim_temp, dim)) else: code.putln("%s = %d;" % (failed_dim_temp, dim)) code.put("} else ") # check bounds in positive direction if signed != 0: cast = "" else: cast = "(size_t)" code.putln("if (%s) %s = %d;" % ( code.unlikely("%s >= %s%s" % (cname, cast, shape)), failed_dim_temp, dim)) if in_nogil_context: code.globalstate.use_utility_code(raise_indexerror_nogil) func = '__Pyx_RaiseBufferIndexErrorNogil' else: code.globalstate.use_utility_code(raise_indexerror_code) func = '__Pyx_RaiseBufferIndexError' code.putln("if (%s) {" % code.unlikely("%s != -1" % failed_dim_temp)) code.putln('%s(%s);' % (func, failed_dim_temp)) code.putln(code.error_goto(pos)) code.putln('}') code.funcstate.release_temp(failed_dim_temp) elif negative_indices: # Only fix negative indices. for signed, cname, shape in zip(index_signeds, index_cnames, entry.get_buf_shapevars()): if signed != 0: code.putln("if (%s < 0) %s += %s;" % (cname, cname, shape)) return entry.generate_buffer_lookup_code(code, index_cnames) def use_bufstruct_declare_code(env): env.use_utility_code(buffer_struct_declare_code) def buf_lookup_full_code(proto, defin, name, nd): """ Generates a buffer lookup function for the right number of dimensions. The function gives back a void* at the right location. """ # _i_ndex, _s_tride, sub_o_ffset macroargs = ", ".join(["i%d, s%d, o%d" % (i, i, i) for i in range(nd)]) proto.putln("#define %s(type, buf, %s) (type)(%s_imp(buf, %s))" % (name, macroargs, name, macroargs)) funcargs = ", ".join(["Py_ssize_t i%d, Py_ssize_t s%d, Py_ssize_t o%d" % (i, i, i) for i in range(nd)]) proto.putln("static CYTHON_INLINE void* %s_imp(void* buf, %s);" % (name, funcargs)) defin.putln(dedent(""" static CYTHON_INLINE void* %s_imp(void* buf, %s) { char* ptr = (char*)buf; """) % (name, funcargs) + "".join([dedent("""\ ptr += s%d * i%d; if (o%d >= 0) ptr = *((char**)ptr) + o%d; """) % (i, i, i, i) for i in range(nd)] ) + "\nreturn ptr;\n}") def buf_lookup_strided_code(proto, defin, name, nd): """ Generates a buffer lookup function for the right number of dimensions. The function gives back a void* at the right location. """ # _i_ndex, _s_tride args = ", ".join(["i%d, s%d" % (i, i) for i in range(nd)]) offset = " + ".join(["i%d * s%d" % (i, i) for i in range(nd)]) proto.putln("#define %s(type, buf, %s) (type)((char*)buf + %s)" % (name, args, offset)) def buf_lookup_c_code(proto, defin, name, nd): """ Similar to strided lookup, but can assume that the last dimension doesn't need a multiplication as long as. Still we keep the same signature for now. """ if nd == 1: proto.putln("#define %s(type, buf, i0, s0) ((type)buf + i0)" % name) else: args = ", ".join(["i%d, s%d" % (i, i) for i in range(nd)]) offset = " + ".join(["i%d * s%d" % (i, i) for i in range(nd - 1)]) proto.putln("#define %s(type, buf, %s) ((type)((char*)buf + %s) + i%d)" % (name, args, offset, nd - 1)) def buf_lookup_fortran_code(proto, defin, name, nd): """ Like C lookup, but the first index is optimized instead. """ if nd == 1: proto.putln("#define %s(type, buf, i0, s0) ((type)buf + i0)" % name) else: args = ", ".join(["i%d, s%d" % (i, i) for i in range(nd)]) offset = " + ".join(["i%d * s%d" % (i, i) for i in range(1, nd)]) proto.putln("#define %s(type, buf, %s) ((type)((char*)buf + %s) + i%d)" % (name, args, offset, 0)) def use_py2_buffer_functions(env): env.use_utility_code(GetAndReleaseBufferUtilityCode()) class GetAndReleaseBufferUtilityCode(object): # Emulation of PyObject_GetBuffer and PyBuffer_Release for Python 2. # For >= 2.6 we do double mode -- use the new buffer interface on objects # which has the right tp_flags set, but emulation otherwise. requires = None is_cython_utility = False def __init__(self): pass def __eq__(self, other): return isinstance(other, GetAndReleaseBufferUtilityCode) def __hash__(self): return 24342342 def get_tree(self, **kwargs): pass def put_code(self, output): code = output['utility_code_def'] proto_code = output['utility_code_proto'] env = output.module_node.scope cython_scope = env.context.cython_scope # Search all types for __getbuffer__ overloads types = [] visited_scopes = set() def find_buffer_types(scope): if scope in visited_scopes: return visited_scopes.add(scope) for m in scope.cimported_modules: find_buffer_types(m) for e in scope.type_entries: if isinstance(e.utility_code_definition, CythonUtilityCode): continue t = e.type if t.is_extension_type: if scope is cython_scope and not e.used: continue release = get = None for x in t.scope.pyfunc_entries: if x.name == u"__getbuffer__": get = x.func_cname elif x.name == u"__releasebuffer__": release = x.func_cname if get: types.append((t.typeptr_cname, get, release)) find_buffer_types(env) util_code = TempitaUtilityCode.load( "GetAndReleaseBuffer", from_file="Buffer.c", context=dict(types=types)) proto = util_code.format_code(util_code.proto) impl = util_code.format_code( util_code.inject_string_constants(util_code.impl, output)[1]) proto_code.putln(proto) code.putln(impl) def mangle_dtype_name(dtype): # Use prefixes to separate user defined types from builtins # (consider "typedef float unsigned_int") if dtype.is_pyobject: return "object" elif dtype.is_ptr: return "ptr" else: if dtype.is_typedef or dtype.is_struct_or_union: prefix = "nn_" else: prefix = "" return prefix + dtype.specialization_name() def get_type_information_cname(code, dtype, maxdepth=None): """ Output the run-time type information (__Pyx_TypeInfo) for given dtype, and return the name of the type info struct. Structs with two floats of the same size are encoded as complex numbers. One can separate between complex numbers declared as struct or with native encoding by inspecting to see if the fields field of the type is filled in. """ namesuffix = mangle_dtype_name(dtype) name = "__Pyx_TypeInfo_%s" % namesuffix structinfo_name = "__Pyx_StructFields_%s" % namesuffix if dtype.is_error: return "" # It's critical that walking the type info doesn't use more stack # depth than dtype.struct_nesting_depth() returns, so use an assertion for this if maxdepth is None: maxdepth = dtype.struct_nesting_depth() if maxdepth <= 0: assert False if name not in code.globalstate.utility_codes: code.globalstate.utility_codes.add(name) typecode = code.globalstate['typeinfo'] arraysizes = [] if dtype.is_array: while dtype.is_array: arraysizes.append(dtype.size) dtype = dtype.base_type complex_possible = dtype.is_struct_or_union and dtype.can_be_complex() declcode = dtype.empty_declaration_code() if dtype.is_simple_buffer_dtype(): structinfo_name = "NULL" elif dtype.is_struct: struct_scope = dtype.scope if dtype.is_cv_qualified: struct_scope = struct_scope.base_type_scope # Must pre-call all used types in order not to recurse during utility code writing. fields = struct_scope.var_entries assert len(fields) > 0 types = [get_type_information_cname(code, f.type, maxdepth - 1) for f in fields] typecode.putln("static __Pyx_StructField %s[] = {" % structinfo_name, safe=True) if dtype.is_cv_qualified: # roughly speaking, remove "const" from struct_type struct_type = dtype.cv_base_type.empty_declaration_code() else: struct_type = dtype.empty_declaration_code() for f, typeinfo in zip(fields, types): typecode.putln(' {&%s, "%s", offsetof(%s, %s)},' % (typeinfo, f.name, struct_type, f.cname), safe=True) typecode.putln(' {NULL, NULL, 0}', safe=True) typecode.putln("};", safe=True) else: assert False rep = str(dtype) flags = "0" is_unsigned = "0" if dtype is PyrexTypes.c_char_type: is_unsigned = "__PYX_IS_UNSIGNED(%s)" % declcode typegroup = "'H'" elif dtype.is_int: is_unsigned = "__PYX_IS_UNSIGNED(%s)" % declcode typegroup = "%s ? 'U' : 'I'" % is_unsigned elif complex_possible or dtype.is_complex: typegroup = "'C'" elif dtype.is_float: typegroup = "'R'" elif dtype.is_struct: typegroup = "'S'" if dtype.packed: flags = "__PYX_BUF_FLAGS_PACKED_STRUCT" elif dtype.is_pyobject: typegroup = "'O'" else: assert False, dtype typeinfo = ('static __Pyx_TypeInfo %s = ' '{ "%s", %s, sizeof(%s), { %s }, %s, %s, %s, %s };') tup = (name, rep, structinfo_name, declcode, ', '.join([str(x) for x in arraysizes]) or '0', len(arraysizes), typegroup, is_unsigned, flags) typecode.putln(typeinfo % tup, safe=True) return name def load_buffer_utility(util_code_name, context=None, **kwargs): if context is None: return UtilityCode.load(util_code_name, "Buffer.c", **kwargs) else: return TempitaUtilityCode.load(util_code_name, "Buffer.c", context=context, **kwargs) context = dict(max_dims=Options.buffer_max_dims) buffer_struct_declare_code = load_buffer_utility("BufferStructDeclare", context=context) buffer_formats_declare_code = load_buffer_utility("BufferFormatStructs") # Utility function to set the right exception # The caller should immediately goto_error raise_indexerror_code = load_buffer_utility("BufferIndexError") raise_indexerror_nogil = load_buffer_utility("BufferIndexErrorNogil") raise_buffer_fallback_code = load_buffer_utility("BufferFallbackError") acquire_utility_code = load_buffer_utility("BufferGetAndValidate", context=context) buffer_format_check_code = load_buffer_utility("BufferFormatCheck", context=context) # See utility code BufferFormatFromTypeInfo _typeinfo_to_format_code = load_buffer_utility("TypeInfoToFormat") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Compiler/Builtin.py0000644000175100001770000007650300000000000020605 0ustar00runnerdocker00000000000000# # Builtin Definitions # from __future__ import absolute_import from .StringEncoding import EncodedString from .Symtab import BuiltinScope, StructOrUnionScope, ModuleScope, Entry from .Code import UtilityCode, TempitaUtilityCode from .TypeSlots import Signature from . import PyrexTypes # C-level implementations of builtin types, functions and methods iter_next_utility_code = UtilityCode.load("IterNext", "ObjectHandling.c") getattr_utility_code = UtilityCode.load("GetAttr", "ObjectHandling.c") getattr3_utility_code = UtilityCode.load("GetAttr3", "Builtins.c") pyexec_utility_code = UtilityCode.load("PyExec", "Builtins.c") pyexec_globals_utility_code = UtilityCode.load("PyExecGlobals", "Builtins.c") globals_utility_code = UtilityCode.load("Globals", "Builtins.c") builtin_utility_code = { 'StopAsyncIteration': UtilityCode.load_cached("StopAsyncIteration", "Coroutine.c"), } # mapping from builtins to their C-level equivalents class _BuiltinOverride(object): def __init__(self, py_name, args, ret_type, cname, py_equiv="*", utility_code=None, sig=None, func_type=None, is_strict_signature=False, builtin_return_type=None, nogil=None): self.py_name, self.cname, self.py_equiv = py_name, cname, py_equiv self.args, self.ret_type = args, ret_type self.func_type, self.sig = func_type, sig self.builtin_return_type = builtin_return_type self.is_strict_signature = is_strict_signature self.utility_code = utility_code self.nogil = nogil def build_func_type(self, sig=None, self_arg=None): if sig is None: sig = Signature(self.args, self.ret_type, nogil=self.nogil) sig.exception_check = False # not needed for the current builtins func_type = sig.function_type(self_arg) if self.is_strict_signature: func_type.is_strict_signature = True if self.builtin_return_type: func_type.return_type = builtin_types[self.builtin_return_type] return func_type class BuiltinAttribute(object): def __init__(self, py_name, cname=None, field_type=None, field_type_name=None): self.py_name = py_name self.cname = cname or py_name self.field_type_name = field_type_name # can't do the lookup before the type is declared! self.field_type = field_type def declare_in_type(self, self_type): if self.field_type_name is not None: # lazy type lookup field_type = builtin_scope.lookup(self.field_type_name).type else: field_type = self.field_type or PyrexTypes.py_object_type entry = self_type.scope.declare(self.py_name, self.cname, field_type, None, 'private') entry.is_variable = True class BuiltinFunction(_BuiltinOverride): def declare_in_scope(self, scope): func_type, sig = self.func_type, self.sig if func_type is None: func_type = self.build_func_type(sig) scope.declare_builtin_cfunction(self.py_name, func_type, self.cname, self.py_equiv, self.utility_code) class BuiltinMethod(_BuiltinOverride): def declare_in_type(self, self_type): method_type, sig = self.func_type, self.sig if method_type is None: # override 'self' type (first argument) self_arg = PyrexTypes.CFuncTypeArg("", self_type, None) self_arg.not_none = True self_arg.accept_builtin_subtypes = True method_type = self.build_func_type(sig, self_arg) self_type.scope.declare_builtin_cfunction( self.py_name, method_type, self.cname, utility_code=self.utility_code) class BuiltinProperty(object): # read only for now def __init__(self, py_name, property_type, call_cname, exception_value=None, exception_check=None, utility_code=None): self.py_name = py_name self.property_type = property_type self.call_cname = call_cname self.utility_code = utility_code self.exception_value = exception_value self.exception_check = exception_check def declare_in_type(self, self_type): self_type.scope.declare_cproperty( self.py_name, self.property_type, self.call_cname, exception_value=self.exception_value, exception_check=self.exception_check, utility_code=self.utility_code ) builtin_function_table = [ # name, args, return, C API func, py equiv = "*" BuiltinFunction('abs', "d", "d", "fabs", is_strict_signature=True, nogil=True), BuiltinFunction('abs', "f", "f", "fabsf", is_strict_signature=True, nogil=True), BuiltinFunction('abs', "i", "i", "abs", is_strict_signature=True, nogil=True), BuiltinFunction('abs', "l", "l", "labs", is_strict_signature=True, nogil=True), BuiltinFunction('abs', None, None, "__Pyx_abs_longlong", utility_code = UtilityCode.load("abs_longlong", "Builtins.c"), func_type = PyrexTypes.CFuncType( PyrexTypes.c_longlong_type, [ PyrexTypes.CFuncTypeArg("arg", PyrexTypes.c_longlong_type, None) ], is_strict_signature = True, nogil=True)), ] + list( BuiltinFunction('abs', None, None, "/*abs_{0}*/".format(t.specialization_name()), func_type = PyrexTypes.CFuncType( t, [PyrexTypes.CFuncTypeArg("arg", t, None)], is_strict_signature = True, nogil=True)) for t in (PyrexTypes.c_uint_type, PyrexTypes.c_ulong_type, PyrexTypes.c_ulonglong_type) ) + list( BuiltinFunction('abs', None, None, "__Pyx_c_abs{0}".format(t.funcsuffix), func_type = PyrexTypes.CFuncType( t.real_type, [ PyrexTypes.CFuncTypeArg("arg", t, None) ], is_strict_signature = True, nogil=True)) for t in (PyrexTypes.c_float_complex_type, PyrexTypes.c_double_complex_type, PyrexTypes.c_longdouble_complex_type) ) + [ BuiltinFunction('abs', "O", "O", "__Pyx_PyNumber_Absolute", utility_code=UtilityCode.load("py_abs", "Builtins.c")), #('all', "", "", ""), #('any', "", "", ""), #('ascii', "", "", ""), #('bin', "", "", ""), BuiltinFunction('callable', "O", "b", "__Pyx_PyCallable_Check", utility_code = UtilityCode.load("CallableCheck", "ObjectHandling.c")), #('chr', "", "", ""), #('cmp', "", "", "", ""), # int PyObject_Cmp(PyObject *o1, PyObject *o2, int *result) #('compile', "", "", ""), # PyObject* Py_CompileString( char *str, char *filename, int start) BuiltinFunction('delattr', "OO", "r", "PyObject_DelAttr"), BuiltinFunction('dir', "O", "O", "PyObject_Dir"), BuiltinFunction('divmod', "OO", "O", "PyNumber_Divmod"), BuiltinFunction('exec', "O", "O", "__Pyx_PyExecGlobals", utility_code = pyexec_globals_utility_code), BuiltinFunction('exec', "OO", "O", "__Pyx_PyExec2", utility_code = pyexec_utility_code), BuiltinFunction('exec', "OOO", "O", "__Pyx_PyExec3", utility_code = pyexec_utility_code), #('eval', "", "", ""), #('execfile', "", "", ""), #('filter', "", "", ""), BuiltinFunction('getattr3', "OOO", "O", "__Pyx_GetAttr3", "getattr", utility_code=getattr3_utility_code), # Pyrex legacy BuiltinFunction('getattr', "OOO", "O", "__Pyx_GetAttr3", utility_code=getattr3_utility_code), BuiltinFunction('getattr', "OO", "O", "__Pyx_GetAttr", utility_code=getattr_utility_code), BuiltinFunction('hasattr', "OO", "b", "__Pyx_HasAttr", utility_code = UtilityCode.load("HasAttr", "Builtins.c")), BuiltinFunction('hash', "O", "h", "PyObject_Hash"), #('hex', "", "", ""), #('id', "", "", ""), #('input', "", "", ""), BuiltinFunction('intern', "O", "O", "__Pyx_Intern", utility_code = UtilityCode.load("Intern", "Builtins.c")), BuiltinFunction('isinstance', "OO", "b", "PyObject_IsInstance"), BuiltinFunction('issubclass', "OO", "b", "PyObject_IsSubclass"), BuiltinFunction('iter', "OO", "O", "PyCallIter_New"), BuiltinFunction('iter', "O", "O", "PyObject_GetIter"), BuiltinFunction('len', "O", "z", "PyObject_Length"), BuiltinFunction('locals', "", "O", "__pyx_locals"), #('map', "", "", ""), #('max', "", "", ""), #('min', "", "", ""), BuiltinFunction('next', "O", "O", "__Pyx_PyIter_Next", utility_code = iter_next_utility_code), # not available in Py2 => implemented here BuiltinFunction('next', "OO", "O", "__Pyx_PyIter_Next2", utility_code = iter_next_utility_code), # not available in Py2 => implemented here #('oct', "", "", ""), #('open', "ss", "O", "PyFile_FromString"), # not in Py3 ] + [ BuiltinFunction('ord', None, None, "__Pyx_long_cast", func_type=PyrexTypes.CFuncType( PyrexTypes.c_long_type, [PyrexTypes.CFuncTypeArg("c", c_type, None)], is_strict_signature=True)) for c_type in [PyrexTypes.c_py_ucs4_type, PyrexTypes.c_py_unicode_type] ] + [ BuiltinFunction('ord', None, None, "__Pyx_uchar_cast", func_type=PyrexTypes.CFuncType( PyrexTypes.c_uchar_type, [PyrexTypes.CFuncTypeArg("c", c_type, None)], is_strict_signature=True)) for c_type in [PyrexTypes.c_char_type, PyrexTypes.c_schar_type, PyrexTypes.c_uchar_type] ] + [ BuiltinFunction('ord', None, None, "__Pyx_PyObject_Ord", utility_code=UtilityCode.load_cached("object_ord", "Builtins.c"), func_type=PyrexTypes.CFuncType( PyrexTypes.c_long_type, [ PyrexTypes.CFuncTypeArg("c", PyrexTypes.py_object_type, None) ], exception_value="(long)(Py_UCS4)-1")), BuiltinFunction('pow', "OOO", "O", "PyNumber_Power"), BuiltinFunction('pow', "OO", "O", "__Pyx_PyNumber_Power2", utility_code = UtilityCode.load("pow2", "Builtins.c")), #('range', "", "", ""), #('raw_input', "", "", ""), #('reduce', "", "", ""), BuiltinFunction('reload', "O", "O", "PyImport_ReloadModule"), BuiltinFunction('repr', "O", "O", "PyObject_Repr"), # , builtin_return_type='str'), # add in Cython 3.1 #('round', "", "", ""), BuiltinFunction('setattr', "OOO", "r", "PyObject_SetAttr"), #('sum', "", "", ""), #('sorted', "", "", ""), #('type', "O", "O", "PyObject_Type"), BuiltinFunction('unichr', "i", "O", "PyUnicode_FromOrdinal", builtin_return_type='unicode'), #('unicode', "", "", ""), #('vars', "", "", ""), #('zip', "", "", ""), # Can't do these easily until we have builtin type entries. #('typecheck', "OO", "i", "PyObject_TypeCheck", False), #('issubtype', "OO", "i", "PyType_IsSubtype", False), # Put in namespace append optimization. BuiltinFunction('__Pyx_PyObject_Append', "OO", "O", "__Pyx_PyObject_Append"), # This is conditionally looked up based on a compiler directive. BuiltinFunction('__Pyx_Globals', "", "O", "__Pyx_Globals", utility_code=globals_utility_code), ] # Builtin types # bool # buffer # classmethod # dict # enumerate # file # float # int # list # long # object # property # slice # staticmethod # super # str # tuple # type # xrange builtin_types_table = [ ("type", "PyType_Type", []), # This conflicts with the C++ bool type, and unfortunately # C++ is too liberal about PyObject* <-> bool conversions, # resulting in unintuitive runtime behavior and segfaults. # ("bool", "PyBool_Type", []), ("int", "PyInt_Type", []), ("long", "PyLong_Type", []), ("float", "PyFloat_Type", []), ("complex", "PyComplex_Type", [BuiltinAttribute('cval', field_type_name = 'Py_complex'), BuiltinAttribute('real', 'cval.real', field_type = PyrexTypes.c_double_type), BuiltinAttribute('imag', 'cval.imag', field_type = PyrexTypes.c_double_type), ]), ("basestring", "PyBaseString_Type", [ BuiltinMethod("join", "TO", "T", "__Pyx_PyBaseString_Join", utility_code=UtilityCode.load("StringJoin", "StringTools.c")), BuiltinMethod("__mul__", "Tz", "T", "__Pyx_PySequence_Multiply", utility_code=UtilityCode.load("PySequenceMultiply", "ObjectHandling.c")), ]), ("bytearray", "PyByteArray_Type", [ BuiltinMethod("__mul__", "Tz", "T", "__Pyx_PySequence_Multiply", utility_code=UtilityCode.load("PySequenceMultiply", "ObjectHandling.c")), ]), ("bytes", "PyBytes_Type", [BuiltinMethod("join", "TO", "O", "__Pyx_PyBytes_Join", utility_code=UtilityCode.load("StringJoin", "StringTools.c")), BuiltinMethod("__mul__", "Tz", "T", "__Pyx_PySequence_Multiply", utility_code=UtilityCode.load("PySequenceMultiply", "ObjectHandling.c")), ]), ("str", "PyString_Type", [BuiltinMethod("join", "TO", "O", "__Pyx_PyString_Join", builtin_return_type='basestring', utility_code=UtilityCode.load("StringJoin", "StringTools.c")), BuiltinMethod("__mul__", "Tz", "T", "__Pyx_PySequence_Multiply", utility_code=UtilityCode.load("PySequenceMultiply", "ObjectHandling.c")), ]), ("unicode", "PyUnicode_Type", [BuiltinMethod("__contains__", "TO", "b", "PyUnicode_Contains"), BuiltinMethod("join", "TO", "T", "PyUnicode_Join"), BuiltinMethod("__mul__", "Tz", "T", "__Pyx_PySequence_Multiply", utility_code=UtilityCode.load("PySequenceMultiply", "ObjectHandling.c")), ]), ("tuple", "PyTuple_Type", [BuiltinMethod("__mul__", "Tz", "T", "__Pyx_PySequence_Multiply", utility_code=UtilityCode.load("PySequenceMultiply", "ObjectHandling.c")), ]), ("list", "PyList_Type", [BuiltinMethod("insert", "TzO", "r", "PyList_Insert"), BuiltinMethod("reverse", "T", "r", "PyList_Reverse"), BuiltinMethod("append", "TO", "r", "__Pyx_PyList_Append", utility_code=UtilityCode.load("ListAppend", "Optimize.c")), BuiltinMethod("extend", "TO", "r", "__Pyx_PyList_Extend", utility_code=UtilityCode.load("ListExtend", "Optimize.c")), BuiltinMethod("__mul__", "Tz", "T", "__Pyx_PySequence_Multiply", utility_code=UtilityCode.load("PySequenceMultiply", "ObjectHandling.c")), ]), ("dict", "PyDict_Type", [BuiltinMethod("__contains__", "TO", "b", "PyDict_Contains"), BuiltinMethod("has_key", "TO", "b", "PyDict_Contains"), BuiltinMethod("items", "T", "O", "__Pyx_PyDict_Items", utility_code=UtilityCode.load("py_dict_items", "Builtins.c")), BuiltinMethod("keys", "T", "O", "__Pyx_PyDict_Keys", utility_code=UtilityCode.load("py_dict_keys", "Builtins.c")), BuiltinMethod("values", "T", "O", "__Pyx_PyDict_Values", utility_code=UtilityCode.load("py_dict_values", "Builtins.c")), BuiltinMethod("iteritems", "T", "O", "__Pyx_PyDict_IterItems", utility_code=UtilityCode.load("py_dict_iteritems", "Builtins.c")), BuiltinMethod("iterkeys", "T", "O", "__Pyx_PyDict_IterKeys", utility_code=UtilityCode.load("py_dict_iterkeys", "Builtins.c")), BuiltinMethod("itervalues", "T", "O", "__Pyx_PyDict_IterValues", utility_code=UtilityCode.load("py_dict_itervalues", "Builtins.c")), BuiltinMethod("viewitems", "T", "O", "__Pyx_PyDict_ViewItems", utility_code=UtilityCode.load("py_dict_viewitems", "Builtins.c")), BuiltinMethod("viewkeys", "T", "O", "__Pyx_PyDict_ViewKeys", utility_code=UtilityCode.load("py_dict_viewkeys", "Builtins.c")), BuiltinMethod("viewvalues", "T", "O", "__Pyx_PyDict_ViewValues", utility_code=UtilityCode.load("py_dict_viewvalues", "Builtins.c")), BuiltinMethod("clear", "T", "r", "__Pyx_PyDict_Clear", utility_code=UtilityCode.load("py_dict_clear", "Optimize.c")), BuiltinMethod("copy", "T", "T", "PyDict_Copy")]), ("slice", "PySlice_Type", [BuiltinAttribute('start'), BuiltinAttribute('stop'), BuiltinAttribute('step'), ]), # ("file", "PyFile_Type", []), # not in Py3 ("set", "PySet_Type", [BuiltinMethod("clear", "T", "r", "PySet_Clear"), # discard() and remove() have a special treatment for unhashable values BuiltinMethod("discard", "TO", "r", "__Pyx_PySet_Discard", utility_code=UtilityCode.load("py_set_discard", "Optimize.c")), BuiltinMethod("remove", "TO", "r", "__Pyx_PySet_Remove", utility_code=UtilityCode.load("py_set_remove", "Optimize.c")), # update is actually variadic (see Github issue #1645) # BuiltinMethod("update", "TO", "r", "__Pyx_PySet_Update", # utility_code=UtilityCode.load_cached("PySet_Update", "Builtins.c")), BuiltinMethod("add", "TO", "r", "PySet_Add"), BuiltinMethod("pop", "T", "O", "PySet_Pop")]), ("frozenset", "PyFrozenSet_Type", []), ("Exception", "((PyTypeObject*)PyExc_Exception)[0]", []), ("StopAsyncIteration", "((PyTypeObject*)__Pyx_PyExc_StopAsyncIteration)[0]", []), ("memoryview", "PyMemoryView_Type", [ # TODO - format would be nice, but hard to get # __len__ can be accessed through a direct lookup of the buffer (but probably in Optimize.c) # error checking would ideally be limited api only BuiltinProperty("ndim", PyrexTypes.c_int_type, '__Pyx_PyMemoryView_Get_ndim', exception_value="-1", exception_check=True, utility_code=TempitaUtilityCode.load_cached( "memoryview_get_from_buffer", "Builtins.c", context=dict(name="ndim") ) ), BuiltinProperty("readonly", PyrexTypes.c_bint_type, '__Pyx_PyMemoryView_Get_readonly', exception_value="-1", exception_check=True, utility_code=TempitaUtilityCode.load_cached( "memoryview_get_from_buffer", "Builtins.c", context=dict(name="readonly") ) ), BuiltinProperty("itemsize", PyrexTypes.c_py_ssize_t_type, '__Pyx_PyMemoryView_Get_itemsize', exception_value="-1", exception_check=True, utility_code=TempitaUtilityCode.load_cached( "memoryview_get_from_buffer", "Builtins.c", context=dict(name="itemsize") ) )] ) ] types_that_construct_their_instance = frozenset({ # some builtin types do not always return an instance of # themselves - these do: 'type', 'bool', 'long', 'float', 'complex', 'bytes', 'unicode', 'bytearray', 'tuple', 'list', 'dict', 'set', 'frozenset', # 'str', # only in Py3.x # 'file', # only in Py2.x 'memoryview' }) builtin_structs_table = [ ('Py_buffer', 'Py_buffer', [("buf", PyrexTypes.c_void_ptr_type), ("obj", PyrexTypes.py_object_type), ("len", PyrexTypes.c_py_ssize_t_type), ("itemsize", PyrexTypes.c_py_ssize_t_type), ("readonly", PyrexTypes.c_bint_type), ("ndim", PyrexTypes.c_int_type), ("format", PyrexTypes.c_char_ptr_type), ("shape", PyrexTypes.c_py_ssize_t_ptr_type), ("strides", PyrexTypes.c_py_ssize_t_ptr_type), ("suboffsets", PyrexTypes.c_py_ssize_t_ptr_type), ("smalltable", PyrexTypes.CArrayType(PyrexTypes.c_py_ssize_t_type, 2)), ("internal", PyrexTypes.c_void_ptr_type), ]), ('Py_complex', 'Py_complex', [('real', PyrexTypes.c_double_type), ('imag', PyrexTypes.c_double_type), ]) ] # set up builtin scope builtin_scope = BuiltinScope() def init_builtin_funcs(): for bf in builtin_function_table: bf.declare_in_scope(builtin_scope) builtin_types = {} def init_builtin_types(): global builtin_types for name, cname, methods in builtin_types_table: utility = builtin_utility_code.get(name) if name == 'frozenset': objstruct_cname = 'PySetObject' elif name == 'bytearray': objstruct_cname = 'PyByteArrayObject' elif name == 'bool': objstruct_cname = None elif name == 'Exception': objstruct_cname = "PyBaseExceptionObject" elif name == 'StopAsyncIteration': objstruct_cname = "PyBaseExceptionObject" else: objstruct_cname = 'Py%sObject' % name.capitalize() type_class = PyrexTypes.BuiltinObjectType if name in ['dict', 'list', 'set', 'frozenset']: type_class = PyrexTypes.BuiltinTypeConstructorObjectType elif name == 'tuple': type_class = PyrexTypes.PythonTupleTypeConstructor the_type = builtin_scope.declare_builtin_type(name, cname, utility, objstruct_cname, type_class=type_class) builtin_types[name] = the_type for method in methods: method.declare_in_type(the_type) def init_builtin_structs(): for name, cname, attribute_types in builtin_structs_table: scope = StructOrUnionScope(name) for attribute_name, attribute_type in attribute_types: scope.declare_var(attribute_name, attribute_type, None, attribute_name, allow_pyobject=True) builtin_scope.declare_struct_or_union( name, "struct", scope, 1, None, cname = cname) def init_builtins(): #Errors.init_thread() # hopefully not needed - we should not emit warnings ourselves init_builtin_structs() init_builtin_types() init_builtin_funcs() entry = builtin_scope.declare_var( '__debug__', PyrexTypes.c_const_type(PyrexTypes.c_bint_type), pos=None, cname='__pyx_assertions_enabled()', is_cdef=True) entry.utility_code = UtilityCode.load_cached("AssertionsEnabled", "Exceptions.c") global type_type, list_type, tuple_type, dict_type, set_type, frozenset_type, slice_type global bytes_type, str_type, unicode_type, basestring_type, bytearray_type global float_type, int_type, long_type, bool_type, complex_type global memoryview_type, py_buffer_type global sequence_types type_type = builtin_scope.lookup('type').type list_type = builtin_scope.lookup('list').type tuple_type = builtin_scope.lookup('tuple').type dict_type = builtin_scope.lookup('dict').type set_type = builtin_scope.lookup('set').type frozenset_type = builtin_scope.lookup('frozenset').type slice_type = builtin_scope.lookup('slice').type bytes_type = builtin_scope.lookup('bytes').type str_type = builtin_scope.lookup('str').type unicode_type = builtin_scope.lookup('unicode').type basestring_type = builtin_scope.lookup('basestring').type bytearray_type = builtin_scope.lookup('bytearray').type memoryview_type = builtin_scope.lookup('memoryview').type float_type = builtin_scope.lookup('float').type int_type = builtin_scope.lookup('int').type long_type = builtin_scope.lookup('long').type bool_type = builtin_scope.lookup('bool').type complex_type = builtin_scope.lookup('complex').type sequence_types = ( list_type, tuple_type, bytes_type, str_type, unicode_type, basestring_type, bytearray_type, memoryview_type, ) # Set up type inference links between equivalent Python/C types bool_type.equivalent_type = PyrexTypes.c_bint_type PyrexTypes.c_bint_type.equivalent_type = bool_type float_type.equivalent_type = PyrexTypes.c_double_type PyrexTypes.c_double_type.equivalent_type = float_type complex_type.equivalent_type = PyrexTypes.c_double_complex_type PyrexTypes.c_double_complex_type.equivalent_type = complex_type py_buffer_type = builtin_scope.lookup('Py_buffer').type init_builtins() ############################## # Support for a few standard library modules that Cython understands (currently typing and dataclasses) ############################## _known_module_scopes = {} def get_known_standard_library_module_scope(module_name): mod = _known_module_scopes.get(module_name) if mod: return mod if module_name == "typing": mod = ModuleScope(module_name, None, None) for name, tp in [ ('Dict', dict_type), ('List', list_type), ('Tuple', tuple_type), ('Set', set_type), ('FrozenSet', frozenset_type), ]: name = EncodedString(name) entry = mod.declare_type(name, tp, pos = None) var_entry = Entry(name, None, PyrexTypes.py_object_type) var_entry.is_pyglobal = True var_entry.is_variable = True var_entry.scope = mod entry.as_variable = var_entry entry.known_standard_library_import = "%s.%s" % (module_name, name) for name in ['ClassVar', 'Optional']: name = EncodedString(name) indexed_type = PyrexTypes.SpecialPythonTypeConstructor(EncodedString("typing."+name)) entry = mod.declare_type(name, indexed_type, pos = None) var_entry = Entry(name, None, PyrexTypes.py_object_type) var_entry.is_pyglobal = True var_entry.is_variable = True var_entry.scope = mod entry.as_variable = var_entry entry.known_standard_library_import = "%s.%s" % (module_name, name) _known_module_scopes[module_name] = mod elif module_name == "dataclasses": mod = ModuleScope(module_name, None, None) indexed_type = PyrexTypes.SpecialPythonTypeConstructor(EncodedString("dataclasses.InitVar")) initvar_string = EncodedString("InitVar") entry = mod.declare_type(initvar_string, indexed_type, pos = None) var_entry = Entry(initvar_string, None, PyrexTypes.py_object_type) var_entry.is_pyglobal = True var_entry.scope = mod entry.as_variable = var_entry entry.known_standard_library_import = "%s.InitVar" % module_name for name in ["dataclass", "field"]: mod.declare_var(EncodedString(name), PyrexTypes.py_object_type, pos=None) _known_module_scopes[module_name] = mod elif module_name == "functools": mod = ModuleScope(module_name, None, None) for name in ["total_ordering"]: mod.declare_var(EncodedString(name), PyrexTypes.py_object_type, pos=None) _known_module_scopes[module_name] = mod return mod def get_known_standard_library_entry(qualified_name): name_parts = qualified_name.split(".") module_name = EncodedString(name_parts[0]) rest = name_parts[1:] if len(rest) > 1: # for now, we don't know how to deal with any nested modules return None mod = get_known_standard_library_module_scope(module_name) # eventually handle more sophisticated multiple lookups if needed if mod and rest: return mod.lookup_here(rest[0]) return None def exprnode_to_known_standard_library_name(node, env): qualified_name_parts = [] known_name = None while node.is_attribute: qualified_name_parts.append(node.attribute) node = node.obj if node.is_name: entry = env.lookup(node.name) if entry and entry.known_standard_library_import: if get_known_standard_library_entry( entry.known_standard_library_import): known_name = entry.known_standard_library_import else: standard_env = get_known_standard_library_module_scope( entry.known_standard_library_import) if standard_env: qualified_name_parts.append(standard_env.name) known_name = ".".join(reversed(qualified_name_parts)) return known_name ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Compiler/CmdLine.py0000644000175100001770000003035600000000000020506 0ustar00runnerdocker00000000000000# # Cython - Command Line Parsing # from __future__ import absolute_import import sys import os from argparse import ArgumentParser, Action, SUPPRESS from . import Options if sys.version_info < (3, 3): # TODO: This workaround can be removed in Cython 3.1 FileNotFoundError = IOError class ParseDirectivesAction(Action): def __call__(self, parser, namespace, values, option_string=None): old_directives = dict(getattr(namespace, self.dest, Options.get_directive_defaults())) directives = Options.parse_directive_list( values, relaxed_bool=True, current_settings=old_directives) setattr(namespace, self.dest, directives) class ParseOptionsAction(Action): def __call__(self, parser, namespace, values, option_string=None): options = dict(getattr(namespace, self.dest, {})) for opt in values.split(','): if '=' in opt: n, v = opt.split('=', 1) v = v.lower() not in ('false', 'f', '0', 'no') else: n, v = opt, True options[n] = v setattr(namespace, self.dest, options) class ParseCompileTimeEnvAction(Action): def __call__(self, parser, namespace, values, option_string=None): old_env = dict(getattr(namespace, self.dest, {})) new_env = Options.parse_compile_time_env(values, current_settings=old_env) setattr(namespace, self.dest, new_env) class ActivateAllWarningsAction(Action): def __call__(self, parser, namespace, values, option_string=None): directives = getattr(namespace, 'compiler_directives', {}) directives.update(Options.extra_warnings) namespace.compiler_directives = directives class SetLenientAction(Action): def __call__(self, parser, namespace, values, option_string=None): namespace.error_on_unknown_names = False namespace.error_on_uninitialized = False class SetGDBDebugAction(Action): def __call__(self, parser, namespace, values, option_string=None): namespace.gdb_debug = True namespace.output_dir = os.curdir class SetGDBDebugOutputAction(Action): def __call__(self, parser, namespace, values, option_string=None): namespace.gdb_debug = True namespace.output_dir = values class SetAnnotateCoverageAction(Action): def __call__(self, parser, namespace, values, option_string=None): namespace.annotate = True namespace.annotate_coverage_xml = values def create_cython_argparser(): description = "Cython (https://cython.org/) is a compiler for code written in the "\ "Cython language. Cython is based on Pyrex by Greg Ewing." parser = ArgumentParser(description=description, argument_default=SUPPRESS) parser.add_argument("-V", "--version", dest='show_version', action='store_const', const=1, help='Display version number of cython compiler') parser.add_argument("-l", "--create-listing", dest='use_listing_file', action='store_const', const=1, help='Write error messages to a listing file') parser.add_argument("-I", "--include-dir", dest='include_path', action='append', help='Search for include files in named directory ' '(multiple include directories are allowed).') parser.add_argument("-o", "--output-file", dest='output_file', action='store', type=str, help='Specify name of generated C file') parser.add_argument("-t", "--timestamps", dest='timestamps', action='store_const', const=1, help='Only compile newer source files') parser.add_argument("-f", "--force", dest='timestamps', action='store_const', const=0, help='Compile all source files (overrides implied -t)') parser.add_argument("-v", "--verbose", dest='verbose', action='count', help='Be verbose, print file names on multiple compilation') parser.add_argument("-p", "--embed-positions", dest='embed_pos_in_docstring', action='store_const', const=1, help='If specified, the positions in Cython files of each ' 'function definition is embedded in its docstring.') parser.add_argument("--cleanup", dest='generate_cleanup_code', action='store', type=int, help='Release interned objects on python exit, for memory debugging. ' 'Level indicates aggressiveness, default 0 releases nothing.') parser.add_argument("-w", "--working", dest='working_path', action='store', type=str, help='Sets the working directory for Cython (the directory modules are searched from)') parser.add_argument("--gdb", action=SetGDBDebugAction, nargs=0, help='Output debug information for cygdb') parser.add_argument("--gdb-outdir", action=SetGDBDebugOutputAction, type=str, help='Specify gdb debug information output directory. Implies --gdb.') parser.add_argument("-D", "--no-docstrings", dest='docstrings', action='store_false', help='Strip docstrings from the compiled module.') parser.add_argument('-a', '--annotate', action='store_const', const='default', dest='annotate', help='Produce a colorized HTML version of the source.') parser.add_argument('--annotate-fullc', action='store_const', const='fullc', dest='annotate', help='Produce a colorized HTML version of the source ' 'which includes entire generated C/C++-code.') parser.add_argument("--annotate-coverage", dest='annotate_coverage_xml', action=SetAnnotateCoverageAction, type=str, help='Annotate and include coverage information from cov.xml.') parser.add_argument("--line-directives", dest='emit_linenums', action='store_true', help='Produce #line directives pointing to the .pyx source') parser.add_argument("-+", "--cplus", dest='cplus', action='store_const', const=1, help='Output a C++ rather than C file.') parser.add_argument('--embed', action='store_const', const='main', help='Generate a main() function that embeds the Python interpreter. ' 'Pass --embed= for a name other than main().') parser.add_argument('-2', dest='language_level', action='store_const', const=2, help='Compile based on Python-2 syntax and code semantics.') parser.add_argument('-3', dest='language_level', action='store_const', const=3, help='Compile based on Python-3 syntax and code semantics.') parser.add_argument('--3str', dest='language_level', action='store_const', const='3str', help='Compile based on Python-3 syntax and code semantics without ' 'assuming unicode by default for string literals under Python 2.') parser.add_argument("--lenient", action=SetLenientAction, nargs=0, help='Change some compile time errors to runtime errors to ' 'improve Python compatibility') parser.add_argument("--capi-reexport-cincludes", dest='capi_reexport_cincludes', action='store_true', help='Add cincluded headers to any auto-generated header files.') parser.add_argument("--fast-fail", dest='fast_fail', action='store_true', help='Abort the compilation on the first error') parser.add_argument("-Werror", "--warning-errors", dest='warning_errors', action='store_true', help='Make all warnings into errors') parser.add_argument("-Wextra", "--warning-extra", action=ActivateAllWarningsAction, nargs=0, help='Enable extra warnings') parser.add_argument('-X', '--directive', metavar='NAME=VALUE,...', dest='compiler_directives', type=str, action=ParseDirectivesAction, help='Overrides a compiler directive') parser.add_argument('-E', '--compile-time-env', metavar='NAME=VALUE,...', dest='compile_time_env', type=str, action=ParseCompileTimeEnvAction, help='Provides compile time env like DEF would do.') parser.add_argument("--module-name", dest='module_name', type=str, action='store', help='Fully qualified module name. If not given, is ' 'deduced from the import path if source file is in ' 'a package, or equals the filename otherwise.') parser.add_argument('-M', '--depfile', action='store_true', help='produce depfiles for the sources') parser.add_argument('sources', nargs='*', default=[]) # TODO: add help parser.add_argument("-z", "--pre-import", dest='pre_import', action='store', type=str, help=SUPPRESS) parser.add_argument("--convert-range", dest='convert_range', action='store_true', help=SUPPRESS) parser.add_argument("--no-c-in-traceback", dest='c_line_in_traceback', action='store_false', help=SUPPRESS) parser.add_argument("--cimport-from-pyx", dest='cimport_from_pyx', action='store_true', help=SUPPRESS) parser.add_argument("--old-style-globals", dest='old_style_globals', action='store_true', help=SUPPRESS) # debug stuff: from . import DebugFlags for name in vars(DebugFlags): if name.startswith("debug"): option_name = name.replace('_', '-') parser.add_argument("--" + option_name, action='store_true', help=SUPPRESS) return parser def parse_command_line_raw(parser, args): # special handling for --embed and --embed=xxxx as they aren't correctly parsed def filter_out_embed_options(args): with_embed, without_embed = [], [] for x in args: if x == '--embed' or x.startswith('--embed='): with_embed.append(x) else: without_embed.append(x) return with_embed, without_embed with_embed, args_without_embed = filter_out_embed_options(args) arguments, unknown = parser.parse_known_args(args_without_embed) sources = arguments.sources del arguments.sources # unknown can be either debug, embed or input files or really unknown for option in unknown: if option.startswith('-'): parser.error("unknown option " + option) else: sources.append(option) # embed-stuff must be handled extra: for x in with_embed: if x == '--embed': name = 'main' # default value else: name = x[len('--embed='):] setattr(arguments, 'embed', name) return arguments, sources def parse_command_line(args): parser = create_cython_argparser() arguments, sources = parse_command_line_raw(parser, args) work_dir = getattr(arguments, 'working_path', '') for source in sources: if work_dir and not os.path.isabs(source): source = os.path.join(work_dir, source) if not os.path.exists(source): import errno raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), source) options = Options.CompilationOptions(Options.default_options) for name, value in vars(arguments).items(): if name.startswith('debug'): from . import DebugFlags if name in dir(DebugFlags): setattr(DebugFlags, name, value) else: parser.error("Unknown debug flag: %s\n" % name) elif hasattr(Options, name): setattr(Options, name, value) else: setattr(options, name, value) if options.use_listing_file and len(sources) > 1: parser.error("cython: Only one source file allowed when using -o\n") if len(sources) == 0 and not options.show_version: parser.error("cython: Need at least one source file\n") if Options.embed and len(sources) > 1: parser.error("cython: Only one source file allowed when using --embed\n") if options.module_name: if options.timestamps: parser.error("cython: Cannot use --module-name with --timestamps\n") if len(sources) > 1: parser.error("cython: Only one source file allowed when using --module-name\n") return options, sources ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Compiler/Code.pxd0000644000175100001770000000673400000000000020213 0ustar00runnerdocker00000000000000# cython: language_level=3 cimport cython from ..StringIOTree cimport StringIOTree cdef class UtilityCodeBase(object): cpdef format_code(self, code_string, replace_empty_lines=*) cdef class UtilityCode(UtilityCodeBase): cdef public object name cdef public object proto cdef public object impl cdef public object init cdef public object cleanup cdef public object proto_block cdef public object requires cdef public dict _cache cdef public list specialize_list cdef public object file cpdef none_or_sub(self, s, context) cdef class FunctionState: cdef public set names_taken cdef public object owner cdef public object scope cdef public object error_label cdef public size_t label_counter cdef public set labels_used cdef public object return_label cdef public object continue_label cdef public object break_label cdef public list yield_labels cdef public object return_from_error_cleanup_label # not used in __init__ ? cdef public object exc_vars cdef public object current_except cdef public bint in_try_finally cdef public bint can_trace cdef public bint gil_owned cdef public list temps_allocated cdef public dict temps_free cdef public dict temps_used_type cdef public set zombie_temps cdef public size_t temp_counter cdef public list collect_temps_stack cdef public object closure_temps cdef public bint should_declare_error_indicator cdef public bint uses_error_indicator cdef public bint error_without_exception cdef public bint needs_refnanny @cython.locals(n=size_t) cpdef new_label(self, name=*) cpdef tuple get_loop_labels(self) cpdef set_loop_labels(self, labels) cpdef tuple get_all_labels(self) cpdef set_all_labels(self, labels) cpdef start_collecting_temps(self) cpdef stop_collecting_temps(self) cpdef list temps_in_use(self) cdef class IntConst: cdef public object cname cdef public object value cdef public bint is_long cdef class PyObjectConst: cdef public object cname cdef public object type cdef class StringConst: cdef public object cname cdef public object text cdef public object escaped_value cdef public dict py_strings cdef public list py_versions @cython.locals(intern=bint, is_str=bint, is_unicode=bint) cpdef get_py_string_const(self, encoding, identifier=*, is_str=*, py3str_cstring=*) ## cdef class PyStringConst: ## cdef public object cname ## cdef public object encoding ## cdef public bint is_str ## cdef public bint is_unicode ## cdef public bint intern #class GlobalState(object): #def funccontext_property(name): cdef class CCodeWriter(object): cdef readonly StringIOTree buffer cdef readonly list pyclass_stack cdef readonly object globalstate cdef readonly object funcstate cdef object code_config cdef object last_pos cdef object last_marked_pos cdef Py_ssize_t level cdef public Py_ssize_t call_level # debug-only, see Nodes.py cdef bint bol cpdef write(self, s) @cython.final cdef _write_lines(self, s) cpdef _write_to_buffer(self, s) cpdef put(self, code) cpdef put_safe(self, code) cpdef putln(self, code=*, bint safe=*) @cython.final cdef increase_indent(self) @cython.final cdef decrease_indent(self) @cython.final cdef indent(self) cdef class PyrexCodeWriter: cdef public object f cdef public Py_ssize_t level ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Compiler/Code.py0000644000175100001770000031336000000000000020044 0ustar00runnerdocker00000000000000# cython: language_level=3str # cython: auto_pickle=False # # Code output module # from __future__ import absolute_import import cython cython.declare(os=object, re=object, operator=object, textwrap=object, Template=object, Naming=object, Options=object, StringEncoding=object, Utils=object, SourceDescriptor=object, StringIOTree=object, DebugFlags=object, basestring=object, defaultdict=object, closing=object, partial=object) import hashlib import operator import os import re import shutil import textwrap from string import Template from functools import partial from contextlib import closing, contextmanager from collections import defaultdict from . import Naming from . import Options from . import DebugFlags from . import StringEncoding from .. import Utils from .Scanning import SourceDescriptor from ..StringIOTree import StringIOTree try: from __builtin__ import basestring except ImportError: from builtins import str as basestring non_portable_builtins_map = { # builtins that have different names in different Python versions 'bytes' : ('PY_MAJOR_VERSION < 3', 'str'), 'unicode' : ('PY_MAJOR_VERSION >= 3', 'str'), 'basestring' : ('PY_MAJOR_VERSION >= 3', 'str'), 'xrange' : ('PY_MAJOR_VERSION >= 3', 'range'), 'raw_input' : ('PY_MAJOR_VERSION >= 3', 'input'), } ctypedef_builtins_map = { # types of builtins in "ctypedef class" statements which we don't # import either because the names conflict with C types or because # the type simply is not exposed. 'py_int' : '&PyInt_Type', 'py_long' : '&PyLong_Type', 'py_float' : '&PyFloat_Type', 'wrapper_descriptor' : '&PyWrapperDescr_Type', } basicsize_builtins_map = { # builtins whose type has a different tp_basicsize than sizeof(...) 'PyTypeObject': 'PyHeapTypeObject', } uncachable_builtins = [ # Global/builtin names that cannot be cached because they may or may not # be available at import time, for various reasons: ## - Py3.7+ 'breakpoint', # might deserve an implementation in Cython ## - Py3.4+ '__loader__', '__spec__', ## - Py3+ 'BlockingIOError', 'BrokenPipeError', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'FileExistsError', 'FileNotFoundError', 'InterruptedError', 'IsADirectoryError', 'ModuleNotFoundError', 'NotADirectoryError', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ResourceWarning', #'StopAsyncIteration', # backported 'TimeoutError', '__build_class__', 'ascii', # might deserve an implementation in Cython #'exec', # implemented in Cython ## - platform specific 'WindowsError', ## - others '_', # e.g. used by gettext ] special_py_methods = cython.declare(frozenset, frozenset(( '__cinit__', '__dealloc__', '__richcmp__', '__next__', '__await__', '__aiter__', '__anext__', '__getreadbuffer__', '__getwritebuffer__', '__getsegcount__', '__getcharbuffer__', '__getbuffer__', '__releasebuffer__', ))) modifier_output_mapper = { 'inline': 'CYTHON_INLINE' }.get class IncludeCode(object): """ An include file and/or verbatim C code to be included in the generated sources. """ # attributes: # # pieces {order: unicode}: pieces of C code to be generated. # For the included file, the key "order" is zero. # For verbatim include code, the "order" is the "order" # attribute of the original IncludeCode where this piece # of C code was first added. This is needed to prevent # duplication if the same include code is found through # multiple cimports. # location int: where to put this include in the C sources, one # of the constants INITIAL, EARLY, LATE # order int: sorting order (automatically set by increasing counter) # Constants for location. If the same include occurs with different # locations, the earliest one takes precedense. INITIAL = 0 EARLY = 1 LATE = 2 counter = 1 # Counter for "order" def __init__(self, include=None, verbatim=None, late=True, initial=False): self.order = self.counter type(self).counter += 1 self.pieces = {} if include: if include[0] == '<' and include[-1] == '>': self.pieces[0] = u'#include {0}'.format(include) late = False # system include is never late else: self.pieces[0] = u'#include "{0}"'.format(include) if verbatim: self.pieces[self.order] = verbatim if initial: self.location = self.INITIAL elif late: self.location = self.LATE else: self.location = self.EARLY def dict_update(self, d, key): """ Insert `self` in dict `d` with key `key`. If that key already exists, update the attributes of the existing value with `self`. """ if key in d: other = d[key] other.location = min(self.location, other.location) other.pieces.update(self.pieces) else: d[key] = self def sortkey(self): return self.order def mainpiece(self): """ Return the main piece of C code, corresponding to the include file. If there was no include file, return None. """ return self.pieces.get(0) def write(self, code): # Write values of self.pieces dict, sorted by the keys for k in sorted(self.pieces): code.putln(self.pieces[k]) def get_utility_dir(): # make this a function and not global variables: # http://trac.cython.org/cython_trac/ticket/475 Cython_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) return os.path.join(Cython_dir, "Utility") read_utilities_hook = None """ Override the hook for reading a utilities file that contains code fragments used by the codegen. The hook functions takes the path of the utilities file, and returns a list of strings, one per line. The default behavior is to open a file relative to get_utility_dir(). """ def read_utilities_from_utility_dir(path): """ Read all lines of the file at the provided path from a path relative to get_utility_dir(). """ filename = os.path.join(get_utility_dir(), path) with closing(Utils.open_source_file(filename, encoding='UTF-8')) as f: return f.readlines() # by default, read utilities from the utility directory. read_utilities_hook = read_utilities_from_utility_dir class UtilityCodeBase(object): """ Support for loading utility code from a file. Code sections in the file can be specified as follows: ##### MyUtility.proto ##### [proto declarations] ##### MyUtility.init ##### [code run at module initialization] ##### MyUtility ##### #@requires: MyOtherUtility #@substitute: naming [definitions] ##### MyUtility ##### #@substitute: tempita [requires tempita substitution - context can't be specified here though so only tempita utility that requires no external context will benefit from this tag - only necessary when @required from non-tempita code] for prototypes and implementation respectively. For non-python or -cython files backslashes should be used instead. 5 to 30 comment characters may be used on either side. If the @cname decorator is not used and this is a CythonUtilityCode, one should pass in the 'name' keyword argument to be used for name mangling of such entries. """ is_cython_utility = False _utility_cache = {} @classmethod def _add_utility(cls, utility, type, lines, begin_lineno, tags=None): if utility is None: return code = '\n'.join(lines) if tags and 'substitute' in tags and 'naming' in tags['substitute']: try: code = Template(code).substitute(vars(Naming)) except (KeyError, ValueError) as e: raise RuntimeError("Error parsing templated utility code of type '%s' at line %d: %s" % ( type, begin_lineno, e)) # remember correct line numbers at least until after templating code = '\n' * begin_lineno + code if type == 'proto': utility[0] = code elif type == 'impl': utility[1] = code else: all_tags = utility[2] all_tags[type] = code if tags: all_tags = utility[2] for name, values in tags.items(): all_tags.setdefault(name, set()).update(values) @classmethod def load_utilities_from_file(cls, path): utilities = cls._utility_cache.get(path) if utilities: return utilities _, ext = os.path.splitext(path) if ext in ('.pyx', '.py', '.pxd', '.pxi'): comment = '#' strip_comments = partial(re.compile(r'^\s*#(?!\s*cython\s*:).*').sub, '') rstrip = StringEncoding._unicode.rstrip else: comment = '/' strip_comments = partial(re.compile(r'^\s*//.*|/\*[^*]*\*/').sub, '') rstrip = partial(re.compile(r'\s+(\\?)$').sub, r'\1') match_special = re.compile( (r'^%(C)s{5,30}\s*(?P(?:\w|\.)+)\s*%(C)s{5,30}|' r'^%(C)s+@(?P\w+)\s*:\s*(?P(?:\w|[.:])+)') % {'C': comment}).match match_type = re.compile(r'(.+)[.](proto(?:[.]\S+)?|impl|init|cleanup)$').match all_lines = read_utilities_hook(path) utilities = defaultdict(lambda: [None, None, {}]) lines = [] tags = defaultdict(set) utility = type = None begin_lineno = 0 for lineno, line in enumerate(all_lines): m = match_special(line) if m: if m.group('name'): cls._add_utility(utility, type, lines, begin_lineno, tags) begin_lineno = lineno + 1 del lines[:] tags.clear() name = m.group('name') mtype = match_type(name) if mtype: name, type = mtype.groups() else: type = 'impl' utility = utilities[name] else: tags[m.group('tag')].add(m.group('value')) lines.append('') # keep line number correct else: lines.append(rstrip(strip_comments(line))) if utility is None: raise ValueError("Empty utility code file") # Don't forget to add the last utility code cls._add_utility(utility, type, lines, begin_lineno, tags) utilities = dict(utilities) # un-defaultdict-ify cls._utility_cache[path] = utilities return utilities @classmethod def load(cls, util_code_name, from_file, **kwargs): """ Load utility code from a file specified by from_file (relative to Cython/Utility) and name util_code_name. """ if '::' in util_code_name: from_file, util_code_name = util_code_name.rsplit('::', 1) assert from_file utilities = cls.load_utilities_from_file(from_file) proto, impl, tags = utilities[util_code_name] if tags: if "substitute" in tags and "tempita" in tags["substitute"]: if not issubclass(cls, TempitaUtilityCode): return TempitaUtilityCode.load(util_code_name, from_file, **kwargs) orig_kwargs = kwargs.copy() for name, values in tags.items(): if name in kwargs: continue # only pass lists when we have to: most argument expect one value or None if name == 'requires': if orig_kwargs: values = [cls.load(dep, from_file, **orig_kwargs) for dep in sorted(values)] else: # dependencies are rarely unique, so use load_cached() when we can values = [cls.load_cached(dep, from_file) for dep in sorted(values)] elif name == 'substitute': # don't want to pass "naming" or "tempita" to the constructor # since these will have been handled values = values - {'naming', 'tempita'} if not values: continue elif not values: values = None elif len(values) == 1: values = list(values)[0] kwargs[name] = values if proto is not None: kwargs['proto'] = proto if impl is not None: kwargs['impl'] = impl if 'name' not in kwargs: kwargs['name'] = util_code_name if 'file' not in kwargs and from_file: kwargs['file'] = from_file return cls(**kwargs) @classmethod def load_cached(cls, utility_code_name, from_file, __cache={}): """ Calls .load(), but using a per-type cache based on utility name and file name. """ key = (utility_code_name, from_file, cls) try: return __cache[key] except KeyError: pass code = __cache[key] = cls.load(utility_code_name, from_file) return code @classmethod def load_as_string(cls, util_code_name, from_file, **kwargs): """ Load a utility code as a string. Returns (proto, implementation) """ util = cls.load(util_code_name, from_file, **kwargs) proto, impl = util.proto, util.impl return util.format_code(proto), util.format_code(impl) def format_code(self, code_string, replace_empty_lines=re.compile(r'\n\n+').sub): """ Format a code section for output. """ if code_string: code_string = replace_empty_lines('\n', code_string.strip()) + '\n\n' return code_string def __str__(self): return "<%s(%s)>" % (type(self).__name__, self.name) def get_tree(self, **kwargs): return None def __deepcopy__(self, memodict=None): # No need to deep-copy utility code since it's essentially immutable. return self class UtilityCode(UtilityCodeBase): """ Stores utility code to add during code generation. See GlobalState.put_utility_code. hashes/equals by instance proto C prototypes impl implementation code init code to call on module initialization requires utility code dependencies proto_block the place in the resulting file where the prototype should end up name name of the utility code (or None) file filename of the utility code file this utility was loaded from (or None) """ def __init__(self, proto=None, impl=None, init=None, cleanup=None, requires=None, proto_block='utility_code_proto', name=None, file=None): # proto_block: Which code block to dump prototype in. See GlobalState. self.proto = proto self.impl = impl self.init = init self.cleanup = cleanup self.requires = requires self._cache = {} self.specialize_list = [] self.proto_block = proto_block self.name = name self.file = file def __hash__(self): return hash((self.proto, self.impl)) def __eq__(self, other): if self is other: return True self_type, other_type = type(self), type(other) if self_type is not other_type and not (isinstance(other, self_type) or isinstance(self, other_type)): return False self_proto = getattr(self, 'proto', None) other_proto = getattr(other, 'proto', None) return (self_proto, self.impl) == (other_proto, other.impl) def none_or_sub(self, s, context): """ Format a string in this utility code with context. If None, do nothing. """ if s is None: return None return s % context def specialize(self, pyrex_type=None, **data): name = self.name if pyrex_type is not None: data['type'] = pyrex_type.empty_declaration_code() data['type_name'] = pyrex_type.specialization_name() name = "%s[%s]" % (name, data['type_name']) # Dicts aren't hashable... key = tuple(sorted(data.items())) try: return self._cache[key] except KeyError: if self.requires is None: requires = None else: requires = [r.specialize(data) for r in self.requires] s = self._cache[key] = UtilityCode( self.none_or_sub(self.proto, data), self.none_or_sub(self.impl, data), self.none_or_sub(self.init, data), self.none_or_sub(self.cleanup, data), requires, self.proto_block, name, ) self.specialize_list.append(s) return s def inject_string_constants(self, impl, output): """Replace 'PYIDENT("xyz")' by a constant Python identifier cname. """ if 'PYIDENT(' not in impl and 'PYUNICODE(' not in impl: return False, impl replacements = {} def externalise(matchobj): key = matchobj.groups() try: cname = replacements[key] except KeyError: str_type, name = key cname = replacements[key] = output.get_py_string_const( StringEncoding.EncodedString(name), identifier=str_type == 'IDENT').cname return cname impl = re.sub(r'PY(IDENT|UNICODE)\("([^"]+)"\)', externalise, impl) assert 'PYIDENT(' not in impl and 'PYUNICODE(' not in impl return True, impl def inject_unbound_methods(self, impl, output): """Replace 'UNBOUND_METHOD(type, "name")' by a constant Python identifier cname. """ if 'CALL_UNBOUND_METHOD(' not in impl: return False, impl def externalise(matchobj): type_cname, method_name, obj_cname, args = matchobj.groups() args = [arg.strip() for arg in args[1:].split(',')] if args else [] assert len(args) < 3, "CALL_UNBOUND_METHOD() does not support %d call arguments" % len(args) return output.cached_unbound_method_call_code(obj_cname, type_cname, method_name, args) impl = re.sub( r'CALL_UNBOUND_METHOD\(' r'([a-zA-Z_]+),' # type cname r'\s*"([^"]+)",' # method name r'\s*([^),]+)' # object cname r'((?:,[^),]+)*)' # args* r'\)', externalise, impl) assert 'CALL_UNBOUND_METHOD(' not in impl return True, impl def wrap_c_strings(self, impl): """Replace CSTRING('''xyz''') by a C compatible string """ if 'CSTRING(' not in impl: return impl def split_string(matchobj): content = matchobj.group(1).replace('"', '\042') return ''.join( '"%s\\n"\n' % line if not line.endswith('\\') or line.endswith('\\\\') else '"%s"\n' % line[:-1] for line in content.splitlines()) impl = re.sub(r'CSTRING\(\s*"""([^"]*(?:"[^"]+)*)"""\s*\)', split_string, impl) assert 'CSTRING(' not in impl return impl def put_code(self, output): if self.requires: for dependency in self.requires: output.use_utility_code(dependency) if self.proto: writer = output[self.proto_block] writer.putln("/* %s.proto */" % self.name) writer.put_or_include( self.format_code(self.proto), '%s_proto' % self.name) if self.impl: impl = self.format_code(self.wrap_c_strings(self.impl)) is_specialised1, impl = self.inject_string_constants(impl, output) is_specialised2, impl = self.inject_unbound_methods(impl, output) writer = output['utility_code_def'] writer.putln("/* %s */" % self.name) if not (is_specialised1 or is_specialised2): # no module specific adaptations => can be reused writer.put_or_include(impl, '%s_impl' % self.name) else: writer.put(impl) if self.init: writer = output['init_globals'] writer.putln("/* %s.init */" % self.name) if isinstance(self.init, basestring): writer.put(self.format_code(self.init)) else: self.init(writer, output.module_pos) # 'init' code can end with an 'if' statement for an error condition like: # if (check_ok()) ; else writer.putln(writer.error_goto_if_PyErr(output.module_pos)) writer.putln() if self.cleanup and Options.generate_cleanup_code: writer = output['cleanup_globals'] writer.putln("/* %s.cleanup */" % self.name) if isinstance(self.cleanup, basestring): writer.put_or_include( self.format_code(self.cleanup), '%s_cleanup' % self.name) else: self.cleanup(writer, output.module_pos) def sub_tempita(s, context, file=None, name=None): "Run tempita on string s with given context." if not s: return None if file: context['__name'] = "%s:%s" % (file, name) elif name: context['__name'] = name from ..Tempita import sub return sub(s, **context) class TempitaUtilityCode(UtilityCode): def __init__(self, name=None, proto=None, impl=None, init=None, file=None, context=None, **kwargs): if context is None: context = {} proto = sub_tempita(proto, context, file, name) impl = sub_tempita(impl, context, file, name) init = sub_tempita(init, context, file, name) super(TempitaUtilityCode, self).__init__( proto, impl, init=init, name=name, file=file, **kwargs) @classmethod def load_cached(cls, utility_code_name, from_file=None, context=None, __cache={}): context_key = tuple(sorted(context.items())) if context else None assert hash(context_key) is not None # raise TypeError if not hashable key = (cls, from_file, utility_code_name, context_key) try: return __cache[key] except KeyError: pass code = __cache[key] = cls.load(utility_code_name, from_file, context=context) return code def none_or_sub(self, s, context): """ Format a string in this utility code with context. If None, do nothing. """ if s is None: return None return sub_tempita(s, context, self.file, self.name) class LazyUtilityCode(UtilityCodeBase): """ Utility code that calls a callback with the root code writer when available. Useful when you only have 'env' but not 'code'. """ __name__ = '' requires = None def __init__(self, callback): self.callback = callback def put_code(self, globalstate): utility = self.callback(globalstate.rootwriter) globalstate.use_utility_code(utility) class FunctionState(object): # return_label string function return point label # error_label string error catch point label # error_without_exception boolean Can go to the error label without an exception (e.g. __next__ can return NULL) # continue_label string loop continue point label # break_label string loop break point label # return_from_error_cleanup_label string # label_counter integer counter for naming labels # in_try_finally boolean inside try of try...finally # exc_vars (string * 3) exception variables for reraise, or None # can_trace boolean line tracing is supported in the current context # scope Scope the scope object of the current function # Not used for now, perhaps later def __init__(self, owner, names_taken=set(), scope=None): self.names_taken = names_taken self.owner = owner self.scope = scope self.error_label = None self.label_counter = 0 self.labels_used = set() self.return_label = self.new_label() self.new_error_label() self.continue_label = None self.break_label = None self.yield_labels = [] self.in_try_finally = 0 self.exc_vars = None self.current_except = None self.can_trace = False self.gil_owned = True self.temps_allocated = [] # of (name, type, manage_ref, static) self.temps_free = {} # (type, manage_ref) -> list of free vars with same type/managed status self.temps_used_type = {} # name -> (type, manage_ref) self.zombie_temps = set() # temps that must not be reused after release self.temp_counter = 0 self.closure_temps = None # This is used to collect temporaries, useful to find out which temps # need to be privatized in parallel sections self.collect_temps_stack = [] # This is used for the error indicator, which needs to be local to the # function. It used to be global, which relies on the GIL being held. # However, exceptions may need to be propagated through 'nogil' # sections, in which case we introduce a race condition. self.should_declare_error_indicator = False self.uses_error_indicator = False self.error_without_exception = False self.needs_refnanny = False # safety checks def validate_exit(self): # validate that all allocated temps have been freed if self.temps_allocated: leftovers = self.temps_in_use() if leftovers: msg = "TEMPGUARD: Temps left over at end of '%s': %s" % (self.scope.name, ', '.join([ '%s [%s]' % (name, ctype) for name, ctype, is_pytemp in sorted(leftovers)]), ) #print(msg) raise RuntimeError(msg) # labels def new_label(self, name=None): n = self.label_counter self.label_counter = n + 1 label = "%s%d" % (Naming.label_prefix, n) if name is not None: label += '_' + name return label def new_yield_label(self, expr_type='yield'): label = self.new_label('resume_from_%s' % expr_type) num_and_label = (len(self.yield_labels) + 1, label) self.yield_labels.append(num_and_label) return num_and_label def new_error_label(self, prefix=""): old_err_lbl = self.error_label self.error_label = self.new_label(prefix + 'error') return old_err_lbl def get_loop_labels(self): return ( self.continue_label, self.break_label) def set_loop_labels(self, labels): (self.continue_label, self.break_label) = labels def new_loop_labels(self, prefix=""): old_labels = self.get_loop_labels() self.set_loop_labels( (self.new_label(prefix + "continue"), self.new_label(prefix + "break"))) return old_labels def get_all_labels(self): return ( self.continue_label, self.break_label, self.return_label, self.error_label) def set_all_labels(self, labels): (self.continue_label, self.break_label, self.return_label, self.error_label) = labels def all_new_labels(self): old_labels = self.get_all_labels() new_labels = [] for old_label, name in zip(old_labels, ['continue', 'break', 'return', 'error']): if old_label: new_labels.append(self.new_label(name)) else: new_labels.append(old_label) self.set_all_labels(new_labels) return old_labels def use_label(self, lbl): self.labels_used.add(lbl) def label_used(self, lbl): return lbl in self.labels_used # temp handling def allocate_temp(self, type, manage_ref, static=False, reusable=True): """ Allocates a temporary (which may create a new one or get a previously allocated and released one of the same type). Type is simply registered and handed back, but will usually be a PyrexType. If type.needs_refcounting, manage_ref comes into play. If manage_ref is set to True, the temp will be decref-ed on return statements and in exception handling clauses. Otherwise the caller has to deal with any reference counting of the variable. If not type.needs_refcounting, then manage_ref will be ignored, but it still has to be passed. It is recommended to pass False by convention if it is known that type will never be a reference counted type. static=True marks the temporary declaration with "static". This is only used when allocating backing store for a module-level C array literals. if reusable=False, the temp will not be reused after release. A C string referring to the variable is returned. """ if type.is_cv_qualified and not type.is_reference: type = type.cv_base_type elif type.is_reference and not type.is_fake_reference: type = type.ref_base_type elif type.is_cfunction: from . import PyrexTypes type = PyrexTypes.c_ptr_type(type) # A function itself isn't an l-value elif type.is_cpp_class and not type.is_fake_reference and self.scope.directives['cpp_locals']: self.scope.use_utility_code(UtilityCode.load_cached("OptionalLocals", "CppSupport.cpp")) if not type.needs_refcounting: # Make manage_ref canonical, so that manage_ref will always mean # a decref is needed. manage_ref = False freelist = self.temps_free.get((type, manage_ref)) if reusable and freelist is not None and freelist[0]: result = freelist[0].pop() freelist[1].remove(result) else: while True: self.temp_counter += 1 result = "%s%d" % (Naming.codewriter_temp_prefix, self.temp_counter) if result not in self.names_taken: break self.temps_allocated.append((result, type, manage_ref, static)) if not reusable: self.zombie_temps.add(result) self.temps_used_type[result] = (type, manage_ref) if DebugFlags.debug_temp_code_comments: self.owner.putln("/* %s allocated (%s)%s */" % (result, type, "" if reusable else " - zombie")) if self.collect_temps_stack: self.collect_temps_stack[-1].add((result, type)) return result def release_temp(self, name): """ Releases a temporary so that it can be reused by other code needing a temp of the same type. """ type, manage_ref = self.temps_used_type[name] freelist = self.temps_free.get((type, manage_ref)) if freelist is None: freelist = ([], set()) # keep order in list and make lookups in set fast self.temps_free[(type, manage_ref)] = freelist if name in freelist[1]: raise RuntimeError("Temp %s freed twice!" % name) if name not in self.zombie_temps: freelist[0].append(name) freelist[1].add(name) if DebugFlags.debug_temp_code_comments: self.owner.putln("/* %s released %s*/" % ( name, " - zombie" if name in self.zombie_temps else "")) def temps_in_use(self): """Return a list of (cname,type,manage_ref) tuples of temp names and their type that are currently in use. """ used = [] for name, type, manage_ref, static in self.temps_allocated: freelist = self.temps_free.get((type, manage_ref)) if freelist is None or name not in freelist[1]: used.append((name, type, manage_ref and type.needs_refcounting)) return used def temps_holding_reference(self): """Return a list of (cname,type) tuples of temp names and their type that are currently in use. This includes only temps with a reference counted type which owns its reference. """ return [(name, type) for name, type, manage_ref in self.temps_in_use() if manage_ref and type.needs_refcounting] def all_managed_temps(self): """Return a list of (cname, type) tuples of refcount-managed Python objects. """ return [(cname, type) for cname, type, manage_ref, static in self.temps_allocated if manage_ref] def all_free_managed_temps(self): """Return a list of (cname, type) tuples of refcount-managed Python objects that are not currently in use. This is used by try-except and try-finally blocks to clean up temps in the error case. """ return sorted([ # Enforce deterministic order. (cname, type) for (type, manage_ref), freelist in self.temps_free.items() if manage_ref for cname in freelist[0] ]) def start_collecting_temps(self): """ Useful to find out which temps were used in a code block """ self.collect_temps_stack.append(set()) def stop_collecting_temps(self): return self.collect_temps_stack.pop() def init_closure_temps(self, scope): self.closure_temps = ClosureTempAllocator(scope) class NumConst(object): """Global info about a Python number constant held by GlobalState. cname string value string py_type string int, long, float value_code string evaluation code if different from value """ def __init__(self, cname, value, py_type, value_code=None): self.cname = cname self.value = value self.py_type = py_type self.value_code = value_code or value class PyObjectConst(object): """Global info about a generic constant held by GlobalState. """ # cname string # type PyrexType def __init__(self, cname, type): self.cname = cname self.type = type cython.declare(possible_unicode_identifier=object, possible_bytes_identifier=object, replace_identifier=object, find_alphanums=object) possible_unicode_identifier = re.compile(br"(?![0-9])\w+$".decode('ascii'), re.U).match possible_bytes_identifier = re.compile(r"(?![0-9])\w+$".encode('ASCII')).match replace_identifier = re.compile(r'[^a-zA-Z0-9_]+').sub find_alphanums = re.compile('([a-zA-Z0-9]+)').findall class StringConst(object): """Global info about a C string constant held by GlobalState. """ # cname string # text EncodedString or BytesLiteral # py_strings {(identifier, encoding) : PyStringConst} def __init__(self, cname, text, byte_string): self.cname = cname self.text = text self.escaped_value = StringEncoding.escape_byte_string(byte_string) self.py_strings = None self.py_versions = [] def add_py_version(self, version): if not version: self.py_versions = [2, 3] elif version not in self.py_versions: self.py_versions.append(version) def get_py_string_const(self, encoding, identifier=None, is_str=False, py3str_cstring=None): py_strings = self.py_strings text = self.text is_str = bool(identifier or is_str) is_unicode = encoding is None and not is_str if encoding is None: # unicode string encoding_key = None else: # bytes or str encoding = encoding.lower() if encoding in ('utf8', 'utf-8', 'ascii', 'usascii', 'us-ascii'): encoding = None encoding_key = None else: encoding_key = ''.join(find_alphanums(encoding)) key = (is_str, is_unicode, encoding_key, py3str_cstring) if py_strings is not None: try: return py_strings[key] except KeyError: pass else: self.py_strings = {} if identifier: intern = True elif identifier is None: if isinstance(text, bytes): intern = bool(possible_bytes_identifier(text)) else: intern = bool(possible_unicode_identifier(text)) else: intern = False if intern: prefix = Naming.interned_prefixes['str'] else: prefix = Naming.py_const_prefix if encoding_key: encoding_prefix = '_%s' % encoding_key else: encoding_prefix = '' pystring_cname = "%s%s%s_%s" % ( prefix, (is_str and 's') or (is_unicode and 'u') or 'b', encoding_prefix, self.cname[len(Naming.const_prefix):]) py_string = PyStringConst( pystring_cname, encoding, is_unicode, is_str, py3str_cstring, intern) self.py_strings[key] = py_string return py_string class PyStringConst(object): """Global info about a Python string constant held by GlobalState. """ # cname string # py3str_cstring string # encoding string # intern boolean # is_unicode boolean # is_str boolean def __init__(self, cname, encoding, is_unicode, is_str=False, py3str_cstring=None, intern=False): self.cname = cname self.py3str_cstring = py3str_cstring self.encoding = encoding self.is_str = is_str self.is_unicode = is_unicode self.intern = intern def __lt__(self, other): return self.cname < other.cname class GlobalState(object): # filename_table {string : int} for finding filename table indexes # filename_list [string] filenames in filename table order # input_file_contents dict contents (=list of lines) of any file that was used as input # to create this output C code. This is # used to annotate the comments. # # utility_codes set IDs of used utility code (to avoid reinsertion) # # declared_cnames {string:Entry} used in a transition phase to merge pxd-declared # constants etc. into the pyx-declared ones (i.e, # check if constants are already added). # In time, hopefully the literals etc. will be # supplied directly instead. # # const_cnames_used dict global counter for unique constant identifiers # # parts {string:CCodeWriter} # interned_strings # consts # interned_nums # directives set Temporary variable used to track # the current set of directives in the code generation # process. directives = {} code_layout = [ 'h_code', 'filename_table', 'utility_code_proto_before_types', 'numeric_typedefs', # Let these detailed individual parts stay!, 'complex_type_declarations', # as the proper solution is to make a full DAG... 'type_declarations', # More coarse-grained blocks would simply hide 'utility_code_proto', # the ugliness, not fix it 'module_declarations', 'typeinfo', 'before_global_var', 'global_var', 'string_decls', 'decls', 'late_includes', 'module_state', 'module_state_clear', 'module_state_traverse', 'module_state_defines', # redefines names used in module_state/_clear/_traverse 'module_code', # user code goes here 'pystring_table', 'cached_builtins', 'cached_constants', 'init_constants', 'init_globals', # (utility code called at init-time) 'init_module', 'cleanup_globals', 'cleanup_module', 'main_method', 'utility_code_pragmas', # silence some irrelevant warnings in utility code 'utility_code_def', 'utility_code_pragmas_end', # clean-up the utility_code_pragmas 'end' ] # h files can only have a much smaller list of sections h_code_layout = [ 'h_code', 'utility_code_proto_before_types', 'type_declarations', 'utility_code_proto', 'end' ] def __init__(self, writer, module_node, code_config, common_utility_include_dir=None): self.filename_table = {} self.filename_list = [] self.input_file_contents = {} self.utility_codes = set() self.declared_cnames = {} self.in_utility_code_generation = False self.code_config = code_config self.common_utility_include_dir = common_utility_include_dir self.parts = {} self.module_node = module_node # because some utility code generation needs it # (generating backwards-compatible Get/ReleaseBuffer self.const_cnames_used = {} self.string_const_index = {} self.dedup_const_index = {} self.pyunicode_ptr_const_index = {} self.num_const_index = {} self.py_constants = [] self.cached_cmethods = {} self.initialised_constants = set() writer.set_global_state(self) self.rootwriter = writer def initialize_main_c_code(self): rootwriter = self.rootwriter for i, part in enumerate(self.code_layout): w = self.parts[part] = rootwriter.insertion_point() if i > 0: w.putln("/* #### Code section: %s ### */" % part) if not Options.cache_builtins: del self.parts['cached_builtins'] else: w = self.parts['cached_builtins'] w.enter_cfunc_scope() w.putln("static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) {") w = self.parts['cached_constants'] w.enter_cfunc_scope() w.putln("") w.putln("static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) {") w.put_declare_refcount_context() w.put_setup_refcount_context(StringEncoding.EncodedString("__Pyx_InitCachedConstants")) w = self.parts['init_globals'] w.enter_cfunc_scope() w.putln("") w.putln("static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) {") w = self.parts['init_constants'] w.enter_cfunc_scope() w.putln("") w.putln("static CYTHON_SMALL_CODE int __Pyx_InitConstants(void) {") if not Options.generate_cleanup_code: del self.parts['cleanup_globals'] else: w = self.parts['cleanup_globals'] w.enter_cfunc_scope() w.putln("") w.putln("static CYTHON_SMALL_CODE void __Pyx_CleanupGlobals(void) {") code = self.parts['utility_code_proto'] code.putln("") code.putln("/* --- Runtime support code (head) --- */") code = self.parts['utility_code_def'] if self.code_config.emit_linenums: code.write('\n#line 1 "cython_utility"\n') code.putln("") code.putln("/* --- Runtime support code --- */") def initialize_main_h_code(self): rootwriter = self.rootwriter for part in self.h_code_layout: self.parts[part] = rootwriter.insertion_point() def finalize_main_c_code(self): self.close_global_decls() # # utility_code_def # code = self.parts['utility_code_def'] util = TempitaUtilityCode.load_cached("TypeConversions", "TypeConversion.c") code.put(util.format_code(util.impl)) code.putln("") # # utility code pragmas # code = self.parts['utility_code_pragmas'] util = UtilityCode.load_cached("UtilityCodePragmas", "ModuleSetupCode.c") code.putln(util.format_code(util.impl)) code.putln("") code = self.parts['utility_code_pragmas_end'] util = UtilityCode.load_cached("UtilityCodePragmasEnd", "ModuleSetupCode.c") code.putln(util.format_code(util.impl)) code.putln("") def __getitem__(self, key): return self.parts[key] # # Global constants, interned objects, etc. # def close_global_decls(self): # This is called when it is known that no more global declarations will # declared. self.generate_const_declarations() if Options.cache_builtins: w = self.parts['cached_builtins'] w.putln("return 0;") if w.label_used(w.error_label): w.put_label(w.error_label) w.putln("return -1;") w.putln("}") w.exit_cfunc_scope() w = self.parts['cached_constants'] w.put_finish_refcount_context() w.putln("return 0;") if w.label_used(w.error_label): w.put_label(w.error_label) w.put_finish_refcount_context() w.putln("return -1;") w.putln("}") w.exit_cfunc_scope() for part in ['init_globals', 'init_constants']: w = self.parts[part] w.putln("return 0;") if w.label_used(w.error_label): w.put_label(w.error_label) w.putln("return -1;") w.putln("}") w.exit_cfunc_scope() if Options.generate_cleanup_code: w = self.parts['cleanup_globals'] w.putln("}") w.exit_cfunc_scope() if Options.generate_cleanup_code: w = self.parts['cleanup_module'] w.putln("}") w.exit_cfunc_scope() def put_pyobject_decl(self, entry): self['global_var'].putln("static PyObject *%s;" % entry.cname) # constant handling at code generation time def get_cached_constants_writer(self, target=None): if target is not None: if target in self.initialised_constants: # Return None on second/later calls to prevent duplicate creation code. return None self.initialised_constants.add(target) return self.parts['cached_constants'] def get_int_const(self, str_value, longness=False): py_type = longness and 'long' or 'int' try: c = self.num_const_index[(str_value, py_type)] except KeyError: c = self.new_num_const(str_value, py_type) return c def get_float_const(self, str_value, value_code): try: c = self.num_const_index[(str_value, 'float')] except KeyError: c = self.new_num_const(str_value, 'float', value_code) return c def get_py_const(self, type, prefix='', cleanup_level=None, dedup_key=None): if dedup_key is not None: const = self.dedup_const_index.get(dedup_key) if const is not None: return const # create a new Python object constant const = self.new_py_const(type, prefix) if (cleanup_level is not None and cleanup_level <= Options.generate_cleanup_code # Note that this function is used for all argument defaults # which aren't just Python objects and type.needs_refcounting): cleanup_writer = self.parts['cleanup_globals'] cleanup_writer.putln('Py_CLEAR(%s);' % const.cname) if dedup_key is not None: self.dedup_const_index[dedup_key] = const return const def get_string_const(self, text, py_version=None): # return a C string constant, creating a new one if necessary if text.is_unicode: byte_string = text.utf8encode() else: byte_string = text.byteencode() try: c = self.string_const_index[byte_string] except KeyError: c = self.new_string_const(text, byte_string) c.add_py_version(py_version) return c def get_pyunicode_ptr_const(self, text): # return a Py_UNICODE[] constant, creating a new one if necessary assert text.is_unicode try: c = self.pyunicode_ptr_const_index[text] except KeyError: c = self.pyunicode_ptr_const_index[text] = self.new_const_cname() return c def get_py_string_const(self, text, identifier=None, is_str=False, unicode_value=None): # return a Python string constant, creating a new one if necessary py3str_cstring = None if is_str and unicode_value is not None \ and unicode_value.utf8encode() != text.byteencode(): py3str_cstring = self.get_string_const(unicode_value, py_version=3) c_string = self.get_string_const(text, py_version=2) else: c_string = self.get_string_const(text) py_string = c_string.get_py_string_const( text.encoding, identifier, is_str, py3str_cstring) return py_string def get_interned_identifier(self, text): return self.get_py_string_const(text, identifier=True) def new_string_const(self, text, byte_string): cname = self.new_string_const_cname(byte_string) c = StringConst(cname, text, byte_string) self.string_const_index[byte_string] = c return c def new_num_const(self, value, py_type, value_code=None): cname = self.new_num_const_cname(value, py_type) c = NumConst(cname, value, py_type, value_code) self.num_const_index[(value, py_type)] = c return c def new_py_const(self, type, prefix=''): cname = self.new_const_cname(prefix) c = PyObjectConst(cname, type) self.py_constants.append(c) return c def new_string_const_cname(self, bytes_value): # Create a new globally-unique nice name for a C string constant. value = bytes_value.decode('ASCII', 'ignore') return self.new_const_cname(value=value) def unique_const_cname(self, format_str): # type: (str) -> str used = self.const_cnames_used cname = value = format_str.format(sep='', counter='') while cname in used: counter = used[value] = used[value] + 1 cname = format_str.format(sep='_', counter=counter) used[cname] = 1 return cname def new_num_const_cname(self, value, py_type): # type: (str, str) -> str if py_type == 'long': value += 'L' py_type = 'int' prefix = Naming.interned_prefixes[py_type] value = value.replace('.', '_').replace('+', '_').replace('-', 'neg_') if len(value) > 42: # update tests/run/large_integer_T5290.py in case the amount is changed cname = self.unique_const_cname( prefix + "large{counter}_" + value[:18] + "_xxx_" + value[-18:]) else: cname = "%s%s" % (prefix, value) return cname def new_const_cname(self, prefix='', value=''): value = replace_identifier('_', value)[:32].strip('_') name_suffix = self.unique_const_cname(value + "{sep}{counter}") if prefix: prefix = Naming.interned_prefixes[prefix] else: prefix = Naming.const_prefix return "%s%s" % (prefix, name_suffix) def get_cached_unbound_method(self, type_cname, method_name): key = (type_cname, method_name) try: cname = self.cached_cmethods[key] except KeyError: cname = self.cached_cmethods[key] = self.new_const_cname( 'umethod', '%s_%s' % (type_cname, method_name)) return cname def cached_unbound_method_call_code(self, obj_cname, type_cname, method_name, arg_cnames): # admittedly, not the best place to put this method, but it is reused by UtilityCode and ExprNodes ... utility_code_name = "CallUnboundCMethod%d" % len(arg_cnames) self.use_utility_code(UtilityCode.load_cached(utility_code_name, "ObjectHandling.c")) cache_cname = self.get_cached_unbound_method(type_cname, method_name) args = [obj_cname] + arg_cnames return "__Pyx_%s(&%s, %s)" % ( utility_code_name, cache_cname, ', '.join(args), ) def add_cached_builtin_decl(self, entry): if entry.is_builtin and entry.is_const: if self.should_declare(entry.cname, entry): self.put_pyobject_decl(entry) w = self.parts['cached_builtins'] condition = None if entry.name in non_portable_builtins_map: condition, replacement = non_portable_builtins_map[entry.name] w.putln('#if %s' % condition) self.put_cached_builtin_init( entry.pos, StringEncoding.EncodedString(replacement), entry.cname) w.putln('#else') self.put_cached_builtin_init( entry.pos, StringEncoding.EncodedString(entry.name), entry.cname) if condition: w.putln('#endif') def put_cached_builtin_init(self, pos, name, cname): w = self.parts['cached_builtins'] interned_cname = self.get_interned_identifier(name).cname self.use_utility_code( UtilityCode.load_cached("GetBuiltinName", "ObjectHandling.c")) w.putln('%s = __Pyx_GetBuiltinName(%s); if (!%s) %s' % ( cname, interned_cname, cname, w.error_goto(pos))) def generate_const_declarations(self): self.generate_cached_methods_decls() self.generate_string_constants() self.generate_num_constants() self.generate_object_constant_decls() def generate_object_constant_decls(self): consts = [(len(c.cname), c.cname, c) for c in self.py_constants] consts.sort() for _, cname, c in consts: self.parts['module_state'].putln("%s;" % c.type.declaration_code(cname)) self.parts['module_state_defines'].putln( "#define %s %s->%s" % (cname, Naming.modulestateglobal_cname, cname)) if not c.type.needs_refcounting: # Note that py_constants is used for all argument defaults # which aren't necessarily PyObjects, so aren't appropriate # to clear. continue self.parts['module_state_clear'].putln( "Py_CLEAR(clear_module_state->%s);" % cname) self.parts['module_state_traverse'].putln( "Py_VISIT(traverse_module_state->%s);" % cname) def generate_cached_methods_decls(self): if not self.cached_cmethods: return decl = self.parts['decls'] init = self.parts['init_constants'] cnames = [] for (type_cname, method_name), cname in sorted(self.cached_cmethods.items()): cnames.append(cname) method_name_cname = self.get_interned_identifier(StringEncoding.EncodedString(method_name)).cname decl.putln('static __Pyx_CachedCFunction %s = {0, 0, 0, 0, 0};' % ( cname)) # split type reference storage as it might not be static init.putln('%s.type = (PyObject*)&%s;' % ( cname, type_cname)) # method name string isn't static in limited api init.putln('%s.method_name = &%s;' % ( cname, method_name_cname)) if Options.generate_cleanup_code: cleanup = self.parts['cleanup_globals'] for cname in cnames: cleanup.putln("Py_CLEAR(%s.method);" % cname) def generate_string_constants(self): c_consts = [(len(c.cname), c.cname, c) for c in self.string_const_index.values()] c_consts.sort() py_strings = [] decls_writer = self.parts['string_decls'] for _, cname, c in c_consts: conditional = False if c.py_versions and (2 not in c.py_versions or 3 not in c.py_versions): conditional = True decls_writer.putln("#if PY_MAJOR_VERSION %s 3" % ( (2 in c.py_versions) and '<' or '>=')) decls_writer.putln('static const char %s[] = "%s";' % ( cname, StringEncoding.split_string_literal(c.escaped_value))) if conditional: decls_writer.putln("#endif") if c.py_strings is not None: for py_string in c.py_strings.values(): py_strings.append((c.cname, len(py_string.cname), py_string)) for c, cname in sorted(self.pyunicode_ptr_const_index.items()): utf16_array, utf32_array = StringEncoding.encode_pyunicode_string(c) if utf16_array: # Narrow and wide representations differ decls_writer.putln("#ifdef Py_UNICODE_WIDE") decls_writer.putln("static Py_UNICODE %s[] = { %s };" % (cname, utf32_array)) if utf16_array: decls_writer.putln("#else") decls_writer.putln("static Py_UNICODE %s[] = { %s };" % (cname, utf16_array)) decls_writer.putln("#endif") init_constants = self.parts['init_constants'] if py_strings: self.use_utility_code(UtilityCode.load_cached("InitStrings", "StringTools.c")) py_strings.sort() w = self.parts['pystring_table'] w.putln("") w.putln("static int __Pyx_CreateStringTabAndInitStrings(void) {") # the stringtab is a function local rather than a global to # ensure that it doesn't conflict with module state w.putln("__Pyx_StringTabEntry %s[] = {" % Naming.stringtab_cname) for py_string_args in py_strings: c_cname, _, py_string = py_string_args if not py_string.is_str or not py_string.encoding or \ py_string.encoding in ('ASCII', 'USASCII', 'US-ASCII', 'UTF8', 'UTF-8'): encoding = '0' else: encoding = '"%s"' % py_string.encoding.lower() self.parts['module_state'].putln("PyObject *%s;" % py_string.cname) self.parts['module_state_defines'].putln("#define %s %s->%s" % ( py_string.cname, Naming.modulestateglobal_cname, py_string.cname)) self.parts['module_state_clear'].putln("Py_CLEAR(clear_module_state->%s);" % py_string.cname) self.parts['module_state_traverse'].putln("Py_VISIT(traverse_module_state->%s);" % py_string.cname) if py_string.py3str_cstring: w.putln("#if PY_MAJOR_VERSION >= 3") w.putln("{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % ( py_string.cname, py_string.py3str_cstring.cname, py_string.py3str_cstring.cname, '0', 1, 0, py_string.intern )) w.putln("#else") w.putln("{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % ( py_string.cname, c_cname, c_cname, encoding, py_string.is_unicode, py_string.is_str, py_string.intern )) if py_string.py3str_cstring: w.putln("#endif") w.putln("{0, 0, 0, 0, 0, 0, 0}") w.putln("};") w.putln("return __Pyx_InitStrings(%s);" % Naming.stringtab_cname) w.putln("}") init_constants.putln( "if (__Pyx_CreateStringTabAndInitStrings() < 0) %s;" % init_constants.error_goto(self.module_pos)) def generate_num_constants(self): consts = [(c.py_type, c.value[0] == '-', len(c.value), c.value, c.value_code, c) for c in self.num_const_index.values()] consts.sort() init_constants = self.parts['init_constants'] for py_type, _, _, value, value_code, c in consts: cname = c.cname self.parts['module_state'].putln("PyObject *%s;" % cname) self.parts['module_state_defines'].putln("#define %s %s->%s" % ( cname, Naming.modulestateglobal_cname, cname)) self.parts['module_state_clear'].putln( "Py_CLEAR(clear_module_state->%s);" % cname) self.parts['module_state_traverse'].putln( "Py_VISIT(traverse_module_state->%s);" % cname) if py_type == 'float': function = 'PyFloat_FromDouble(%s)' elif py_type == 'long': function = 'PyLong_FromString((char *)"%s", 0, 0)' elif Utils.long_literal(value): function = 'PyInt_FromString((char *)"%s", 0, 0)' elif len(value.lstrip('-')) > 4: function = "PyInt_FromLong(%sL)" else: function = "PyInt_FromLong(%s)" init_constants.putln('%s = %s; %s' % ( cname, function % value_code, init_constants.error_goto_if_null(cname, self.module_pos))) # The functions below are there in a transition phase only # and will be deprecated. They are called from Nodes.BlockNode. # The copy&paste duplication is intentional in order to be able # to see quickly how BlockNode worked, until this is replaced. def should_declare(self, cname, entry): if cname in self.declared_cnames: other = self.declared_cnames[cname] assert str(entry.type) == str(other.type) assert entry.init == other.init return False else: self.declared_cnames[cname] = entry return True # # File name state # def lookup_filename(self, source_desc): entry = source_desc.get_filenametable_entry() try: index = self.filename_table[entry] except KeyError: index = len(self.filename_list) self.filename_list.append(source_desc) self.filename_table[entry] = index return index def commented_file_contents(self, source_desc): try: return self.input_file_contents[source_desc] except KeyError: pass source_file = source_desc.get_lines(encoding='ASCII', error_handling='ignore') try: F = [u' * ' + line.rstrip().replace( u'*/', u'*[inserted by cython to avoid comment closer]/' ).replace( u'/*', u'/[inserted by cython to avoid comment start]*' ) for line in source_file] finally: if hasattr(source_file, 'close'): source_file.close() if not F: F.append(u'') self.input_file_contents[source_desc] = F return F # # Utility code state # def use_utility_code(self, utility_code): """ Adds code to the C file. utility_code should a) implement __eq__/__hash__ for the purpose of knowing whether the same code has already been included b) implement put_code, which takes a globalstate instance See UtilityCode. """ if utility_code and utility_code not in self.utility_codes: self.utility_codes.add(utility_code) utility_code.put_code(self) def use_entry_utility_code(self, entry): if entry is None: return if entry.utility_code: self.use_utility_code(entry.utility_code) if entry.utility_code_definition: self.use_utility_code(entry.utility_code_definition) def funccontext_property(func): name = func.__name__ attribute_of = operator.attrgetter(name) def get(self): return attribute_of(self.funcstate) def set(self, value): setattr(self.funcstate, name, value) return property(get, set) class CCodeConfig(object): # emit_linenums boolean write #line pragmas? # emit_code_comments boolean copy the original code into C comments? # c_line_in_traceback boolean append the c file and line number to the traceback for exceptions? def __init__(self, emit_linenums=True, emit_code_comments=True, c_line_in_traceback=True): self.emit_code_comments = emit_code_comments self.emit_linenums = emit_linenums self.c_line_in_traceback = c_line_in_traceback class CCodeWriter(object): """ Utility class to output C code. When creating an insertion point one must care about the state that is kept: - formatting state (level, bol) is cloned and used in insertion points as well - labels, temps, exc_vars: One must construct a scope in which these can exist by calling enter_cfunc_scope/exit_cfunc_scope (these are for sanity checking and forward compatibility). Created insertion points looses this scope and cannot access it. - marker: Not copied to insertion point - filename_table, filename_list, input_file_contents: All codewriters coming from the same root share the same instances simultaneously. """ # f file output file # buffer StringIOTree # level int indentation level # bol bool beginning of line? # marker string comment to emit before next line # funcstate FunctionState contains state local to a C function used for code # generation (labels and temps state etc.) # globalstate GlobalState contains state global for a C file (input file info, # utility code, declared constants etc.) # pyclass_stack list used during recursive code generation to pass information # about the current class one is in # code_config CCodeConfig configuration options for the C code writer @cython.locals(create_from='CCodeWriter') def __init__(self, create_from=None, buffer=None, copy_formatting=False): if buffer is None: buffer = StringIOTree() self.buffer = buffer self.last_pos = None self.last_marked_pos = None self.pyclass_stack = [] self.funcstate = None self.globalstate = None self.code_config = None self.level = 0 self.call_level = 0 self.bol = 1 if create_from is not None: # Use same global state self.set_global_state(create_from.globalstate) self.funcstate = create_from.funcstate # Clone formatting state if copy_formatting: self.level = create_from.level self.bol = create_from.bol self.call_level = create_from.call_level self.last_pos = create_from.last_pos self.last_marked_pos = create_from.last_marked_pos def create_new(self, create_from, buffer, copy_formatting): # polymorphic constructor -- very slightly more versatile # than using __class__ result = CCodeWriter(create_from, buffer, copy_formatting) return result def set_global_state(self, global_state): assert self.globalstate is None # prevent overwriting once it's set self.globalstate = global_state self.code_config = global_state.code_config def copyto(self, f): self.buffer.copyto(f) def getvalue(self): return self.buffer.getvalue() def write(self, s): if '\n' in s: self._write_lines(s) else: self._write_to_buffer(s) def _write_lines(self, s): # Cygdb needs to know which Cython source line corresponds to which C line. # Therefore, we write this information into "self.buffer.markers" and then write it from there # into cython_debug/cython_debug_info_* (see ModuleNode._serialize_lineno_map). filename_line = self.last_marked_pos[:2] if self.last_marked_pos else (None, 0) self.buffer.markers.extend([filename_line] * s.count('\n')) self._write_to_buffer(s) def _write_to_buffer(self, s): self.buffer.write(s) def insertion_point(self): other = self.create_new(create_from=self, buffer=self.buffer.insertion_point(), copy_formatting=True) return other def new_writer(self): """ Creates a new CCodeWriter connected to the same global state, which can later be inserted using insert. """ return CCodeWriter(create_from=self) def insert(self, writer): """ Inserts the contents of another code writer (created with the same global state) in the current location. It is ok to write to the inserted writer also after insertion. """ assert writer.globalstate is self.globalstate self.buffer.insert(writer.buffer) # Properties delegated to function scope @funccontext_property def label_counter(self): pass @funccontext_property def return_label(self): pass @funccontext_property def error_label(self): pass @funccontext_property def labels_used(self): pass @funccontext_property def continue_label(self): pass @funccontext_property def break_label(self): pass @funccontext_property def return_from_error_cleanup_label(self): pass @funccontext_property def yield_labels(self): pass def label_interceptor(self, new_labels, orig_labels, skip_to_label=None, pos=None, trace=True): """ Helper for generating multiple label interceptor code blocks. @param new_labels: the new labels that should be intercepted @param orig_labels: the original labels that we should dispatch to after the interception @param skip_to_label: a label to skip to before starting the code blocks @param pos: the node position to mark for each interceptor block @param trace: add a trace line for the pos marker or not """ for label, orig_label in zip(new_labels, orig_labels): if not self.label_used(label): continue if skip_to_label: # jump over the whole interception block self.put_goto(skip_to_label) skip_to_label = None if pos is not None: self.mark_pos(pos, trace=trace) self.put_label(label) yield (label, orig_label) self.put_goto(orig_label) # Functions delegated to function scope def new_label(self, name=None): return self.funcstate.new_label(name) def new_error_label(self, *args): return self.funcstate.new_error_label(*args) def new_yield_label(self, *args): return self.funcstate.new_yield_label(*args) def get_loop_labels(self): return self.funcstate.get_loop_labels() def set_loop_labels(self, labels): return self.funcstate.set_loop_labels(labels) def new_loop_labels(self, *args): return self.funcstate.new_loop_labels(*args) def get_all_labels(self): return self.funcstate.get_all_labels() def set_all_labels(self, labels): return self.funcstate.set_all_labels(labels) def all_new_labels(self): return self.funcstate.all_new_labels() def use_label(self, lbl): return self.funcstate.use_label(lbl) def label_used(self, lbl): return self.funcstate.label_used(lbl) def enter_cfunc_scope(self, scope=None): self.funcstate = FunctionState(self, scope=scope) def exit_cfunc_scope(self): self.funcstate.validate_exit() self.funcstate = None # constant handling def get_py_int(self, str_value, longness): return self.globalstate.get_int_const(str_value, longness).cname def get_py_float(self, str_value, value_code): return self.globalstate.get_float_const(str_value, value_code).cname def get_py_const(self, type, prefix='', cleanup_level=None, dedup_key=None): return self.globalstate.get_py_const(type, prefix, cleanup_level, dedup_key).cname def get_string_const(self, text): return self.globalstate.get_string_const(text).cname def get_pyunicode_ptr_const(self, text): return self.globalstate.get_pyunicode_ptr_const(text) def get_py_string_const(self, text, identifier=None, is_str=False, unicode_value=None): return self.globalstate.get_py_string_const( text, identifier, is_str, unicode_value).cname def get_argument_default_const(self, type): return self.globalstate.get_py_const(type).cname def intern(self, text): return self.get_py_string_const(text) def intern_identifier(self, text): return self.get_py_string_const(text, identifier=True) def get_cached_constants_writer(self, target=None): return self.globalstate.get_cached_constants_writer(target) # code generation def putln(self, code="", safe=False): if self.last_pos and self.bol: self.emit_marker() if self.code_config.emit_linenums and self.last_marked_pos: source_desc, line, _ = self.last_marked_pos self._write_lines('\n#line %s "%s"\n' % (line, source_desc.get_escaped_description())) if code: if safe: self.put_safe(code) else: self.put(code) self._write_lines("\n") self.bol = 1 def mark_pos(self, pos, trace=True): if pos is None: return if self.last_marked_pos and self.last_marked_pos[:2] == pos[:2]: return self.last_pos = (pos, trace) def emit_marker(self): pos, trace = self.last_pos self.last_marked_pos = pos self.last_pos = None self._write_lines("\n") if self.code_config.emit_code_comments: self.indent() self._write_lines("/* %s */\n" % self._build_marker(pos)) if trace and self.funcstate and self.funcstate.can_trace and self.globalstate.directives['linetrace']: self.indent() self._write_lines('__Pyx_TraceLine(%d,%d,%s)\n' % ( pos[1], not self.funcstate.gil_owned, self.error_goto(pos))) def _build_marker(self, pos): source_desc, line, col = pos assert isinstance(source_desc, SourceDescriptor) contents = self.globalstate.commented_file_contents(source_desc) lines = contents[max(0, line-3):line] # line numbers start at 1 lines[-1] += u' # <<<<<<<<<<<<<<' lines += contents[line:line+2] return u'"%s":%d\n%s\n' % (source_desc.get_escaped_description(), line, u'\n'.join(lines)) def put_safe(self, code): # put code, but ignore {} self.write(code) self.bol = 0 def put_or_include(self, code, name): include_dir = self.globalstate.common_utility_include_dir if include_dir and len(code) > 1024: include_file = "%s_%s.h" % ( name, hashlib.sha1(code.encode('utf8')).hexdigest()) path = os.path.join(include_dir, include_file) if not os.path.exists(path): tmp_path = '%s.tmp%s' % (path, os.getpid()) with closing(Utils.open_new_file(tmp_path)) as f: f.write(code) shutil.move(tmp_path, path) code = '#include "%s"\n' % path self.put(code) def put(self, code): fix_indent = False if "{" in code: dl = code.count("{") else: dl = 0 if "}" in code: dl -= code.count("}") if dl < 0: self.level += dl elif dl == 0 and code[0] == "}": # special cases like "} else {" need a temporary dedent fix_indent = True self.level -= 1 if self.bol: self.indent() self.write(code) self.bol = 0 if dl > 0: self.level += dl elif fix_indent: self.level += 1 def putln_tempita(self, code, **context): from ..Tempita import sub self.putln(sub(code, **context)) def put_tempita(self, code, **context): from ..Tempita import sub self.put(sub(code, **context)) def increase_indent(self): self.level += 1 def decrease_indent(self): self.level -= 1 def begin_block(self): self.putln("{") self.increase_indent() def end_block(self): self.decrease_indent() self.putln("}") def indent(self): self._write_to_buffer(" " * self.level) def get_py_version_hex(self, pyversion): return "0x%02X%02X%02X%02X" % (tuple(pyversion) + (0,0,0,0))[:4] def put_label(self, lbl): if lbl in self.funcstate.labels_used: self.putln("%s:;" % lbl) def put_goto(self, lbl): self.funcstate.use_label(lbl) self.putln("goto %s;" % lbl) def put_var_declaration(self, entry, storage_class="", dll_linkage=None, definition=True): #print "Code.put_var_declaration:", entry.name, "definition =", definition ### if entry.visibility == 'private' and not (definition or entry.defined_in_pxd): #print "...private and not definition, skipping", entry.cname ### return if entry.visibility == "private" and not entry.used: #print "...private and not used, skipping", entry.cname ### return if not entry.cf_used: self.put('CYTHON_UNUSED ') if storage_class: self.put("%s " % storage_class) if entry.is_cpp_optional: self.put(entry.type.cpp_optional_declaration_code( entry.cname, dll_linkage=dll_linkage)) else: self.put(entry.type.declaration_code( entry.cname, dll_linkage=dll_linkage)) if entry.init is not None: self.put_safe(" = %s" % entry.type.literal_code(entry.init)) elif entry.type.is_pyobject: self.put(" = NULL") self.putln(";") self.funcstate.scope.use_entry_utility_code(entry) def put_temp_declarations(self, func_context): for name, type, manage_ref, static in func_context.temps_allocated: if type.is_cpp_class and not type.is_fake_reference and func_context.scope.directives['cpp_locals']: decl = type.cpp_optional_declaration_code(name) else: decl = type.declaration_code(name) if type.is_pyobject: self.putln("%s = NULL;" % decl) elif type.is_memoryviewslice: self.putln("%s = %s;" % (decl, type.literal_code(type.default_value))) else: self.putln("%s%s;" % (static and "static " or "", decl)) if func_context.should_declare_error_indicator: if self.funcstate.uses_error_indicator: unused = '' else: unused = 'CYTHON_UNUSED ' # Initialize these variables to silence compiler warnings self.putln("%sint %s = 0;" % (unused, Naming.lineno_cname)) self.putln("%sconst char *%s = NULL;" % (unused, Naming.filename_cname)) self.putln("%sint %s = 0;" % (unused, Naming.clineno_cname)) def put_generated_by(self): self.putln(Utils.GENERATED_BY_MARKER) self.putln("") def put_h_guard(self, guard): self.putln("#ifndef %s" % guard) self.putln("#define %s" % guard) def unlikely(self, cond): if Options.gcc_branch_hints: return 'unlikely(%s)' % cond else: return cond def build_function_modifiers(self, modifiers, mapper=modifier_output_mapper): if not modifiers: return '' return '%s ' % ' '.join([mapper(m,m) for m in modifiers]) # Python objects and reference counting def entry_as_pyobject(self, entry): type = entry.type if (not entry.is_self_arg and not entry.type.is_complete() or entry.type.is_extension_type): return "(PyObject *)" + entry.cname else: return entry.cname def as_pyobject(self, cname, type): from .PyrexTypes import py_object_type, typecast return typecast(py_object_type, type, cname) def put_gotref(self, cname, type): type.generate_gotref(self, cname) def put_giveref(self, cname, type): type.generate_giveref(self, cname) def put_xgiveref(self, cname, type): type.generate_xgiveref(self, cname) def put_xgotref(self, cname, type): type.generate_xgotref(self, cname) def put_incref(self, cname, type, nanny=True): # Note: original put_Memslice_Incref/Decref also added in some utility code # this is unnecessary since the relevant utility code is loaded anyway if a memoryview is used # and so has been removed. However, it's potentially a feature that might be useful here type.generate_incref(self, cname, nanny=nanny) def put_xincref(self, cname, type, nanny=True): type.generate_xincref(self, cname, nanny=nanny) def put_decref(self, cname, type, nanny=True, have_gil=True): type.generate_decref(self, cname, nanny=nanny, have_gil=have_gil) def put_xdecref(self, cname, type, nanny=True, have_gil=True): type.generate_xdecref(self, cname, nanny=nanny, have_gil=have_gil) def put_decref_clear(self, cname, type, clear_before_decref=False, nanny=True, have_gil=True): type.generate_decref_clear(self, cname, clear_before_decref=clear_before_decref, nanny=nanny, have_gil=have_gil) def put_xdecref_clear(self, cname, type, clear_before_decref=False, nanny=True, have_gil=True): type.generate_xdecref_clear(self, cname, clear_before_decref=clear_before_decref, nanny=nanny, have_gil=have_gil) def put_decref_set(self, cname, type, rhs_cname): type.generate_decref_set(self, cname, rhs_cname) def put_xdecref_set(self, cname, type, rhs_cname): type.generate_xdecref_set(self, cname, rhs_cname) def put_incref_memoryviewslice(self, slice_cname, type, have_gil): # TODO ideally this would just be merged into "put_incref" type.generate_incref_memoryviewslice(self, slice_cname, have_gil=have_gil) def put_var_incref_memoryviewslice(self, entry, have_gil): self.put_incref_memoryviewslice(entry.cname, entry.type, have_gil=have_gil) def put_var_gotref(self, entry): self.put_gotref(entry.cname, entry.type) def put_var_giveref(self, entry): self.put_giveref(entry.cname, entry.type) def put_var_xgotref(self, entry): self.put_xgotref(entry.cname, entry.type) def put_var_xgiveref(self, entry): self.put_xgiveref(entry.cname, entry.type) def put_var_incref(self, entry, **kwds): self.put_incref(entry.cname, entry.type, **kwds) def put_var_xincref(self, entry, **kwds): self.put_xincref(entry.cname, entry.type, **kwds) def put_var_decref(self, entry, **kwds): self.put_decref(entry.cname, entry.type, **kwds) def put_var_xdecref(self, entry, **kwds): self.put_xdecref(entry.cname, entry.type, **kwds) def put_var_decref_clear(self, entry, **kwds): self.put_decref_clear(entry.cname, entry.type, clear_before_decref=entry.in_closure, **kwds) def put_var_decref_set(self, entry, rhs_cname, **kwds): self.put_decref_set(entry.cname, entry.type, rhs_cname, **kwds) def put_var_xdecref_set(self, entry, rhs_cname, **kwds): self.put_xdecref_set(entry.cname, entry.type, rhs_cname, **kwds) def put_var_xdecref_clear(self, entry, **kwds): self.put_xdecref_clear(entry.cname, entry.type, clear_before_decref=entry.in_closure, **kwds) def put_var_decrefs(self, entries, used_only = 0): for entry in entries: if not used_only or entry.used: if entry.xdecref_cleanup: self.put_var_xdecref(entry) else: self.put_var_decref(entry) def put_var_xdecrefs(self, entries): for entry in entries: self.put_var_xdecref(entry) def put_var_xdecrefs_clear(self, entries): for entry in entries: self.put_var_xdecref_clear(entry) def put_init_to_py_none(self, cname, type, nanny=True): from .PyrexTypes import py_object_type, typecast py_none = typecast(type, py_object_type, "Py_None") if nanny: self.putln("%s = %s; __Pyx_INCREF(Py_None);" % (cname, py_none)) else: self.putln("%s = %s; Py_INCREF(Py_None);" % (cname, py_none)) def put_init_var_to_py_none(self, entry, template = "%s", nanny=True): code = template % entry.cname #if entry.type.is_extension_type: # code = "((PyObject*)%s)" % code self.put_init_to_py_none(code, entry.type, nanny) if entry.in_closure: self.put_giveref('Py_None') def put_pymethoddef(self, entry, term, allow_skip=True, wrapper_code_writer=None): is_reverse_number_slot = False if entry.is_special or entry.name == '__getattribute__': from . import TypeSlots is_reverse_number_slot = True if entry.name not in special_py_methods and not TypeSlots.is_reverse_number_slot(entry.name): if entry.name == '__getattr__' and not self.globalstate.directives['fast_getattr']: pass # Python's typeobject.c will automatically fill in our slot # in add_operators() (called by PyType_Ready) with a value # that's better than ours. elif allow_skip: return method_flags = entry.signature.method_flags() if not method_flags: return if entry.is_special: method_flags += [TypeSlots.method_coexist] func_ptr = wrapper_code_writer.put_pymethoddef_wrapper(entry) if wrapper_code_writer else entry.func_cname # Add required casts, but try not to shadow real warnings. cast = entry.signature.method_function_type() if cast != 'PyCFunction': func_ptr = '(void*)(%s)%s' % (cast, func_ptr) entry_name = entry.name.as_c_string_literal() if is_reverse_number_slot: # Unlike most special functions, reverse number operator slots are actually generated here # (to ensure that they can be looked up). However, they're sometimes guarded by the preprocessor # so a bit of extra logic is needed slot = TypeSlots.get_slot_table(self.globalstate.directives).get_slot_by_method_name(entry.name) preproc_guard = slot.preprocessor_guard_code() if preproc_guard: self.putln(preproc_guard) self.putln( '{%s, (PyCFunction)%s, %s, %s}%s' % ( entry_name, func_ptr, "|".join(method_flags), entry.doc_cname if entry.doc else '0', term)) if is_reverse_number_slot and preproc_guard: self.putln("#endif") def put_pymethoddef_wrapper(self, entry): func_cname = entry.func_cname if entry.is_special: method_flags = entry.signature.method_flags() or [] from .TypeSlots import method_noargs if method_noargs in method_flags: # Special NOARGS methods really take no arguments besides 'self', but PyCFunction expects one. func_cname = Naming.method_wrapper_prefix + func_cname self.putln("static PyObject *%s(PyObject *self, CYTHON_UNUSED PyObject *arg) {" % func_cname) func_call = "%s(self)" % entry.func_cname if entry.name == "__next__": self.putln("PyObject *res = %s;" % func_call) # tp_iternext can return NULL without an exception self.putln("if (!res && !PyErr_Occurred()) { PyErr_SetNone(PyExc_StopIteration); }") self.putln("return res;") else: self.putln("return %s;" % func_call) self.putln("}") return func_cname # GIL methods def use_fast_gil_utility_code(self): if self.globalstate.directives['fast_gil']: self.globalstate.use_utility_code(UtilityCode.load_cached("FastGil", "ModuleSetupCode.c")) else: self.globalstate.use_utility_code(UtilityCode.load_cached("NoFastGil", "ModuleSetupCode.c")) def put_ensure_gil(self, declare_gilstate=True, variable=None): """ Acquire the GIL. The generated code is safe even when no PyThreadState has been allocated for this thread (for threads not initialized by using the Python API). Additionally, the code generated by this method may be called recursively. """ self.globalstate.use_utility_code( UtilityCode.load_cached("ForceInitThreads", "ModuleSetupCode.c")) self.use_fast_gil_utility_code() self.putln("#ifdef WITH_THREAD") if not variable: variable = '__pyx_gilstate_save' if declare_gilstate: self.put("PyGILState_STATE ") self.putln("%s = __Pyx_PyGILState_Ensure();" % variable) self.putln("#endif") def put_release_ensured_gil(self, variable=None): """ Releases the GIL, corresponds to `put_ensure_gil`. """ self.use_fast_gil_utility_code() if not variable: variable = '__pyx_gilstate_save' self.putln("#ifdef WITH_THREAD") self.putln("__Pyx_PyGILState_Release(%s);" % variable) self.putln("#endif") def put_acquire_gil(self, variable=None, unknown_gil_state=True): """ Acquire the GIL. The thread's thread state must have been initialized by a previous `put_release_gil` """ self.use_fast_gil_utility_code() self.putln("#ifdef WITH_THREAD") self.putln("__Pyx_FastGIL_Forget();") if variable: self.putln('_save = %s;' % variable) if unknown_gil_state: self.putln("if (_save) {") self.putln("Py_BLOCK_THREADS") if unknown_gil_state: self.putln("}") self.putln("#endif") def put_release_gil(self, variable=None, unknown_gil_state=True): "Release the GIL, corresponds to `put_acquire_gil`." self.use_fast_gil_utility_code() self.putln("#ifdef WITH_THREAD") self.putln("PyThreadState *_save;") self.putln("_save = NULL;") if unknown_gil_state: # we don't *know* that we don't have the GIL (since we may be inside a nogil function, # and Py_UNBLOCK_THREADS is unsafe without the GIL) self.putln("if (PyGILState_Check()) {") self.putln("Py_UNBLOCK_THREADS") if unknown_gil_state: self.putln("}") if variable: self.putln('%s = _save;' % variable) self.putln("__Pyx_FastGIL_Remember();") self.putln("#endif") def declare_gilstate(self): self.putln("#ifdef WITH_THREAD") self.putln("PyGILState_STATE __pyx_gilstate_save;") self.putln("#endif") # error handling def put_error_if_neg(self, pos, value): # TODO this path is almost _never_ taken, yet this macro makes is slower! # return self.putln("if (unlikely(%s < 0)) %s" % (value, self.error_goto(pos))) return self.putln("if (%s < 0) %s" % (value, self.error_goto(pos))) def put_error_if_unbound(self, pos, entry, in_nogil_context=False, unbound_check_code=None): if entry.from_closure: func = '__Pyx_RaiseClosureNameError' self.globalstate.use_utility_code( UtilityCode.load_cached("RaiseClosureNameError", "ObjectHandling.c")) elif entry.type.is_memoryviewslice and in_nogil_context: func = '__Pyx_RaiseUnboundMemoryviewSliceNogil' self.globalstate.use_utility_code( UtilityCode.load_cached("RaiseUnboundMemoryviewSliceNogil", "ObjectHandling.c")) elif entry.type.is_cpp_class and entry.is_cglobal: func = '__Pyx_RaiseCppGlobalNameError' self.globalstate.use_utility_code( UtilityCode.load_cached("RaiseCppGlobalNameError", "ObjectHandling.c")) elif entry.type.is_cpp_class and entry.is_variable and not entry.is_member and entry.scope.is_c_class_scope: # there doesn't seem to be a good way to detecting an instance-attribute of a C class # (is_member is only set for class attributes) func = '__Pyx_RaiseCppAttributeError' self.globalstate.use_utility_code( UtilityCode.load_cached("RaiseCppAttributeError", "ObjectHandling.c")) else: func = '__Pyx_RaiseUnboundLocalError' self.globalstate.use_utility_code( UtilityCode.load_cached("RaiseUnboundLocalError", "ObjectHandling.c")) if not unbound_check_code: unbound_check_code = entry.type.check_for_null_code(entry.cname) self.putln('if (unlikely(!%s)) { %s("%s"); %s }' % ( unbound_check_code, func, entry.name, self.error_goto(pos))) def set_error_info(self, pos, used=False): self.funcstate.should_declare_error_indicator = True if used: self.funcstate.uses_error_indicator = True return "__PYX_MARK_ERR_POS(%s, %s)" % ( self.lookup_filename(pos[0]), pos[1]) def error_goto(self, pos, used=True): lbl = self.funcstate.error_label self.funcstate.use_label(lbl) if pos is None: return 'goto %s;' % lbl self.funcstate.should_declare_error_indicator = True if used: self.funcstate.uses_error_indicator = True return "__PYX_ERR(%s, %s, %s)" % ( self.lookup_filename(pos[0]), pos[1], lbl) def error_goto_if(self, cond, pos): return "if (%s) %s" % (self.unlikely(cond), self.error_goto(pos)) def error_goto_if_null(self, cname, pos): return self.error_goto_if("!%s" % cname, pos) def error_goto_if_neg(self, cname, pos): # Add extra parentheses to silence clang warnings about constant conditions. return self.error_goto_if("(%s < 0)" % cname, pos) def error_goto_if_PyErr(self, pos): return self.error_goto_if("PyErr_Occurred()", pos) def lookup_filename(self, filename): return self.globalstate.lookup_filename(filename) def put_declare_refcount_context(self): self.putln('__Pyx_RefNannyDeclarations') def put_setup_refcount_context(self, name, acquire_gil=False): name = name.as_c_string_literal() # handle unicode names if acquire_gil: self.globalstate.use_utility_code( UtilityCode.load_cached("ForceInitThreads", "ModuleSetupCode.c")) self.putln('__Pyx_RefNannySetupContext(%s, %d);' % (name, acquire_gil and 1 or 0)) def put_finish_refcount_context(self, nogil=False): self.putln("__Pyx_RefNannyFinishContextNogil()" if nogil else "__Pyx_RefNannyFinishContext();") def put_add_traceback(self, qualified_name, include_cline=True): """ Build a Python traceback for propagating exceptions. qualified_name should be the qualified name of the function. """ qualified_name = qualified_name.as_c_string_literal() # handle unicode names format_tuple = ( qualified_name, Naming.clineno_cname if include_cline else 0, Naming.lineno_cname, Naming.filename_cname, ) self.funcstate.uses_error_indicator = True self.putln('__Pyx_AddTraceback(%s, %s, %s, %s);' % format_tuple) def put_unraisable(self, qualified_name, nogil=False): """ Generate code to print a Python warning for an unraisable exception. qualified_name should be the qualified name of the function. """ format_tuple = ( qualified_name, Naming.clineno_cname, Naming.lineno_cname, Naming.filename_cname, self.globalstate.directives['unraisable_tracebacks'], nogil, ) self.funcstate.uses_error_indicator = True self.putln('__Pyx_WriteUnraisable("%s", %s, %s, %s, %d, %d);' % format_tuple) self.globalstate.use_utility_code( UtilityCode.load_cached("WriteUnraisableException", "Exceptions.c")) def put_trace_declarations(self): self.putln('__Pyx_TraceDeclarations') def put_trace_frame_init(self, codeobj=None): if codeobj: self.putln('__Pyx_TraceFrameInit(%s)' % codeobj) def put_trace_call(self, name, pos, nogil=False): self.putln('__Pyx_TraceCall("%s", %s[%s], %s, %d, %s);' % ( name, Naming.filetable_cname, self.lookup_filename(pos[0]), pos[1], nogil, self.error_goto(pos))) def put_trace_exception(self): self.putln("__Pyx_TraceException();") def put_trace_return(self, retvalue_cname, nogil=False): self.putln("__Pyx_TraceReturn(%s, %d);" % (retvalue_cname, nogil)) def putln_openmp(self, string): self.putln("#ifdef _OPENMP") self.putln(string) self.putln("#endif /* _OPENMP */") def undef_builtin_expect(self, cond): """ Redefine the macros likely() and unlikely to no-ops, depending on condition 'cond' """ self.putln("#if %s" % cond) self.putln(" #undef likely") self.putln(" #undef unlikely") self.putln(" #define likely(x) (x)") self.putln(" #define unlikely(x) (x)") self.putln("#endif") def redef_builtin_expect(self, cond): self.putln("#if %s" % cond) self.putln(" #undef likely") self.putln(" #undef unlikely") self.putln(" #define likely(x) __builtin_expect(!!(x), 1)") self.putln(" #define unlikely(x) __builtin_expect(!!(x), 0)") self.putln("#endif") class PyrexCodeWriter(object): # f file output file # level int indentation level def __init__(self, outfile_name): self.f = Utils.open_new_file(outfile_name) self.level = 0 def putln(self, code): self.f.write("%s%s\n" % (" " * self.level, code)) def indent(self): self.level += 1 def dedent(self): self.level -= 1 class PyxCodeWriter(object): """ Can be used for writing out some Cython code. """ def __init__(self, buffer=None, indent_level=0, context=None, encoding='ascii'): self.buffer = buffer or StringIOTree() self.level = indent_level self.original_level = indent_level self.context = context self.encoding = encoding def indent(self, levels=1): self.level += levels return True def dedent(self, levels=1): self.level -= levels @contextmanager def indenter(self, line): """ with pyx_code.indenter("for i in range(10):"): pyx_code.putln("print i") """ self.putln(line) self.indent() yield self.dedent() def empty(self): return self.buffer.empty() def getvalue(self): result = self.buffer.getvalue() if isinstance(result, bytes): result = result.decode(self.encoding) return result def putln(self, line, context=None): context = context or self.context if context: line = sub_tempita(line, context) self._putln(line) def _putln(self, line): self.buffer.write(u"%s%s\n" % (self.level * u" ", line)) def put_chunk(self, chunk, context=None): context = context or self.context if context: chunk = sub_tempita(chunk, context) chunk = textwrap.dedent(chunk) for line in chunk.splitlines(): self._putln(line) def insertion_point(self): return type(self)(self.buffer.insertion_point(), self.level, self.context) def reset(self): # resets the buffer so that nothing gets written. Most useful # for abandoning all work in a specific insertion point self.buffer.reset() self.level = self.original_level def named_insertion_point(self, name): setattr(self, name, self.insertion_point()) class ClosureTempAllocator(object): def __init__(self, klass): self.klass = klass self.temps_allocated = {} self.temps_free = {} self.temps_count = 0 def reset(self): for type, cnames in self.temps_allocated.items(): self.temps_free[type] = list(cnames) def allocate_temp(self, type): if type not in self.temps_allocated: self.temps_allocated[type] = [] self.temps_free[type] = [] elif self.temps_free[type]: return self.temps_free[type].pop(0) cname = '%s%d' % (Naming.codewriter_temp_prefix, self.temps_count) self.klass.declare_var(pos=None, name=cname, cname=cname, type=type, is_cdef=True) self.temps_allocated[type].append(cname) self.temps_count += 1 return cname ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Compiler/CodeGeneration.py0000644000175100001770000000212400000000000022051 0ustar00runnerdocker00000000000000from __future__ import absolute_import from .Visitor import VisitorTransform from .Nodes import StatListNode class ExtractPxdCode(VisitorTransform): """ Finds nodes in a pxd file that should generate code, and returns them in a StatListNode. The result is a tuple (StatListNode, ModuleScope), i.e. everything that is needed from the pxd after it is processed. A purer approach would be to separately compile the pxd code, but the result would have to be slightly more sophisticated than pure strings (functions + wanted interned strings + wanted utility code + wanted cached objects) so for now this approach is taken. """ def __call__(self, root): self.funcs = [] self.visitchildren(root) return (StatListNode(root.pos, stats=self.funcs), root.scope) def visit_FuncDefNode(self, node): self.funcs.append(node) # Do not visit children, nested funcdefnodes will # also be moved by this action... return node def visit_Node(self, node): self.visitchildren(node) return node ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Compiler/CythonScope.py0000644000175100001770000001531700000000000021431 0ustar00runnerdocker00000000000000from __future__ import absolute_import from .Symtab import ModuleScope from .PyrexTypes import * from .UtilityCode import CythonUtilityCode from .Errors import error from .Scanning import StringSourceDescriptor from . import MemoryView from .StringEncoding import EncodedString class CythonScope(ModuleScope): is_cython_builtin = 1 _cythonscope_initialized = False def __init__(self, context): ModuleScope.__init__(self, u'cython', None, None) self.pxd_file_loaded = True self.populate_cython_scope() # The Main.Context object self.context = context for fused_type in (cy_integral_type, cy_floating_type, cy_numeric_type): entry = self.declare_typedef(fused_type.name, fused_type, None, cname='') entry.in_cinclude = True def is_cpp(self): # Allow C++ utility code in C++ contexts. return self.context.cpp def lookup_type(self, name): # This function should go away when types are all first-level objects. type = parse_basic_type(name) if type: return type return super(CythonScope, self).lookup_type(name) def lookup(self, name): entry = super(CythonScope, self).lookup(name) if entry is None and not self._cythonscope_initialized: self.load_cythonscope() entry = super(CythonScope, self).lookup(name) return entry def find_module(self, module_name, pos): error("cython.%s is not available" % module_name, pos) def find_submodule(self, module_name, as_package=False): entry = self.entries.get(module_name, None) if not entry: self.load_cythonscope() entry = self.entries.get(module_name, None) if entry and entry.as_module: return entry.as_module else: # TODO: fix find_submodule control flow so that we're not # expected to create a submodule here (to protect CythonScope's # possible immutability). Hack ourselves out of the situation # for now. raise error((StringSourceDescriptor(u"cython", u""), 0, 0), "cython.%s is not available" % module_name) def lookup_qualified_name(self, qname): # ExprNode.as_cython_attribute generates qnames and we untangle it here... name_path = qname.split(u'.') scope = self while len(name_path) > 1: scope = scope.lookup_here(name_path[0]) if scope: scope = scope.as_module del name_path[0] if scope is None: return None else: return scope.lookup_here(name_path[0]) def populate_cython_scope(self): # These are used to optimize isinstance in FinalOptimizePhase type_object = self.declare_typedef( 'PyTypeObject', base_type = c_void_type, pos = None, cname = 'PyTypeObject') type_object.is_void = True type_object_type = type_object.type self.declare_cfunction( 'PyObject_TypeCheck', CFuncType(c_bint_type, [CFuncTypeArg("o", py_object_type, None), CFuncTypeArg("t", c_ptr_type(type_object_type), None)]), pos = None, defining = 1, cname = 'PyObject_TypeCheck') def load_cythonscope(self): """ Creates some entries for testing purposes and entries for cython.array() and for cython.view.*. """ if self._cythonscope_initialized: return self._cythonscope_initialized = True cython_testscope_utility_code.declare_in_scope( self, cython_scope=self) cython_test_extclass_utility_code.declare_in_scope( self, cython_scope=self) # # The view sub-scope # self.viewscope = viewscope = ModuleScope(u'view', self, None) self.declare_module('view', viewscope, None).as_module = viewscope viewscope.is_cython_builtin = True viewscope.pxd_file_loaded = True cythonview_testscope_utility_code.declare_in_scope( viewscope, cython_scope=self) view_utility_scope = MemoryView.view_utility_code.declare_in_scope( self.viewscope, cython_scope=self, allowlist=MemoryView.view_utility_allowlist) # Marks the types as being cython_builtin_type so that they can be # extended from without Cython attempting to import cython.view ext_types = [ entry.type for entry in view_utility_scope.entries.values() if entry.type.is_extension_type ] for ext_type in ext_types: ext_type.is_cython_builtin_type = 1 # self.entries["array"] = view_utility_scope.entries.pop("array") # dataclasses scope dc_str = EncodedString(u'dataclasses') dataclassesscope = ModuleScope(dc_str, self, context=None) self.declare_module(dc_str, dataclassesscope, pos=None).as_module = dataclassesscope dataclassesscope.is_cython_builtin = True dataclassesscope.pxd_file_loaded = True # doesn't actually have any contents def create_cython_scope(context): # One could in fact probably make it a singleton, # but not sure yet whether any code mutates it (which would kill reusing # it across different contexts) return CythonScope(context) # Load test utilities for the cython scope def load_testscope_utility(cy_util_name, **kwargs): return CythonUtilityCode.load(cy_util_name, "TestCythonScope.pyx", **kwargs) undecorated_methods_protos = UtilityCode(proto=u""" /* These methods are undecorated and have therefore no prototype */ static PyObject *__pyx_TestClass_cdef_method( struct __pyx_TestClass_obj *self, int value); static PyObject *__pyx_TestClass_cpdef_method( struct __pyx_TestClass_obj *self, int value, int skip_dispatch); static PyObject *__pyx_TestClass_def_method( PyObject *self, PyObject *value); """) cython_testscope_utility_code = load_testscope_utility("TestScope") test_cython_utility_dep = load_testscope_utility("TestDep") cython_test_extclass_utility_code = \ load_testscope_utility("TestClass", name="TestClass", requires=[undecorated_methods_protos, test_cython_utility_dep]) cythonview_testscope_utility_code = load_testscope_utility("View.TestScope") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Compiler/Dataclass.py0000644000175100001770000010630000000000000021063 0ustar00runnerdocker00000000000000# functions to transform a c class into a dataclass from collections import OrderedDict from textwrap import dedent import operator from . import ExprNodes from . import Nodes from . import PyrexTypes from . import Builtin from . import Naming from .Errors import error, warning from .Code import UtilityCode, TempitaUtilityCode, PyxCodeWriter from .Visitor import VisitorTransform from .StringEncoding import EncodedString from .TreeFragment import TreeFragment from .ParseTreeTransforms import NormalizeTree, SkipDeclarations from .Options import copy_inherited_directives _dataclass_loader_utilitycode = None def make_dataclasses_module_callnode(pos): global _dataclass_loader_utilitycode if not _dataclass_loader_utilitycode: python_utility_code = UtilityCode.load_cached("Dataclasses_fallback", "Dataclasses.py") python_utility_code = EncodedString(python_utility_code.impl) _dataclass_loader_utilitycode = TempitaUtilityCode.load( "SpecificModuleLoader", "Dataclasses.c", context={'cname': "dataclasses", 'py_code': python_utility_code.as_c_string_literal()}) return ExprNodes.PythonCapiCallNode( pos, "__Pyx_Load_dataclasses_Module", PyrexTypes.CFuncType(PyrexTypes.py_object_type, []), utility_code=_dataclass_loader_utilitycode, args=[], ) def make_dataclass_call_helper(pos, callable, kwds): utility_code = UtilityCode.load_cached("DataclassesCallHelper", "Dataclasses.c") func_type = PyrexTypes.CFuncType( PyrexTypes.py_object_type, [ PyrexTypes.CFuncTypeArg("callable", PyrexTypes.py_object_type, None), PyrexTypes.CFuncTypeArg("kwds", PyrexTypes.py_object_type, None) ], ) return ExprNodes.PythonCapiCallNode( pos, function_name="__Pyx_DataclassesCallHelper", func_type=func_type, utility_code=utility_code, args=[callable, kwds], ) class RemoveAssignmentsToNames(VisitorTransform, SkipDeclarations): """ Cython (and Python) normally treats class A: x = 1 as generating a class attribute. However for dataclasses the `= 1` should be interpreted as a default value to initialize an instance attribute with. This transform therefore removes the `x=1` assignment so that the class attribute isn't generated, while recording what it has removed so that it can be used in the initialization. """ def __init__(self, names): super(RemoveAssignmentsToNames, self).__init__() self.names = names self.removed_assignments = {} def visit_CClassNode(self, node): self.visitchildren(node) return node def visit_PyClassNode(self, node): return node # go no further def visit_FuncDefNode(self, node): return node # go no further def visit_SingleAssignmentNode(self, node): if node.lhs.is_name and node.lhs.name in self.names: if node.lhs.name in self.removed_assignments: warning(node.pos, ("Multiple assignments for '%s' in dataclass; " "using most recent") % node.lhs.name, 1) self.removed_assignments[node.lhs.name] = node.rhs return [] return node # I believe cascaded assignment is always a syntax error with annotations # so there's no need to define visit_CascadedAssignmentNode def visit_Node(self, node): self.visitchildren(node) return node class TemplateCode(object): """ Adds the ability to keep track of placeholder argument names to PyxCodeWriter. Also adds extra_stats which are nodes bundled at the end when this is converted to a tree. """ _placeholder_count = 0 def __init__(self, writer=None, placeholders=None, extra_stats=None): self.writer = PyxCodeWriter() if writer is None else writer self.placeholders = {} if placeholders is None else placeholders self.extra_stats = [] if extra_stats is None else extra_stats def add_code_line(self, code_line): self.writer.putln(code_line) def add_code_lines(self, code_lines): for line in code_lines: self.writer.putln(line) def reset(self): # don't attempt to reset placeholders - it really doesn't matter if # we have unused placeholders self.writer.reset() def empty(self): return self.writer.empty() def indenter(self): return self.writer.indenter() def new_placeholder(self, field_names, value): name = self._new_placeholder_name(field_names) self.placeholders[name] = value return name def add_extra_statements(self, statements): if self.extra_stats is None: assert False, "Can only use add_extra_statements on top-level writer" self.extra_stats.extend(statements) def _new_placeholder_name(self, field_names): while True: name = "DATACLASS_PLACEHOLDER_%d" % self._placeholder_count if (name not in self.placeholders and name not in field_names): # make sure name isn't already used and doesn't # conflict with a variable name (which is unlikely but possible) break self._placeholder_count += 1 return name def generate_tree(self, level='c_class'): stat_list_node = TreeFragment( self.writer.getvalue(), level=level, pipeline=[NormalizeTree(None)], ).substitute(self.placeholders) stat_list_node.stats += self.extra_stats return stat_list_node def insertion_point(self): new_writer = self.writer.insertion_point() return TemplateCode( writer=new_writer, placeholders=self.placeholders, extra_stats=self.extra_stats ) class _MISSING_TYPE(object): pass MISSING = _MISSING_TYPE() class Field(object): """ Field is based on the dataclasses.field class from the standard library module. It is used internally during the generation of Cython dataclasses to keep track of the settings for individual attributes. Attributes of this class are stored as nodes so they can be used in code construction more readily (i.e. we store BoolNode rather than bool) """ default = MISSING default_factory = MISSING private = False literal_keys = ("repr", "hash", "init", "compare", "metadata") # default values are defined by the CPython dataclasses.field def __init__(self, pos, default=MISSING, default_factory=MISSING, repr=None, hash=None, init=None, compare=None, metadata=None, is_initvar=False, is_classvar=False, **additional_kwds): if default is not MISSING: self.default = default if default_factory is not MISSING: self.default_factory = default_factory self.repr = repr or ExprNodes.BoolNode(pos, value=True) self.hash = hash or ExprNodes.NoneNode(pos) self.init = init or ExprNodes.BoolNode(pos, value=True) self.compare = compare or ExprNodes.BoolNode(pos, value=True) self.metadata = metadata or ExprNodes.NoneNode(pos) self.is_initvar = is_initvar self.is_classvar = is_classvar for k, v in additional_kwds.items(): # There should not be any additional keywords! error(v.pos, "cython.dataclasses.field() got an unexpected keyword argument '%s'" % k) for field_name in self.literal_keys: field_value = getattr(self, field_name) if not field_value.is_literal: error(field_value.pos, "cython.dataclasses.field parameter '%s' must be a literal value" % field_name) def iterate_record_node_arguments(self): for key in (self.literal_keys + ('default', 'default_factory')): value = getattr(self, key) if value is not MISSING: yield key, value def process_class_get_fields(node): var_entries = node.scope.var_entries # order of definition is used in the dataclass var_entries = sorted(var_entries, key=operator.attrgetter('pos')) var_names = [entry.name for entry in var_entries] # don't treat `x = 1` as an assignment of a class attribute within the dataclass transform = RemoveAssignmentsToNames(var_names) transform(node) default_value_assignments = transform.removed_assignments base_type = node.base_type fields = OrderedDict() while base_type: if base_type.is_external or not base_type.scope.implemented: warning(node.pos, "Cannot reliably handle Cython dataclasses with base types " "in external modules since it is not possible to tell what fields they have", 2) if base_type.dataclass_fields: fields = base_type.dataclass_fields.copy() break base_type = base_type.base_type for entry in var_entries: name = entry.name is_initvar = entry.declared_with_pytyping_modifier("dataclasses.InitVar") # TODO - classvars aren't included in "var_entries" so are missed here # and thus this code is never triggered is_classvar = entry.declared_with_pytyping_modifier("typing.ClassVar") if name in default_value_assignments: assignment = default_value_assignments[name] if (isinstance(assignment, ExprNodes.CallNode) and ( assignment.function.as_cython_attribute() == "dataclasses.field" or Builtin.exprnode_to_known_standard_library_name( assignment.function, node.scope) == "dataclasses.field")): # I believe most of this is well-enforced when it's treated as a directive # but it doesn't hurt to make sure valid_general_call = (isinstance(assignment, ExprNodes.GeneralCallNode) and isinstance(assignment.positional_args, ExprNodes.TupleNode) and not assignment.positional_args.args and (assignment.keyword_args is None or isinstance(assignment.keyword_args, ExprNodes.DictNode))) valid_simple_call = (isinstance(assignment, ExprNodes.SimpleCallNode) and not assignment.args) if not (valid_general_call or valid_simple_call): error(assignment.pos, "Call to 'cython.dataclasses.field' must only consist " "of compile-time keyword arguments") continue keyword_args = assignment.keyword_args.as_python_dict() if valid_general_call and assignment.keyword_args else {} if 'default' in keyword_args and 'default_factory' in keyword_args: error(assignment.pos, "cannot specify both default and default_factory") continue field = Field(node.pos, **keyword_args) else: if assignment.type in [Builtin.list_type, Builtin.dict_type, Builtin.set_type]: # The standard library module generates a TypeError at runtime # in this situation. # Error message is copied from CPython error(assignment.pos, "mutable default for field {1} is not allowed: " "use default_factory".format(assignment.type.name, name)) field = Field(node.pos, default=assignment) else: field = Field(node.pos) field.is_initvar = is_initvar field.is_classvar = is_classvar if entry.visibility == "private": field.private = True fields[name] = field node.entry.type.dataclass_fields = fields return fields def handle_cclass_dataclass(node, dataclass_args, analyse_decs_transform): # default argument values from https://docs.python.org/3/library/dataclasses.html kwargs = dict(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, kw_only=False) if dataclass_args is not None: if dataclass_args[0]: error(node.pos, "cython.dataclasses.dataclass takes no positional arguments") for k, v in dataclass_args[1].items(): if k not in kwargs: error(node.pos, "cython.dataclasses.dataclass() got an unexpected keyword argument '%s'" % k) if not isinstance(v, ExprNodes.BoolNode): error(node.pos, "Arguments passed to cython.dataclasses.dataclass must be True or False") kwargs[k] = v.value kw_only = kwargs['kw_only'] fields = process_class_get_fields(node) dataclass_module = make_dataclasses_module_callnode(node.pos) # create __dataclass_params__ attribute. I try to use the exact # `_DataclassParams` class defined in the standard library module if at all possible # for maximum duck-typing compatibility. dataclass_params_func = ExprNodes.AttributeNode(node.pos, obj=dataclass_module, attribute=EncodedString("_DataclassParams")) dataclass_params_keywords = ExprNodes.DictNode.from_pairs( node.pos, [ (ExprNodes.IdentifierStringNode(node.pos, value=EncodedString(k)), ExprNodes.BoolNode(node.pos, value=v)) for k, v in kwargs.items() ] + [ (ExprNodes.IdentifierStringNode(node.pos, value=EncodedString(k)), ExprNodes.BoolNode(node.pos, value=v)) for k, v in [('kw_only', kw_only), ('match_args', False), ('slots', False), ('weakref_slot', False)] ]) dataclass_params = make_dataclass_call_helper( node.pos, dataclass_params_func, dataclass_params_keywords) dataclass_params_assignment = Nodes.SingleAssignmentNode( node.pos, lhs = ExprNodes.NameNode(node.pos, name=EncodedString("__dataclass_params__")), rhs = dataclass_params) dataclass_fields_stats = _set_up_dataclass_fields(node, fields, dataclass_module) stats = Nodes.StatListNode(node.pos, stats=[dataclass_params_assignment] + dataclass_fields_stats) code = TemplateCode() generate_init_code(code, kwargs['init'], node, fields, kw_only) generate_repr_code(code, kwargs['repr'], node, fields) generate_eq_code(code, kwargs['eq'], node, fields) generate_order_code(code, kwargs['order'], node, fields) generate_hash_code(code, kwargs['unsafe_hash'], kwargs['eq'], kwargs['frozen'], node, fields) stats.stats += code.generate_tree().stats # turn off annotation typing, so all arguments to __init__ are accepted as # generic objects and thus can accept _HAS_DEFAULT_FACTORY. # Type conversion comes later comp_directives = Nodes.CompilerDirectivesNode(node.pos, directives=copy_inherited_directives(node.scope.directives, annotation_typing=False), body=stats) comp_directives.analyse_declarations(node.scope) # probably already in this scope, but it doesn't hurt to make sure analyse_decs_transform.enter_scope(node, node.scope) analyse_decs_transform.visit(comp_directives) analyse_decs_transform.exit_scope() node.body.stats.append(comp_directives) def generate_init_code(code, init, node, fields, kw_only): """ Notes on CPython generated "__init__": * Implemented in `_init_fn`. * The use of the `dataclasses._HAS_DEFAULT_FACTORY` sentinel value as the default argument for fields that need constructing with a factory function is copied from the CPython implementation. (`None` isn't suitable because it could also be a value for the user to pass.) There's no real reason why it needs importing from the dataclasses module though - it could equally be a value generated by Cython when the module loads. * seen_default and the associated error message are copied directly from Python * Call to user-defined __post_init__ function (if it exists) is copied from CPython. Cython behaviour deviates a little here (to be decided if this is right...) Because the class variable from the assignment does not exist Cython fields will return None (or whatever their type default is) if not initialized while Python dataclasses will fall back to looking up the class variable. """ if not init or node.scope.lookup_here("__init__"): return # selfname behaviour copied from the cpython module selfname = "__dataclass_self__" if "self" in fields else "self" args = [selfname] if kw_only: args.append("*") function_start_point = code.insertion_point() code = code.insertion_point() # create a temp to get _HAS_DEFAULT_FACTORY dataclass_module = make_dataclasses_module_callnode(node.pos) has_default_factory = ExprNodes.AttributeNode( node.pos, obj=dataclass_module, attribute=EncodedString("_HAS_DEFAULT_FACTORY") ) default_factory_placeholder = code.new_placeholder(fields, has_default_factory) seen_default = False for name, field in fields.items(): entry = node.scope.lookup(name) if entry.annotation: annotation = u": %s" % entry.annotation.string.value else: annotation = u"" assignment = u'' if field.default is not MISSING or field.default_factory is not MISSING: seen_default = True if field.default_factory is not MISSING: ph_name = default_factory_placeholder else: ph_name = code.new_placeholder(fields, field.default) # 'default' should be a node assignment = u" = %s" % ph_name elif seen_default and not kw_only and field.init.value: error(entry.pos, ("non-default argument '%s' follows default argument " "in dataclass __init__") % name) code.reset() return if field.init.value: args.append(u"%s%s%s" % (name, annotation, assignment)) if field.is_initvar: continue elif field.default_factory is MISSING: if field.init.value: code.add_code_line(u" %s.%s = %s" % (selfname, name, name)) elif assignment: # not an argument to the function, but is still initialized code.add_code_line(u" %s.%s%s" % (selfname, name, assignment)) else: ph_name = code.new_placeholder(fields, field.default_factory) if field.init.value: # close to: # def __init__(self, name=_PLACEHOLDER_VALUE): # self.name = name_default_factory() if name is _PLACEHOLDER_VALUE else name code.add_code_line(u" %s.%s = %s() if %s is %s else %s" % ( selfname, name, ph_name, name, default_factory_placeholder, name)) else: # still need to use the default factory to initialize code.add_code_line(u" %s.%s = %s()" % ( selfname, name, ph_name)) if node.scope.lookup("__post_init__"): post_init_vars = ", ".join(name for name, field in fields.items() if field.is_initvar) code.add_code_line(" %s.__post_init__(%s)" % (selfname, post_init_vars)) if code.empty(): code.add_code_line(" pass") args = u", ".join(args) function_start_point.add_code_line(u"def __init__(%s):" % args) def generate_repr_code(code, repr, node, fields): """ The core of the CPython implementation is just: ['return self.__class__.__qualname__ + f"(' + ', '.join([f"{f.name}={{self.{f.name}!r}}" for f in fields]) + ')"'], The only notable difference here is self.__class__.__qualname__ -> type(self).__name__ which is because Cython currently supports Python 2. However, it also has some guards for recursive repr invocations. In the standard library implementation they're done with a wrapper decorator that captures a set (with the set keyed by id and thread). Here we create a set as a thread local variable and key only by id. """ if not repr or node.scope.lookup("__repr__"): return # The recursive guard is likely a little costly, so skip it if possible. # is_gc_simple defines where it can contain recursive objects needs_recursive_guard = False for name in fields.keys(): entry = node.scope.lookup(name) type_ = entry.type if type_.is_memoryviewslice: type_ = type_.dtype if not type_.is_pyobject: continue # no GC if not type_.is_gc_simple: needs_recursive_guard = True break if needs_recursive_guard: code.add_code_line("__pyx_recursive_repr_guard = __import__('threading').local()") code.add_code_line("__pyx_recursive_repr_guard.running = set()") code.add_code_line("def __repr__(self):") if needs_recursive_guard: code.add_code_line(" key = id(self)") code.add_code_line(" guard_set = self.__pyx_recursive_repr_guard.running") code.add_code_line(" if key in guard_set: return '...'") code.add_code_line(" guard_set.add(key)") code.add_code_line(" try:") strs = [u"%s={self.%s!r}" % (name, name) for name, field in fields.items() if field.repr.value and not field.is_initvar] format_string = u", ".join(strs) code.add_code_line(u' name = getattr(type(self), "__qualname__", type(self).__name__)') code.add_code_line(u" return f'{name}(%s)'" % format_string) if needs_recursive_guard: code.add_code_line(" finally:") code.add_code_line(" guard_set.remove(key)") def generate_cmp_code(code, op, funcname, node, fields): if node.scope.lookup_here(funcname): return names = [name for name, field in fields.items() if (field.compare.value and not field.is_initvar)] code.add_code_lines([ "def %s(self, other):" % funcname, " if other.__class__ is not self.__class__:" " return NotImplemented", # " cdef %s other_cast" % node.class_name, " other_cast = <%s>other" % node.class_name, ]) # The Python implementation of dataclasses.py does a tuple comparison # (roughly): # return self._attributes_to_tuple() {op} other._attributes_to_tuple() # # For the Cython implementation a tuple comparison isn't an option because # not all attributes can be converted to Python objects and stored in a tuple # # TODO - better diagnostics of whether the types support comparison before # generating the code. Plus, do we want to convert C structs to dicts and # compare them that way (I think not, but it might be in demand)? checks = [] op_without_equals = op.replace('=', '') for name in names: if op != '==': # tuple comparison rules - early elements take precedence code.add_code_line(" if self.%s %s other_cast.%s: return True" % ( name, op_without_equals, name)) code.add_code_line(" if self.%s != other_cast.%s: return False" % ( name, name)) if "=" in op: code.add_code_line(" return True") # "() == ()" is True else: code.add_code_line(" return False") def generate_eq_code(code, eq, node, fields): if not eq: return generate_cmp_code(code, "==", "__eq__", node, fields) def generate_order_code(code, order, node, fields): if not order: return for op, name in [("<", "__lt__"), ("<=", "__le__"), (">", "__gt__"), (">=", "__ge__")]: generate_cmp_code(code, op, name, node, fields) def generate_hash_code(code, unsafe_hash, eq, frozen, node, fields): """ Copied from CPython implementation - the intention is to follow this as far as is possible: # +------------------- unsafe_hash= parameter # | +----------- eq= parameter # | | +--- frozen= parameter # | | | # v v v | | | # | no | yes | <--- class has explicitly defined __hash__ # +=======+=======+=======+========+========+ # | False | False | False | | | No __eq__, use the base class __hash__ # +-------+-------+-------+--------+--------+ # | False | False | True | | | No __eq__, use the base class __hash__ # +-------+-------+-------+--------+--------+ # | False | True | False | None | | <-- the default, not hashable # +-------+-------+-------+--------+--------+ # | False | True | True | add | | Frozen, so hashable, allows override # +-------+-------+-------+--------+--------+ # | True | False | False | add | raise | Has no __eq__, but hashable # +-------+-------+-------+--------+--------+ # | True | False | True | add | raise | Has no __eq__, but hashable # +-------+-------+-------+--------+--------+ # | True | True | False | add | raise | Not frozen, but hashable # +-------+-------+-------+--------+--------+ # | True | True | True | add | raise | Frozen, so hashable # +=======+=======+=======+========+========+ # For boxes that are blank, __hash__ is untouched and therefore # inherited from the base class. If the base is object, then # id-based hashing is used. The Python implementation creates a tuple of all the fields, then hashes them. This implementation creates a tuple of all the hashes of all the fields and hashes that. The reason for this slight difference is to avoid to-Python conversions for anything that Cython knows how to hash directly (It doesn't look like this currently applies to anything though...). """ hash_entry = node.scope.lookup_here("__hash__") if hash_entry: # TODO ideally assignment of __hash__ to None shouldn't trigger this # but difficult to get the right information here if unsafe_hash: # error message taken from CPython dataclasses module error(node.pos, "Cannot overwrite attribute __hash__ in class %s" % node.class_name) return if not unsafe_hash: if not eq: return if not frozen: code.add_extra_statements([ Nodes.SingleAssignmentNode( node.pos, lhs=ExprNodes.NameNode(node.pos, name=EncodedString("__hash__")), rhs=ExprNodes.NoneNode(node.pos), ) ]) return names = [ name for name, field in fields.items() if not field.is_initvar and ( field.compare.value if field.hash.value is None else field.hash.value) ] # make a tuple of the hashes hash_tuple_items = u", ".join(u"self.%s" % name for name in names) if hash_tuple_items: hash_tuple_items += u"," # ensure that one arg form is a tuple # if we're here we want to generate a hash code.add_code_lines([ "def __hash__(self):", " return hash((%s))" % hash_tuple_items, ]) def get_field_type(pos, entry): """ sets the .type attribute for a field Returns the annotation if possible (since this is what the dataclasses module does). If not (for example, attributes defined with cdef) then it creates a string fallback. """ if entry.annotation: # Right now it doesn't look like cdef classes generate an # __annotations__ dict, therefore it's safe to just return # entry.annotation # (TODO: remove .string if we ditch PEP563) return entry.annotation.string # If they do in future then we may need to look up into that # to duplicating the node. The code below should do this: #class_name_node = ExprNodes.NameNode(pos, name=entry.scope.name) #annotations = ExprNodes.AttributeNode( # pos, obj=class_name_node, # attribute=EncodedString("__annotations__") #) #return ExprNodes.IndexNode( # pos, base=annotations, # index=ExprNodes.StringNode(pos, value=entry.name) #) else: # it's slightly unclear what the best option is here - we could # try to return PyType_Type. This case should only happen with # attributes defined with cdef so Cython is free to make it's own # decision s = EncodedString(entry.type.declaration_code("", for_display=1)) return ExprNodes.StringNode(pos, value=s) class FieldRecordNode(ExprNodes.ExprNode): """ __dataclass_fields__ contains a bunch of field objects recording how each field of the dataclass was initialized (mainly corresponding to the arguments passed to the "field" function). This node is used for the attributes of these field objects. If possible, coerces `arg` to a Python object. Otherwise, generates a sensible backup string. """ subexprs = ['arg'] def __init__(self, pos, arg): super(FieldRecordNode, self).__init__(pos, arg=arg) def analyse_types(self, env): self.arg.analyse_types(env) self.type = self.arg.type return self def coerce_to_pyobject(self, env): if self.arg.type.can_coerce_to_pyobject(env): return self.arg.coerce_to_pyobject(env) else: # A string representation of the code that gave the field seems like a reasonable # fallback. This'll mostly happen for "default" and "default_factory" where the # type may be a C-type that can't be converted to Python. return self._make_string() def _make_string(self): from .AutoDocTransforms import AnnotationWriter writer = AnnotationWriter(description="Dataclass field") string = writer.write(self.arg) return ExprNodes.StringNode(self.pos, value=EncodedString(string)) def generate_evaluation_code(self, code): return self.arg.generate_evaluation_code(code) def _set_up_dataclass_fields(node, fields, dataclass_module): # For defaults and default_factories containing things like lambda, # they're already declared in the class scope, and it creates a big # problem if multiple copies are floating around in both the __init__ # function, and in the __dataclass_fields__ structure. # Therefore, create module-level constants holding these values and # pass those around instead # # If possible we use the `Field` class defined in the standard library # module so that the information stored here is as close to a regular # dataclass as is possible. variables_assignment_stats = [] for name, field in fields.items(): if field.private: continue # doesn't appear in the public interface for attrname in [ "default", "default_factory" ]: field_default = getattr(field, attrname) if field_default is MISSING or field_default.is_literal or field_default.is_name: # some simple cases where we don't need to set up # the variable as a module-level constant continue global_scope = node.scope.global_scope() module_field_name = global_scope.mangle( global_scope.mangle(Naming.dataclass_field_default_cname, node.class_name), name) # create an entry in the global scope for this variable to live field_node = ExprNodes.NameNode(field_default.pos, name=EncodedString(module_field_name)) field_node.entry = global_scope.declare_var( field_node.name, type=field_default.type or PyrexTypes.unspecified_type, pos=field_default.pos, cname=field_node.name, is_cdef=True, # TODO: do we need to set 'pytyping_modifiers' here? ) # replace the field so that future users just receive the namenode setattr(field, attrname, field_node) variables_assignment_stats.append( Nodes.SingleAssignmentNode(field_default.pos, lhs=field_node, rhs=field_default)) placeholders = {} field_func = ExprNodes.AttributeNode(node.pos, obj=dataclass_module, attribute=EncodedString("field")) dc_fields = ExprNodes.DictNode(node.pos, key_value_pairs=[]) dc_fields_namevalue_assignments = [] for name, field in fields.items(): if field.private: continue # doesn't appear in the public interface type_placeholder_name = "PLACEHOLDER_%s" % name placeholders[type_placeholder_name] = get_field_type( node.pos, node.scope.entries[name] ) # defining these make the fields introspect more like a Python dataclass field_type_placeholder_name = "PLACEHOLDER_FIELD_TYPE_%s" % name if field.is_initvar: placeholders[field_type_placeholder_name] = ExprNodes.AttributeNode( node.pos, obj=dataclass_module, attribute=EncodedString("_FIELD_INITVAR") ) elif field.is_classvar: # TODO - currently this isn't triggered placeholders[field_type_placeholder_name] = ExprNodes.AttributeNode( node.pos, obj=dataclass_module, attribute=EncodedString("_FIELD_CLASSVAR") ) else: placeholders[field_type_placeholder_name] = ExprNodes.AttributeNode( node.pos, obj=dataclass_module, attribute=EncodedString("_FIELD") ) dc_field_keywords = ExprNodes.DictNode.from_pairs( node.pos, [(ExprNodes.IdentifierStringNode(node.pos, value=EncodedString(k)), FieldRecordNode(node.pos, arg=v)) for k, v in field.iterate_record_node_arguments()] ) dc_field_call = make_dataclass_call_helper( node.pos, field_func, dc_field_keywords ) dc_fields.key_value_pairs.append( ExprNodes.DictItemNode( node.pos, key=ExprNodes.IdentifierStringNode(node.pos, value=EncodedString(name)), value=dc_field_call)) dc_fields_namevalue_assignments.append( dedent(u"""\ __dataclass_fields__[{0!r}].name = {0!r} __dataclass_fields__[{0!r}].type = {1} __dataclass_fields__[{0!r}]._field_type = {2} """).format(name, type_placeholder_name, field_type_placeholder_name)) dataclass_fields_assignment = \ Nodes.SingleAssignmentNode(node.pos, lhs = ExprNodes.NameNode(node.pos, name=EncodedString("__dataclass_fields__")), rhs = dc_fields) dc_fields_namevalue_assignments = u"\n".join(dc_fields_namevalue_assignments) dc_fields_namevalue_assignments = TreeFragment(dc_fields_namevalue_assignments, level="c_class", pipeline=[NormalizeTree(None)]) dc_fields_namevalue_assignments = dc_fields_namevalue_assignments.substitute(placeholders) return (variables_assignment_stats + [dataclass_fields_assignment] + dc_fields_namevalue_assignments.stats) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Compiler/DebugFlags.py0000644000175100001770000000115700000000000021173 0ustar00runnerdocker00000000000000# Can be enabled at the command line with --debug-xxx. debug_disposal_code = 0 debug_temp_alloc = 0 debug_coercion = 0 # Write comments into the C code that show where temporary variables # are allocated and released. debug_temp_code_comments = 0 # Write a call trace of the code generation phase into the C code. debug_trace_code_generation = 0 # Do not replace exceptions with user-friendly error messages. debug_no_exception_intercept = 0 # Print a message each time a new stage in the pipeline is entered. debug_verbose_pipeline = 0 # Raise an exception when an error is encountered. debug_exception_on_error = 0 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3127222 Cython-3.0.8/Cython/Compiler/Errors.py0000644000175100001770000002214000000000000020437 0ustar00runnerdocker00000000000000# # Errors # from __future__ import absolute_import try: from __builtin__ import basestring as any_string_type except ImportError: any_string_type = (bytes, str) import sys from contextlib import contextmanager try: from threading import local as _threadlocal except ImportError: class _threadlocal(object): pass threadlocal = _threadlocal() from ..Utils import open_new_file from . import DebugFlags from . import Options class PyrexError(Exception): pass class PyrexWarning(Exception): pass class CannotSpecialize(PyrexError): pass def context(position): source = position[0] assert not (isinstance(source, any_string_type)), ( "Please replace filename strings with Scanning.FileSourceDescriptor instances %r" % source) try: F = source.get_lines() except UnicodeDecodeError: # file has an encoding problem s = u"[unprintable code]\n" else: s = u''.join(F[max(0, position[1]-6):position[1]]) s = u'...\n%s%s^\n' % (s, u' '*(position[2])) s = u'%s\n%s%s\n' % (u'-'*60, s, u'-'*60) return s def format_position(position): if position: return u"%s:%d:%d: " % (position[0].get_error_description(), position[1], position[2]) return u'' def format_error(message, position): if position: pos_str = format_position(position) cont = context(position) message = u'\nError compiling Cython file:\n%s\n%s%s' % (cont, pos_str, message or u'') return message class CompileError(PyrexError): def __init__(self, position = None, message = u""): self.position = position self.message_only = message self.formatted_message = format_error(message, position) self.reported = False Exception.__init__(self, self.formatted_message) # Python Exception subclass pickling is broken, # see https://bugs.python.org/issue1692335 self.args = (position, message) def __str__(self): return self.formatted_message class CompileWarning(PyrexWarning): def __init__(self, position = None, message = ""): self.position = position Exception.__init__(self, format_position(position) + message) class InternalError(Exception): # If this is ever raised, there is a bug in the compiler. def __init__(self, message): self.message_only = message Exception.__init__(self, u"Internal compiler error: %s" % message) class AbortError(Exception): # Throw this to stop the compilation immediately. def __init__(self, message): self.message_only = message Exception.__init__(self, u"Abort error: %s" % message) class CompilerCrash(CompileError): # raised when an unexpected exception occurs in a transform def __init__(self, pos, context, message, cause, stacktrace=None): if message: message = u'\n' + message else: message = u'\n' self.message_only = message if context: message = u"Compiler crash in %s%s" % (context, message) if stacktrace: import traceback message += ( u'\n\nCompiler crash traceback from this point on:\n' + u''.join(traceback.format_tb(stacktrace))) if cause: if not stacktrace: message += u'\n' message += u'%s: %s' % (cause.__class__.__name__, cause) CompileError.__init__(self, pos, message) # Python Exception subclass pickling is broken, # see https://bugs.python.org/issue1692335 self.args = (pos, context, message, cause, stacktrace) class NoElementTreeInstalledException(PyrexError): """raised when the user enabled options.gdb_debug but no ElementTree implementation was found """ def open_listing_file(path, echo_to_stderr=True): # Begin a new error listing. If path is None, no file # is opened, the error counter is just reset. if path is not None: threadlocal.cython_errors_listing_file = open_new_file(path) else: threadlocal.cython_errors_listing_file = None if echo_to_stderr: threadlocal.cython_errors_echo_file = sys.stderr else: threadlocal.cython_errors_echo_file = None threadlocal.cython_errors_count = 0 def close_listing_file(): if threadlocal.cython_errors_listing_file: threadlocal.cython_errors_listing_file.close() threadlocal.cython_errors_listing_file = None def report_error(err, use_stack=True): error_stack = threadlocal.cython_errors_stack if error_stack and use_stack: error_stack[-1].append(err) else: # See Main.py for why dual reporting occurs. Quick fix for now. if err.reported: return err.reported = True try: line = u"%s\n" % err except UnicodeEncodeError: # Python <= 2.5 does this for non-ASCII Unicode exceptions line = format_error(getattr(err, 'message_only', "[unprintable exception message]"), getattr(err, 'position', None)) + u'\n' listing_file = threadlocal.cython_errors_listing_file if listing_file: try: listing_file.write(line) except UnicodeEncodeError: listing_file.write(line.encode('ASCII', 'replace')) echo_file = threadlocal.cython_errors_echo_file if echo_file: try: echo_file.write(line) except UnicodeEncodeError: echo_file.write(line.encode('ASCII', 'replace')) threadlocal.cython_errors_count += 1 if Options.fast_fail: raise AbortError("fatal errors") def error(position, message): #print("Errors.error:", repr(position), repr(message)) ### if position is None: raise InternalError(message) err = CompileError(position, message) if DebugFlags.debug_exception_on_error: raise Exception(err) # debug report_error(err) return err LEVEL = 1 # warn about all errors level 1 or higher def _write_file_encode(file, line): try: file.write(line) except UnicodeEncodeError: file.write(line.encode('ascii', 'replace')) def performance_hint(position, message, env): if not env.directives['show_performance_hints']: return warn = CompileWarning(position, message) line = "performance hint: %s\n" % warn listing_file = threadlocal.cython_errors_listing_file if listing_file: _write_file_encode(listing_file, line) echo_file = threadlocal.cython_errors_echo_file if echo_file: _write_file_encode(echo_file, line) return warn def message(position, message, level=1): if level < LEVEL: return warn = CompileWarning(position, message) line = u"note: %s\n" % warn listing_file = threadlocal.cython_errors_listing_file if listing_file: _write_file_encode(listing_file, line) echo_file = threadlocal.cython_errors_echo_file if echo_file: _write_file_encode(echo_file, line) return warn def warning(position, message, level=0): if level < LEVEL: return if Options.warning_errors and position: return error(position, message) warn = CompileWarning(position, message) line = u"warning: %s\n" % warn listing_file = threadlocal.cython_errors_listing_file if listing_file: _write_file_encode(listing_file, line) echo_file = threadlocal.cython_errors_echo_file if echo_file: _write_file_encode(echo_file, line) return warn def warn_once(position, message, level=0): if level < LEVEL: return warn_once_seen = threadlocal.cython_errors_warn_once_seen if message in warn_once_seen: return warn = CompileWarning(position, message) line = u"warning: %s\n" % warn listing_file = threadlocal.cython_errors_listing_file if listing_file: _write_file_encode(listing_file, line) echo_file = threadlocal.cython_errors_echo_file if echo_file: _write_file_encode(echo_file, line) warn_once_seen.add(message) return warn # These functions can be used to momentarily suppress errors. def hold_errors(): errors = [] threadlocal.cython_errors_stack.append(errors) return errors def release_errors(ignore=False): held_errors = threadlocal.cython_errors_stack.pop() if not ignore: for err in held_errors: report_error(err) def held_errors(): return threadlocal.cython_errors_stack[-1] # same as context manager: @contextmanager def local_errors(ignore=False): errors = hold_errors() try: yield errors finally: release_errors(ignore=ignore) # Keep all global state in thread local storage to support parallel cythonisation in distutils. def init_thread(): threadlocal.cython_errors_count = 0 threadlocal.cython_errors_listing_file = None threadlocal.cython_errors_echo_file = None threadlocal.cython_errors_warn_once_seen = set() threadlocal.cython_errors_stack = [] def reset(): threadlocal.cython_errors_warn_once_seen.clear() del threadlocal.cython_errors_stack[:] def get_errors_count(): return threadlocal.cython_errors_count ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3167222 Cython-3.0.8/Cython/Compiler/ExprNodes.py0000644000175100001770000222603000000000000021100 0ustar00runnerdocker00000000000000# # Parse tree nodes for expressions # from __future__ import absolute_import import cython cython.declare(error=object, warning=object, warn_once=object, InternalError=object, CompileError=object, UtilityCode=object, TempitaUtilityCode=object, StringEncoding=object, operator=object, local_errors=object, report_error=object, Naming=object, Nodes=object, PyrexTypes=object, py_object_type=object, list_type=object, tuple_type=object, set_type=object, dict_type=object, unicode_type=object, str_type=object, bytes_type=object, type_type=object, Builtin=object, Symtab=object, Utils=object, find_coercion_error=object, debug_disposal_code=object, debug_temp_alloc=object, debug_coercion=object, bytearray_type=object, slice_type=object, memoryview_type=object, builtin_sequence_types=object, _py_int_types=object, IS_PYTHON3=cython.bint) import re import sys import copy import os.path import operator from .Errors import ( error, warning, InternalError, CompileError, report_error, local_errors, CannotSpecialize, performance_hint) from .Code import UtilityCode, TempitaUtilityCode from . import StringEncoding from . import Naming from . import Nodes from .Nodes import Node, utility_code_for_imports, SingleAssignmentNode from . import PyrexTypes from .PyrexTypes import py_object_type, typecast, error_type, \ unspecified_type from . import TypeSlots from .Builtin import ( list_type, tuple_type, set_type, dict_type, type_type, unicode_type, str_type, bytes_type, bytearray_type, basestring_type, slice_type, long_type, sequence_types as builtin_sequence_types, memoryview_type, ) from . import Builtin from . import Symtab from .. import Utils from .Annotate import AnnotationItem from . import Future from ..Debugging import print_call_chain from .DebugFlags import debug_disposal_code, debug_coercion from .Pythran import (to_pythran, is_pythran_supported_type, is_pythran_supported_operation_type, is_pythran_expr, pythran_func_type, pythran_binop_type, pythran_unaryop_type, has_np_pythran, pythran_indexing_code, pythran_indexing_type, is_pythran_supported_node_or_none, pythran_type, pythran_is_numpy_func_supported, pythran_get_func_include_file, pythran_functor) from .PyrexTypes import PythranExpr try: from __builtin__ import basestring except ImportError: # Python 3 basestring = str any_string_type = (bytes, str) else: # Python 2 any_string_type = (bytes, unicode) if sys.version_info[0] >= 3: IS_PYTHON3 = True _py_int_types = int else: IS_PYTHON3 = False _py_int_types = (int, long) class NotConstant(object): _obj = None def __new__(cls): if NotConstant._obj is None: NotConstant._obj = super(NotConstant, cls).__new__(cls) return NotConstant._obj def __repr__(self): return "" not_a_constant = NotConstant() constant_value_not_set = object() # error messages when coercing from key[0] to key[1] coercion_error_dict = { # string related errors (unicode_type, str_type): ("Cannot convert Unicode string to 'str' implicitly." " This is not portable and requires explicit encoding."), (unicode_type, bytes_type): "Cannot convert Unicode string to 'bytes' implicitly, encoding required.", (unicode_type, PyrexTypes.c_char_ptr_type): "Unicode objects only support coercion to Py_UNICODE*.", (unicode_type, PyrexTypes.c_const_char_ptr_type): "Unicode objects only support coercion to Py_UNICODE*.", (unicode_type, PyrexTypes.c_uchar_ptr_type): "Unicode objects only support coercion to Py_UNICODE*.", (unicode_type, PyrexTypes.c_const_uchar_ptr_type): "Unicode objects only support coercion to Py_UNICODE*.", (bytes_type, unicode_type): "Cannot convert 'bytes' object to unicode implicitly, decoding required", (bytes_type, str_type): "Cannot convert 'bytes' object to str implicitly. This is not portable to Py3.", (bytes_type, basestring_type): ("Cannot convert 'bytes' object to basestring implicitly." " This is not portable to Py3."), (bytes_type, PyrexTypes.c_py_unicode_ptr_type): "Cannot convert 'bytes' object to Py_UNICODE*, use 'unicode'.", (bytes_type, PyrexTypes.c_const_py_unicode_ptr_type): ( "Cannot convert 'bytes' object to Py_UNICODE*, use 'unicode'."), (basestring_type, bytes_type): "Cannot convert 'basestring' object to bytes implicitly. This is not portable.", (str_type, unicode_type): ("str objects do not support coercion to unicode," " use a unicode string literal instead (u'')"), (str_type, bytes_type): "Cannot convert 'str' to 'bytes' implicitly. This is not portable.", (str_type, PyrexTypes.c_char_ptr_type): "'str' objects do not support coercion to C types (use 'bytes'?).", (str_type, PyrexTypes.c_const_char_ptr_type): "'str' objects do not support coercion to C types (use 'bytes'?).", (str_type, PyrexTypes.c_uchar_ptr_type): "'str' objects do not support coercion to C types (use 'bytes'?).", (str_type, PyrexTypes.c_const_uchar_ptr_type): "'str' objects do not support coercion to C types (use 'bytes'?).", (str_type, PyrexTypes.c_py_unicode_ptr_type): "'str' objects do not support coercion to C types (use 'unicode'?).", (str_type, PyrexTypes.c_const_py_unicode_ptr_type): ( "'str' objects do not support coercion to C types (use 'unicode'?)."), (PyrexTypes.c_char_ptr_type, unicode_type): "Cannot convert 'char*' to unicode implicitly, decoding required", (PyrexTypes.c_const_char_ptr_type, unicode_type): ( "Cannot convert 'char*' to unicode implicitly, decoding required"), (PyrexTypes.c_uchar_ptr_type, unicode_type): "Cannot convert 'char*' to unicode implicitly, decoding required", (PyrexTypes.c_const_uchar_ptr_type, unicode_type): ( "Cannot convert 'char*' to unicode implicitly, decoding required"), } def find_coercion_error(type_tuple, default, env): err = coercion_error_dict.get(type_tuple) if err is None: return default elif (env.directives['c_string_encoding'] and any(t in type_tuple for t in (PyrexTypes.c_char_ptr_type, PyrexTypes.c_uchar_ptr_type, PyrexTypes.c_const_char_ptr_type, PyrexTypes.c_const_uchar_ptr_type))): if type_tuple[1].is_pyobject: return default elif env.directives['c_string_encoding'] in ('ascii', 'default'): return default else: return "'%s' objects do not support coercion to C types with non-ascii or non-default c_string_encoding" % type_tuple[0].name else: return err def default_str_type(env): return { 'bytes': bytes_type, 'bytearray': bytearray_type, 'str': str_type, 'unicode': unicode_type }.get(env.directives['c_string_type']) def check_negative_indices(*nodes): """ Raise a warning on nodes that are known to have negative numeric values. Used to find (potential) bugs inside of "wraparound=False" sections. """ for node in nodes: if node is None or ( not isinstance(node.constant_result, _py_int_types) and not isinstance(node.constant_result, float)): continue if node.constant_result < 0: warning(node.pos, "the result of using negative indices inside of " "code sections marked as 'wraparound=False' is " "undefined", level=1) def infer_sequence_item_type(env, seq_node, index_node=None, seq_type=None): if not seq_node.is_sequence_constructor: if seq_type is None: seq_type = seq_node.infer_type(env) if seq_type is tuple_type: # tuples are immutable => we can safely follow assignments if seq_node.cf_state and len(seq_node.cf_state) == 1: try: seq_node = seq_node.cf_state[0].rhs except AttributeError: pass if seq_node is not None and seq_node.is_sequence_constructor: if index_node is not None and index_node.has_constant_result(): try: item = seq_node.args[index_node.constant_result] except (ValueError, TypeError, IndexError): pass else: return item.infer_type(env) # if we're lucky, all items have the same type item_types = {item.infer_type(env) for item in seq_node.args} if len(item_types) == 1: return item_types.pop() return None def make_dedup_key(outer_type, item_nodes): """ Recursively generate a deduplication key from a sequence of values. Includes Cython node types to work around the fact that (1, 2.0) == (1.0, 2), for example. @param outer_type: The type of the outer container. @param item_nodes: A sequence of constant nodes that will be traversed recursively. @return: A tuple that can be used as a dict key for deduplication. """ item_keys = [ (py_object_type, None, type(None)) if node is None # For sequences and their "mult_factor", see TupleNode. else make_dedup_key(node.type, [node.mult_factor if node.is_literal else None] + node.args) if node.is_sequence_constructor else make_dedup_key(node.type, (node.start, node.stop, node.step)) if node.is_slice # For constants, look at the Python value type if we don't know the concrete Cython type. else (node.type, node.constant_result, type(node.constant_result) if node.type is py_object_type else None) if node.has_constant_result() # IdentifierStringNode doesn't usually have a "constant_result" set because: # 1. it doesn't usually have unicode_value # 2. it's often created later in the compilation process after ConstantFolding # but should be cacheable else (node.type, node.value, node.unicode_value, "IdentifierStringNode") if isinstance(node, IdentifierStringNode) else None # something we cannot handle => short-circuit below for node in item_nodes ] if None in item_keys: return None return outer_type, tuple(item_keys) # Returns a block of code to translate the exception, # plus a boolean indicating whether to check for Python exceptions. def get_exception_handler(exception_value): if exception_value is None: return "__Pyx_CppExn2PyErr();", False elif (exception_value.type == PyrexTypes.c_char_type and exception_value.value == '*'): return "__Pyx_CppExn2PyErr();", True elif exception_value.type.is_pyobject: return ( 'try { throw; } catch(const std::exception& exn) {' 'PyErr_SetString(%s, exn.what());' '} catch(...) { PyErr_SetNone(%s); }' % ( exception_value.entry.cname, exception_value.entry.cname), False) else: return ( '%s(); if (!PyErr_Occurred())' 'PyErr_SetString(PyExc_RuntimeError, ' '"Error converting c++ exception.");' % ( exception_value.entry.cname), False) def maybe_check_py_error(code, check_py_exception, pos, nogil): if check_py_exception: if nogil: code.globalstate.use_utility_code( UtilityCode.load_cached("ErrOccurredWithGIL", "Exceptions.c")) code.putln(code.error_goto_if("__Pyx_ErrOccurredWithGIL()", pos)) else: code.putln(code.error_goto_if("PyErr_Occurred()", pos)) def translate_cpp_exception(code, pos, inside, py_result, exception_value, nogil): raise_py_exception, check_py_exception = get_exception_handler(exception_value) code.putln("try {") code.putln("%s" % inside) if py_result: code.putln(code.error_goto_if_null(py_result, pos)) maybe_check_py_error(code, check_py_exception, pos, nogil) code.putln("} catch(...) {") if nogil: code.put_ensure_gil(declare_gilstate=True) code.putln(raise_py_exception) if nogil: code.put_release_ensured_gil() code.putln(code.error_goto(pos)) code.putln("}") def needs_cpp_exception_conversion(node): assert node.exception_check == "+" if node.exception_value is None: return True # exception_value can be a NameNode # (in which case it's used as a handler function and no conversion is needed) if node.exception_value.is_name: return False # or a CharNode with a value of "*" if isinstance(node.exception_value, CharNode) and node.exception_value.value == "*": return True # Most other const-nodes are disallowed after "+" by the parser return False # Used to handle the case where an lvalue expression and an overloaded assignment # both have an exception declaration. def translate_double_cpp_exception(code, pos, lhs_type, lhs_code, rhs_code, lhs_exc_val, assign_exc_val, nogil): handle_lhs_exc, lhc_check_py_exc = get_exception_handler(lhs_exc_val) handle_assignment_exc, assignment_check_py_exc = get_exception_handler(assign_exc_val) code.putln("try {") code.putln(lhs_type.declaration_code("__pyx_local_lvalue = %s;" % lhs_code)) maybe_check_py_error(code, lhc_check_py_exc, pos, nogil) code.putln("try {") code.putln("__pyx_local_lvalue = %s;" % rhs_code) maybe_check_py_error(code, assignment_check_py_exc, pos, nogil) # Catch any exception from the overloaded assignment. code.putln("} catch(...) {") if nogil: code.put_ensure_gil(declare_gilstate=True) code.putln(handle_assignment_exc) if nogil: code.put_release_ensured_gil() code.putln(code.error_goto(pos)) code.putln("}") # Catch any exception from evaluating lhs. code.putln("} catch(...) {") if nogil: code.put_ensure_gil(declare_gilstate=True) code.putln(handle_lhs_exc) if nogil: code.put_release_ensured_gil() code.putln(code.error_goto(pos)) code.putln('}') class ExprNode(Node): # subexprs [string] Class var holding names of subexpr node attrs # type PyrexType Type of the result # result_code string Code fragment # result_ctype string C type of result_code if different from type # is_temp boolean Result is in a temporary variable # is_sequence_constructor # boolean Is a list or tuple constructor expression # is_starred boolean Is a starred expression (e.g. '*a') # use_managed_ref boolean use ref-counted temps/assignments/etc. # result_is_used boolean indicates that the result will be dropped and the # result_code/temp_result can safely be set to None # is_numpy_attribute boolean Is a Numpy module attribute # annotation ExprNode or None PEP526 annotation for names or expressions # generator_arg_tag None or Node A tag to mark ExprNodes that potentially need to # be changed to a generator argument result_ctype = None type = None annotation = None temp_code = None old_temp = None # error checker for multiple frees etc. use_managed_ref = True # can be set by optimisation transforms result_is_used = True is_numpy_attribute = False generator_arg_tag = None # The Analyse Expressions phase for expressions is split # into two sub-phases: # # Analyse Types # Determines the result type of the expression based # on the types of its sub-expressions, and inserts # coercion nodes into the expression tree where needed. # Marks nodes which will need to have temporary variables # allocated. # # Allocate Temps # Allocates temporary variables where needed, and fills # in the result_code field of each node. # # ExprNode provides some convenience routines which # perform both of the above phases. These should only # be called from statement nodes, and only when no # coercion nodes need to be added around the expression # being analysed. In that case, the above two phases # should be invoked separately. # # Framework code in ExprNode provides much of the common # processing for the various phases. It makes use of the # 'subexprs' class attribute of ExprNodes, which should # contain a list of the names of attributes which can # hold sub-nodes or sequences of sub-nodes. # # The framework makes use of a number of abstract methods. # Their responsibilities are as follows. # # Declaration Analysis phase # # analyse_target_declaration # Called during the Analyse Declarations phase to analyse # the LHS of an assignment or argument of a del statement. # Nodes which cannot be the LHS of an assignment need not # implement it. # # Expression Analysis phase # # analyse_types # - Call analyse_types on all sub-expressions. # - Check operand types, and wrap coercion nodes around # sub-expressions where needed. # - Set the type of this node. # - If a temporary variable will be required for the # result, set the is_temp flag of this node. # # analyse_target_types # Called during the Analyse Types phase to analyse # the LHS of an assignment or argument of a del # statement. Similar responsibilities to analyse_types. # # target_code # Called by the default implementation of allocate_target_temps. # Should return a C lvalue for assigning to the node. The default # implementation calls calculate_result_code. # # check_const # - Check that this node and its subnodes form a # legal constant expression. If so, do nothing, # otherwise call not_const. # # The default implementation of check_const # assumes that the expression is not constant. # # check_const_addr # - Same as check_const, except check that the # expression is a C lvalue whose address is # constant. Otherwise, call addr_not_const. # # The default implementation of calc_const_addr # assumes that the expression is not a constant # lvalue. # # Code Generation phase # # generate_evaluation_code # - Call generate_evaluation_code for sub-expressions. # - Perform the functions of generate_result_code # (see below). # - If result is temporary, call generate_disposal_code # on all sub-expressions. # # A default implementation of generate_evaluation_code # is provided which uses the following abstract methods: # # generate_result_code # - Generate any C statements necessary to calculate # the result of this node from the results of its # sub-expressions. # # calculate_result_code # - Should return a C code fragment evaluating to the # result. This is only called when the result is not # a temporary. # # generate_assignment_code # Called on the LHS of an assignment. # - Call generate_evaluation_code for sub-expressions. # - Generate code to perform the assignment. # - If the assignment absorbed a reference, call # generate_post_assignment_code on the RHS, # otherwise call generate_disposal_code on it. # # generate_deletion_code # Called on an argument of a del statement. # - Call generate_evaluation_code for sub-expressions. # - Generate code to perform the deletion. # - Call generate_disposal_code on all sub-expressions. # # is_sequence_constructor = False is_dict_literal = False is_set_literal = False is_string_literal = False is_attribute = False is_subscript = False is_slice = False is_buffer_access = False is_memview_index = False is_memview_slice = False is_memview_broadcast = False is_memview_copy_assignment = False is_temp = False has_temp_moved = False # if True then attempting to do anything but free the temp is invalid is_target = False is_starred = False constant_result = constant_value_not_set child_attrs = property(fget=operator.attrgetter('subexprs')) def analyse_annotations(self, env): pass def not_implemented(self, method_name): print_call_chain(method_name, "not implemented") raise InternalError( "%s.%s not implemented" % (self.__class__.__name__, method_name)) def is_lvalue(self): return 0 def is_addressable(self): return self.is_lvalue() and not self.type.is_memoryviewslice def is_ephemeral(self): # An ephemeral node is one whose result is in # a Python temporary and we suspect there are no # other references to it. Certain operations are # disallowed on such values, since they are # likely to result in a dangling pointer. return self.type.is_pyobject and self.is_temp def subexpr_nodes(self): # Extract a list of subexpression nodes based # on the contents of the subexprs class attribute. nodes = [] for name in self.subexprs: item = getattr(self, name) if item is not None: if type(item) is list: nodes.extend(item) else: nodes.append(item) return nodes def result(self): if self.is_temp: #if not self.temp_code: # pos = (os.path.basename(self.pos[0].get_description()),) + self.pos[1:] if self.pos else '(?)' # raise RuntimeError("temp result name not set in %s at %r" % ( # self.__class__.__name__, pos)) return self.temp_code else: return self.calculate_result_code() def _make_move_result_rhs(self, result, optional=False): if optional and not (self.is_temp and self.type.is_cpp_class and not self.type.is_reference): return result self.has_temp_moved = True return "{}({})".format("__PYX_STD_MOVE_IF_SUPPORTED" if optional else "std::move", result) def move_result_rhs(self): return self._make_move_result_rhs(self.result(), optional=True) def move_result_rhs_as(self, type): result = self.result_as(type) if not (type.is_reference or type.needs_refcounting): requires_move = type.is_rvalue_reference and self.is_temp result = self._make_move_result_rhs(result, optional=not requires_move) return result def pythran_result(self, type_=None): if is_pythran_supported_node_or_none(self): return to_pythran(self) assert type_ is not None return to_pythran(self, type_) def is_c_result_required(self): """ Subtypes may return False here if result temp allocation can be skipped. """ return True def result_as(self, type = None): # Return the result code cast to the specified C type. if (self.is_temp and self.type.is_pyobject and type != py_object_type): # Allocated temporaries are always PyObject *, which may not # reflect the actual type (e.g. an extension type) return typecast(type, py_object_type, self.result()) return typecast(type, self.ctype(), self.result()) def py_result(self): # Return the result code cast to PyObject *. return self.result_as(py_object_type) def ctype(self): # Return the native C type of the result (i.e. the # C type of the result_code expression). return self.result_ctype or self.type def get_constant_c_result_code(self): # Return the constant value of this node as a result code # string, or None if the node is not constant. This method # can be called when the constant result code is required # before the code generation phase. # # The return value is a string that can represent a simple C # value, a constant C name or a constant C expression. If the # node type depends on Python code, this must return None. return None def calculate_constant_result(self): # Calculate the constant compile time result value of this # expression and store it in ``self.constant_result``. Does # nothing by default, thus leaving ``self.constant_result`` # unknown. If valid, the result can be an arbitrary Python # value. # # This must only be called when it is assured that all # sub-expressions have a valid constant_result value. The # ConstantFolding transform will do this. pass def has_constant_result(self): return self.constant_result is not constant_value_not_set and \ self.constant_result is not not_a_constant def compile_time_value(self, denv): # Return value of compile-time expression, or report error. error(self.pos, "Invalid compile-time expression") def compile_time_value_error(self, e): error(self.pos, "Error in compile-time expression: %s: %s" % ( e.__class__.__name__, e)) # ------------- Declaration Analysis ---------------- def analyse_target_declaration(self, env): error(self.pos, "Cannot assign to or delete this") def analyse_assignment_expression_target_declaration(self, env): error(self.pos, "Cannot use anything except a name in an assignment expression") # ------------- Expression Analysis ---------------- def analyse_const_expression(self, env): # Called during the analyse_declarations phase of a # constant expression. Analyses the expression's type, # checks whether it is a legal const expression, # and determines its value. node = self.analyse_types(env) node.check_const() return node def analyse_expressions(self, env): # Convenience routine performing both the Type # Analysis and Temp Allocation phases for a whole # expression. return self.analyse_types(env) def analyse_target_expression(self, env, rhs): # Convenience routine performing both the Type # Analysis and Temp Allocation phases for the LHS of # an assignment. return self.analyse_target_types(env) def analyse_boolean_expression(self, env): # Analyse expression and coerce to a boolean. node = self.analyse_types(env) bool = node.coerce_to_boolean(env) return bool def analyse_temp_boolean_expression(self, env): # Analyse boolean expression and coerce result into # a temporary. This is used when a branch is to be # performed on the result and we won't have an # opportunity to ensure disposal code is executed # afterwards. By forcing the result into a temporary, # we ensure that all disposal has been done by the # time we get the result. node = self.analyse_types(env) return node.coerce_to_boolean(env).coerce_to_simple(env) # --------------- Type Inference ----------------- def type_dependencies(self, env): # Returns the list of entries whose types must be determined # before the type of self can be inferred. if getattr(self, 'type', None) is not None: return () return sum([node.type_dependencies(env) for node in self.subexpr_nodes()], ()) def infer_type(self, env): # Attempt to deduce the type of self. # Differs from analyse_types as it avoids unnecessary # analysis of subexpressions, but can assume everything # in self.type_dependencies() has been resolved. type = getattr(self, 'type', None) if type is not None: return type entry = getattr(self, 'entry', None) if entry is not None: return entry.type self.not_implemented("infer_type") def nonlocally_immutable(self): # Returns whether this variable is a safe reference, i.e. # can't be modified as part of globals or closures. return self.is_literal or self.is_temp or self.type.is_array or self.type.is_cfunction def inferable_item_node(self, index=0): """ Return a node that represents the (type) result of an indexing operation, e.g. for tuple unpacking or iteration. """ return IndexNode(self.pos, base=self, index=IntNode( self.pos, value=str(index), constant_result=index, type=PyrexTypes.c_py_ssize_t_type)) # --------------- Type Analysis ------------------ def analyse_as_module(self, env): # If this node can be interpreted as a reference to a # cimported module, return its scope, else None. return None def analyse_as_type(self, env): # If this node can be interpreted as a reference to a # type, return that type, else None. return None def analyse_as_specialized_type(self, env): type = self.analyse_as_type(env) if type and type.is_fused and env.fused_to_specific: # while it would be nice to test "if entry.type in env.fused_to_specific" # rather than try/catch this doesn't work reliably (mainly for nested fused types) try: return type.specialize(env.fused_to_specific) except KeyError: pass if type and type.is_fused: error(self.pos, "Type is not specific") return type def analyse_as_extension_type(self, env): # If this node can be interpreted as a reference to an # extension type or builtin type, return its type, else None. return None def analyse_types(self, env): self.not_implemented("analyse_types") def analyse_target_types(self, env): return self.analyse_types(env) def nogil_check(self, env): # By default, any expression based on Python objects is # prevented in nogil environments. Subtypes must override # this if they can work without the GIL. if self.type and self.type.is_pyobject: self.gil_error() def gil_assignment_check(self, env): if env.nogil and self.type.is_pyobject: error(self.pos, "Assignment of Python object not allowed without gil") def check_const(self): self.not_const() return False def not_const(self): error(self.pos, "Not allowed in a constant expression") def check_const_addr(self): self.addr_not_const() return False def addr_not_const(self): error(self.pos, "Address is not constant") # ----------------- Result Allocation ----------------- def result_in_temp(self): # Return true if result is in a temporary owned by # this node or one of its subexpressions. Overridden # by certain nodes which can share the result of # a subnode. return self.is_temp def target_code(self): # Return code fragment for use as LHS of a C assignment. return self.calculate_result_code() def calculate_result_code(self): self.not_implemented("calculate_result_code") # def release_target_temp(self, env): # # Release temporaries used by LHS of an assignment. # self.release_subexpr_temps(env) def allocate_temp_result(self, code): if self.temp_code: raise RuntimeError("Temp allocated multiple times in %r: %r" % (self.__class__.__name__, self.pos)) type = self.type if not type.is_void: if type.is_pyobject: type = PyrexTypes.py_object_type elif not (self.result_is_used or type.is_memoryviewslice or self.is_c_result_required()): self.temp_code = None return self.temp_code = code.funcstate.allocate_temp( type, manage_ref=self.use_managed_ref) else: self.temp_code = None def release_temp_result(self, code): if not self.temp_code: if not self.result_is_used: # not used anyway, so ignore if not set up return pos = (os.path.basename(self.pos[0].get_description()),) + self.pos[1:] if self.pos else '(?)' if self.old_temp: raise RuntimeError("temp %s released multiple times in %s at %r" % ( self.old_temp, self.__class__.__name__, pos)) else: raise RuntimeError("no temp, but release requested in %s at %r" % ( self.__class__.__name__, pos)) code.funcstate.release_temp(self.temp_code) self.old_temp = self.temp_code self.temp_code = None # ---------------- Code Generation ----------------- def make_owned_reference(self, code): """ Make sure we own a reference to result. If the result is in a temp, it is already a new reference. """ if not self.result_in_temp(): code.put_incref(self.result(), self.ctype()) def make_owned_memoryviewslice(self, code): """ Make sure we own the reference to this memoryview slice. """ # TODO ideally this would be shared with "make_owned_reference" if not self.result_in_temp(): code.put_incref_memoryviewslice(self.result(), self.type, have_gil=not self.in_nogil_context) def generate_evaluation_code(self, code): # Generate code to evaluate this node and # its sub-expressions, and dispose of any # temporary results of its sub-expressions. self.generate_subexpr_evaluation_code(code) code.mark_pos(self.pos) if self.is_temp: self.allocate_temp_result(code) self.generate_result_code(code) if self.is_temp and not (self.type.is_string or self.type.is_pyunicode_ptr): # If we are temp we do not need to wait until this node is disposed # before disposing children. self.generate_subexpr_disposal_code(code) self.free_subexpr_temps(code) def generate_subexpr_evaluation_code(self, code): for node in self.subexpr_nodes(): node.generate_evaluation_code(code) def generate_result_code(self, code): self.not_implemented("generate_result_code") def generate_disposal_code(self, code): if self.has_temp_moved: code.globalstate.use_utility_code( UtilityCode.load_cached("MoveIfSupported", "CppSupport.cpp")) if self.is_temp: if self.type.is_string or self.type.is_pyunicode_ptr: # postponed from self.generate_evaluation_code() self.generate_subexpr_disposal_code(code) self.free_subexpr_temps(code) if self.result(): code.put_decref_clear(self.result(), self.ctype(), have_gil=not self.in_nogil_context) else: # Already done if self.is_temp self.generate_subexpr_disposal_code(code) def generate_subexpr_disposal_code(self, code): # Generate code to dispose of temporary results # of all sub-expressions. for node in self.subexpr_nodes(): node.generate_disposal_code(code) def generate_post_assignment_code(self, code): if self.is_temp: if self.type.is_string or self.type.is_pyunicode_ptr: # postponed from self.generate_evaluation_code() self.generate_subexpr_disposal_code(code) self.free_subexpr_temps(code) elif self.type.is_pyobject: code.putln("%s = 0;" % self.result()) elif self.type.is_memoryviewslice: code.putln("%s.memview = NULL;" % self.result()) code.putln("%s.data = NULL;" % self.result()) if self.has_temp_moved: code.globalstate.use_utility_code( UtilityCode.load_cached("MoveIfSupported", "CppSupport.cpp")) else: self.generate_subexpr_disposal_code(code) def generate_assignment_code(self, rhs, code, overloaded_assignment=False, exception_check=None, exception_value=None): # Stub method for nodes which are not legal as # the LHS of an assignment. An error will have # been reported earlier. pass def generate_deletion_code(self, code, ignore_nonexisting=False): # Stub method for nodes that are not legal as # the argument of a del statement. An error # will have been reported earlier. pass def free_temps(self, code): if self.is_temp: if not self.type.is_void: self.release_temp_result(code) else: self.free_subexpr_temps(code) def free_subexpr_temps(self, code): for sub in self.subexpr_nodes(): sub.free_temps(code) def generate_function_definitions(self, env, code): pass # ----Generation of small bits of reference counting -- def generate_decref_set(self, code, rhs): code.put_decref_set(self.result(), self.ctype(), rhs) def generate_xdecref_set(self, code, rhs): code.put_xdecref_set(self.result(), self.ctype(), rhs) def generate_gotref(self, code, handle_null=False, maybe_null_extra_check=True): if not (handle_null and self.cf_is_null): if (handle_null and self.cf_maybe_null and maybe_null_extra_check): self.generate_xgotref(code) else: code.put_gotref(self.result(), self.ctype()) def generate_xgotref(self, code): code.put_xgotref(self.result(), self.ctype()) def generate_giveref(self, code): code.put_giveref(self.result(), self.ctype()) def generate_xgiveref(self, code): code.put_xgiveref(self.result(), self.ctype()) # ---------------- Annotation --------------------- def annotate(self, code): for node in self.subexpr_nodes(): node.annotate(code) # ----------------- Coercion ---------------------- def coerce_to(self, dst_type, env): # Coerce the result so that it can be assigned to # something of type dst_type. If processing is necessary, # wraps this node in a coercion node and returns that. # Otherwise, returns this node unchanged. # # This method is called during the analyse_expressions # phase of the src_node's processing. # # Note that subclasses that override this (especially # ConstNodes) must not (re-)set their own .type attribute # here. Since expression nodes may turn up in different # places in the tree (e.g. inside of CloneNodes in cascaded # assignments), this method must return a new node instance # if it changes the type. # src = self src_type = self.type if self.check_for_coercion_error(dst_type, env): return self used_as_reference = dst_type.is_reference if used_as_reference and not src_type.is_reference: dst_type = dst_type.ref_base_type if src_type.is_cv_qualified: src_type = src_type.cv_base_type if src_type.is_fused or dst_type.is_fused: # See if we are coercing a fused function to a pointer to a # specialized function if (src_type.is_cfunction and not dst_type.is_fused and dst_type.is_ptr and dst_type.base_type.is_cfunction): dst_type = dst_type.base_type for signature in src_type.get_all_specialized_function_types(): if signature.same_as(dst_type): src.type = signature src.entry = src.type.entry src.entry.used = True return self if src_type.is_fused: error(self.pos, "Type is not specialized") elif src_type.is_null_ptr and dst_type.is_ptr: # NULL can be implicitly cast to any pointer type return self else: error(self.pos, "Cannot coerce to a type that is not specialized") self.type = error_type return self if self.coercion_type is not None: # This is purely for error checking purposes! node = NameNode(self.pos, name='', type=self.coercion_type) node.coerce_to(dst_type, env) if dst_type.is_memoryviewslice: from . import MemoryView if not src.type.is_memoryviewslice: if src.type.is_pyobject: src = CoerceToMemViewSliceNode(src, dst_type, env) elif src.type.is_array: src = CythonArrayNode.from_carray(src, env).coerce_to(dst_type, env) elif not src_type.is_error: error(self.pos, "Cannot convert '%s' to memoryviewslice" % (src_type,)) else: if src.type.writable_needed: dst_type.writable_needed = True if not src.type.conforms_to(dst_type, broadcast=self.is_memview_broadcast, copying=self.is_memview_copy_assignment): if src.type.dtype.same_as(dst_type.dtype): msg = "Memoryview '%s' not conformable to memoryview '%s'." tup = src.type, dst_type else: msg = "Different base types for memoryviews (%s, %s)" tup = src.type.dtype, dst_type.dtype error(self.pos, msg % tup) elif dst_type.is_pyobject: # We never need a type check when assigning None to a Python object type. if src.is_none: pass elif src.constant_result is None: src = NoneNode(src.pos).coerce_to(dst_type, env) else: if not src.type.is_pyobject: if dst_type is bytes_type and src.type.is_int: src = CoerceIntToBytesNode(src, env) else: src = CoerceToPyTypeNode(src, env, type=dst_type) # FIXME: I would expect that CoerceToPyTypeNode(type=dst_type) returns a value of type dst_type # but it doesn't for ctuples. Thus, we add a PyTypeTestNode which then triggers the # Python conversion and becomes useless. That sems backwards and inefficient. # We should not need a PyTypeTestNode after a previous conversion above. if not src.type.subtype_of(dst_type): src = PyTypeTestNode(src, dst_type, env) elif is_pythran_expr(dst_type) and is_pythran_supported_type(src.type): # We let the compiler decide whether this is valid return src elif is_pythran_expr(src.type): if is_pythran_supported_type(dst_type): # Match the case were a pythran expr is assigned to a value, or vice versa. # We let the C++ compiler decide whether this is valid or not! return src # Else, we need to convert the Pythran expression to a Python object src = CoerceToPyTypeNode(src, env, type=dst_type) elif src.type.is_pyobject: if used_as_reference and dst_type.is_cpp_class: warning( self.pos, "Cannot pass Python object as C++ data structure reference (%s &), will pass by copy." % dst_type) src = CoerceFromPyTypeNode(dst_type, src, env) elif (dst_type.is_complex and src_type != dst_type and dst_type.assignable_from(src_type)): src = CoerceToComplexNode(src, dst_type, env) elif (src_type is PyrexTypes.soft_complex_type and src_type != dst_type and not dst_type.assignable_from(src_type)): src = coerce_from_soft_complex(src, dst_type, env) else: # neither src nor dst are py types # Added the string comparison, since for c types that # is enough, but Cython gets confused when the types are # in different pxi files. # TODO: Remove this hack and require shared declarations. if not (src.type == dst_type or str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)): self.fail_assignment(dst_type) return src def fail_assignment(self, dst_type): extra_diagnostics = dst_type.assignment_failure_extra_info(self.type) if extra_diagnostics: extra_diagnostics = ". " + extra_diagnostics error(self.pos, "Cannot assign type '%s' to '%s'%s" % ( self.type, dst_type, extra_diagnostics)) def check_for_coercion_error(self, dst_type, env, fail=False, default=None): if fail and not default: default = "Cannot assign type '%(FROM)s' to '%(TO)s'" message = find_coercion_error((self.type, dst_type), default, env) if message is not None: error(self.pos, message % {'FROM': self.type, 'TO': dst_type}) return True if fail: self.fail_assignment(dst_type) return True return False def coerce_to_pyobject(self, env): return self.coerce_to(PyrexTypes.py_object_type, env) def coerce_to_boolean(self, env): # Coerce result to something acceptable as # a boolean value. # if it's constant, calculate the result now if self.has_constant_result(): bool_value = bool(self.constant_result) return BoolNode(self.pos, value=bool_value, constant_result=bool_value) type = self.type if type.is_enum or type.is_error: return self elif type is PyrexTypes.c_bint_type: return self elif type.is_pyobject or type.is_int or type.is_ptr or type.is_float: return CoerceToBooleanNode(self, env) elif type.is_cpp_class and type.scope and type.scope.lookup("operator bool"): return SimpleCallNode( self.pos, function=AttributeNode( self.pos, obj=self, attribute=StringEncoding.EncodedString('operator bool')), args=[]).analyse_types(env) elif type.is_ctuple: bool_value = len(type.components) == 0 return BoolNode(self.pos, value=bool_value, constant_result=bool_value) else: error(self.pos, "Type '%s' not acceptable as a boolean" % type) return self def coerce_to_integer(self, env): # If not already some C integer type, coerce to longint. if self.type.is_int: return self else: return self.coerce_to(PyrexTypes.c_long_type, env) def coerce_to_temp(self, env): # Ensure that the result is in a temporary. if self.result_in_temp(): return self else: return CoerceToTempNode(self, env) def coerce_to_simple(self, env): # Ensure that the result is simple (see is_simple). if self.is_simple(): return self else: return self.coerce_to_temp(env) def is_simple(self): # A node is simple if its result is something that can # be referred to without performing any operations, e.g. # a constant, local var, C global var, struct member # reference, or temporary. return self.result_in_temp() def may_be_none(self): if self.type and not (self.type.is_pyobject or self.type.is_memoryviewslice): return False if self.has_constant_result(): return self.constant_result is not None return True def as_cython_attribute(self): return None def as_none_safe_node(self, message, error="PyExc_TypeError", format_args=()): # Wraps the node in a NoneCheckNode if it is not known to be # not-None (e.g. because it is a Python literal). if self.may_be_none(): return NoneCheckNode(self, error, message, format_args) else: return self @classmethod def from_node(cls, node, **kwargs): """Instantiate this node class from another node, properly copying over all attributes that one would forget otherwise. """ attributes = "cf_state cf_maybe_null cf_is_null constant_result".split() for attr_name in attributes: if attr_name in kwargs: continue try: value = getattr(node, attr_name) except AttributeError: pass else: kwargs[attr_name] = value return cls(node.pos, **kwargs) def get_known_standard_library_import(self): """ Gets the module.path that this node was imported from. Many nodes do not have one, or it is ambiguous, in which case this function returns a false value. """ return None class AtomicExprNode(ExprNode): # Abstract base class for expression nodes which have # no sub-expressions. subexprs = [] # Override to optimize -- we know we have no children def generate_subexpr_evaluation_code(self, code): pass def generate_subexpr_disposal_code(self, code): pass class PyConstNode(AtomicExprNode): # Abstract base class for constant Python values. is_literal = 1 type = py_object_type nogil_check = None def is_simple(self): return 1 def may_be_none(self): return False def analyse_types(self, env): return self def calculate_result_code(self): return self.value def generate_result_code(self, code): pass class NoneNode(PyConstNode): # The constant value None is_none = 1 value = "Py_None" constant_result = None def compile_time_value(self, denv): return None def may_be_none(self): return True def coerce_to(self, dst_type, env): if not (dst_type.is_pyobject or dst_type.is_memoryviewslice or dst_type.is_error): # Catch this error early and loudly. error(self.pos, "Cannot assign None to %s" % dst_type) return super(NoneNode, self).coerce_to(dst_type, env) class EllipsisNode(PyConstNode): # '...' in a subscript list. value = "Py_Ellipsis" constant_result = Ellipsis def compile_time_value(self, denv): return Ellipsis class ConstNode(AtomicExprNode): # Abstract base type for literal constant nodes. # # value string C code fragment is_literal = 1 nogil_check = None def is_simple(self): return 1 def nonlocally_immutable(self): return 1 def may_be_none(self): return False def analyse_types(self, env): return self # Types are held in class variables def check_const(self): return True def get_constant_c_result_code(self): return self.calculate_result_code() def calculate_result_code(self): return str(self.value) def generate_result_code(self, code): pass class BoolNode(ConstNode): type = PyrexTypes.c_bint_type # The constant value True or False def calculate_constant_result(self): self.constant_result = self.value def compile_time_value(self, denv): return self.value def calculate_result_code(self): if self.type.is_pyobject: return 'Py_True' if self.value else 'Py_False' else: return str(int(self.value)) def coerce_to(self, dst_type, env): if dst_type == self.type: return self if dst_type is py_object_type and self.type is Builtin.bool_type: return self if dst_type.is_pyobject and self.type.is_int: return BoolNode( self.pos, value=self.value, constant_result=self.constant_result, type=Builtin.bool_type) if dst_type.is_int and self.type.is_pyobject: return BoolNode( self.pos, value=self.value, constant_result=self.constant_result, type=PyrexTypes.c_bint_type) return ConstNode.coerce_to(self, dst_type, env) class NullNode(ConstNode): type = PyrexTypes.c_null_ptr_type value = "NULL" constant_result = 0 def get_constant_c_result_code(self): return self.value class CharNode(ConstNode): type = PyrexTypes.c_char_type def calculate_constant_result(self): self.constant_result = ord(self.value) def compile_time_value(self, denv): return ord(self.value) def calculate_result_code(self): return "'%s'" % StringEncoding.escape_char(self.value) class IntNode(ConstNode): # unsigned "" or "U" # longness "" or "L" or "LL" # is_c_literal True/False/None creator considers this a C integer literal unsigned = "" longness = "" is_c_literal = None # unknown # hex_value and base_10_value are designed only to simplify # writing tests to get a consistent representation of value @property def hex_value(self): return Utils.strip_py2_long_suffix(hex(Utils.str_to_number(self.value))) @property def base_10_value(self): return str(Utils.str_to_number(self.value)) def __init__(self, pos, **kwds): ExprNode.__init__(self, pos, **kwds) if 'type' not in kwds: self.type = self.find_suitable_type_for_value() def find_suitable_type_for_value(self): if self.constant_result is constant_value_not_set: try: self.calculate_constant_result() except ValueError: pass # we ignore 'is_c_literal = True' and instead map signed 32bit # integers as C long values if self.is_c_literal or \ not self.has_constant_result() or \ self.unsigned or self.longness == 'LL': # clearly a C literal rank = (self.longness == 'LL') and 2 or 1 suitable_type = PyrexTypes.modifiers_and_name_to_type[not self.unsigned, rank, "int"] if self.type: suitable_type = PyrexTypes.widest_numeric_type(suitable_type, self.type) else: # C literal or Python literal - split at 32bit boundary if -2**31 <= self.constant_result < 2**31: if self.type and self.type.is_int: suitable_type = self.type else: suitable_type = PyrexTypes.c_long_type else: suitable_type = PyrexTypes.py_object_type return suitable_type def coerce_to(self, dst_type, env): if self.type is dst_type: return self elif dst_type.is_float: if self.has_constant_result(): return FloatNode(self.pos, value='%d.0' % int(self.constant_result), type=dst_type, constant_result=float(self.constant_result)) else: return FloatNode(self.pos, value=self.value, type=dst_type, constant_result=not_a_constant) if dst_type.is_numeric and not dst_type.is_complex: node = IntNode(self.pos, value=self.value, constant_result=self.constant_result, type=dst_type, is_c_literal=True, unsigned=self.unsigned, longness=self.longness) return node elif dst_type.is_pyobject: node = IntNode(self.pos, value=self.value, constant_result=self.constant_result, type=PyrexTypes.py_object_type, is_c_literal=False, unsigned=self.unsigned, longness=self.longness) else: # FIXME: not setting the type here to keep it working with # complex numbers. Should they be special cased? node = IntNode(self.pos, value=self.value, constant_result=self.constant_result, unsigned=self.unsigned, longness=self.longness) # We still need to perform normal coerce_to processing on the # result, because we might be coercing to an extension type, # in which case a type test node will be needed. return ConstNode.coerce_to(node, dst_type, env) def coerce_to_boolean(self, env): return IntNode( self.pos, value=self.value, constant_result=self.constant_result, type=PyrexTypes.c_bint_type, unsigned=self.unsigned, longness=self.longness) def generate_evaluation_code(self, code): if self.type.is_pyobject: # pre-allocate a Python version of the number # (In hex if sufficiently large to cope with Python's string-to-int limitations. # We use quite a small value of "sufficiently large" - 10**13 is picked as # the approximate point where hex strings become shorter) value = Utils.str_to_number(self.value) formatter = hex if value > (10**13) else str plain_integer_string = formatter(value) plain_integer_string = Utils.strip_py2_long_suffix(plain_integer_string) self.result_code = code.get_py_int(plain_integer_string, self.longness) else: self.result_code = self.get_constant_c_result_code() def get_constant_c_result_code(self): unsigned, longness = self.unsigned, self.longness literal = self.value_as_c_integer_string() if not (unsigned or longness) and self.type.is_int and literal[0] == '-' and literal[1] != '0': # negative decimal literal => guess longness from type to prevent wrap-around if self.type.rank >= PyrexTypes.c_longlong_type.rank: longness = 'LL' elif self.type.rank >= PyrexTypes.c_long_type.rank: longness = 'L' return literal + unsigned + longness def value_as_c_integer_string(self): value = self.value if len(value) <= 2: # too short to go wrong (and simplifies code below) return value neg_sign = '' if value[0] == '-': neg_sign = '-' value = value[1:] if value[0] == '0': literal_type = value[1] # 0'o' - 0'b' - 0'x' # 0x123 hex literals and 0123 octal literals work nicely in C # but C-incompatible Py3 oct/bin notations need conversion if neg_sign and literal_type in 'oOxX0123456789' and value[2:].isdigit(): # negative hex/octal literal => prevent C compiler from using # unsigned integer types by converting to decimal (see C standard 6.4.4.1) value = str(Utils.str_to_number(value)) elif literal_type in 'oO': value = '0' + value[2:] # '0o123' => '0123' elif literal_type in 'bB': value = str(int(value[2:], 2)) elif value.isdigit() and not self.unsigned and not self.longness: if not neg_sign: # C compilers do not consider unsigned types for decimal literals, # but they do for hex (see C standard 6.4.4.1) value = '0x%X' % int(value) return neg_sign + value def calculate_result_code(self): return self.result_code def calculate_constant_result(self): self.constant_result = Utils.str_to_number(self.value) def compile_time_value(self, denv): return Utils.str_to_number(self.value) class FloatNode(ConstNode): type = PyrexTypes.c_double_type def calculate_constant_result(self): self.constant_result = float(self.value) def compile_time_value(self, denv): float_value = float(self.value) str_float_value = ("%.330f" % float_value).strip('0') str_value = Utils.normalise_float_repr(self.value) if str_value not in (str_float_value, repr(float_value).lstrip('0')): warning(self.pos, "Using this floating point value with DEF may lose precision, using %r" % float_value) return float_value def coerce_to(self, dst_type, env): if dst_type.is_pyobject and self.type.is_float: return FloatNode( self.pos, value=self.value, constant_result=self.constant_result, type=Builtin.float_type) if dst_type.is_float and self.type.is_pyobject: return FloatNode( self.pos, value=self.value, constant_result=self.constant_result, type=dst_type) return ConstNode.coerce_to(self, dst_type, env) def calculate_result_code(self): return self.result_code def get_constant_c_result_code(self): strval = self.value assert isinstance(strval, basestring) cmpval = repr(float(strval)) if cmpval == 'nan': return "(Py_HUGE_VAL * 0)" elif cmpval == 'inf': return "Py_HUGE_VAL" elif cmpval == '-inf': return "(-Py_HUGE_VAL)" else: return strval def generate_evaluation_code(self, code): c_value = self.get_constant_c_result_code() if self.type.is_pyobject: self.result_code = code.get_py_float(self.value, c_value) else: self.result_code = c_value def _analyse_name_as_type(name, pos, env): ctype = PyrexTypes.parse_basic_type(name) if ctype is not None and env.in_c_type_context: return ctype global_scope = env.global_scope() global_entry = global_scope.lookup(name) if global_entry and global_entry.is_type: type = global_entry.type if (not env.in_c_type_context and type is Builtin.int_type and global_scope.context.language_level == 2): # While we still support Python2 this needs to be downgraded # to a generic Python object to include both int and long. # With language_level > 3, we keep the type but also accept 'long' in Py2. type = py_object_type if type and (type.is_pyobject or env.in_c_type_context): return type ctype = ctype or type # This is fairly heavy, so it's worth trying some easier things above. from .TreeFragment import TreeFragment with local_errors(ignore=True): pos = (pos[0], pos[1], pos[2]-7) try: declaration = TreeFragment(u"sizeof(%s)" % name, name=pos[0].filename, initial_pos=pos) except CompileError: pass else: sizeof_node = declaration.root.stats[0].expr if isinstance(sizeof_node, SizeofTypeNode): sizeof_node = sizeof_node.analyse_types(env) if isinstance(sizeof_node, SizeofTypeNode): type = sizeof_node.arg_type if type and (type.is_pyobject or env.in_c_type_context): return type ctype = ctype or type return ctype class BytesNode(ConstNode): # A char* or bytes literal # # value BytesLiteral is_string_literal = True # start off as Python 'bytes' to support len() in O(1) type = bytes_type def calculate_constant_result(self): self.constant_result = self.value def as_sliced_node(self, start, stop, step=None): value = StringEncoding.bytes_literal(self.value[start:stop:step], self.value.encoding) return BytesNode(self.pos, value=value, constant_result=value) def compile_time_value(self, denv): return self.value.byteencode() def analyse_as_type(self, env): return _analyse_name_as_type(self.value.decode('ISO8859-1'), self.pos, env) def can_coerce_to_char_literal(self): return len(self.value) == 1 def coerce_to_boolean(self, env): # This is special because testing a C char* for truth directly # would yield the wrong result. bool_value = bool(self.value) return BoolNode(self.pos, value=bool_value, constant_result=bool_value) def coerce_to(self, dst_type, env): if self.type == dst_type: return self if dst_type.is_int: if not self.can_coerce_to_char_literal(): error(self.pos, "Only single-character string literals can be coerced into ints.") return self if dst_type.is_unicode_char: error(self.pos, "Bytes literals cannot coerce to Py_UNICODE/Py_UCS4, use a unicode literal instead.") return self return CharNode(self.pos, value=self.value, constant_result=ord(self.value)) node = BytesNode(self.pos, value=self.value, constant_result=self.constant_result) if dst_type.is_pyobject: if dst_type in (py_object_type, Builtin.bytes_type): node.type = Builtin.bytes_type else: self.check_for_coercion_error(dst_type, env, fail=True) return node elif dst_type in (PyrexTypes.c_char_ptr_type, PyrexTypes.c_const_char_ptr_type): node.type = dst_type return node elif dst_type in (PyrexTypes.c_uchar_ptr_type, PyrexTypes.c_const_uchar_ptr_type, PyrexTypes.c_void_ptr_type): node.type = (PyrexTypes.c_const_char_ptr_type if dst_type == PyrexTypes.c_const_uchar_ptr_type else PyrexTypes.c_char_ptr_type) return CastNode(node, dst_type) elif dst_type.assignable_from(PyrexTypes.c_char_ptr_type): # Exclude the case of passing a C string literal into a non-const C++ string. if not dst_type.is_cpp_class or dst_type.is_const: node.type = dst_type return node # We still need to perform normal coerce_to processing on the # result, because we might be coercing to an extension type, # in which case a type test node will be needed. return ConstNode.coerce_to(node, dst_type, env) def generate_evaluation_code(self, code): if self.type.is_pyobject: result = code.get_py_string_const(self.value) elif self.type.is_const: result = code.get_string_const(self.value) else: # not const => use plain C string literal and cast to mutable type literal = self.value.as_c_string_literal() # C++ may require a cast result = typecast(self.type, PyrexTypes.c_void_ptr_type, literal) self.result_code = result def get_constant_c_result_code(self): return None # FIXME def calculate_result_code(self): return self.result_code class UnicodeNode(ConstNode): # A Py_UNICODE* or unicode literal # # value EncodedString # bytes_value BytesLiteral the literal parsed as bytes string # ('-3' unicode literals only) is_string_literal = True bytes_value = None type = unicode_type def calculate_constant_result(self): self.constant_result = self.value def analyse_as_type(self, env): return _analyse_name_as_type(self.value, self.pos, env) def as_sliced_node(self, start, stop, step=None): if StringEncoding.string_contains_surrogates(self.value[:stop]): # this is unsafe as it may give different results # in different runtimes return None value = StringEncoding.EncodedString(self.value[start:stop:step]) value.encoding = self.value.encoding if self.bytes_value is not None: bytes_value = StringEncoding.bytes_literal( self.bytes_value[start:stop:step], self.bytes_value.encoding) else: bytes_value = None return UnicodeNode( self.pos, value=value, bytes_value=bytes_value, constant_result=value) def coerce_to(self, dst_type, env): if dst_type is self.type: pass elif dst_type.is_unicode_char: if not self.can_coerce_to_char_literal(): error(self.pos, "Only single-character Unicode string literals or " "surrogate pairs can be coerced into Py_UCS4/Py_UNICODE.") return self int_value = ord(self.value) return IntNode(self.pos, type=dst_type, value=str(int_value), constant_result=int_value) elif not dst_type.is_pyobject: if dst_type.is_string and self.bytes_value is not None: # special case: '-3' enforced unicode literal used in a # C char* context return BytesNode(self.pos, value=self.bytes_value).coerce_to(dst_type, env) if dst_type.is_pyunicode_ptr: return UnicodeNode(self.pos, value=self.value, type=dst_type) error(self.pos, "Unicode literals do not support coercion to C types other " "than Py_UNICODE/Py_UCS4 (for characters) or Py_UNICODE* " "(for strings).") elif dst_type not in (py_object_type, Builtin.basestring_type): self.check_for_coercion_error(dst_type, env, fail=True) return self def can_coerce_to_char_literal(self): return len(self.value) == 1 ## or (len(self.value) == 2 ## and (0xD800 <= self.value[0] <= 0xDBFF) ## and (0xDC00 <= self.value[1] <= 0xDFFF)) def coerce_to_boolean(self, env): bool_value = bool(self.value) return BoolNode(self.pos, value=bool_value, constant_result=bool_value) def contains_surrogates(self): return StringEncoding.string_contains_surrogates(self.value) def generate_evaluation_code(self, code): if self.type.is_pyobject: # FIXME: this should go away entirely! # Since string_contains_lone_surrogates() returns False for surrogate pairs in Py2/UCS2, # Py2 can generate different code from Py3 here. Let's hope we get away with claiming that # the processing of surrogate pairs in code was always ambiguous and lead to different results # on P16/32bit Unicode platforms. if StringEncoding.string_contains_lone_surrogates(self.value): # lone (unpaired) surrogates are not really portable and cannot be # decoded by the UTF-8 codec in Py3.3 self.result_code = code.get_py_const(py_object_type, 'ustring') data_cname = code.get_string_const( StringEncoding.BytesLiteral(self.value.encode('unicode_escape'))) const_code = code.get_cached_constants_writer(self.result_code) if const_code is None: return # already initialised const_code.mark_pos(self.pos) const_code.putln( "%s = PyUnicode_DecodeUnicodeEscape(%s, sizeof(%s) - 1, NULL); %s" % ( self.result_code, data_cname, data_cname, const_code.error_goto_if_null(self.result_code, self.pos))) const_code.put_error_if_neg( self.pos, "__Pyx_PyUnicode_READY(%s)" % self.result_code) else: self.result_code = code.get_py_string_const(self.value) else: self.result_code = code.get_pyunicode_ptr_const(self.value) def calculate_result_code(self): return self.result_code def compile_time_value(self, env): return self.value class StringNode(PyConstNode): # A Python str object, i.e. a byte string in Python 2.x and a # unicode string in Python 3.x # # value BytesLiteral (or EncodedString with ASCII content) # unicode_value EncodedString or None # is_identifier boolean type = str_type is_string_literal = True is_identifier = None unicode_value = None def calculate_constant_result(self): if self.unicode_value is not None: # only the Unicode value is portable across Py2/3 self.constant_result = self.unicode_value def analyse_as_type(self, env): return _analyse_name_as_type(self.unicode_value or self.value.decode('ISO8859-1'), self.pos, env) def as_sliced_node(self, start, stop, step=None): value = type(self.value)(self.value[start:stop:step]) value.encoding = self.value.encoding if self.unicode_value is not None: if StringEncoding.string_contains_surrogates(self.unicode_value[:stop]): # this is unsafe as it may give different results in different runtimes return None unicode_value = StringEncoding.EncodedString( self.unicode_value[start:stop:step]) else: unicode_value = None return StringNode( self.pos, value=value, unicode_value=unicode_value, constant_result=value, is_identifier=self.is_identifier) def coerce_to(self, dst_type, env): if dst_type is not py_object_type and not str_type.subtype_of(dst_type): # if dst_type is Builtin.bytes_type: # # special case: bytes = 'str literal' # return BytesNode(self.pos, value=self.value) if not dst_type.is_pyobject: return BytesNode(self.pos, value=self.value).coerce_to(dst_type, env) if dst_type is not Builtin.basestring_type: self.check_for_coercion_error(dst_type, env, fail=True) return self def can_coerce_to_char_literal(self): return not self.is_identifier and len(self.value) == 1 def generate_evaluation_code(self, code): self.result_code = code.get_py_string_const( self.value, identifier=self.is_identifier, is_str=True, unicode_value=self.unicode_value) def get_constant_c_result_code(self): return None def calculate_result_code(self): return self.result_code def compile_time_value(self, env): if self.value.is_unicode: return self.value if not IS_PYTHON3: # use plain str/bytes object in Py2 return self.value.byteencode() # in Py3, always return a Unicode string if self.unicode_value is not None: return self.unicode_value return self.value.decode('iso8859-1') class IdentifierStringNode(StringNode): # A special str value that represents an identifier (bytes in Py2, # unicode in Py3). is_identifier = True class ImagNode(AtomicExprNode): # Imaginary number literal # # value string imaginary part (float value) type = PyrexTypes.c_double_complex_type def calculate_constant_result(self): self.constant_result = complex(0.0, float(self.value)) def compile_time_value(self, denv): return complex(0.0, float(self.value)) def analyse_types(self, env): self.type.create_declaration_utility_code(env) return self def may_be_none(self): return False def coerce_to(self, dst_type, env): if self.type is dst_type: return self node = ImagNode(self.pos, value=self.value) if dst_type.is_pyobject: node.is_temp = 1 node.type = Builtin.complex_type # We still need to perform normal coerce_to processing on the # result, because we might be coercing to an extension type, # in which case a type test node will be needed. return AtomicExprNode.coerce_to(node, dst_type, env) gil_message = "Constructing complex number" def calculate_result_code(self): if self.type.is_pyobject: return self.result() else: return "%s(0, %r)" % (self.type.from_parts, float(self.value)) def generate_result_code(self, code): if self.type.is_pyobject: code.putln( "%s = PyComplex_FromDoubles(0.0, %r); %s" % ( self.result(), float(self.value), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) class NewExprNode(AtomicExprNode): # C++ new statement # # cppclass node c++ class to create type = None def infer_type(self, env): type = self.cppclass.analyse_as_type(env) if type is None or not type.is_cpp_class: error(self.pos, "new operator can only be applied to a C++ class") self.type = error_type return self.cpp_check(env) constructor = type.get_constructor(self.pos) self.class_type = type self.entry = constructor self.type = constructor.type return self.type def analyse_types(self, env): if self.type is None: self.infer_type(env) return self def may_be_none(self): return False def generate_result_code(self, code): pass def calculate_result_code(self): return "new " + self.class_type.empty_declaration_code() class NameNode(AtomicExprNode): # Reference to a local or global variable name. # # name string Python name of the variable # entry Entry Symbol table entry # type_entry Entry For extension type names, the original type entry # cf_is_null boolean Is uninitialized before this node # cf_maybe_null boolean Maybe uninitialized before this node # allow_null boolean Don't raise UnboundLocalError # nogil boolean Whether it is used in a nogil context is_name = True is_cython_module = False cython_attribute = None lhs_of_first_assignment = False # TODO: remove me is_used_as_rvalue = 0 entry = None type_entry = None cf_maybe_null = True cf_is_null = False allow_null = False nogil = False inferred_type = None def as_cython_attribute(self): return self.cython_attribute def type_dependencies(self, env): if self.entry is None: self.entry = env.lookup(self.name) if self.entry is not None and self.entry.type.is_unspecified: return (self,) else: return () def infer_type(self, env): if self.entry is None: self.entry = env.lookup(self.name) if self.entry is None or self.entry.type is unspecified_type: if self.inferred_type is not None: return self.inferred_type return py_object_type elif (self.entry.type.is_extension_type or self.entry.type.is_builtin_type) and \ self.name == self.entry.type.name: # Unfortunately the type attribute of type objects # is used for the pointer to the type they represent. return type_type elif self.entry.type.is_cfunction: if self.entry.scope.is_builtin_scope: # special case: optimised builtin functions must be treated as Python objects return py_object_type else: # special case: referring to a C function must return its pointer return PyrexTypes.CPtrType(self.entry.type) else: # If entry is inferred as pyobject it's safe to use local # NameNode's inferred_type. if self.entry.type.is_pyobject and self.inferred_type: # Overflow may happen if integer if not (self.inferred_type.is_int and self.entry.might_overflow): return self.inferred_type return self.entry.type def compile_time_value(self, denv): try: return denv.lookup(self.name) except KeyError: error(self.pos, "Compile-time name '%s' not defined" % self.name) def get_constant_c_result_code(self): if not self.entry or self.entry.type.is_pyobject: return None return self.entry.cname def coerce_to(self, dst_type, env): # If coercing to a generic pyobject and this is a builtin # C function with a Python equivalent, manufacture a NameNode # referring to the Python builtin. #print "NameNode.coerce_to:", self.name, dst_type ### if dst_type is py_object_type: entry = self.entry if entry and entry.is_cfunction: var_entry = entry.as_variable if var_entry: if var_entry.is_builtin and var_entry.is_const: var_entry = env.declare_builtin(var_entry.name, self.pos) node = NameNode(self.pos, name = self.name) node.entry = var_entry node.analyse_rvalue_entry(env) return node return super(NameNode, self).coerce_to(dst_type, env) def declare_from_annotation(self, env, as_target=False): """Implements PEP 526 annotation typing in a fairly relaxed way. Annotations are ignored for global variables. All other annotations are stored on the entry in the symbol table. String literals are allowed and not evaluated. The ambiguous Python types 'int' and 'long' are not evaluated - the 'cython.int' form must be used instead. """ name = self.name annotation = self.annotation entry = self.entry or env.lookup_here(name) if not entry: # annotations never create global cdef names if env.is_module_scope: return modifiers = () if ( # name: "description" => not a type, but still a declared variable or attribute annotation.expr.is_string_literal # don't do type analysis from annotations if not asked to, but still collect the annotation or not env.directives['annotation_typing'] ): atype = None elif env.is_py_class_scope: # For Python class scopes every attribute is a Python object atype = py_object_type else: modifiers, atype = annotation.analyse_type_annotation(env) if atype is None: atype = unspecified_type if as_target and env.directives['infer_types'] != False else py_object_type elif atype.is_fused and env.fused_to_specific: try: atype = atype.specialize(env.fused_to_specific) except CannotSpecialize: error(self.pos, "'%s' cannot be specialized since its type is not a fused argument to this function" % self.name) atype = error_type visibility = 'private' if env.is_c_dataclass_scope: # handle "frozen" directive - full inspection of the dataclass directives happens # in Dataclass.py is_frozen = env.is_c_dataclass_scope == "frozen" if atype.is_pyobject or atype.can_coerce_to_pyobject(env): visibility = 'readonly' if is_frozen else 'public' # If the object can't be coerced that's fine - we just don't create a property if as_target and env.is_c_class_scope and not (atype.is_pyobject or atype.is_error): # TODO: this will need revising slightly if annotated cdef attributes are implemented atype = py_object_type warning(annotation.pos, "Annotation ignored since class-level attributes must be Python objects. " "Were you trying to set up an instance attribute?", 2) entry = self.entry = env.declare_var( name, atype, self.pos, is_cdef=not as_target, visibility=visibility, pytyping_modifiers=modifiers) # Even if the entry already exists, make sure we're supplying an annotation if we can. if annotation and not entry.annotation: entry.annotation = annotation def analyse_as_module(self, env): # Try to interpret this as a reference to a cimported module. # Returns the module scope, or None. entry = self.entry if not entry: entry = env.lookup(self.name) if entry and entry.as_module: return entry.as_module if entry and entry.known_standard_library_import: scope = Builtin.get_known_standard_library_module_scope(entry.known_standard_library_import) if scope and scope.is_module_scope: return scope return None def analyse_as_type(self, env): type = None if self.cython_attribute: type = PyrexTypes.parse_basic_type(self.cython_attribute) elif env.in_c_type_context: type = PyrexTypes.parse_basic_type(self.name) if type: return type entry = self.entry if not entry: entry = env.lookup(self.name) if entry and not entry.is_type and entry.known_standard_library_import: entry = Builtin.get_known_standard_library_entry(entry.known_standard_library_import) if entry and entry.is_type: # Infer equivalent C types instead of Python types when possible. type = entry.type if not env.in_c_type_context and type is Builtin.long_type: # Try to give a helpful warning when users write plain C type names. warning(self.pos, "Found Python 2.x type 'long' in a Python annotation. Did you mean to use 'cython.long'?") type = py_object_type elif type.is_pyobject and type.equivalent_type: type = type.equivalent_type elif type is Builtin.int_type and env.global_scope().context.language_level == 2: # While we still support Python 2 this must be a plain object # so that it can be either int or long. With language_level=3(str), # we pick up the type but accept both int and long in Py2. type = py_object_type return type if self.name == 'object': # This is normally parsed as "simple C type", but not if we don't parse C types. return py_object_type # Try to give a helpful warning when users write plain C type names. if not env.in_c_type_context and PyrexTypes.parse_basic_type(self.name): warning(self.pos, "Found C type '%s' in a Python annotation. Did you mean to use 'cython.%s'?" % (self.name, self.name)) return None def analyse_as_extension_type(self, env): # Try to interpret this as a reference to an extension type. # Returns the extension type, or None. entry = self.entry if not entry: entry = env.lookup(self.name) if entry and entry.is_type: if entry.type.is_extension_type or entry.type.is_builtin_type: return entry.type return None def analyse_target_declaration(self, env): return self._analyse_target_declaration(env, is_assignment_expression=False) def analyse_assignment_expression_target_declaration(self, env): return self._analyse_target_declaration(env, is_assignment_expression=True) def _analyse_target_declaration(self, env, is_assignment_expression): self.is_target = True if not self.entry: if is_assignment_expression: self.entry = env.lookup_assignment_expression_target(self.name) else: self.entry = env.lookup_here(self.name) if self.entry: self.entry.known_standard_library_import = "" # already exists somewhere and so is now ambiguous if not self.entry and self.annotation is not None: # name : type = ... is_dataclass = env.is_c_dataclass_scope # In a dataclass, an assignment should not prevent a name from becoming an instance attribute. # Hence, "as_target = not is_dataclass". self.declare_from_annotation(env, as_target=not is_dataclass) elif (self.entry and self.entry.is_inherited and self.annotation and env.is_c_dataclass_scope): error(self.pos, "Cannot redeclare inherited fields in Cython dataclasses") if not self.entry: if env.directives['warn.undeclared']: warning(self.pos, "implicit declaration of '%s'" % self.name, 1) if env.directives['infer_types'] != False: type = unspecified_type else: type = py_object_type if is_assignment_expression: self.entry = env.declare_assignment_expression_target(self.name, type, self.pos) else: self.entry = env.declare_var(self.name, type, self.pos) if self.entry.is_declared_generic: self.result_ctype = py_object_type if self.entry.as_module: # cimported modules namespace can shadow actual variables self.entry.is_variable = 1 def analyse_types(self, env): self.initialized_check = env.directives['initializedcheck'] entry = self.entry if entry is None: entry = env.lookup(self.name) if not entry: entry = env.declare_builtin(self.name, self.pos) if entry and entry.is_builtin and entry.is_const: self.is_literal = True if not entry: self.type = PyrexTypes.error_type return self self.entry = entry entry.used = 1 if entry.type.is_buffer: from . import Buffer Buffer.used_buffer_aux_vars(entry) self.analyse_rvalue_entry(env) return self def analyse_target_types(self, env): self.analyse_entry(env, is_target=True) entry = self.entry if entry.is_cfunction and entry.as_variable: # FIXME: unify "is_overridable" flags below if (entry.is_overridable or entry.type.is_overridable) or not self.is_lvalue() and entry.fused_cfunction: # We need this for assigning to cpdef names and for the fused 'def' TreeFragment entry = self.entry = entry.as_variable self.type = entry.type if self.type.is_const: error(self.pos, "Assignment to const '%s'" % self.name) if not self.is_lvalue(): error(self.pos, "Assignment to non-lvalue '%s'" % self.name) self.type = PyrexTypes.error_type entry.used = 1 if entry.type.is_buffer: from . import Buffer Buffer.used_buffer_aux_vars(entry) return self def analyse_rvalue_entry(self, env): #print "NameNode.analyse_rvalue_entry:", self.name ### #print "Entry:", self.entry.__dict__ ### self.analyse_entry(env) entry = self.entry if entry.is_declared_generic: self.result_ctype = py_object_type if entry.is_pyglobal or entry.is_builtin: if entry.is_builtin and entry.is_const: self.is_temp = 0 else: self.is_temp = 1 self.is_used_as_rvalue = 1 elif entry.type.is_memoryviewslice: self.is_temp = False self.is_used_as_rvalue = True self.use_managed_ref = True return self def nogil_check(self, env): self.nogil = True if self.is_used_as_rvalue: entry = self.entry if entry.is_builtin: if not entry.is_const: # cached builtins are ok self.gil_error() elif entry.is_pyglobal: self.gil_error() gil_message = "Accessing Python global or builtin" def analyse_entry(self, env, is_target=False): #print "NameNode.analyse_entry:", self.name ### self.check_identifier_kind() entry = self.entry type = entry.type if (not is_target and type.is_pyobject and self.inferred_type and self.inferred_type.is_builtin_type): # assume that type inference is smarter than the static entry type = self.inferred_type self.type = type def check_identifier_kind(self): # Check that this is an appropriate kind of name for use in an # expression. Also finds the variable entry associated with # an extension type. entry = self.entry if entry.is_type and entry.type.is_extension_type: self.type_entry = entry if entry.is_type and (entry.type.is_enum or entry.type.is_cpp_enum): py_entry = Symtab.Entry(self.name, None, py_object_type) py_entry.is_pyglobal = True py_entry.scope = self.entry.scope self.entry = py_entry elif not (entry.is_const or entry.is_variable or entry.is_builtin or entry.is_cfunction or entry.is_cpp_class): if self.entry.as_variable: self.entry = self.entry.as_variable elif not self.is_cython_module: error(self.pos, "'%s' is not a constant, variable or function identifier" % self.name) def is_cimported_module_without_shadow(self, env): if self.is_cython_module or self.cython_attribute: return False entry = self.entry or env.lookup(self.name) return entry.as_module and not entry.is_variable def is_simple(self): # If it's not a C variable, it'll be in a temp. return 1 def may_be_none(self): if self.cf_state and self.type and (self.type.is_pyobject or self.type.is_memoryviewslice): # guard against infinite recursion on self-dependencies if getattr(self, '_none_checking', False): # self-dependency - either this node receives a None # value from *another* node, or it can not reference # None at this point => safe to assume "not None" return False self._none_checking = True # evaluate control flow state to see if there were any # potential None values assigned to the node so far may_be_none = False for assignment in self.cf_state: if assignment.rhs.may_be_none(): may_be_none = True break del self._none_checking return may_be_none return super(NameNode, self).may_be_none() def nonlocally_immutable(self): if ExprNode.nonlocally_immutable(self): return True entry = self.entry if not entry or entry.in_closure: return False return entry.is_local or entry.is_arg or entry.is_builtin or entry.is_readonly def calculate_target_results(self, env): pass def check_const(self): entry = self.entry if entry is not None and not ( entry.is_const or entry.is_cfunction or entry.is_builtin or entry.type.is_const): self.not_const() return False return True def check_const_addr(self): entry = self.entry if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin): self.addr_not_const() return False return True def is_lvalue(self): return ( self.entry.is_variable and not self.entry.is_readonly ) or ( self.entry.is_cfunction and self.entry.is_overridable ) def is_addressable(self): return self.entry.is_variable and not self.type.is_memoryviewslice def is_ephemeral(self): # Name nodes are never ephemeral, even if the # result is in a temporary. return 0 def calculate_result_code(self): entry = self.entry if not entry: return "" # There was an error earlier if self.entry.is_cpp_optional and not self.is_target: return "(*%s)" % entry.cname return entry.cname def generate_result_code(self, code): entry = self.entry if entry is None: return # There was an error earlier if entry.utility_code: code.globalstate.use_utility_code(entry.utility_code) if entry.is_builtin and entry.is_const: return # Lookup already cached elif entry.is_pyclass_attr: assert entry.type.is_pyobject, "Python global or builtin not a Python object" interned_cname = code.intern_identifier(self.entry.name) if entry.is_builtin: namespace = Naming.builtins_cname else: # entry.is_pyglobal namespace = entry.scope.namespace_cname if not self.cf_is_null: code.putln( '%s = PyObject_GetItem(%s, %s);' % ( self.result(), namespace, interned_cname)) code.putln('if (unlikely(!%s)) {' % self.result()) code.putln('PyErr_Clear();') code.globalstate.use_utility_code( UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c")) code.putln( '__Pyx_GetModuleGlobalName(%s, %s);' % ( self.result(), interned_cname)) if not self.cf_is_null: code.putln("}") code.putln(code.error_goto_if_null(self.result(), self.pos)) self.generate_gotref(code) elif entry.is_builtin and not entry.scope.is_module_scope: # known builtin assert entry.type.is_pyobject, "Python global or builtin not a Python object" interned_cname = code.intern_identifier(self.entry.name) code.globalstate.use_utility_code( UtilityCode.load_cached("GetBuiltinName", "ObjectHandling.c")) code.putln( '%s = __Pyx_GetBuiltinName(%s); %s' % ( self.result(), interned_cname, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) elif entry.is_pyglobal or (entry.is_builtin and entry.scope.is_module_scope): # name in class body, global name or unknown builtin assert entry.type.is_pyobject, "Python global or builtin not a Python object" interned_cname = code.intern_identifier(self.entry.name) if entry.scope.is_module_scope: code.globalstate.use_utility_code( UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c")) code.putln( '__Pyx_GetModuleGlobalName(%s, %s); %s' % ( self.result(), interned_cname, code.error_goto_if_null(self.result(), self.pos))) else: # FIXME: is_pyglobal is also used for class namespace code.globalstate.use_utility_code( UtilityCode.load_cached("GetNameInClass", "ObjectHandling.c")) code.putln( '__Pyx_GetNameInClass(%s, %s, %s); %s' % ( self.result(), entry.scope.namespace_cname, interned_cname, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) elif entry.is_local or entry.in_closure or entry.from_closure or entry.type.is_memoryviewslice: # Raise UnboundLocalError for objects and memoryviewslices raise_unbound = ( (self.cf_maybe_null or self.cf_is_null) and not self.allow_null) memslice_check = entry.type.is_memoryviewslice and self.initialized_check optional_cpp_check = entry.is_cpp_optional and self.initialized_check if optional_cpp_check: unbound_check_code = entry.type.cpp_optional_check_for_null_code(entry.cname) else: unbound_check_code = entry.type.check_for_null_code(entry.cname) if unbound_check_code and raise_unbound and (entry.type.is_pyobject or memslice_check or optional_cpp_check): code.put_error_if_unbound(self.pos, entry, self.in_nogil_context, unbound_check_code=unbound_check_code) elif entry.is_cglobal and entry.is_cpp_optional and self.initialized_check: unbound_check_code = entry.type.cpp_optional_check_for_null_code(entry.cname) code.put_error_if_unbound(self.pos, entry, unbound_check_code=unbound_check_code) def generate_assignment_code(self, rhs, code, overloaded_assignment=False, exception_check=None, exception_value=None): #print "NameNode.generate_assignment_code:", self.name ### entry = self.entry if entry is None: return # There was an error earlier if (self.entry.type.is_ptr and isinstance(rhs, ListNode) and not self.lhs_of_first_assignment and not rhs.in_module_scope): error(self.pos, "Literal list must be assigned to pointer at time of declaration") # is_pyglobal seems to be True for module level-globals only. # We use this to access class->tp_dict if necessary. if entry.is_pyglobal: assert entry.type.is_pyobject, "Python global or builtin not a Python object" interned_cname = code.intern_identifier(self.entry.name) namespace = self.entry.scope.namespace_cname if entry.is_member: # if the entry is a member we have to cheat: SetAttr does not work # on types, so we create a descriptor which is then added to tp_dict. setter = '__Pyx_SetItemOnTypeDict' elif entry.scope.is_module_scope: setter = 'PyDict_SetItem' namespace = Naming.moddict_cname elif entry.is_pyclass_attr: # Special-case setting __new__ n = "SetNewInClass" if self.name == "__new__" else "SetNameInClass" code.globalstate.use_utility_code(UtilityCode.load_cached(n, "ObjectHandling.c")) setter = '__Pyx_' + n else: assert False, repr(entry) code.put_error_if_neg( self.pos, '%s(%s, %s, %s)' % ( setter, namespace, interned_cname, rhs.py_result())) if debug_disposal_code: print("NameNode.generate_assignment_code:") print("...generating disposal code for %s" % rhs) rhs.generate_disposal_code(code) rhs.free_temps(code) if entry.is_member: # in Py2.6+, we need to invalidate the method cache code.putln("PyType_Modified(%s);" % entry.scope.parent_type.typeptr_cname) else: if self.type.is_memoryviewslice: self.generate_acquire_memoryviewslice(rhs, code) elif self.type.is_buffer: # Generate code for doing the buffer release/acquisition. # This might raise an exception in which case the assignment (done # below) will not happen. # # The reason this is not in a typetest-like node is because the # variables that the acquired buffer info is stored to is allocated # per entry and coupled with it. self.generate_acquire_buffer(rhs, code) assigned = False if self.type.is_pyobject: #print "NameNode.generate_assignment_code: to", self.name ### #print "...from", rhs ### #print "...LHS type", self.type, "ctype", self.ctype() ### #print "...RHS type", rhs.type, "ctype", rhs.ctype() ### if self.use_managed_ref: rhs.make_owned_reference(code) is_external_ref = entry.is_cglobal or self.entry.in_closure or self.entry.from_closure if is_external_ref: self.generate_gotref(code, handle_null=True) assigned = True if entry.is_cglobal: self.generate_decref_set(code, rhs.result_as(self.ctype())) else: if not self.cf_is_null: if self.cf_maybe_null: self.generate_xdecref_set(code, rhs.result_as(self.ctype())) else: self.generate_decref_set(code, rhs.result_as(self.ctype())) else: assigned = False if is_external_ref: rhs.generate_giveref(code) if not self.type.is_memoryviewslice: if not assigned: if overloaded_assignment: result = rhs.move_result_rhs() if exception_check == '+': translate_cpp_exception( code, self.pos, '%s = %s;' % (self.result(), result), self.result() if self.type.is_pyobject else None, exception_value, self.in_nogil_context) else: code.putln('%s = %s;' % (self.result(), result)) else: result = rhs.move_result_rhs_as(self.ctype()) if is_pythran_expr(self.type): code.putln('new (&%s) decltype(%s){%s};' % (self.result(), self.result(), result)) elif result != self.result(): code.putln('%s = %s;' % (self.result(), result)) if debug_disposal_code: print("NameNode.generate_assignment_code:") print("...generating post-assignment code for %s" % rhs) rhs.generate_post_assignment_code(code) elif rhs.result_in_temp(): rhs.generate_post_assignment_code(code) rhs.free_temps(code) def generate_acquire_memoryviewslice(self, rhs, code): """ Slices, coercions from objects, return values etc are new references. We have a borrowed reference in case of dst = src """ from . import MemoryView MemoryView.put_acquire_memoryviewslice( lhs_cname=self.result(), lhs_type=self.type, lhs_pos=self.pos, rhs=rhs, code=code, have_gil=not self.in_nogil_context, first_assignment=self.cf_is_null) def generate_acquire_buffer(self, rhs, code): # rhstmp is only used in case the rhs is a complicated expression leading to # the object, to avoid repeating the same C expression for every reference # to the rhs. It does NOT hold a reference. pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp if pretty_rhs: rhstmp = rhs.result_as(self.ctype()) else: rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False) code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype()))) from . import Buffer Buffer.put_assign_to_buffer(self.result(), rhstmp, self.entry, is_initialized=not self.lhs_of_first_assignment, pos=self.pos, code=code) if not pretty_rhs: code.putln("%s = 0;" % rhstmp) code.funcstate.release_temp(rhstmp) def generate_deletion_code(self, code, ignore_nonexisting=False): if self.entry is None: return # There was an error earlier elif self.entry.is_pyclass_attr: namespace = self.entry.scope.namespace_cname interned_cname = code.intern_identifier(self.entry.name) if ignore_nonexisting: key_error_code = 'PyErr_Clear(); else' else: # minor hack: fake a NameError on KeyError key_error_code = ( '{ PyErr_Clear(); PyErr_Format(PyExc_NameError, "name \'%%s\' is not defined", "%s"); }' % self.entry.name) code.putln( 'if (unlikely(PyObject_DelItem(%s, %s) < 0)) {' ' if (likely(PyErr_ExceptionMatches(PyExc_KeyError))) %s' ' %s ' '}' % (namespace, interned_cname, key_error_code, code.error_goto(self.pos))) elif self.entry.is_pyglobal: code.globalstate.use_utility_code( UtilityCode.load_cached("PyObjectSetAttrStr", "ObjectHandling.c")) interned_cname = code.intern_identifier(self.entry.name) del_code = '__Pyx_PyObject_DelAttrStr(%s, %s)' % ( Naming.module_cname, interned_cname) if ignore_nonexisting: code.putln( 'if (unlikely(%s < 0)) {' ' if (likely(PyErr_ExceptionMatches(PyExc_AttributeError))) PyErr_Clear(); else %s ' '}' % (del_code, code.error_goto(self.pos))) else: code.put_error_if_neg(self.pos, del_code) elif self.entry.type.is_pyobject or self.entry.type.is_memoryviewslice: if not self.cf_is_null: if self.cf_maybe_null and not ignore_nonexisting: code.put_error_if_unbound(self.pos, self.entry) if self.entry.in_closure: # generator self.generate_gotref(code, handle_null=True, maybe_null_extra_check=ignore_nonexisting) if ignore_nonexisting and self.cf_maybe_null: code.put_xdecref_clear(self.result(), self.ctype(), have_gil=not self.nogil) else: code.put_decref_clear(self.result(), self.ctype(), have_gil=not self.nogil) else: error(self.pos, "Deletion of C names not supported") def annotate(self, code): if getattr(self, 'is_called', False): pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1) if self.type.is_pyobject: style, text = 'py_call', 'python function (%s)' else: style, text = 'c_call', 'c function (%s)' code.annotate(pos, AnnotationItem(style, text % self.type, size=len(self.name))) def get_known_standard_library_import(self): if self.entry: return self.entry.known_standard_library_import return None class BackquoteNode(ExprNode): # `expr` # # arg ExprNode type = py_object_type subexprs = ['arg'] def analyse_types(self, env): self.arg = self.arg.analyse_types(env) self.arg = self.arg.coerce_to_pyobject(env) self.is_temp = 1 return self gil_message = "Backquote expression" def calculate_constant_result(self): self.constant_result = repr(self.arg.constant_result) def generate_result_code(self, code): code.putln( "%s = PyObject_Repr(%s); %s" % ( self.result(), self.arg.py_result(), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) class ImportNode(ExprNode): # Used as part of import statement implementation. # Implements result = # __import__(module_name, globals(), None, name_list, level) # # module_name StringNode dotted name of module. Empty module # name means importing the parent package according # to level # name_list ListNode or None list of names to be imported # level int relative import level: # -1: attempt both relative import and absolute import; # 0: absolute import; # >0: the number of parent directories to search # relative to the current module. # None: decide the level according to language level and # directives # get_top_level_module int true: return top-level module, false: return imported module # module_names TupleNode the separate names of the module and submodules, or None type = py_object_type module_names = None get_top_level_module = False is_temp = True subexprs = ['module_name', 'name_list', 'module_names'] def analyse_types(self, env): if self.level is None: # For modules in packages, and without 'absolute_import' enabled, try relative (Py2) import first. if env.global_scope().parent_module and ( env.directives['py2_import'] or Future.absolute_import not in env.global_scope().context.future_directives): self.level = -1 else: self.level = 0 module_name = self.module_name.analyse_types(env) self.module_name = module_name.coerce_to_pyobject(env) assert self.module_name.is_string_literal if self.name_list: name_list = self.name_list.analyse_types(env) self.name_list = name_list.coerce_to_pyobject(env) elif '.' in self.module_name.value: self.module_names = TupleNode(self.module_name.pos, args=[ IdentifierStringNode(self.module_name.pos, value=part, constant_result=part) for part in map(StringEncoding.EncodedString, self.module_name.value.split('.')) ]).analyse_types(env) return self gil_message = "Python import" def generate_result_code(self, code): assert self.module_name.is_string_literal module_name = self.module_name.value if self.level <= 0 and not self.name_list and not self.get_top_level_module: if self.module_names: assert self.module_names.is_literal # make sure we create the tuple only once if self.level == 0: utility_code = UtilityCode.load_cached("ImportDottedModule", "ImportExport.c") helper_func = "__Pyx_ImportDottedModule" else: utility_code = UtilityCode.load_cached("ImportDottedModuleRelFirst", "ImportExport.c") helper_func = "__Pyx_ImportDottedModuleRelFirst" code.globalstate.use_utility_code(utility_code) import_code = "%s(%s, %s)" % ( helper_func, self.module_name.py_result(), self.module_names.py_result() if self.module_names else 'NULL', ) else: code.globalstate.use_utility_code(UtilityCode.load_cached("Import", "ImportExport.c")) import_code = "__Pyx_Import(%s, %s, %d)" % ( self.module_name.py_result(), self.name_list.py_result() if self.name_list else '0', self.level) if self.level <= 0 and module_name in utility_code_for_imports: helper_func, code_name, code_file = utility_code_for_imports[module_name] code.globalstate.use_utility_code(UtilityCode.load_cached(code_name, code_file)) import_code = '%s(%s)' % (helper_func, import_code) code.putln("%s = %s; %s" % ( self.result(), import_code, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) def get_known_standard_library_import(self): return self.module_name.value class ScopedExprNode(ExprNode): # Abstract base class for ExprNodes that have their own local # scope, such as generator expressions. # # expr_scope Scope the inner scope of the expression subexprs = [] expr_scope = None # does this node really have a local scope, e.g. does it leak loop # variables or not? non-leaking Py3 behaviour is default, except # for list comprehensions where the behaviour differs in Py2 and # Py3 (set in Parsing.py based on parser context) has_local_scope = True def init_scope(self, outer_scope, expr_scope=None): if expr_scope is not None: self.expr_scope = expr_scope elif self.has_local_scope: self.expr_scope = Symtab.ComprehensionScope(outer_scope) elif not self.expr_scope: # don't unset if it's already been set self.expr_scope = None def analyse_declarations(self, env): self.init_scope(env) def analyse_scoped_declarations(self, env): # this is called with the expr_scope as env pass def analyse_types(self, env): # no recursion here, the children will be analysed separately below return self def analyse_scoped_expressions(self, env): # this is called with the expr_scope as env return self def generate_evaluation_code(self, code): # set up local variables and free their references on exit generate_inner_evaluation_code = super(ScopedExprNode, self).generate_evaluation_code if not self.has_local_scope or not self.expr_scope.var_entries: # no local variables => delegate, done generate_inner_evaluation_code(code) return code.putln('{ /* enter inner scope */') py_entries = [] for _, entry in sorted(item for item in self.expr_scope.entries.items() if item[0]): if not entry.in_closure: if entry.type.is_pyobject and entry.used: py_entries.append(entry) if not py_entries: # no local Python references => no cleanup required generate_inner_evaluation_code(code) code.putln('} /* exit inner scope */') return # must free all local Python references at each exit point old_loop_labels = code.new_loop_labels() old_error_label = code.new_error_label() generate_inner_evaluation_code(code) # normal (non-error) exit self._generate_vars_cleanup(code, py_entries) # error/loop body exit points exit_scope = code.new_label('exit_scope') code.put_goto(exit_scope) for label, old_label in ([(code.error_label, old_error_label)] + list(zip(code.get_loop_labels(), old_loop_labels))): if code.label_used(label): code.put_label(label) self._generate_vars_cleanup(code, py_entries) code.put_goto(old_label) code.put_label(exit_scope) code.putln('} /* exit inner scope */') code.set_loop_labels(old_loop_labels) code.error_label = old_error_label def _generate_vars_cleanup(self, code, py_entries): for entry in py_entries: if entry.is_cglobal: code.put_var_gotref(entry) code.put_var_decref_set(entry, "Py_None") else: code.put_var_xdecref_clear(entry) class IteratorNode(ScopedExprNode): # Used as part of for statement implementation. # # Implements result = iter(sequence) # # sequence ExprNode type = py_object_type iter_func_ptr = None counter_cname = None reversed = False # currently only used for list/tuple types (see Optimize.py) is_async = False has_local_scope = False subexprs = ['sequence'] def analyse_types(self, env): if self.expr_scope: env = self.expr_scope # actually evaluate sequence in this scope instead self.sequence = self.sequence.analyse_types(env) if (self.sequence.type.is_array or self.sequence.type.is_ptr) and \ not self.sequence.type.is_string: # C array iteration will be transformed later on self.type = self.sequence.type elif self.sequence.type.is_cpp_class: return CppIteratorNode(self.pos, sequence=self.sequence).analyse_types(env) elif self.is_reversed_cpp_iteration(): sequence = self.sequence.arg_tuple.args[0].arg return CppIteratorNode(self.pos, sequence=sequence, reversed=True).analyse_types(env) else: self.sequence = self.sequence.coerce_to_pyobject(env) if self.sequence.type in (list_type, tuple_type): self.sequence = self.sequence.as_none_safe_node("'NoneType' object is not iterable") self.is_temp = 1 return self gil_message = "Iterating over Python object" _func_iternext_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType( PyrexTypes.py_object_type, [ PyrexTypes.CFuncTypeArg("it", PyrexTypes.py_object_type, None), ])) def is_reversed_cpp_iteration(self): """ Returns True if the 'reversed' function is applied to a C++ iterable. This supports C++ classes with reverse_iterator implemented. """ if not (isinstance(self.sequence, SimpleCallNode) and self.sequence.arg_tuple and len(self.sequence.arg_tuple.args) == 1): return False func = self.sequence.function if func.is_name and func.name == "reversed": if not func.entry.is_builtin: return False arg = self.sequence.arg_tuple.args[0] if isinstance(arg, CoercionNode) and arg.arg.is_name: arg = arg.arg.entry return arg.type.is_cpp_class return False def type_dependencies(self, env): return self.sequence.type_dependencies(self.expr_scope or env) def infer_type(self, env): sequence_type = self.sequence.infer_type(env) if sequence_type.is_array or sequence_type.is_ptr: return sequence_type elif sequence_type.is_cpp_class: begin = sequence_type.scope.lookup("begin") if begin is not None: return begin.type.return_type elif sequence_type.is_pyobject: return sequence_type return py_object_type def generate_result_code(self, code): sequence_type = self.sequence.type if sequence_type.is_cpp_class: assert False, "Should have been changed to CppIteratorNode" if sequence_type.is_array or sequence_type.is_ptr: raise InternalError("for in carray slice not transformed") is_builtin_sequence = sequence_type in (list_type, tuple_type) if not is_builtin_sequence: # reversed() not currently optimised (see Optimize.py) assert not self.reversed, "internal error: reversed() only implemented for list/tuple objects" self.may_be_a_sequence = not sequence_type.is_builtin_type if self.may_be_a_sequence: code.putln( "if (likely(PyList_CheckExact(%s)) || PyTuple_CheckExact(%s)) {" % ( self.sequence.py_result(), self.sequence.py_result())) if is_builtin_sequence or self.may_be_a_sequence: code.putln("%s = %s; __Pyx_INCREF(%s);" % ( self.result(), self.sequence.py_result(), self.result(), )) self.counter_cname = code.funcstate.allocate_temp( PyrexTypes.c_py_ssize_t_type, manage_ref=False) if self.reversed: if sequence_type is list_type: len_func = '__Pyx_PyList_GET_SIZE' else: len_func = '__Pyx_PyTuple_GET_SIZE' code.putln("%s = %s(%s);" % (self.counter_cname, len_func, self.result())) code.putln("#if !CYTHON_ASSUME_SAFE_MACROS") code.putln(code.error_goto_if_neg(self.counter_cname, self.pos)) code.putln("#endif") code.putln("--%s;" % self.counter_cname) # len -> last item else: code.putln("%s = 0;" % self.counter_cname) if not is_builtin_sequence: self.iter_func_ptr = code.funcstate.allocate_temp(self._func_iternext_type, manage_ref=False) if self.may_be_a_sequence: code.putln("%s = NULL;" % self.iter_func_ptr) code.putln("} else {") code.put("%s = -1; " % self.counter_cname) code.putln("%s = PyObject_GetIter(%s); %s" % ( self.result(), self.sequence.py_result(), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) # PyObject_GetIter() fails if "tp_iternext" is not set, but the check below # makes it visible to the C compiler that the pointer really isn't NULL, so that # it can distinguish between the special cases and the generic case code.putln("%s = __Pyx_PyObject_GetIterNextFunc(%s); %s" % ( self.iter_func_ptr, self.py_result(), code.error_goto_if_null(self.iter_func_ptr, self.pos))) if self.may_be_a_sequence: code.putln("}") def generate_next_sequence_item(self, test_name, result_name, code): assert self.counter_cname, "internal error: counter_cname temp not prepared" assert test_name in ('List', 'Tuple') final_size = '__Pyx_Py%s_GET_SIZE(%s)' % (test_name, self.py_result()) size_is_safe = False if self.sequence.is_sequence_constructor: item_count = len(self.sequence.args) if self.sequence.mult_factor is None: final_size = item_count size_is_safe = True elif isinstance(self.sequence.mult_factor.constant_result, _py_int_types): final_size = item_count * self.sequence.mult_factor.constant_result size_is_safe = True if size_is_safe: code.putln("if (%s >= %s) break;" % (self.counter_cname, final_size)) else: code.putln("{") code.putln("Py_ssize_t %s = %s;" % (Naming.quick_temp_cname, final_size)) code.putln("#if !CYTHON_ASSUME_SAFE_MACROS") code.putln(code.error_goto_if_neg(Naming.quick_temp_cname, self.pos)) code.putln("#endif") code.putln("if (%s >= %s) break;" % (self.counter_cname, Naming.quick_temp_cname)) code.putln("}") if self.reversed: inc_dec = '--' else: inc_dec = '++' code.putln("#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS") code.putln( "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s%s; %s" % ( result_name, test_name, self.py_result(), self.counter_cname, result_name, self.counter_cname, inc_dec, # use the error label to avoid C compiler warnings if we only use it below code.error_goto_if_neg('0', self.pos) )) code.putln("#else") code.putln( "%s = __Pyx_PySequence_ITEM(%s, %s); %s%s; %s" % ( result_name, self.py_result(), self.counter_cname, self.counter_cname, inc_dec, code.error_goto_if_null(result_name, self.pos))) code.put_gotref(result_name, py_object_type) code.putln("#endif") def generate_iter_next_result_code(self, result_name, code): sequence_type = self.sequence.type if self.reversed: code.putln("if (%s < 0) break;" % self.counter_cname) if sequence_type is list_type: self.generate_next_sequence_item('List', result_name, code) return elif sequence_type is tuple_type: self.generate_next_sequence_item('Tuple', result_name, code) return if self.may_be_a_sequence: code.putln("if (likely(!%s)) {" % self.iter_func_ptr) code.putln("if (likely(PyList_CheckExact(%s))) {" % self.py_result()) self.generate_next_sequence_item('List', result_name, code) code.putln("} else {") self.generate_next_sequence_item('Tuple', result_name, code) code.putln("}") code.put("} else ") code.putln("{") code.putln( "%s = %s(%s);" % ( result_name, self.iter_func_ptr, self.py_result())) code.putln("if (unlikely(!%s)) {" % result_name) code.putln("PyObject* exc_type = PyErr_Occurred();") code.putln("if (exc_type) {") code.putln("if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();") code.putln("else %s" % code.error_goto(self.pos)) code.putln("}") code.putln("break;") code.putln("}") code.put_gotref(result_name, py_object_type) code.putln("}") def free_temps(self, code): if self.counter_cname: code.funcstate.release_temp(self.counter_cname) if self.iter_func_ptr: code.funcstate.release_temp(self.iter_func_ptr) self.iter_func_ptr = None ExprNode.free_temps(self, code) class CppIteratorNode(ExprNode): # Iteration over a C++ container. # Created at the analyse_types stage by IteratorNode cpp_sequence_cname = None cpp_attribute_op = "." extra_dereference = "" is_temp = True reversed = False subexprs = ['sequence'] def get_iterator_func_names(self): return ("begin", "end") if not self.reversed else ("rbegin", "rend") def analyse_types(self, env): sequence_type = self.sequence.type if sequence_type.is_ptr: sequence_type = sequence_type.base_type begin_name, end_name = self.get_iterator_func_names() begin = sequence_type.scope.lookup(begin_name) end = sequence_type.scope.lookup(end_name) if (begin is None or not begin.type.is_cfunction or begin.type.args): error(self.pos, "missing %s() on %s" % (begin_name, self.sequence.type)) self.type = error_type return self if (end is None or not end.type.is_cfunction or end.type.args): error(self.pos, "missing %s() on %s" % (end_name, self.sequence.type)) self.type = error_type return self iter_type = begin.type.return_type if iter_type.is_cpp_class: if env.directives['cpp_locals']: self.extra_dereference = "*" if env.lookup_operator_for_types( self.pos, "!=", [iter_type, end.type.return_type]) is None: error(self.pos, "missing operator!= on result of %s() on %s" % (begin_name, self.sequence.type)) self.type = error_type return self if env.lookup_operator_for_types(self.pos, '++', [iter_type]) is None: error(self.pos, "missing operator++ on result of %s() on %s" % (begin_name, self.sequence.type)) self.type = error_type return self if env.lookup_operator_for_types(self.pos, '*', [iter_type]) is None: error(self.pos, "missing operator* on result of %s() on %s" % (begin_name, self.sequence.type)) self.type = error_type return self self.type = iter_type elif iter_type.is_ptr: if not (iter_type == end.type.return_type): error(self.pos, "incompatible types for %s() and %s()" % (begin_name, end_name)) self.type = iter_type else: error(self.pos, "result type of %s() on %s must be a C++ class or pointer" % (begin_name, self.sequence.type)) self.type = error_type return self def generate_result_code(self, code): sequence_type = self.sequence.type begin_name, _ = self.get_iterator_func_names() # essentially 3 options: if self.sequence.is_simple(): # 1) Sequence can be accessed directly, like a name; # assigning to it may break the container, but that's the responsibility # of the user code.putln("%s = %s%s%s();" % ( self.result(), self.sequence.result(), self.cpp_attribute_op, begin_name)) else: # (while it'd be nice to limit the scope of the loop temp, it's essentially # impossible to do while supporting generators) temp_type = sequence_type if temp_type.is_reference: # 2) Sequence is a reference (often obtained by dereferencing a pointer); # make the temp a pointer so we are not sensitive to users reassigning # the pointer than it came from temp_type = PyrexTypes.CPtrType(sequence_type.ref_base_type) if temp_type.is_ptr or code.globalstate.directives['cpp_locals']: self.cpp_attribute_op = "->" # 3) (otherwise) sequence comes from a function call or similar, so we must # create a temp to store it in self.cpp_sequence_cname = code.funcstate.allocate_temp(temp_type, manage_ref=False) code.putln("%s = %s%s;" % (self.cpp_sequence_cname, "&" if temp_type.is_ptr else "", self.sequence.move_result_rhs())) code.putln("%s = %s%s%s();" % ( self.result(), self.cpp_sequence_cname, self.cpp_attribute_op, begin_name)) def generate_iter_next_result_code(self, result_name, code): # end call isn't cached to support containers that allow adding while iterating # (much as this is usually a bad idea) _, end_name = self.get_iterator_func_names() code.putln("if (!(%s%s != %s%s%s())) break;" % ( self.extra_dereference, self.result(), self.cpp_sequence_cname or self.sequence.result(), self.cpp_attribute_op, end_name)) code.putln("%s = *%s%s;" % ( result_name, self.extra_dereference, self.result())) code.putln("++%s%s;" % (self.extra_dereference, self.result())) def generate_subexpr_disposal_code(self, code): if not self.cpp_sequence_cname: # the sequence is accessed directly so any temporary result in its # subexpressions must remain available until the iterator is not needed return ExprNode.generate_subexpr_disposal_code(self, code) def free_subexpr_temps(self, code): if not self.cpp_sequence_cname: # the sequence is accessed directly so any temporary result in its # subexpressions must remain available until the iterator is not needed return ExprNode.free_subexpr_temps(self, code) def generate_disposal_code(self, code): if not self.cpp_sequence_cname: # postponed from CppIteratorNode.generate_subexpr_disposal_code # and CppIteratorNode.free_subexpr_temps ExprNode.generate_subexpr_disposal_code(self, code) ExprNode.free_subexpr_temps(self, code) ExprNode.generate_disposal_code(self, code) def free_temps(self, code): if self.cpp_sequence_cname: code.funcstate.release_temp(self.cpp_sequence_cname) # skip over IteratorNode since we don't use any of the temps it does ExprNode.free_temps(self, code) class NextNode(AtomicExprNode): # Used as part of for statement implementation. # Implements result = next(iterator) # Created during analyse_types phase. # The iterator is not owned by this node. # # iterator IteratorNode def __init__(self, iterator): AtomicExprNode.__init__(self, iterator.pos) self.iterator = iterator def nogil_check(self, env): # ignore - errors (if any) are already handled by IteratorNode pass def type_dependencies(self, env): return self.iterator.type_dependencies(env) def infer_type(self, env, iterator_type=None): if iterator_type is None: iterator_type = self.iterator.infer_type(env) if iterator_type.is_ptr or iterator_type.is_array: return iterator_type.base_type elif iterator_type.is_cpp_class: item_type = env.lookup_operator_for_types(self.pos, "*", [iterator_type]).type.return_type item_type = PyrexTypes.remove_cv_ref(item_type, remove_fakeref=True) return item_type else: # Avoid duplication of complicated logic. fake_index_node = IndexNode( self.pos, base=self.iterator.sequence, index=IntNode(self.pos, value='PY_SSIZE_T_MAX', type=PyrexTypes.c_py_ssize_t_type)) return fake_index_node.infer_type(env) def analyse_types(self, env): self.type = self.infer_type(env, self.iterator.type) self.is_temp = 1 return self def generate_result_code(self, code): self.iterator.generate_iter_next_result_code(self.result(), code) class AsyncIteratorNode(ScopedExprNode): # Used as part of 'async for' statement implementation. # # Implements result = sequence.__aiter__() # # sequence ExprNode subexprs = ['sequence'] is_async = True type = py_object_type is_temp = 1 has_local_scope = False def infer_type(self, env): return py_object_type def analyse_types(self, env): if self.expr_scope: env = self.expr_scope self.sequence = self.sequence.analyse_types(env) if not self.sequence.type.is_pyobject: error(self.pos, "async for loops not allowed on C/C++ types") self.sequence = self.sequence.coerce_to_pyobject(env) return self def generate_result_code(self, code): code.globalstate.use_utility_code(UtilityCode.load_cached("AsyncIter", "Coroutine.c")) code.putln("%s = __Pyx_Coroutine_GetAsyncIter(%s); %s" % ( self.result(), self.sequence.py_result(), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) class AsyncNextNode(AtomicExprNode): # Used as part of 'async for' statement implementation. # Implements result = iterator.__anext__() # Created during analyse_types phase. # The iterator is not owned by this node. # # iterator IteratorNode type = py_object_type is_temp = 1 def __init__(self, iterator): AtomicExprNode.__init__(self, iterator.pos) self.iterator = iterator def infer_type(self, env): return py_object_type def analyse_types(self, env): return self def generate_result_code(self, code): code.globalstate.use_utility_code(UtilityCode.load_cached("AsyncIter", "Coroutine.c")) code.putln("%s = __Pyx_Coroutine_AsyncIterNext(%s); %s" % ( self.result(), self.iterator.py_result(), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) class WithExitCallNode(ExprNode): # The __exit__() call of a 'with' statement. Used in both the # except and finally clauses. # with_stat WithStatNode the surrounding 'with' statement # args TupleNode or ResultStatNode the exception info tuple # await_expr AwaitExprNode the await expression of an 'async with' statement subexprs = ['args', 'await_expr'] test_if_run = True await_expr = None def analyse_types(self, env): self.args = self.args.analyse_types(env) if self.await_expr: self.await_expr = self.await_expr.analyse_types(env) self.type = PyrexTypes.c_bint_type self.is_temp = True return self def generate_evaluation_code(self, code): if self.test_if_run: # call only if it was not already called (and decref-cleared) code.putln("if (%s) {" % self.with_stat.exit_var) self.args.generate_evaluation_code(code) result_var = code.funcstate.allocate_temp(py_object_type, manage_ref=False) code.mark_pos(self.pos) code.globalstate.use_utility_code(UtilityCode.load_cached( "PyObjectCall", "ObjectHandling.c")) code.putln("%s = __Pyx_PyObject_Call(%s, %s, NULL);" % ( result_var, self.with_stat.exit_var, self.args.result())) code.put_decref_clear(self.with_stat.exit_var, type=py_object_type) self.args.generate_disposal_code(code) self.args.free_temps(code) code.putln(code.error_goto_if_null(result_var, self.pos)) code.put_gotref(result_var, py_object_type) if self.await_expr: # FIXME: result_var temp currently leaks into the closure self.await_expr.generate_evaluation_code(code, source_cname=result_var, decref_source=True) code.putln("%s = %s;" % (result_var, self.await_expr.py_result())) self.await_expr.generate_post_assignment_code(code) self.await_expr.free_temps(code) if self.result_is_used: self.allocate_temp_result(code) code.putln("%s = __Pyx_PyObject_IsTrue(%s);" % (self.result(), result_var)) code.put_decref_clear(result_var, type=py_object_type) if self.result_is_used: code.put_error_if_neg(self.pos, self.result()) code.funcstate.release_temp(result_var) if self.test_if_run: code.putln("}") class ExcValueNode(AtomicExprNode): # Node created during analyse_types phase # of an ExceptClauseNode to fetch the current # exception value. type = py_object_type def __init__(self, pos): ExprNode.__init__(self, pos) def set_var(self, var): self.var = var def calculate_result_code(self): return self.var def generate_result_code(self, code): pass def analyse_types(self, env): return self class TempNode(ExprNode): # Node created during analyse_types phase # of some nodes to hold a temporary value. # # Note: One must call "allocate" and "release" on # the node during code generation to get/release the temp. # This is because the temp result is often used outside of # the regular cycle. subexprs = [] def __init__(self, pos, type, env=None): ExprNode.__init__(self, pos) self.type = type if type.is_pyobject: self.result_ctype = py_object_type self.is_temp = 1 def analyse_types(self, env): return self def analyse_target_declaration(self, env): self.is_target = True def generate_result_code(self, code): pass def allocate(self, code): self.temp_cname = code.funcstate.allocate_temp(self.type, manage_ref=True) def release(self, code): code.funcstate.release_temp(self.temp_cname) self.temp_cname = None def result(self): try: return self.temp_cname except: assert False, "Remember to call allocate/release on TempNode" raise # Do not participate in normal temp alloc/dealloc: def allocate_temp_result(self, code): pass def release_temp_result(self, code): pass class PyTempNode(TempNode): # TempNode holding a Python value. def __init__(self, pos, env): TempNode.__init__(self, pos, PyrexTypes.py_object_type, env) class RawCNameExprNode(ExprNode): subexprs = [] def __init__(self, pos, type=None, cname=None): ExprNode.__init__(self, pos, type=type) if cname is not None: self.cname = cname def analyse_types(self, env): return self def set_cname(self, cname): self.cname = cname def result(self): return self.cname def generate_result_code(self, code): pass #------------------------------------------------------------------- # # F-strings # #------------------------------------------------------------------- class JoinedStrNode(ExprNode): # F-strings # # values [UnicodeNode|FormattedValueNode] Substrings of the f-string # type = unicode_type is_temp = True gil_message = "String concatenation" subexprs = ['values'] def analyse_types(self, env): self.values = [v.analyse_types(env).coerce_to_pyobject(env) for v in self.values] return self def may_be_none(self): # PyUnicode_Join() always returns a Unicode string or raises an exception return False def generate_evaluation_code(self, code): code.mark_pos(self.pos) num_items = len(self.values) list_var = code.funcstate.allocate_temp(py_object_type, manage_ref=True) ulength_var = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False) max_char_var = code.funcstate.allocate_temp(PyrexTypes.c_py_ucs4_type, manage_ref=False) code.putln('%s = PyTuple_New(%s); %s' % ( list_var, num_items, code.error_goto_if_null(list_var, self.pos))) code.put_gotref(list_var, py_object_type) code.putln("%s = 0;" % ulength_var) code.putln("%s = 127;" % max_char_var) # at least ASCII character range for i, node in enumerate(self.values): node.generate_evaluation_code(code) node.make_owned_reference(code) ulength = "__Pyx_PyUnicode_GET_LENGTH(%s)" % node.py_result() max_char_value = "__Pyx_PyUnicode_MAX_CHAR_VALUE(%s)" % node.py_result() is_ascii = False if isinstance(node, UnicodeNode): try: # most strings will be ASCII or at least Latin-1 node.value.encode('iso8859-1') max_char_value = '255' node.value.encode('us-ascii') is_ascii = True except UnicodeEncodeError: if max_char_value != '255': # not ISO8859-1 => check BMP limit max_char = max(map(ord, node.value)) if max_char < 0xD800: # BMP-only, no surrogate pairs used max_char_value = '65535' ulength = str(len(node.value)) elif max_char >= 65536: # clearly outside of BMP, and not on a 16-bit Unicode system max_char_value = '1114111' ulength = str(len(node.value)) else: # not really worth implementing a check for surrogate pairs here # drawback: C code can differ when generating on Py2 with 2-byte Unicode pass else: ulength = str(len(node.value)) elif isinstance(node, FormattedValueNode) and node.value.type.is_numeric: is_ascii = True # formatted C numbers are always ASCII if not is_ascii: code.putln("%s = (%s > %s) ? %s : %s;" % ( max_char_var, max_char_value, max_char_var, max_char_value, max_char_var)) code.putln("%s += %s;" % (ulength_var, ulength)) node.generate_giveref(code) code.putln('PyTuple_SET_ITEM(%s, %s, %s);' % (list_var, i, node.py_result())) node.generate_post_assignment_code(code) node.free_temps(code) code.mark_pos(self.pos) self.allocate_temp_result(code) code.globalstate.use_utility_code(UtilityCode.load_cached("JoinPyUnicode", "StringTools.c")) code.putln('%s = __Pyx_PyUnicode_Join(%s, %d, %s, %s); %s' % ( self.result(), list_var, num_items, ulength_var, max_char_var, code.error_goto_if_null(self.py_result(), self.pos))) self.generate_gotref(code) code.put_decref_clear(list_var, py_object_type) code.funcstate.release_temp(list_var) code.funcstate.release_temp(ulength_var) code.funcstate.release_temp(max_char_var) class FormattedValueNode(ExprNode): # {}-delimited portions of an f-string # # value ExprNode The expression itself # conversion_char str or None Type conversion (!s, !r, !a, none, or 'd' for integer conversion) # format_spec JoinedStrNode or None Format string passed to __format__ # c_format_spec str or None If not None, formatting can be done at the C level subexprs = ['value', 'format_spec'] type = unicode_type is_temp = True c_format_spec = None gil_message = "String formatting" find_conversion_func = { 's': 'PyObject_Unicode', 'r': 'PyObject_Repr', 'a': 'PyObject_ASCII', # NOTE: mapped to PyObject_Repr() in Py2 'd': '__Pyx_PyNumber_IntOrLong', # NOTE: internal mapping for '%d' formatting }.get def may_be_none(self): # PyObject_Format() always returns a Unicode string or raises an exception return False def analyse_types(self, env): self.value = self.value.analyse_types(env) if not self.format_spec or self.format_spec.is_string_literal: c_format_spec = self.format_spec.value if self.format_spec else self.value.type.default_format_spec if self.value.type.can_coerce_to_pystring(env, format_spec=c_format_spec): self.c_format_spec = c_format_spec if self.format_spec: self.format_spec = self.format_spec.analyse_types(env).coerce_to_pyobject(env) if self.c_format_spec is None: self.value = self.value.coerce_to_pyobject(env) if not self.format_spec and (not self.conversion_char or self.conversion_char == 's'): if self.value.type is unicode_type and not self.value.may_be_none(): # value is definitely a unicode string and we don't format it any special return self.value return self def generate_result_code(self, code): if self.c_format_spec is not None and not self.value.type.is_pyobject: convert_func_call = self.value.type.convert_to_pystring( self.value.result(), code, self.c_format_spec) code.putln("%s = %s; %s" % ( self.result(), convert_func_call, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) return value_result = self.value.py_result() value_is_unicode = self.value.type is unicode_type and not self.value.may_be_none() if self.format_spec: format_func = '__Pyx_PyObject_Format' format_spec = self.format_spec.py_result() else: # common case: expect simple Unicode pass-through if no format spec format_func = '__Pyx_PyObject_FormatSimple' # passing a Unicode format string in Py2 forces PyObject_Format() to also return a Unicode string format_spec = Naming.empty_unicode conversion_char = self.conversion_char if conversion_char == 's' and value_is_unicode: # no need to pipe unicode strings through str() conversion_char = None if conversion_char: fn = self.find_conversion_func(conversion_char) assert fn is not None, "invalid conversion character found: '%s'" % conversion_char value_result = '%s(%s)' % (fn, value_result) code.globalstate.use_utility_code( UtilityCode.load_cached("PyObjectFormatAndDecref", "StringTools.c")) format_func += 'AndDecref' elif self.format_spec: code.globalstate.use_utility_code( UtilityCode.load_cached("PyObjectFormat", "StringTools.c")) else: code.globalstate.use_utility_code( UtilityCode.load_cached("PyObjectFormatSimple", "StringTools.c")) code.putln("%s = %s(%s, %s); %s" % ( self.result(), format_func, value_result, format_spec, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) #------------------------------------------------------------------- # # Parallel nodes (cython.parallel.thread(savailable|id)) # #------------------------------------------------------------------- class ParallelThreadsAvailableNode(AtomicExprNode): """ Note: this is disabled and not a valid directive at this moment Implements cython.parallel.threadsavailable(). If we are called from the sequential part of the application, we need to call omp_get_max_threads(), and in the parallel part we can just call omp_get_num_threads() """ type = PyrexTypes.c_int_type def analyse_types(self, env): self.is_temp = True # env.add_include_file("omp.h") return self def generate_result_code(self, code): code.putln("#ifdef _OPENMP") code.putln("if (omp_in_parallel()) %s = omp_get_max_threads();" % self.temp_code) code.putln("else %s = omp_get_num_threads();" % self.temp_code) code.putln("#else") code.putln("%s = 1;" % self.temp_code) code.putln("#endif") def result(self): return self.temp_code class ParallelThreadIdNode(AtomicExprNode): #, Nodes.ParallelNode): """ Implements cython.parallel.threadid() """ type = PyrexTypes.c_int_type def analyse_types(self, env): self.is_temp = True # env.add_include_file("omp.h") return self def generate_result_code(self, code): code.putln("#ifdef _OPENMP") code.putln("%s = omp_get_thread_num();" % self.temp_code) code.putln("#else") code.putln("%s = 0;" % self.temp_code) code.putln("#endif") def result(self): return self.temp_code #------------------------------------------------------------------- # # Trailer nodes # #------------------------------------------------------------------- class _IndexingBaseNode(ExprNode): # Base class for indexing nodes. # # base ExprNode the value being indexed def is_ephemeral(self): # in most cases, indexing will return a safe reference to an object in a container, # so we consider the result safe if the base object is return self.base.is_ephemeral() or self.base.type in ( basestring_type, str_type, bytes_type, bytearray_type, unicode_type) def check_const_addr(self): return self.base.check_const_addr() and self.index.check_const() def is_lvalue(self): # NOTE: references currently have both is_reference and is_ptr # set. Since pointers and references have different lvalue # rules, we must be careful to separate the two. if self.type.is_reference: if self.type.ref_base_type.is_array: # fixed-sized arrays aren't l-values return False elif self.type.is_ptr: # non-const pointers can always be reassigned return True # Just about everything else returned by the index operator # can be an lvalue. return True class IndexNode(_IndexingBaseNode): # Sequence indexing. # # base ExprNode # index ExprNode # type_indices [PyrexType] # # is_fused_index boolean Whether the index is used to specialize a # c(p)def function subexprs = ['base', 'index'] type_indices = None is_subscript = True is_fused_index = False def calculate_constant_result(self): self.constant_result = self.base.constant_result[self.index.constant_result] def compile_time_value(self, denv): base = self.base.compile_time_value(denv) index = self.index.compile_time_value(denv) try: return base[index] except Exception as e: self.compile_time_value_error(e) def is_simple(self): base = self.base return (base.is_simple() and self.index.is_simple() and base.type and (base.type.is_ptr or base.type.is_array)) def may_be_none(self): base_type = self.base.type if base_type: if base_type.is_string: return False if isinstance(self.index, SliceNode): # slicing! if base_type in (bytes_type, bytearray_type, str_type, unicode_type, basestring_type, list_type, tuple_type): return False return ExprNode.may_be_none(self) def analyse_target_declaration(self, env): pass def analyse_as_type(self, env): base_type = self.base.analyse_as_type(env) if base_type: if base_type.is_cpp_class or base_type.python_type_constructor_name: if self.index.is_sequence_constructor: template_values = self.index.args else: template_values = [self.index] type_node = Nodes.TemplatedTypeNode( pos=self.pos, positional_args=template_values, keyword_args=None) return type_node.analyse(env, base_type=base_type) elif self.index.is_slice or self.index.is_sequence_constructor: # memory view from . import MemoryView env.use_utility_code(MemoryView.view_utility_code) axes = [self.index] if self.index.is_slice else list(self.index.args) return PyrexTypes.MemoryViewSliceType(base_type, MemoryView.get_axes_specs(env, axes)) elif not base_type.is_pyobject: # C array index = self.index.compile_time_value(env) if index is not None: try: index = int(index) except (ValueError, TypeError): pass else: return PyrexTypes.CArrayType(base_type, index) error(self.pos, "Array size must be a compile time constant") return None def analyse_pytyping_modifiers(self, env): # Check for declaration modifiers, e.g. "typing.Optional[...]" or "dataclasses.InitVar[...]" # TODO: somehow bring this together with TemplatedTypeNode.analyse_pytyping_modifiers() modifiers = [] modifier_node = self while modifier_node.is_subscript: modifier_type = modifier_node.base.analyse_as_type(env) if (modifier_type and modifier_type.python_type_constructor_name and modifier_type.modifier_name): modifiers.append(modifier_type.modifier_name) modifier_node = modifier_node.index return modifiers def type_dependencies(self, env): return self.base.type_dependencies(env) + self.index.type_dependencies(env) def infer_type(self, env): base_type = self.base.infer_type(env) if self.index.is_slice: # slicing! if base_type.is_string: # sliced C strings must coerce to Python return bytes_type elif base_type.is_pyunicode_ptr: # sliced Py_UNICODE* strings must coerce to Python return unicode_type elif base_type in (unicode_type, bytes_type, str_type, bytearray_type, list_type, tuple_type): # slicing these returns the same type return base_type elif base_type.is_memoryviewslice: return base_type else: # TODO: Handle buffers (hopefully without too much redundancy). return py_object_type index_type = self.index.infer_type(env) if index_type and index_type.is_int or isinstance(self.index, IntNode): # indexing! if base_type is unicode_type: # Py_UCS4 will automatically coerce to a unicode string # if required, so this is safe. We only infer Py_UCS4 # when the index is a C integer type. Otherwise, we may # need to use normal Python item access, in which case # it's faster to return the one-char unicode string than # to receive it, throw it away, and potentially rebuild it # on a subsequent PyObject coercion. return PyrexTypes.c_py_ucs4_type elif base_type is str_type: # always returns str - Py2: bytes, Py3: unicode return base_type elif base_type is bytearray_type: return PyrexTypes.c_uchar_type elif isinstance(self.base, BytesNode): #if env.global_scope().context.language_level >= 3: # # inferring 'char' can be made to work in Python 3 mode # return PyrexTypes.c_char_type # Py2/3 return different types on indexing bytes objects return py_object_type elif base_type in (tuple_type, list_type): # if base is a literal, take a look at its values item_type = infer_sequence_item_type( env, self.base, self.index, seq_type=base_type) if item_type is not None: return item_type elif base_type.is_ptr or base_type.is_array: return base_type.base_type elif base_type.is_ctuple and isinstance(self.index, IntNode): if self.index.has_constant_result(): index = self.index.constant_result if index < 0: index += base_type.size if 0 <= index < base_type.size: return base_type.components[index] elif base_type.is_memoryviewslice: if base_type.ndim == 0: pass # probably an error, but definitely don't know what to do - return pyobject for now if base_type.ndim == 1: return base_type.dtype else: return PyrexTypes.MemoryViewSliceType(base_type.dtype, base_type.axes[1:]) if self.index.is_sequence_constructor and base_type.is_memoryviewslice: inferred_type = base_type for a in self.index.args: if not inferred_type.is_memoryviewslice: break # something's gone wrong inferred_type = IndexNode(self.pos, base=ExprNode(self.base.pos, type=inferred_type), index=a).infer_type(env) else: return inferred_type if base_type.is_cpp_class: class FakeOperand: def __init__(self, **kwds): self.__dict__.update(kwds) operands = [ FakeOperand(pos=self.pos, type=base_type), FakeOperand(pos=self.pos, type=index_type), ] index_func = env.lookup_operator('[]', operands) if index_func is not None: return index_func.type.return_type if is_pythran_expr(base_type) and is_pythran_expr(index_type): index_with_type = (self.index, index_type) return PythranExpr(pythran_indexing_type(base_type, [index_with_type])) # may be slicing or indexing, we don't know if base_type in (unicode_type, str_type): # these types always returns their own type on Python indexing/slicing return base_type else: # TODO: Handle buffers (hopefully without too much redundancy). return py_object_type def analyse_types(self, env): return self.analyse_base_and_index_types(env, getting=True) def analyse_target_types(self, env): node = self.analyse_base_and_index_types(env, setting=True) if node.type.is_const: error(self.pos, "Assignment to const dereference") if node is self and not node.is_lvalue(): error(self.pos, "Assignment to non-lvalue of type '%s'" % node.type) return node def analyse_base_and_index_types(self, env, getting=False, setting=False, analyse_base=True): # Note: This might be cleaned up by having IndexNode # parsed in a saner way and only construct the tuple if # needed. if analyse_base: self.base = self.base.analyse_types(env) if self.base.type.is_error: # Do not visit child tree if base is undeclared to avoid confusing # error messages self.type = PyrexTypes.error_type return self is_slice = self.index.is_slice if not env.directives['wraparound']: if is_slice: check_negative_indices(self.index.start, self.index.stop) else: check_negative_indices(self.index) # Potentially overflowing index value. if not is_slice and isinstance(self.index, IntNode) and Utils.long_literal(self.index.value): self.index = self.index.coerce_to_pyobject(env) is_memslice = self.base.type.is_memoryviewslice # Handle the case where base is a literal char* (and we expect a string, not an int) if not is_memslice and (isinstance(self.base, BytesNode) or is_slice): if self.base.type.is_string or not (self.base.type.is_ptr or self.base.type.is_array): self.base = self.base.coerce_to_pyobject(env) replacement_node = self.analyse_as_buffer_operation(env, getting) if replacement_node is not None: return replacement_node self.nogil = env.nogil base_type = self.base.type if not base_type.is_cfunction: self.index = self.index.analyse_types(env) self.original_index_type = self.index.type if self.original_index_type.is_reference: self.original_index_type = self.original_index_type.ref_base_type if base_type.is_unicode_char: # we infer Py_UNICODE/Py_UCS4 for unicode strings in some # cases, but indexing must still work for them if setting: warning(self.pos, "cannot assign to Unicode string index", level=1) elif self.index.constant_result in (0, -1): # uchar[0] => uchar return self.base self.base = self.base.coerce_to_pyobject(env) base_type = self.base.type if base_type.is_pyobject: return self.analyse_as_pyobject(env, is_slice, getting, setting) elif base_type.is_ptr or base_type.is_array: return self.analyse_as_c_array(env, is_slice) elif base_type.is_cpp_class: return self.analyse_as_cpp(env, setting) elif base_type.is_cfunction: return self.analyse_as_c_function(env) elif base_type.is_ctuple: return self.analyse_as_c_tuple(env, getting, setting) else: error(self.pos, "Attempting to index non-array type '%s'" % base_type) self.type = PyrexTypes.error_type return self def analyse_as_pyobject(self, env, is_slice, getting, setting): base_type = self.base.type if self.index.type.is_unicode_char and base_type is not dict_type: # TODO: eventually fold into case below and remove warning, once people have adapted their code warning(self.pos, "Item lookup of unicode character codes now always converts to a Unicode string. " "Use an explicit C integer cast to get back the previous integer lookup behaviour.", level=1) self.index = self.index.coerce_to_pyobject(env) self.is_temp = 1 elif self.index.type.is_int and base_type is not dict_type: if (getting and not env.directives['boundscheck'] and (base_type in (list_type, tuple_type, bytearray_type)) and (not self.index.type.signed or not env.directives['wraparound'] or (isinstance(self.index, IntNode) and self.index.has_constant_result() and self.index.constant_result >= 0)) ): self.is_temp = 0 else: self.is_temp = 1 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env) self.original_index_type.create_to_py_utility_code(env) else: self.index = self.index.coerce_to_pyobject(env) self.is_temp = 1 if self.index.type.is_int and base_type is unicode_type: # Py_UNICODE/Py_UCS4 will automatically coerce to a unicode string # if required, so this is fast and safe self.type = PyrexTypes.c_py_ucs4_type elif self.index.type.is_int and base_type is bytearray_type: if setting: self.type = PyrexTypes.c_uchar_type else: # not using 'uchar' to enable fast and safe error reporting as '-1' self.type = PyrexTypes.c_int_type elif is_slice and base_type in (bytes_type, bytearray_type, str_type, unicode_type, list_type, tuple_type): self.type = base_type else: item_type = None if base_type in (list_type, tuple_type) and self.index.type.is_int: item_type = infer_sequence_item_type( env, self.base, self.index, seq_type=base_type) if base_type in (list_type, tuple_type, dict_type): # do the None check explicitly (not in a helper) to allow optimising it away self.base = self.base.as_none_safe_node("'NoneType' object is not subscriptable") if item_type is None or not item_type.is_pyobject: # Even if we inferred a C type as result, we will read a Python object, so trigger coercion if needed. # We could potentially use "item_type.equivalent_type" here, but that may trigger assumptions # about the actual runtime item types, rather than just their ability to coerce to the C "item_type". self.type = py_object_type else: self.type = item_type self.wrap_in_nonecheck_node(env, getting) return self def analyse_as_c_array(self, env, is_slice): base_type = self.base.type self.type = base_type.base_type if self.type.is_cpp_class: self.type = PyrexTypes.CReferenceType(self.type) if is_slice: self.type = base_type elif self.index.type.is_pyobject: self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env) elif not self.index.type.is_int: error(self.pos, "Invalid index type '%s'" % self.index.type) return self def analyse_as_cpp(self, env, setting): base_type = self.base.type function = env.lookup_operator("[]", [self.base, self.index]) if function is None: error(self.pos, "Indexing '%s' not supported for index type '%s'" % (base_type, self.index.type)) self.type = PyrexTypes.error_type self.result_code = "" return self func_type = function.type if func_type.is_ptr: func_type = func_type.base_type self.exception_check = func_type.exception_check self.exception_value = func_type.exception_value if self.exception_check: if not setting: self.is_temp = True if needs_cpp_exception_conversion(self): env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp")) self.index = self.index.coerce_to(func_type.args[0].type, env) self.type = func_type.return_type if setting and not func_type.return_type.is_reference: error(self.pos, "Can't set non-reference result '%s'" % self.type) return self def analyse_as_c_function(self, env): base_type = self.base.type if base_type.is_fused: self.parse_indexed_fused_cdef(env) else: self.type_indices = self.parse_index_as_types(env) self.index = None # FIXME: use a dedicated Node class instead of generic IndexNode if base_type.templates is None: error(self.pos, "Can only parameterize template functions.") self.type = error_type elif self.type_indices is None: # Error recorded earlier. self.type = error_type elif len(base_type.templates) != len(self.type_indices): error(self.pos, "Wrong number of template arguments: expected %s, got %s" % ( (len(base_type.templates), len(self.type_indices)))) self.type = error_type else: self.type = base_type.specialize(dict(zip(base_type.templates, self.type_indices))) # FIXME: use a dedicated Node class instead of generic IndexNode return self def analyse_as_c_tuple(self, env, getting, setting): base_type = self.base.type if isinstance(self.index, IntNode) and self.index.has_constant_result(): index = self.index.constant_result if -base_type.size <= index < base_type.size: if index < 0: index += base_type.size self.type = base_type.components[index] else: error(self.pos, "Index %s out of bounds for '%s'" % (index, base_type)) self.type = PyrexTypes.error_type return self else: self.base = self.base.coerce_to_pyobject(env) return self.analyse_base_and_index_types(env, getting=getting, setting=setting, analyse_base=False) def analyse_as_buffer_operation(self, env, getting): """ Analyse buffer indexing and memoryview indexing/slicing """ if isinstance(self.index, TupleNode): indices = self.index.args else: indices = [self.index] base = self.base base_type = base.type replacement_node = None if base_type.is_memoryviewslice: # memoryviewslice indexing or slicing from . import MemoryView if base.is_memview_slice: # For memory views, "view[i][j]" is the same as "view[i, j]" => use the latter for speed. merged_indices = base.merged_indices(indices) if merged_indices is not None: base = base.base base_type = base.type indices = merged_indices have_slices, indices, newaxes = MemoryView.unellipsify(indices, base_type.ndim) if have_slices: replacement_node = MemoryViewSliceNode(self.pos, indices=indices, base=base) else: replacement_node = MemoryViewIndexNode(self.pos, indices=indices, base=base) elif base_type.is_buffer or base_type.is_pythran_expr: if base_type.is_pythran_expr or len(indices) == base_type.ndim: # Buffer indexing is_buffer_access = True indices = [index.analyse_types(env) for index in indices] if base_type.is_pythran_expr: do_replacement = all( index.type.is_int or index.is_slice or index.type.is_pythran_expr for index in indices) if do_replacement: for i,index in enumerate(indices): if index.is_slice: index = SliceIntNode(index.pos, start=index.start, stop=index.stop, step=index.step) index = index.analyse_types(env) indices[i] = index else: do_replacement = all(index.type.is_int for index in indices) if do_replacement: replacement_node = BufferIndexNode(self.pos, indices=indices, base=base) # On cloning, indices is cloned. Otherwise, unpack index into indices. assert not isinstance(self.index, CloneNode) if replacement_node is not None: replacement_node = replacement_node.analyse_types(env, getting) return replacement_node def wrap_in_nonecheck_node(self, env, getting): if not env.directives['nonecheck'] or not self.base.may_be_none(): return self.base = self.base.as_none_safe_node("'NoneType' object is not subscriptable") def parse_index_as_types(self, env, required=True): if isinstance(self.index, TupleNode): indices = self.index.args else: indices = [self.index] type_indices = [] for index in indices: type_indices.append(index.analyse_as_type(env)) if type_indices[-1] is None: if required: error(index.pos, "not parsable as a type") return None return type_indices def parse_indexed_fused_cdef(self, env): """ Interpret fused_cdef_func[specific_type1, ...] Note that if this method is called, we are an indexed cdef function with fused argument types, and this IndexNode will be replaced by the NameNode with specific entry just after analysis of expressions by AnalyseExpressionsTransform. """ self.type = PyrexTypes.error_type self.is_fused_index = True base_type = self.base.type positions = [] if self.index.is_name or self.index.is_attribute: positions.append(self.index.pos) elif isinstance(self.index, TupleNode): for arg in self.index.args: positions.append(arg.pos) specific_types = self.parse_index_as_types(env, required=False) if specific_types is None: self.index = self.index.analyse_types(env) if not self.base.entry.as_variable: error(self.pos, "Can only index fused functions with types") else: # A cpdef function indexed with Python objects self.base.entry = self.entry = self.base.entry.as_variable self.base.type = self.type = self.entry.type self.base.is_temp = True self.is_temp = True self.entry.used = True self.is_fused_index = False return for i, type in enumerate(specific_types): specific_types[i] = type.specialize_fused(env) fused_types = base_type.get_fused_types() if len(specific_types) > len(fused_types): return error(self.pos, "Too many types specified") elif len(specific_types) < len(fused_types): t = fused_types[len(specific_types)] return error(self.pos, "Not enough types specified to specialize " "the function, %s is still fused" % t) # See if our index types form valid specializations for pos, specific_type, fused_type in zip(positions, specific_types, fused_types): if not any([specific_type.same_as(t) for t in fused_type.types]): return error(pos, "Type not in fused type") if specific_type is None or specific_type.is_error: return fused_to_specific = dict(zip(fused_types, specific_types)) type = base_type.specialize(fused_to_specific) if type.is_fused: # Only partially specific, this is invalid error(self.pos, "Index operation makes function only partially specific") else: # Fully specific, find the signature with the specialized entry for signature in self.base.type.get_all_specialized_function_types(): if type.same_as(signature): self.type = signature if self.base.is_attribute: # Pretend to be a normal attribute, for cdef extension # methods self.entry = signature.entry self.is_attribute = True self.obj = self.base.obj self.type.entry.used = True self.base.type = signature self.base.entry = signature.entry break else: # This is a bug raise InternalError("Couldn't find the right signature") gil_message = "Indexing Python object" def calculate_result_code(self): if self.base.type in (list_type, tuple_type, bytearray_type): if self.base.type is list_type: index_code = "PyList_GET_ITEM(%s, %s)" elif self.base.type is tuple_type: index_code = "PyTuple_GET_ITEM(%s, %s)" elif self.base.type is bytearray_type: index_code = "((unsigned char)(PyByteArray_AS_STRING(%s)[%s]))" else: assert False, "unexpected base type in indexing: %s" % self.base.type elif self.base.type.is_cfunction: return "%s<%s>" % ( self.base.result(), ",".join([param.empty_declaration_code() for param in self.type_indices])) elif self.base.type.is_ctuple: index = self.index.constant_result if index < 0: index += self.base.type.size return "%s.f%s" % (self.base.result(), index) else: if (self.type.is_ptr or self.type.is_array) and self.type == self.base.type: error(self.pos, "Invalid use of pointer slice") return index_code = "(%s[%s])" return index_code % (self.base.result(), self.index.result()) def extra_index_params(self, code): if self.index.type.is_int: is_list = self.base.type is list_type wraparound = ( bool(code.globalstate.directives['wraparound']) and self.original_index_type.signed and not (isinstance(self.index.constant_result, _py_int_types) and self.index.constant_result >= 0)) boundscheck = bool(code.globalstate.directives['boundscheck']) return ", %s, %d, %s, %d, %d, %d" % ( self.original_index_type.empty_declaration_code(), self.original_index_type.signed and 1 or 0, self.original_index_type.to_py_function, is_list, wraparound, boundscheck) else: return "" def generate_result_code(self, code): if not self.is_temp: # all handled in self.calculate_result_code() return utility_code = None error_value = None if self.type.is_pyobject: error_value = 'NULL' if self.index.type.is_int: if self.base.type is list_type: function = "__Pyx_GetItemInt_List" elif self.base.type is tuple_type: function = "__Pyx_GetItemInt_Tuple" else: function = "__Pyx_GetItemInt" utility_code = TempitaUtilityCode.load_cached("GetItemInt", "ObjectHandling.c") else: if self.base.type is dict_type: function = "__Pyx_PyDict_GetItem" utility_code = UtilityCode.load_cached("DictGetItem", "ObjectHandling.c") elif self.base.type is py_object_type and self.index.type in (str_type, unicode_type): # obj[str] is probably doing a dict lookup function = "__Pyx_PyObject_Dict_GetItem" utility_code = UtilityCode.load_cached("DictGetItem", "ObjectHandling.c") else: function = "__Pyx_PyObject_GetItem" code.globalstate.use_utility_code( TempitaUtilityCode.load_cached("GetItemInt", "ObjectHandling.c")) utility_code = UtilityCode.load_cached("ObjectGetItem", "ObjectHandling.c") elif self.type.is_unicode_char and self.base.type is unicode_type: assert self.index.type.is_int function = "__Pyx_GetItemInt_Unicode" error_value = '(Py_UCS4)-1' utility_code = UtilityCode.load_cached("GetItemIntUnicode", "StringTools.c") elif self.base.type is bytearray_type: assert self.index.type.is_int assert self.type.is_int function = "__Pyx_GetItemInt_ByteArray" error_value = '-1' utility_code = UtilityCode.load_cached("GetItemIntByteArray", "StringTools.c") elif not (self.base.type.is_cpp_class and self.exception_check): assert False, "unexpected type %s and base type %s for indexing (%s)" % ( self.type, self.base.type, self.pos) if utility_code is not None: code.globalstate.use_utility_code(utility_code) if self.index.type.is_int: index_code = self.index.result() else: index_code = self.index.py_result() if self.base.type.is_cpp_class and self.exception_check: translate_cpp_exception(code, self.pos, "%s = %s[%s];" % (self.result(), self.base.result(), self.index.result()), self.result() if self.type.is_pyobject else None, self.exception_value, self.in_nogil_context) else: error_check = '!%s' if error_value == 'NULL' else '%%s == %s' % error_value code.putln( "%s = %s(%s, %s%s); %s" % ( self.result(), function, self.base.py_result(), index_code, self.extra_index_params(code), code.error_goto_if(error_check % self.result(), self.pos))) if self.type.is_pyobject: self.generate_gotref(code) def generate_setitem_code(self, value_code, code): if self.index.type.is_int: if self.base.type is bytearray_type: code.globalstate.use_utility_code( UtilityCode.load_cached("SetItemIntByteArray", "StringTools.c")) function = "__Pyx_SetItemInt_ByteArray" else: code.globalstate.use_utility_code( UtilityCode.load_cached("SetItemInt", "ObjectHandling.c")) function = "__Pyx_SetItemInt" index_code = self.index.result() else: index_code = self.index.py_result() if self.base.type is dict_type: function = "PyDict_SetItem" # It would seem that we could specialized lists/tuples, but that # shouldn't happen here. # Both PyList_SetItem() and PyTuple_SetItem() take a Py_ssize_t as # index instead of an object, and bad conversion here would give # the wrong exception. Also, tuples are supposed to be immutable, # and raise a TypeError when trying to set their entries # (PyTuple_SetItem() is for creating new tuples from scratch). else: function = "PyObject_SetItem" code.putln(code.error_goto_if_neg( "%s(%s, %s, %s%s)" % ( function, self.base.py_result(), index_code, value_code, self.extra_index_params(code)), self.pos)) def generate_assignment_code(self, rhs, code, overloaded_assignment=False, exception_check=None, exception_value=None): self.generate_subexpr_evaluation_code(code) if self.type.is_pyobject: self.generate_setitem_code(rhs.py_result(), code) elif self.base.type is bytearray_type: value_code = self._check_byte_value(code, rhs) self.generate_setitem_code(value_code, code) elif self.base.type.is_cpp_class and self.exception_check and self.exception_check == '+': if overloaded_assignment and exception_check and self.exception_value != exception_value: # Handle the case that both the index operator and the assignment # operator have a c++ exception handler and they are not the same. translate_double_cpp_exception(code, self.pos, self.type, self.result(), rhs.result(), self.exception_value, exception_value, self.in_nogil_context) else: # Handle the case that only the index operator has a # c++ exception handler, or that # both exception handlers are the same. translate_cpp_exception(code, self.pos, "%s = %s;" % (self.result(), rhs.result()), self.result() if self.type.is_pyobject else None, self.exception_value, self.in_nogil_context) else: code.putln( "%s = %s;" % (self.result(), rhs.result())) self.generate_subexpr_disposal_code(code) self.free_subexpr_temps(code) rhs.generate_disposal_code(code) rhs.free_temps(code) def _check_byte_value(self, code, rhs): # TODO: should we do this generally on downcasts, or just here? assert rhs.type.is_int, repr(rhs.type) value_code = rhs.result() if rhs.has_constant_result(): if 0 <= rhs.constant_result < 256: return value_code needs_cast = True # make at least the C compiler happy warning(rhs.pos, "value outside of range(0, 256)" " when assigning to byte: %s" % rhs.constant_result, level=1) else: needs_cast = rhs.type != PyrexTypes.c_uchar_type if not self.nogil: conditions = [] if rhs.is_literal or rhs.type.signed: conditions.append('%s < 0' % value_code) if (rhs.is_literal or not (rhs.is_temp and rhs.type in ( PyrexTypes.c_uchar_type, PyrexTypes.c_char_type, PyrexTypes.c_schar_type))): conditions.append('%s > 255' % value_code) if conditions: code.putln("if (unlikely(%s)) {" % ' || '.join(conditions)) code.putln( 'PyErr_SetString(PyExc_ValueError,' ' "byte must be in range(0, 256)"); %s' % code.error_goto(self.pos)) code.putln("}") if needs_cast: value_code = '((unsigned char)%s)' % value_code return value_code def generate_deletion_code(self, code, ignore_nonexisting=False): self.generate_subexpr_evaluation_code(code) #if self.type.is_pyobject: if self.index.type.is_int: function = "__Pyx_DelItemInt" index_code = self.index.result() code.globalstate.use_utility_code( UtilityCode.load_cached("DelItemInt", "ObjectHandling.c")) else: index_code = self.index.py_result() if self.base.type is dict_type: function = "PyDict_DelItem" else: function = "PyObject_DelItem" code.putln(code.error_goto_if_neg( "%s(%s, %s%s)" % ( function, self.base.py_result(), index_code, self.extra_index_params(code)), self.pos)) self.generate_subexpr_disposal_code(code) self.free_subexpr_temps(code) class BufferIndexNode(_IndexingBaseNode): """ Indexing of buffers and memoryviews. This node is created during type analysis from IndexNode and replaces it. Attributes: base - base node being indexed indices - list of indexing expressions """ subexprs = ['base', 'indices'] is_buffer_access = True # Whether we're assigning to a buffer (in that case it needs to be writable) writable_needed = False # Any indexing temp variables that we need to clean up. index_temps = () def analyse_target_types(self, env): self.analyse_types(env, getting=False) def analyse_types(self, env, getting=True): """ Analyse types for buffer indexing only. Overridden by memoryview indexing and slicing subclasses """ # self.indices are already analyzed if not self.base.is_name and not is_pythran_expr(self.base.type): error(self.pos, "Can only index buffer variables") self.type = error_type return self if not getting: if not self.base.entry.type.writable: error(self.pos, "Writing to readonly buffer") else: self.writable_needed = True if self.base.type.is_buffer: self.base.entry.buffer_aux.writable_needed = True self.none_error_message = "'NoneType' object is not subscriptable" self.analyse_buffer_index(env, getting) self.wrap_in_nonecheck_node(env) return self def analyse_buffer_index(self, env, getting): if is_pythran_expr(self.base.type): index_with_type_list = [(idx, idx.type) for idx in self.indices] self.type = PythranExpr(pythran_indexing_type(self.base.type, index_with_type_list)) else: self.base = self.base.coerce_to_simple(env) self.type = self.base.type.dtype self.buffer_type = self.base.type if getting and (self.type.is_pyobject or self.type.is_pythran_expr): self.is_temp = True def analyse_assignment(self, rhs): """ Called by IndexNode when this node is assigned to, with the rhs of the assignment """ def wrap_in_nonecheck_node(self, env): if not env.directives['nonecheck'] or not self.base.may_be_none(): return self.base = self.base.as_none_safe_node(self.none_error_message) def nogil_check(self, env): if self.is_buffer_access or self.is_memview_index: if self.type.is_pyobject: error(self.pos, "Cannot access buffer with object dtype without gil") self.type = error_type def calculate_result_code(self): return "(*%s)" % self.buffer_ptr_code def buffer_entry(self): base = self.base if self.base.is_nonecheck: base = base.arg return base.type.get_entry(base) def get_index_in_temp(self, code, ivar): ret = code.funcstate.allocate_temp( PyrexTypes.widest_numeric_type( ivar.type, PyrexTypes.c_ssize_t_type if ivar.type.signed else PyrexTypes.c_size_t_type), manage_ref=False) code.putln("%s = %s;" % (ret, ivar.result())) return ret def buffer_lookup_code(self, code): """ ndarray[1, 2, 3] and memslice[1, 2, 3] """ if self.in_nogil_context: if self.is_buffer_access or self.is_memview_index: if code.globalstate.directives['boundscheck']: warning(self.pos, "Use boundscheck(False) for faster access", level=1) # Assign indices to temps of at least (s)size_t to allow further index calculations. self.index_temps = index_temps = [self.get_index_in_temp(code,ivar) for ivar in self.indices] # Generate buffer access code using these temps from . import Buffer buffer_entry = self.buffer_entry() if buffer_entry.type.is_buffer: negative_indices = buffer_entry.type.negative_indices else: negative_indices = Buffer.buffer_defaults['negative_indices'] return buffer_entry, Buffer.put_buffer_lookup_code( entry=buffer_entry, index_signeds=[ivar.type.signed for ivar in self.indices], index_cnames=index_temps, directives=code.globalstate.directives, pos=self.pos, code=code, negative_indices=negative_indices, in_nogil_context=self.in_nogil_context) def generate_assignment_code(self, rhs, code, overloaded_assignment=False): self.generate_subexpr_evaluation_code(code) self.generate_buffer_setitem_code(rhs, code) self.generate_subexpr_disposal_code(code) self.free_subexpr_temps(code) rhs.generate_disposal_code(code) rhs.free_temps(code) def generate_buffer_setitem_code(self, rhs, code, op=""): base_type = self.base.type if is_pythran_expr(base_type) and is_pythran_supported_type(rhs.type): obj = code.funcstate.allocate_temp(PythranExpr(pythran_type(self.base.type)), manage_ref=False) # We have got to do this because we have to declare pythran objects # at the beginning of the functions. # Indeed, Cython uses "goto" statement for error management, and # RAII doesn't work with that kind of construction. # Moreover, the way Pythran expressions are made is that they don't # support move-assignation easily. # This, we explicitly destroy then in-place new objects in this # case. code.putln("__Pyx_call_destructor(%s);" % obj) code.putln("new (&%s) decltype(%s){%s};" % (obj, obj, self.base.pythran_result())) code.putln("%s%s %s= %s;" % ( obj, pythran_indexing_code(self.indices), op, rhs.pythran_result())) code.funcstate.release_temp(obj) return # Used from generate_assignment_code and InPlaceAssignmentNode buffer_entry, ptrexpr = self.buffer_lookup_code(code) if self.buffer_type.dtype.is_pyobject: # Must manage refcounts. XDecref what is already there # and incref what we put in (NumPy allows there to be NULL) ptr = code.funcstate.allocate_temp(buffer_entry.buf_ptr_type, manage_ref=False) rhs_code = rhs.result() code.putln("%s = %s;" % (ptr, ptrexpr)) code.put_xgotref("*%s" % ptr, self.buffer_type.dtype) code.putln("__Pyx_INCREF(%s); __Pyx_XDECREF(*%s);" % ( rhs_code, ptr)) code.putln("*%s %s= %s;" % (ptr, op, rhs_code)) code.put_xgiveref("*%s" % ptr, self.buffer_type.dtype) code.funcstate.release_temp(ptr) else: # Simple case code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result())) def generate_result_code(self, code): if is_pythran_expr(self.base.type): res = self.result() code.putln("__Pyx_call_destructor(%s);" % res) code.putln("new (&%s) decltype(%s){%s%s};" % ( res, res, self.base.pythran_result(), pythran_indexing_code(self.indices))) return buffer_entry, self.buffer_ptr_code = self.buffer_lookup_code(code) if self.type.is_pyobject: # is_temp is True, so must pull out value and incref it. # NOTE: object temporary results for nodes are declared # as PyObject *, so we need a cast res = self.result() code.putln("%s = (PyObject *) *%s;" % (res, self.buffer_ptr_code)) # NumPy does (occasionally) allow NULL to denote None. code.putln("if (unlikely(%s == NULL)) %s = Py_None;" % (res, res)) code.putln("__Pyx_INCREF((PyObject*)%s);" % res) def free_subexpr_temps(self, code): for temp in self.index_temps: code.funcstate.release_temp(temp) self.index_temps = () super(BufferIndexNode, self).free_subexpr_temps(code) class MemoryViewIndexNode(BufferIndexNode): is_memview_index = True is_buffer_access = False def analyse_types(self, env, getting=True): # memoryviewslice indexing or slicing from . import MemoryView self.is_pythran_mode = has_np_pythran(env) indices = self.indices have_slices, indices, newaxes = MemoryView.unellipsify(indices, self.base.type.ndim) if not getting: self.writable_needed = True if self.base.is_name or self.base.is_attribute: self.base.entry.type.writable_needed = True self.memslice_index = (not newaxes and len(indices) == self.base.type.ndim) axes = [] index_type = PyrexTypes.c_py_ssize_t_type new_indices = [] if len(indices) - len(newaxes) > self.base.type.ndim: self.type = error_type error(indices[self.base.type.ndim].pos, "Too many indices specified for type %s" % self.base.type) return self axis_idx = 0 for i, index in enumerate(indices[:]): index = index.analyse_types(env) if index.is_none: self.is_memview_slice = True new_indices.append(index) axes.append(('direct', 'strided')) continue access, packing = self.base.type.axes[axis_idx] axis_idx += 1 if index.is_slice: self.is_memview_slice = True if index.step.is_none: axes.append((access, packing)) else: axes.append((access, 'strided')) # Coerce start, stop and step to temps of the right type for attr in ('start', 'stop', 'step'): value = getattr(index, attr) if not value.is_none: value = value.coerce_to(index_type, env) #value = value.coerce_to_temp(env) setattr(index, attr, value) new_indices.append(value) elif index.type.is_int or index.type.is_pyobject: if index.type.is_pyobject: performance_hint(index.pos, "Index should be typed for more efficient access", env) self.is_memview_index = True index = index.coerce_to(index_type, env) indices[i] = index new_indices.append(index) else: self.type = error_type error(index.pos, "Invalid index for memoryview specified, type %s" % index.type) return self ### FIXME: replace by MemoryViewSliceNode if is_memview_slice ? self.is_memview_index = self.is_memview_index and not self.is_memview_slice self.indices = new_indices # All indices with all start/stop/step for slices. # We need to keep this around. self.original_indices = indices self.nogil = env.nogil self.analyse_operation(env, getting, axes) self.wrap_in_nonecheck_node(env) return self def analyse_operation(self, env, getting, axes): self.none_error_message = "Cannot index None memoryview slice" self.analyse_buffer_index(env, getting) def analyse_broadcast_operation(self, rhs): """ Support broadcasting for slice assignment. E.g. m_2d[...] = m_1d # or, m_1d[...] = m_2d # if the leading dimension has extent 1 """ if self.type.is_memoryviewslice: lhs = self if lhs.is_memview_broadcast or rhs.is_memview_broadcast: lhs.is_memview_broadcast = True rhs.is_memview_broadcast = True def analyse_as_memview_scalar_assignment(self, rhs): lhs = self.analyse_assignment(rhs) if lhs: rhs.is_memview_copy_assignment = lhs.is_memview_copy_assignment return lhs return self class MemoryViewSliceNode(MemoryViewIndexNode): is_memview_slice = True # No-op slicing operation, this node will be replaced is_ellipsis_noop = False is_memview_scalar_assignment = False is_memview_index = False is_memview_broadcast = False def analyse_ellipsis_noop(self, env, getting): """Slicing operations needing no evaluation, i.e. m[...] or m[:, :]""" ### FIXME: replace directly self.is_ellipsis_noop = all( index.is_slice and index.start.is_none and index.stop.is_none and index.step.is_none for index in self.indices) if self.is_ellipsis_noop: self.type = self.base.type def analyse_operation(self, env, getting, axes): from . import MemoryView if not getting: self.is_memview_broadcast = True self.none_error_message = "Cannot assign to None memoryview slice" else: self.none_error_message = "Cannot slice None memoryview slice" self.analyse_ellipsis_noop(env, getting) if self.is_ellipsis_noop: return self.index = None self.is_temp = True self.use_managed_ref = True if not MemoryView.validate_axes(self.pos, axes): self.type = error_type return self.type = PyrexTypes.MemoryViewSliceType(self.base.type.dtype, axes) if not (self.base.is_simple() or self.base.result_in_temp()): self.base = self.base.coerce_to_temp(env) def analyse_assignment(self, rhs): if not rhs.type.is_memoryviewslice and ( self.type.dtype.assignable_from(rhs.type) or rhs.type.is_pyobject): # scalar assignment return MemoryCopyScalar(self.pos, self) else: return MemoryCopySlice(self.pos, self) def merged_indices(self, indices): """Return a new list of indices/slices with 'indices' merged into the current ones according to slicing rules. Is used to implement "view[i][j]" => "view[i, j]". Return None if the indices cannot (easily) be merged at compile time. """ if not indices: return None # NOTE: Need to evaluate "self.original_indices" here as they might differ from "self.indices". new_indices = self.original_indices[:] indices = indices[:] for i, s in enumerate(self.original_indices): if s.is_slice: if s.start.is_none and s.stop.is_none and s.step.is_none: # Full slice found, replace by index. new_indices[i] = indices[0] indices.pop(0) if not indices: return new_indices else: # Found something non-trivial, e.g. a partial slice. return None elif not s.type.is_int: # Not a slice, not an integer index => could be anything... return None if indices: if len(new_indices) + len(indices) > self.base.type.ndim: return None new_indices += indices return new_indices def is_simple(self): if self.is_ellipsis_noop: # TODO: fix SimpleCallNode.is_simple() return self.base.is_simple() or self.base.result_in_temp() return self.result_in_temp() def calculate_result_code(self): """This is called in case this is a no-op slicing node""" return self.base.result() def generate_result_code(self, code): if self.is_ellipsis_noop: return ### FIXME: remove buffer_entry = self.buffer_entry() have_gil = not self.in_nogil_context # TODO Mark: this is insane, do it better have_slices = False it = iter(self.indices) for index in self.original_indices: if index.is_slice: have_slices = True if not index.start.is_none: index.start = next(it) if not index.stop.is_none: index.stop = next(it) if not index.step.is_none: index.step = next(it) else: next(it) assert not list(it) buffer_entry.generate_buffer_slice_code( code, self.original_indices, self.result(), self.type, have_gil=have_gil, have_slices=have_slices, directives=code.globalstate.directives) def generate_assignment_code(self, rhs, code, overloaded_assignment=False): if self.is_ellipsis_noop: self.generate_subexpr_evaluation_code(code) else: self.generate_evaluation_code(code) if self.is_memview_scalar_assignment: self.generate_memoryviewslice_assign_scalar_code(rhs, code) else: self.generate_memoryviewslice_setslice_code(rhs, code) if self.is_ellipsis_noop: self.generate_subexpr_disposal_code(code) else: self.generate_disposal_code(code) rhs.generate_disposal_code(code) rhs.free_temps(code) class MemoryCopyNode(ExprNode): """ Wraps a memoryview slice for slice assignment. dst: destination mememoryview slice """ subexprs = ['dst'] def __init__(self, pos, dst): super(MemoryCopyNode, self).__init__(pos) self.dst = dst self.type = dst.type def generate_assignment_code(self, rhs, code, overloaded_assignment=False): self.dst.generate_evaluation_code(code) self._generate_assignment_code(rhs, code) self.dst.generate_disposal_code(code) self.dst.free_temps(code) rhs.generate_disposal_code(code) rhs.free_temps(code) class MemoryCopySlice(MemoryCopyNode): """ Copy the contents of slice src to slice dst. Does not support indirect slices. memslice1[...] = memslice2 memslice1[:] = memslice2 """ is_memview_copy_assignment = True copy_slice_cname = "__pyx_memoryview_copy_contents" def _generate_assignment_code(self, src, code): dst = self.dst src.type.assert_direct_dims(src.pos) dst.type.assert_direct_dims(dst.pos) code.putln(code.error_goto_if_neg( "%s(%s, %s, %d, %d, %d)" % (self.copy_slice_cname, src.result(), dst.result(), src.type.ndim, dst.type.ndim, dst.type.dtype.is_pyobject), dst.pos)) class MemoryCopyScalar(MemoryCopyNode): """ Assign a scalar to a slice. dst must be simple, scalar will be assigned to a correct type and not just something assignable. memslice1[...] = 0.0 memslice1[:] = 0.0 """ def __init__(self, pos, dst): super(MemoryCopyScalar, self).__init__(pos, dst) self.type = dst.type.dtype def _generate_assignment_code(self, scalar, code): from . import MemoryView self.dst.type.assert_direct_dims(self.dst.pos) dtype = self.dst.type.dtype type_decl = dtype.declaration_code("") slice_decl = self.dst.type.declaration_code("") code.begin_block() code.putln("%s __pyx_temp_scalar = %s;" % (type_decl, scalar.result())) if self.dst.result_in_temp() or self.dst.is_simple(): dst_temp = self.dst.result() else: code.putln("%s __pyx_temp_slice = %s;" % (slice_decl, self.dst.result())) dst_temp = "__pyx_temp_slice" force_strided = False indices = self.dst.original_indices for idx in indices: if isinstance(idx, SliceNode) and not (idx.start.is_none and idx.stop.is_none and idx.step.is_none): force_strided = True slice_iter_obj = MemoryView.slice_iter(self.dst.type, dst_temp, self.dst.type.ndim, code, force_strided=force_strided) p = slice_iter_obj.start_loops() if dtype.is_pyobject: code.putln("Py_DECREF(*(PyObject **) %s);" % p) code.putln("*((%s *) %s) = __pyx_temp_scalar;" % (type_decl, p)) if dtype.is_pyobject: code.putln("Py_INCREF(__pyx_temp_scalar);") slice_iter_obj.end_loops() code.end_block() class SliceIndexNode(ExprNode): # 2-element slice indexing # # base ExprNode # start ExprNode or None # stop ExprNode or None # slice ExprNode or None constant slice object # nogil bool used internally subexprs = ['base', 'start', 'stop', 'slice'] nogil = False slice = None def infer_type(self, env): base_type = self.base.infer_type(env) if base_type.is_string or base_type.is_cpp_class: return bytes_type elif base_type.is_pyunicode_ptr: return unicode_type elif base_type in (bytes_type, bytearray_type, str_type, unicode_type, basestring_type, list_type, tuple_type): return base_type elif base_type.is_ptr or base_type.is_array: return PyrexTypes.c_array_type(base_type.base_type, None) return py_object_type def inferable_item_node(self, index=0): # slicing shouldn't change the result type of the base, but the index might if index is not not_a_constant and self.start: if self.start.has_constant_result(): index += self.start.constant_result else: index = not_a_constant return self.base.inferable_item_node(index) def may_be_none(self): base_type = self.base.type if base_type: if base_type.is_string: return False if base_type in (bytes_type, str_type, unicode_type, basestring_type, list_type, tuple_type): return False return ExprNode.may_be_none(self) def calculate_constant_result(self): if self.start is None: start = None else: start = self.start.constant_result if self.stop is None: stop = None else: stop = self.stop.constant_result self.constant_result = self.base.constant_result[start:stop] def compile_time_value(self, denv): base = self.base.compile_time_value(denv) if self.start is None: start = 0 else: start = self.start.compile_time_value(denv) if self.stop is None: stop = None else: stop = self.stop.compile_time_value(denv) try: return base[start:stop] except Exception as e: self.compile_time_value_error(e) def analyse_target_declaration(self, env): pass def analyse_target_types(self, env): node = self.analyse_types(env, getting=False) # when assigning, we must accept any Python type if node.type.is_pyobject: node.type = py_object_type return node def analyse_types(self, env, getting=True): self.base = self.base.analyse_types(env) if self.base.type.is_buffer or self.base.type.is_pythran_expr or self.base.type.is_memoryviewslice: none_node = NoneNode(self.pos) index = SliceNode(self.pos, start=self.start or none_node, stop=self.stop or none_node, step=none_node) index_node = IndexNode(self.pos, index=index, base=self.base) return index_node.analyse_base_and_index_types( env, getting=getting, setting=not getting, analyse_base=False) if self.start: self.start = self.start.analyse_types(env) if self.stop: self.stop = self.stop.analyse_types(env) if not env.directives['wraparound']: check_negative_indices(self.start, self.stop) base_type = self.base.type if base_type.is_array and not getting: # cannot assign directly to C array => try to assign by making a copy if not self.start and not self.stop: self.type = base_type else: self.type = PyrexTypes.CPtrType(base_type.base_type) elif base_type.is_string or base_type.is_cpp_string: self.type = default_str_type(env) elif base_type.is_pyunicode_ptr: self.type = unicode_type elif base_type.is_ptr: self.type = base_type elif base_type.is_array: # we need a ptr type here instead of an array type, as # array types can result in invalid type casts in the C # code self.type = PyrexTypes.CPtrType(base_type.base_type) else: self.base = self.base.coerce_to_pyobject(env) self.type = py_object_type if base_type.is_builtin_type: # slicing builtin types returns something of the same type self.type = base_type self.base = self.base.as_none_safe_node("'NoneType' object is not subscriptable") if self.type is py_object_type: if (not self.start or self.start.is_literal) and \ (not self.stop or self.stop.is_literal): # cache the constant slice object, in case we need it none_node = NoneNode(self.pos) self.slice = SliceNode( self.pos, start=copy.deepcopy(self.start or none_node), stop=copy.deepcopy(self.stop or none_node), step=none_node ).analyse_types(env) else: c_int = PyrexTypes.c_py_ssize_t_type def allow_none(node, default_value, env): # Coerce to Py_ssize_t, but allow None as meaning the default slice bound. from .UtilNodes import EvalWithTempExprNode, ResultRefNode node_ref = ResultRefNode(node) new_expr = CondExprNode( node.pos, true_val=IntNode( node.pos, type=c_int, value=default_value, constant_result=int(default_value) if default_value.isdigit() else not_a_constant, ), false_val=node_ref.coerce_to(c_int, env), test=PrimaryCmpNode( node.pos, operand1=node_ref, operator='is', operand2=NoneNode(node.pos), ).analyse_types(env) ).analyse_result_type(env) return EvalWithTempExprNode(node_ref, new_expr) if self.start: if self.start.type.is_pyobject: self.start = allow_none(self.start, '0', env) self.start = self.start.coerce_to(c_int, env) if self.stop: if self.stop.type.is_pyobject: self.stop = allow_none(self.stop, 'PY_SSIZE_T_MAX', env) self.stop = self.stop.coerce_to(c_int, env) self.is_temp = 1 return self def analyse_as_type(self, env): base_type = self.base.analyse_as_type(env) if base_type: if not self.start and not self.stop: # memory view from . import MemoryView env.use_utility_code(MemoryView.view_utility_code) none_node = NoneNode(self.pos) slice_node = SliceNode( self.pos, start=none_node, stop=none_node, step=none_node, ) return PyrexTypes.MemoryViewSliceType( base_type, MemoryView.get_axes_specs(env, [slice_node])) return None def nogil_check(self, env): self.nogil = env.nogil return super(SliceIndexNode, self).nogil_check(env) gil_message = "Slicing Python object" get_slice_utility_code = TempitaUtilityCode.load( "SliceObject", "ObjectHandling.c", context={'access': 'Get'}) set_slice_utility_code = TempitaUtilityCode.load( "SliceObject", "ObjectHandling.c", context={'access': 'Set'}) def coerce_to(self, dst_type, env): if ((self.base.type.is_string or self.base.type.is_cpp_string) and dst_type in (bytes_type, bytearray_type, str_type, unicode_type)): if (dst_type not in (bytes_type, bytearray_type) and not env.directives['c_string_encoding']): error(self.pos, "default encoding required for conversion from '%s' to '%s'" % (self.base.type, dst_type)) self.type = dst_type if dst_type.is_array and self.base.type.is_array: if not self.start and not self.stop: # redundant slice building, copy C arrays directly return self.base.coerce_to(dst_type, env) # else: check array size if possible return super(SliceIndexNode, self).coerce_to(dst_type, env) def generate_result_code(self, code): if not self.type.is_pyobject: error(self.pos, "Slicing is not currently supported for '%s'." % self.type) return base_result = self.base.result() result = self.result() start_code = self.start_code() stop_code = self.stop_code() if self.base.type.is_string: base_result = self.base.result() if self.base.type not in (PyrexTypes.c_char_ptr_type, PyrexTypes.c_const_char_ptr_type): base_result = '((const char*)%s)' % base_result if self.type is bytearray_type: type_name = 'ByteArray' else: type_name = self.type.name.title() if self.stop is None: code.putln( "%s = __Pyx_Py%s_FromString(%s + %s); %s" % ( result, type_name, base_result, start_code, code.error_goto_if_null(result, self.pos))) else: code.putln( "%s = __Pyx_Py%s_FromStringAndSize(%s + %s, %s - %s); %s" % ( result, type_name, base_result, start_code, stop_code, start_code, code.error_goto_if_null(result, self.pos))) elif self.base.type.is_pyunicode_ptr: base_result = self.base.result() if self.base.type != PyrexTypes.c_py_unicode_ptr_type: base_result = '((const Py_UNICODE*)%s)' % base_result if self.stop is None: code.putln( "%s = __Pyx_PyUnicode_FromUnicode(%s + %s); %s" % ( result, base_result, start_code, code.error_goto_if_null(result, self.pos))) else: code.putln( "%s = __Pyx_PyUnicode_FromUnicodeAndLength(%s + %s, %s - %s); %s" % ( result, base_result, start_code, stop_code, start_code, code.error_goto_if_null(result, self.pos))) elif self.base.type is unicode_type: code.globalstate.use_utility_code( UtilityCode.load_cached("PyUnicode_Substring", "StringTools.c")) code.putln( "%s = __Pyx_PyUnicode_Substring(%s, %s, %s); %s" % ( result, base_result, start_code, stop_code, code.error_goto_if_null(result, self.pos))) elif self.type is py_object_type: code.globalstate.use_utility_code(self.get_slice_utility_code) (has_c_start, has_c_stop, c_start, c_stop, py_start, py_stop, py_slice) = self.get_slice_config() code.putln( "%s = __Pyx_PyObject_GetSlice(%s, %s, %s, %s, %s, %s, %d, %d, %d); %s" % ( result, self.base.py_result(), c_start, c_stop, py_start, py_stop, py_slice, has_c_start, has_c_stop, bool(code.globalstate.directives['wraparound']), code.error_goto_if_null(result, self.pos))) else: if self.base.type is list_type: code.globalstate.use_utility_code( TempitaUtilityCode.load_cached("SliceTupleAndList", "ObjectHandling.c")) cfunc = '__Pyx_PyList_GetSlice' elif self.base.type is tuple_type: code.globalstate.use_utility_code( TempitaUtilityCode.load_cached("SliceTupleAndList", "ObjectHandling.c")) cfunc = '__Pyx_PyTuple_GetSlice' else: cfunc = 'PySequence_GetSlice' code.putln( "%s = %s(%s, %s, %s); %s" % ( result, cfunc, self.base.py_result(), start_code, stop_code, code.error_goto_if_null(result, self.pos))) self.generate_gotref(code) def generate_assignment_code(self, rhs, code, overloaded_assignment=False, exception_check=None, exception_value=None): self.generate_subexpr_evaluation_code(code) if self.type.is_pyobject: code.globalstate.use_utility_code(self.set_slice_utility_code) has_c_start, has_c_stop, c_start, c_stop, py_start, py_stop, py_slice = self.get_slice_config() code.put_error_if_neg(self.pos, "__Pyx_PyObject_SetSlice(%s, %s, %s, %s, %s, %s, %s, %d, %d, %d)" % ( self.base.py_result(), rhs.py_result(), c_start, c_stop, py_start, py_stop, py_slice, has_c_start, has_c_stop, bool(code.globalstate.directives['wraparound']))) else: start_offset = self.start_code() if self.start else '0' if rhs.type.is_array: array_length = rhs.type.size self.generate_slice_guard_code(code, array_length) else: array_length = '%s - %s' % (self.stop_code(), start_offset) code.globalstate.use_utility_code(UtilityCode.load_cached("IncludeStringH", "StringTools.c")) code.putln("memcpy(&(%s[%s]), %s, sizeof(%s[0]) * (%s));" % ( self.base.result(), start_offset, rhs.result(), self.base.result(), array_length )) self.generate_subexpr_disposal_code(code) self.free_subexpr_temps(code) rhs.generate_disposal_code(code) rhs.free_temps(code) def generate_deletion_code(self, code, ignore_nonexisting=False): if not self.base.type.is_pyobject: error(self.pos, "Deleting slices is only supported for Python types, not '%s'." % self.type) return self.generate_subexpr_evaluation_code(code) code.globalstate.use_utility_code(self.set_slice_utility_code) (has_c_start, has_c_stop, c_start, c_stop, py_start, py_stop, py_slice) = self.get_slice_config() code.put_error_if_neg(self.pos, "__Pyx_PyObject_DelSlice(%s, %s, %s, %s, %s, %s, %d, %d, %d)" % ( self.base.py_result(), c_start, c_stop, py_start, py_stop, py_slice, has_c_start, has_c_stop, bool(code.globalstate.directives['wraparound']))) self.generate_subexpr_disposal_code(code) self.free_subexpr_temps(code) def get_slice_config(self): has_c_start, c_start, py_start = False, '0', 'NULL' if self.start: has_c_start = not self.start.type.is_pyobject if has_c_start: c_start = self.start.result() else: py_start = '&%s' % self.start.py_result() has_c_stop, c_stop, py_stop = False, '0', 'NULL' if self.stop: has_c_stop = not self.stop.type.is_pyobject if has_c_stop: c_stop = self.stop.result() else: py_stop = '&%s' % self.stop.py_result() py_slice = self.slice and '&%s' % self.slice.py_result() or 'NULL' return (has_c_start, has_c_stop, c_start, c_stop, py_start, py_stop, py_slice) def generate_slice_guard_code(self, code, target_size): if not self.base.type.is_array: return slice_size = self.base.type.size try: total_length = slice_size = int(slice_size) except ValueError: total_length = None start = stop = None if self.stop: stop = self.stop.result() try: stop = int(stop) if stop < 0: if total_length is None: slice_size = '%s + %d' % (slice_size, stop) else: slice_size += stop else: slice_size = stop stop = None except ValueError: pass if self.start: start = self.start.result() try: start = int(start) if start < 0: if total_length is None: start = '%s + %d' % (self.base.type.size, start) else: start += total_length if isinstance(slice_size, _py_int_types): slice_size -= start else: slice_size = '%s - (%s)' % (slice_size, start) start = None except ValueError: pass runtime_check = None compile_time_check = False try: int_target_size = int(target_size) except ValueError: int_target_size = None else: compile_time_check = isinstance(slice_size, _py_int_types) if compile_time_check and slice_size < 0: if int_target_size > 0: error(self.pos, "Assignment to empty slice.") elif compile_time_check and start is None and stop is None: # we know the exact slice length if int_target_size != slice_size: error(self.pos, "Assignment to slice of wrong length, expected %s, got %s" % ( slice_size, target_size)) elif start is not None: if stop is None: stop = slice_size runtime_check = "(%s)-(%s)" % (stop, start) elif stop is not None: runtime_check = stop else: runtime_check = slice_size if runtime_check: code.putln("if (unlikely((%s) != (%s))) {" % (runtime_check, target_size)) if self.nogil: code.put_ensure_gil() code.putln( 'PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length,' ' expected %%" CYTHON_FORMAT_SSIZE_T "d, got %%" CYTHON_FORMAT_SSIZE_T "d",' ' (Py_ssize_t)(%s), (Py_ssize_t)(%s));' % ( target_size, runtime_check)) if self.nogil: code.put_release_ensured_gil() code.putln(code.error_goto(self.pos)) code.putln("}") def start_code(self): if self.start: return self.start.result() else: return "0" def stop_code(self): if self.stop: return self.stop.result() elif self.base.type.is_array: return self.base.type.size else: return "PY_SSIZE_T_MAX" def calculate_result_code(self): # self.result() is not used, but this method must exist return "" class SliceNode(ExprNode): # start:stop:step in subscript list # # start ExprNode # stop ExprNode # step ExprNode subexprs = ['start', 'stop', 'step'] is_slice = True type = slice_type is_temp = 1 def calculate_constant_result(self): self.constant_result = slice( self.start.constant_result, self.stop.constant_result, self.step.constant_result) def compile_time_value(self, denv): start = self.start.compile_time_value(denv) stop = self.stop.compile_time_value(denv) step = self.step.compile_time_value(denv) try: return slice(start, stop, step) except Exception as e: self.compile_time_value_error(e) def may_be_none(self): return False def analyse_types(self, env): start = self.start.analyse_types(env) stop = self.stop.analyse_types(env) step = self.step.analyse_types(env) self.start = start.coerce_to_pyobject(env) self.stop = stop.coerce_to_pyobject(env) self.step = step.coerce_to_pyobject(env) if self.start.is_literal and self.stop.is_literal and self.step.is_literal: self.is_literal = True self.is_temp = False return self gil_message = "Constructing Python slice object" def calculate_result_code(self): return self.result_code def generate_result_code(self, code): if self.is_literal: dedup_key = make_dedup_key(self.type, (self,)) self.result_code = code.get_py_const(py_object_type, 'slice', cleanup_level=2, dedup_key=dedup_key) code = code.get_cached_constants_writer(self.result_code) if code is None: return # already initialised code.mark_pos(self.pos) code.putln( "%s = PySlice_New(%s, %s, %s); %s" % ( self.result(), self.start.py_result(), self.stop.py_result(), self.step.py_result(), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) if self.is_literal: self.generate_giveref(code) class SliceIntNode(SliceNode): # start:stop:step in subscript list # This is just a node to hold start,stop and step nodes that can be # converted to integers. This does not generate a slice python object. # # start ExprNode # stop ExprNode # step ExprNode is_temp = 0 def calculate_constant_result(self): self.constant_result = slice( self.start.constant_result, self.stop.constant_result, self.step.constant_result) def compile_time_value(self, denv): start = self.start.compile_time_value(denv) stop = self.stop.compile_time_value(denv) step = self.step.compile_time_value(denv) try: return slice(start, stop, step) except Exception as e: self.compile_time_value_error(e) def may_be_none(self): return False def analyse_types(self, env): self.start = self.start.analyse_types(env) self.stop = self.stop.analyse_types(env) self.step = self.step.analyse_types(env) if not self.start.is_none: self.start = self.start.coerce_to_integer(env) if not self.stop.is_none: self.stop = self.stop.coerce_to_integer(env) if not self.step.is_none: self.step = self.step.coerce_to_integer(env) if self.start.is_literal and self.stop.is_literal and self.step.is_literal: self.is_literal = True self.is_temp = False return self def calculate_result_code(self): pass def generate_result_code(self, code): for a in self.start,self.stop,self.step: if isinstance(a, CloneNode): a.arg.result() class CallNode(ExprNode): # allow overriding the default 'may_be_none' behaviour may_return_none = None def infer_type(self, env): # TODO(robertwb): Reduce redundancy with analyse_types. function = self.function func_type = function.infer_type(env) if isinstance(function, NewExprNode): # note: needs call to infer_type() above return PyrexTypes.CPtrType(function.class_type) if func_type is py_object_type: # function might have lied for safety => try to find better type entry = getattr(function, 'entry', None) if entry is not None: func_type = entry.type or func_type if func_type.is_ptr: func_type = func_type.base_type if func_type.is_cfunction: if getattr(self.function, 'entry', None) and hasattr(self, 'args'): alternatives = self.function.entry.all_alternatives() arg_types = [arg.infer_type(env) for arg in self.args] func_entry = PyrexTypes.best_match(arg_types, alternatives) if func_entry: func_type = func_entry.type if func_type.is_ptr: func_type = func_type.base_type return func_type.return_type return func_type.return_type elif func_type is type_type: if function.is_name and function.entry and function.entry.type: result_type = function.entry.type if result_type.is_extension_type: return result_type elif result_type.is_builtin_type: if function.entry.name == 'float': return PyrexTypes.c_double_type elif function.entry.name in Builtin.types_that_construct_their_instance: return result_type func_type = self.function.analyse_as_type(env) if func_type and (func_type.is_struct_or_union or func_type.is_cpp_class): return func_type return py_object_type def type_dependencies(self, env): # TODO: Update when Danilo's C++ code merged in to handle the # the case of function overloading. return self.function.type_dependencies(env) def is_simple(self): # C function calls could be considered simple, but they may # have side-effects that may hit when multiple operations must # be effected in order, e.g. when constructing the argument # sequence for a function call or comparing values. return False def may_be_none(self): if self.may_return_none is not None: return self.may_return_none func_type = self.function.type if func_type is type_type and self.function.is_name: entry = self.function.entry if entry.type.is_extension_type: return False if (entry.type.is_builtin_type and entry.name in Builtin.types_that_construct_their_instance): return False return ExprNode.may_be_none(self) def set_py_result_type(self, function, func_type=None): if func_type is None: func_type = function.type if func_type is Builtin.type_type and ( function.is_name and function.entry and function.entry.is_builtin and function.entry.name in Builtin.types_that_construct_their_instance): # calling a builtin type that returns a specific object type if function.entry.name == 'float': # the following will come true later on in a transform self.type = PyrexTypes.c_double_type self.result_ctype = PyrexTypes.c_double_type else: self.type = Builtin.builtin_types[function.entry.name] self.result_ctype = py_object_type self.may_return_none = False elif function.is_name and function.type_entry: # We are calling an extension type constructor. As long as we do not # support __new__(), the result type is clear self.type = function.type_entry.type self.result_ctype = py_object_type self.may_return_none = False else: self.type = py_object_type def analyse_as_type_constructor(self, env): type = self.function.analyse_as_type(env) if type and type.is_struct_or_union: args, kwds = self.explicit_args_kwds() items = [] for arg, member in zip(args, type.scope.var_entries): items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.pos, value=member.name), value=arg)) if kwds: items += kwds.key_value_pairs self.key_value_pairs = items self.__class__ = DictNode self.analyse_types(env) # FIXME self.coerce_to(type, env) return True elif type and type.is_cpp_class: self.args = [ arg.analyse_types(env) for arg in self.args ] constructor = type.scope.lookup("") if not constructor: error(self.function.pos, "no constructor found for C++ type '%s'" % self.function.name) self.type = error_type return self self.function = RawCNameExprNode(self.function.pos, constructor.type) self.function.entry = constructor self.function.set_cname(type.empty_declaration_code()) self.analyse_c_function_call(env) self.type = type return True def is_lvalue(self): return self.type.is_reference def nogil_check(self, env): func_type = self.function_type() if func_type.is_pyobject: self.gil_error() elif not func_type.is_error and not getattr(func_type, 'nogil', False): self.gil_error() gil_message = "Calling gil-requiring function" class SimpleCallNode(CallNode): # Function call without keyword, * or ** args. # # function ExprNode # args [ExprNode] # arg_tuple ExprNode or None used internally # self ExprNode or None used internally # coerced_self ExprNode or None used internally # wrapper_call bool used internally # has_optional_args bool used internally # nogil bool used internally subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple'] self = None coerced_self = None arg_tuple = None wrapper_call = False has_optional_args = False nogil = False analysed = False overflowcheck = False def compile_time_value(self, denv): function = self.function.compile_time_value(denv) args = [arg.compile_time_value(denv) for arg in self.args] try: return function(*args) except Exception as e: self.compile_time_value_error(e) @classmethod def for_cproperty(cls, pos, obj, entry): # Create a call node for C property access. property_scope = entry.scope getter_entry = property_scope.lookup_here(entry.name) assert getter_entry, "Getter not found in scope %s: %s" % (property_scope, property_scope.entries) function = NameNode(pos, name=entry.name, entry=getter_entry, type=getter_entry.type) node = cls(pos, function=function, args=[obj]) return node def analyse_as_type(self, env): attr = self.function.as_cython_attribute() if attr == 'pointer': if len(self.args) != 1: error(self.args.pos, "only one type allowed.") else: type = self.args[0].analyse_as_type(env) if not type: error(self.args[0].pos, "Unknown type") else: return PyrexTypes.CPtrType(type) elif attr == 'typeof': if len(self.args) != 1: error(self.args.pos, "only one type allowed.") operand = self.args[0].analyse_types(env) return operand.type def explicit_args_kwds(self): return self.args, None def analyse_types(self, env): if self.analysed: return self self.analysed = True if self.analyse_as_type_constructor(env): return self self.function.is_called = 1 self.function = self.function.analyse_types(env) function = self.function if function.is_attribute and function.entry and function.entry.is_cmethod: # Take ownership of the object from which the attribute # was obtained, because we need to pass it as 'self'. self.self = function.obj function.obj = CloneNode(self.self) func_type = self.function_type() self.is_numpy_call_with_exprs = False if (has_np_pythran(env) and function.is_numpy_attribute and pythran_is_numpy_func_supported(function)): has_pythran_args = True self.arg_tuple = TupleNode(self.pos, args = self.args) self.arg_tuple = self.arg_tuple.analyse_types(env) for arg in self.arg_tuple.args: has_pythran_args &= is_pythran_supported_node_or_none(arg) self.is_numpy_call_with_exprs = bool(has_pythran_args) if self.is_numpy_call_with_exprs: env.add_include_file(pythran_get_func_include_file(function)) return NumPyMethodCallNode.from_node( self, function_cname=pythran_functor(function), arg_tuple=self.arg_tuple, type=PythranExpr(pythran_func_type(function, self.arg_tuple.args)), ) elif func_type.is_pyobject: self.arg_tuple = TupleNode(self.pos, args = self.args) self.arg_tuple = self.arg_tuple.analyse_types(env).coerce_to_pyobject(env) self.args = None self.set_py_result_type(function, func_type) self.is_temp = 1 else: self.args = [ arg.analyse_types(env) for arg in self.args ] self.analyse_c_function_call(env) if func_type.exception_check == '+': self.is_temp = True return self def function_type(self): # Return the type of the function being called, coercing a function # pointer to a function if necessary. If the function has fused # arguments, return the specific type. func_type = self.function.type if func_type.is_ptr: func_type = func_type.base_type return func_type def analyse_c_function_call(self, env): func_type = self.function.type if func_type is error_type: self.type = error_type return if func_type.is_cfunction and func_type.is_static_method: if self.self and self.self.type.is_extension_type: # To support this we'd need to pass self to determine whether # it was overloaded in Python space (possibly via a Cython # superclass turning a cdef method into a cpdef one). error(self.pos, "Cannot call a static method on an instance variable.") args = self.args elif self.self: args = [self.self] + self.args else: args = self.args if func_type.is_cpp_class: overloaded_entry = self.function.type.scope.lookup("operator()") if overloaded_entry is None: self.type = PyrexTypes.error_type self.result_code = "" return elif hasattr(self.function, 'entry'): overloaded_entry = self.function.entry elif self.function.is_subscript and self.function.is_fused_index: overloaded_entry = self.function.type.entry else: overloaded_entry = None if overloaded_entry: if self.function.type.is_fused: functypes = self.function.type.get_all_specialized_function_types() alternatives = [f.entry for f in functypes] else: alternatives = overloaded_entry.all_alternatives() entry = PyrexTypes.best_match([arg.type for arg in args], alternatives, self.pos, env, args) if not entry: self.type = PyrexTypes.error_type self.result_code = "" return entry.used = True if not func_type.is_cpp_class: self.function.entry = entry self.function.type = entry.type func_type = self.function_type() else: entry = None func_type = self.function_type() if not func_type.is_cfunction: error(self.pos, "Calling non-function type '%s'" % func_type) self.type = PyrexTypes.error_type self.result_code = "" return # Check no. of args max_nargs = len(func_type.args) expected_nargs = max_nargs - func_type.optional_arg_count actual_nargs = len(args) if func_type.optional_arg_count and expected_nargs != actual_nargs: self.has_optional_args = 1 self.is_temp = 1 # check 'self' argument if entry and entry.is_cmethod and func_type.args and not func_type.is_static_method: formal_arg = func_type.args[0] arg = args[0] if formal_arg.not_none: if self.self: self.self = self.self.as_none_safe_node( "'NoneType' object has no attribute '%{0}s'".format('.30' if len(entry.name) <= 30 else ''), error='PyExc_AttributeError', format_args=[entry.name]) else: # unbound method arg = arg.as_none_safe_node( "descriptor '%s' requires a '%s' object but received a 'NoneType'", format_args=[entry.name, formal_arg.type.name]) if self.self: if formal_arg.accept_builtin_subtypes: arg = CMethodSelfCloneNode(self.self) else: arg = CloneNode(self.self) arg = self.coerced_self = arg.coerce_to(formal_arg.type, env) elif formal_arg.type.is_builtin_type: # special case: unbound methods of builtins accept subtypes arg = arg.coerce_to(formal_arg.type, env) if arg.type.is_builtin_type and isinstance(arg, PyTypeTestNode): arg.exact_builtin_type = False args[0] = arg # Coerce arguments some_args_in_temps = False for i in range(min(max_nargs, actual_nargs)): formal_arg = func_type.args[i] formal_type = formal_arg.type arg = args[i].coerce_to(formal_type, env) if formal_arg.not_none: # C methods must do the None checks at *call* time arg = arg.as_none_safe_node( "cannot pass None into a C function argument that is declared 'not None'") if arg.is_temp: if i > 0: # first argument in temp doesn't impact subsequent arguments some_args_in_temps = True elif arg.type.is_pyobject and not env.nogil: if i == 0 and self.self is not None: # a method's cloned "self" argument is ok pass elif arg.nonlocally_immutable(): # plain local variables are ok pass else: # we do not safely own the argument's reference, # but we must make sure it cannot be collected # before we return from the function, so we create # an owned temp reference to it if i > 0: # first argument doesn't matter some_args_in_temps = True arg = arg.coerce_to_temp(env) args[i] = arg # handle additional varargs parameters for i in range(max_nargs, actual_nargs): arg = args[i] if arg.type.is_pyobject: if arg.type is str_type: arg_ctype = PyrexTypes.c_char_ptr_type else: arg_ctype = arg.type.default_coerced_ctype() if arg_ctype is None: error(self.args[i-1].pos, "Python object cannot be passed as a varargs parameter") else: args[i] = arg = arg.coerce_to(arg_ctype, env) if arg.is_temp and i > 0: some_args_in_temps = True if some_args_in_temps: # if some args are temps and others are not, they may get # constructed in the wrong order (temps first) => make # sure they are either all temps or all not temps (except # for the last argument, which is evaluated last in any # case) for i in range(actual_nargs-1): if i == 0 and self.self is not None: continue # self is ok arg = args[i] if arg.nonlocally_immutable(): # locals, C functions, unassignable types are safe. pass elif arg.type.is_cpp_class: # Assignment has side effects, avoid. pass elif env.nogil and arg.type.is_pyobject: # can't copy a Python reference into a temp in nogil # env (this is safe: a construction would fail in # nogil anyway) pass else: #self.args[i] = arg.coerce_to_temp(env) # instead: issue a warning if i > 0 or i == 1 and self.self is not None: # skip first arg warning(arg.pos, "Argument evaluation order in C function call is undefined and may not be as expected", 0) break self.args[:] = args # Calc result type and code fragment if isinstance(self.function, NewExprNode): self.type = PyrexTypes.CPtrType(self.function.class_type) else: self.type = func_type.return_type if self.function.is_name or self.function.is_attribute: func_entry = self.function.entry if func_entry and (func_entry.utility_code or func_entry.utility_code_definition): self.is_temp = 1 # currently doesn't work for self.calculate_result_code() if self.type.is_pyobject: self.result_ctype = py_object_type self.is_temp = 1 elif func_type.exception_value is not None or func_type.exception_check: self.is_temp = 1 elif self.type.is_memoryviewslice: self.is_temp = 1 # func_type.exception_check = True if self.is_temp and self.type.is_reference: self.type = PyrexTypes.CFakeReferenceType(self.type.ref_base_type) # C++ exception handler if func_type.exception_check == '+': if needs_cpp_exception_conversion(func_type): env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp")) self.overflowcheck = env.directives['overflowcheck'] def calculate_result_code(self): return self.c_call_code() def c_call_code(self): func_type = self.function_type() if self.type is PyrexTypes.error_type or not func_type.is_cfunction: return "" formal_args = func_type.args arg_list_code = [] args = list(zip(formal_args, self.args)) max_nargs = len(func_type.args) expected_nargs = max_nargs - func_type.optional_arg_count actual_nargs = len(self.args) for formal_arg, actual_arg in args[:expected_nargs]: arg_code = actual_arg.move_result_rhs_as(formal_arg.type) arg_list_code.append(arg_code) if func_type.is_overridable: arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod))) if func_type.optional_arg_count: if expected_nargs == actual_nargs: optional_args = 'NULL' else: optional_args = "&%s" % self.opt_arg_struct arg_list_code.append(optional_args) for actual_arg in self.args[len(formal_args):]: arg_list_code.append(actual_arg.move_result_rhs()) result = "%s(%s)" % (self.function.result(), ', '.join(arg_list_code)) return result def is_c_result_required(self): func_type = self.function_type() if not func_type.exception_value or func_type.exception_check == '+': return False # skip allocation of unused result temp return True def generate_evaluation_code(self, code): function = self.function if function.is_name or function.is_attribute: code.globalstate.use_entry_utility_code(function.entry) abs_function_cnames = ('abs', 'labs', '__Pyx_abs_longlong') is_signed_int = self.type.is_int and self.type.signed if self.overflowcheck and is_signed_int and function.result() in abs_function_cnames: code.globalstate.use_utility_code(UtilityCode.load_cached("Common", "Overflow.c")) code.putln('if (unlikely(%s == __PYX_MIN(%s))) {\ PyErr_SetString(PyExc_OverflowError,\ "Trying to take the absolute value of the most negative integer is not defined."); %s; }' % ( self.args[0].result(), self.args[0].type.empty_declaration_code(), code.error_goto(self.pos))) if not function.type.is_pyobject or len(self.arg_tuple.args) > 1 or ( self.arg_tuple.args and self.arg_tuple.is_literal): super(SimpleCallNode, self).generate_evaluation_code(code) return # Special case 0-args and try to avoid explicit tuple creation for Python calls with 1 arg. arg = self.arg_tuple.args[0] if self.arg_tuple.args else None subexprs = (self.self, self.coerced_self, function, arg) for subexpr in subexprs: if subexpr is not None: subexpr.generate_evaluation_code(code) code.mark_pos(self.pos) assert self.is_temp self.allocate_temp_result(code) if arg is None: code.globalstate.use_utility_code(UtilityCode.load_cached( "PyObjectCallNoArg", "ObjectHandling.c")) code.putln( "%s = __Pyx_PyObject_CallNoArg(%s); %s" % ( self.result(), function.py_result(), code.error_goto_if_null(self.result(), self.pos))) else: code.globalstate.use_utility_code(UtilityCode.load_cached( "PyObjectCallOneArg", "ObjectHandling.c")) code.putln( "%s = __Pyx_PyObject_CallOneArg(%s, %s); %s" % ( self.result(), function.py_result(), arg.py_result(), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) for subexpr in subexprs: if subexpr is not None: subexpr.generate_disposal_code(code) subexpr.free_temps(code) def generate_result_code(self, code): func_type = self.function_type() if func_type.is_pyobject: arg_code = self.arg_tuple.py_result() code.globalstate.use_utility_code(UtilityCode.load_cached( "PyObjectCall", "ObjectHandling.c")) code.putln( "%s = __Pyx_PyObject_Call(%s, %s, NULL); %s" % ( self.result(), self.function.py_result(), arg_code, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) elif func_type.is_cfunction: nogil = not code.funcstate.gil_owned if self.has_optional_args: actual_nargs = len(self.args) expected_nargs = len(func_type.args) - func_type.optional_arg_count self.opt_arg_struct = code.funcstate.allocate_temp( func_type.op_arg_struct.base_type, manage_ref=True) code.putln("%s.%s = %s;" % ( self.opt_arg_struct, Naming.pyrex_prefix + "n", len(self.args) - expected_nargs)) args = list(zip(func_type.args, self.args)) for formal_arg, actual_arg in args[expected_nargs:actual_nargs]: code.putln("%s.%s = %s;" % ( self.opt_arg_struct, func_type.opt_arg_cname(formal_arg.name), actual_arg.result_as(formal_arg.type))) exc_checks = [] if self.type.is_pyobject and self.is_temp: exc_checks.append("!%s" % self.result()) elif self.type.is_memoryviewslice: assert self.is_temp exc_checks.append(self.type.error_condition(self.result())) elif func_type.exception_check != '+': exc_val = func_type.exception_value exc_check = func_type.exception_check if exc_val is not None: exc_checks.append("%s == %s" % (self.result(), func_type.return_type.cast_code(exc_val))) if exc_check: if nogil: if not exc_checks: perf_hint_entry = getattr(self.function, "entry", None) PyrexTypes.write_noexcept_performance_hint( self.pos, code.funcstate.scope, function_name=perf_hint_entry.name if perf_hint_entry else None, void_return=self.type.is_void, is_call=True) code.globalstate.use_utility_code( UtilityCode.load_cached("ErrOccurredWithGIL", "Exceptions.c")) exc_checks.append("__Pyx_ErrOccurredWithGIL()") else: exc_checks.append("PyErr_Occurred()") if self.is_temp or exc_checks: rhs = self.c_call_code() if self.result(): lhs = "%s = " % self.result() if self.is_temp and self.type.is_pyobject: #return_type = self.type # func_type.return_type #print "SimpleCallNode.generate_result_code: casting", rhs, \ # "from", return_type, "to pyobject" ### rhs = typecast(py_object_type, self.type, rhs) else: lhs = "" if func_type.exception_check == '+': translate_cpp_exception(code, self.pos, '%s%s;' % (lhs, rhs), self.result() if self.type.is_pyobject else None, func_type.exception_value, nogil) else: if exc_checks: goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos) else: goto_error = "" code.putln("%s%s; %s" % (lhs, rhs, goto_error)) if self.type.is_pyobject and self.result(): self.generate_gotref(code) if self.has_optional_args: code.funcstate.release_temp(self.opt_arg_struct) class NumPyMethodCallNode(ExprNode): # Pythran call to a NumPy function or method. # # function_cname string the function/method to call # arg_tuple TupleNode the arguments as an args tuple subexprs = ['arg_tuple'] is_temp = True may_return_none = True def generate_evaluation_code(self, code): code.mark_pos(self.pos) self.allocate_temp_result(code) assert self.arg_tuple.mult_factor is None args = self.arg_tuple.args for arg in args: arg.generate_evaluation_code(code) code.putln("// function evaluation code for numpy function") code.putln("__Pyx_call_destructor(%s);" % self.result()) code.putln("new (&%s) decltype(%s){%s{}(%s)};" % ( self.result(), self.result(), self.function_cname, ", ".join(a.pythran_result() for a in args))) class PyMethodCallNode(SimpleCallNode): # Specialised call to a (potential) PyMethodObject with non-constant argument tuple. # Allows the self argument to be injected directly instead of repacking a tuple for it. # # function ExprNode the function/method object to call # arg_tuple TupleNode the arguments for the args tuple subexprs = ['function', 'arg_tuple'] is_temp = True def generate_evaluation_code(self, code): code.mark_pos(self.pos) self.allocate_temp_result(code) self.function.generate_evaluation_code(code) assert self.arg_tuple.mult_factor is None args = self.arg_tuple.args for arg in args: arg.generate_evaluation_code(code) # make sure function is in temp so that we can replace the reference below if it's a method reuse_function_temp = self.function.is_temp if reuse_function_temp: function = self.function.result() else: function = code.funcstate.allocate_temp(py_object_type, manage_ref=True) self.function.make_owned_reference(code) code.put("%s = %s; " % (function, self.function.py_result())) self.function.generate_disposal_code(code) self.function.free_temps(code) self_arg = code.funcstate.allocate_temp(py_object_type, manage_ref=True) code.putln("%s = NULL;" % self_arg) arg_offset_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False) code.putln("%s = 0;" % arg_offset_cname) def attribute_is_likely_method(attr): obj = attr.obj if obj.is_name and obj.entry.is_pyglobal: return False # more likely to be a function return True if self.function.is_attribute: likely_method = 'likely' if attribute_is_likely_method(self.function) else 'unlikely' elif self.function.is_name and self.function.cf_state: # not an attribute itself, but might have been assigned from one (e.g. bound method) for assignment in self.function.cf_state: value = assignment.rhs if value and value.is_attribute and value.obj.type and value.obj.type.is_pyobject: if attribute_is_likely_method(value): likely_method = 'likely' break else: likely_method = 'unlikely' else: likely_method = 'unlikely' code.putln("#if CYTHON_UNPACK_METHODS") code.putln("if (%s(PyMethod_Check(%s))) {" % (likely_method, function)) code.putln("%s = PyMethod_GET_SELF(%s);" % (self_arg, function)) # the following is always true in Py3 (kept only for safety), # but is false for unbound methods in Py2 code.putln("if (likely(%s)) {" % self_arg) code.putln("PyObject* function = PyMethod_GET_FUNCTION(%s);" % function) code.put_incref(self_arg, py_object_type) code.put_incref("function", py_object_type) # free method object as early to possible to enable reuse from CPython's freelist code.put_decref_set(function, py_object_type, "function") code.putln("%s = 1;" % arg_offset_cname) code.putln("}") code.putln("}") code.putln("#endif") # CYTHON_UNPACK_METHODS # TODO may need to deal with unused variables in the #else case # actually call the function code.globalstate.use_utility_code( UtilityCode.load_cached("PyObjectFastCall", "ObjectHandling.c")) code.putln("{") # To avoid passing an out-of-bounds argument pointer in the no-args case, # we need at least two entries, so we pad with NULL and point to that. # See https://github.com/cython/cython/issues/5668 code.putln("PyObject *__pyx_callargs[%d] = {%s, %s};" % ( (len(args) + 1) if args else 2, self_arg, ', '.join(arg.py_result() for arg in args) if args else "NULL", )) code.putln("%s = __Pyx_PyObject_FastCall(%s, __pyx_callargs+1-%s, %d+%s);" % ( self.result(), function, arg_offset_cname, len(args), arg_offset_cname)) code.put_xdecref_clear(self_arg, py_object_type) code.funcstate.release_temp(self_arg) code.funcstate.release_temp(arg_offset_cname) for arg in args: arg.generate_disposal_code(code) arg.free_temps(code) code.putln(code.error_goto_if_null(self.result(), self.pos)) self.generate_gotref(code) if reuse_function_temp: self.function.generate_disposal_code(code) self.function.free_temps(code) else: code.put_decref_clear(function, py_object_type) code.funcstate.release_temp(function) code.putln("}") class InlinedDefNodeCallNode(CallNode): # Inline call to defnode # # function PyCFunctionNode # function_name NameNode # args [ExprNode] subexprs = ['args', 'function_name'] is_temp = 1 type = py_object_type function = None function_name = None def can_be_inlined(self): func_type= self.function.def_node if func_type.star_arg or func_type.starstar_arg: return False if len(func_type.args) != len(self.args): return False if func_type.num_kwonly_args: return False # actually wrong number of arguments return True def analyse_types(self, env): self.function_name = self.function_name.analyse_types(env) self.args = [ arg.analyse_types(env) for arg in self.args ] func_type = self.function.def_node actual_nargs = len(self.args) # Coerce arguments some_args_in_temps = False for i in range(actual_nargs): formal_type = func_type.args[i].type arg = self.args[i].coerce_to(formal_type, env) if arg.is_temp: if i > 0: # first argument in temp doesn't impact subsequent arguments some_args_in_temps = True elif arg.type.is_pyobject and not env.nogil: if arg.nonlocally_immutable(): # plain local variables are ok pass else: # we do not safely own the argument's reference, # but we must make sure it cannot be collected # before we return from the function, so we create # an owned temp reference to it if i > 0: # first argument doesn't matter some_args_in_temps = True arg = arg.coerce_to_temp(env) self.args[i] = arg if some_args_in_temps: # if some args are temps and others are not, they may get # constructed in the wrong order (temps first) => make # sure they are either all temps or all not temps (except # for the last argument, which is evaluated last in any # case) for i in range(actual_nargs-1): arg = self.args[i] if arg.nonlocally_immutable(): # locals, C functions, unassignable types are safe. pass elif arg.type.is_cpp_class: # Assignment has side effects, avoid. pass elif env.nogil and arg.type.is_pyobject: # can't copy a Python reference into a temp in nogil # env (this is safe: a construction would fail in # nogil anyway) pass else: #self.args[i] = arg.coerce_to_temp(env) # instead: issue a warning if i > 0: warning(arg.pos, "Argument evaluation order in C function call is undefined and may not be as expected", 0) break return self def generate_result_code(self, code): arg_code = [self.function_name.py_result()] func_type = self.function.def_node for arg, proto_arg in zip(self.args, func_type.args): if arg.type.is_pyobject: arg_code.append(arg.result_as(proto_arg.type)) else: arg_code.append(arg.result()) arg_code = ', '.join(arg_code) code.putln( "%s = %s(%s); %s" % ( self.result(), self.function.def_node.entry.pyfunc_cname, arg_code, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) class PythonCapiFunctionNode(ExprNode): subexprs = [] def __init__(self, pos, py_name, cname, func_type, utility_code = None): ExprNode.__init__(self, pos, name=py_name, cname=cname, type=func_type, utility_code=utility_code) def analyse_types(self, env): return self def generate_result_code(self, code): if self.utility_code: code.globalstate.use_utility_code(self.utility_code) def calculate_result_code(self): return self.cname class PythonCapiCallNode(SimpleCallNode): # Python C-API Function call (only created in transforms) # By default, we assume that the call never returns None, as this # is true for most C-API functions in CPython. If this does not # apply to a call, set the following to True (or None to inherit # the default behaviour). may_return_none = False def __init__(self, pos, function_name, func_type, utility_code = None, py_name=None, **kwargs): self.type = func_type.return_type self.result_ctype = self.type self.function = PythonCapiFunctionNode( pos, py_name, function_name, func_type, utility_code = utility_code) # call this last so that we can override the constructed # attributes above with explicit keyword arguments if required SimpleCallNode.__init__(self, pos, **kwargs) class CachedBuiltinMethodCallNode(CallNode): # Python call to a method of a known Python builtin (only created in transforms) subexprs = ['obj', 'args'] is_temp = True def __init__(self, call_node, obj, method_name, args): super(CachedBuiltinMethodCallNode, self).__init__( call_node.pos, obj=obj, method_name=method_name, args=args, may_return_none=call_node.may_return_none, type=call_node.type) def may_be_none(self): if self.may_return_none is not None: return self.may_return_none return ExprNode.may_be_none(self) def generate_result_code(self, code): type_cname = self.obj.type.cname obj_cname = self.obj.py_result() args = [arg.py_result() for arg in self.args] call_code = code.globalstate.cached_unbound_method_call_code( obj_cname, type_cname, self.method_name, args) code.putln("%s = %s; %s" % ( self.result(), call_code, code.error_goto_if_null(self.result(), self.pos) )) self.generate_gotref(code) class GeneralCallNode(CallNode): # General Python function call, including keyword, # * and ** arguments. # # function ExprNode # positional_args ExprNode Tuple of positional arguments # keyword_args ExprNode or None Dict of keyword arguments type = py_object_type subexprs = ['function', 'positional_args', 'keyword_args'] nogil_check = Node.gil_error def compile_time_value(self, denv): function = self.function.compile_time_value(denv) positional_args = self.positional_args.compile_time_value(denv) keyword_args = self.keyword_args.compile_time_value(denv) try: return function(*positional_args, **keyword_args) except Exception as e: self.compile_time_value_error(e) def explicit_args_kwds(self): if (self.keyword_args and not self.keyword_args.is_dict_literal or not self.positional_args.is_sequence_constructor): raise CompileError(self.pos, 'Compile-time keyword arguments must be explicit.') return self.positional_args.args, self.keyword_args def analyse_types(self, env): if self.analyse_as_type_constructor(env): return self self.function = self.function.analyse_types(env) if not self.function.type.is_pyobject: if self.function.type.is_error: self.type = error_type return self if hasattr(self.function, 'entry'): node = self.map_to_simple_call_node() if node is not None and node is not self: return node.analyse_types(env) elif self.function.entry.as_variable: self.function = self.function.coerce_to_pyobject(env) elif node is self: error(self.pos, "Non-trivial keyword arguments and starred " "arguments not allowed in cdef functions.") else: # error was already reported pass else: self.function = self.function.coerce_to_pyobject(env) if self.keyword_args: self.keyword_args = self.keyword_args.analyse_types(env) self.positional_args = self.positional_args.analyse_types(env) self.positional_args = \ self.positional_args.coerce_to_pyobject(env) self.set_py_result_type(self.function) self.is_temp = 1 return self def map_to_simple_call_node(self): """ Tries to map keyword arguments to declared positional arguments. Returns self to try a Python call, None to report an error or a SimpleCallNode if the mapping succeeds. """ if not isinstance(self.positional_args, TupleNode): # has starred argument return self if not self.keyword_args.is_dict_literal: # keywords come from arbitrary expression => nothing to do here return self function = self.function entry = getattr(function, 'entry', None) if not entry: return self function_type = entry.type if function_type.is_ptr: function_type = function_type.base_type if not function_type.is_cfunction: return self pos_args = self.positional_args.args kwargs = self.keyword_args declared_args = function_type.args if entry.is_cmethod: declared_args = declared_args[1:] # skip 'self' if len(pos_args) > len(declared_args): error(self.pos, "function call got too many positional arguments, " "expected %d, got %s" % (len(declared_args), len(pos_args))) return None matched_args = { arg.name for arg in declared_args[:len(pos_args)] if arg.name } unmatched_args = declared_args[len(pos_args):] matched_kwargs_count = 0 args = list(pos_args) # check for duplicate keywords seen = set(matched_args) has_errors = False for arg in kwargs.key_value_pairs: name = arg.key.value if name in seen: error(arg.pos, "argument '%s' passed twice" % name) has_errors = True # continue to report more errors if there are any seen.add(name) # match keywords that are passed in order for decl_arg, arg in zip(unmatched_args, kwargs.key_value_pairs): name = arg.key.value if decl_arg.name == name: matched_args.add(name) matched_kwargs_count += 1 args.append(arg.value) else: break # match keyword arguments that are passed out-of-order, but keep # the evaluation of non-simple arguments in order by moving them # into temps from .UtilNodes import EvalWithTempExprNode, LetRefNode temps = [] if len(kwargs.key_value_pairs) > matched_kwargs_count: unmatched_args = declared_args[len(args):] keywords = dict([ (arg.key.value, (i+len(pos_args), arg)) for i, arg in enumerate(kwargs.key_value_pairs) ]) first_missing_keyword = None for decl_arg in unmatched_args: name = decl_arg.name if name not in keywords: # missing keyword argument => either done or error if not first_missing_keyword: first_missing_keyword = name continue elif first_missing_keyword: if entry.as_variable: # we might be able to convert the function to a Python # object, which then allows full calling semantics # with default values in gaps - currently, we only # support optional arguments at the end return self # wasn't the last keyword => gaps are not supported error(self.pos, "C function call is missing " "argument '%s'" % first_missing_keyword) return None pos, arg = keywords[name] matched_args.add(name) matched_kwargs_count += 1 if arg.value.is_simple(): args.append(arg.value) else: temp = LetRefNode(arg.value) assert temp.is_simple() args.append(temp) temps.append((pos, temp)) if temps: # may have to move preceding non-simple args into temps final_args = [] new_temps = [] first_temp_arg = temps[0][-1] for arg_value in args: if arg_value is first_temp_arg: break # done if arg_value.is_simple(): final_args.append(arg_value) else: temp = LetRefNode(arg_value) new_temps.append(temp) final_args.append(temp) if new_temps: args = final_args temps = new_temps + [ arg for i,arg in sorted(temps) ] # check for unexpected keywords for arg in kwargs.key_value_pairs: name = arg.key.value if name not in matched_args: has_errors = True error(arg.pos, "C function got unexpected keyword argument '%s'" % name) if has_errors: # error was reported already return None # all keywords mapped to positional arguments # if we are missing arguments, SimpleCallNode will figure it out node = SimpleCallNode(self.pos, function=function, args=args) for temp in temps[::-1]: node = EvalWithTempExprNode(temp, node) return node def generate_result_code(self, code): if self.type.is_error: return if self.keyword_args: kwargs = self.keyword_args.py_result() else: kwargs = 'NULL' code.globalstate.use_utility_code(UtilityCode.load_cached( "PyObjectCall", "ObjectHandling.c")) code.putln( "%s = __Pyx_PyObject_Call(%s, %s, %s); %s" % ( self.result(), self.function.py_result(), self.positional_args.py_result(), kwargs, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) class AsTupleNode(ExprNode): # Convert argument to tuple. Used for normalising # the * argument of a function call. # # arg ExprNode subexprs = ['arg'] is_temp = 1 def calculate_constant_result(self): self.constant_result = tuple(self.arg.constant_result) def compile_time_value(self, denv): arg = self.arg.compile_time_value(denv) try: return tuple(arg) except Exception as e: self.compile_time_value_error(e) def analyse_types(self, env): self.arg = self.arg.analyse_types(env).coerce_to_pyobject(env) if self.arg.type is tuple_type: return self.arg.as_none_safe_node("'NoneType' object is not iterable") self.type = tuple_type return self def may_be_none(self): return False nogil_check = Node.gil_error gil_message = "Constructing Python tuple" def generate_result_code(self, code): cfunc = "__Pyx_PySequence_Tuple" if self.arg.type in (py_object_type, tuple_type) else "PySequence_Tuple" code.putln( "%s = %s(%s); %s" % ( self.result(), cfunc, self.arg.py_result(), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) class MergedDictNode(ExprNode): # Helper class for keyword arguments and other merged dicts. # # keyword_args [DictNode or other ExprNode] subexprs = ['keyword_args'] is_temp = 1 type = dict_type reject_duplicates = True def calculate_constant_result(self): result = {} reject_duplicates = self.reject_duplicates for item in self.keyword_args: if item.is_dict_literal: # process items in order items = ((key.constant_result, value.constant_result) for key, value in item.key_value_pairs) else: items = item.constant_result.iteritems() for key, value in items: if reject_duplicates and key in result: raise ValueError("duplicate keyword argument found: %s" % key) result[key] = value self.constant_result = result def compile_time_value(self, denv): result = {} reject_duplicates = self.reject_duplicates for item in self.keyword_args: if item.is_dict_literal: # process items in order items = [(key.compile_time_value(denv), value.compile_time_value(denv)) for key, value in item.key_value_pairs] else: items = item.compile_time_value(denv).iteritems() try: for key, value in items: if reject_duplicates and key in result: raise ValueError("duplicate keyword argument found: %s" % key) result[key] = value except Exception as e: self.compile_time_value_error(e) return result def type_dependencies(self, env): return () def infer_type(self, env): return dict_type def analyse_types(self, env): self.keyword_args = [ arg.analyse_types(env).coerce_to_pyobject(env).as_none_safe_node( # FIXME: CPython's error message starts with the runtime function name 'argument after ** must be a mapping, not NoneType') for arg in self.keyword_args ] return self def may_be_none(self): return False gil_message = "Constructing Python dict" def generate_evaluation_code(self, code): code.mark_pos(self.pos) self.allocate_temp_result(code) args = iter(self.keyword_args) item = next(args) item.generate_evaluation_code(code) if item.type is not dict_type: # CPython supports calling functions with non-dicts, so do we code.putln('if (likely(PyDict_CheckExact(%s))) {' % item.py_result()) if item.is_dict_literal: item.make_owned_reference(code) code.putln("%s = %s;" % (self.result(), item.py_result())) item.generate_post_assignment_code(code) else: code.putln("%s = PyDict_Copy(%s); %s" % ( self.result(), item.py_result(), code.error_goto_if_null(self.result(), item.pos))) self.generate_gotref(code) item.generate_disposal_code(code) if item.type is not dict_type: code.putln('} else {') code.globalstate.use_utility_code(UtilityCode.load_cached( "PyObjectCallOneArg", "ObjectHandling.c")) code.putln("%s = __Pyx_PyObject_CallOneArg((PyObject*)&PyDict_Type, %s); %s" % ( self.result(), item.py_result(), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) item.generate_disposal_code(code) code.putln('}') item.free_temps(code) helpers = set() for item in args: if item.is_dict_literal: # inline update instead of creating an intermediate dict for arg in item.key_value_pairs: arg.generate_evaluation_code(code) if self.reject_duplicates: code.putln("if (unlikely(PyDict_Contains(%s, %s))) {" % ( self.result(), arg.key.py_result())) helpers.add("RaiseDoubleKeywords") # FIXME: find out function name at runtime! code.putln('__Pyx_RaiseDoubleKeywordsError("function", %s); %s' % ( arg.key.py_result(), code.error_goto(self.pos))) code.putln("}") code.put_error_if_neg(arg.key.pos, "PyDict_SetItem(%s, %s, %s)" % ( self.result(), arg.key.py_result(), arg.value.py_result())) arg.generate_disposal_code(code) arg.free_temps(code) else: item.generate_evaluation_code(code) if self.reject_duplicates: # merge mapping into kwdict one by one as we need to check for duplicates helpers.add("MergeKeywords") code.put_error_if_neg(item.pos, "__Pyx_MergeKeywords(%s, %s)" % ( self.result(), item.py_result())) else: # simple case, just add all entries helpers.add("RaiseMappingExpected") code.putln("if (unlikely(PyDict_Update(%s, %s) < 0)) {" % ( self.result(), item.py_result())) code.putln("if (PyErr_ExceptionMatches(PyExc_AttributeError)) " "__Pyx_RaiseMappingExpectedError(%s);" % item.py_result()) code.putln(code.error_goto(item.pos)) code.putln("}") item.generate_disposal_code(code) item.free_temps(code) for helper in sorted(helpers): code.globalstate.use_utility_code(UtilityCode.load_cached(helper, "FunctionArguments.c")) def annotate(self, code): for item in self.keyword_args: item.annotate(code) class AttributeNode(ExprNode): # obj.attribute # # obj ExprNode # attribute string # needs_none_check boolean Used if obj is an extension type. # If set to True, it is known that the type is not None. # # Used internally: # # is_py_attr boolean Is a Python getattr operation # member string C name of struct member # is_called boolean Function call is being done on result # entry Entry Symbol table entry of attribute is_attribute = 1 subexprs = ['obj'] entry = None is_called = 0 needs_none_check = True is_memslice_transpose = False is_special_lookup = False is_py_attr = 0 def as_cython_attribute(self): if (isinstance(self.obj, NameNode) and self.obj.is_cython_module and not self.attribute == u"parallel"): return self.attribute cy = self.obj.as_cython_attribute() if cy: return "%s.%s" % (cy, self.attribute) return None def coerce_to(self, dst_type, env): # If coercing to a generic pyobject and this is a cpdef function # we can create the corresponding attribute if dst_type is py_object_type: entry = self.entry if entry and entry.is_cfunction and entry.as_variable: # must be a cpdef function self.is_temp = 1 self.entry = entry.as_variable self.analyse_as_python_attribute(env) return self elif entry and entry.is_cfunction and self.obj.type is not Builtin.type_type: # "bound" cdef function. # This implementation is likely a little inefficient and could be improved. # Essentially it does: # __import__("functools").partial(coerce_to_object(self), self.obj) from .UtilNodes import EvalWithTempExprNode, ResultRefNode # take self.obj out to a temp because it's used twice obj_node = ResultRefNode(self.obj, type=self.obj.type) obj_node.result_ctype = self.obj.result_ctype self.obj = obj_node unbound_node = ExprNode.coerce_to(self, dst_type, env) utility_code=UtilityCode.load_cached( "PyMethodNew2Arg", "ObjectHandling.c" ) func_type = PyrexTypes.CFuncType( PyrexTypes.py_object_type, [ PyrexTypes.CFuncTypeArg("func", PyrexTypes.py_object_type, None), PyrexTypes.CFuncTypeArg("self", PyrexTypes.py_object_type, None) ], ) binding_call = PythonCapiCallNode( self.pos, function_name="__Pyx_PyMethod_New2Arg", func_type=func_type, args=[unbound_node, obj_node], utility_code=utility_code, ) complete_call = EvalWithTempExprNode(obj_node, binding_call) return complete_call.analyse_types(env) return ExprNode.coerce_to(self, dst_type, env) def calculate_constant_result(self): attr = self.attribute if attr.startswith("__") and attr.endswith("__"): return self.constant_result = getattr(self.obj.constant_result, attr) def compile_time_value(self, denv): attr = self.attribute if attr.startswith("__") and attr.endswith("__"): error(self.pos, "Invalid attribute name '%s' in compile-time expression" % attr) return None obj = self.obj.compile_time_value(denv) try: return getattr(obj, attr) except Exception as e: self.compile_time_value_error(e) def type_dependencies(self, env): return self.obj.type_dependencies(env) def infer_type(self, env): # FIXME: this is way too redundant with analyse_types() node = self.analyse_as_cimported_attribute_node(env, target=False) if node is not None: if node.entry.type and node.entry.type.is_cfunction: # special-case - function converted to pointer return PyrexTypes.CPtrType(node.entry.type) else: return node.entry.type node = self.analyse_as_type_attribute(env) if node is not None: return node.entry.type obj_type = self.obj.infer_type(env) self.analyse_attribute(env, obj_type=obj_type) if obj_type.is_builtin_type and self.type.is_cfunction: # special case: C-API replacements for C methods of # builtin types cannot be inferred as C functions as # that would prevent their use as bound methods return py_object_type elif self.entry and self.entry.is_cmethod: # special case: bound methods should not be inferred # as their unbound method types return py_object_type return self.type def analyse_target_declaration(self, env): self.is_target = True def analyse_target_types(self, env): node = self.analyse_types(env, target = 1) if node.type.is_const: error(self.pos, "Assignment to const attribute '%s'" % self.attribute) if not node.is_lvalue(): error(self.pos, "Assignment to non-lvalue of type '%s'" % self.type) return node def analyse_types(self, env, target = 0): if not self.type: self.type = PyrexTypes.error_type # default value if it isn't analysed successfully self.initialized_check = env.directives['initializedcheck'] node = self.analyse_as_cimported_attribute_node(env, target) if node is None and not target: node = self.analyse_as_type_attribute(env) if node is None: node = self.analyse_as_ordinary_attribute_node(env, target) assert node is not None if (node.is_attribute or node.is_name) and node.entry: node.entry.used = True if node.is_attribute: node.wrap_obj_in_nonecheck(env) return node def analyse_as_cimported_attribute_node(self, env, target): # Try to interpret this as a reference to an imported # C const, type, var or function. If successful, mutates # this node into a NameNode and returns 1, otherwise # returns 0. module_scope = self.obj.analyse_as_module(env) if module_scope: entry = module_scope.lookup_here(self.attribute) if entry and not entry.known_standard_library_import and ( entry.is_cglobal or entry.is_cfunction or entry.is_type or entry.is_const): return self.as_name_node(env, entry, target) if self.is_cimported_module_without_shadow(env): # TODO: search for submodule error(self.pos, "cimported module has no attribute '%s'" % self.attribute) return self return None def analyse_as_type_attribute(self, env): # Try to interpret this as a reference to an unbound # C method of an extension type or builtin type. If successful, # creates a corresponding NameNode and returns it, otherwise # returns None. if self.obj.is_string_literal: return type = self.obj.analyse_as_type(env) if type: if type.is_extension_type or type.is_builtin_type or type.is_cpp_class: entry = type.scope.lookup_here(self.attribute) if entry and (entry.is_cmethod or type.is_cpp_class and entry.type.is_cfunction): if type.is_builtin_type: if not self.is_called: # must handle this as Python object return None ubcm_entry = entry else: ubcm_entry = self._create_unbound_cmethod_entry(type, entry, env) ubcm_entry.overloaded_alternatives = [ self._create_unbound_cmethod_entry(type, overloaded_alternative, env) for overloaded_alternative in entry.overloaded_alternatives ] return self.as_name_node(env, ubcm_entry, target=False) elif type.is_enum or type.is_cpp_enum: if self.attribute in type.values: for entry in type.entry.enum_values: if entry.name == self.attribute: return self.as_name_node(env, entry, target=False) else: error(self.pos, "%s not a known value of %s" % (self.attribute, type)) else: error(self.pos, "%s not a known value of %s" % (self.attribute, type)) return None def _create_unbound_cmethod_entry(self, type, entry, env): # Create a temporary entry describing the unbound C method in `entry` # as an ordinary function. if entry.func_cname and entry.type.op_arg_struct is None: cname = entry.func_cname if entry.type.is_static_method or ( env.parent_scope and env.parent_scope.is_cpp_class_scope): ctype = entry.type elif type.is_cpp_class: error(self.pos, "%s not a static member of %s" % (entry.name, type)) ctype = PyrexTypes.error_type else: # Fix self type. ctype = copy.copy(entry.type) ctype.args = ctype.args[:] ctype.args[0] = PyrexTypes.CFuncTypeArg('self', type, 'self', None) else: cname = "%s->%s" % (type.vtabptr_cname, entry.cname) ctype = entry.type ubcm_entry = Symtab.Entry(entry.name, cname, ctype) ubcm_entry.is_cfunction = 1 ubcm_entry.func_cname = entry.func_cname ubcm_entry.is_unbound_cmethod = 1 ubcm_entry.scope = entry.scope return ubcm_entry def analyse_as_type(self, env): module_scope = self.obj.analyse_as_module(env) if module_scope: return module_scope.lookup_type(self.attribute) if not self.obj.is_string_literal: base_type = self.obj.analyse_as_type(env) if base_type and getattr(base_type, 'scope', None) is not None: return base_type.scope.lookup_type(self.attribute) return None def analyse_as_extension_type(self, env): # Try to interpret this as a reference to an extension type # in a cimported module. Returns the extension type, or None. module_scope = self.obj.analyse_as_module(env) if module_scope: entry = module_scope.lookup_here(self.attribute) if entry and entry.is_type: if entry.type.is_extension_type or entry.type.is_builtin_type: return entry.type return None def analyse_as_module(self, env): # Try to interpret this as a reference to a cimported module # in another cimported module. Returns the module scope, or None. module_scope = self.obj.analyse_as_module(env) if module_scope: entry = module_scope.lookup_here(self.attribute) if entry and entry.as_module: return entry.as_module return None def as_name_node(self, env, entry, target): # Create a corresponding NameNode from this node and complete the # analyse_types phase. node = NameNode.from_node(self, name=self.attribute, entry=entry) if target: node = node.analyse_target_types(env) else: node = node.analyse_rvalue_entry(env) node.entry.used = 1 return node def analyse_as_ordinary_attribute_node(self, env, target): self.obj = self.obj.analyse_types(env) self.analyse_attribute(env) if self.entry and self.entry.is_cmethod and not self.is_called: # error(self.pos, "C method can only be called") pass ## Reference to C array turns into pointer to first element. #while self.type.is_array: # self.type = self.type.element_ptr_type() if self.is_py_attr: if not target: self.is_temp = 1 self.result_ctype = py_object_type elif target and self.obj.type.is_builtin_type: error(self.pos, "Assignment to an immutable object field") elif self.entry and self.entry.is_cproperty: if not target: return SimpleCallNode.for_cproperty(self.pos, self.obj, self.entry).analyse_types(env) # TODO: implement writable C-properties? error(self.pos, "Assignment to a read-only property") #elif self.type.is_memoryviewslice and not target: # self.is_temp = True return self def analyse_attribute(self, env, obj_type = None): # Look up attribute and set self.type and self.member. immutable_obj = obj_type is not None # used during type inference self.is_py_attr = 0 self.member = self.attribute if obj_type is None: if self.obj.type.is_string or self.obj.type.is_pyunicode_ptr: self.obj = self.obj.coerce_to_pyobject(env) obj_type = self.obj.type else: if obj_type.is_string or obj_type.is_pyunicode_ptr: obj_type = py_object_type if obj_type.is_ptr or obj_type.is_array: obj_type = obj_type.base_type self.op = "->" elif obj_type.is_extension_type or obj_type.is_builtin_type: self.op = "->" elif obj_type.is_reference and obj_type.is_fake_reference: self.op = "->" else: self.op = "." if obj_type.has_attributes: if obj_type.attributes_known(): entry = obj_type.scope.lookup_here(self.attribute) if obj_type.is_memoryviewslice and not entry: if self.attribute == 'T': self.is_memslice_transpose = True self.is_temp = True self.use_managed_ref = True self.type = self.obj.type.transpose(self.pos) return else: obj_type.declare_attribute(self.attribute, env, self.pos) entry = obj_type.scope.lookup_here(self.attribute) if entry and entry.is_member: entry = None else: error(self.pos, "Cannot select attribute of incomplete type '%s'" % obj_type) self.type = PyrexTypes.error_type return self.entry = entry if entry: if obj_type.is_extension_type and entry.name == "__weakref__": error(self.pos, "Illegal use of special attribute __weakref__") # def methods need the normal attribute lookup # because they do not have struct entries # fused function go through assignment synthesis # (foo = pycfunction(foo_func_obj)) and need to go through # regular Python lookup as well if entry.is_cproperty: self.type = entry.type return elif (entry.is_variable and not entry.fused_cfunction) or entry.is_cmethod: self.type = entry.type self.member = entry.cname return else: # If it's not a variable or C method, it must be a Python # method of an extension type, so we treat it like a Python # attribute. pass # If we get here, the base object is not a struct/union/extension # type, or it is an extension type and the attribute is either not # declared or is declared as a Python method. Treat it as a Python # attribute reference. self.analyse_as_python_attribute(env, obj_type, immutable_obj) def analyse_as_python_attribute(self, env, obj_type=None, immutable_obj=False): if obj_type is None: obj_type = self.obj.type # mangle private '__*' Python attributes used inside of a class self.attribute = env.mangle_class_private_name(self.attribute) self.member = self.attribute self.type = py_object_type self.is_py_attr = 1 if not obj_type.is_pyobject and not obj_type.is_error: # Expose python methods for immutable objects. if (obj_type.is_string or obj_type.is_cpp_string or obj_type.is_buffer or obj_type.is_memoryviewslice or obj_type.is_numeric or (obj_type.is_ctuple and obj_type.can_coerce_to_pyobject(env)) or (obj_type.is_struct and obj_type.can_coerce_to_pyobject(env))): if not immutable_obj: self.obj = self.obj.coerce_to_pyobject(env) elif (obj_type.is_cfunction and (self.obj.is_name or self.obj.is_attribute) and self.obj.entry.as_variable and self.obj.entry.as_variable.type.is_pyobject): # might be an optimised builtin function => unpack it if not immutable_obj: self.obj = self.obj.coerce_to_pyobject(env) else: error(self.pos, "Object of type '%s' has no attribute '%s'" % (obj_type, self.attribute)) def wrap_obj_in_nonecheck(self, env): if not env.directives['nonecheck']: return msg = None format_args = () if (self.obj.type.is_extension_type and self.needs_none_check and not self.is_py_attr): msg = "'NoneType' object has no attribute '%{0}s'".format('.30' if len(self.attribute) <= 30 else '') format_args = (self.attribute,) elif self.obj.type.is_memoryviewslice: if self.is_memslice_transpose: msg = "Cannot transpose None memoryview slice" else: entry = self.obj.type.scope.lookup_here(self.attribute) if entry: # copy/is_c_contig/shape/strides etc msg = "Cannot access '%s' attribute of None memoryview slice" format_args = (entry.name,) if msg: self.obj = self.obj.as_none_safe_node(msg, 'PyExc_AttributeError', format_args=format_args) def nogil_check(self, env): if self.is_py_attr: self.gil_error() gil_message = "Accessing Python attribute" def is_cimported_module_without_shadow(self, env): return self.obj.is_cimported_module_without_shadow(env) def is_simple(self): if self.obj: return self.result_in_temp() or self.obj.is_simple() else: return NameNode.is_simple(self) def is_lvalue(self): if self.obj: return True else: return NameNode.is_lvalue(self) def is_ephemeral(self): if self.obj: return self.obj.is_ephemeral() else: return NameNode.is_ephemeral(self) def calculate_result_code(self): result = self.calculate_access_code() if self.entry and self.entry.is_cpp_optional and not self.is_target: result = "(*%s)" % result return result def calculate_access_code(self): # Does the job of calculate_result_code but doesn't dereference cpp_optionals # Therefore allowing access to the holder variable obj = self.obj obj_code = obj.result_as(obj.type) #print "...obj_code =", obj_code ### if self.entry and self.entry.is_cmethod: if obj.type.is_extension_type and not self.entry.is_builtin_cmethod: if self.entry.final_func_cname: return self.entry.final_func_cname if self.type.from_fused: # If the attribute was specialized through indexing, make # sure to get the right fused name, as our entry was # replaced by our parent index node # (AnalyseExpressionsTransform) self.member = self.entry.cname return "((struct %s *)%s%s%s)->%s" % ( obj.type.vtabstruct_cname, obj_code, self.op, obj.type.vtabslot_cname, self.member) elif self.result_is_used: return self.member # Generating no code at all for unused access to optimised builtin # methods fixes the problem that some optimisations only exist as # macros, i.e. there is no function pointer to them, so we would # generate invalid C code here. return elif obj.type.is_complex: return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code) else: if obj.type.is_builtin_type and self.entry and self.entry.is_variable: # accessing a field of a builtin type, need to cast better than result_as() does obj_code = obj.type.cast_code(obj.result(), to_object_struct = True) return "%s%s%s" % (obj_code, self.op, self.member) def generate_result_code(self, code): if self.is_py_attr: if self.is_special_lookup: code.globalstate.use_utility_code( UtilityCode.load_cached("PyObjectLookupSpecial", "ObjectHandling.c")) lookup_func_name = '__Pyx_PyObject_LookupSpecial' else: code.globalstate.use_utility_code( UtilityCode.load_cached("PyObjectGetAttrStr", "ObjectHandling.c")) lookup_func_name = '__Pyx_PyObject_GetAttrStr' code.putln( '%s = %s(%s, %s); %s' % ( self.result(), lookup_func_name, self.obj.py_result(), code.intern_identifier(self.attribute), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) elif self.type.is_memoryviewslice: if self.is_memslice_transpose: # transpose the slice for access, packing in self.type.axes: if access == 'ptr': error(self.pos, "Transposing not supported for slices " "with indirect dimensions") return code.putln("%s = %s;" % (self.result(), self.obj.result())) code.put_incref_memoryviewslice(self.result(), self.type, have_gil=True) T = "__pyx_memslice_transpose(&%s)" % self.result() code.putln(code.error_goto_if_neg(T, self.pos)) elif self.initialized_check: code.putln( 'if (unlikely(!%s.memview)) {' 'PyErr_SetString(PyExc_AttributeError,' '"Memoryview is not initialized");' '%s' '}' % (self.result(), code.error_goto(self.pos))) elif self.entry.is_cpp_optional and self.initialized_check: if self.is_target: undereferenced_result = self.result() else: assert not self.is_temp # calculate_access_code() only makes sense for non-temps undereferenced_result = self.calculate_access_code() unbound_check_code = self.type.cpp_optional_check_for_null_code(undereferenced_result) code.put_error_if_unbound(self.pos, self.entry, unbound_check_code=unbound_check_code) else: # result_code contains what is needed, but we may need to insert # a check and raise an exception if self.obj.type and self.obj.type.is_extension_type: pass elif self.entry and self.entry.is_cmethod: # C method implemented as function call with utility code code.globalstate.use_entry_utility_code(self.entry) def generate_disposal_code(self, code): if self.is_temp and self.type.is_memoryviewslice and self.is_memslice_transpose: # mirror condition for putting the memview incref here: code.put_xdecref_clear(self.result(), self.type, have_gil=True) else: ExprNode.generate_disposal_code(self, code) def generate_assignment_code(self, rhs, code, overloaded_assignment=False, exception_check=None, exception_value=None): self.obj.generate_evaluation_code(code) if self.is_py_attr: code.globalstate.use_utility_code( UtilityCode.load_cached("PyObjectSetAttrStr", "ObjectHandling.c")) code.put_error_if_neg(self.pos, '__Pyx_PyObject_SetAttrStr(%s, %s, %s)' % ( self.obj.py_result(), code.intern_identifier(self.attribute), rhs.py_result())) rhs.generate_disposal_code(code) rhs.free_temps(code) elif self.obj.type.is_complex: code.putln("__Pyx_SET_C%s%s(%s, %s);" % ( self.member.upper(), self.obj.type.implementation_suffix, self.obj.result_as(self.obj.type), rhs.result_as(self.ctype()))) rhs.generate_disposal_code(code) rhs.free_temps(code) else: select_code = self.result() if self.type.is_pyobject and self.use_managed_ref: rhs.make_owned_reference(code) rhs.generate_giveref(code) code.put_gotref(select_code, self.type) code.put_decref(select_code, self.ctype()) elif self.type.is_memoryviewslice: from . import MemoryView MemoryView.put_assign_to_memviewslice( select_code, rhs, rhs.result(), self.type, code) if not self.type.is_memoryviewslice: code.putln( "%s = %s;" % ( select_code, rhs.move_result_rhs_as(self.ctype()))) #rhs.result())) rhs.generate_post_assignment_code(code) rhs.free_temps(code) self.obj.generate_disposal_code(code) self.obj.free_temps(code) def generate_deletion_code(self, code, ignore_nonexisting=False): self.obj.generate_evaluation_code(code) if self.is_py_attr or (self.entry.scope.is_property_scope and u'__del__' in self.entry.scope.entries): code.globalstate.use_utility_code( UtilityCode.load_cached("PyObjectSetAttrStr", "ObjectHandling.c")) code.put_error_if_neg(self.pos, '__Pyx_PyObject_DelAttrStr(%s, %s)' % ( self.obj.py_result(), code.intern_identifier(self.attribute))) else: error(self.pos, "Cannot delete C attribute of extension type") self.obj.generate_disposal_code(code) self.obj.free_temps(code) def annotate(self, code): if self.is_py_attr: style, text = 'py_attr', 'python attribute (%s)' else: style, text = 'c_attr', 'c attribute (%s)' code.annotate(self.pos, AnnotationItem(style, text % self.type, size=len(self.attribute))) def get_known_standard_library_import(self): module_name = self.obj.get_known_standard_library_import() if module_name: return StringEncoding.EncodedString("%s.%s" % (module_name, self.attribute)) return None #------------------------------------------------------------------- # # Constructor nodes # #------------------------------------------------------------------- class StarredUnpackingNode(ExprNode): # A starred expression like "*a" # # This is only allowed in sequence assignment or construction such as # # a, *b = (1,2,3,4) => a = 1 ; b = [2,3,4] # # and will be special cased during type analysis (or generate an error # if it's found at unexpected places). # # target ExprNode subexprs = ['target'] is_starred = 1 type = py_object_type is_temp = 1 starred_expr_allowed_here = False def __init__(self, pos, target): ExprNode.__init__(self, pos, target=target) def analyse_declarations(self, env): if not self.starred_expr_allowed_here: error(self.pos, "starred expression is not allowed here") self.target.analyse_declarations(env) def infer_type(self, env): return self.target.infer_type(env) def analyse_types(self, env): if not self.starred_expr_allowed_here: error(self.pos, "starred expression is not allowed here") self.target = self.target.analyse_types(env) self.type = self.target.type return self def analyse_target_declaration(self, env): self.target.analyse_target_declaration(env) def analyse_target_types(self, env): self.target = self.target.analyse_target_types(env) self.type = self.target.type return self def calculate_result_code(self): return "" def generate_result_code(self, code): pass class SequenceNode(ExprNode): # Base class for list and tuple constructor nodes. # Contains common code for performing sequence unpacking. # # args [ExprNode] # unpacked_items [ExprNode] or None # coerced_unpacked_items [ExprNode] or None # mult_factor ExprNode the integer number of content repetitions ([1,2]*3) subexprs = ['args', 'mult_factor'] is_sequence_constructor = 1 unpacked_items = None mult_factor = None slow = False # trade speed for code size (e.g. use PyTuple_Pack()) def compile_time_value_list(self, denv): return [arg.compile_time_value(denv) for arg in self.args] def replace_starred_target_node(self): # replace a starred node in the targets by the contained expression self.starred_assignment = False args = [] for arg in self.args: if arg.is_starred: if self.starred_assignment: error(arg.pos, "more than 1 starred expression in assignment") self.starred_assignment = True arg = arg.target arg.is_starred = True args.append(arg) self.args = args def analyse_target_declaration(self, env): self.replace_starred_target_node() for arg in self.args: arg.analyse_target_declaration(env) def analyse_types(self, env, skip_children=False): for i, arg in enumerate(self.args): if not skip_children: arg = arg.analyse_types(env) self.args[i] = arg.coerce_to_pyobject(env) if self.mult_factor: mult_factor = self.mult_factor.analyse_types(env) if not mult_factor.type.is_int: mult_factor = mult_factor.coerce_to_pyobject(env) self.mult_factor = mult_factor.coerce_to_simple(env) self.is_temp = 1 # not setting self.type here, subtypes do this return self def coerce_to_ctuple(self, dst_type, env): if self.type == dst_type: return self assert not self.mult_factor if len(self.args) != dst_type.size: error(self.pos, "trying to coerce sequence to ctuple of wrong length, expected %d, got %d" % ( dst_type.size, len(self.args))) coerced_args = [arg.coerce_to(type, env) for arg, type in zip(self.args, dst_type.components)] return TupleNode(self.pos, args=coerced_args, type=dst_type, is_temp=True) def _create_merge_node_if_necessary(self, env): self._flatten_starred_args() if not any(arg.is_starred for arg in self.args): return self # convert into MergedSequenceNode by building partial sequences args = [] values = [] for arg in self.args: if arg.is_starred: if values: args.append(TupleNode(values[0].pos, args=values).analyse_types(env, skip_children=True)) values = [] args.append(arg.target) else: values.append(arg) if values: args.append(TupleNode(values[0].pos, args=values).analyse_types(env, skip_children=True)) node = MergedSequenceNode(self.pos, args, self.type) if self.mult_factor: node = binop_node( self.pos, '*', node, self.mult_factor.coerce_to_pyobject(env), inplace=True, type=self.type, is_temp=True) return node def _flatten_starred_args(self): args = [] for arg in self.args: if arg.is_starred and arg.target.is_sequence_constructor and not arg.target.mult_factor: args.extend(arg.target.args) else: args.append(arg) self.args[:] = args def may_be_none(self): return False def analyse_target_types(self, env): if self.mult_factor: error(self.pos, "can't assign to multiplied sequence") self.unpacked_items = [] self.coerced_unpacked_items = [] self.any_coerced_items = False for i, arg in enumerate(self.args): arg = self.args[i] = arg.analyse_target_types(env) if arg.is_starred: if not arg.type.assignable_from(list_type): error(arg.pos, "starred target must have Python object (list) type") if arg.type is py_object_type: arg.type = list_type unpacked_item = PyTempNode(self.pos, env) coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env) if unpacked_item is not coerced_unpacked_item: self.any_coerced_items = True self.unpacked_items.append(unpacked_item) self.coerced_unpacked_items.append(coerced_unpacked_item) self.type = py_object_type return self def generate_result_code(self, code): self.generate_operation_code(code) def generate_sequence_packing_code(self, code, target=None, plain=False): if target is None: target = self.result() size_factor = c_mult = '' mult_factor = None if self.mult_factor and not plain: mult_factor = self.mult_factor if mult_factor.type.is_int: c_mult = mult_factor.result() if (isinstance(mult_factor.constant_result, _py_int_types) and mult_factor.constant_result > 0): size_factor = ' * %s' % mult_factor.constant_result elif mult_factor.type.signed: size_factor = ' * ((%s<0) ? 0:%s)' % (c_mult, c_mult) else: size_factor = ' * (%s)' % (c_mult,) if self.type is tuple_type and (self.is_literal or self.slow) and not c_mult: # use PyTuple_Pack() to avoid generating huge amounts of one-time code code.putln('%s = PyTuple_Pack(%d, %s); %s' % ( target, len(self.args), ', '.join(arg.py_result() for arg in self.args), code.error_goto_if_null(target, self.pos))) code.put_gotref(target, py_object_type) elif self.type.is_ctuple: for i, arg in enumerate(self.args): code.putln("%s.f%s = %s;" % ( target, i, arg.result())) else: # build the tuple/list step by step, potentially multiplying it as we go if self.type is list_type: create_func, set_item_func = 'PyList_New', '__Pyx_PyList_SET_ITEM' elif self.type is tuple_type: create_func, set_item_func = 'PyTuple_New', '__Pyx_PyTuple_SET_ITEM' else: raise InternalError("sequence packing for unexpected type %s" % self.type) arg_count = len(self.args) code.putln("%s = %s(%s%s); %s" % ( target, create_func, arg_count, size_factor, code.error_goto_if_null(target, self.pos))) code.put_gotref(target, py_object_type) if c_mult: # FIXME: can't use a temp variable here as the code may # end up in the constant building function. Temps # currently don't work there. #counter = code.funcstate.allocate_temp(mult_factor.type, manage_ref=False) counter = Naming.quick_temp_cname code.putln('{ Py_ssize_t %s;' % counter) if arg_count == 1: offset = counter else: offset = '%s * %s' % (counter, arg_count) code.putln('for (%s=0; %s < %s; %s++) {' % ( counter, counter, c_mult, counter )) else: offset = '' for i in range(arg_count): arg = self.args[i] if c_mult or not arg.result_in_temp(): code.put_incref(arg.result(), arg.ctype()) arg.generate_giveref(code) code.putln("if (%s(%s, %s, %s)) %s;" % ( set_item_func, target, (offset and i) and ('%s + %s' % (offset, i)) or (offset or i), arg.py_result(), code.error_goto(self.pos))) if c_mult: code.putln('}') #code.funcstate.release_temp(counter) code.putln('}') if mult_factor is not None and mult_factor.type.is_pyobject: code.putln('{ PyObject* %s = PyNumber_InPlaceMultiply(%s, %s); %s' % ( Naming.quick_temp_cname, target, mult_factor.py_result(), code.error_goto_if_null(Naming.quick_temp_cname, self.pos) )) code.put_gotref(Naming.quick_temp_cname, py_object_type) code.put_decref(target, py_object_type) code.putln('%s = %s;' % (target, Naming.quick_temp_cname)) code.putln('}') def generate_subexpr_disposal_code(self, code): if self.mult_factor and self.mult_factor.type.is_int: super(SequenceNode, self).generate_subexpr_disposal_code(code) elif self.type is tuple_type and (self.is_literal or self.slow): super(SequenceNode, self).generate_subexpr_disposal_code(code) else: # We call generate_post_assignment_code here instead # of generate_disposal_code, because values were stored # in the tuple using a reference-stealing operation. for arg in self.args: arg.generate_post_assignment_code(code) # Should NOT call free_temps -- this is invoked by the default # generate_evaluation_code which will do that. if self.mult_factor: self.mult_factor.generate_disposal_code(code) def generate_assignment_code(self, rhs, code, overloaded_assignment=False, exception_check=None, exception_value=None): if self.starred_assignment: self.generate_starred_assignment_code(rhs, code) else: self.generate_parallel_assignment_code(rhs, code) for item in self.unpacked_items: item.release(code) rhs.free_temps(code) _func_iternext_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType( PyrexTypes.py_object_type, [ PyrexTypes.CFuncTypeArg("it", PyrexTypes.py_object_type, None), ])) def generate_parallel_assignment_code(self, rhs, code): # Need to work around the fact that generate_evaluation_code # allocates the temps in a rather hacky way -- the assignment # is evaluated twice, within each if-block. for item in self.unpacked_items: item.allocate(code) special_unpack = (rhs.type is py_object_type or rhs.type in (tuple_type, list_type) or not rhs.type.is_builtin_type) long_enough_for_a_loop = len(self.unpacked_items) > 3 if special_unpack: self.generate_special_parallel_unpacking_code( code, rhs, use_loop=long_enough_for_a_loop) else: code.putln("{") self.generate_generic_parallel_unpacking_code( code, rhs, self.unpacked_items, use_loop=long_enough_for_a_loop) code.putln("}") for value_node in self.coerced_unpacked_items: value_node.generate_evaluation_code(code) for i in range(len(self.args)): self.args[i].generate_assignment_code( self.coerced_unpacked_items[i], code) def generate_special_parallel_unpacking_code(self, code, rhs, use_loop): sequence_type_test = '1' none_check = "likely(%s != Py_None)" % rhs.py_result() if rhs.type is list_type: sequence_types = ['List'] if rhs.may_be_none(): sequence_type_test = none_check elif rhs.type is tuple_type: sequence_types = ['Tuple'] if rhs.may_be_none(): sequence_type_test = none_check else: sequence_types = ['Tuple', 'List'] tuple_check = 'likely(PyTuple_CheckExact(%s))' % rhs.py_result() list_check = 'PyList_CheckExact(%s)' % rhs.py_result() sequence_type_test = "(%s) || (%s)" % (tuple_check, list_check) code.putln("if (%s) {" % sequence_type_test) code.putln("PyObject* sequence = %s;" % rhs.py_result()) # list/tuple => check size code.putln("Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);") code.putln("if (unlikely(size != %d)) {" % len(self.args)) code.globalstate.use_utility_code( UtilityCode.load_cached("RaiseTooManyValuesToUnpack", "ObjectHandling.c")) code.putln("if (size > %d) __Pyx_RaiseTooManyValuesError(%d);" % ( len(self.args), len(self.args))) code.globalstate.use_utility_code( UtilityCode.load_cached("RaiseNeedMoreValuesToUnpack", "ObjectHandling.c")) code.putln("else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);") # < 0 => exception code.putln(code.error_goto(self.pos)) code.putln("}") code.putln("#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS") # unpack items from list/tuple in unrolled loop (can't fail) if len(sequence_types) == 2: code.putln("if (likely(Py%s_CheckExact(sequence))) {" % sequence_types[0]) for i, item in enumerate(self.unpacked_items): code.putln("%s = Py%s_GET_ITEM(sequence, %d); " % ( item.result(), sequence_types[0], i)) if len(sequence_types) == 2: code.putln("} else {") for i, item in enumerate(self.unpacked_items): code.putln("%s = Py%s_GET_ITEM(sequence, %d); " % ( item.result(), sequence_types[1], i)) code.putln("}") for item in self.unpacked_items: code.put_incref(item.result(), item.ctype()) code.putln("#else") # in non-CPython, use the PySequence protocol (which can fail) if not use_loop: for i, item in enumerate(self.unpacked_items): code.putln("%s = PySequence_ITEM(sequence, %d); %s" % ( item.result(), i, code.error_goto_if_null(item.result(), self.pos))) code.put_gotref(item.result(), item.type) else: code.putln("{") code.putln("Py_ssize_t i;") code.putln("PyObject** temps[%s] = {%s};" % ( len(self.unpacked_items), ','.join(['&%s' % item.result() for item in self.unpacked_items]))) code.putln("for (i=0; i < %s; i++) {" % len(self.unpacked_items)) code.putln("PyObject* item = PySequence_ITEM(sequence, i); %s" % ( code.error_goto_if_null('item', self.pos))) code.put_gotref('item', py_object_type) code.putln("*(temps[i]) = item;") code.putln("}") code.putln("}") code.putln("#endif") rhs.generate_disposal_code(code) if sequence_type_test == '1': code.putln("}") # all done elif sequence_type_test == none_check: # either tuple/list or None => save some code by generating the error directly code.putln("} else {") code.globalstate.use_utility_code( UtilityCode.load_cached("RaiseNoneIterError", "ObjectHandling.c")) code.putln("__Pyx_RaiseNoneNotIterableError(); %s" % code.error_goto(self.pos)) code.putln("}") # all done else: code.putln("} else {") # needs iteration fallback code self.generate_generic_parallel_unpacking_code( code, rhs, self.unpacked_items, use_loop=use_loop) code.putln("}") def generate_generic_parallel_unpacking_code(self, code, rhs, unpacked_items, use_loop, terminate=True): code.globalstate.use_utility_code( UtilityCode.load_cached("RaiseNeedMoreValuesToUnpack", "ObjectHandling.c")) code.globalstate.use_utility_code( UtilityCode.load_cached("IterFinish", "ObjectHandling.c")) code.putln("Py_ssize_t index = -1;") # must be at the start of a C block! if use_loop: code.putln("PyObject** temps[%s] = {%s};" % ( len(self.unpacked_items), ','.join(['&%s' % item.result() for item in unpacked_items]))) iterator_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True) code.putln( "%s = PyObject_GetIter(%s); %s" % ( iterator_temp, rhs.py_result(), code.error_goto_if_null(iterator_temp, self.pos))) code.put_gotref(iterator_temp, py_object_type) rhs.generate_disposal_code(code) iternext_func = code.funcstate.allocate_temp(self._func_iternext_type, manage_ref=False) code.putln("%s = __Pyx_PyObject_GetIterNextFunc(%s);" % ( iternext_func, iterator_temp)) unpacking_error_label = code.new_label('unpacking_failed') unpack_code = "%s(%s)" % (iternext_func, iterator_temp) if use_loop: code.putln("for (index=0; index < %s; index++) {" % len(unpacked_items)) code.put("PyObject* item = %s; if (unlikely(!item)) " % unpack_code) code.put_goto(unpacking_error_label) code.put_gotref("item", py_object_type) code.putln("*(temps[index]) = item;") code.putln("}") else: for i, item in enumerate(unpacked_items): code.put( "index = %d; %s = %s; if (unlikely(!%s)) " % ( i, item.result(), unpack_code, item.result())) code.put_goto(unpacking_error_label) item.generate_gotref(code) if terminate: code.globalstate.use_utility_code( UtilityCode.load_cached("UnpackItemEndCheck", "ObjectHandling.c")) code.put_error_if_neg(self.pos, "__Pyx_IternextUnpackEndCheck(%s, %d)" % ( unpack_code, len(unpacked_items))) code.putln("%s = NULL;" % iternext_func) code.put_decref_clear(iterator_temp, py_object_type) unpacking_done_label = code.new_label('unpacking_done') code.put_goto(unpacking_done_label) code.put_label(unpacking_error_label) code.put_decref_clear(iterator_temp, py_object_type) code.putln("%s = NULL;" % iternext_func) code.putln("if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);") code.putln(code.error_goto(self.pos)) code.put_label(unpacking_done_label) code.funcstate.release_temp(iternext_func) if terminate: code.funcstate.release_temp(iterator_temp) iterator_temp = None return iterator_temp def generate_starred_assignment_code(self, rhs, code): for i, arg in enumerate(self.args): if arg.is_starred: starred_target = self.unpacked_items[i] unpacked_fixed_items_left = self.unpacked_items[:i] unpacked_fixed_items_right = self.unpacked_items[i+1:] break else: assert False iterator_temp = None if unpacked_fixed_items_left: for item in unpacked_fixed_items_left: item.allocate(code) code.putln('{') iterator_temp = self.generate_generic_parallel_unpacking_code( code, rhs, unpacked_fixed_items_left, use_loop=True, terminate=False) for i, item in enumerate(unpacked_fixed_items_left): value_node = self.coerced_unpacked_items[i] value_node.generate_evaluation_code(code) code.putln('}') starred_target.allocate(code) target_list = starred_target.result() code.putln("%s = %s(%s); %s" % ( target_list, "__Pyx_PySequence_ListKeepNew" if ( not iterator_temp and rhs.is_temp and rhs.type in (py_object_type, list_type)) else "PySequence_List", iterator_temp or rhs.py_result(), code.error_goto_if_null(target_list, self.pos))) starred_target.generate_gotref(code) if iterator_temp: code.put_decref_clear(iterator_temp, py_object_type) code.funcstate.release_temp(iterator_temp) else: rhs.generate_disposal_code(code) if unpacked_fixed_items_right: code.globalstate.use_utility_code( UtilityCode.load_cached("RaiseNeedMoreValuesToUnpack", "ObjectHandling.c")) length_temp = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False) code.putln('%s = PyList_GET_SIZE(%s);' % (length_temp, target_list)) code.putln("if (unlikely(%s < %d)) {" % (length_temp, len(unpacked_fixed_items_right))) code.putln("__Pyx_RaiseNeedMoreValuesError(%d+%s); %s" % ( len(unpacked_fixed_items_left), length_temp, code.error_goto(self.pos))) code.putln('}') for item in unpacked_fixed_items_right[::-1]: item.allocate(code) for i, (item, coerced_arg) in enumerate(zip(unpacked_fixed_items_right[::-1], self.coerced_unpacked_items[::-1])): code.putln('#if CYTHON_COMPILING_IN_CPYTHON') code.putln("%s = PyList_GET_ITEM(%s, %s-%d); " % ( item.py_result(), target_list, length_temp, i+1)) # resize the list the hard way code.putln("((PyVarObject*)%s)->ob_size--;" % target_list) code.putln('#else') code.putln("%s = PySequence_ITEM(%s, %s-%d); " % ( item.py_result(), target_list, length_temp, i+1)) code.putln('#endif') item.generate_gotref(code) coerced_arg.generate_evaluation_code(code) code.putln('#if !CYTHON_COMPILING_IN_CPYTHON') sublist_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True) code.putln('%s = PySequence_GetSlice(%s, 0, %s-%d); %s' % ( sublist_temp, target_list, length_temp, len(unpacked_fixed_items_right), code.error_goto_if_null(sublist_temp, self.pos))) code.put_gotref(sublist_temp, py_object_type) code.funcstate.release_temp(length_temp) code.put_decref(target_list, py_object_type) code.putln('%s = %s; %s = NULL;' % (target_list, sublist_temp, sublist_temp)) code.putln('#else') code.putln('CYTHON_UNUSED_VAR(%s);' % sublist_temp) code.funcstate.release_temp(sublist_temp) code.putln('#endif') for i, arg in enumerate(self.args): arg.generate_assignment_code(self.coerced_unpacked_items[i], code) def annotate(self, code): for arg in self.args: arg.annotate(code) if self.unpacked_items: for arg in self.unpacked_items: arg.annotate(code) for arg in self.coerced_unpacked_items: arg.annotate(code) class TupleNode(SequenceNode): # Tuple constructor. type = tuple_type is_partly_literal = False gil_message = "Constructing Python tuple" def infer_type(self, env): if self.mult_factor or not self.args: return tuple_type arg_types = [arg.infer_type(env) for arg in self.args] if any(type.is_pyobject or type.is_memoryviewslice or type.is_unspecified or type.is_fused for type in arg_types): return tuple_type return env.declare_tuple_type(self.pos, arg_types).type def analyse_types(self, env, skip_children=False): # reset before re-analysing if self.is_literal: self.is_literal = False if self.is_partly_literal: self.is_partly_literal = False if len(self.args) == 0: self.is_temp = False self.is_literal = True return self if not skip_children: for i, arg in enumerate(self.args): if arg.is_starred: arg.starred_expr_allowed_here = True self.args[i] = arg.analyse_types(env) if (not self.mult_factor and not any((arg.is_starred or arg.type.is_pyobject or arg.type.is_memoryviewslice or arg.type.is_fused) for arg in self.args)): self.type = env.declare_tuple_type(self.pos, (arg.type for arg in self.args)).type self.is_temp = 1 return self node = SequenceNode.analyse_types(self, env, skip_children=True) node = node._create_merge_node_if_necessary(env) if not node.is_sequence_constructor: return node if not all(child.is_literal for child in node.args): return node if not node.mult_factor or ( node.mult_factor.is_literal and isinstance(node.mult_factor.constant_result, _py_int_types)): node.is_temp = False node.is_literal = True else: if not node.mult_factor.type.is_pyobject and not node.mult_factor.type.is_int: node.mult_factor = node.mult_factor.coerce_to_pyobject(env) node.is_temp = True node.is_partly_literal = True return node def analyse_as_type(self, env): # ctuple type if not self.args: return None item_types = [arg.analyse_as_type(env) for arg in self.args] if any(t is None for t in item_types): return None entry = env.declare_tuple_type(self.pos, item_types) return entry.type def coerce_to(self, dst_type, env): if self.type.is_ctuple: if dst_type.is_ctuple and self.type.size == dst_type.size: return self.coerce_to_ctuple(dst_type, env) elif dst_type is tuple_type or dst_type is py_object_type: coerced_args = [arg.coerce_to_pyobject(env) for arg in self.args] return TupleNode( self.pos, args=coerced_args, type=tuple_type, mult_factor=self.mult_factor, is_temp=1, ).analyse_types(env, skip_children=True) else: return self.coerce_to_pyobject(env).coerce_to(dst_type, env) elif dst_type.is_ctuple and not self.mult_factor: return self.coerce_to_ctuple(dst_type, env) else: return SequenceNode.coerce_to(self, dst_type, env) def as_list(self): t = ListNode(self.pos, args=self.args, mult_factor=self.mult_factor) if isinstance(self.constant_result, tuple): t.constant_result = list(self.constant_result) return t def is_simple(self): # either temp or constant => always simple return True def nonlocally_immutable(self): # either temp or constant => always safe return True def calculate_result_code(self): if len(self.args) > 0: return self.result_code else: return Naming.empty_tuple def calculate_constant_result(self): self.constant_result = tuple([ arg.constant_result for arg in self.args]) def compile_time_value(self, denv): values = self.compile_time_value_list(denv) try: return tuple(values) except Exception as e: self.compile_time_value_error(e) def generate_operation_code(self, code): if len(self.args) == 0: # result_code is Naming.empty_tuple return if self.is_literal or self.is_partly_literal: # The "mult_factor" is part of the deduplication if it is also constant, i.e. when # we deduplicate the multiplied result. Otherwise, only deduplicate the constant part. dedup_key = make_dedup_key(self.type, [self.mult_factor if self.is_literal else None] + self.args) tuple_target = code.get_py_const(py_object_type, 'tuple', cleanup_level=2, dedup_key=dedup_key) const_code = code.get_cached_constants_writer(tuple_target) if const_code is not None: # constant is not yet initialised const_code.mark_pos(self.pos) self.generate_sequence_packing_code(const_code, tuple_target, plain=not self.is_literal) const_code.put_giveref(tuple_target, py_object_type) if self.is_literal: self.result_code = tuple_target elif self.mult_factor.type.is_int: code.globalstate.use_utility_code( UtilityCode.load_cached("PySequenceMultiply", "ObjectHandling.c")) code.putln('%s = __Pyx_PySequence_Multiply(%s, %s); %s' % ( self.result(), tuple_target, self.mult_factor.result(), code.error_goto_if_null(self.result(), self.pos) )) self.generate_gotref(code) else: code.putln('%s = PyNumber_Multiply(%s, %s); %s' % ( self.result(), tuple_target, self.mult_factor.py_result(), code.error_goto_if_null(self.result(), self.pos) )) self.generate_gotref(code) else: self.type.entry.used = True self.generate_sequence_packing_code(code) class ListNode(SequenceNode): # List constructor. # obj_conversion_errors [PyrexError] used internally # orignial_args [ExprNode] used internally obj_conversion_errors = [] type = list_type in_module_scope = False gil_message = "Constructing Python list" def type_dependencies(self, env): return () def infer_type(self, env): # TODO: Infer non-object list arrays. return list_type def analyse_expressions(self, env): for arg in self.args: if arg.is_starred: arg.starred_expr_allowed_here = True node = SequenceNode.analyse_expressions(self, env) return node.coerce_to_pyobject(env) def analyse_types(self, env): with local_errors(ignore=True) as errors: self.original_args = list(self.args) node = SequenceNode.analyse_types(self, env) node.obj_conversion_errors = errors if env.is_module_scope: self.in_module_scope = True node = node._create_merge_node_if_necessary(env) return node def coerce_to(self, dst_type, env): if dst_type.is_pyobject: for err in self.obj_conversion_errors: report_error(err) self.obj_conversion_errors = [] if not self.type.subtype_of(dst_type): error(self.pos, "Cannot coerce list to type '%s'" % dst_type) elif (dst_type.is_array or dst_type.is_ptr) and dst_type.base_type is not PyrexTypes.c_void_type: array_length = len(self.args) if self.mult_factor: if isinstance(self.mult_factor.constant_result, _py_int_types): if self.mult_factor.constant_result <= 0: error(self.pos, "Cannot coerce non-positively multiplied list to '%s'" % dst_type) else: array_length *= self.mult_factor.constant_result else: error(self.pos, "Cannot coerce dynamically multiplied list to '%s'" % dst_type) base_type = dst_type.base_type self.type = PyrexTypes.CArrayType(base_type, array_length) for i in range(len(self.original_args)): arg = self.args[i] if isinstance(arg, CoerceToPyTypeNode): arg = arg.arg self.args[i] = arg.coerce_to(base_type, env) elif dst_type.is_cpp_class: # TODO(robertwb): Avoid object conversion for vector/list/set. return TypecastNode(self.pos, operand=self, type=PyrexTypes.py_object_type).coerce_to(dst_type, env) elif self.mult_factor: error(self.pos, "Cannot coerce multiplied list to '%s'" % dst_type) elif dst_type.is_struct: if len(self.args) > len(dst_type.scope.var_entries): error(self.pos, "Too many members for '%s'" % dst_type) else: if len(self.args) < len(dst_type.scope.var_entries): warning(self.pos, "Too few members for '%s'" % dst_type, 1) for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)): if isinstance(arg, CoerceToPyTypeNode): arg = arg.arg self.args[i] = arg.coerce_to(member.type, env) self.type = dst_type elif dst_type.is_ctuple: return self.coerce_to_ctuple(dst_type, env) else: self.type = error_type error(self.pos, "Cannot coerce list to type '%s'" % dst_type) return self def as_list(self): # dummy for compatibility with TupleNode return self def as_tuple(self): t = TupleNode(self.pos, args=self.args, mult_factor=self.mult_factor) if isinstance(self.constant_result, list): t.constant_result = tuple(self.constant_result) return t def allocate_temp_result(self, code): if self.type.is_array: if self.in_module_scope: self.temp_code = code.funcstate.allocate_temp( self.type, manage_ref=False, static=True, reusable=False) else: # To be valid C++, we must allocate the memory on the stack # manually and be sure not to reuse it for something else. # Yes, this means that we leak a temp array variable. self.temp_code = code.funcstate.allocate_temp( self.type, manage_ref=False, reusable=False) else: SequenceNode.allocate_temp_result(self, code) def calculate_constant_result(self): if self.mult_factor: raise ValueError() # may exceed the compile time memory self.constant_result = [ arg.constant_result for arg in self.args] def compile_time_value(self, denv): l = self.compile_time_value_list(denv) if self.mult_factor: l *= self.mult_factor.compile_time_value(denv) return l def generate_operation_code(self, code): if self.type.is_pyobject: for err in self.obj_conversion_errors: report_error(err) self.generate_sequence_packing_code(code) elif self.type.is_array: if self.mult_factor: code.putln("{") code.putln("Py_ssize_t %s;" % Naming.quick_temp_cname) code.putln("for ({i} = 0; {i} < {count}; {i}++) {{".format( i=Naming.quick_temp_cname, count=self.mult_factor.result())) offset = '+ (%d * %s)' % (len(self.args), Naming.quick_temp_cname) else: offset = '' for i, arg in enumerate(self.args): if arg.type.is_array: code.globalstate.use_utility_code(UtilityCode.load_cached("IncludeStringH", "StringTools.c")) code.putln("memcpy(&(%s[%s%s]), %s, sizeof(%s[0]));" % ( self.result(), i, offset, arg.result(), self.result() )) else: code.putln("%s[%s%s] = %s;" % ( self.result(), i, offset, arg.result())) if self.mult_factor: code.putln("}") code.putln("}") elif self.type.is_struct: for arg, member in zip(self.args, self.type.scope.var_entries): code.putln("%s.%s = %s;" % ( self.result(), member.cname, arg.result())) else: raise InternalError("List type never specified") class ComprehensionNode(ScopedExprNode): # A list/set/dict comprehension child_attrs = ["loop"] is_temp = True constant_result = not_a_constant def infer_type(self, env): return self.type def analyse_declarations(self, env): self.append.target = self # this is used in the PyList_Append of the inner loop self.init_scope(env) # setup loop scope if isinstance(self.loop, Nodes._ForInStatNode): assert isinstance(self.loop.iterator, ScopedExprNode), self.loop.iterator self.loop.iterator.init_scope(None, env) else: assert isinstance(self.loop, Nodes.ForFromStatNode), self.loop def analyse_scoped_declarations(self, env): self.loop.analyse_declarations(env) def analyse_types(self, env): if not self.has_local_scope: self.loop = self.loop.analyse_expressions(env) return self def analyse_scoped_expressions(self, env): if self.has_local_scope: self.loop = self.loop.analyse_expressions(env) return self def may_be_none(self): return False def generate_result_code(self, code): self.generate_operation_code(code) def generate_operation_code(self, code): if self.type is Builtin.list_type: create_code = 'PyList_New(0)' elif self.type is Builtin.set_type: create_code = 'PySet_New(NULL)' elif self.type is Builtin.dict_type: create_code = 'PyDict_New()' else: raise InternalError("illegal type for comprehension: %s" % self.type) code.putln('%s = %s; %s' % ( self.result(), create_code, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) self.loop.generate_execution_code(code) def annotate(self, code): self.loop.annotate(code) class ComprehensionAppendNode(Node): # Need to be careful to avoid infinite recursion: # target must not be in child_attrs/subexprs child_attrs = ['expr'] target = None type = PyrexTypes.c_int_type def analyse_expressions(self, env): self.expr = self.expr.analyse_expressions(env) if not self.expr.type.is_pyobject: self.expr = self.expr.coerce_to_pyobject(env) return self def generate_execution_code(self, code): if self.target.type is list_type: code.globalstate.use_utility_code( UtilityCode.load_cached("ListCompAppend", "Optimize.c")) function = "__Pyx_ListComp_Append" elif self.target.type is set_type: function = "PySet_Add" else: raise InternalError( "Invalid type for comprehension node: %s" % self.target.type) self.expr.generate_evaluation_code(code) code.putln(code.error_goto_if("%s(%s, (PyObject*)%s)" % ( function, self.target.result(), self.expr.result() ), self.pos)) self.expr.generate_disposal_code(code) self.expr.free_temps(code) def generate_function_definitions(self, env, code): self.expr.generate_function_definitions(env, code) def annotate(self, code): self.expr.annotate(code) class DictComprehensionAppendNode(ComprehensionAppendNode): child_attrs = ['key_expr', 'value_expr'] def analyse_expressions(self, env): self.key_expr = self.key_expr.analyse_expressions(env) if not self.key_expr.type.is_pyobject: self.key_expr = self.key_expr.coerce_to_pyobject(env) self.value_expr = self.value_expr.analyse_expressions(env) if not self.value_expr.type.is_pyobject: self.value_expr = self.value_expr.coerce_to_pyobject(env) return self def generate_execution_code(self, code): self.key_expr.generate_evaluation_code(code) self.value_expr.generate_evaluation_code(code) code.putln(code.error_goto_if("PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s)" % ( self.target.result(), self.key_expr.result(), self.value_expr.result() ), self.pos)) self.key_expr.generate_disposal_code(code) self.key_expr.free_temps(code) self.value_expr.generate_disposal_code(code) self.value_expr.free_temps(code) def generate_function_definitions(self, env, code): self.key_expr.generate_function_definitions(env, code) self.value_expr.generate_function_definitions(env, code) def annotate(self, code): self.key_expr.annotate(code) self.value_expr.annotate(code) class InlinedGeneratorExpressionNode(ExprNode): # An inlined generator expression for which the result is calculated # inside of the loop and returned as a single, first and only Generator # return value. # This will only be created by transforms when replacing safe builtin # calls on generator expressions. # # gen GeneratorExpressionNode the generator, not containing any YieldExprNodes # orig_func String the name of the builtin function this node replaces # target ExprNode or None a 'target' for a ComprehensionAppend node subexprs = ["gen"] orig_func = None target = None is_temp = True type = py_object_type def __init__(self, pos, gen, comprehension_type=None, **kwargs): gbody = gen.def_node.gbody gbody.is_inlined = True if comprehension_type is not None: assert comprehension_type in (list_type, set_type, dict_type), comprehension_type gbody.inlined_comprehension_type = comprehension_type kwargs.update( target=RawCNameExprNode(pos, comprehension_type, Naming.retval_cname), type=comprehension_type, ) super(InlinedGeneratorExpressionNode, self).__init__(pos, gen=gen, **kwargs) def may_be_none(self): return self.orig_func not in ('any', 'all', 'sorted') def infer_type(self, env): return self.type def analyse_types(self, env): self.gen = self.gen.analyse_expressions(env) return self def generate_result_code(self, code): code.putln("%s = __Pyx_Generator_Next(%s); %s" % ( self.result(), self.gen.result(), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) class MergedSequenceNode(ExprNode): """ Merge a sequence of iterables into a set/list/tuple. The target collection is determined by self.type, which must be set externally. args [ExprNode] """ subexprs = ['args'] is_temp = True gil_message = "Constructing Python collection" def __init__(self, pos, args, type): if type in (list_type, tuple_type) and args and args[0].is_sequence_constructor: # construct a list directly from the first argument that we can then extend if args[0].type is not list_type: args[0] = ListNode(args[0].pos, args=args[0].args, is_temp=True, mult_factor=args[0].mult_factor) ExprNode.__init__(self, pos, args=args, type=type) def calculate_constant_result(self): result = [] for item in self.args: if item.is_sequence_constructor and item.mult_factor: if item.mult_factor.constant_result <= 0: continue # otherwise, adding each item once should be enough if item.is_set_literal or item.is_sequence_constructor: # process items in order items = (arg.constant_result for arg in item.args) else: items = item.constant_result result.extend(items) if self.type is set_type: result = set(result) elif self.type is tuple_type: result = tuple(result) else: assert self.type is list_type self.constant_result = result def compile_time_value(self, denv): result = [] for item in self.args: if item.is_sequence_constructor and item.mult_factor: if item.mult_factor.compile_time_value(denv) <= 0: continue if item.is_set_literal or item.is_sequence_constructor: # process items in order items = (arg.compile_time_value(denv) for arg in item.args) else: items = item.compile_time_value(denv) result.extend(items) if self.type is set_type: try: result = set(result) except Exception as e: self.compile_time_value_error(e) elif self.type is tuple_type: result = tuple(result) else: assert self.type is list_type return result def type_dependencies(self, env): return () def infer_type(self, env): return self.type def analyse_types(self, env): args = [ arg.analyse_types(env).coerce_to_pyobject(env).as_none_safe_node( # FIXME: CPython's error message starts with the runtime function name 'argument after * must be an iterable, not NoneType') for arg in self.args ] if len(args) == 1 and args[0].type is self.type: # strip this intermediate node and use the bare collection return args[0] assert self.type in (set_type, list_type, tuple_type) self.args = args return self def may_be_none(self): return False def generate_evaluation_code(self, code): code.mark_pos(self.pos) self.allocate_temp_result(code) is_set = self.type is set_type args = iter(self.args) item = next(args) item.generate_evaluation_code(code) if (is_set and item.is_set_literal or not is_set and item.is_sequence_constructor and item.type is list_type): code.putln("%s = %s;" % (self.result(), item.py_result())) item.generate_post_assignment_code(code) else: code.putln("%s = %s(%s); %s" % ( self.result(), 'PySet_New' if is_set else "__Pyx_PySequence_ListKeepNew" if item.is_temp and item.type in (py_object_type, list_type) else "PySequence_List", item.py_result(), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) item.generate_disposal_code(code) item.free_temps(code) helpers = set() if is_set: add_func = "PySet_Add" extend_func = "__Pyx_PySet_Update" else: add_func = "__Pyx_ListComp_Append" extend_func = "__Pyx_PyList_Extend" for item in args: if (is_set and (item.is_set_literal or item.is_sequence_constructor) or (item.is_sequence_constructor and not item.mult_factor)): if not is_set and item.args: helpers.add(("ListCompAppend", "Optimize.c")) for arg in item.args: arg.generate_evaluation_code(code) code.put_error_if_neg(arg.pos, "%s(%s, %s)" % ( add_func, self.result(), arg.py_result())) arg.generate_disposal_code(code) arg.free_temps(code) continue if is_set: helpers.add(("PySet_Update", "Builtins.c")) else: helpers.add(("ListExtend", "Optimize.c")) item.generate_evaluation_code(code) code.put_error_if_neg(item.pos, "%s(%s, %s)" % ( extend_func, self.result(), item.py_result())) item.generate_disposal_code(code) item.free_temps(code) if self.type is tuple_type: code.putln("{") code.putln("PyObject *%s = PyList_AsTuple(%s);" % ( Naming.quick_temp_cname, self.result())) code.put_decref(self.result(), py_object_type) code.putln("%s = %s; %s" % ( self.result(), Naming.quick_temp_cname, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) code.putln("}") for helper in sorted(helpers): code.globalstate.use_utility_code(UtilityCode.load_cached(*helper)) def annotate(self, code): for item in self.args: item.annotate(code) class SetNode(ExprNode): """ Set constructor. """ subexprs = ['args'] type = set_type is_set_literal = True gil_message = "Constructing Python set" def analyse_types(self, env): for i in range(len(self.args)): arg = self.args[i] arg = arg.analyse_types(env) self.args[i] = arg.coerce_to_pyobject(env) self.type = set_type self.is_temp = 1 return self def may_be_none(self): return False def calculate_constant_result(self): self.constant_result = {arg.constant_result for arg in self.args} def compile_time_value(self, denv): values = [arg.compile_time_value(denv) for arg in self.args] try: return set(values) except Exception as e: self.compile_time_value_error(e) def generate_evaluation_code(self, code): for arg in self.args: arg.generate_evaluation_code(code) self.allocate_temp_result(code) code.putln( "%s = PySet_New(0); %s" % ( self.result(), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) for arg in self.args: code.put_error_if_neg( self.pos, "PySet_Add(%s, %s)" % (self.result(), arg.py_result())) arg.generate_disposal_code(code) arg.free_temps(code) class DictNode(ExprNode): # Dictionary constructor. # # key_value_pairs [DictItemNode] # exclude_null_values [boolean] Do not add NULL values to dict # # obj_conversion_errors [PyrexError] used internally subexprs = ['key_value_pairs'] is_temp = 1 exclude_null_values = False type = dict_type is_dict_literal = True reject_duplicates = False obj_conversion_errors = [] @classmethod def from_pairs(cls, pos, pairs): return cls(pos, key_value_pairs=[ DictItemNode(pos, key=k, value=v) for k, v in pairs]) def calculate_constant_result(self): self.constant_result = dict([ item.constant_result for item in self.key_value_pairs]) def compile_time_value(self, denv): pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv)) for item in self.key_value_pairs] try: return dict(pairs) except Exception as e: self.compile_time_value_error(e) def type_dependencies(self, env): return () def infer_type(self, env): # TODO: Infer struct constructors. return dict_type def analyse_types(self, env): with local_errors(ignore=True) as errors: self.key_value_pairs = [ item.analyse_types(env) for item in self.key_value_pairs ] self.obj_conversion_errors = errors return self def may_be_none(self): return False def coerce_to(self, dst_type, env): if dst_type.is_pyobject: self.release_errors() if self.type.is_struct_or_union: if not dict_type.subtype_of(dst_type): error(self.pos, "Cannot interpret struct as non-dict type '%s'" % dst_type) return DictNode(self.pos, key_value_pairs=[ DictItemNode(item.pos, key=item.key.coerce_to_pyobject(env), value=item.value.coerce_to_pyobject(env)) for item in self.key_value_pairs]) if not self.type.subtype_of(dst_type): error(self.pos, "Cannot interpret dict as type '%s'" % dst_type) elif dst_type.is_struct_or_union: self.type = dst_type if not dst_type.is_struct and len(self.key_value_pairs) != 1: error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type) elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries): warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1) for item in self.key_value_pairs: if isinstance(item.key, CoerceToPyTypeNode): item.key = item.key.arg if not item.key.is_string_literal: error(item.key.pos, "Invalid struct field identifier") item.key = StringNode(item.key.pos, value="") else: key = str(item.key.value) # converts string literals to unicode in Py3 member = dst_type.scope.lookup_here(key) if not member: error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, key)) else: value = item.value if isinstance(value, CoerceToPyTypeNode): value = value.arg item.value = value.coerce_to(member.type, env) else: return super(DictNode, self).coerce_to(dst_type, env) return self def release_errors(self): for err in self.obj_conversion_errors: report_error(err) self.obj_conversion_errors = [] gil_message = "Constructing Python dict" def generate_evaluation_code(self, code): # Custom method used here because key-value # pairs are evaluated and used one at a time. code.mark_pos(self.pos) self.allocate_temp_result(code) is_dict = self.type.is_pyobject if is_dict: self.release_errors() code.putln( "%s = __Pyx_PyDict_NewPresized(%d); %s" % ( self.result(), len(self.key_value_pairs), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) keys_seen = set() key_type = None needs_error_helper = False for item in self.key_value_pairs: item.generate_evaluation_code(code) if is_dict: if self.exclude_null_values: code.putln('if (%s) {' % item.value.py_result()) key = item.key if self.reject_duplicates: if keys_seen is not None: # avoid runtime 'in' checks for literals that we can do at compile time if not key.is_string_literal: keys_seen = None elif key.value in keys_seen: # FIXME: this could be a compile time error, at least in Cython code keys_seen = None elif key_type is not type(key.value): if key_type is None: key_type = type(key.value) keys_seen.add(key.value) else: # different types => may not be able to compare at compile time keys_seen = None else: keys_seen.add(key.value) if keys_seen is None: code.putln('if (unlikely(PyDict_Contains(%s, %s))) {' % ( self.result(), key.py_result())) # currently only used in function calls needs_error_helper = True code.putln('__Pyx_RaiseDoubleKeywordsError("function", %s); %s' % ( key.py_result(), code.error_goto(item.pos))) code.putln("} else {") code.put_error_if_neg(self.pos, "PyDict_SetItem(%s, %s, %s)" % ( self.result(), item.key.py_result(), item.value.py_result())) if self.reject_duplicates and keys_seen is None: code.putln('}') if self.exclude_null_values: code.putln('}') else: if item.value.type.is_array: code.putln("memcpy(%s.%s, %s, sizeof(%s));" % ( self.result(), item.key.value, item.value.result(), item.value.result())) else: code.putln("%s.%s = %s;" % ( self.result(), item.key.value, item.value.result())) item.generate_disposal_code(code) item.free_temps(code) if needs_error_helper: code.globalstate.use_utility_code( UtilityCode.load_cached("RaiseDoubleKeywords", "FunctionArguments.c")) def annotate(self, code): for item in self.key_value_pairs: item.annotate(code) def as_python_dict(self): # returns a dict with constant keys and Node values # (only works on DictNodes where the keys are ConstNodes or PyConstNode) return dict([(key.value, value) for key, value in self.key_value_pairs]) class DictItemNode(ExprNode): # Represents a single item in a DictNode # # key ExprNode # value ExprNode subexprs = ['key', 'value'] nogil_check = None # Parent DictNode takes care of it def calculate_constant_result(self): self.constant_result = ( self.key.constant_result, self.value.constant_result) def analyse_types(self, env): self.key = self.key.analyse_types(env) self.value = self.value.analyse_types(env) self.key = self.key.coerce_to_pyobject(env) self.value = self.value.coerce_to_pyobject(env) return self def generate_evaluation_code(self, code): self.key.generate_evaluation_code(code) self.value.generate_evaluation_code(code) def generate_disposal_code(self, code): self.key.generate_disposal_code(code) self.value.generate_disposal_code(code) def free_temps(self, code): self.key.free_temps(code) self.value.free_temps(code) def __iter__(self): return iter([self.key, self.value]) class SortedDictKeysNode(ExprNode): # build sorted list of dict keys, e.g. for dir() subexprs = ['arg'] is_temp = True def __init__(self, arg): ExprNode.__init__(self, arg.pos, arg=arg) self.type = Builtin.list_type def analyse_types(self, env): arg = self.arg.analyse_types(env) if arg.type is Builtin.dict_type: arg = arg.as_none_safe_node( "'NoneType' object is not iterable") self.arg = arg return self def may_be_none(self): return False def generate_result_code(self, code): dict_result = self.arg.py_result() if self.arg.type is Builtin.dict_type: code.putln('%s = PyDict_Keys(%s); %s' % ( self.result(), dict_result, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) else: # originally used PyMapping_Keys() here, but that may return a tuple code.globalstate.use_utility_code(UtilityCode.load_cached( 'PyObjectCallMethod0', 'ObjectHandling.c')) keys_cname = code.intern_identifier(StringEncoding.EncodedString("keys")) code.putln('%s = __Pyx_PyObject_CallMethod0(%s, %s); %s' % ( self.result(), dict_result, keys_cname, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) code.putln("if (unlikely(!PyList_Check(%s))) {" % self.result()) self.generate_decref_set(code, "PySequence_List(%s)" % self.result()) code.putln(code.error_goto_if_null(self.result(), self.pos)) self.generate_gotref(code) code.putln("}") code.put_error_if_neg( self.pos, 'PyList_Sort(%s)' % self.py_result()) class ModuleNameMixin(object): def get_py_mod_name(self, code): return code.get_py_string_const( self.module_name, identifier=True) def get_py_qualified_name(self, code): return code.get_py_string_const( self.qualname, identifier=True) class ClassNode(ExprNode, ModuleNameMixin): # Helper class used in the implementation of Python # class definitions. Constructs a class object given # a name, tuple of bases and class dictionary. # # name EncodedString Name of the class # class_def_node PyClassDefNode PyClassDefNode defining this class # doc ExprNode or None Doc string # module_name EncodedString Name of defining module subexprs = ['doc'] type = py_object_type is_temp = True def analyse_annotations(self, env): pass def infer_type(self, env): # TODO: could return 'type' in some cases return py_object_type def analyse_types(self, env): if self.doc: self.doc = self.doc.analyse_types(env) self.doc = self.doc.coerce_to_pyobject(env) env.use_utility_code(UtilityCode.load_cached("CreateClass", "ObjectHandling.c")) return self def may_be_none(self): return True gil_message = "Constructing Python class" def generate_result_code(self, code): class_def_node = self.class_def_node cname = code.intern_identifier(self.name) if self.doc: code.put_error_if_neg(self.pos, 'PyDict_SetItem(%s, %s, %s)' % ( class_def_node.dict.py_result(), code.intern_identifier( StringEncoding.EncodedString("__doc__")), self.doc.py_result())) py_mod_name = self.get_py_mod_name(code) qualname = self.get_py_qualified_name(code) code.putln( '%s = __Pyx_CreateClass(%s, %s, %s, %s, %s); %s' % ( self.result(), class_def_node.bases.py_result(), class_def_node.dict.py_result(), cname, qualname, py_mod_name, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) class Py3ClassNode(ExprNode): # Helper class used in the implementation of Python3+ # class definitions. Constructs a class object given # a name, tuple of bases and class dictionary. # # name EncodedString Name of the class # module_name EncodedString Name of defining module # class_def_node PyClassDefNode PyClassDefNode defining this class # calculate_metaclass bool should call CalculateMetaclass() # allow_py2_metaclass bool should look for Py2 metaclass # force_type bool always create a "new style" class, even with no bases subexprs = [] type = py_object_type force_type = False is_temp = True def infer_type(self, env): # TODO: could return 'type' in some cases return py_object_type def analyse_types(self, env): return self def may_be_none(self): return True gil_message = "Constructing Python class" def analyse_annotations(self, env): from .AutoDocTransforms import AnnotationWriter position = self.class_def_node.pos dict_items = [ DictItemNode( entry.pos, key=IdentifierStringNode(entry.pos, value=entry.name), value=entry.annotation.string ) for entry in env.entries.values() if entry.annotation ] # Annotations dict shouldn't exist for classes which don't declare any. if dict_items: annotations_dict = DictNode(position, key_value_pairs=dict_items) lhs = NameNode(position, name=StringEncoding.EncodedString(u"__annotations__")) lhs.entry = env.lookup_here(lhs.name) or env.declare_var(lhs.name, dict_type, position) node = SingleAssignmentNode(position, lhs=lhs, rhs=annotations_dict) node.analyse_declarations(env) self.class_def_node.body.stats.insert(0, node) def generate_result_code(self, code): code.globalstate.use_utility_code(UtilityCode.load_cached("Py3ClassCreate", "ObjectHandling.c")) cname = code.intern_identifier(self.name) class_def_node = self.class_def_node mkw = class_def_node.mkw.py_result() if class_def_node.mkw else 'NULL' if class_def_node.metaclass: metaclass = class_def_node.metaclass.py_result() elif self.force_type: metaclass = "((PyObject*)&PyType_Type)" else: metaclass = "((PyObject*)&__Pyx_DefaultClassType)" code.putln( '%s = __Pyx_Py3ClassCreate(%s, %s, %s, %s, %s, %d, %d); %s' % ( self.result(), metaclass, cname, class_def_node.bases.py_result(), class_def_node.dict.py_result(), mkw, self.calculate_metaclass, self.allow_py2_metaclass, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) class PyClassMetaclassNode(ExprNode): # Helper class holds Python3 metaclass object # # class_def_node PyClassDefNode PyClassDefNode defining this class subexprs = [] def analyse_types(self, env): self.type = py_object_type self.is_temp = True return self def may_be_none(self): return True def generate_result_code(self, code): bases = self.class_def_node.bases mkw = self.class_def_node.mkw if mkw: code.globalstate.use_utility_code( UtilityCode.load_cached("Py3MetaclassGet", "ObjectHandling.c")) call = "__Pyx_Py3MetaclassGet(%s, %s)" % ( bases.result(), mkw.result()) else: code.globalstate.use_utility_code( UtilityCode.load_cached("CalculateMetaclass", "ObjectHandling.c")) call = "__Pyx_CalculateMetaclass(NULL, %s)" % ( bases.result()) code.putln( "%s = %s; %s" % ( self.result(), call, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) class PyClassNamespaceNode(ExprNode, ModuleNameMixin): # Helper class holds Python3 namespace object # # All this are not owned by this node # class_def_node PyClassDefNode PyClassDefNode defining this class # doc ExprNode or None Doc string (owned) subexprs = ['doc'] def analyse_types(self, env): if self.doc: self.doc = self.doc.analyse_types(env).coerce_to_pyobject(env) self.type = py_object_type self.is_temp = 1 return self def may_be_none(self): return True def generate_result_code(self, code): cname = code.intern_identifier(self.name) py_mod_name = self.get_py_mod_name(code) qualname = self.get_py_qualified_name(code) class_def_node = self.class_def_node null = "(PyObject *) NULL" doc_code = self.doc.result() if self.doc else null mkw = class_def_node.mkw.py_result() if class_def_node.mkw else null metaclass = class_def_node.metaclass.py_result() if class_def_node.metaclass else null code.putln( "%s = __Pyx_Py3MetaclassPrepare(%s, %s, %s, %s, %s, %s, %s); %s" % ( self.result(), metaclass, class_def_node.bases.result(), cname, qualname, mkw, py_mod_name, doc_code, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) class ClassCellInjectorNode(ExprNode): # Initialize CyFunction.func_classobj is_temp = True type = py_object_type subexprs = [] is_active = False def analyse_expressions(self, env): return self def generate_result_code(self, code): assert self.is_active code.putln( '%s = PyList_New(0); %s' % ( self.result(), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) def generate_injection_code(self, code, classobj_cname): assert self.is_active code.globalstate.use_utility_code( UtilityCode.load_cached("CyFunctionClassCell", "CythonFunction.c")) code.put_error_if_neg(self.pos, '__Pyx_CyFunction_InitClassCell(%s, %s)' % ( self.result(), classobj_cname)) class ClassCellNode(ExprNode): # Class Cell for noargs super() subexprs = [] is_temp = True is_generator = False type = py_object_type def analyse_types(self, env): return self def generate_result_code(self, code): if not self.is_generator: code.putln('%s = __Pyx_CyFunction_GetClassObj(%s);' % ( self.result(), Naming.self_cname)) else: code.putln('%s = %s->classobj;' % ( self.result(), Naming.generator_cname)) code.putln( 'if (!%s) { PyErr_SetString(PyExc_SystemError, ' '"super(): empty __class__ cell"); %s }' % ( self.result(), code.error_goto(self.pos))) code.put_incref(self.result(), py_object_type) class PyCFunctionNode(ExprNode, ModuleNameMixin): # Helper class used in the implementation of Python # functions. Constructs a PyCFunction object # from a PyMethodDef struct. # # pymethdef_cname string PyMethodDef structure # binding bool # def_node DefNode the Python function node # module_name EncodedString Name of defining module # code_object CodeObjectNode the PyCodeObject creator node subexprs = ['code_object', 'defaults_tuple', 'defaults_kwdict', 'annotations_dict'] code_object = None binding = False def_node = None defaults = None defaults_struct = None defaults_pyobjects = 0 defaults_tuple = None defaults_kwdict = None annotations_dict = None type = py_object_type is_temp = 1 specialized_cpdefs = None is_specialization = False @classmethod def from_defnode(cls, node, binding): return cls(node.pos, def_node=node, pymethdef_cname=node.entry.pymethdef_cname, binding=binding or node.specialized_cpdefs, specialized_cpdefs=node.specialized_cpdefs, code_object=CodeObjectNode(node)) def analyse_types(self, env): if self.binding: self.analyse_default_args(env) return self def analyse_default_args(self, env): """ Handle non-literal function's default arguments. """ nonliteral_objects = [] nonliteral_other = [] default_args = [] default_kwargs = [] annotations = [] # For global cpdef functions and def/cpdef methods in cdef classes, we must use global constants # for default arguments to avoid the dependency on the CyFunction object as 'self' argument # in the underlying C function. Basically, cpdef functions/methods are static C functions, # so their optional arguments must be static, too. # TODO: change CyFunction implementation to pass both function object and owning object for method calls must_use_constants = env.is_c_class_scope or (self.def_node.is_wrapper and env.is_module_scope) for arg in self.def_node.args: if arg.default: if not must_use_constants: if arg.default.is_literal: arg.default = DefaultLiteralArgNode(arg.pos, arg.default) if arg.default.type: arg.default = arg.default.coerce_to(arg.type, env) else: arg.is_dynamic = True if arg.type.is_pyobject: nonliteral_objects.append(arg) else: nonliteral_other.append(arg) if arg.default.type and arg.default.type.can_coerce_to_pyobject(env): if arg.kw_only: default_kwargs.append(arg) else: default_args.append(arg) if arg.annotation: arg.annotation = arg.annotation.analyse_types(env) annotations.append((arg.pos, arg.name, arg.annotation.string)) for arg in (self.def_node.star_arg, self.def_node.starstar_arg): if arg and arg.annotation: arg.annotation = arg.annotation.analyse_types(env) annotations.append((arg.pos, arg.name, arg.annotation.string)) annotation = self.def_node.return_type_annotation if annotation: self.def_node.return_type_annotation = annotation.analyse_types(env) annotations.append((annotation.pos, StringEncoding.EncodedString("return"), annotation.string)) if nonliteral_objects or nonliteral_other: module_scope = env.global_scope() cname = module_scope.next_id(Naming.defaults_struct_prefix) scope = Symtab.StructOrUnionScope(cname) self.defaults = [] for arg in nonliteral_objects: type_ = arg.type if type_.is_buffer: type_ = type_.base entry = scope.declare_var(arg.name, type_, None, Naming.arg_prefix + arg.name, allow_pyobject=True) self.defaults.append((arg, entry)) for arg in nonliteral_other: entry = scope.declare_var(arg.name, arg.type, None, Naming.arg_prefix + arg.name, allow_pyobject=False, allow_memoryview=True) self.defaults.append((arg, entry)) entry = module_scope.declare_struct_or_union( None, 'struct', scope, 1, None, cname=cname) self.defaults_struct = scope self.defaults_pyobjects = len(nonliteral_objects) for arg, entry in self.defaults: arg.default_value = '%s->%s' % ( Naming.dynamic_args_cname, entry.cname) self.def_node.defaults_struct = self.defaults_struct.name if default_args or default_kwargs: if self.defaults_struct is None: if default_args: defaults_tuple = TupleNode(self.pos, args=[ arg.default for arg in default_args]) self.defaults_tuple = defaults_tuple.analyse_types(env).coerce_to_pyobject(env) if default_kwargs: defaults_kwdict = DictNode(self.pos, key_value_pairs=[ DictItemNode( arg.pos, key=IdentifierStringNode(arg.pos, value=arg.name), value=arg.default) for arg in default_kwargs]) self.defaults_kwdict = defaults_kwdict.analyse_types(env) elif not self.specialized_cpdefs: # Fused dispatch functions do not support (dynamic) default arguments, only the specialisations do. if default_args: defaults_tuple = DefaultsTupleNode( self.pos, default_args, self.defaults_struct) else: defaults_tuple = NoneNode(self.pos) if default_kwargs: defaults_kwdict = DefaultsKwDictNode( self.pos, default_kwargs, self.defaults_struct) else: defaults_kwdict = NoneNode(self.pos) defaults_getter = Nodes.DefNode( self.pos, args=[], star_arg=None, starstar_arg=None, body=Nodes.ReturnStatNode( self.pos, return_type=py_object_type, value=TupleNode( self.pos, args=[defaults_tuple, defaults_kwdict])), decorators=None, name=StringEncoding.EncodedString("__defaults__")) # defaults getter must never live in class scopes, it's always a module function module_scope = env.global_scope() defaults_getter.analyse_declarations(module_scope) defaults_getter = defaults_getter.analyse_expressions(module_scope) defaults_getter.body = defaults_getter.body.analyse_expressions( defaults_getter.local_scope) defaults_getter.py_wrapper_required = False defaults_getter.pymethdef_required = False self.def_node.defaults_getter = defaults_getter if annotations: annotations_dict = DictNode(self.pos, key_value_pairs=[ DictItemNode( pos, key=IdentifierStringNode(pos, value=name), value=value) for pos, name, value in annotations]) self.annotations_dict = annotations_dict.analyse_types(env) def may_be_none(self): return False gil_message = "Constructing Python function" def closure_result_code(self): return "NULL" def generate_result_code(self, code): if self.binding: self.generate_cyfunction_code(code) else: self.generate_pycfunction_code(code) def generate_pycfunction_code(self, code): py_mod_name = self.get_py_mod_name(code) code.putln( '%s = PyCFunction_NewEx(&%s, %s, %s); %s' % ( self.result(), self.pymethdef_cname, self.closure_result_code(), py_mod_name, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) def generate_cyfunction_code(self, code): if self.specialized_cpdefs: def_node = self.specialized_cpdefs[0] else: def_node = self.def_node if self.specialized_cpdefs or self.is_specialization: code.globalstate.use_utility_code( UtilityCode.load_cached("FusedFunction", "CythonFunction.c")) constructor = "__pyx_FusedFunction_New" else: code.globalstate.use_utility_code( UtilityCode.load_cached("CythonFunction", "CythonFunction.c")) constructor = "__Pyx_CyFunction_New" if self.code_object: code_object_result = self.code_object.py_result() else: code_object_result = 'NULL' flags = [] if def_node.is_staticmethod: flags.append('__Pyx_CYFUNCTION_STATICMETHOD') elif def_node.is_classmethod: flags.append('__Pyx_CYFUNCTION_CLASSMETHOD') if def_node.local_scope.parent_scope.is_c_class_scope and not def_node.entry.is_anonymous: flags.append('__Pyx_CYFUNCTION_CCLASS') if def_node.is_coroutine: flags.append('__Pyx_CYFUNCTION_COROUTINE') if flags: flags = ' | '.join(flags) else: flags = '0' code.putln( '%s = %s(&%s, %s, %s, %s, %s, %s, %s); %s' % ( self.result(), constructor, self.pymethdef_cname, flags, self.get_py_qualified_name(code), self.closure_result_code(), self.get_py_mod_name(code), Naming.moddict_cname, code_object_result, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) if def_node.requires_classobj: assert code.pyclass_stack, "pyclass_stack is empty" class_node = code.pyclass_stack[-1] code.put_incref(self.py_result(), py_object_type) code.putln( 'PyList_Append(%s, %s);' % ( class_node.class_cell.result(), self.result())) self.generate_giveref(code) if self.defaults: code.putln( 'if (!__Pyx_CyFunction_InitDefaults(%s, sizeof(%s), %d)) %s' % ( self.result(), self.defaults_struct.name, self.defaults_pyobjects, code.error_goto(self.pos))) defaults = '__Pyx_CyFunction_Defaults(%s, %s)' % ( self.defaults_struct.name, self.result()) for arg, entry in self.defaults: arg.generate_assignment_code(code, target='%s->%s' % ( defaults, entry.cname)) if self.defaults_tuple: code.putln('__Pyx_CyFunction_SetDefaultsTuple(%s, %s);' % ( self.result(), self.defaults_tuple.py_result())) if not self.specialized_cpdefs: # disable introspection functions for fused dispatcher function since the user never sees it # TODO: this is mostly disabled because the attributes end up pointing to ones belonging # to the specializations - ideally this would be fixed instead if self.defaults_kwdict: code.putln('__Pyx_CyFunction_SetDefaultsKwDict(%s, %s);' % ( self.result(), self.defaults_kwdict.py_result())) if def_node.defaults_getter: code.putln('__Pyx_CyFunction_SetDefaultsGetter(%s, %s);' % ( self.result(), def_node.defaults_getter.entry.pyfunc_cname)) if self.annotations_dict: code.putln('__Pyx_CyFunction_SetAnnotationsDict(%s, %s);' % ( self.result(), self.annotations_dict.py_result())) class InnerFunctionNode(PyCFunctionNode): # Special PyCFunctionNode that depends on a closure class binding = True needs_closure_code = True def closure_result_code(self): if self.needs_closure_code: return "((PyObject*)%s)" % Naming.cur_scope_cname return "NULL" class CodeObjectNode(ExprNode): # Create a PyCodeObject for a CyFunction instance. # # def_node DefNode the Python function node # varnames TupleNode a tuple with all local variable names subexprs = ['varnames'] is_temp = False result_code = None def __init__(self, def_node): ExprNode.__init__(self, def_node.pos, def_node=def_node) args = list(def_node.args) # if we have args/kwargs, then the first two in var_entries are those local_vars = [arg for arg in def_node.local_scope.var_entries if arg.name] self.varnames = TupleNode( def_node.pos, args=[IdentifierStringNode(arg.pos, value=arg.name) for arg in args + local_vars], is_temp=0, is_literal=1) def may_be_none(self): return False def calculate_result_code(self, code=None): if self.result_code is None: self.result_code = code.get_py_const(py_object_type, 'codeobj', cleanup_level=2) return self.result_code def generate_result_code(self, code): if self.result_code is None: self.result_code = code.get_py_const(py_object_type, 'codeobj', cleanup_level=2) code = code.get_cached_constants_writer(self.result_code) if code is None: return # already initialised code.mark_pos(self.pos) func = self.def_node func_name = code.get_py_string_const( func.name, identifier=True, is_str=False, unicode_value=func.name) # FIXME: better way to get the module file path at module init time? Encoding to use? file_path = StringEncoding.bytes_literal(func.pos[0].get_filenametable_entry().encode('utf8'), 'utf8') file_path_const = code.get_py_string_const(file_path, identifier=False, is_str=True) # This combination makes CPython create a new dict for "frame.f_locals" (see GH #1836). flags = ['CO_OPTIMIZED', 'CO_NEWLOCALS'] if self.def_node.star_arg: flags.append('CO_VARARGS') if self.def_node.starstar_arg: flags.append('CO_VARKEYWORDS') if self.def_node.is_asyncgen: flags.append('CO_ASYNC_GENERATOR') elif self.def_node.is_coroutine: flags.append('CO_COROUTINE') elif self.def_node.is_generator: flags.append('CO_GENERATOR') code.putln("%s = (PyObject*)__Pyx_PyCode_New(%d, %d, %d, %d, 0, %s, %s, %s, %s, %s, %s, %s, %s, %s, %d, %s); %s" % ( self.result_code, len(func.args) - func.num_kwonly_args, # argcount func.num_posonly_args, # posonlyargcount (Py3.8+ only) func.num_kwonly_args, # kwonlyargcount (Py3 only) len(self.varnames.args), # nlocals '|'.join(flags) or '0', # flags Naming.empty_bytes, # code Naming.empty_tuple, # consts Naming.empty_tuple, # names (FIXME) self.varnames.result(), # varnames Naming.empty_tuple, # freevars (FIXME) Naming.empty_tuple, # cellvars (FIXME) file_path_const, # filename func_name, # name self.pos[1], # firstlineno Naming.empty_bytes, # lnotab code.error_goto_if_null(self.result_code, self.pos), )) class DefaultLiteralArgNode(ExprNode): # CyFunction's literal argument default value # # Evaluate literal only once. subexprs = [] is_literal = True is_temp = False def __init__(self, pos, arg): super(DefaultLiteralArgNode, self).__init__(pos) self.arg = arg self.constant_result = arg.constant_result self.type = self.arg.type self.evaluated = False def analyse_types(self, env): return self def generate_result_code(self, code): pass def generate_evaluation_code(self, code): if not self.evaluated: self.arg.generate_evaluation_code(code) self.evaluated = True def result(self): return self.type.cast_code(self.arg.result()) class DefaultNonLiteralArgNode(ExprNode): # CyFunction's non-literal argument default value subexprs = [] def __init__(self, pos, arg, defaults_struct): super(DefaultNonLiteralArgNode, self).__init__(pos) self.arg = arg self.defaults_struct = defaults_struct def analyse_types(self, env): self.type = self.arg.type self.is_temp = False return self def generate_result_code(self, code): pass def result(self): return '__Pyx_CyFunction_Defaults(%s, %s)->%s' % ( self.defaults_struct.name, Naming.self_cname, self.defaults_struct.lookup(self.arg.name).cname) class DefaultsTupleNode(TupleNode): # CyFunction's __defaults__ tuple def __init__(self, pos, defaults, defaults_struct): args = [] for arg in defaults: if not arg.default.is_literal: arg = DefaultNonLiteralArgNode(pos, arg, defaults_struct) else: arg = arg.default args.append(arg) super(DefaultsTupleNode, self).__init__(pos, args=args) def analyse_types(self, env, skip_children=False): return super(DefaultsTupleNode, self).analyse_types(env, skip_children).coerce_to_pyobject(env) class DefaultsKwDictNode(DictNode): # CyFunction's __kwdefaults__ dict def __init__(self, pos, defaults, defaults_struct): items = [] for arg in defaults: name = IdentifierStringNode(arg.pos, value=arg.name) if not arg.default.is_literal: arg = DefaultNonLiteralArgNode(pos, arg, defaults_struct) else: arg = arg.default items.append(DictItemNode(arg.pos, key=name, value=arg)) super(DefaultsKwDictNode, self).__init__(pos, key_value_pairs=items) class LambdaNode(InnerFunctionNode): # Lambda expression node (only used as a function reference) # # args [CArgDeclNode] formal arguments # star_arg PyArgDeclNode or None * argument # starstar_arg PyArgDeclNode or None ** argument # lambda_name string a module-globally unique lambda name # result_expr ExprNode # def_node DefNode the underlying function 'def' node child_attrs = ['def_node'] name = StringEncoding.EncodedString('') def analyse_declarations(self, env): if hasattr(self, "lambda_name"): # this if-statement makes it safe to run twice return self.lambda_name = self.def_node.lambda_name = env.next_id('lambda') self.def_node.no_assignment_synthesis = True self.def_node.pymethdef_required = True self.def_node.is_cyfunction = True self.def_node.analyse_declarations(env) self.pymethdef_cname = self.def_node.entry.pymethdef_cname env.add_lambda_def(self.def_node) def analyse_types(self, env): self.def_node = self.def_node.analyse_expressions(env) return super(LambdaNode, self).analyse_types(env) def generate_result_code(self, code): self.def_node.generate_execution_code(code) super(LambdaNode, self).generate_result_code(code) class GeneratorExpressionNode(LambdaNode): # A generator expression, e.g. (i for i in range(10)) # # Result is a generator. # # loop ForStatNode the for-loop, containing a YieldExprNode # def_node DefNode the underlying generator 'def' node # call_parameters [ExprNode] (Internal) parameters passed to the DefNode call name = StringEncoding.EncodedString('genexpr') binding = False child_attrs = LambdaNode.child_attrs + ["call_parameters"] subexprs = LambdaNode.subexprs + ["call_parameters"] def __init__(self, pos, *args, **kwds): super(GeneratorExpressionNode, self).__init__(pos, *args, **kwds) self.call_parameters = [] def analyse_declarations(self, env): if hasattr(self, "genexpr_name"): # this if-statement makes it safe to run twice return self.genexpr_name = env.next_id('genexpr') super(GeneratorExpressionNode, self).analyse_declarations(env) # No pymethdef required self.def_node.pymethdef_required = False self.def_node.py_wrapper_required = False self.def_node.is_cyfunction = False # Force genexpr signature self.def_node.entry.signature = TypeSlots.pyfunction_noargs # setup loop scope if isinstance(self.loop, Nodes._ForInStatNode): assert isinstance(self.loop.iterator, ScopedExprNode) self.loop.iterator.init_scope(None, env) else: assert isinstance(self.loop, Nodes.ForFromStatNode) def generate_result_code(self, code): args_to_call = ([self.closure_result_code()] + [ cp.result() for cp in self.call_parameters ]) args_to_call = ", ".join(args_to_call) code.putln( '%s = %s(%s); %s' % ( self.result(), self.def_node.entry.pyfunc_cname, args_to_call, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) class YieldExprNode(ExprNode): # Yield expression node # # arg ExprNode the value to return from the generator # label_num integer yield label number # is_yield_from boolean is a YieldFromExprNode to delegate to another generator subexprs = ['arg'] type = py_object_type label_num = 0 is_yield_from = False is_await = False in_async_gen = False expr_keyword = 'yield' def analyse_types(self, env): if not self.label_num or (self.is_yield_from and self.in_async_gen): error(self.pos, "'%s' not supported here" % self.expr_keyword) self.is_temp = 1 if self.arg is not None: self.arg = self.arg.analyse_types(env) if not self.arg.type.is_pyobject: self.coerce_yield_argument(env) return self def coerce_yield_argument(self, env): self.arg = self.arg.coerce_to_pyobject(env) def generate_evaluation_code(self, code): if self.arg: self.arg.generate_evaluation_code(code) self.arg.make_owned_reference(code) code.putln( "%s = %s;" % ( Naming.retval_cname, self.arg.result_as(py_object_type))) self.arg.generate_post_assignment_code(code) self.arg.free_temps(code) else: code.put_init_to_py_none(Naming.retval_cname, py_object_type) self.generate_yield_code(code) def generate_yield_code(self, code): """ Generate the code to return the argument in 'Naming.retval_cname' and to continue at the yield label. """ label_num, label_name = code.new_yield_label( self.expr_keyword.replace(' ', '_')) code.use_label(label_name) saved = [] code.funcstate.closure_temps.reset() for cname, type, manage_ref in code.funcstate.temps_in_use(): save_cname = code.funcstate.closure_temps.allocate_temp(type) saved.append((cname, save_cname, type)) if type.is_cpp_class: code.globalstate.use_utility_code( UtilityCode.load_cached("MoveIfSupported", "CppSupport.cpp")) cname = "__PYX_STD_MOVE_IF_SUPPORTED(%s)" % cname else: code.put_xgiveref(cname, type) code.putln('%s->%s = %s;' % (Naming.cur_scope_cname, save_cname, cname)) code.put_xgiveref(Naming.retval_cname, py_object_type) profile = code.globalstate.directives['profile'] linetrace = code.globalstate.directives['linetrace'] if profile or linetrace: code.put_trace_return(Naming.retval_cname, nogil=not code.funcstate.gil_owned) code.put_finish_refcount_context() if code.funcstate.current_except is not None: # inside of an except block => save away currently handled exception code.putln("__Pyx_Coroutine_SwapException(%s);" % Naming.generator_cname) else: # no exceptions being handled => restore exception state of caller code.putln("__Pyx_Coroutine_ResetAndClearException(%s);" % Naming.generator_cname) code.putln("/* return from %sgenerator, %sing value */" % ( 'async ' if self.in_async_gen else '', 'await' if self.is_await else 'yield')) code.putln("%s->resume_label = %d;" % ( Naming.generator_cname, label_num)) if self.in_async_gen and not self.is_await: # __Pyx__PyAsyncGenValueWrapperNew() steals a reference to the return value code.putln("return __Pyx__PyAsyncGenValueWrapperNew(%s);" % Naming.retval_cname) else: code.putln("return %s;" % Naming.retval_cname) code.put_label(label_name) for cname, save_cname, type in saved: save_cname = "%s->%s" % (Naming.cur_scope_cname, save_cname) if type.is_cpp_class: save_cname = "__PYX_STD_MOVE_IF_SUPPORTED(%s)" % save_cname code.putln('%s = %s;' % (cname, save_cname)) if type.is_pyobject: code.putln('%s = 0;' % save_cname) code.put_xgotref(cname, type) elif type.is_memoryviewslice: code.putln('%s.memview = NULL; %s.data = NULL;' % (save_cname, save_cname)) self.generate_sent_value_handling_code(code, Naming.sent_value_cname) if self.result_is_used: self.allocate_temp_result(code) code.put('%s = %s; ' % (self.result(), Naming.sent_value_cname)) code.put_incref(self.result(), py_object_type) def generate_sent_value_handling_code(self, code, value_cname): code.putln(code.error_goto_if_null(value_cname, self.pos)) class _YieldDelegationExprNode(YieldExprNode): def yield_from_func(self, code): raise NotImplementedError() def generate_evaluation_code(self, code, source_cname=None, decref_source=False): if source_cname is None: self.arg.generate_evaluation_code(code) code.putln("%s = %s(%s, %s);" % ( Naming.retval_cname, self.yield_from_func(code), Naming.generator_cname, self.arg.py_result() if source_cname is None else source_cname)) if source_cname is None: self.arg.generate_disposal_code(code) self.arg.free_temps(code) elif decref_source: code.put_decref_clear(source_cname, py_object_type) code.put_xgotref(Naming.retval_cname, py_object_type) code.putln("if (likely(%s)) {" % Naming.retval_cname) self.generate_yield_code(code) code.putln("} else {") # either error or sub-generator has normally terminated: return value => node result if self.result_is_used: self.fetch_iteration_result(code) else: self.handle_iteration_exception(code) code.putln("}") def fetch_iteration_result(self, code): # YieldExprNode has allocated the result temp for us code.putln("%s = NULL;" % self.result()) code.put_error_if_neg(self.pos, "__Pyx_PyGen_FetchStopIterationValue(&%s)" % self.result()) self.generate_gotref(code) def handle_iteration_exception(self, code): code.putln("PyObject* exc_type = __Pyx_PyErr_CurrentExceptionType();") code.putln("if (exc_type) {") code.putln("if (likely(exc_type == PyExc_StopIteration || (exc_type != PyExc_GeneratorExit &&" " __Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration)))) PyErr_Clear();") code.putln("else %s" % code.error_goto(self.pos)) code.putln("}") class YieldFromExprNode(_YieldDelegationExprNode): # "yield from GEN" expression is_yield_from = True expr_keyword = 'yield from' def coerce_yield_argument(self, env): if not self.arg.type.is_string: # FIXME: support C arrays and C++ iterators? error(self.pos, "yielding from non-Python object not supported") self.arg = self.arg.coerce_to_pyobject(env) def yield_from_func(self, code): code.globalstate.use_utility_code(UtilityCode.load_cached("GeneratorYieldFrom", "Coroutine.c")) return "__Pyx_Generator_Yield_From" class AwaitExprNode(_YieldDelegationExprNode): # 'await' expression node # # arg ExprNode the Awaitable value to await # label_num integer yield label number is_await = True expr_keyword = 'await' def coerce_yield_argument(self, env): if self.arg is not None: # FIXME: use same check as in YieldFromExprNode.coerce_yield_argument() ? self.arg = self.arg.coerce_to_pyobject(env) def yield_from_func(self, code): code.globalstate.use_utility_code(UtilityCode.load_cached("CoroutineYieldFrom", "Coroutine.c")) return "__Pyx_Coroutine_Yield_From" class AwaitIterNextExprNode(AwaitExprNode): # 'await' expression node as part of 'async for' iteration # # Breaks out of loop on StopAsyncIteration exception. def _generate_break(self, code): code.globalstate.use_utility_code(UtilityCode.load_cached("StopAsyncIteration", "Coroutine.c")) code.putln("PyObject* exc_type = __Pyx_PyErr_CurrentExceptionType();") code.putln("if (unlikely(exc_type && (exc_type == __Pyx_PyExc_StopAsyncIteration || (" " exc_type != PyExc_StopIteration && exc_type != PyExc_GeneratorExit &&" " __Pyx_PyErr_GivenExceptionMatches(exc_type, __Pyx_PyExc_StopAsyncIteration))))) {") code.putln("PyErr_Clear();") code.putln("break;") code.putln("}") def fetch_iteration_result(self, code): assert code.break_label, "AwaitIterNextExprNode outside of 'async for' loop" self._generate_break(code) super(AwaitIterNextExprNode, self).fetch_iteration_result(code) def generate_sent_value_handling_code(self, code, value_cname): assert code.break_label, "AwaitIterNextExprNode outside of 'async for' loop" code.putln("if (unlikely(!%s)) {" % value_cname) self._generate_break(code) # all non-break exceptions are errors, as in parent class code.putln(code.error_goto(self.pos)) code.putln("}") class GlobalsExprNode(AtomicExprNode): type = dict_type is_temp = 1 def analyse_types(self, env): env.use_utility_code(Builtin.globals_utility_code) return self gil_message = "Constructing globals dict" def may_be_none(self): return False def generate_result_code(self, code): code.putln('%s = __Pyx_Globals(); %s' % ( self.result(), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) class LocalsDictItemNode(DictItemNode): def analyse_types(self, env): self.key = self.key.analyse_types(env) self.value = self.value.analyse_types(env) self.key = self.key.coerce_to_pyobject(env) if self.value.type.can_coerce_to_pyobject(env): self.value = self.value.coerce_to_pyobject(env) else: self.value = None return self class FuncLocalsExprNode(DictNode): def __init__(self, pos, env): local_vars = sorted([ entry.name for entry in env.entries.values() if entry.name]) items = [LocalsDictItemNode( pos, key=IdentifierStringNode(pos, value=var), value=NameNode(pos, name=var, allow_null=True)) for var in local_vars] DictNode.__init__(self, pos, key_value_pairs=items, exclude_null_values=True) def analyse_types(self, env): node = super(FuncLocalsExprNode, self).analyse_types(env) node.key_value_pairs = [ i for i in node.key_value_pairs if i.value is not None ] return node class PyClassLocalsExprNode(AtomicExprNode): def __init__(self, pos, pyclass_dict): AtomicExprNode.__init__(self, pos) self.pyclass_dict = pyclass_dict def analyse_types(self, env): self.type = self.pyclass_dict.type self.is_temp = False return self def may_be_none(self): return False def result(self): return self.pyclass_dict.result() def generate_result_code(self, code): pass def LocalsExprNode(pos, scope_node, env): if env.is_module_scope: return GlobalsExprNode(pos) if env.is_py_class_scope: return PyClassLocalsExprNode(pos, scope_node.dict) return FuncLocalsExprNode(pos, env) #------------------------------------------------------------------- # # Unary operator nodes # #------------------------------------------------------------------- compile_time_unary_operators = { 'not': operator.not_, '~': operator.inv, '-': operator.neg, '+': operator.pos, } class UnopNode(ExprNode): # operator string # operand ExprNode # # Processing during analyse_expressions phase: # # analyse_c_operation # Called when the operand is not a pyobject. # - Check operand type and coerce if needed. # - Determine result type and result code fragment. # - Allocate temporary for result if needed. subexprs = ['operand'] infix = True is_inc_dec_op = False def calculate_constant_result(self): func = compile_time_unary_operators[self.operator] self.constant_result = func(self.operand.constant_result) def compile_time_value(self, denv): func = compile_time_unary_operators.get(self.operator) if not func: error(self.pos, "Unary '%s' not supported in compile-time expression" % self.operator) operand = self.operand.compile_time_value(denv) try: return func(operand) except Exception as e: self.compile_time_value_error(e) def infer_type(self, env): operand_type = self.operand.infer_type(env) if operand_type.is_cpp_class or operand_type.is_ptr: cpp_type = operand_type.find_cpp_operation_type(self.operator) if cpp_type is not None: return cpp_type return self.infer_unop_type(env, operand_type) def infer_unop_type(self, env, operand_type): if operand_type.is_pyobject: return py_object_type else: return operand_type def may_be_none(self): if self.operand.type and self.operand.type.is_builtin_type: if self.operand.type is not type_type: return False return ExprNode.may_be_none(self) def analyse_types(self, env): self.operand = self.operand.analyse_types(env) if self.is_pythran_operation(env): self.type = PythranExpr(pythran_unaryop_type(self.operator, self.operand.type)) self.is_temp = 1 elif self.is_py_operation(): self.coerce_operand_to_pyobject(env) self.type = py_object_type self.is_temp = 1 elif self.is_cpp_operation(): self.analyse_cpp_operation(env) else: self.analyse_c_operation(env) return self def check_const(self): return self.operand.check_const() def is_py_operation(self): return self.operand.type.is_pyobject or self.operand.type.is_ctuple def is_pythran_operation(self, env): np_pythran = has_np_pythran(env) op_type = self.operand.type return np_pythran and (op_type.is_buffer or op_type.is_pythran_expr) def nogil_check(self, env): if self.is_py_operation(): self.gil_error() def is_cpp_operation(self): type = self.operand.type return type.is_cpp_class def coerce_operand_to_pyobject(self, env): self.operand = self.operand.coerce_to_pyobject(env) def generate_result_code(self, code): if self.type.is_pythran_expr: code.putln("// Pythran unaryop") code.putln("__Pyx_call_destructor(%s);" % self.result()) code.putln("new (&%s) decltype(%s){%s%s};" % ( self.result(), self.result(), self.operator, self.operand.pythran_result())) elif self.operand.type.is_pyobject: self.generate_py_operation_code(code) elif self.is_temp: if self.is_cpp_operation() and self.exception_check == '+': translate_cpp_exception(code, self.pos, "%s = %s %s;" % (self.result(), self.operator, self.operand.result()), self.result() if self.type.is_pyobject else None, self.exception_value, self.in_nogil_context) else: code.putln("%s = %s %s;" % (self.result(), self.operator, self.operand.result())) def generate_py_operation_code(self, code): function = self.py_operation_function(code) code.putln( "%s = %s(%s); %s" % ( self.result(), function, self.operand.py_result(), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) def type_error(self): if not self.operand.type.is_error: error(self.pos, "Invalid operand type for '%s' (%s)" % (self.operator, self.operand.type)) self.type = PyrexTypes.error_type def analyse_cpp_operation(self, env, overload_check=True): operand_types = [self.operand.type] if self.is_inc_dec_op and not self.is_prefix: operand_types.append(PyrexTypes.c_int_type) entry = env.lookup_operator_for_types(self.pos, self.operator, operand_types) if overload_check and not entry: self.type_error() return if entry: self.exception_check = entry.type.exception_check self.exception_value = entry.type.exception_value if self.exception_check == '+': self.is_temp = True if needs_cpp_exception_conversion(self): env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp")) else: self.exception_check = '' self.exception_value = '' if self.is_inc_dec_op and not self.is_prefix: cpp_type = self.operand.type.find_cpp_operation_type( self.operator, operand_type=PyrexTypes.c_int_type ) else: cpp_type = self.operand.type.find_cpp_operation_type(self.operator) if overload_check and cpp_type is None: error(self.pos, "'%s' operator not defined for %s" % ( self.operator, type)) self.type_error() return self.type = cpp_type class NotNode(UnopNode): # 'not' operator # # operand ExprNode operator = '!' type = PyrexTypes.c_bint_type def calculate_constant_result(self): self.constant_result = not self.operand.constant_result def compile_time_value(self, denv): operand = self.operand.compile_time_value(denv) try: return not operand except Exception as e: self.compile_time_value_error(e) def infer_unop_type(self, env, operand_type): return PyrexTypes.c_bint_type def analyse_types(self, env): self.operand = self.operand.analyse_types(env) operand_type = self.operand.type if operand_type.is_cpp_class: self.analyse_cpp_operation(env) else: self.operand = self.operand.coerce_to_boolean(env) return self def calculate_result_code(self): return "(!%s)" % self.operand.result() class UnaryPlusNode(UnopNode): # unary '+' operator operator = '+' def analyse_c_operation(self, env): self.type = PyrexTypes.widest_numeric_type( self.operand.type, PyrexTypes.c_int_type) def py_operation_function(self, code): return "PyNumber_Positive" def calculate_result_code(self): if self.is_cpp_operation(): return "(+%s)" % self.operand.result() else: return self.operand.result() class UnaryMinusNode(UnopNode): # unary '-' operator operator = '-' def analyse_c_operation(self, env): if self.operand.type.is_numeric: self.type = PyrexTypes.widest_numeric_type( self.operand.type, PyrexTypes.c_int_type) elif self.operand.type.is_enum: self.type = PyrexTypes.c_int_type else: self.type_error() if self.type.is_complex: self.infix = False def py_operation_function(self, code): return "PyNumber_Negative" def calculate_result_code(self): if self.infix: return "(-%s)" % self.operand.result() else: return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.result()) def get_constant_c_result_code(self): value = self.operand.get_constant_c_result_code() if value: return "(-%s)" % value class TildeNode(UnopNode): # unary '~' operator def analyse_c_operation(self, env): if self.operand.type.is_int: self.type = PyrexTypes.widest_numeric_type( self.operand.type, PyrexTypes.c_int_type) elif self.operand.type.is_enum: self.type = PyrexTypes.c_int_type else: self.type_error() def py_operation_function(self, code): return "PyNumber_Invert" def calculate_result_code(self): return "(~%s)" % self.operand.result() class CUnopNode(UnopNode): def is_py_operation(self): return False class DereferenceNode(CUnopNode): # unary * operator operator = '*' def infer_unop_type(self, env, operand_type): if operand_type.is_ptr: return operand_type.base_type else: return PyrexTypes.error_type def analyse_c_operation(self, env): if self.operand.type.is_ptr: if env.is_cpp: self.type = PyrexTypes.CReferenceType(self.operand.type.base_type) else: self.type = self.operand.type.base_type else: self.type_error() def calculate_result_code(self): return "(*%s)" % self.operand.result() class DecrementIncrementNode(CUnopNode): # unary ++/-- operator is_inc_dec_op = True def type_error(self): if not self.operand.type.is_error: if self.is_prefix: error(self.pos, "No match for 'operator%s' (operand type is '%s')" % (self.operator, self.operand.type)) else: error(self.pos, "No 'operator%s(int)' declared for postfix '%s' (operand type is '%s')" % (self.operator, self.operator, self.operand.type)) self.type = PyrexTypes.error_type def analyse_c_operation(self, env): if self.operand.type.is_numeric: self.type = PyrexTypes.widest_numeric_type( self.operand.type, PyrexTypes.c_int_type) elif self.operand.type.is_ptr: self.type = self.operand.type else: self.type_error() def calculate_result_code(self): if self.is_prefix: return "(%s%s)" % (self.operator, self.operand.result()) else: return "(%s%s)" % (self.operand.result(), self.operator) def inc_dec_constructor(is_prefix, operator): return lambda pos, **kwds: DecrementIncrementNode(pos, is_prefix=is_prefix, operator=operator, **kwds) class AmpersandNode(CUnopNode): # The C address-of operator. # # operand ExprNode operator = '&' def infer_unop_type(self, env, operand_type): return PyrexTypes.c_ptr_type(operand_type) def analyse_types(self, env): self.operand = self.operand.analyse_types(env) argtype = self.operand.type if argtype.is_cpp_class: self.analyse_cpp_operation(env, overload_check=False) if not (argtype.is_cfunction or argtype.is_reference or self.operand.is_addressable()): if argtype.is_memoryviewslice: self.error("Cannot take address of memoryview slice") else: self.error("Taking address of non-lvalue (type %s)" % argtype) return self if argtype.is_pyobject: self.error("Cannot take address of Python %s" % ( "variable '%s'" % self.operand.name if self.operand.is_name else "object attribute '%s'" % self.operand.attribute if self.operand.is_attribute else "object")) return self if not argtype.is_cpp_class or not self.type: self.type = PyrexTypes.c_ptr_type(argtype) return self def check_const(self): return self.operand.check_const_addr() def error(self, mess): error(self.pos, mess) self.type = PyrexTypes.error_type self.result_code = "" def calculate_result_code(self): return "(&%s)" % self.operand.result() def generate_result_code(self, code): if (self.operand.type.is_cpp_class and self.exception_check == '+'): translate_cpp_exception(code, self.pos, "%s = %s %s;" % (self.result(), self.operator, self.operand.result()), self.result() if self.type.is_pyobject else None, self.exception_value, self.in_nogil_context) unop_node_classes = { "+": UnaryPlusNode, "-": UnaryMinusNode, "~": TildeNode, } def unop_node(pos, operator, operand): # Construct unnop node of appropriate class for # given operator. if isinstance(operand, IntNode) and operator == '-': return IntNode(pos = operand.pos, value = str(-Utils.str_to_number(operand.value)), longness=operand.longness, unsigned=operand.unsigned) elif isinstance(operand, UnopNode) and operand.operator == operator in '+-': warning(pos, "Python has no increment/decrement operator: %s%sx == %s(%sx) == x" % ((operator,)*4), 5) return unop_node_classes[operator](pos, operator = operator, operand = operand) class TypecastNode(ExprNode): # C type cast # # operand ExprNode # base_type CBaseTypeNode # declarator CDeclaratorNode # typecheck boolean # # If used from a transform, one can if wanted specify the attribute # "type" directly and leave base_type and declarator to None subexprs = ['operand'] base_type = declarator = type = None def type_dependencies(self, env): return () def infer_type(self, env): if self.type is None: base_type = self.base_type.analyse(env) _, self.type = self.declarator.analyse(base_type, env) return self.type def analyse_types(self, env): if self.type is None: base_type = self.base_type.analyse(env) _, self.type = self.declarator.analyse(base_type, env) if self.operand.has_constant_result(): # Must be done after self.type is resolved. self.calculate_constant_result() if self.type.is_cfunction: error(self.pos, "Cannot cast to a function type") self.type = PyrexTypes.error_type self.operand = self.operand.analyse_types(env) if self.type is PyrexTypes.c_bint_type: # short circuit this to a coercion return self.operand.coerce_to_boolean(env) to_py = self.type.is_pyobject from_py = self.operand.type.is_pyobject if from_py and not to_py and self.operand.is_ephemeral(): if not self.type.is_numeric and not self.type.is_cpp_class: error(self.pos, "Casting temporary Python object to non-numeric non-Python type") if to_py and not from_py: if self.type is bytes_type and self.operand.type.is_int: return CoerceIntToBytesNode(self.operand, env) elif self.operand.type.can_coerce_to_pyobject(env): self.result_ctype = py_object_type self.operand = self.operand.coerce_to(self.type, env) else: if self.operand.type.is_ptr: if not (self.operand.type.base_type.is_void or self.operand.type.base_type.is_struct): error(self.pos, "Python objects cannot be cast from pointers of primitive types") else: # Should this be an error? warning(self.pos, "No conversion from %s to %s, python object pointer used." % ( self.operand.type, self.type)) self.operand = self.operand.coerce_to_simple(env) elif from_py and not to_py: if self.type.create_from_py_utility_code(env): self.operand = self.operand.coerce_to(self.type, env) elif self.type.is_ptr: if not (self.type.base_type.is_void or self.type.base_type.is_struct): error(self.pos, "Python objects cannot be cast to pointers of primitive types") else: warning(self.pos, "No conversion from %s to %s, python object pointer used." % ( self.type, self.operand.type)) elif from_py and to_py: if self.typecheck: self.operand = PyTypeTestNode(self.operand, self.type, env, notnone=True) elif isinstance(self.operand, SliceIndexNode): # This cast can influence the created type of string slices. self.operand = self.operand.coerce_to(self.type, env) elif self.type.is_complex and self.operand.type.is_complex: self.operand = self.operand.coerce_to_simple(env) elif self.operand.type.is_fused: self.operand = self.operand.coerce_to(self.type, env) #self.type = self.operand.type if self.type.is_ptr and self.type.base_type.is_cfunction and self.type.base_type.nogil: op_type = self.operand.type if op_type.is_ptr: op_type = op_type.base_type if op_type.is_cfunction and not op_type.nogil: warning(self.pos, "Casting a GIL-requiring function into a nogil function circumvents GIL validation", 1) return self def is_simple(self): # either temp or a C cast => no side effects other than the operand's return self.operand.is_simple() def is_ephemeral(self): # either temp or a C cast => no side effects other than the operand's return self.operand.is_ephemeral() def nonlocally_immutable(self): return self.is_temp or self.operand.nonlocally_immutable() def nogil_check(self, env): if self.type and self.type.is_pyobject and self.is_temp: self.gil_error() def check_const(self): return self.operand.check_const() def calculate_constant_result(self): self.constant_result = self.calculate_result_code(self.operand.constant_result) def calculate_result_code(self, operand_result = None): if operand_result is None: operand_result = self.operand.result() if self.type.is_complex: operand_result = self.operand.result() if self.operand.type.is_complex: real_part = self.type.real_type.cast_code( self.operand.type.real_code(operand_result)) imag_part = self.type.real_type.cast_code( self.operand.type.imag_code(operand_result)) else: real_part = self.type.real_type.cast_code(operand_result) imag_part = "0" return "%s(%s, %s)" % ( self.type.from_parts, real_part, imag_part) else: return self.type.cast_code(operand_result) def get_constant_c_result_code(self): operand_result = self.operand.get_constant_c_result_code() if operand_result: return self.type.cast_code(operand_result) def result_as(self, type): if self.type.is_pyobject and not self.is_temp: # Optimise away some unnecessary casting return self.operand.result_as(type) else: return ExprNode.result_as(self, type) def generate_result_code(self, code): if self.is_temp: code.putln( "%s = (PyObject *)%s;" % ( self.result(), self.operand.result())) code.put_incref(self.result(), self.ctype()) ERR_START = "Start may not be given" ERR_NOT_STOP = "Stop must be provided to indicate shape" ERR_STEPS = ("Strides may only be given to indicate contiguity. " "Consider slicing it after conversion") ERR_NOT_POINTER = "Can only create cython.array from pointer or array" ERR_BASE_TYPE = "Pointer base type does not match cython.array base type" class CythonArrayNode(ExprNode): """ Used when a pointer of base_type is cast to a memoryviewslice with that base type. i.e. p creates a fortran-contiguous cython.array. We leave the type set to object so coercions to object are more efficient and less work. Acquiring a memoryviewslice from this will be just as efficient. ExprNode.coerce_to() will do the additional typecheck on self.compile_time_type This also handles my_c_array operand ExprNode the thing we're casting base_type_node MemoryViewSliceTypeNode the cast expression node """ subexprs = ['operand', 'shapes'] shapes = None is_temp = True mode = "c" array_dtype = None shape_type = PyrexTypes.c_py_ssize_t_type def analyse_types(self, env): from . import MemoryView self.operand = self.operand.analyse_types(env) if self.array_dtype: array_dtype = self.array_dtype else: array_dtype = self.base_type_node.base_type_node.analyse(env) axes = self.base_type_node.axes self.type = error_type self.shapes = [] ndim = len(axes) # Base type of the pointer or C array we are converting base_type = self.operand.type if not self.operand.type.is_ptr and not self.operand.type.is_array: error(self.operand.pos, ERR_NOT_POINTER) return self # Dimension sizes of C array array_dimension_sizes = [] if base_type.is_array: while base_type.is_array: array_dimension_sizes.append(base_type.size) base_type = base_type.base_type elif base_type.is_ptr: base_type = base_type.base_type else: error(self.pos, "unexpected base type %s found" % base_type) return self if not (base_type.same_as(array_dtype) or base_type.is_void): error(self.operand.pos, ERR_BASE_TYPE) return self elif self.operand.type.is_array and len(array_dimension_sizes) != ndim: error(self.operand.pos, "Expected %d dimensions, array has %d dimensions" % (ndim, len(array_dimension_sizes))) return self # Verify the start, stop and step values # In case of a C array, use the size of C array in each dimension to # get an automatic cast for axis_no, axis in enumerate(axes): if not axis.start.is_none: error(axis.start.pos, ERR_START) return self if axis.stop.is_none: if array_dimension_sizes: dimsize = array_dimension_sizes[axis_no] axis.stop = IntNode(self.pos, value=str(dimsize), constant_result=dimsize, type=PyrexTypes.c_int_type) else: error(axis.pos, ERR_NOT_STOP) return self axis.stop = axis.stop.analyse_types(env) shape = axis.stop.coerce_to(self.shape_type, env) if not shape.is_literal: shape.coerce_to_temp(env) self.shapes.append(shape) first_or_last = axis_no in (0, ndim - 1) if not axis.step.is_none and first_or_last: # '1' in the first or last dimension denotes F or C contiguity axis.step = axis.step.analyse_types(env) if (not axis.step.type.is_int and axis.step.is_literal and not axis.step.type.is_error): error(axis.step.pos, "Expected an integer literal") return self if axis.step.compile_time_value(env) != 1: error(axis.step.pos, ERR_STEPS) return self if axis_no == 0: self.mode = "fortran" elif not axis.step.is_none and not first_or_last: # step provided in some other dimension error(axis.step.pos, ERR_STEPS) return self if not self.operand.is_name: self.operand = self.operand.coerce_to_temp(env) axes = [('direct', 'follow')] * len(axes) if self.mode == "fortran": axes[0] = ('direct', 'contig') else: axes[-1] = ('direct', 'contig') self.coercion_type = PyrexTypes.MemoryViewSliceType(array_dtype, axes) self.coercion_type.validate_memslice_dtype(self.pos) self.type = self.get_cython_array_type(env) MemoryView.use_cython_array_utility_code(env) env.use_utility_code(MemoryView.typeinfo_to_format_code) return self def allocate_temp_result(self, code): if self.temp_code: raise RuntimeError("temp allocated multiple times") self.temp_code = code.funcstate.allocate_temp(self.type, True) def infer_type(self, env): return self.get_cython_array_type(env) def get_cython_array_type(self, env): cython_scope = env.global_scope().context.cython_scope cython_scope.load_cythonscope() return cython_scope.viewscope.lookup("array").type def generate_result_code(self, code): from . import Buffer shapes = [self.shape_type.cast_code(shape.result()) for shape in self.shapes] dtype = self.coercion_type.dtype shapes_temp = code.funcstate.allocate_temp(py_object_type, True) format_temp = code.funcstate.allocate_temp(py_object_type, True) itemsize = "sizeof(%s)" % dtype.empty_declaration_code() type_info = Buffer.get_type_information_cname(code, dtype) if self.operand.type.is_ptr: code.putln("if (!%s) {" % self.operand.result()) code.putln( 'PyErr_SetString(PyExc_ValueError,' '"Cannot create cython.array from NULL pointer");') code.putln(code.error_goto(self.operand.pos)) code.putln("}") code.putln("%s = __pyx_format_from_typeinfo(&%s); %s" % ( format_temp, type_info, code.error_goto_if_null(format_temp, self.pos), )) code.put_gotref(format_temp, py_object_type) buildvalue_fmt = " __PYX_BUILD_PY_SSIZE_T " * len(shapes) code.putln('%s = Py_BuildValue((char*) "(" %s ")", %s); %s' % ( shapes_temp, buildvalue_fmt, ", ".join(shapes), code.error_goto_if_null(shapes_temp, self.pos), )) code.put_gotref(shapes_temp, py_object_type) code.putln('%s = __pyx_array_new(%s, %s, PyBytes_AS_STRING(%s), (char *) "%s", (char *) %s); %s' % ( self.result(), shapes_temp, itemsize, format_temp, self.mode, self.operand.result(), code.error_goto_if_null(self.result(), self.pos), )) self.generate_gotref(code) def dispose(temp): code.put_decref_clear(temp, py_object_type) code.funcstate.release_temp(temp) dispose(shapes_temp) dispose(format_temp) @classmethod def from_carray(cls, src_node, env): """ Given a C array type, return a CythonArrayNode """ pos = src_node.pos base_type = src_node.type none_node = NoneNode(pos) axes = [] while base_type.is_array: axes.append(SliceNode(pos, start=none_node, stop=none_node, step=none_node)) base_type = base_type.base_type axes[-1].step = IntNode(pos, value="1", is_c_literal=True) memslicenode = Nodes.MemoryViewSliceTypeNode(pos, axes=axes, base_type_node=base_type) result = CythonArrayNode(pos, base_type_node=memslicenode, operand=src_node, array_dtype=base_type) result = result.analyse_types(env) return result class SizeofNode(ExprNode): # Abstract base class for sizeof(x) expression nodes. type = PyrexTypes.c_size_t_type def check_const(self): return True def generate_result_code(self, code): pass class SizeofTypeNode(SizeofNode): # C sizeof function applied to a type # # base_type CBaseTypeNode # declarator CDeclaratorNode subexprs = [] arg_type = None def analyse_types(self, env): # we may have incorrectly interpreted a dotted name as a type rather than an attribute # this could be better handled by more uniformly treating types as runtime-available objects if 0 and self.base_type.module_path: path = self.base_type.module_path obj = env.lookup(path[0]) if obj.as_module is None: operand = NameNode(pos=self.pos, name=path[0]) for attr in path[1:]: operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr) operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name) node = SizeofVarNode(self.pos, operand=operand).analyse_types(env) return node if self.arg_type is None: base_type = self.base_type.analyse(env) _, arg_type = self.declarator.analyse(base_type, env) self.arg_type = arg_type self.check_type() return self def check_type(self): arg_type = self.arg_type if not arg_type: return if arg_type.is_pyobject and not arg_type.is_extension_type: error(self.pos, "Cannot take sizeof Python object") elif arg_type.is_void: error(self.pos, "Cannot take sizeof void") elif not arg_type.is_complete(): error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type) def calculate_result_code(self): if self.arg_type.is_extension_type: # the size of the pointer is boring # we want the size of the actual struct arg_code = self.arg_type.declaration_code("", deref=1) else: arg_code = self.arg_type.empty_declaration_code() return "(sizeof(%s))" % arg_code class SizeofVarNode(SizeofNode): # C sizeof function applied to a variable # # operand ExprNode subexprs = ['operand'] def analyse_types(self, env): # We may actually be looking at a type rather than a variable... # If we are, traditional analysis would fail... operand_as_type = self.operand.analyse_as_type(env) if operand_as_type: self.arg_type = operand_as_type if self.arg_type.is_fused: try: self.arg_type = self.arg_type.specialize(env.fused_to_specific) except CannotSpecialize: error(self.operand.pos, "Type cannot be specialized since it is not a fused argument to this function") self.__class__ = SizeofTypeNode self.check_type() else: self.operand = self.operand.analyse_types(env) return self def calculate_result_code(self): return "(sizeof(%s))" % self.operand.result() def generate_result_code(self, code): pass class TypeidNode(ExprNode): # C++ typeid operator applied to a type or variable # # operand ExprNode # arg_type ExprNode # is_variable boolean subexprs = ['operand'] arg_type = None is_variable = None is_temp = 1 def get_type_info_type(self, env): env_module = env while not env_module.is_module_scope: env_module = env_module.outer_scope typeinfo_module = env_module.find_module('libcpp.typeinfo', self.pos) typeinfo_entry = typeinfo_module.lookup('type_info') return PyrexTypes.CFakeReferenceType(PyrexTypes.c_const_type(typeinfo_entry.type)) cpp_message = 'typeid operator' def analyse_types(self, env): if not self.type: self.type = PyrexTypes.error_type # default value if it isn't analysed successfully self.cpp_check(env) type_info = self.get_type_info_type(env) if not type_info: self.error("The 'libcpp.typeinfo' module must be cimported to use the typeid() operator") return self if self.operand is None: return self # already analysed, no need to repeat self.type = type_info as_type = self.operand.analyse_as_specialized_type(env) if as_type: self.arg_type = as_type self.is_type = True self.operand = None # nothing further uses self.operand - will only cause problems if its used in code generation else: self.arg_type = self.operand.analyse_types(env) self.is_type = False self.operand = None # nothing further uses self.operand - will only cause problems if its used in code generation if self.arg_type.type.is_pyobject: self.error("Cannot use typeid on a Python object") return self elif self.arg_type.type.is_void: self.error("Cannot use typeid on void") return self elif not self.arg_type.type.is_complete(): self.error("Cannot use typeid on incomplete type '%s'" % self.arg_type.type) return self env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp")) return self def error(self, mess): error(self.pos, mess) self.type = PyrexTypes.error_type self.result_code = "" def check_const(self): return True def calculate_result_code(self): return self.temp_code def generate_result_code(self, code): if self.is_type: arg_code = self.arg_type.empty_declaration_code() else: arg_code = self.arg_type.result() translate_cpp_exception(code, self.pos, "%s = typeid(%s);" % (self.temp_code, arg_code), None, None, self.in_nogil_context) class TypeofNode(ExprNode): # Compile-time type of an expression, as a string. # # operand ExprNode # literal StringNode # internal literal = None type = py_object_type subexprs = ['literal'] # 'operand' will be ignored after type analysis! def analyse_types(self, env): self.operand = self.operand.analyse_types(env) value = StringEncoding.EncodedString(str(self.operand.type)) #self.operand.type.typeof_name()) literal = StringNode(self.pos, value=value) literal = literal.analyse_types(env) self.literal = literal.coerce_to_pyobject(env) return self def analyse_as_type(self, env): self.operand = self.operand.analyse_types(env) return self.operand.type def may_be_none(self): return False def generate_evaluation_code(self, code): self.literal.generate_evaluation_code(code) def calculate_result_code(self): return self.literal.calculate_result_code() #------------------------------------------------------------------- # # Binary operator nodes # #------------------------------------------------------------------- try: matmul_operator = operator.matmul except AttributeError: def matmul_operator(a, b): try: func = a.__matmul__ except AttributeError: func = b.__rmatmul__ return func(a, b) compile_time_binary_operators = { '<': operator.lt, '<=': operator.le, '==': operator.eq, '!=': operator.ne, '>=': operator.ge, '>': operator.gt, 'is': operator.is_, 'is_not': operator.is_not, '+': operator.add, '&': operator.and_, '/': operator.truediv, '//': operator.floordiv, '<<': operator.lshift, '%': operator.mod, '*': operator.mul, '|': operator.or_, '**': operator.pow, '>>': operator.rshift, '-': operator.sub, '^': operator.xor, '@': matmul_operator, 'in': lambda x, seq: x in seq, 'not_in': lambda x, seq: x not in seq, } def get_compile_time_binop(node): func = compile_time_binary_operators.get(node.operator) if not func: error(node.pos, "Binary '%s' not supported in compile-time expression" % node.operator) return func class BinopNode(ExprNode): # operator string # operand1 ExprNode # operand2 ExprNode # # Processing during analyse_expressions phase: # # analyse_c_operation # Called when neither operand is a pyobject. # - Check operand types and coerce if needed. # - Determine result type and result code fragment. # - Allocate temporary for result if needed. subexprs = ['operand1', 'operand2'] inplace = False def calculate_constant_result(self): func = compile_time_binary_operators[self.operator] self.constant_result = func( self.operand1.constant_result, self.operand2.constant_result) def compile_time_value(self, denv): func = get_compile_time_binop(self) operand1 = self.operand1.compile_time_value(denv) operand2 = self.operand2.compile_time_value(denv) try: return func(operand1, operand2) except Exception as e: self.compile_time_value_error(e) def infer_type(self, env): return self.result_type(self.operand1.infer_type(env), self.operand2.infer_type(env), env) def analyse_types(self, env): self.operand1 = self.operand1.analyse_types(env) self.operand2 = self.operand2.analyse_types(env) self.analyse_operation(env) return self def analyse_operation(self, env): if self.is_pythran_operation(env): self.type = self.result_type(self.operand1.type, self.operand2.type, env) assert self.type.is_pythran_expr self.is_temp = 1 elif self.is_py_operation(): self.coerce_operands_to_pyobjects(env) self.type = self.result_type(self.operand1.type, self.operand2.type, env) assert self.type.is_pyobject self.is_temp = 1 elif self.is_cpp_operation(): self.analyse_cpp_operation(env) else: self.analyse_c_operation(env) def is_py_operation(self): return self.is_py_operation_types(self.operand1.type, self.operand2.type) def is_py_operation_types(self, type1, type2): return type1.is_pyobject or type2.is_pyobject or type1.is_ctuple or type2.is_ctuple def is_pythran_operation(self, env): return self.is_pythran_operation_types(self.operand1.type, self.operand2.type, env) def is_pythran_operation_types(self, type1, type2, env): # Support only expr op supported_type, or supported_type op expr return has_np_pythran(env) and \ (is_pythran_supported_operation_type(type1) and is_pythran_supported_operation_type(type2)) and \ (is_pythran_expr(type1) or is_pythran_expr(type2)) def is_cpp_operation(self): return (self.operand1.type.is_cpp_class or self.operand2.type.is_cpp_class) def analyse_cpp_operation(self, env): entry = env.lookup_operator(self.operator, [self.operand1, self.operand2]) if not entry: self.type_error() return func_type = entry.type self.exception_check = func_type.exception_check self.exception_value = func_type.exception_value if self.exception_check == '+': # Used by NumBinopNodes to break up expressions involving multiple # operators so that exceptions can be handled properly. self.is_temp = 1 if needs_cpp_exception_conversion(self): env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp")) if func_type.is_ptr: func_type = func_type.base_type if len(func_type.args) == 1: self.operand2 = self.operand2.coerce_to(func_type.args[0].type, env) else: self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env) self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env) self.type = func_type.return_type def result_type(self, type1, type2, env): if self.is_pythran_operation_types(type1, type2, env): return PythranExpr(pythran_binop_type(self.operator, type1, type2)) if self.is_py_operation_types(type1, type2): if type2.is_string: type2 = Builtin.bytes_type elif type2.is_pyunicode_ptr: type2 = Builtin.unicode_type if type1.is_string: type1 = Builtin.bytes_type elif type1.is_pyunicode_ptr: type1 = Builtin.unicode_type if type1.is_builtin_type or type2.is_builtin_type: if type1 is type2 and self.operator in '**%+|&^': # FIXME: at least these operators should be safe - others? return type1 result_type = self.infer_builtin_types_operation(type1, type2) if result_type is not None: return result_type return py_object_type elif type1.is_error or type2.is_error: return PyrexTypes.error_type else: return self.compute_c_result_type(type1, type2) def infer_builtin_types_operation(self, type1, type2): return None def nogil_check(self, env): if self.is_py_operation(): self.gil_error() def coerce_operands_to_pyobjects(self, env): self.operand1 = self.operand1.coerce_to_pyobject(env) self.operand2 = self.operand2.coerce_to_pyobject(env) def check_const(self): return self.operand1.check_const() and self.operand2.check_const() def is_ephemeral(self): return (super(BinopNode, self).is_ephemeral() or self.operand1.is_ephemeral() or self.operand2.is_ephemeral()) def generate_result_code(self, code): type1 = self.operand1.type type2 = self.operand2.type if self.type.is_pythran_expr: code.putln("// Pythran binop") code.putln("__Pyx_call_destructor(%s);" % self.result()) if self.operator == '**': code.putln("new (&%s) decltype(%s){pythonic::numpy::functor::power{}(%s, %s)};" % ( self.result(), self.result(), self.operand1.pythran_result(), self.operand2.pythran_result())) else: code.putln("new (&%s) decltype(%s){%s %s %s};" % ( self.result(), self.result(), self.operand1.pythran_result(), self.operator, self.operand2.pythran_result())) elif type1.is_pyobject or type2.is_pyobject: function = self.py_operation_function(code) extra_args = ", Py_None" if self.operator == '**' else "" op1_result = self.operand1.py_result() if type1.is_pyobject else self.operand1.result() op2_result = self.operand2.py_result() if type2.is_pyobject else self.operand2.result() code.putln( "%s = %s(%s, %s%s); %s" % ( self.result(), function, op1_result, op2_result, extra_args, code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) elif self.is_temp: # C++ overloaded operators with exception values are currently all # handled through temporaries. if self.is_cpp_operation() and self.exception_check == '+': translate_cpp_exception(code, self.pos, "%s = %s;" % (self.result(), self.calculate_result_code()), self.result() if self.type.is_pyobject else None, self.exception_value, self.in_nogil_context) else: code.putln("%s = %s;" % (self.result(), self.calculate_result_code())) def type_error(self): if not (self.operand1.type.is_error or self.operand2.type.is_error): error(self.pos, "Invalid operand types for '%s' (%s; %s)" % (self.operator, self.operand1.type, self.operand2.type)) self.type = PyrexTypes.error_type class CBinopNode(BinopNode): def analyse_types(self, env): node = BinopNode.analyse_types(self, env) if node.is_py_operation(): node.type = PyrexTypes.error_type return node def py_operation_function(self, code): return "" def calculate_result_code(self): return "(%s %s %s)" % ( self.operand1.result(), self.operator, self.operand2.result()) def compute_c_result_type(self, type1, type2): cpp_type = None if type1.is_cpp_class or type1.is_ptr: cpp_type = type1.find_cpp_operation_type(self.operator, type2) if cpp_type is None and (type2.is_cpp_class or type2.is_ptr): cpp_type = type2.find_cpp_operation_type(self.operator, type1) # FIXME: do we need to handle other cases here? return cpp_type def c_binop_constructor(operator): def make_binop_node(pos, **operands): return CBinopNode(pos, operator=operator, **operands) return make_binop_node class NumBinopNode(BinopNode): # Binary operation taking numeric arguments. infix = True overflow_check = False overflow_bit_node = None def analyse_c_operation(self, env): type1 = self.operand1.type type2 = self.operand2.type self.type = self.compute_c_result_type(type1, type2) if not self.type: self.type_error() return if self.type.is_complex: self.infix = False if (self.type.is_int and env.directives['overflowcheck'] and self.operator in self.overflow_op_names): if (self.operator in ('+', '*') and self.operand1.has_constant_result() and not self.operand2.has_constant_result()): self.operand1, self.operand2 = self.operand2, self.operand1 self.overflow_check = True self.overflow_fold = env.directives['overflowcheck.fold'] self.func = self.type.overflow_check_binop( self.overflow_op_names[self.operator], env, const_rhs = self.operand2.has_constant_result()) self.is_temp = True if not self.infix or (type1.is_numeric and type2.is_numeric): self.operand1 = self.operand1.coerce_to(self.type, env) self.operand2 = self.operand2.coerce_to(self.type, env) def compute_c_result_type(self, type1, type2): if self.c_types_okay(type1, type2): widest_type = PyrexTypes.widest_numeric_type(type1, type2) if widest_type is PyrexTypes.c_bint_type: if self.operator not in '|^&': # False + False == 0 # not False! widest_type = PyrexTypes.c_int_type else: widest_type = PyrexTypes.widest_numeric_type( widest_type, PyrexTypes.c_int_type) return widest_type else: return None def may_be_none(self): if self.type and self.type.is_builtin_type: # if we know the result type, we know the operation, so it can't be None return False type1 = self.operand1.type type2 = self.operand2.type if type1 and type1.is_builtin_type and type2 and type2.is_builtin_type: # XXX: I can't think of any case where a binary operation # on builtin types evaluates to None - add a special case # here if there is one. return False return super(NumBinopNode, self).may_be_none() def get_constant_c_result_code(self): value1 = self.operand1.get_constant_c_result_code() value2 = self.operand2.get_constant_c_result_code() if value1 and value2: return "(%s %s %s)" % (value1, self.operator, value2) else: return None def c_types_okay(self, type1, type2): #print "NumBinopNode.c_types_okay:", type1, type2 ### return (type1.is_numeric or type1.is_enum) \ and (type2.is_numeric or type2.is_enum) def generate_evaluation_code(self, code): if self.overflow_check: self.overflow_bit_node = self self.overflow_bit = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False) code.putln("%s = 0;" % self.overflow_bit) super(NumBinopNode, self).generate_evaluation_code(code) if self.overflow_check: code.putln("if (unlikely(%s)) {" % self.overflow_bit) code.putln('PyErr_SetString(PyExc_OverflowError, "value too large");') code.putln(code.error_goto(self.pos)) code.putln("}") code.funcstate.release_temp(self.overflow_bit) def calculate_result_code(self): if self.overflow_bit_node is not None: return "%s(%s, %s, &%s)" % ( self.func, self.operand1.result(), self.operand2.result(), self.overflow_bit_node.overflow_bit) elif self.type.is_cpp_class or self.infix: if is_pythran_expr(self.type): result1, result2 = self.operand1.pythran_result(), self.operand2.pythran_result() else: result1, result2 = self.operand1.result(), self.operand2.result() return "(%s %s %s)" % (result1, self.operator, result2) else: func = self.type.binary_op(self.operator) if func is None: error(self.pos, "binary operator %s not supported for %s" % (self.operator, self.type)) return "%s(%s, %s)" % ( func, self.operand1.result(), self.operand2.result()) def is_py_operation_types(self, type1, type2): return (type1.is_unicode_char or type2.is_unicode_char or BinopNode.is_py_operation_types(self, type1, type2)) def py_operation_function(self, code): function_name = self.py_functions[self.operator] if self.inplace: function_name = function_name.replace('PyNumber_', 'PyNumber_InPlace') return function_name py_functions = { "|": "PyNumber_Or", "^": "PyNumber_Xor", "&": "PyNumber_And", "<<": "PyNumber_Lshift", ">>": "PyNumber_Rshift", "+": "PyNumber_Add", "-": "PyNumber_Subtract", "*": "PyNumber_Multiply", "@": "__Pyx_PyNumber_MatrixMultiply", "/": "__Pyx_PyNumber_Divide", "//": "PyNumber_FloorDivide", "%": "PyNumber_Remainder", "**": "PyNumber_Power", } overflow_op_names = { "+": "add", "-": "sub", "*": "mul", "<<": "lshift", } class IntBinopNode(NumBinopNode): # Binary operation taking integer arguments. def c_types_okay(self, type1, type2): #print "IntBinopNode.c_types_okay:", type1, type2 ### return (type1.is_int or type1.is_enum) \ and (type2.is_int or type2.is_enum) class AddNode(NumBinopNode): # '+' operator. def is_py_operation_types(self, type1, type2): if type1.is_string and type2.is_string or type1.is_pyunicode_ptr and type2.is_pyunicode_ptr: return 1 else: return NumBinopNode.is_py_operation_types(self, type1, type2) def infer_builtin_types_operation(self, type1, type2): # b'abc' + 'abc' raises an exception in Py3, # so we can safely infer the Py2 type for bytes here string_types = (bytes_type, bytearray_type, str_type, basestring_type, unicode_type) if type1 in string_types and type2 in string_types: return string_types[max(string_types.index(type1), string_types.index(type2))] return None def compute_c_result_type(self, type1, type2): #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ### if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum): return type1 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum): return type2 else: return NumBinopNode.compute_c_result_type( self, type1, type2) def py_operation_function(self, code): type1, type2 = self.operand1.type, self.operand2.type func = None if type1 is unicode_type or type2 is unicode_type: if type1 in (unicode_type, str_type) and type2 in (unicode_type, str_type): is_unicode_concat = True elif isinstance(self.operand1, FormattedValueNode) or isinstance(self.operand2, FormattedValueNode): # Assume that even if we don't know the second type, it's going to be a string. is_unicode_concat = True else: # Operation depends on the second type. is_unicode_concat = False if is_unicode_concat: if self.inplace or self.operand1.is_temp: code.globalstate.use_utility_code( UtilityCode.load_cached("UnicodeConcatInPlace", "ObjectHandling.c")) func = '__Pyx_PyUnicode_Concat' elif type1 is str_type and type2 is str_type: code.globalstate.use_utility_code( UtilityCode.load_cached("StrConcatInPlace", "ObjectHandling.c")) func = '__Pyx_PyStr_Concat' if func: # any necessary utility code will be got by "NumberAdd" in generate_evaluation_code if self.inplace or self.operand1.is_temp: func += 'InPlace' # upper case to indicate unintuitive macro if self.operand1.may_be_none() or self.operand2.may_be_none(): func += 'Safe' return func return super(AddNode, self).py_operation_function(code) class SubNode(NumBinopNode): # '-' operator. def compute_c_result_type(self, type1, type2): if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum): return type1 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array): return PyrexTypes.c_ptrdiff_t_type else: return NumBinopNode.compute_c_result_type( self, type1, type2) class MulNode(NumBinopNode): # '*' operator. is_sequence_mul = False def analyse_types(self, env): self.operand1 = self.operand1.analyse_types(env) self.operand2 = self.operand2.analyse_types(env) self.is_sequence_mul = self.calculate_is_sequence_mul() # TODO: we could also optimise the case of "[...] * 2 * n", i.e. with an existing 'mult_factor' if self.is_sequence_mul: operand1 = self.operand1 operand2 = self.operand2 if operand1.is_sequence_constructor and operand1.mult_factor is None: return self.analyse_sequence_mul(env, operand1, operand2) elif operand2.is_sequence_constructor and operand2.mult_factor is None: return self.analyse_sequence_mul(env, operand2, operand1) self.analyse_operation(env) return self @staticmethod def is_builtin_seqmul_type(type): return type.is_builtin_type and type in builtin_sequence_types and type is not memoryview_type def calculate_is_sequence_mul(self): type1 = self.operand1.type type2 = self.operand2.type if type1 is long_type or type1.is_int: # normalise to (X * int) type1, type2 = type2, type1 if type2 is long_type or type2.is_int: if type1.is_string or type1.is_ctuple: return True if self.is_builtin_seqmul_type(type1): return True return False def analyse_sequence_mul(self, env, seq, mult): assert seq.mult_factor is None seq = seq.coerce_to_pyobject(env) seq.mult_factor = mult return seq.analyse_types(env) def coerce_operands_to_pyobjects(self, env): if self.is_sequence_mul: # Keep operands as they are, but ctuples must become Python tuples to multiply them. if self.operand1.type.is_ctuple: self.operand1 = self.operand1.coerce_to_pyobject(env) elif self.operand2.type.is_ctuple: self.operand2 = self.operand2.coerce_to_pyobject(env) return super(MulNode, self).coerce_operands_to_pyobjects(env) def is_py_operation_types(self, type1, type2): return self.is_sequence_mul or super(MulNode, self).is_py_operation_types(type1, type2) def py_operation_function(self, code): if self.is_sequence_mul: code.globalstate.use_utility_code( UtilityCode.load_cached("PySequenceMultiply", "ObjectHandling.c")) return "__Pyx_PySequence_Multiply" if self.operand1.type.is_pyobject else "__Pyx_PySequence_Multiply_Left" return super(MulNode, self).py_operation_function(code) def infer_builtin_types_operation(self, type1, type2): # let's assume that whatever builtin type you multiply a builtin sequence type with # will either return a sequence of the same type or fail with an exception if type1.is_builtin_type and type2.is_builtin_type: if self.is_builtin_seqmul_type(type1): return type1 if self.is_builtin_seqmul_type(type2): return type2 # multiplication of containers/numbers with an integer value # always (?) returns the same type if type1.is_int: return type2 if type2.is_int: return type1 return None class MatMultNode(NumBinopNode): # '@' operator. def is_py_operation_types(self, type1, type2): return True def generate_evaluation_code(self, code): code.globalstate.use_utility_code(UtilityCode.load_cached("MatrixMultiply", "ObjectHandling.c")) super(MatMultNode, self).generate_evaluation_code(code) class DivNode(NumBinopNode): # '/' or '//' operator. cdivision = None truedivision = None # == "unknown" if operator == '/' ctruedivision = False cdivision_warnings = False zerodivision_check = None def find_compile_time_binary_operator(self, op1, op2): func = compile_time_binary_operators[self.operator] if self.operator == '/' and self.truedivision is None: # => true div for floats, floor div for integers if isinstance(op1, _py_int_types) and isinstance(op2, _py_int_types): func = compile_time_binary_operators['//'] return func def calculate_constant_result(self): op1 = self.operand1.constant_result op2 = self.operand2.constant_result func = self.find_compile_time_binary_operator(op1, op2) self.constant_result = func( self.operand1.constant_result, self.operand2.constant_result) def compile_time_value(self, denv): operand1 = self.operand1.compile_time_value(denv) operand2 = self.operand2.compile_time_value(denv) try: func = self.find_compile_time_binary_operator( operand1, operand2) return func(operand1, operand2) except Exception as e: self.compile_time_value_error(e) def _check_truedivision(self, env): if self.cdivision or env.directives['cdivision']: self.ctruedivision = False else: self.ctruedivision = self.truedivision def infer_type(self, env): self._check_truedivision(env) return self.result_type( self.operand1.infer_type(env), self.operand2.infer_type(env), env) def analyse_operation(self, env): self._check_truedivision(env) NumBinopNode.analyse_operation(self, env) if self.is_cpp_operation(): self.cdivision = True if not self.type.is_pyobject: self.zerodivision_check = ( self.cdivision is None and not env.directives['cdivision'] and (not self.operand2.has_constant_result() or self.operand2.constant_result == 0)) if self.zerodivision_check or env.directives['cdivision_warnings']: # Need to check ahead of time to warn or raise zero division error self.operand1 = self.operand1.coerce_to_simple(env) self.operand2 = self.operand2.coerce_to_simple(env) def compute_c_result_type(self, type1, type2): if self.operator == '/' and self.ctruedivision and not type1.is_cpp_class and not type2.is_cpp_class: if not type1.is_float and not type2.is_float: widest_type = PyrexTypes.widest_numeric_type(type1, PyrexTypes.c_double_type) widest_type = PyrexTypes.widest_numeric_type(type2, widest_type) return widest_type return NumBinopNode.compute_c_result_type(self, type1, type2) def zero_division_message(self): if self.type.is_int: return "integer division or modulo by zero" else: return "float division" def generate_evaluation_code(self, code): if not self.type.is_pyobject and not self.type.is_complex: if self.cdivision is None: self.cdivision = ( code.globalstate.directives['cdivision'] or self.type.is_float or ((self.type.is_numeric or self.type.is_enum) and not self.type.signed) ) if not self.cdivision: code.globalstate.use_utility_code( UtilityCode.load_cached("DivInt", "CMath.c").specialize(self.type)) NumBinopNode.generate_evaluation_code(self, code) self.generate_div_warning_code(code) def generate_div_warning_code(self, code): in_nogil = self.in_nogil_context if not self.type.is_pyobject: if self.zerodivision_check: if not self.infix: zero_test = "%s(%s)" % (self.type.unary_op('zero'), self.operand2.result()) else: zero_test = "%s == 0" % self.operand2.result() code.putln("if (unlikely(%s)) {" % zero_test) if in_nogil: code.put_ensure_gil() code.putln('PyErr_SetString(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message()) if in_nogil: code.put_release_ensured_gil() code.putln(code.error_goto(self.pos)) code.putln("}") if self.type.is_int and self.type.signed and self.operator != '%': code.globalstate.use_utility_code(UtilityCode.load_cached("UnaryNegOverflows", "Overflow.c")) if self.operand2.type.signed == 2: # explicitly signed, no runtime check needed minus1_check = 'unlikely(%s == -1)' % self.operand2.result() else: type_of_op2 = self.operand2.type.empty_declaration_code() minus1_check = '(!(((%s)-1) > 0)) && unlikely(%s == (%s)-1)' % ( type_of_op2, self.operand2.result(), type_of_op2) code.putln("else if (sizeof(%s) == sizeof(long) && %s " " && unlikely(__Pyx_UNARY_NEG_WOULD_OVERFLOW(%s))) {" % ( self.type.empty_declaration_code(), minus1_check, self.operand1.result())) if in_nogil: code.put_ensure_gil() code.putln('PyErr_SetString(PyExc_OverflowError, "value too large to perform division");') if in_nogil: code.put_release_ensured_gil() code.putln(code.error_goto(self.pos)) code.putln("}") if code.globalstate.directives['cdivision_warnings'] and self.operator != '/': code.globalstate.use_utility_code( UtilityCode.load_cached("CDivisionWarning", "CMath.c")) code.putln("if (unlikely((%s < 0) ^ (%s < 0))) {" % ( self.operand1.result(), self.operand2.result())) warning_code = "__Pyx_cdivision_warning(%(FILENAME)s, %(LINENO)s)" % { 'FILENAME': Naming.filename_cname, 'LINENO': Naming.lineno_cname, } if in_nogil: result_code = 'result' code.putln("int %s;" % result_code) code.put_ensure_gil() code.putln(code.set_error_info(self.pos, used=True)) code.putln("%s = %s;" % (result_code, warning_code)) code.put_release_ensured_gil() else: result_code = warning_code code.putln(code.set_error_info(self.pos, used=True)) code.put("if (unlikely(%s)) " % result_code) code.put_goto(code.error_label) code.putln("}") def calculate_result_code(self): if self.type.is_complex or self.is_cpp_operation(): return NumBinopNode.calculate_result_code(self) elif self.type.is_float and self.operator == '//': return "floor(%s / %s)" % ( self.operand1.result(), self.operand2.result()) elif self.truedivision or self.cdivision: op1 = self.operand1.result() op2 = self.operand2.result() if self.truedivision: if self.type != self.operand1.type: op1 = self.type.cast_code(op1) if self.type != self.operand2.type: op2 = self.type.cast_code(op2) return "(%s / %s)" % (op1, op2) else: return "__Pyx_div_%s(%s, %s)" % ( self.type.specialization_name(), self.operand1.result(), self.operand2.result()) _find_formatting_types = re.compile( br"%" br"(?:%|" # %% br"(?:\([^)]+\))?" # %(name) br"[-+#,0-9 ]*([a-z])" # %.2f etc. br")").findall # These format conversion types can never trigger a Unicode string conversion in Py2. _safe_bytes_formats = frozenset({ # Excludes 's' and 'r', which can generate non-bytes strings. b'd', b'i', b'o', b'u', b'x', b'X', b'e', b'E', b'f', b'F', b'g', b'G', b'c', b'b', b'a', }) class ModNode(DivNode): # '%' operator. def is_py_operation_types(self, type1, type2): return (type1.is_string or type2.is_string or NumBinopNode.is_py_operation_types(self, type1, type2)) def infer_builtin_types_operation(self, type1, type2): # b'%s' % xyz raises an exception in Py3<3.5, so it's safe to infer the type for Py2 and later Py3's. if type1 is unicode_type: # None + xyz may be implemented by RHS if type2.is_builtin_type or not self.operand1.may_be_none(): return type1 elif type1 in (bytes_type, str_type, basestring_type): if type2 is unicode_type: return type2 elif type2.is_numeric: return type1 elif self.operand1.is_string_literal: if type1 is str_type or type1 is bytes_type: if set(_find_formatting_types(self.operand1.value)) <= _safe_bytes_formats: return type1 return basestring_type elif type1 is bytes_type and not type2.is_builtin_type: return None # RHS might implement '% operator differently in Py3 else: return basestring_type # either str or unicode, can't tell return None def zero_division_message(self): if self.type.is_int: return "integer division or modulo by zero" else: return "float divmod()" def analyse_operation(self, env): DivNode.analyse_operation(self, env) if not self.type.is_pyobject: if self.cdivision is None: self.cdivision = env.directives['cdivision'] or not self.type.signed if not self.cdivision and not self.type.is_int and not self.type.is_float: error(self.pos, "mod operator not supported for type '%s'" % self.type) def generate_evaluation_code(self, code): if not self.type.is_pyobject and not self.cdivision: if self.type.is_int: code.globalstate.use_utility_code( UtilityCode.load_cached("ModInt", "CMath.c").specialize(self.type)) else: # float code.globalstate.use_utility_code( UtilityCode.load_cached("ModFloat", "CMath.c").specialize( self.type, math_h_modifier=self.type.math_h_modifier)) # NOTE: skipping over DivNode here NumBinopNode.generate_evaluation_code(self, code) self.generate_div_warning_code(code) def calculate_result_code(self): if self.cdivision: if self.type.is_float: return "fmod%s(%s, %s)" % ( self.type.math_h_modifier, self.operand1.result(), self.operand2.result()) else: return "(%s %% %s)" % ( self.operand1.result(), self.operand2.result()) else: return "__Pyx_mod_%s(%s, %s)" % ( self.type.specialization_name(), self.operand1.result(), self.operand2.result()) def py_operation_function(self, code): type1, type2 = self.operand1.type, self.operand2.type # ("..." % x) must call "x.__rmod__()" for string subtypes. if type1 is unicode_type: if self.operand1.may_be_none() or ( type2.is_extension_type and type2.subtype_of(type1) or type2 is py_object_type and not isinstance(self.operand2, CoerceToPyTypeNode)): return '__Pyx_PyUnicode_FormatSafe' else: return 'PyUnicode_Format' elif type1 is str_type: if self.operand1.may_be_none() or ( type2.is_extension_type and type2.subtype_of(type1) or type2 is py_object_type and not isinstance(self.operand2, CoerceToPyTypeNode)): return '__Pyx_PyString_FormatSafe' else: return '__Pyx_PyString_Format' return super(ModNode, self).py_operation_function(code) class PowNode(NumBinopNode): # '**' operator. is_cpow = None type_was_inferred = False # was the result type affected by cpow==False? # Intended to allow it to be changed if the node is coerced. def _check_cpow(self, env): if self.is_cpow is not None: return # already set self.is_cpow = env.directives['cpow'] def infer_type(self, env): self._check_cpow(env) return super(PowNode, self).infer_type(env) def analyse_types(self, env): self._check_cpow(env) return super(PowNode, self).analyse_types(env) def analyse_c_operation(self, env): NumBinopNode.analyse_c_operation(self, env) if self.type.is_complex: if self.type.real_type.is_float: self.operand1 = self.operand1.coerce_to(self.type, env) self.operand2 = self.operand2.coerce_to(self.type, env) self.pow_func = self.type.binary_op('**') else: error(self.pos, "complex int powers not supported") self.pow_func = "" elif self.type.is_float: self.pow_func = "pow" + self.type.math_h_modifier elif self.type.is_int: self.pow_func = "__Pyx_pow_%s" % self.type.empty_declaration_code().replace(' ', '_') env.use_utility_code( UtilityCode.load_cached("IntPow", "CMath.c").specialize( func_name=self.pow_func, type=self.type.empty_declaration_code(), signed=self.type.signed and 1 or 0)) elif not self.type.is_error: error(self.pos, "got unexpected types for C power operator: %s, %s" % (self.operand1.type, self.operand2.type)) def compute_c_result_type(self, type1, type2): from numbers import Real c_result_type = None op1_is_definitely_positive = ( self.operand1.has_constant_result() and self.operand1.constant_result >= 0 ) or ( type1.is_int and type1.signed == 0 # definitely unsigned ) type2_is_int = type2.is_int or ( self.operand2.has_constant_result() and isinstance(self.operand2.constant_result, Real) and int(self.operand2.constant_result) == self.operand2.constant_result ) needs_widening = False if self.is_cpow: c_result_type = super(PowNode, self).compute_c_result_type(type1, type2) if not self.operand2.has_constant_result(): needs_widening = ( isinstance(self.operand2.constant_result, _py_int_types) and self.operand2.constant_result < 0 ) elif op1_is_definitely_positive or type2_is_int: # cpow==False # if type2 is an integer then we can't end up going from real to complex c_result_type = super(PowNode, self).compute_c_result_type(type1, type2) if not self.operand2.has_constant_result(): needs_widening = type2.is_int and type2.signed if needs_widening: self.type_was_inferred = True else: needs_widening = ( isinstance(self.operand2.constant_result, _py_int_types) and self.operand2.constant_result < 0 ) elif self.c_types_okay(type1, type2): # Allowable result types are double or complex double. # Return the special "soft complex" type to store it as a # complex number but with specialized coercions to Python c_result_type = PyrexTypes.soft_complex_type self.type_was_inferred = True if needs_widening: c_result_type = PyrexTypes.widest_numeric_type(c_result_type, PyrexTypes.c_double_type) return c_result_type def calculate_result_code(self): # Work around MSVC overloading ambiguity. def typecast(operand): if self.type == operand.type: return operand.result() else: return self.type.cast_code(operand.result()) return "%s(%s, %s)" % ( self.pow_func, typecast(self.operand1), typecast(self.operand2)) def py_operation_function(self, code): if (self.type.is_pyobject and self.operand1.constant_result == 2 and isinstance(self.operand1.constant_result, _py_int_types) and self.operand2.type is py_object_type): code.globalstate.use_utility_code(UtilityCode.load_cached('PyNumberPow2', 'Optimize.c')) if self.inplace: return '__Pyx_PyNumber_InPlacePowerOf2' else: return '__Pyx_PyNumber_PowerOf2' return super(PowNode, self).py_operation_function(code) def coerce_to(self, dst_type, env): if dst_type == self.type: return self if (self.is_cpow is None and self.type_was_inferred and (dst_type.is_float or dst_type.is_int)): # if we're trying to coerce this directly to a C float or int # then fall back to the cpow == True behaviour since this is # almost certainly the user intent. # However, ensure that the operand types are suitable C types if self.type is PyrexTypes.soft_complex_type: def check_types(operand, recurse=True): if operand.type.is_float or operand.type.is_int: return True, operand if recurse and isinstance(operand, CoerceToComplexNode): return check_types(operand.arg, recurse=False), operand.arg return False, None msg_detail = "a non-complex C numeric type" elif dst_type.is_int: def check_types(operand): if operand.type.is_int: return True, operand else: # int, int doesn't seem to involve coercion nodes return False, None msg_detail = "an integer C numeric type" else: def check_types(operand): return False, None check_op1, op1 = check_types(self.operand1) check_op2, op2 = check_types(self.operand2) if check_op1 and check_op2: warning(self.pos, "Treating '**' as if 'cython.cpow(True)' since it " "is directly assigned to a %s. " "This is likely to be fragile and we recommend setting " "'cython.cpow' explicitly." % msg_detail) self.is_cpow = True self.operand1 = op1 self.operand2 = op2 result = self.analyse_types(env) if result.type != dst_type: result = result.coerce_to(dst_type, env) return result return super(PowNode, self).coerce_to(dst_type, env) class BoolBinopNode(ExprNode): """ Short-circuiting boolean operation. Note that this node provides the same code generation method as BoolBinopResultNode to simplify expression nesting. operator string "and"/"or" operand1 BoolBinopNode/BoolBinopResultNode left operand operand2 BoolBinopNode/BoolBinopResultNode right operand """ subexprs = ['operand1', 'operand2'] is_temp = True operator = None operand1 = None operand2 = None def infer_type(self, env): type1 = self.operand1.infer_type(env) type2 = self.operand2.infer_type(env) return PyrexTypes.independent_spanning_type(type1, type2) def may_be_none(self): if self.operator == 'or': return self.operand2.may_be_none() else: return self.operand1.may_be_none() or self.operand2.may_be_none() def calculate_constant_result(self): operand1 = self.operand1.constant_result operand2 = self.operand2.constant_result if self.operator == 'and': self.constant_result = operand1 and operand2 else: self.constant_result = operand1 or operand2 def compile_time_value(self, denv): operand1 = self.operand1.compile_time_value(denv) operand2 = self.operand2.compile_time_value(denv) if self.operator == 'and': return operand1 and operand2 else: return operand1 or operand2 def is_ephemeral(self): return self.operand1.is_ephemeral() or self.operand2.is_ephemeral() def analyse_types(self, env): # Note: we do not do any coercion here as we most likely do not know the final type anyway. # We even accept to set self.type to ErrorType if both operands do not have a spanning type. # The coercion to the final type and to a "simple" value is left to coerce_to(). operand1 = self.operand1.analyse_types(env) operand2 = self.operand2.analyse_types(env) self.type = PyrexTypes.independent_spanning_type( operand1.type, operand2.type) self.operand1 = self._wrap_operand(operand1, env) self.operand2 = self._wrap_operand(operand2, env) return self def _wrap_operand(self, operand, env): if not isinstance(operand, (BoolBinopNode, BoolBinopResultNode)): operand = BoolBinopResultNode(operand, self.type, env) return operand def wrap_operands(self, env): """ Must get called by transforms that want to create a correct BoolBinopNode after the type analysis phase. """ self.operand1 = self._wrap_operand(self.operand1, env) self.operand2 = self._wrap_operand(self.operand2, env) def coerce_to_boolean(self, env): return self.coerce_to(PyrexTypes.c_bint_type, env) def coerce_to(self, dst_type, env): operand1 = self.operand1.coerce_to(dst_type, env) operand2 = self.operand2.coerce_to(dst_type, env) return BoolBinopNode.from_node( self, type=dst_type, operator=self.operator, operand1=operand1, operand2=operand2) def generate_bool_evaluation_code(self, code, final_result_temp, final_result_type, and_label, or_label, end_label, fall_through): code.mark_pos(self.pos) outer_labels = (and_label, or_label) if self.operator == 'and': my_label = and_label = code.new_label('next_and') else: my_label = or_label = code.new_label('next_or') self.operand1.generate_bool_evaluation_code( code, final_result_temp, final_result_type, and_label, or_label, end_label, my_label) and_label, or_label = outer_labels code.put_label(my_label) self.operand2.generate_bool_evaluation_code( code, final_result_temp, final_result_type, and_label, or_label, end_label, fall_through) def generate_evaluation_code(self, code): self.allocate_temp_result(code) result_type = PyrexTypes.py_object_type if self.type.is_pyobject else self.type or_label = and_label = None end_label = code.new_label('bool_binop_done') self.generate_bool_evaluation_code(code, self.result(), result_type, and_label, or_label, end_label, end_label) code.put_label(end_label) gil_message = "Truth-testing Python object" def check_const(self): return self.operand1.check_const() and self.operand2.check_const() def generate_subexpr_disposal_code(self, code): pass # nothing to do here, all done in generate_evaluation_code() def free_subexpr_temps(self, code): pass # nothing to do here, all done in generate_evaluation_code() def generate_operand1_test(self, code): # Generate code to test the truth of the first operand. if self.type.is_pyobject: test_result = code.funcstate.allocate_temp( PyrexTypes.c_bint_type, manage_ref=False) code.putln( "%s = __Pyx_PyObject_IsTrue(%s); %s" % ( test_result, self.operand1.py_result(), code.error_goto_if_neg(test_result, self.pos))) else: test_result = self.operand1.result() return (test_result, self.type.is_pyobject) class BoolBinopResultNode(ExprNode): """ Intermediate result of a short-circuiting and/or expression. Tests the result for 'truthiness' and takes care of coercing the final result of the overall expression to the target type. Note that this node provides the same code generation method as BoolBinopNode to simplify expression nesting. arg ExprNode the argument to test value ExprNode the coerced result value node """ subexprs = ['arg', 'value'] is_temp = True arg = None value = None def __init__(self, arg, result_type, env): # using 'arg' multiple times, so it must be a simple/temp value arg = arg.coerce_to_simple(env) # wrap in ProxyNode, in case a transform wants to replace self.arg later arg = ProxyNode(arg) super(BoolBinopResultNode, self).__init__( arg.pos, arg=arg, type=result_type, value=CloneNode(arg).coerce_to(result_type, env)) def coerce_to_boolean(self, env): return self.coerce_to(PyrexTypes.c_bint_type, env) def coerce_to(self, dst_type, env): # unwrap, coerce, rewrap arg = self.arg.arg if dst_type is PyrexTypes.c_bint_type: arg = arg.coerce_to_boolean(env) # TODO: unwrap more coercion nodes? return BoolBinopResultNode(arg, dst_type, env) def nogil_check(self, env): # let's leave all errors to BoolBinopNode pass def generate_operand_test(self, code): # Generate code to test the truth of the first operand. if self.arg.type.is_pyobject: test_result = code.funcstate.allocate_temp( PyrexTypes.c_bint_type, manage_ref=False) code.putln( "%s = __Pyx_PyObject_IsTrue(%s); %s" % ( test_result, self.arg.py_result(), code.error_goto_if_neg(test_result, self.pos))) else: test_result = self.arg.result() return (test_result, self.arg.type.is_pyobject) def generate_bool_evaluation_code(self, code, final_result_temp, final_result_type, and_label, or_label, end_label, fall_through): code.mark_pos(self.pos) # x => x # x and ... or ... => next 'and' / 'or' # False ... or x => next 'or' # True and x => next 'and' # True or x => True (operand) self.arg.generate_evaluation_code(code) if and_label or or_label: test_result, uses_temp = self.generate_operand_test(code) if uses_temp and (and_label and or_label): # cannot become final result => free early # disposal: uses_temp and (and_label and or_label) self.arg.generate_disposal_code(code) sense = '!' if or_label else '' code.putln("if (%s%s) {" % (sense, test_result)) if uses_temp: code.funcstate.release_temp(test_result) if not uses_temp or not (and_label and or_label): # disposal: (not uses_temp) or {not (and_label and or_label) [if]} self.arg.generate_disposal_code(code) if or_label and or_label != fall_through: # value is false => short-circuit to next 'or' code.put_goto(or_label) if and_label: # value is true => go to next 'and' if or_label: code.putln("} else {") if not uses_temp: # disposal: (not uses_temp) and {(and_label and or_label) [else]} self.arg.generate_disposal_code(code) if and_label != fall_through: code.put_goto(and_label) if not and_label or not or_label: # if no next 'and' or 'or', we provide the result if and_label or or_label: code.putln("} else {") self.value.generate_evaluation_code(code) self.value.make_owned_reference(code) code.putln("%s = %s;" % (final_result_temp, self.value.result_as(final_result_type))) self.value.generate_post_assignment_code(code) # disposal: {not (and_label and or_label) [else]} self.arg.generate_disposal_code(code) self.value.free_temps(code) if end_label != fall_through: code.put_goto(end_label) if and_label or or_label: code.putln("}") self.arg.free_temps(code) def analyse_types(self, env): return self class CondExprNode(ExprNode): # Short-circuiting conditional expression. # # test ExprNode # true_val ExprNode # false_val ExprNode true_val = None false_val = None is_temp = True subexprs = ['test', 'true_val', 'false_val'] def type_dependencies(self, env): return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env) def infer_type(self, env): return PyrexTypes.independent_spanning_type( self.true_val.infer_type(env), self.false_val.infer_type(env)) def calculate_constant_result(self): if self.test.constant_result: self.constant_result = self.true_val.constant_result else: self.constant_result = self.false_val.constant_result def is_ephemeral(self): return self.true_val.is_ephemeral() or self.false_val.is_ephemeral() def analyse_types(self, env): self.test = self.test.analyse_temp_boolean_expression(env) self.true_val = self.true_val.analyse_types(env) self.false_val = self.false_val.analyse_types(env) return self.analyse_result_type(env) def analyse_result_type(self, env): true_val_type = self.true_val.type false_val_type = self.false_val.type self.type = PyrexTypes.independent_spanning_type(true_val_type, false_val_type) if self.type.is_reference: self.type = PyrexTypes.CFakeReferenceType(self.type.ref_base_type) if self.type.is_pyobject: self.result_ctype = py_object_type elif self.true_val.is_ephemeral() or self.false_val.is_ephemeral(): error(self.pos, "Unsafe C derivative of temporary Python reference used in conditional expression") if true_val_type.is_pyobject or false_val_type.is_pyobject or self.type.is_pyobject: if true_val_type != self.type: self.true_val = self.true_val.coerce_to(self.type, env) if false_val_type != self.type: self.false_val = self.false_val.coerce_to(self.type, env) if self.type.is_error: self.type_error() return self def coerce_to_integer(self, env): if not self.true_val.type.is_int: self.true_val = self.true_val.coerce_to_integer(env) if not self.false_val.type.is_int: self.false_val = self.false_val.coerce_to_integer(env) self.result_ctype = None out = self.analyse_result_type(env) if not out.type.is_int: # fall back to ordinary coercion since we haven't ended as the correct type if out is self: out = super(CondExprNode, out).coerce_to_integer(env) else: # I believe `analyse_result_type` always returns a CondExprNode but # handle the opposite case just in case out = out.coerce_to_integer(env) return out def coerce_to(self, dst_type, env): if self.true_val.type != dst_type: self.true_val = self.true_val.coerce_to(dst_type, env) if self.false_val.type != dst_type: self.false_val = self.false_val.coerce_to(dst_type, env) self.result_ctype = None out = self.analyse_result_type(env) if out.type != dst_type: # fall back to ordinary coercion since we haven't ended as the correct type if out is self: out = super(CondExprNode, out).coerce_to(dst_type, env) else: # I believe `analyse_result_type` always returns a CondExprNode but # handle the opposite case just in case out = out.coerce_to(dst_type, env) return out def type_error(self): if not (self.true_val.type.is_error or self.false_val.type.is_error): error(self.pos, "Incompatible types in conditional expression (%s; %s)" % (self.true_val.type, self.false_val.type)) self.type = PyrexTypes.error_type def check_const(self): return (self.test.check_const() and self.true_val.check_const() and self.false_val.check_const()) def generate_evaluation_code(self, code): # Because subexprs may not be evaluated we can use a more optimal # subexpr allocation strategy than the default, so override evaluation_code. code.mark_pos(self.pos) self.allocate_temp_result(code) self.test.generate_evaluation_code(code) code.putln("if (%s) {" % self.test.result()) self.eval_and_get(code, self.true_val) code.putln("} else {") self.eval_and_get(code, self.false_val) code.putln("}") self.test.generate_disposal_code(code) self.test.free_temps(code) def eval_and_get(self, code, expr): expr.generate_evaluation_code(code) if self.type.is_memoryviewslice: expr.make_owned_memoryviewslice(code) else: expr.make_owned_reference(code) code.putln('%s = %s;' % (self.result(), expr.result_as(self.ctype()))) expr.generate_post_assignment_code(code) expr.free_temps(code) def generate_subexpr_disposal_code(self, code): pass # done explicitly above (cleanup must separately happen within the if/else blocks) def free_subexpr_temps(self, code): pass # done explicitly above (cleanup must separately happen within the if/else blocks) richcmp_constants = { "<" : "Py_LT", "<=": "Py_LE", "==": "Py_EQ", "!=": "Py_NE", "<>": "Py_NE", ">" : "Py_GT", ">=": "Py_GE", # the following are faked by special compare functions "in" : "Py_EQ", "not_in": "Py_NE", } class CmpNode(object): # Mixin class containing code common to PrimaryCmpNodes # and CascadedCmpNodes. special_bool_cmp_function = None special_bool_cmp_utility_code = None special_bool_extra_args = [] def infer_type(self, env): # TODO: Actually implement this (after merging with -unstable). return py_object_type def calculate_cascaded_constant_result(self, operand1_result): func = compile_time_binary_operators[self.operator] operand2_result = self.operand2.constant_result if (isinstance(operand1_result, any_string_type) and isinstance(operand2_result, any_string_type) and type(operand1_result) != type(operand2_result)): # string comparison of different types isn't portable return if self.operator in ('in', 'not_in'): if isinstance(self.operand2, (ListNode, TupleNode, SetNode)): if not self.operand2.args: self.constant_result = self.operator == 'not_in' return elif isinstance(self.operand2, ListNode) and not self.cascade: # tuples are more efficient to store than lists self.operand2 = self.operand2.as_tuple() elif isinstance(self.operand2, DictNode): if not self.operand2.key_value_pairs: self.constant_result = self.operator == 'not_in' return self.constant_result = func(operand1_result, operand2_result) def cascaded_compile_time_value(self, operand1, denv): func = get_compile_time_binop(self) operand2 = self.operand2.compile_time_value(denv) try: result = func(operand1, operand2) except Exception as e: self.compile_time_value_error(e) result = None if result: cascade = self.cascade if cascade: result = result and cascade.cascaded_compile_time_value(operand2, denv) return result def is_cpp_comparison(self): return self.operand1.type.is_cpp_class or self.operand2.type.is_cpp_class def find_common_int_type(self, env, op, operand1, operand2): # type1 != type2 and at least one of the types is not a C int type1 = operand1.type type2 = operand2.type type1_can_be_int = False type2_can_be_int = False if operand1.is_string_literal and operand1.can_coerce_to_char_literal(): type1_can_be_int = True if operand2.is_string_literal and operand2.can_coerce_to_char_literal(): type2_can_be_int = True if type1.is_int: if type2_can_be_int: return type1 elif type2.is_int: if type1_can_be_int: return type2 elif type1_can_be_int: if type2_can_be_int: if Builtin.unicode_type in (type1, type2): return PyrexTypes.c_py_ucs4_type else: return PyrexTypes.c_uchar_type return None def find_common_type(self, env, op, operand1, common_type=None): operand2 = self.operand2 type1 = operand1.type type2 = operand2.type new_common_type = None # catch general errors if (type1 == str_type and (type2.is_string or type2 in (bytes_type, unicode_type)) or type2 == str_type and (type1.is_string or type1 in (bytes_type, unicode_type))): error(self.pos, "Comparisons between bytes/unicode and str are not portable to Python 3") new_common_type = error_type # try to use numeric comparisons where possible elif type1.is_complex or type2.is_complex: if (op not in ('==', '!=') and (type1.is_complex or type1.is_numeric) and (type2.is_complex or type2.is_numeric)): error(self.pos, "complex types are unordered") new_common_type = error_type elif type1.is_pyobject: new_common_type = Builtin.complex_type if type1.subtype_of(Builtin.complex_type) else py_object_type elif type2.is_pyobject: new_common_type = Builtin.complex_type if type2.subtype_of(Builtin.complex_type) else py_object_type else: new_common_type = PyrexTypes.widest_numeric_type(type1, type2) elif type1.is_numeric and type2.is_numeric: new_common_type = PyrexTypes.widest_numeric_type(type1, type2) elif common_type is None or not common_type.is_pyobject: new_common_type = self.find_common_int_type(env, op, operand1, operand2) if new_common_type is None: # fall back to generic type compatibility tests if type1.is_ctuple or type2.is_ctuple: new_common_type = py_object_type elif type1 == type2: new_common_type = type1 elif type1.is_pyobject or type2.is_pyobject: if type2.is_numeric or type2.is_string: if operand2.check_for_coercion_error(type1, env): new_common_type = error_type else: new_common_type = py_object_type elif type1.is_numeric or type1.is_string: if operand1.check_for_coercion_error(type2, env): new_common_type = error_type else: new_common_type = py_object_type elif py_object_type.assignable_from(type1) and py_object_type.assignable_from(type2): new_common_type = py_object_type else: # one Python type and one non-Python type, not assignable self.invalid_types_error(operand1, op, operand2) new_common_type = error_type elif type1.assignable_from(type2): new_common_type = type1 elif type2.assignable_from(type1): new_common_type = type2 else: # C types that we couldn't handle up to here are an error self.invalid_types_error(operand1, op, operand2) new_common_type = error_type if new_common_type.is_string and (isinstance(operand1, BytesNode) or isinstance(operand2, BytesNode)): # special case when comparing char* to bytes literal: must # compare string values! new_common_type = bytes_type # recursively merge types if common_type is None or new_common_type.is_error: common_type = new_common_type else: # we could do a lot better by splitting the comparison # into a non-Python part and a Python part, but this is # safer for now common_type = PyrexTypes.spanning_type(common_type, new_common_type) if self.cascade: common_type = self.cascade.find_common_type(env, self.operator, operand2, common_type) return common_type def invalid_types_error(self, operand1, op, operand2): error(self.pos, "Invalid types for '%s' (%s, %s)" % (op, operand1.type, operand2.type)) def is_python_comparison(self): return (not self.is_ptr_contains() and not self.is_c_string_contains() and (self.has_python_operands() or (self.cascade and self.cascade.is_python_comparison()) or self.operator in ('in', 'not_in'))) def coerce_operands_to(self, dst_type, env): operand2 = self.operand2 if operand2.type != dst_type: self.operand2 = operand2.coerce_to(dst_type, env) if self.cascade: self.cascade.coerce_operands_to(dst_type, env) def is_python_result(self): return ((self.has_python_operands() and self.special_bool_cmp_function is None and self.operator not in ('is', 'is_not', 'in', 'not_in') and not self.is_c_string_contains() and not self.is_ptr_contains()) or (self.cascade and self.cascade.is_python_result())) def is_c_string_contains(self): return self.operator in ('in', 'not_in') and \ ((self.operand1.type.is_int and (self.operand2.type.is_string or self.operand2.type is bytes_type)) or (self.operand1.type.is_unicode_char and self.operand2.type is unicode_type)) def is_ptr_contains(self): if self.operator in ('in', 'not_in'): container_type = self.operand2.type return (container_type.is_ptr or container_type.is_array) \ and not container_type.is_string def find_special_bool_compare_function(self, env, operand1, result_is_bool=False): # note: currently operand1 must get coerced to a Python object if we succeed here! if self.operator in ('==', '!='): type1, type2 = operand1.type, self.operand2.type if result_is_bool or (type1.is_builtin_type and type2.is_builtin_type): if type1 is Builtin.unicode_type or type2 is Builtin.unicode_type: self.special_bool_cmp_utility_code = UtilityCode.load_cached("UnicodeEquals", "StringTools.c") self.special_bool_cmp_function = "__Pyx_PyUnicode_Equals" return True elif type1 is Builtin.bytes_type or type2 is Builtin.bytes_type: self.special_bool_cmp_utility_code = UtilityCode.load_cached("BytesEquals", "StringTools.c") self.special_bool_cmp_function = "__Pyx_PyBytes_Equals" return True elif type1 is Builtin.basestring_type or type2 is Builtin.basestring_type: self.special_bool_cmp_utility_code = UtilityCode.load_cached("UnicodeEquals", "StringTools.c") self.special_bool_cmp_function = "__Pyx_PyUnicode_Equals" return True elif type1 is Builtin.str_type or type2 is Builtin.str_type: self.special_bool_cmp_utility_code = UtilityCode.load_cached("StrEquals", "StringTools.c") self.special_bool_cmp_function = "__Pyx_PyString_Equals" return True elif result_is_bool: from .Optimize import optimise_numeric_binop result = optimise_numeric_binop( "Eq" if self.operator == "==" else "Ne", self, PyrexTypes.c_bint_type, operand1, self.operand2 ) if result: (self.special_bool_cmp_function, self.special_bool_cmp_utility_code, self.special_bool_extra_args, _) = result return True elif self.operator in ('in', 'not_in'): if self.operand2.type is Builtin.dict_type: self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable") self.special_bool_cmp_utility_code = UtilityCode.load_cached("PyDictContains", "ObjectHandling.c") self.special_bool_cmp_function = "__Pyx_PyDict_ContainsTF" return True elif self.operand2.type is Builtin.set_type: self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable") self.special_bool_cmp_utility_code = UtilityCode.load_cached("PySetContains", "ObjectHandling.c") self.special_bool_cmp_function = "__Pyx_PySet_ContainsTF" return True elif self.operand2.type is Builtin.unicode_type: self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable") self.special_bool_cmp_utility_code = UtilityCode.load_cached("PyUnicodeContains", "StringTools.c") self.special_bool_cmp_function = "__Pyx_PyUnicode_ContainsTF" return True else: if not self.operand2.type.is_pyobject: self.operand2 = self.operand2.coerce_to_pyobject(env) self.special_bool_cmp_utility_code = UtilityCode.load_cached("PySequenceContains", "ObjectHandling.c") self.special_bool_cmp_function = "__Pyx_PySequence_ContainsTF" return True return False def generate_operation_code(self, code, result_code, operand1, op, operand2): if self.type.is_pyobject: error_clause = code.error_goto_if_null got_ref = "__Pyx_XGOTREF(%s); " % result_code if self.special_bool_cmp_function: code.globalstate.use_utility_code( UtilityCode.load_cached("PyBoolOrNullFromLong", "ObjectHandling.c")) coerce_result = "__Pyx_PyBoolOrNull_FromLong" else: coerce_result = "__Pyx_PyBool_FromLong" else: error_clause = code.error_goto_if_neg got_ref = "" coerce_result = "" if self.special_bool_cmp_function: if operand1.type.is_pyobject: result1 = operand1.py_result() else: result1 = operand1.result() if operand2.type.is_pyobject: result2 = operand2.py_result() else: result2 = operand2.result() special_bool_extra_args_result = ", ".join([ extra_arg.result() for extra_arg in self.special_bool_extra_args ]) if self.special_bool_cmp_utility_code: code.globalstate.use_utility_code(self.special_bool_cmp_utility_code) code.putln( "%s = %s(%s(%s, %s, %s)); %s%s" % ( result_code, coerce_result, self.special_bool_cmp_function, result1, result2, special_bool_extra_args_result if self.special_bool_extra_args else richcmp_constants[op], got_ref, error_clause(result_code, self.pos))) elif operand1.type.is_pyobject and op not in ('is', 'is_not'): assert op not in ('in', 'not_in'), op assert self.type.is_pyobject or self.type is PyrexTypes.c_bint_type code.putln("%s = PyObject_RichCompare%s(%s, %s, %s); %s%s" % ( result_code, "" if self.type.is_pyobject else "Bool", operand1.py_result(), operand2.py_result(), richcmp_constants[op], got_ref, error_clause(result_code, self.pos))) elif operand1.type.is_complex: code.putln("%s = %s(%s%s(%s, %s));" % ( result_code, coerce_result, op == "!=" and "!" or "", operand1.type.unary_op('eq'), operand1.result(), operand2.result())) else: type1 = operand1.type type2 = operand2.type if (type1.is_extension_type or type2.is_extension_type) \ and not type1.same_as(type2): common_type = py_object_type elif type1.is_numeric: common_type = PyrexTypes.widest_numeric_type(type1, type2) else: common_type = type1 code1 = operand1.result_as(common_type) code2 = operand2.result_as(common_type) statement = "%s = %s(%s %s %s);" % ( result_code, coerce_result, code1, self.c_operator(op), code2) if self.is_cpp_comparison() and self.exception_check == '+': translate_cpp_exception( code, self.pos, statement, result_code if self.type.is_pyobject else None, self.exception_value, self.in_nogil_context) else: code.putln(statement) def c_operator(self, op): if op == 'is': return "==" elif op == 'is_not': return "!=" else: return op class PrimaryCmpNode(ExprNode, CmpNode): # Non-cascaded comparison or first comparison of # a cascaded sequence. # # operator string # operand1 ExprNode # operand2 ExprNode # cascade CascadedCmpNode # We don't use the subexprs mechanism, because # things here are too complicated for it to handle. # Instead, we override all the framework methods # which use it. child_attrs = ['operand1', 'operand2', 'coerced_operand2', 'cascade', 'special_bool_extra_args'] cascade = None coerced_operand2 = None is_memslice_nonecheck = False def infer_type(self, env): type1 = self.operand1.infer_type(env) type2 = self.operand2.infer_type(env) if is_pythran_expr(type1) or is_pythran_expr(type2): if is_pythran_supported_type(type1) and is_pythran_supported_type(type2): return PythranExpr(pythran_binop_type(self.operator, type1, type2)) # TODO: implement this for other types. return py_object_type def type_dependencies(self, env): return () def calculate_constant_result(self): assert not self.cascade self.calculate_cascaded_constant_result(self.operand1.constant_result) def compile_time_value(self, denv): operand1 = self.operand1.compile_time_value(denv) return self.cascaded_compile_time_value(operand1, denv) def unify_cascade_type(self): cdr = self.cascade while cdr: cdr.type = self.type cdr = cdr.cascade def analyse_types(self, env): self.operand1 = self.operand1.analyse_types(env) self.operand2 = self.operand2.analyse_types(env) if self.is_cpp_comparison(): self.analyse_cpp_comparison(env) if self.cascade: error(self.pos, "Cascading comparison not yet supported for cpp types.") return self type1 = self.operand1.type type2 = self.operand2.type if is_pythran_expr(type1) or is_pythran_expr(type2): if is_pythran_supported_type(type1) and is_pythran_supported_type(type2): self.type = PythranExpr(pythran_binop_type(self.operator, type1, type2)) self.is_pycmp = False return self if self.analyse_memoryviewslice_comparison(env): return self if self.cascade: self.cascade = self.cascade.analyse_types(env) if self.operator in ('in', 'not_in'): if self.is_c_string_contains(): self.is_pycmp = False common_type = None if self.cascade: error(self.pos, "Cascading comparison not yet supported for 'int_val in string'.") return self if self.operand2.type is unicode_type: env.use_utility_code(UtilityCode.load_cached("PyUCS4InUnicode", "StringTools.c")) else: if self.operand1.type is PyrexTypes.c_uchar_type: self.operand1 = self.operand1.coerce_to(PyrexTypes.c_char_type, env) if self.operand2.type is not bytes_type: self.operand2 = self.operand2.coerce_to(bytes_type, env) env.use_utility_code(UtilityCode.load_cached("BytesContains", "StringTools.c")) self.operand2 = self.operand2.as_none_safe_node( "argument of type 'NoneType' is not iterable") elif self.is_ptr_contains(): if self.cascade: error(self.pos, "Cascading comparison not supported for 'val in sliced pointer'.") self.type = PyrexTypes.c_bint_type # Will be transformed by IterationTransform return self elif self.find_special_bool_compare_function(env, self.operand1): if not self.operand1.type.is_pyobject: self.operand1 = self.operand1.coerce_to_pyobject(env) common_type = None # if coercion needed, the method call above has already done it self.is_pycmp = False # result is bint else: common_type = py_object_type self.is_pycmp = True elif self.find_special_bool_compare_function(env, self.operand1): if not self.operand1.type.is_pyobject: self.operand1 = self.operand1.coerce_to_pyobject(env) common_type = None # if coercion needed, the method call above has already done it self.is_pycmp = False # result is bint else: common_type = self.find_common_type(env, self.operator, self.operand1) self.is_pycmp = common_type.is_pyobject if common_type is not None and not common_type.is_error: if self.operand1.type != common_type: self.operand1 = self.operand1.coerce_to(common_type, env) self.coerce_operands_to(common_type, env) if self.cascade: self.operand2 = self.operand2.coerce_to_simple(env) self.cascade.coerce_cascaded_operands_to_temp(env) operand2 = self.cascade.optimise_comparison(self.operand2, env) if operand2 is not self.operand2: self.coerced_operand2 = operand2 if self.is_python_result(): self.type = PyrexTypes.py_object_type else: self.type = PyrexTypes.c_bint_type self.unify_cascade_type() if self.is_pycmp or self.cascade or self.special_bool_cmp_function: # 1) owned reference, 2) reused value, 3) potential function error return value self.is_temp = 1 return self def analyse_cpp_comparison(self, env): type1 = self.operand1.type type2 = self.operand2.type self.is_pycmp = False entry = env.lookup_operator(self.operator, [self.operand1, self.operand2]) if entry is None: error(self.pos, "Invalid types for '%s' (%s, %s)" % (self.operator, type1, type2)) self.type = PyrexTypes.error_type self.result_code = "" return func_type = entry.type if func_type.is_ptr: func_type = func_type.base_type self.exception_check = func_type.exception_check self.exception_value = func_type.exception_value if self.exception_check == '+': self.is_temp = True if needs_cpp_exception_conversion(self): env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp")) if len(func_type.args) == 1: self.operand2 = self.operand2.coerce_to(func_type.args[0].type, env) else: self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env) self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env) self.type = func_type.return_type def analyse_memoryviewslice_comparison(self, env): have_none = self.operand1.is_none or self.operand2.is_none have_slice = (self.operand1.type.is_memoryviewslice or self.operand2.type.is_memoryviewslice) ops = ('==', '!=', 'is', 'is_not') if have_slice and have_none and self.operator in ops: self.is_pycmp = False self.type = PyrexTypes.c_bint_type self.is_memslice_nonecheck = True return True return False def coerce_to_boolean(self, env): if self.is_pycmp: # coercing to bool => may allow for more efficient comparison code if self.find_special_bool_compare_function( env, self.operand1, result_is_bool=True): self.is_pycmp = False self.type = PyrexTypes.c_bint_type self.is_temp = 1 if self.cascade: operand2 = self.cascade.optimise_comparison( self.operand2, env, result_is_bool=True) if operand2 is not self.operand2: self.coerced_operand2 = operand2 self.unify_cascade_type() return self # TODO: check if we can optimise parts of the cascade here return ExprNode.coerce_to_boolean(self, env) def has_python_operands(self): return (self.operand1.type.is_pyobject or self.operand2.type.is_pyobject) def check_const(self): if self.cascade: self.not_const() return False else: return self.operand1.check_const() and self.operand2.check_const() def calculate_result_code(self): operand1, operand2 = self.operand1, self.operand2 if operand1.type.is_complex: if self.operator == "!=": negation = "!" else: negation = "" return "(%s%s(%s, %s))" % ( negation, operand1.type.binary_op('=='), operand1.result(), operand2.result()) elif self.is_c_string_contains(): if operand2.type is unicode_type: method = "__Pyx_UnicodeContainsUCS4" else: method = "__Pyx_BytesContains" if self.operator == "not_in": negation = "!" else: negation = "" return "(%s%s(%s, %s))" % ( negation, method, operand2.result(), operand1.result()) else: if is_pythran_expr(self.type): result1, result2 = operand1.pythran_result(), operand2.pythran_result() else: result1, result2 = operand1.result(), operand2.result() if self.is_memslice_nonecheck: if operand1.type.is_memoryviewslice: result1 = "((PyObject *) %s.memview)" % result1 else: result2 = "((PyObject *) %s.memview)" % result2 return "(%s %s %s)" % ( result1, self.c_operator(self.operator), result2) def generate_evaluation_code(self, code): self.operand1.generate_evaluation_code(code) self.operand2.generate_evaluation_code(code) for extra_arg in self.special_bool_extra_args: extra_arg.generate_evaluation_code(code) if self.is_temp: self.allocate_temp_result(code) self.generate_operation_code(code, self.result(), self.operand1, self.operator, self.operand2) if self.cascade: self.cascade.generate_evaluation_code( code, self.result(), self.coerced_operand2 or self.operand2, needs_evaluation=self.coerced_operand2 is not None) self.operand1.generate_disposal_code(code) self.operand1.free_temps(code) self.operand2.generate_disposal_code(code) self.operand2.free_temps(code) def generate_subexpr_disposal_code(self, code): # If this is called, it is a non-cascaded cmp, # so only need to dispose of the two main operands. self.operand1.generate_disposal_code(code) self.operand2.generate_disposal_code(code) def free_subexpr_temps(self, code): # If this is called, it is a non-cascaded cmp, # so only need to dispose of the two main operands. self.operand1.free_temps(code) self.operand2.free_temps(code) def annotate(self, code): self.operand1.annotate(code) self.operand2.annotate(code) if self.cascade: self.cascade.annotate(code) class CascadedCmpNode(Node, CmpNode): # A CascadedCmpNode is not a complete expression node. It # hangs off the side of another comparison node, shares # its left operand with that node, and shares its result # with the PrimaryCmpNode at the head of the chain. # # operator string # operand2 ExprNode # cascade CascadedCmpNode child_attrs = ['operand2', 'coerced_operand2', 'cascade', 'special_bool_extra_args'] cascade = None coerced_operand2 = None constant_result = constant_value_not_set # FIXME: where to calculate this? def infer_type(self, env): # TODO: Actually implement this (after merging with -unstable). return py_object_type def type_dependencies(self, env): return () def has_constant_result(self): return self.constant_result is not constant_value_not_set and \ self.constant_result is not not_a_constant def analyse_types(self, env): self.operand2 = self.operand2.analyse_types(env) if self.cascade: self.cascade = self.cascade.analyse_types(env) return self def has_python_operands(self): return self.operand2.type.is_pyobject def is_cpp_comparison(self): # cascaded comparisons aren't currently implemented for c++ classes. return False def optimise_comparison(self, operand1, env, result_is_bool=False): if self.find_special_bool_compare_function(env, operand1, result_is_bool): self.is_pycmp = False self.type = PyrexTypes.c_bint_type if not operand1.type.is_pyobject: operand1 = operand1.coerce_to_pyobject(env) if self.cascade: operand2 = self.cascade.optimise_comparison(self.operand2, env, result_is_bool) if operand2 is not self.operand2: self.coerced_operand2 = operand2 return operand1 def coerce_operands_to_pyobjects(self, env): self.operand2 = self.operand2.coerce_to_pyobject(env) if self.operand2.type is dict_type and self.operator in ('in', 'not_in'): self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable") if self.cascade: self.cascade.coerce_operands_to_pyobjects(env) def coerce_cascaded_operands_to_temp(self, env): if self.cascade: #self.operand2 = self.operand2.coerce_to_temp(env) #CTT self.operand2 = self.operand2.coerce_to_simple(env) self.cascade.coerce_cascaded_operands_to_temp(env) def generate_evaluation_code(self, code, result, operand1, needs_evaluation=False): if self.type.is_pyobject: code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result) code.put_decref(result, self.type) else: code.putln("if (%s) {" % result) if needs_evaluation: operand1.generate_evaluation_code(code) self.operand2.generate_evaluation_code(code) for extra_arg in self.special_bool_extra_args: extra_arg.generate_evaluation_code(code) self.generate_operation_code(code, result, operand1, self.operator, self.operand2) if self.cascade: self.cascade.generate_evaluation_code( code, result, self.coerced_operand2 or self.operand2, needs_evaluation=self.coerced_operand2 is not None) if needs_evaluation: operand1.generate_disposal_code(code) operand1.free_temps(code) # Cascaded cmp result is always temp self.operand2.generate_disposal_code(code) self.operand2.free_temps(code) code.putln("}") def annotate(self, code): self.operand2.annotate(code) if self.cascade: self.cascade.annotate(code) binop_node_classes = { "or": BoolBinopNode, "and": BoolBinopNode, "|": IntBinopNode, "^": IntBinopNode, "&": IntBinopNode, "<<": IntBinopNode, ">>": IntBinopNode, "+": AddNode, "-": SubNode, "*": MulNode, "@": MatMultNode, "/": DivNode, "//": DivNode, "%": ModNode, "**": PowNode, } def binop_node(pos, operator, operand1, operand2, inplace=False, **kwargs): # Construct binop node of appropriate class for # given operator. return binop_node_classes[operator]( pos, operator=operator, operand1=operand1, operand2=operand2, inplace=inplace, **kwargs) #------------------------------------------------------------------- # # Coercion nodes # # Coercion nodes are special in that they are created during # the analyse_types phase of parse tree processing. # Their __init__ methods consequently incorporate some aspects # of that phase. # #------------------------------------------------------------------- class CoercionNode(ExprNode): # Abstract base class for coercion nodes. # # arg ExprNode node being coerced subexprs = ['arg'] constant_result = not_a_constant def __init__(self, arg): super(CoercionNode, self).__init__(arg.pos) self.arg = arg if debug_coercion: print("%s Coercing %s" % (self, self.arg)) def calculate_constant_result(self): # constant folding can break type coercion, so this is disabled pass def annotate(self, code): self.arg.annotate(code) if self.arg.type != self.type: file, line, col = self.pos code.annotate((file, line, col-1), AnnotationItem( style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type))) def analyse_types(self, env): return self class CoerceToMemViewSliceNode(CoercionNode): """ Coerce an object to a memoryview slice. This holds a new reference in a managed temp. """ def __init__(self, arg, dst_type, env): assert dst_type.is_memoryviewslice assert not arg.type.is_memoryviewslice CoercionNode.__init__(self, arg) self.type = dst_type self.is_temp = 1 self.use_managed_ref = True self.arg = arg self.type.create_from_py_utility_code(env) def generate_result_code(self, code): code.putln(self.type.from_py_call_code( self.arg.py_result(), self.result(), self.pos, code )) class CastNode(CoercionNode): # Wrap a node in a C type cast. def __init__(self, arg, new_type): CoercionNode.__init__(self, arg) self.type = new_type def may_be_none(self): return self.arg.may_be_none() def calculate_result_code(self): return self.arg.result_as(self.type) def generate_result_code(self, code): self.arg.generate_result_code(code) class PyTypeTestNode(CoercionNode): # This node is used to check that a generic Python # object is an instance of a particular extension type. # This node borrows the result of its argument node. exact_builtin_type = True def __init__(self, arg, dst_type, env, notnone=False): # The arg is known to be a Python object, and # the dst_type is known to be an extension type. assert dst_type.is_extension_type or dst_type.is_builtin_type, \ "PyTypeTest for %s against non extension type %s" % (arg.type, dst_type) CoercionNode.__init__(self, arg) self.type = dst_type self.result_ctype = arg.ctype() self.notnone = notnone nogil_check = Node.gil_error gil_message = "Python type test" def analyse_types(self, env): return self def may_be_none(self): if self.notnone: return False return self.arg.may_be_none() def is_simple(self): return self.arg.is_simple() def result_in_temp(self): return self.arg.result_in_temp() def is_ephemeral(self): return self.arg.is_ephemeral() def nonlocally_immutable(self): return self.arg.nonlocally_immutable() def reanalyse(self): if self.type != self.arg.type or not self.arg.is_temp: return self if not self.type.typeobj_is_available(): return self if self.arg.may_be_none() and self.notnone: return self.arg.as_none_safe_node("Cannot convert NoneType to %.200s" % self.type.name) return self.arg def calculate_constant_result(self): # FIXME pass def calculate_result_code(self): return self.arg.result() def generate_result_code(self, code): if self.type.typeobj_is_available(): if self.type.is_builtin_type: type_test = self.type.type_test_code( self.arg.py_result(), self.notnone, exact=self.exact_builtin_type) code.globalstate.use_utility_code(UtilityCode.load_cached( "RaiseUnexpectedTypeError", "ObjectHandling.c")) else: type_test = self.type.type_test_code( self.arg.py_result(), self.notnone) code.globalstate.use_utility_code( UtilityCode.load_cached("ExtTypeTest", "ObjectHandling.c")) code.putln("if (!(%s)) %s" % ( type_test, code.error_goto(self.pos))) else: error(self.pos, "Cannot test type of extern C class " "without type object name specification") def generate_post_assignment_code(self, code): self.arg.generate_post_assignment_code(code) def allocate_temp_result(self, code): pass def release_temp_result(self, code): pass def free_temps(self, code): self.arg.free_temps(code) def free_subexpr_temps(self, code): self.arg.free_subexpr_temps(code) class NoneCheckNode(CoercionNode): # This node is used to check that a Python object is not None and # raises an appropriate exception (as specified by the creating # transform). is_nonecheck = True def __init__(self, arg, exception_type_cname, exception_message, exception_format_args=()): CoercionNode.__init__(self, arg) self.type = arg.type self.result_ctype = arg.ctype() self.exception_type_cname = exception_type_cname self.exception_message = exception_message self.exception_format_args = tuple(exception_format_args or ()) nogil_check = None # this node only guards an operation that would fail already def analyse_types(self, env): return self def may_be_none(self): return False def is_simple(self): return self.arg.is_simple() def result_in_temp(self): return self.arg.result_in_temp() def nonlocally_immutable(self): return self.arg.nonlocally_immutable() def calculate_result_code(self): return self.arg.result() def condition(self): if self.type.is_pyobject: return self.arg.py_result() elif self.type.is_memoryviewslice: return "((PyObject *) %s.memview)" % self.arg.result() else: raise Exception("unsupported type") @classmethod def generate(cls, arg, code, exception_message, exception_type_cname="PyExc_TypeError", exception_format_args=(), in_nogil_context=False): node = cls(arg, exception_type_cname, exception_message, exception_format_args) node.in_nogil_context = in_nogil_context node.put_nonecheck(code) @classmethod def generate_if_needed(cls, arg, code, exception_message, exception_type_cname="PyExc_TypeError", exception_format_args=(), in_nogil_context=False): if arg.may_be_none(): cls.generate(arg, code, exception_message, exception_type_cname, exception_format_args, in_nogil_context) def put_nonecheck(self, code): code.putln( "if (unlikely(%s == Py_None)) {" % self.condition()) if self.in_nogil_context: code.put_ensure_gil() escape = StringEncoding.escape_byte_string if self.exception_format_args: code.putln('PyErr_Format(%s, "%s", %s);' % ( self.exception_type_cname, StringEncoding.escape_byte_string( self.exception_message.encode('UTF-8')), ', '.join([ '"%s"' % escape(str(arg).encode('UTF-8')) for arg in self.exception_format_args ]))) else: code.putln('PyErr_SetString(%s, "%s");' % ( self.exception_type_cname, escape(self.exception_message.encode('UTF-8')))) if self.in_nogil_context: code.put_release_ensured_gil() code.putln(code.error_goto(self.pos)) code.putln("}") def generate_result_code(self, code): self.put_nonecheck(code) def generate_post_assignment_code(self, code): self.arg.generate_post_assignment_code(code) def free_temps(self, code): self.arg.free_temps(code) class CoerceToPyTypeNode(CoercionNode): # This node is used to convert a C data type # to a Python object. type = py_object_type target_type = py_object_type is_temp = 1 def __init__(self, arg, env, type=py_object_type): if not arg.type.create_to_py_utility_code(env): error(arg.pos, "Cannot convert '%s' to Python object" % arg.type) elif arg.type.is_complex: # special case: complex coercion is so complex that it # uses a macro ("__pyx_PyComplex_FromComplex()"), for # which the argument must be simple arg = arg.coerce_to_simple(env) CoercionNode.__init__(self, arg) if type is py_object_type: # be specific about some known types if arg.type.is_string or arg.type.is_cpp_string: self.type = default_str_type(env) elif arg.type.is_pyunicode_ptr or arg.type.is_unicode_char: self.type = unicode_type elif arg.type.is_complex: self.type = Builtin.complex_type self.target_type = self.type elif arg.type.is_string or arg.type.is_cpp_string: if (type not in (bytes_type, bytearray_type) and not env.directives['c_string_encoding']): error(arg.pos, "default encoding required for conversion from '%s' to '%s'" % (arg.type, type)) self.type = self.target_type = type else: # FIXME: check that the target type and the resulting type are compatible self.target_type = type gil_message = "Converting to Python object" def may_be_none(self): # FIXME: is this always safe? return False def coerce_to_boolean(self, env): arg_type = self.arg.type if (arg_type == PyrexTypes.c_bint_type or (arg_type.is_pyobject and arg_type.name == 'bool')): return self.arg.coerce_to_temp(env) else: return CoerceToBooleanNode(self, env) def coerce_to_integer(self, env): # If not already some C integer type, coerce to longint. if self.arg.type.is_int: return self.arg else: return self.arg.coerce_to(PyrexTypes.c_long_type, env) def analyse_types(self, env): # The arg is always already analysed return self def generate_result_code(self, code): code.putln('%s; %s' % ( self.arg.type.to_py_call_code( self.arg.result(), self.result(), self.target_type), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) class CoerceIntToBytesNode(CoerceToPyTypeNode): # This node is used to convert a C int type to a Python bytes # object. is_temp = 1 def __init__(self, arg, env): arg = arg.coerce_to_simple(env) CoercionNode.__init__(self, arg) self.type = Builtin.bytes_type def generate_result_code(self, code): arg = self.arg arg_result = arg.result() if arg.type not in (PyrexTypes.c_char_type, PyrexTypes.c_uchar_type, PyrexTypes.c_schar_type): if arg.type.signed: code.putln("if ((%s < 0) || (%s > 255)) {" % ( arg_result, arg_result)) else: code.putln("if (%s > 255) {" % arg_result) code.putln('PyErr_SetString(PyExc_OverflowError, ' '"value too large to pack into a byte"); %s' % ( code.error_goto(self.pos))) code.putln('}') temp = None if arg.type is not PyrexTypes.c_char_type: temp = code.funcstate.allocate_temp(PyrexTypes.c_char_type, manage_ref=False) code.putln("%s = (char)%s;" % (temp, arg_result)) arg_result = temp code.putln('%s = PyBytes_FromStringAndSize(&%s, 1); %s' % ( self.result(), arg_result, code.error_goto_if_null(self.result(), self.pos))) if temp is not None: code.funcstate.release_temp(temp) self.generate_gotref(code) class CoerceFromPyTypeNode(CoercionNode): # This node is used to convert a Python object # to a C data type. # Allow 'None' to map to a difference C value independent of the coercion, e.g. to 'NULL' or '0'. special_none_cvalue = None def __init__(self, result_type, arg, env): CoercionNode.__init__(self, arg) self.type = result_type self.is_temp = 1 if not result_type.create_from_py_utility_code(env): error(arg.pos, "Cannot convert Python object to '%s'" % result_type) if self.type.is_string or self.type.is_pyunicode_ptr: if self.arg.is_name and self.arg.entry and self.arg.entry.is_pyglobal: warning(arg.pos, "Obtaining '%s' from externally modifiable global Python value" % result_type, level=1) if self.type.is_pyunicode_ptr: warning(arg.pos, "Py_UNICODE* has been removed in Python 3.12. This conversion to a " "Py_UNICODE* will no longer compile in the latest Python versions. " "Use Python C API functions like PyUnicode_AsWideCharString if you " "need to obtain a wchar_t* on Windows (and free the string manually after use).", level=1) def analyse_types(self, env): # The arg is always already analysed return self def is_ephemeral(self): return (self.type.is_ptr and not self.type.is_array) and self.arg.is_ephemeral() def generate_result_code(self, code): from_py_function = None # for certain source types, we can do better than the generic coercion if self.type.is_string and self.arg.type is bytes_type: if self.type.from_py_function.startswith('__Pyx_PyObject_As'): from_py_function = '__Pyx_PyBytes' + self.type.from_py_function[len('__Pyx_PyObject'):] NoneCheckNode.generate_if_needed(self.arg, code, "expected bytes, NoneType found") code.putln(self.type.from_py_call_code( self.arg.py_result(), self.result(), self.pos, code, from_py_function=from_py_function, special_none_cvalue=self.special_none_cvalue, )) if self.type.is_pyobject: self.generate_gotref(code) def nogil_check(self, env): error(self.pos, "Coercion from Python not allowed without the GIL") class CoerceToBooleanNode(CoercionNode): # This node is used when a result needs to be used # in a boolean context. type = PyrexTypes.c_bint_type _special_builtins = { Builtin.list_type: 'PyList_GET_SIZE', Builtin.tuple_type: 'PyTuple_GET_SIZE', Builtin.set_type: 'PySet_GET_SIZE', Builtin.frozenset_type: 'PySet_GET_SIZE', Builtin.bytes_type: 'PyBytes_GET_SIZE', Builtin.bytearray_type: 'PyByteArray_GET_SIZE', Builtin.unicode_type: '__Pyx_PyUnicode_IS_TRUE', } def __init__(self, arg, env): CoercionNode.__init__(self, arg) if arg.type.is_pyobject: self.is_temp = 1 def nogil_check(self, env): if self.arg.type.is_pyobject and self._special_builtins.get(self.arg.type) is None: self.gil_error() gil_message = "Truth-testing Python object" def check_const(self): if self.is_temp: self.not_const() return False return self.arg.check_const() def calculate_result_code(self): return "(%s != 0)" % self.arg.result() def generate_result_code(self, code): if not self.is_temp: return test_func = self._special_builtins.get(self.arg.type) if test_func is not None: checks = ["(%s != Py_None)" % self.arg.py_result()] if self.arg.may_be_none() else [] checks.append("(%s(%s) != 0)" % (test_func, self.arg.py_result())) code.putln("%s = %s;" % (self.result(), '&&'.join(checks))) else: code.putln( "%s = __Pyx_PyObject_IsTrue(%s); %s" % ( self.result(), self.arg.py_result(), code.error_goto_if_neg(self.result(), self.pos))) def analyse_types(self, env): return self class CoerceToComplexNode(CoercionNode): def __init__(self, arg, dst_type, env): if arg.type.is_complex: arg = arg.coerce_to_simple(env) self.type = dst_type CoercionNode.__init__(self, arg) dst_type.create_declaration_utility_code(env) def calculate_result_code(self): if self.arg.type.is_complex: real_part = self.arg.type.real_code(self.arg.result()) imag_part = self.arg.type.imag_code(self.arg.result()) else: real_part = self.arg.result() imag_part = "0" return "%s(%s, %s)" % ( self.type.from_parts, real_part, imag_part) def generate_result_code(self, code): pass def analyse_types(self, env): return self def coerce_from_soft_complex(arg, dst_type, env): from .UtilNodes import HasGilNode cfunc_type = PyrexTypes.CFuncType( PyrexTypes.c_double_type, [ PyrexTypes.CFuncTypeArg("value", PyrexTypes.soft_complex_type, None), PyrexTypes.CFuncTypeArg("have_gil", PyrexTypes.c_bint_type, None) ], exception_value="-1", exception_check=True, nogil=True # We can acquire the GIL internally on failure ) call = PythonCapiCallNode( arg.pos, "__Pyx_SoftComplexToDouble", cfunc_type, utility_code = UtilityCode.load_cached("SoftComplexToDouble", "Complex.c"), args = [arg, HasGilNode(arg.pos)], ) call = call.analyse_types(env) if call.type != dst_type: call = call.coerce_to(dst_type, env) return call class CoerceToTempNode(CoercionNode): # This node is used to force the result of another node # to be stored in a temporary. It is only used if the # argument node's result is not already in a temporary. def __init__(self, arg, env): CoercionNode.__init__(self, arg) self.type = self.arg.type.as_argument_type() self.constant_result = self.arg.constant_result self.is_temp = 1 if self.type.is_pyobject: self.result_ctype = py_object_type gil_message = "Creating temporary Python reference" def analyse_types(self, env): # The arg is always already analysed return self def may_be_none(self): return self.arg.may_be_none() def coerce_to_boolean(self, env): self.arg = self.arg.coerce_to_boolean(env) if self.arg.is_simple(): return self.arg self.type = self.arg.type self.result_ctype = self.type return self def generate_result_code(self, code): #self.arg.generate_evaluation_code(code) # Already done # by generic generate_subexpr_evaluation_code! code.putln("%s = %s;" % ( self.result(), self.arg.result_as(self.ctype()))) if self.use_managed_ref: if not self.type.is_memoryviewslice: code.put_incref(self.result(), self.ctype()) else: code.put_incref_memoryviewslice(self.result(), self.type, have_gil=not self.in_nogil_context) class ProxyNode(CoercionNode): """ A node that should not be replaced by transforms or other means, and hence can be useful to wrap the argument to a clone node MyNode -> ProxyNode -> ArgNode CloneNode -^ """ nogil_check = None def __init__(self, arg): super(ProxyNode, self).__init__(arg) self.constant_result = arg.constant_result self.update_type_and_entry() def analyse_types(self, env): self.arg = self.arg.analyse_expressions(env) self.update_type_and_entry() return self def infer_type(self, env): return self.arg.infer_type(env) def update_type_and_entry(self): type = getattr(self.arg, 'type', None) if type: self.type = type self.result_ctype = self.arg.result_ctype arg_entry = getattr(self.arg, 'entry', None) if arg_entry: self.entry = arg_entry def generate_result_code(self, code): self.arg.generate_result_code(code) def result(self): return self.arg.result() def is_simple(self): return self.arg.is_simple() def may_be_none(self): return self.arg.may_be_none() def generate_evaluation_code(self, code): self.arg.generate_evaluation_code(code) def generate_disposal_code(self, code): self.arg.generate_disposal_code(code) def free_temps(self, code): self.arg.free_temps(code) class CloneNode(CoercionNode): # This node is employed when the result of another node needs # to be used multiple times. The argument node's result must # be in a temporary. This node "borrows" the result from the # argument node, and does not generate any evaluation or # disposal code for it. The original owner of the argument # node is responsible for doing those things. subexprs = [] # Arg is not considered a subexpr nogil_check = None def __init__(self, arg): CoercionNode.__init__(self, arg) self.constant_result = arg.constant_result type = getattr(arg, 'type', None) if type: self.type = type self.result_ctype = arg.result_ctype arg_entry = getattr(arg, 'entry', None) if arg_entry: self.entry = arg_entry def result(self): return self.arg.result() def may_be_none(self): return self.arg.may_be_none() def type_dependencies(self, env): return self.arg.type_dependencies(env) def infer_type(self, env): return self.arg.infer_type(env) def analyse_types(self, env): self.type = self.arg.type self.result_ctype = self.arg.result_ctype self.is_temp = 1 arg_entry = getattr(self.arg, 'entry', None) if arg_entry: self.entry = arg_entry return self def coerce_to(self, dest_type, env): if self.arg.is_literal: return self.arg.coerce_to(dest_type, env) return super(CloneNode, self).coerce_to(dest_type, env) def is_simple(self): return True # result is always in a temp (or a name) def generate_evaluation_code(self, code): pass def generate_result_code(self, code): pass def generate_disposal_code(self, code): pass def generate_post_assignment_code(self, code): # if we're assigning from a CloneNode then it's "giveref"ed away, so it does # need a matching incref (ideally this should happen before the assignment though) if self.is_temp: # should usually be true code.put_incref(self.result(), self.ctype()) def free_temps(self, code): pass class CppOptionalTempCoercion(CoercionNode): """ Used only in CoerceCppTemps - handles cases the temp is actually a OptionalCppClassType (and thus needs dereferencing when on the rhs) """ is_temp = False @property def type(self): return self.arg.type def calculate_result_code(self): return "(*%s)" % self.arg.result() def generate_result_code(self, code): pass def _make_move_result_rhs(self, result, optional=False): # this wouldn't normally get moved (because it isn't a temp), but force it to be because it # is a thin wrapper around a temp return super(CppOptionalTempCoercion, self)._make_move_result_rhs(result, optional=False) class CMethodSelfCloneNode(CloneNode): # Special CloneNode for the self argument of builtin C methods # that accepts subtypes of the builtin type. This is safe only # for 'final' subtypes, as subtypes of the declared type may # override the C method. def coerce_to(self, dst_type, env): if dst_type.is_builtin_type and self.type.subtype_of(dst_type): return self return CloneNode.coerce_to(self, dst_type, env) class ModuleRefNode(ExprNode): # Simple returns the module object type = py_object_type is_temp = False subexprs = [] def analyse_types(self, env): return self def may_be_none(self): return False def calculate_result_code(self): return Naming.module_cname def generate_result_code(self, code): pass class DocstringRefNode(ExprNode): # Extracts the docstring of the body element subexprs = ['body'] type = py_object_type is_temp = True def __init__(self, pos, body): ExprNode.__init__(self, pos) assert body.type.is_pyobject self.body = body def analyse_types(self, env): return self def generate_result_code(self, code): code.putln('%s = __Pyx_GetAttr(%s, %s); %s' % ( self.result(), self.body.result(), code.intern_identifier(StringEncoding.EncodedString("__doc__")), code.error_goto_if_null(self.result(), self.pos))) self.generate_gotref(code) class AnnotationNode(ExprNode): # Deals with the two possible uses of an annotation. # 1. The post PEP-563 use where an annotation is stored # as a string # 2. The Cython use where the annotation can indicate an # object type # # Doesn't handle the pre PEP-563 version where the # annotation is evaluated into a Python Object. subexprs = [] # 'untyped' is set for fused specializations: # Once a fused function has been created we don't want # annotations to override an already set type. untyped = False def __init__(self, pos, expr, string=None): """string is expected to already be a StringNode or None""" ExprNode.__init__(self, pos) if string is None: # import doesn't work at top of file? from .AutoDocTransforms import AnnotationWriter string = StringEncoding.EncodedString( AnnotationWriter(description="annotation").write(expr)) string = StringNode(pos, unicode_value=string, value=string.as_utf8_string()) self.string = string self.expr = expr def analyse_types(self, env): return self # nothing needs doing def analyse_as_type(self, env): # for compatibility when used as a return_type_node, have this interface too return self.analyse_type_annotation(env)[1] def _warn_on_unknown_annotation(self, env, annotation): """Method checks for cases when user should be warned that annotation contains unknown types.""" if isinstance(annotation, SliceIndexNode): annotation = annotation.base if annotation.is_name: # Validate annotation in form `var: type` if not env.lookup(annotation.name): warning(annotation.pos, "Unknown type declaration '%s' in annotation, ignoring" % self.string.value, level=1) elif annotation.is_attribute and annotation.obj.is_name: # Validate annotation in form `var: module.type` if not env.lookup(annotation.obj.name): # `module` is undeclared warning(annotation.pos, "Unknown type declaration '%s' in annotation, ignoring" % self.string.value, level=1) elif annotation.obj.is_cython_module: # `module` is cython module_scope = annotation.obj.analyse_as_module(env) if module_scope and not module_scope.lookup_type(annotation.attribute): error(annotation.pos, "Unknown type declaration '%s' in annotation" % self.string.value) else: module_scope = annotation.obj.analyse_as_module(env) if module_scope and module_scope.pxd_file_loaded: warning(annotation.pos, "Unknown type declaration '%s' in annotation, ignoring" % self.string.value, level=1) else: warning(annotation.pos, "Unknown type declaration in annotation, ignoring") def analyse_type_annotation(self, env, assigned_value=None): if self.untyped: # Already applied as a fused type, not re-evaluating it here. return [], None annotation = self.expr explicit_pytype = explicit_ctype = False if annotation.is_dict_literal: warning(annotation.pos, "Dicts should no longer be used as type annotations. Use 'cython.int' etc. directly.", level=1) for name, value in annotation.key_value_pairs: if not name.is_string_literal: continue if name.value in ('type', b'type'): explicit_pytype = True if not explicit_ctype: annotation = value elif name.value in ('ctype', b'ctype'): explicit_ctype = True annotation = value if explicit_pytype and explicit_ctype: warning(annotation.pos, "Duplicate type declarations found in signature annotation", level=1) elif isinstance(annotation, TupleNode): warning(annotation.pos, "Tuples cannot be declared as simple tuples of types. Use 'tuple[type1, type2, ...]'.", level=1) return [], None with env.new_c_type_context(in_c_type_context=explicit_ctype): arg_type = annotation.analyse_as_type(env) if arg_type is None: self._warn_on_unknown_annotation(env, annotation) return [], arg_type if annotation.is_string_literal: warning(annotation.pos, "Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.", level=1) if explicit_pytype and not explicit_ctype and not (arg_type.is_pyobject or arg_type.equivalent_type): warning(annotation.pos, "Python type declaration in signature annotation does not refer to a Python type") if arg_type.is_complex: # creating utility code needs to be special-cased for complex types arg_type.create_declaration_utility_code(env) # Check for declaration modifiers, e.g. "typing.Optional[...]" or "dataclasses.InitVar[...]" modifiers = annotation.analyse_pytyping_modifiers(env) if annotation.is_subscript else [] return modifiers, arg_type class AssignmentExpressionNode(ExprNode): """ Also known as a named expression or the walrus operator Arguments lhs - NameNode - not stored directly as an attribute of the node rhs - ExprNode Attributes rhs - ExprNode assignment - SingleAssignmentNode """ # subexprs and child_attrs are intentionally different here, because the assignment is not an expression subexprs = ["rhs"] child_attrs = ["rhs", "assignment"] # This order is important for control-flow (i.e. xdecref) to be right is_temp = False assignment = None clone_node = None def __init__(self, pos, lhs, rhs, **kwds): super(AssignmentExpressionNode, self).__init__(pos, **kwds) self.rhs = ProxyNode(rhs) assign_expr_rhs = CloneNode(self.rhs) self.assignment = SingleAssignmentNode( pos, lhs=lhs, rhs=assign_expr_rhs, is_assignment_expression=True) @property def type(self): return self.rhs.type @property def target_name(self): return self.assignment.lhs.name def infer_type(self, env): return self.rhs.infer_type(env) def analyse_declarations(self, env): self.assignment.analyse_declarations(env) def analyse_types(self, env): # we're trying to generate code that looks roughly like: # __pyx_t_1 = rhs # lhs = __pyx_t_1 # __pyx_t_1 # (plus any reference counting that's needed) self.rhs = self.rhs.analyse_types(env) if not self.rhs.arg.is_temp: if not self.rhs.arg.is_literal: # for anything but the simplest cases (where it can be used directly) # we convert rhs to a temp, because CloneNode requires arg to be a temp self.rhs.arg = self.rhs.arg.coerce_to_temp(env) else: # For literals we can optimize by just using the literal twice # # We aren't including `self.rhs.is_name` in this optimization # because that goes wrong for assignment expressions run in # parallel. e.g. `(a := b) + (b := a + c)`) # This is a special case of https://github.com/cython/cython/issues/4146 # TODO - once that's fixed general revisit this code and possibly # use coerce_to_simple self.assignment.rhs = copy.copy(self.rhs) # TODO - there's a missed optimization in the code generation stage # for self.rhs.arg.is_temp: an incref/decref pair can be removed # (but needs a general mechanism to do that) self.assignment = self.assignment.analyse_types(env) return self def coerce_to(self, dst_type, env): if dst_type == self.assignment.rhs.type: # in this quite common case (for example, when both lhs, and self are being coerced to Python) # we can optimize the coercion out by sharing it between # this and the assignment old_rhs_arg = self.rhs.arg if isinstance(old_rhs_arg, CoerceToTempNode): old_rhs_arg = old_rhs_arg.arg rhs_arg = old_rhs_arg.coerce_to(dst_type, env) if rhs_arg is not old_rhs_arg: self.rhs.arg = rhs_arg self.rhs.update_type_and_entry() # clean up the old coercion node that the assignment has likely generated if (isinstance(self.assignment.rhs, CoercionNode) and not isinstance(self.assignment.rhs, CloneNode)): self.assignment.rhs = self.assignment.rhs.arg self.assignment.rhs.type = self.assignment.rhs.arg.type return self return super(AssignmentExpressionNode, self).coerce_to(dst_type, env) def calculate_result_code(self): return self.rhs.result() def generate_result_code(self, code): # we have to do this manually because it isn't a subexpression self.assignment.generate_execution_code(code) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3167222 Cython-3.0.8/Cython/Compiler/FlowControl.pxd0000644000175100001770000000564300000000000021607 0ustar00runnerdocker00000000000000# cython: language_level=3 cimport cython from .Visitor cimport CythonTransform, TreeVisitor cdef class ControlBlock: cdef public set children cdef public set parents cdef public set positions cdef public list stats cdef public dict gen cdef public set bounded # Big integer bitsets cdef public object i_input cdef public object i_output cdef public object i_gen cdef public object i_kill cdef public object i_state cpdef bint empty(self) cpdef detach(self) cpdef add_child(self, block) cdef class ExitBlock(ControlBlock): cpdef bint empty(self) cdef class NameAssignment: cdef public bint is_arg cdef public bint is_deletion cdef public object lhs cdef public object rhs cdef public object entry cdef public object pos cdef public set refs cdef public object bit cdef public object inferred_type cdef public object rhs_scope cdef class AssignmentList: cdef public object bit cdef public object mask cdef public list stats cdef class AssignmentCollector(TreeVisitor): cdef list assignments @cython.final cdef class ControlFlow: cdef public set blocks cdef public set entries cdef public list loops cdef public list exceptions cdef public ControlBlock entry_point cdef public ExitBlock exit_point cdef public ControlBlock block cdef public dict assmts cdef public Py_ssize_t in_try_block cpdef newblock(self, ControlBlock parent=*) cpdef nextblock(self, ControlBlock parent=*) cpdef bint is_tracked(self, entry) cpdef bint is_statically_assigned(self, entry) cpdef mark_position(self, node) cpdef mark_assignment(self, lhs, rhs, entry, rhs_scope=*) cpdef mark_argument(self, lhs, rhs, entry) cpdef mark_deletion(self, node, entry) cpdef mark_reference(self, node, entry) @cython.locals(block=ControlBlock, parent=ControlBlock, unreachable=set) cpdef normalize(self) @cython.locals(bit=object, assmts=AssignmentList, block=ControlBlock) cpdef initialize(self) @cython.locals(assmts=AssignmentList, assmt=NameAssignment) cpdef set map_one(self, istate, entry) @cython.locals(block=ControlBlock, parent=ControlBlock) cdef reaching_definitions(self) cdef class Uninitialized: pass cdef class Unknown: pass cdef class MessageCollection: cdef set messages @cython.locals(dirty=bint, block=ControlBlock, parent=ControlBlock, assmt=NameAssignment) cdef check_definitions(ControlFlow flow, dict compiler_directives) @cython.final cdef class ControlFlowAnalysis(CythonTransform): cdef object gv_ctx cdef object constant_folder cdef set reductions cdef list stack # a stack of (env, flow) tuples cdef object env cdef ControlFlow flow cdef object object_expr cdef bint in_inplace_assignment cpdef mark_assignment(self, lhs, rhs=*, rhs_scope=*) cpdef mark_position(self, node) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3167222 Cython-3.0.8/Cython/Compiler/FlowControl.py0000644000175100001770000013733600000000000021451 0ustar00runnerdocker00000000000000# cython: language_level=3str # cython: auto_pickle=True from __future__ import absolute_import import cython cython.declare(PyrexTypes=object, ExprNodes=object, Nodes=object, Builtin=object, Options=object, TreeVisitor=object, CythonTransform=object, InternalError=object, error=object, warning=object, fake_rhs_expr=object, TypedExprNode=object) from . import Builtin from . import ExprNodes from . import Nodes from . import Options from . import PyrexTypes from .Visitor import TreeVisitor, CythonTransform from .Errors import error, warning, InternalError class TypedExprNode(ExprNodes.ExprNode): # Used for declaring assignments of a specified type without a known entry. def __init__(self, type, may_be_none=None, pos=None): super(TypedExprNode, self).__init__(pos) self.type = type self._may_be_none = may_be_none def may_be_none(self): return self._may_be_none != False # Fake rhs to silence "unused variable" warning fake_rhs_expr = TypedExprNode(PyrexTypes.unspecified_type) class ControlBlock(object): """Control flow graph node. Sequence of assignments and name references. children set of children nodes parents set of parent nodes positions set of position markers stats list of block statements gen dict of assignments generated by this block bounded set of entries that are definitely bounded in this block Example: a = 1 b = a + c # 'c' is already bounded or exception here stats = [Assignment(a), NameReference(a), NameReference(c), Assignment(b)] gen = {Entry(a): Assignment(a), Entry(b): Assignment(b)} bounded = {Entry(a), Entry(c)} """ def __init__(self): self.children = set() self.parents = set() self.positions = set() self.stats = [] self.gen = {} self.bounded = set() self.i_input = 0 self.i_output = 0 self.i_gen = 0 self.i_kill = 0 self.i_state = 0 def empty(self): return (not self.stats and not self.positions) def detach(self): """Detach block from parents and children.""" for child in self.children: child.parents.remove(self) for parent in self.parents: parent.children.remove(self) self.parents.clear() self.children.clear() def add_child(self, block): self.children.add(block) block.parents.add(self) class ExitBlock(ControlBlock): """Non-empty exit point block.""" def empty(self): return False class AssignmentList(object): def __init__(self): self.stats = [] class ControlFlow(object): """Control-flow graph. entry_point ControlBlock entry point for this graph exit_point ControlBlock normal exit point block ControlBlock current block blocks set children nodes entries set tracked entries loops list stack for loop descriptors exceptions list stack for exception descriptors in_try_block int track if we're in a try...except or try...finally block """ def __init__(self): self.blocks = set() self.entries = set() self.loops = [] self.exceptions = [] self.entry_point = ControlBlock() self.exit_point = ExitBlock() self.blocks.add(self.exit_point) self.block = self.entry_point self.in_try_block = 0 def newblock(self, parent=None): """Create floating block linked to `parent` if given. NOTE: Block is NOT added to self.blocks """ block = ControlBlock() self.blocks.add(block) if parent: parent.add_child(block) return block def nextblock(self, parent=None): """Create block children block linked to current or `parent` if given. NOTE: Block is added to self.blocks """ block = ControlBlock() self.blocks.add(block) if parent: parent.add_child(block) elif self.block: self.block.add_child(block) self.block = block return self.block def is_tracked(self, entry): if entry.is_anonymous: return False return (entry.is_local or entry.is_pyclass_attr or entry.is_arg or entry.from_closure or entry.in_closure or entry.error_on_uninitialized) def is_statically_assigned(self, entry): if (entry.is_local and entry.is_variable and (entry.type.is_struct_or_union or entry.type.is_complex or entry.type.is_array or (entry.type.is_cpp_class and not entry.is_cpp_optional))): # stack allocated structured variable => never uninitialised return True return False def mark_position(self, node): """Mark position, will be used to draw graph nodes.""" if self.block: self.block.positions.add(node.pos[:2]) def mark_assignment(self, lhs, rhs, entry, rhs_scope=None): if self.block and self.is_tracked(entry): assignment = NameAssignment(lhs, rhs, entry, rhs_scope=rhs_scope) self.block.stats.append(assignment) self.block.gen[entry] = assignment self.entries.add(entry) def mark_argument(self, lhs, rhs, entry): if self.block and self.is_tracked(entry): assignment = Argument(lhs, rhs, entry) self.block.stats.append(assignment) self.block.gen[entry] = assignment self.entries.add(entry) def mark_deletion(self, node, entry): if self.block and self.is_tracked(entry): assignment = NameDeletion(node, entry) self.block.stats.append(assignment) self.block.gen[entry] = Uninitialized self.entries.add(entry) def mark_reference(self, node, entry): if self.block and self.is_tracked(entry): self.block.stats.append(NameReference(node, entry)) ## XXX: We don't track expression evaluation order so we can't use ## XXX: successful reference as initialization sign. ## # Local variable is definitely bound after this reference ## if not node.allow_null: ## self.block.bounded.add(entry) self.entries.add(entry) def normalize(self): """Delete unreachable and orphan blocks.""" queue = {self.entry_point} visited = set() while queue: root = queue.pop() visited.add(root) for child in root.children: if child not in visited: queue.add(child) unreachable = self.blocks - visited for block in unreachable: block.detach() visited.remove(self.entry_point) for block in visited: if block.empty(): for parent in block.parents: # Re-parent for child in block.children: parent.add_child(child) block.detach() unreachable.add(block) self.blocks -= unreachable def initialize(self): """Set initial state, map assignments to bits.""" self.assmts = {} bit = 1 for entry in self.entries: assmts = AssignmentList() assmts.mask = assmts.bit = bit self.assmts[entry] = assmts bit <<= 1 for block in self.blocks: for stat in block.stats: if isinstance(stat, NameAssignment): stat.bit = bit assmts = self.assmts[stat.entry] assmts.stats.append(stat) assmts.mask |= bit bit <<= 1 for block in self.blocks: for entry, stat in block.gen.items(): assmts = self.assmts[entry] if stat is Uninitialized: block.i_gen |= assmts.bit else: block.i_gen |= stat.bit block.i_kill |= assmts.mask block.i_output = block.i_gen for entry in block.bounded: block.i_kill |= self.assmts[entry].bit for assmts in self.assmts.values(): self.entry_point.i_gen |= assmts.bit self.entry_point.i_output = self.entry_point.i_gen def map_one(self, istate, entry): ret = set() assmts = self.assmts[entry] if istate & assmts.bit: if self.is_statically_assigned(entry): ret.add(StaticAssignment(entry)) elif entry.from_closure: ret.add(Unknown) else: ret.add(Uninitialized) for assmt in assmts.stats: if istate & assmt.bit: ret.add(assmt) return ret def reaching_definitions(self): """Per-block reaching definitions analysis.""" dirty = True while dirty: dirty = False for block in self.blocks: i_input = 0 for parent in block.parents: i_input |= parent.i_output i_output = (i_input & ~block.i_kill) | block.i_gen if i_output != block.i_output: dirty = True block.i_input = i_input block.i_output = i_output class LoopDescr(object): def __init__(self, next_block, loop_block): self.next_block = next_block self.loop_block = loop_block self.exceptions = [] class ExceptionDescr(object): """Exception handling helper. entry_point ControlBlock Exception handling entry point finally_enter ControlBlock Normal finally clause entry point finally_exit ControlBlock Normal finally clause exit point """ def __init__(self, entry_point, finally_enter=None, finally_exit=None): self.entry_point = entry_point self.finally_enter = finally_enter self.finally_exit = finally_exit class NameAssignment(object): def __init__(self, lhs, rhs, entry, rhs_scope=None): if lhs.cf_state is None: lhs.cf_state = set() self.lhs = lhs self.rhs = rhs self.entry = entry self.pos = lhs.pos self.refs = set() self.is_arg = False self.is_deletion = False self.inferred_type = None # For generator expression targets, the rhs can have a different scope than the lhs. self.rhs_scope = rhs_scope def __repr__(self): return '%s(entry=%r)' % (self.__class__.__name__, self.entry) def infer_type(self): self.inferred_type = self.rhs.infer_type(self.rhs_scope or self.entry.scope) return self.inferred_type def type_dependencies(self): return self.rhs.type_dependencies(self.rhs_scope or self.entry.scope) @property def type(self): if not self.entry.type.is_unspecified: return self.entry.type return self.inferred_type class StaticAssignment(NameAssignment): """Initialised at declaration time, e.g. stack allocation.""" def __init__(self, entry): if not entry.type.is_pyobject: may_be_none = False else: may_be_none = None # unknown lhs = TypedExprNode( entry.type, may_be_none=may_be_none, pos=entry.pos) super(StaticAssignment, self).__init__(lhs, lhs, entry) def infer_type(self): return self.entry.type def type_dependencies(self): return () class Argument(NameAssignment): def __init__(self, lhs, rhs, entry): NameAssignment.__init__(self, lhs, rhs, entry) self.is_arg = True class NameDeletion(NameAssignment): def __init__(self, lhs, entry): NameAssignment.__init__(self, lhs, lhs, entry) self.is_deletion = True def infer_type(self): inferred_type = self.rhs.infer_type(self.entry.scope) if (not inferred_type.is_pyobject and inferred_type.can_coerce_to_pyobject(self.entry.scope)): return PyrexTypes.py_object_type self.inferred_type = inferred_type return inferred_type class Uninitialized(object): """Definitely not initialised yet.""" class Unknown(object): """Coming from outer closure, might be initialised or not.""" class NameReference(object): def __init__(self, node, entry): if node.cf_state is None: node.cf_state = set() self.node = node self.entry = entry self.pos = node.pos def __repr__(self): return '%s(entry=%r)' % (self.__class__.__name__, self.entry) class ControlFlowState(list): # Keeps track of Node's entry assignments # # cf_is_null [boolean] It is uninitialized # cf_maybe_null [boolean] May be uninitialized # is_single [boolean] Has only one assignment at this point cf_maybe_null = False cf_is_null = False is_single = False def __init__(self, state): if Uninitialized in state: state.discard(Uninitialized) self.cf_maybe_null = True if not state: self.cf_is_null = True elif Unknown in state: state.discard(Unknown) self.cf_maybe_null = True else: if len(state) == 1: self.is_single = True # XXX: Remove fake_rhs_expr super(ControlFlowState, self).__init__( [i for i in state if i.rhs is not fake_rhs_expr]) def one(self): return self[0] class GVContext(object): """Graphviz subgraph object.""" def __init__(self): self.blockids = {} self.nextid = 0 self.children = [] self.sources = {} def add(self, child): self.children.append(child) def nodeid(self, block): if block not in self.blockids: self.blockids[block] = 'block%d' % self.nextid self.nextid += 1 return self.blockids[block] def extract_sources(self, block): if not block.positions: return '' start = min(block.positions) stop = max(block.positions) srcdescr = start[0] if srcdescr not in self.sources: self.sources[srcdescr] = list(srcdescr.get_lines()) lines = self.sources[srcdescr] return '\\n'.join([l.strip() for l in lines[start[1] - 1:stop[1]]]) def render(self, fp, name, annotate_defs=False): """Render graphviz dot graph""" fp.write('digraph %s {\n' % name) fp.write(' node [shape=box];\n') for child in self.children: child.render(fp, self, annotate_defs) fp.write('}\n') def escape(self, text): return text.replace('"', '\\"').replace('\n', '\\n') class GV(object): """Graphviz DOT renderer.""" def __init__(self, name, flow): self.name = name self.flow = flow def render(self, fp, ctx, annotate_defs=False): fp.write(' subgraph %s {\n' % self.name) for block in self.flow.blocks: label = ctx.extract_sources(block) if annotate_defs: for stat in block.stats: if isinstance(stat, NameAssignment): label += '\n %s [%s %s]' % ( stat.entry.name, 'deletion' if stat.is_deletion else 'definition', stat.pos[1]) elif isinstance(stat, NameReference): if stat.entry: label += '\n %s [reference %s]' % (stat.entry.name, stat.pos[1]) if not label: label = 'empty' pid = ctx.nodeid(block) fp.write(' %s [label="%s"];\n' % (pid, ctx.escape(label))) for block in self.flow.blocks: pid = ctx.nodeid(block) for child in block.children: fp.write(' %s -> %s;\n' % (pid, ctx.nodeid(child))) fp.write(' }\n') class MessageCollection(object): """Collect error/warnings messages first then sort""" def __init__(self): self.messages = set() def error(self, pos, message): self.messages.add((pos, True, message)) def warning(self, pos, message): self.messages.add((pos, False, message)) def report(self): for pos, is_error, message in sorted(self.messages): if is_error: error(pos, message) else: warning(pos, message, 2) def check_definitions(flow, compiler_directives): flow.initialize() flow.reaching_definitions() # Track down state assignments = set() # Node to entry map references = {} assmt_nodes = set() for block in flow.blocks: i_state = block.i_input for stat in block.stats: i_assmts = flow.assmts[stat.entry] state = flow.map_one(i_state, stat.entry) if isinstance(stat, NameAssignment): stat.lhs.cf_state.update(state) assmt_nodes.add(stat.lhs) i_state = i_state & ~i_assmts.mask if stat.is_deletion: i_state |= i_assmts.bit else: i_state |= stat.bit assignments.add(stat) if stat.rhs is not fake_rhs_expr: stat.entry.cf_assignments.append(stat) elif isinstance(stat, NameReference): references[stat.node] = stat.entry stat.entry.cf_references.append(stat) stat.node.cf_state.update(state) ## if not stat.node.allow_null: ## i_state &= ~i_assmts.bit ## # after successful read, the state is known to be initialised state.discard(Uninitialized) state.discard(Unknown) for assmt in state: assmt.refs.add(stat) # Check variable usage warn_maybe_uninitialized = compiler_directives['warn.maybe_uninitialized'] warn_unused_result = compiler_directives['warn.unused_result'] warn_unused = compiler_directives['warn.unused'] warn_unused_arg = compiler_directives['warn.unused_arg'] messages = MessageCollection() # assignment hints for node in assmt_nodes: if Uninitialized in node.cf_state: node.cf_maybe_null = True if len(node.cf_state) == 1: node.cf_is_null = True else: node.cf_is_null = False elif Unknown in node.cf_state: node.cf_maybe_null = True else: node.cf_is_null = False node.cf_maybe_null = False # Find uninitialized references and cf-hints for node, entry in references.items(): if Uninitialized in node.cf_state: node.cf_maybe_null = True if (not entry.from_closure and len(node.cf_state) == 1 and entry.name not in entry.scope.scope_predefined_names): node.cf_is_null = True if (node.allow_null or entry.from_closure or entry.is_pyclass_attr or entry.type.is_error): pass # Can be uninitialized here elif node.cf_is_null and not entry.in_closure: if entry.error_on_uninitialized or ( Options.error_on_uninitialized and ( entry.type.is_pyobject or entry.type.is_unspecified)): messages.error( node.pos, "local variable '%s' referenced before assignment" % entry.name) else: messages.warning( node.pos, "local variable '%s' referenced before assignment" % entry.name) elif warn_maybe_uninitialized: msg = "local variable '%s' might be referenced before assignment" % entry.name if entry.in_closure: msg += " (maybe initialized inside a closure)" messages.warning( node.pos, msg) elif Unknown in node.cf_state: # TODO: better cross-closure analysis to know when inner functions # are being called before a variable is being set, and when # a variable is known to be set before even defining the # inner function, etc. node.cf_maybe_null = True else: node.cf_is_null = False node.cf_maybe_null = False # Unused result for assmt in assignments: if (not assmt.refs and not assmt.entry.is_pyclass_attr and not assmt.entry.in_closure): if assmt.entry.cf_references and warn_unused_result: if assmt.is_arg: messages.warning(assmt.pos, "Unused argument value '%s'" % assmt.entry.name) else: messages.warning(assmt.pos, "Unused result in '%s'" % assmt.entry.name) assmt.lhs.cf_used = False # Unused entries for entry in flow.entries: if (not entry.cf_references and not entry.is_pyclass_attr): if entry.name != '_' and not entry.name.startswith('unused'): # '_' is often used for unused variables, e.g. in loops if entry.is_arg: if warn_unused_arg: messages.warning(entry.pos, "Unused argument '%s'" % entry.name) else: if warn_unused: messages.warning(entry.pos, "Unused entry '%s'" % entry.name) entry.cf_used = False messages.report() for node in assmt_nodes: node.cf_state = ControlFlowState(node.cf_state) for node in references: node.cf_state = ControlFlowState(node.cf_state) class AssignmentCollector(TreeVisitor): def __init__(self): super(AssignmentCollector, self).__init__() self.assignments = [] def visit_Node(self): self._visitchildren(self, None, None) def visit_SingleAssignmentNode(self, node): self.assignments.append((node.lhs, node.rhs)) def visit_CascadedAssignmentNode(self, node): for lhs in node.lhs_list: self.assignments.append((lhs, node.rhs)) class ControlFlowAnalysis(CythonTransform): def find_in_stack(self, env): if env == self.env: return self.flow for e, flow in reversed(self.stack): if e is env: return flow assert False def visit_ModuleNode(self, node): dot_output = self.current_directives['control_flow.dot_output'] self.gv_ctx = GVContext() if dot_output else None from .Optimize import ConstantFolding self.constant_folder = ConstantFolding() # Set of NameNode reductions self.reductions = set() self.in_inplace_assignment = False self.env = node.scope self.flow = ControlFlow() self.stack = [] # a stack of (env, flow) tuples self.object_expr = TypedExprNode(PyrexTypes.py_object_type, may_be_none=True) self.visitchildren(node) check_definitions(self.flow, self.current_directives) if dot_output: annotate_defs = self.current_directives['control_flow.dot_annotate_defs'] with open(dot_output, 'wt') as fp: self.gv_ctx.render(fp, 'module', annotate_defs=annotate_defs) return node def visit_FuncDefNode(self, node): for arg in node.args: if arg.default: self.visitchildren(arg) self.visitchildren(node, ('decorators',)) self.stack.append((self.env, self.flow)) self.env = node.local_scope self.flow = ControlFlow() # Collect all entries for entry in node.local_scope.entries.values(): if self.flow.is_tracked(entry): self.flow.entries.add(entry) self.mark_position(node) # Function body block self.flow.nextblock() for arg in node.args: self._visit(arg) if node.star_arg: self.flow.mark_argument(node.star_arg, TypedExprNode(Builtin.tuple_type, may_be_none=False), node.star_arg.entry) if node.starstar_arg: self.flow.mark_argument(node.starstar_arg, TypedExprNode(Builtin.dict_type, may_be_none=False), node.starstar_arg.entry) self._visit(node.body) # Workaround for generators if node.is_generator: self._visit(node.gbody.body) # Exit point if self.flow.block: self.flow.block.add_child(self.flow.exit_point) # Cleanup graph self.flow.normalize() check_definitions(self.flow, self.current_directives) self.flow.blocks.add(self.flow.entry_point) if self.gv_ctx is not None: self.gv_ctx.add(GV(node.local_scope.name, self.flow)) self.env, self.flow = self.stack.pop() return node def visit_DefNode(self, node): node.used = True return self.visit_FuncDefNode(node) def visit_GeneratorBodyDefNode(self, node): return node def visit_CTypeDefNode(self, node): return node def mark_assignment(self, lhs, rhs=None, rhs_scope=None): if not self.flow.block: return if self.flow.exceptions: exc_descr = self.flow.exceptions[-1] self.flow.block.add_child(exc_descr.entry_point) self.flow.nextblock() if not rhs: rhs = self.object_expr if lhs.is_name: if lhs.entry is not None: entry = lhs.entry else: entry = self.env.lookup(lhs.name) if entry is None: # TODO: This shouldn't happen... return self.flow.mark_assignment(lhs, rhs, entry, rhs_scope=rhs_scope) elif lhs.is_sequence_constructor: for i, arg in enumerate(lhs.args): if arg.is_starred: # "a, *b = x" assigns a list to "b" item_node = TypedExprNode(Builtin.list_type, may_be_none=False, pos=arg.pos) elif rhs is self.object_expr: item_node = rhs else: item_node = rhs.inferable_item_node(i) self.mark_assignment(arg, item_node) else: self._visit(lhs) if self.flow.exceptions: exc_descr = self.flow.exceptions[-1] self.flow.block.add_child(exc_descr.entry_point) self.flow.nextblock() def mark_position(self, node): """Mark position if DOT output is enabled.""" if self.current_directives['control_flow.dot_output']: self.flow.mark_position(node) def visit_FromImportStatNode(self, node): for name, target in node.items: if name != "*": self.mark_assignment(target) self.visitchildren(node) return node def visit_AssignmentNode(self, node): raise InternalError("Unhandled assignment node %s" % type(node)) def visit_SingleAssignmentNode(self, node): self._visit(node.rhs) self.mark_assignment(node.lhs, node.rhs) return node def visit_CascadedAssignmentNode(self, node): self._visit(node.rhs) for lhs in node.lhs_list: self.mark_assignment(lhs, node.rhs) return node def visit_ParallelAssignmentNode(self, node): collector = AssignmentCollector() collector.visitchildren(node) for lhs, rhs in collector.assignments: self._visit(rhs) for lhs, rhs in collector.assignments: self.mark_assignment(lhs, rhs) return node def visit_InPlaceAssignmentNode(self, node): self.in_inplace_assignment = True self.visitchildren(node) self.in_inplace_assignment = False self.mark_assignment(node.lhs, self.constant_folder(node.create_binop_node())) return node def visit_DelStatNode(self, node): for arg in node.args: if arg.is_name: entry = arg.entry or self.env.lookup(arg.name) if entry.in_closure or entry.from_closure: error(arg.pos, "can not delete variable '%s' " "referenced in nested scope" % entry.name) if not node.ignore_nonexisting: self._visit(arg) # mark reference self.flow.mark_deletion(arg, entry) else: self._visit(arg) return node def visit_CArgDeclNode(self, node): entry = self.env.lookup(node.name) if entry: may_be_none = not node.not_none self.flow.mark_argument( node, TypedExprNode(entry.type, may_be_none), entry) return node def visit_NameNode(self, node): if self.flow.block: entry = node.entry or self.env.lookup(node.name) if entry: self.flow.mark_reference(node, entry) if entry in self.reductions and not self.in_inplace_assignment: error(node.pos, "Cannot read reduction variable in loop body") return node def visit_StatListNode(self, node): if self.flow.block: for stat in node.stats: self._visit(stat) if not self.flow.block: stat.is_terminator = True break return node def visit_Node(self, node): self.visitchildren(node) self.mark_position(node) return node def visit_SizeofVarNode(self, node): return node def visit_TypeidNode(self, node): return node def visit_IfStatNode(self, node): next_block = self.flow.newblock() parent = self.flow.block # If clauses for clause in node.if_clauses: parent = self.flow.nextblock(parent) self._visit(clause.condition) self.flow.nextblock() self._visit(clause.body) if self.flow.block: self.flow.block.add_child(next_block) # Else clause if node.else_clause: self.flow.nextblock(parent=parent) self._visit(node.else_clause) if self.flow.block: self.flow.block.add_child(next_block) else: parent.add_child(next_block) if next_block.parents: self.flow.block = next_block else: self.flow.block = None return node def visit_AssertStatNode(self, node): """Essentially an if-condition that wraps a RaiseStatNode. """ self.mark_position(node) next_block = self.flow.newblock() parent = self.flow.block # failure case parent = self.flow.nextblock(parent) self._visit(node.condition) self.flow.nextblock() self._visit(node.exception) if self.flow.block: self.flow.block.add_child(next_block) parent.add_child(next_block) if next_block.parents: self.flow.block = next_block else: self.flow.block = None return node def visit_WhileStatNode(self, node): condition_block = self.flow.nextblock() next_block = self.flow.newblock() # Condition block self.flow.loops.append(LoopDescr(next_block, condition_block)) if node.condition: self._visit(node.condition) # Body block self.flow.nextblock() self._visit(node.body) self.flow.loops.pop() # Loop it if self.flow.block: self.flow.block.add_child(condition_block) self.flow.block.add_child(next_block) # Else clause if node.else_clause: self.flow.nextblock(parent=condition_block) self._visit(node.else_clause) if self.flow.block: self.flow.block.add_child(next_block) else: condition_block.add_child(next_block) if next_block.parents: self.flow.block = next_block else: self.flow.block = None return node def mark_forloop_target(self, node): # TODO: Remove redundancy with range optimization... is_special = False sequence = node.iterator.sequence target = node.target env = node.iterator.expr_scope or self.env if isinstance(sequence, ExprNodes.SimpleCallNode): function = sequence.function if sequence.self is None and function.is_name: entry = env.lookup(function.name) if not entry or entry.is_builtin: if function.name == 'reversed' and len(sequence.args) == 1: sequence = sequence.args[0] elif function.name == 'enumerate' and len(sequence.args) == 1: if target.is_sequence_constructor and len(target.args) == 2: iterator = sequence.args[0] if iterator.is_name: iterator_type = iterator.infer_type(env) if iterator_type.is_builtin_type: # assume that builtin types have a length within Py_ssize_t self.mark_assignment( target.args[0], ExprNodes.IntNode(target.pos, value='PY_SSIZE_T_MAX', type=PyrexTypes.c_py_ssize_t_type), rhs_scope=node.iterator.expr_scope) target = target.args[1] sequence = sequence.args[0] if isinstance(sequence, ExprNodes.SimpleCallNode): function = sequence.function if sequence.self is None and function.is_name: entry = env.lookup(function.name) if not entry or entry.is_builtin: if function.name in ('range', 'xrange'): is_special = True for arg in sequence.args[:2]: self.mark_assignment(target, arg, rhs_scope=node.iterator.expr_scope) if len(sequence.args) > 2: self.mark_assignment(target, self.constant_folder( ExprNodes.binop_node(node.pos, '+', sequence.args[0], sequence.args[2])), rhs_scope=node.iterator.expr_scope) if not is_special: # A for-loop basically translates to subsequent calls to # __getitem__(), so using an IndexNode here allows us to # naturally infer the base type of pointers, C arrays, # Python strings, etc., while correctly falling back to an # object type when the base type cannot be handled. self.mark_assignment(target, node.item, rhs_scope=node.iterator.expr_scope) def visit_AsyncForStatNode(self, node): return self.visit_ForInStatNode(node) def visit_ForInStatNode(self, node): condition_block = self.flow.nextblock() next_block = self.flow.newblock() # Condition with iterator self.flow.loops.append(LoopDescr(next_block, condition_block)) self._visit(node.iterator) # Target assignment self.flow.nextblock() if isinstance(node, Nodes.ForInStatNode): self.mark_forloop_target(node) elif isinstance(node, Nodes.AsyncForStatNode): # not entirely correct, but good enough for now self.mark_assignment(node.target, node.item) else: # Parallel self.mark_assignment(node.target) # Body block if isinstance(node, Nodes.ParallelRangeNode): # In case of an invalid self._delete_privates(node, exclude=node.target.entry) self.flow.nextblock() self._visit(node.body) self.flow.loops.pop() # Loop it if self.flow.block: self.flow.block.add_child(condition_block) # Else clause if node.else_clause: self.flow.nextblock(parent=condition_block) self._visit(node.else_clause) if self.flow.block: self.flow.block.add_child(next_block) else: condition_block.add_child(next_block) if next_block.parents: self.flow.block = next_block else: self.flow.block = None return node def _delete_privates(self, node, exclude=None): for private_node in node.assigned_nodes: if not exclude or private_node.entry is not exclude: self.flow.mark_deletion(private_node, private_node.entry) def visit_ParallelRangeNode(self, node): reductions = self.reductions # if node.target is None or not a NameNode, an error will have # been previously issued if hasattr(node.target, 'entry'): self.reductions = set(reductions) for private_node in node.assigned_nodes: private_node.entry.error_on_uninitialized = True pos, reduction = node.assignments[private_node.entry] if reduction: self.reductions.add(private_node.entry) node = self.visit_ForInStatNode(node) self.reductions = reductions return node def visit_ParallelWithBlockNode(self, node): for private_node in node.assigned_nodes: private_node.entry.error_on_uninitialized = True self._delete_privates(node) self.visitchildren(node) self._delete_privates(node) return node def visit_ForFromStatNode(self, node): condition_block = self.flow.nextblock() next_block = self.flow.newblock() # Condition with iterator self.flow.loops.append(LoopDescr(next_block, condition_block)) self._visit(node.bound1) self._visit(node.bound2) if node.step is not None: self._visit(node.step) # Target assignment self.flow.nextblock() self.mark_assignment(node.target, node.bound1) if node.step is not None: self.mark_assignment(node.target, self.constant_folder( ExprNodes.binop_node(node.pos, '+', node.bound1, node.step))) # Body block self.flow.nextblock() self._visit(node.body) self.flow.loops.pop() # Loop it if self.flow.block: self.flow.block.add_child(condition_block) # Else clause if node.else_clause: self.flow.nextblock(parent=condition_block) self._visit(node.else_clause) if self.flow.block: self.flow.block.add_child(next_block) else: condition_block.add_child(next_block) if next_block.parents: self.flow.block = next_block else: self.flow.block = None return node def visit_LoopNode(self, node): raise InternalError("Generic loops are not supported") def visit_WithTargetAssignmentStatNode(self, node): self.mark_assignment(node.lhs, node.with_node.enter_call) return node def visit_WithStatNode(self, node): self._visit(node.manager) self._visit(node.enter_call) self._visit(node.body) return node def visit_TryExceptStatNode(self, node): # After exception handling next_block = self.flow.newblock() # Body block self.flow.newblock() # Exception entry point entry_point = self.flow.newblock() self.flow.exceptions.append(ExceptionDescr(entry_point)) self.flow.nextblock() ## XXX: links to exception handling point should be added by ## XXX: children nodes self.flow.block.add_child(entry_point) self.flow.nextblock() self.flow.in_try_block += 1 self._visit(node.body) self.flow.in_try_block -= 1 self.flow.exceptions.pop() # After exception if self.flow.block: if node.else_clause: self.flow.nextblock() self._visit(node.else_clause) if self.flow.block: self.flow.block.add_child(next_block) for clause in node.except_clauses: self.flow.block = entry_point if clause.pattern: for pattern in clause.pattern: self._visit(pattern) else: # TODO: handle * pattern pass entry_point = self.flow.newblock(parent=self.flow.block) self.flow.nextblock() if clause.target: self.mark_assignment(clause.target) self._visit(clause.body) if self.flow.block: self.flow.block.add_child(next_block) if self.flow.exceptions: entry_point.add_child(self.flow.exceptions[-1].entry_point) if next_block.parents: self.flow.block = next_block else: self.flow.block = None return node def visit_TryFinallyStatNode(self, node): body_block = self.flow.nextblock() # Exception entry point entry_point = self.flow.newblock() self.flow.block = entry_point self._visit(node.finally_except_clause) if self.flow.block and self.flow.exceptions: self.flow.block.add_child(self.flow.exceptions[-1].entry_point) # Normal execution finally_enter = self.flow.newblock() self.flow.block = finally_enter self._visit(node.finally_clause) finally_exit = self.flow.block descr = ExceptionDescr(entry_point, finally_enter, finally_exit) self.flow.exceptions.append(descr) if self.flow.loops: self.flow.loops[-1].exceptions.append(descr) self.flow.block = body_block body_block.add_child(entry_point) self.flow.nextblock() self.flow.in_try_block += 1 self._visit(node.body) self.flow.in_try_block -= 1 self.flow.exceptions.pop() if self.flow.loops: self.flow.loops[-1].exceptions.pop() if self.flow.block: self.flow.block.add_child(finally_enter) if finally_exit: self.flow.block = self.flow.nextblock(parent=finally_exit) else: self.flow.block = None return node def visit_RaiseStatNode(self, node): self.mark_position(node) self.visitchildren(node) if self.flow.exceptions: self.flow.block.add_child(self.flow.exceptions[-1].entry_point) self.flow.block = None if self.flow.in_try_block: node.in_try_block = True return node def visit_ReraiseStatNode(self, node): self.mark_position(node) if self.flow.exceptions: self.flow.block.add_child(self.flow.exceptions[-1].entry_point) self.flow.block = None return node def visit_ReturnStatNode(self, node): self.mark_position(node) self.visitchildren(node) outer_exception_handlers = iter(self.flow.exceptions[::-1]) for handler in outer_exception_handlers: if handler.finally_enter: self.flow.block.add_child(handler.finally_enter) if handler.finally_exit: # 'return' goes to function exit, or to the next outer 'finally' clause exit_point = self.flow.exit_point for next_handler in outer_exception_handlers: if next_handler.finally_enter: exit_point = next_handler.finally_enter break handler.finally_exit.add_child(exit_point) break else: if self.flow.block: self.flow.block.add_child(self.flow.exit_point) self.flow.block = None return node def visit_BreakStatNode(self, node): if not self.flow.loops: #error(node.pos, "break statement not inside loop") return node loop = self.flow.loops[-1] self.mark_position(node) for exception in loop.exceptions[::-1]: if exception.finally_enter: self.flow.block.add_child(exception.finally_enter) if exception.finally_exit: exception.finally_exit.add_child(loop.next_block) break else: self.flow.block.add_child(loop.next_block) self.flow.block = None return node def visit_ContinueStatNode(self, node): if not self.flow.loops: #error(node.pos, "continue statement not inside loop") return node loop = self.flow.loops[-1] self.mark_position(node) for exception in loop.exceptions[::-1]: if exception.finally_enter: self.flow.block.add_child(exception.finally_enter) if exception.finally_exit: exception.finally_exit.add_child(loop.loop_block) break else: self.flow.block.add_child(loop.loop_block) self.flow.block = None return node def visit_ComprehensionNode(self, node): if node.expr_scope: self.stack.append((self.env, self.flow)) self.env = node.expr_scope # Skip append node here self._visit(node.loop) if node.expr_scope: self.env, _ = self.stack.pop() return node def visit_ScopedExprNode(self, node): # currently this is written to deal with these two types # (with comprehensions covered in their own function) assert isinstance(node, (ExprNodes.IteratorNode, ExprNodes.AsyncIteratorNode)), node if node.expr_scope: self.stack.append((self.env, self.flow)) self.flow = self.find_in_stack(node.expr_scope) self.env = node.expr_scope self.visitchildren(node) if node.expr_scope: self.env, self.flow = self.stack.pop() return node def visit_PyClassDefNode(self, node): self.visitchildren(node, ('dict', 'metaclass', 'mkw', 'bases', 'class_result')) self.flow.mark_assignment(node.target, node.classobj, self.env.lookup(node.target.name)) self.stack.append((self.env, self.flow)) self.env = node.scope self.flow.nextblock() if node.doc_node: self.flow.mark_assignment(node.doc_node, fake_rhs_expr, node.doc_node.entry) self.visitchildren(node, ('body',)) self.flow.nextblock() self.env, _ = self.stack.pop() return node def visit_CClassDefNode(self, node): # just make sure the nodes scope is findable in-case there is a list comprehension in it self.stack.append((node.scope, self.flow)) self.visitchildren(node) self.stack.pop() return node def visit_AmpersandNode(self, node): if node.operand.is_name: # Fake assignment to silence warning self.mark_assignment(node.operand, fake_rhs_expr) self.visitchildren(node) return node ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3167222 Cython-3.0.8/Cython/Compiler/FusedNode.py0000644000175100001770000012454000000000000021046 0ustar00runnerdocker00000000000000from __future__ import absolute_import import copy from . import (ExprNodes, PyrexTypes, MemoryView, ParseTreeTransforms, StringEncoding, Errors, Naming) from .ExprNodes import CloneNode, ProxyNode, TupleNode from .Nodes import FuncDefNode, CFuncDefNode, StatListNode, DefNode from ..Utils import OrderedSet from .Errors import error, CannotSpecialize class FusedCFuncDefNode(StatListNode): """ This node replaces a function with fused arguments. It deep-copies the function for every permutation of fused types, and allocates a new local scope for it. It keeps track of the original function in self.node, and the entry of the original function in the symbol table is given the 'fused_cfunction' attribute which points back to us. Then when a function lookup occurs (to e.g. call it), the call can be dispatched to the right function. node FuncDefNode the original function nodes [FuncDefNode] list of copies of node with different specific types py_func DefNode the fused python function subscriptable from Python space __signatures__ A DictNode mapping signature specialization strings to PyCFunction nodes resulting_fused_function PyCFunction for the fused DefNode that delegates to specializations fused_func_assignment Assignment of the fused function to the function name defaults_tuple TupleNode of defaults (letting PyCFunctionNode build defaults would result in many different tuples) specialized_pycfuncs List of synthesized pycfunction nodes for the specializations code_object CodeObjectNode shared by all specializations and the fused function fused_compound_types All fused (compound) types (e.g. floating[:]) """ __signatures__ = None resulting_fused_function = None fused_func_assignment = None defaults_tuple = None decorators = None child_attrs = StatListNode.child_attrs + [ '__signatures__', 'resulting_fused_function', 'fused_func_assignment'] def __init__(self, node, env): super(FusedCFuncDefNode, self).__init__(node.pos) self.nodes = [] self.node = node is_def = isinstance(self.node, DefNode) if is_def: # self.node.decorators = [] self.copy_def(env) else: self.copy_cdef(env) # Perform some sanity checks. If anything fails, it's a bug for n in self.nodes: assert not n.entry.type.is_fused assert not n.local_scope.return_type.is_fused if node.return_type.is_fused: assert not n.return_type.is_fused if not is_def and n.cfunc_declarator.optional_arg_count: assert n.type.op_arg_struct node.entry.fused_cfunction = self # Copy the nodes as AnalyseDeclarationsTransform will prepend # self.py_func to self.stats, as we only want specialized # CFuncDefNodes in self.nodes self.stats = self.nodes[:] def copy_def(self, env): """ Create a copy of the original def or lambda function for specialized versions. """ fused_compound_types = PyrexTypes.unique( [arg.type for arg in self.node.args if arg.type.is_fused]) fused_types = self._get_fused_base_types(fused_compound_types) permutations = PyrexTypes.get_all_specialized_permutations(fused_types) self.fused_compound_types = fused_compound_types if self.node.entry in env.pyfunc_entries: env.pyfunc_entries.remove(self.node.entry) for cname, fused_to_specific in permutations: copied_node = copy.deepcopy(self.node) # keep signature object identity for special casing in DefNode.analyse_declarations() copied_node.entry.signature = self.node.entry.signature self._specialize_function_args(copied_node.args, fused_to_specific) copied_node.return_type = self.node.return_type.specialize( fused_to_specific) copied_node.analyse_declarations(env) # copied_node.is_staticmethod = self.node.is_staticmethod # copied_node.is_classmethod = self.node.is_classmethod self.create_new_local_scope(copied_node, env, fused_to_specific) self.specialize_copied_def(copied_node, cname, self.node.entry, fused_to_specific, fused_compound_types) PyrexTypes.specialize_entry(copied_node.entry, cname) copied_node.entry.used = True env.entries[copied_node.entry.name] = copied_node.entry if not self.replace_fused_typechecks(copied_node): break self.orig_py_func = self.node self.py_func = self.make_fused_cpdef(self.node, env, is_def=True) def copy_cdef(self, env): """ Create a copy of the original c(p)def function for all specialized versions. """ permutations = self.node.type.get_all_specialized_permutations() # print 'Node %s has %d specializations:' % (self.node.entry.name, # len(permutations)) # import pprint; pprint.pprint([d for cname, d in permutations]) # Prevent copying of the python function self.orig_py_func = orig_py_func = self.node.py_func self.node.py_func = None if orig_py_func: env.pyfunc_entries.remove(orig_py_func.entry) fused_types = self.node.type.get_fused_types() self.fused_compound_types = fused_types new_cfunc_entries = [] for cname, fused_to_specific in permutations: copied_node = copy.deepcopy(self.node) # Make the types in our CFuncType specific. try: type = copied_node.type.specialize(fused_to_specific) except CannotSpecialize: # unlike for the argument types, specializing the return type can fail error(copied_node.pos, "Return type is a fused type that cannot " "be determined from the function arguments") self.py_func = None # this is just to let the compiler exit gracefully return entry = copied_node.entry type.specialize_entry(entry, cname) # Reuse existing Entries (e.g. from .pxd files). for i, orig_entry in enumerate(env.cfunc_entries): if entry.cname == orig_entry.cname and type.same_as_resolved_type(orig_entry.type): copied_node.entry = env.cfunc_entries[i] if not copied_node.entry.func_cname: copied_node.entry.func_cname = entry.func_cname entry = copied_node.entry type = entry.type break else: new_cfunc_entries.append(entry) copied_node.type = type entry.type, type.entry = type, entry entry.used = (entry.used or self.node.entry.defined_in_pxd or env.is_c_class_scope or entry.is_cmethod) if self.node.cfunc_declarator.optional_arg_count: self.node.cfunc_declarator.declare_optional_arg_struct( type, env, fused_cname=cname) copied_node.return_type = type.return_type self.create_new_local_scope(copied_node, env, fused_to_specific) # Make the argument types in the CFuncDeclarator specific self._specialize_function_args(copied_node.cfunc_declarator.args, fused_to_specific) # If a cpdef, declare all specialized cpdefs (this # also calls analyse_declarations) copied_node.declare_cpdef_wrapper(env) if copied_node.py_func: env.pyfunc_entries.remove(copied_node.py_func.entry) self.specialize_copied_def( copied_node.py_func, cname, self.node.entry.as_variable, fused_to_specific, fused_types) if not self.replace_fused_typechecks(copied_node): break # replace old entry with new entries if self.node.entry in env.cfunc_entries: cindex = env.cfunc_entries.index(self.node.entry) env.cfunc_entries[cindex:cindex+1] = new_cfunc_entries else: env.cfunc_entries.extend(new_cfunc_entries) if orig_py_func: self.py_func = self.make_fused_cpdef(orig_py_func, env, is_def=False) else: self.py_func = orig_py_func def _get_fused_base_types(self, fused_compound_types): """ Get a list of unique basic fused types, from a list of (possibly) compound fused types. """ base_types = [] seen = set() for fused_type in fused_compound_types: fused_type.get_fused_types(result=base_types, seen=seen) return base_types def _specialize_function_args(self, args, fused_to_specific): for arg in args: if arg.type.is_fused: arg.type = arg.type.specialize(fused_to_specific) if arg.type.is_memoryviewslice: arg.type.validate_memslice_dtype(arg.pos) if arg.annotation: # TODO might be nice if annotations were specialized instead? # (Or might be hard to do reliably) arg.annotation.untyped = True def create_new_local_scope(self, node, env, f2s): """ Create a new local scope for the copied node and append it to self.nodes. A new local scope is needed because the arguments with the fused types are already in the local scope, and we need the specialized entries created after analyse_declarations on each specialized version of the (CFunc)DefNode. f2s is a dict mapping each fused type to its specialized version """ node.create_local_scope(env) node.local_scope.fused_to_specific = f2s # This is copied from the original function, set it to false to # stop recursion node.has_fused_arguments = False self.nodes.append(node) def specialize_copied_def(self, node, cname, py_entry, f2s, fused_compound_types): """Specialize the copy of a DefNode given the copied node, the specialization cname and the original DefNode entry""" fused_types = self._get_fused_base_types(fused_compound_types) type_strings = [ PyrexTypes.specialization_signature_string(fused_type, f2s) for fused_type in fused_types ] node.specialized_signature_string = '|'.join(type_strings) node.entry.pymethdef_cname = PyrexTypes.get_fused_cname( cname, node.entry.pymethdef_cname) node.entry.doc = py_entry.doc node.entry.doc_cname = py_entry.doc_cname def replace_fused_typechecks(self, copied_node): """ Branch-prune fused type checks like if fused_t is int: ... Returns whether an error was issued and whether we should stop in in order to prevent a flood of errors. """ num_errors = Errors.get_errors_count() transform = ParseTreeTransforms.ReplaceFusedTypeChecks( copied_node.local_scope) transform(copied_node) if Errors.get_errors_count() > num_errors: return False return True def _fused_instance_checks(self, normal_types, pyx_code, env): """ Generate Cython code for instance checks, matching an object to specialized types. """ for specialized_type in normal_types: # all_numeric = all_numeric and specialized_type.is_numeric py_type_name = specialized_type.py_type_name() if py_type_name == 'int': # Support Python 2 long py_type_name = '(int, long)' pyx_code.context.update( py_type_name=py_type_name, specialized_type_name=specialized_type.specialization_string, ) pyx_code.put_chunk( u""" if isinstance(arg, {{py_type_name}}): dest_sig[{{dest_sig_idx}}] = '{{specialized_type_name}}'; break """) def _dtype_name(self, dtype): name = str(dtype).replace('_', '__').replace(' ', '_') if dtype.is_typedef: name = Naming.fused_dtype_prefix + name return name def _dtype_type(self, dtype): if dtype.is_typedef: return self._dtype_name(dtype) return str(dtype) def _sizeof_dtype(self, dtype): if dtype.is_pyobject: return 'sizeof(void *)' else: return "sizeof(%s)" % self._dtype_type(dtype) def _buffer_check_numpy_dtype_setup_cases(self, pyx_code): "Setup some common cases to match dtypes against specializations" with pyx_code.indenter("if kind in u'iu':"): pyx_code.putln("pass") pyx_code.named_insertion_point("dtype_int") with pyx_code.indenter("elif kind == u'f':"): pyx_code.putln("pass") pyx_code.named_insertion_point("dtype_float") with pyx_code.indenter("elif kind == u'c':"): pyx_code.putln("pass") pyx_code.named_insertion_point("dtype_complex") with pyx_code.indenter("elif kind == u'O':"): pyx_code.putln("pass") pyx_code.named_insertion_point("dtype_object") match = "dest_sig[{{dest_sig_idx}}] = '{{specialized_type_name}}'" no_match = "dest_sig[{{dest_sig_idx}}] = None" def _buffer_check_numpy_dtype(self, pyx_code, specialized_buffer_types, pythran_types): """ Match a numpy dtype object to the individual specializations. """ self._buffer_check_numpy_dtype_setup_cases(pyx_code) for specialized_type in pythran_types+specialized_buffer_types: final_type = specialized_type if specialized_type.is_pythran_expr: specialized_type = specialized_type.org_buffer dtype = specialized_type.dtype pyx_code.context.update( itemsize_match=self._sizeof_dtype(dtype) + " == itemsize", signed_match="not (%s_is_signed ^ dtype_signed)" % self._dtype_name(dtype), dtype=dtype, specialized_type_name=final_type.specialization_string) dtypes = [ (dtype.is_int, pyx_code.dtype_int), (dtype.is_float, pyx_code.dtype_float), (dtype.is_complex, pyx_code.dtype_complex) ] for dtype_category, codewriter in dtypes: if not dtype_category: continue cond = '{{itemsize_match}} and (arg.ndim) == %d' % ( specialized_type.ndim,) if dtype.is_int: cond += ' and {{signed_match}}' if final_type.is_pythran_expr: cond += ' and arg_is_pythran_compatible' with codewriter.indenter("if %s:" % cond): #codewriter.putln("print 'buffer match found based on numpy dtype'") codewriter.putln(self.match) codewriter.putln("break") def _buffer_parse_format_string_check(self, pyx_code, decl_code, specialized_type, env): """ For each specialized type, try to coerce the object to a memoryview slice of that type. This means obtaining a buffer and parsing the format string. TODO: separate buffer acquisition from format parsing """ dtype = specialized_type.dtype if specialized_type.is_buffer: axes = [('direct', 'strided')] * specialized_type.ndim else: axes = specialized_type.axes memslice_type = PyrexTypes.MemoryViewSliceType(dtype, axes) memslice_type.create_from_py_utility_code(env) pyx_code.context.update( coerce_from_py_func=memslice_type.from_py_function, dtype=dtype) decl_code.putln( "{{memviewslice_cname}} {{coerce_from_py_func}}(object, int)") pyx_code.context.update( specialized_type_name=specialized_type.specialization_string, sizeof_dtype=self._sizeof_dtype(dtype), ndim_dtype=specialized_type.ndim, dtype_is_struct_obj=int(dtype.is_struct or dtype.is_pyobject)) # use the memoryview object to check itemsize and ndim. # In principle it could check more, but these are the easiest to do quickly pyx_code.put_chunk( u""" # try {{dtype}} if (((itemsize == -1 and arg_as_memoryview.itemsize == {{sizeof_dtype}}) or itemsize == {{sizeof_dtype}}) and arg_as_memoryview.ndim == {{ndim_dtype}}): {{if dtype_is_struct_obj}} if __PYX_IS_PYPY2: # I wasn't able to diagnose why, but PyPy2 fails to convert a # memoryview to a Cython memoryview in this case memslice = {{coerce_from_py_func}}(arg, 0) else: {{else}} if True: {{endif}} memslice = {{coerce_from_py_func}}(arg_as_memoryview, 0) if memslice.memview: __PYX_XCLEAR_MEMVIEW(&memslice, 1) # print 'found a match for the buffer through format parsing' %s break else: __pyx_PyErr_Clear() """ % self.match) def _buffer_checks(self, buffer_types, pythran_types, pyx_code, decl_code, accept_none, env): """ Generate Cython code to match objects to buffer specializations. First try to get a numpy dtype object and match it against the individual specializations. If that fails, try naively to coerce the object to each specialization, which obtains the buffer each time and tries to match the format string. """ # The first thing to find a match in this loop breaks out of the loop pyx_code.put_chunk( u""" """ + (u"arg_is_pythran_compatible = False" if pythran_types else u"") + u""" if ndarray is not None: if isinstance(arg, ndarray): dtype = arg.dtype """ + (u"arg_is_pythran_compatible = True" if pythran_types else u"") + u""" elif __pyx_memoryview_check(arg): arg_base = arg.base if isinstance(arg_base, ndarray): dtype = arg_base.dtype else: dtype = None else: dtype = None itemsize = -1 if dtype is not None: itemsize = dtype.itemsize kind = ord(dtype.kind) dtype_signed = kind == u'i' """) pyx_code.indent(2) if pythran_types: pyx_code.put_chunk( u""" # Pythran only supports the endianness of the current compiler byteorder = dtype.byteorder if byteorder == "<" and not __Pyx_Is_Little_Endian(): arg_is_pythran_compatible = False elif byteorder == ">" and __Pyx_Is_Little_Endian(): arg_is_pythran_compatible = False if arg_is_pythran_compatible: cur_stride = itemsize shape = arg.shape strides = arg.strides for i in range(arg.ndim-1, -1, -1): if (strides[i]) != cur_stride: arg_is_pythran_compatible = False break cur_stride *= shape[i] else: arg_is_pythran_compatible = not (arg.flags.f_contiguous and (arg.ndim) > 1) """) pyx_code.named_insertion_point("numpy_dtype_checks") self._buffer_check_numpy_dtype(pyx_code, buffer_types, pythran_types) pyx_code.dedent(2) if accept_none: # If None is acceptable, then Cython <3.0 matched None with the # first type. This behaviour isn't ideal, but keep it for backwards # compatibility. Better behaviour would be to see if subsequent # arguments give a stronger match. pyx_code.context.update( specialized_type_name=buffer_types[0].specialization_string ) pyx_code.put_chunk( """ if arg is None: %s break """ % self.match) # creating a Cython memoryview from a Python memoryview avoids the # need to get the buffer multiple times, and we can # also use it to check itemsizes etc pyx_code.put_chunk( """ try: arg_as_memoryview = memoryview(arg) except (ValueError, TypeError): pass """) with pyx_code.indenter("else:"): for specialized_type in buffer_types: self._buffer_parse_format_string_check( pyx_code, decl_code, specialized_type, env) def _buffer_declarations(self, pyx_code, decl_code, all_buffer_types, pythran_types): """ If we have any buffer specializations, write out some variable declarations and imports. """ decl_code.put_chunk( u""" ctypedef struct {{memviewslice_cname}}: void *memview void __PYX_XCLEAR_MEMVIEW({{memviewslice_cname}} *, int have_gil) bint __pyx_memoryview_check(object) bint __PYX_IS_PYPY2 "(CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION == 2)" """) pyx_code.local_variable_declarations.put_chunk( u""" cdef {{memviewslice_cname}} memslice cdef Py_ssize_t itemsize cdef bint dtype_signed cdef Py_UCS4 kind itemsize = -1 """) if pythran_types: pyx_code.local_variable_declarations.put_chunk(u""" cdef bint arg_is_pythran_compatible cdef Py_ssize_t cur_stride """) pyx_code.imports.put_chunk( u""" cdef type ndarray ndarray = __Pyx_ImportNumPyArrayTypeIfAvailable() """) pyx_code.imports.put_chunk( u""" cdef memoryview arg_as_memoryview """ ) seen_typedefs = set() seen_int_dtypes = set() for buffer_type in all_buffer_types: dtype = buffer_type.dtype dtype_name = self._dtype_name(dtype) if dtype.is_typedef: if dtype_name not in seen_typedefs: seen_typedefs.add(dtype_name) decl_code.putln( 'ctypedef %s %s "%s"' % (dtype.resolve(), dtype_name, dtype.empty_declaration_code())) if buffer_type.dtype.is_int: if str(dtype) not in seen_int_dtypes: seen_int_dtypes.add(str(dtype)) pyx_code.context.update(dtype_name=dtype_name, dtype_type=self._dtype_type(dtype)) pyx_code.local_variable_declarations.put_chunk( u""" cdef bint {{dtype_name}}_is_signed {{dtype_name}}_is_signed = not (<{{dtype_type}}> -1 > 0) """) def _split_fused_types(self, arg): """ Specialize fused types and split into normal types and buffer types. """ specialized_types = PyrexTypes.get_specialized_types(arg.type) # Prefer long over int, etc by sorting (see type classes in PyrexTypes.py) specialized_types.sort() seen_py_type_names = set() normal_types, buffer_types, pythran_types = [], [], [] has_object_fallback = False for specialized_type in specialized_types: py_type_name = specialized_type.py_type_name() if py_type_name: if py_type_name in seen_py_type_names: continue seen_py_type_names.add(py_type_name) if py_type_name == 'object': has_object_fallback = True else: normal_types.append(specialized_type) elif specialized_type.is_pythran_expr: pythran_types.append(specialized_type) elif specialized_type.is_buffer or specialized_type.is_memoryviewslice: buffer_types.append(specialized_type) return normal_types, buffer_types, pythran_types, has_object_fallback def _unpack_argument(self, pyx_code): pyx_code.put_chunk( u""" # PROCESSING ARGUMENT {{arg_tuple_idx}} if {{arg_tuple_idx}} < len(args): arg = (args)[{{arg_tuple_idx}}] elif kwargs is not None and '{{arg.name}}' in kwargs: arg = (kwargs)['{{arg.name}}'] else: {{if arg.default}} arg = (defaults)[{{default_idx}}] {{else}} {{if arg_tuple_idx < min_positional_args}} raise TypeError("Expected at least %d argument%s, got %d" % ( {{min_positional_args}}, {{'"s"' if min_positional_args != 1 else '""'}}, len(args))) {{else}} raise TypeError("Missing keyword-only argument: '%s'" % "{{arg.default}}") {{endif}} {{endif}} """) def _fused_signature_index(self, pyx_code): """ Generate Cython code for constructing a persistent nested dictionary index of fused type specialization signatures. """ pyx_code.put_chunk( u""" if not _fused_sigindex: for sig in signatures: sigindex_node = _fused_sigindex *sig_series, last_type = sig.strip('()').split('|') for sig_type in sig_series: if sig_type not in sigindex_node: sigindex_node[sig_type] = sigindex_node = {} else: sigindex_node = sigindex_node[sig_type] sigindex_node[last_type] = sig """ ) def make_fused_cpdef(self, orig_py_func, env, is_def): """ This creates the function that is indexable from Python and does runtime dispatch based on the argument types. The function gets the arg tuple and kwargs dict (or None) and the defaults tuple as arguments from the Binding Fused Function's tp_call. """ from . import TreeFragment, Code, UtilityCode fused_types = self._get_fused_base_types([ arg.type for arg in self.node.args if arg.type.is_fused]) context = { 'memviewslice_cname': MemoryView.memviewslice_cname, 'func_args': self.node.args, 'n_fused': len(fused_types), 'min_positional_args': self.node.num_required_args - self.node.num_required_kw_args if is_def else sum(1 for arg in self.node.args if arg.default is None), 'name': orig_py_func.entry.name, } pyx_code = Code.PyxCodeWriter(context=context) decl_code = Code.PyxCodeWriter(context=context) decl_code.put_chunk( u""" cdef extern from *: void __pyx_PyErr_Clear "PyErr_Clear" () type __Pyx_ImportNumPyArrayTypeIfAvailable() int __Pyx_Is_Little_Endian() """) decl_code.indent() pyx_code.put_chunk( u""" def __pyx_fused_cpdef(signatures, args, kwargs, defaults, _fused_sigindex={}): # FIXME: use a typed signature - currently fails badly because # default arguments inherit the types we specify here! cdef list search_list cdef dict sigindex_node dest_sig = [None] * {{n_fused}} if kwargs is not None and not kwargs: kwargs = None cdef Py_ssize_t i # instance check body """) pyx_code.indent() # indent following code to function body pyx_code.named_insertion_point("imports") pyx_code.named_insertion_point("func_defs") pyx_code.named_insertion_point("local_variable_declarations") fused_index = 0 default_idx = 0 all_buffer_types = OrderedSet() seen_fused_types = set() for i, arg in enumerate(self.node.args): if arg.type.is_fused: arg_fused_types = arg.type.get_fused_types() if len(arg_fused_types) > 1: raise NotImplementedError("Determination of more than one fused base " "type per argument is not implemented.") fused_type = arg_fused_types[0] if arg.type.is_fused and fused_type not in seen_fused_types: seen_fused_types.add(fused_type) context.update( arg_tuple_idx=i, arg=arg, dest_sig_idx=fused_index, default_idx=default_idx, ) normal_types, buffer_types, pythran_types, has_object_fallback = self._split_fused_types(arg) self._unpack_argument(pyx_code) # 'unrolled' loop, first match breaks out of it with pyx_code.indenter("while 1:"): if normal_types: self._fused_instance_checks(normal_types, pyx_code, env) if buffer_types or pythran_types: env.use_utility_code(Code.UtilityCode.load_cached("IsLittleEndian", "ModuleSetupCode.c")) self._buffer_checks( buffer_types, pythran_types, pyx_code, decl_code, arg.accept_none, env) if has_object_fallback: pyx_code.context.update(specialized_type_name='object') pyx_code.putln(self.match) else: pyx_code.putln(self.no_match) pyx_code.putln("break") fused_index += 1 all_buffer_types.update(buffer_types) all_buffer_types.update(ty.org_buffer for ty in pythran_types) if arg.default: default_idx += 1 if all_buffer_types: self._buffer_declarations(pyx_code, decl_code, all_buffer_types, pythran_types) env.use_utility_code(Code.UtilityCode.load_cached("Import", "ImportExport.c")) env.use_utility_code(Code.UtilityCode.load_cached("ImportNumPyArray", "ImportExport.c")) self._fused_signature_index(pyx_code) pyx_code.put_chunk( u""" sigindex_matches = [] sigindex_candidates = [_fused_sigindex] for dst_type in dest_sig: found_matches = [] found_candidates = [] # Make two separate lists: One for signature sub-trees # with at least one definite match, and another for # signature sub-trees with only ambiguous matches # (where `dest_sig[i] is None`). if dst_type is None: for sn in sigindex_matches: found_matches.extend(( sn).values()) for sn in sigindex_candidates: found_candidates.extend(( sn).values()) else: for search_list in (sigindex_matches, sigindex_candidates): for sn in search_list: type_match = ( sn).get(dst_type) if type_match is not None: found_matches.append(type_match) sigindex_matches = found_matches sigindex_candidates = found_candidates if not (found_matches or found_candidates): break candidates = sigindex_matches if not candidates: raise TypeError("No matching signature found") elif len(candidates) > 1: raise TypeError("Function call with ambiguous argument types") else: return (signatures)[candidates[0]] """) fragment_code = pyx_code.getvalue() # print decl_code.getvalue() # print fragment_code from .Optimize import ConstantFolding fragment = TreeFragment.TreeFragment( fragment_code, level='module', pipeline=[ConstantFolding()]) ast = TreeFragment.SetPosTransform(self.node.pos)(fragment.root) UtilityCode.declare_declarations_in_scope( decl_code.getvalue(), env.global_scope()) ast.scope = env # FIXME: for static methods of cdef classes, we build the wrong signature here: first arg becomes 'self' ast.analyse_declarations(env) py_func = ast.stats[-1] # the DefNode self.fragment_scope = ast.scope if isinstance(self.node, DefNode): py_func.specialized_cpdefs = self.nodes[:] else: py_func.specialized_cpdefs = [n.py_func for n in self.nodes] return py_func def update_fused_defnode_entry(self, env): copy_attributes = ( 'name', 'pos', 'cname', 'func_cname', 'pyfunc_cname', 'pymethdef_cname', 'doc', 'doc_cname', 'is_member', 'scope' ) entry = self.py_func.entry for attr in copy_attributes: setattr(entry, attr, getattr(self.orig_py_func.entry, attr)) self.py_func.name = self.orig_py_func.name self.py_func.doc = self.orig_py_func.doc env.entries.pop('__pyx_fused_cpdef', None) if isinstance(self.node, DefNode): env.entries[entry.name] = entry else: env.entries[entry.name].as_variable = entry env.pyfunc_entries.append(entry) self.py_func.entry.fused_cfunction = self for node in self.nodes: if isinstance(self.node, DefNode): node.fused_py_func = self.py_func else: node.py_func.fused_py_func = self.py_func node.entry.as_variable = entry self.synthesize_defnodes() self.stats.append(self.__signatures__) def analyse_expressions(self, env): """ Analyse the expressions. Take care to only evaluate default arguments once and clone the result for all specializations """ for fused_compound_type in self.fused_compound_types: for fused_type in fused_compound_type.get_fused_types(): for specialization_type in fused_type.types: if specialization_type.is_complex: specialization_type.create_declaration_utility_code(env) if self.py_func: self.__signatures__ = self.__signatures__.analyse_expressions(env) self.py_func = self.py_func.analyse_expressions(env) self.resulting_fused_function = self.resulting_fused_function.analyse_expressions(env) self.fused_func_assignment = self.fused_func_assignment.analyse_expressions(env) self.defaults = defaults = [] for arg in self.node.args: if arg.default: arg.default = arg.default.analyse_expressions(env) if arg.default.is_literal: defaults.append(copy.copy(arg.default)) else: # coerce the argument to temp since CloneNode really requires a temp defaults.append(ProxyNode(arg.default.coerce_to_temp(env))) else: defaults.append(None) for i, stat in enumerate(self.stats): stat = self.stats[i] = stat.analyse_expressions(env) if isinstance(stat, FuncDefNode) and stat is not self.py_func: # the dispatcher specifically doesn't want its defaults overriding for arg, default in zip(stat.args, defaults): if default is not None: if default.is_literal: arg.default = default.coerce_to(arg.type, env) else: arg.default = CloneNode(default).analyse_expressions(env).coerce_to(arg.type, env) if self.py_func: args = [CloneNode(default) for default in defaults if default] self.defaults_tuple = TupleNode(self.pos, args=args) self.defaults_tuple = self.defaults_tuple.analyse_types(env, skip_children=True).coerce_to_pyobject(env) self.defaults_tuple = ProxyNode(self.defaults_tuple) self.code_object = ProxyNode(self.specialized_pycfuncs[0].code_object) fused_func = self.resulting_fused_function.arg fused_func.defaults_tuple = CloneNode(self.defaults_tuple) fused_func.code_object = CloneNode(self.code_object) for i, pycfunc in enumerate(self.specialized_pycfuncs): pycfunc.code_object = CloneNode(self.code_object) pycfunc = self.specialized_pycfuncs[i] = pycfunc.analyse_types(env) pycfunc.defaults_tuple = CloneNode(self.defaults_tuple) return self def synthesize_defnodes(self): """ Create the __signatures__ dict of PyCFunctionNode specializations. """ if isinstance(self.nodes[0], CFuncDefNode): nodes = [node.py_func for node in self.nodes] else: nodes = self.nodes # For the moment, fused functions do not support METH_FASTCALL for node in nodes: node.entry.signature.use_fastcall = False signatures = [StringEncoding.EncodedString(node.specialized_signature_string) for node in nodes] keys = [ExprNodes.StringNode(node.pos, value=sig) for node, sig in zip(nodes, signatures)] values = [ExprNodes.PyCFunctionNode.from_defnode(node, binding=True) for node in nodes] self.__signatures__ = ExprNodes.DictNode.from_pairs(self.pos, zip(keys, values)) self.specialized_pycfuncs = values for pycfuncnode in values: pycfuncnode.is_specialization = True def generate_function_definitions(self, env, code): if self.py_func: self.py_func.pymethdef_required = True self.fused_func_assignment.generate_function_definitions(env, code) from . import Options for stat in self.stats: if isinstance(stat, FuncDefNode) and ( stat.entry.used or (Options.cimport_from_pyx and not stat.entry.visibility == 'extern')): code.mark_pos(stat.pos) stat.generate_function_definitions(env, code) def generate_execution_code(self, code): # Note: all def function specialization are wrapped in PyCFunction # nodes in the self.__signatures__ dictnode. for default in self.defaults: if default is not None: default.generate_evaluation_code(code) if self.py_func: self.defaults_tuple.generate_evaluation_code(code) self.code_object.generate_evaluation_code(code) for stat in self.stats: code.mark_pos(stat.pos) if isinstance(stat, ExprNodes.ExprNode): stat.generate_evaluation_code(code) else: stat.generate_execution_code(code) if self.__signatures__: self.resulting_fused_function.generate_evaluation_code(code) code.putln( "((__pyx_FusedFunctionObject *) %s)->__signatures__ = %s;" % (self.resulting_fused_function.result(), self.__signatures__.result())) self.__signatures__.generate_giveref(code) self.__signatures__.generate_post_assignment_code(code) self.__signatures__.free_temps(code) self.fused_func_assignment.generate_execution_code(code) # Dispose of results self.resulting_fused_function.generate_disposal_code(code) self.resulting_fused_function.free_temps(code) self.defaults_tuple.generate_disposal_code(code) self.defaults_tuple.free_temps(code) self.code_object.generate_disposal_code(code) self.code_object.free_temps(code) for default in self.defaults: if default is not None: default.generate_disposal_code(code) default.free_temps(code) def annotate(self, code): for stat in self.stats: stat.annotate(code) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3167222 Cython-3.0.8/Cython/Compiler/Future.py0000644000175100001770000000116500000000000020441 0ustar00runnerdocker00000000000000def _get_feature(name): import __future__ # fall back to a unique fake object for earlier Python versions or Python 3 return getattr(__future__, name, object()) unicode_literals = _get_feature("unicode_literals") with_statement = _get_feature("with_statement") # dummy division = _get_feature("division") print_function = _get_feature("print_function") absolute_import = _get_feature("absolute_import") nested_scopes = _get_feature("nested_scopes") # dummy generators = _get_feature("generators") # dummy generator_stop = _get_feature("generator_stop") annotations = _get_feature("annotations") del _get_feature ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3167222 Cython-3.0.8/Cython/Compiler/Interpreter.py0000644000175100001770000000410200000000000021464 0ustar00runnerdocker00000000000000""" This module deals with interpreting the parse tree as Python would have done, in the compiler. For now this only covers parse tree to value conversion of compile-time values. """ from __future__ import absolute_import from .Nodes import * from .ExprNodes import * from .Errors import CompileError class EmptyScope(object): def lookup(self, name): return None empty_scope = EmptyScope() def interpret_compiletime_options(optlist, optdict, type_env=None, type_args=()): """ Tries to interpret a list of compile time option nodes. The result will be a tuple (optlist, optdict) but where all expression nodes have been interpreted. The result is in the form of tuples (value, pos). optlist is a list of nodes, while optdict is a DictNode (the result optdict is a dict) If type_env is set, all type nodes will be analysed and the resulting type set. Otherwise only interpretateable ExprNodes are allowed, other nodes raises errors. A CompileError will be raised if there are problems. """ def interpret(node, ix): if ix in type_args: if type_env: type = node.analyse_as_type(type_env) if not type: raise CompileError(node.pos, "Invalid type.") return (type, node.pos) else: raise CompileError(node.pos, "Type not allowed here.") else: if (sys.version_info[0] >=3 and isinstance(node, StringNode) and node.unicode_value is not None): return (node.unicode_value, node.pos) return (node.compile_time_value(empty_scope), node.pos) if optlist: optlist = [interpret(x, ix) for ix, x in enumerate(optlist)] if optdict: assert isinstance(optdict, DictNode) new_optdict = {} for item in optdict.key_value_pairs: new_key, dummy = interpret(item.key, None) new_optdict[new_key] = interpret(item.value, item.key.value) optdict = new_optdict return (optlist, new_optdict) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3167222 Cython-3.0.8/Cython/Compiler/Lexicon.py0000644000175100001770000005241400000000000020573 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*- # cython: language_level=3, py2_import=True # # Cython Scanner - Lexical Definitions # from __future__ import absolute_import, unicode_literals raw_prefixes = "rR" bytes_prefixes = "bB" string_prefixes = "fFuU" + bytes_prefixes char_prefixes = "cC" any_string_prefix = raw_prefixes + string_prefixes + char_prefixes IDENT = 'IDENT' def make_lexicon(): from ..Plex import \ Str, Any, AnyBut, AnyChar, Rep, Rep1, Opt, Bol, Eol, Eof, \ TEXT, IGNORE, Method, State, Lexicon, Range nonzero_digit = Any("123456789") digit = Any("0123456789") bindigit = Any("01") octdigit = Any("01234567") hexdigit = Any("0123456789ABCDEFabcdef") indentation = Bol + Rep(Any(" \t")) # The list of valid unicode identifier characters are pretty slow to generate at runtime, # and require Python3, so are just included directly here # (via the generated code block at the bottom of the file) unicode_start_character = (Any(unicode_start_ch_any) | Range(unicode_start_ch_range)) unicode_continuation_character = ( unicode_start_character | Any(unicode_continuation_ch_any) | Range(unicode_continuation_ch_range)) def underscore_digits(d): return Rep1(d) + Rep(Str("_") + Rep1(d)) def prefixed_digits(prefix, digits): return prefix + Opt(Str("_")) + underscore_digits(digits) decimal = underscore_digits(digit) dot = Str(".") exponent = Any("Ee") + Opt(Any("+-")) + decimal decimal_fract = (decimal + dot + Opt(decimal)) | (dot + decimal) #name = letter + Rep(letter | digit) name = unicode_start_character + Rep(unicode_continuation_character) intconst = (prefixed_digits(nonzero_digit, digit) | # decimal literals with underscores must not start with '0' (Str("0") + (prefixed_digits(Any("Xx"), hexdigit) | prefixed_digits(Any("Oo"), octdigit) | prefixed_digits(Any("Bb"), bindigit) )) | underscore_digits(Str('0')) # 0_0_0_0... is allowed as a decimal literal | Rep1(digit) # FIXME: remove these Py2 style decimal/octal literals (PY_VERSION_HEX < 3) ) intsuffix = (Opt(Any("Uu")) + Opt(Any("Ll")) + Opt(Any("Ll"))) | (Opt(Any("Ll")) + Opt(Any("Ll")) + Opt(Any("Uu"))) intliteral = intconst + intsuffix fltconst = (decimal_fract + Opt(exponent)) | (decimal + exponent) imagconst = (intconst | fltconst) + Any("jJ") # invalid combinations of prefixes are caught in p_string_literal beginstring = Opt(Rep(Any(string_prefixes + raw_prefixes)) | Any(char_prefixes) ) + (Str("'") | Str('"') | Str("'''") | Str('"""')) two_oct = octdigit + octdigit three_oct = octdigit + octdigit + octdigit two_hex = hexdigit + hexdigit four_hex = two_hex + two_hex escapeseq = Str("\\") + (two_oct | three_oct | Str('N{') + Rep(AnyBut('}')) + Str('}') | Str('u') + four_hex | Str('x') + two_hex | Str('U') + four_hex + four_hex | AnyChar) bra = Any("([{") ket = Any(")]}") ellipsis = Str("...") punct = Any(":,;+-*/|&<>=.%`~^?!@") diphthong = Str("==", "<>", "!=", "<=", ">=", "<<", ">>", "**", "//", "+=", "-=", "*=", "/=", "%=", "|=", "^=", "&=", "<<=", ">>=", "**=", "//=", "->", "@=", "&&", "||", ':=') spaces = Rep1(Any(" \t\f")) escaped_newline = Str("\\\n") lineterm = Eol + Opt(Str("\n")) comment = Str("#") + Rep(AnyBut("\n")) return Lexicon([ (name, Method('normalize_ident')), (intliteral, Method('strip_underscores', symbol='INT')), (fltconst, Method('strip_underscores', symbol='FLOAT')), (imagconst, Method('strip_underscores', symbol='IMAG')), (ellipsis | punct | diphthong, TEXT), (bra, Method('open_bracket_action')), (ket, Method('close_bracket_action')), (lineterm, Method('newline_action')), (beginstring, Method('begin_string_action')), (comment, IGNORE), (spaces, IGNORE), (escaped_newline, IGNORE), State('INDENT', [ (comment + lineterm, Method('commentline')), (Opt(spaces) + Opt(comment) + lineterm, IGNORE), (indentation, Method('indentation_action')), (Eof, Method('eof_action')) ]), State('SQ_STRING', [ (escapeseq, 'ESCAPE'), (Rep1(AnyBut("'\"\n\\")), 'CHARS'), (Str('"'), 'CHARS'), (Str("\n"), Method('unclosed_string_action')), (Str("'"), Method('end_string_action')), (Eof, 'EOF') ]), State('DQ_STRING', [ (escapeseq, 'ESCAPE'), (Rep1(AnyBut('"\n\\')), 'CHARS'), (Str("'"), 'CHARS'), (Str("\n"), Method('unclosed_string_action')), (Str('"'), Method('end_string_action')), (Eof, 'EOF') ]), State('TSQ_STRING', [ (escapeseq, 'ESCAPE'), (Rep1(AnyBut("'\"\n\\")), 'CHARS'), (Any("'\""), 'CHARS'), (Str("\n"), 'NEWLINE'), (Str("'''"), Method('end_string_action')), (Eof, 'EOF') ]), State('TDQ_STRING', [ (escapeseq, 'ESCAPE'), (Rep1(AnyBut('"\'\n\\')), 'CHARS'), (Any("'\""), 'CHARS'), (Str("\n"), 'NEWLINE'), (Str('"""'), Method('end_string_action')), (Eof, 'EOF') ]), (Eof, Method('eof_action')) ], # FIXME: Plex 1.9 needs different args here from Plex 1.1.4 #debug_flags = scanner_debug_flags, #debug_file = scanner_dump_file ) # BEGIN GENERATED CODE # Generated with 'cython-generate-lexicon.py' from: # cpython 3.12.0a7+ (heads/master:4cd1cc843a, Apr 11 2023, 10:32:26) [GCC 11.3.0] unicode_start_ch_any = ( u"\u005f\u00aa\u00b5\u00ba\u02ec\u02ee\u037f\u0386\u038c\u0559\u06d5" u"\u06ff\u0710\u07b1\u07fa\u081a\u0824\u0828\u093d\u0950\u09b2\u09bd" u"\u09ce\u09fc\u0a5e\u0abd\u0ad0\u0af9\u0b3d\u0b71\u0b83\u0b9c\u0bd0" u"\u0c3d\u0c5d\u0c80\u0cbd\u0d3d\u0d4e\u0dbd\u0e32\u0e84\u0ea5\u0eb2" u"\u0ebd\u0ec6\u0f00\u103f\u1061\u108e\u10c7\u10cd\u1258\u12c0\u17d7" u"\u17dc\u18aa\u1aa7\u1cfa\u1f59\u1f5b\u1f5d\u1fbe\u2071\u207f\u2102" u"\u2107\u2115\u2124\u2126\u2128\u214e\u2d27\u2d2d\u2d6f\ua7d3\ua8fb" u"\ua9cf\uaa7a\uaab1\uaac0\uaac2\ufb1d\ufb3e\ufe71\ufe73\ufe77\ufe79" u"\ufe7b\ufe7d\U00010808\U0001083c\U00010a00\U00010f27\U00011075\U00011144\U00011147\U00011176\U000111da" u"\U000111dc\U00011288\U0001133d\U00011350\U000114c7\U00011644\U000116b8\U00011909\U0001193f\U00011941\U000119e1" u"\U000119e3\U00011a00\U00011a3a\U00011a50\U00011a9d\U00011c40\U00011d46\U00011d98\U00011f02\U00011fb0\U00016f50" u"\U00016fe3\U0001b132\U0001b155\U0001d4a2\U0001d4bb\U0001d546\U0001e14e\U0001e94b\U0001ee24\U0001ee27\U0001ee39" u"\U0001ee3b\U0001ee42\U0001ee47\U0001ee49\U0001ee4b\U0001ee54\U0001ee57\U0001ee59\U0001ee5b\U0001ee5d\U0001ee5f" u"\U0001ee64\U0001ee7e" ) unicode_start_ch_range = ( u"\u0041\u005a\u0061\u007a\u00c0\u00d6\u00d8\u00f6\u00f8\u02c1\u02c6" u"\u02d1\u02e0\u02e4\u0370\u0374\u0376\u0377\u037b\u037d\u0388\u038a" u"\u038e\u03a1\u03a3\u03f5\u03f7\u0481\u048a\u052f\u0531\u0556\u0560" u"\u0588\u05d0\u05ea\u05ef\u05f2\u0620\u064a\u066e\u066f\u0671\u06d3" u"\u06e5\u06e6\u06ee\u06ef\u06fa\u06fc\u0712\u072f\u074d\u07a5\u07ca" u"\u07ea\u07f4\u07f5\u0800\u0815\u0840\u0858\u0860\u086a\u0870\u0887" u"\u0889\u088e\u08a0\u08c9\u0904\u0939\u0958\u0961\u0971\u0980\u0985" u"\u098c\u098f\u0990\u0993\u09a8\u09aa\u09b0\u09b6\u09b9\u09dc\u09dd" u"\u09df\u09e1\u09f0\u09f1\u0a05\u0a0a\u0a0f\u0a10\u0a13\u0a28\u0a2a" u"\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59\u0a5c\u0a72\u0a74" u"\u0a85\u0a8d\u0a8f\u0a91\u0a93\u0aa8\u0aaa\u0ab0\u0ab2\u0ab3\u0ab5" u"\u0ab9\u0ae0\u0ae1\u0b05\u0b0c\u0b0f\u0b10\u0b13\u0b28\u0b2a\u0b30" u"\u0b32\u0b33\u0b35\u0b39\u0b5c\u0b5d\u0b5f\u0b61\u0b85\u0b8a\u0b8e" u"\u0b90\u0b92\u0b95\u0b99\u0b9a\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8\u0baa" u"\u0bae\u0bb9\u0c05\u0c0c\u0c0e\u0c10\u0c12\u0c28\u0c2a\u0c39\u0c58" u"\u0c5a\u0c60\u0c61\u0c85\u0c8c\u0c8e\u0c90\u0c92\u0ca8\u0caa\u0cb3" u"\u0cb5\u0cb9\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04\u0d0c\u0d0e" u"\u0d10\u0d12\u0d3a\u0d54\u0d56\u0d5f\u0d61\u0d7a\u0d7f\u0d85\u0d96" u"\u0d9a\u0db1\u0db3\u0dbb\u0dc0\u0dc6\u0e01\u0e30\u0e40\u0e46\u0e81" u"\u0e82\u0e86\u0e8a\u0e8c\u0ea3\u0ea7\u0eb0\u0ec0\u0ec4\u0edc\u0edf" u"\u0f40\u0f47\u0f49\u0f6c\u0f88\u0f8c\u1000\u102a\u1050\u1055\u105a" u"\u105d\u1065\u1066\u106e\u1070\u1075\u1081\u10a0\u10c5\u10d0\u10fa" u"\u10fc\u1248\u124a\u124d\u1250\u1256\u125a\u125d\u1260\u1288\u128a" u"\u128d\u1290\u12b0\u12b2\u12b5\u12b8\u12be\u12c2\u12c5\u12c8\u12d6" u"\u12d8\u1310\u1312\u1315\u1318\u135a\u1380\u138f\u13a0\u13f5\u13f8" u"\u13fd\u1401\u166c\u166f\u167f\u1681\u169a\u16a0\u16ea\u16ee\u16f8" u"\u1700\u1711\u171f\u1731\u1740\u1751\u1760\u176c\u176e\u1770\u1780" u"\u17b3\u1820\u1878\u1880\u18a8\u18b0\u18f5\u1900\u191e\u1950\u196d" u"\u1970\u1974\u1980\u19ab\u19b0\u19c9\u1a00\u1a16\u1a20\u1a54\u1b05" u"\u1b33\u1b45\u1b4c\u1b83\u1ba0\u1bae\u1baf\u1bba\u1be5\u1c00\u1c23" u"\u1c4d\u1c4f\u1c5a\u1c7d\u1c80\u1c88\u1c90\u1cba\u1cbd\u1cbf\u1ce9" u"\u1cec\u1cee\u1cf3\u1cf5\u1cf6\u1d00\u1dbf\u1e00\u1f15\u1f18\u1f1d" u"\u1f20\u1f45\u1f48\u1f4d\u1f50\u1f57\u1f5f\u1f7d\u1f80\u1fb4\u1fb6" u"\u1fbc\u1fc2\u1fc4\u1fc6\u1fcc\u1fd0\u1fd3\u1fd6\u1fdb\u1fe0\u1fec" u"\u1ff2\u1ff4\u1ff6\u1ffc\u2090\u209c\u210a\u2113\u2118\u211d\u212a" u"\u2139\u213c\u213f\u2145\u2149\u2160\u2188\u2c00\u2ce4\u2ceb\u2cee" u"\u2cf2\u2cf3\u2d00\u2d25\u2d30\u2d67\u2d80\u2d96\u2da0\u2da6\u2da8" u"\u2dae\u2db0\u2db6\u2db8\u2dbe\u2dc0\u2dc6\u2dc8\u2dce\u2dd0\u2dd6" u"\u2dd8\u2dde\u3005\u3007\u3021\u3029\u3031\u3035\u3038\u303c\u3041" u"\u3096\u309d\u309f\u30a1\u30fa\u30fc\u30ff\u3105\u312f\u3131\u318e" u"\u31a0\u31bf\u31f0\u31ff\u3400\u4dbf\u4e00\ua48c\ua4d0\ua4fd\ua500" u"\ua60c\ua610\ua61f\ua62a\ua62b\ua640\ua66e\ua67f\ua69d\ua6a0\ua6ef" u"\ua717\ua71f\ua722\ua788\ua78b\ua7ca\ua7d0\ua7d1\ua7d5\ua7d9\ua7f2" u"\ua801\ua803\ua805\ua807\ua80a\ua80c\ua822\ua840\ua873\ua882\ua8b3" u"\ua8f2\ua8f7\ua8fd\ua8fe\ua90a\ua925\ua930\ua946\ua960\ua97c\ua984" u"\ua9b2\ua9e0\ua9e4\ua9e6\ua9ef\ua9fa\ua9fe\uaa00\uaa28\uaa40\uaa42" u"\uaa44\uaa4b\uaa60\uaa76\uaa7e\uaaaf\uaab5\uaab6\uaab9\uaabd\uaadb" u"\uaadd\uaae0\uaaea\uaaf2\uaaf4\uab01\uab06\uab09\uab0e\uab11\uab16" u"\uab20\uab26\uab28\uab2e\uab30\uab5a\uab5c\uab69\uab70\uabe2\uac00" u"\ud7a3\ud7b0\ud7c6\ud7cb\ud7fb\uf900\ufa6d\ufa70\ufad9\ufb00\ufb06" u"\ufb13\ufb17\ufb1f\ufb28\ufb2a\ufb36\ufb38\ufb3c\ufb40\ufb41\ufb43" u"\ufb44\ufb46\ufbb1\ufbd3\ufc5d\ufc64\ufd3d\ufd50\ufd8f\ufd92\ufdc7" u"\ufdf0\ufdf9\ufe7f\ufefc\uff21\uff3a\uff41\uff5a\uff66\uff9d\uffa0" u"\uffbe\uffc2\uffc7\uffca\uffcf\uffd2\uffd7\uffda\uffdc\U00010000\U0001000b" u"\U0001000d\U00010026\U00010028\U0001003a\U0001003c\U0001003d\U0001003f\U0001004d\U00010050\U0001005d\U00010080" u"\U000100fa\U00010140\U00010174\U00010280\U0001029c\U000102a0\U000102d0\U00010300\U0001031f\U0001032d\U0001034a" u"\U00010350\U00010375\U00010380\U0001039d\U000103a0\U000103c3\U000103c8\U000103cf\U000103d1\U000103d5\U00010400" u"\U0001049d\U000104b0\U000104d3\U000104d8\U000104fb\U00010500\U00010527\U00010530\U00010563\U00010570\U0001057a" u"\U0001057c\U0001058a\U0001058c\U00010592\U00010594\U00010595\U00010597\U000105a1\U000105a3\U000105b1\U000105b3" u"\U000105b9\U000105bb\U000105bc\U00010600\U00010736\U00010740\U00010755\U00010760\U00010767\U00010780\U00010785" u"\U00010787\U000107b0\U000107b2\U000107ba\U00010800\U00010805\U0001080a\U00010835\U00010837\U00010838\U0001083f" u"\U00010855\U00010860\U00010876\U00010880\U0001089e\U000108e0\U000108f2\U000108f4\U000108f5\U00010900\U00010915" u"\U00010920\U00010939\U00010980\U000109b7\U000109be\U000109bf\U00010a10\U00010a13\U00010a15\U00010a17\U00010a19" u"\U00010a35\U00010a60\U00010a7c\U00010a80\U00010a9c\U00010ac0\U00010ac7\U00010ac9\U00010ae4\U00010b00\U00010b35" u"\U00010b40\U00010b55\U00010b60\U00010b72\U00010b80\U00010b91\U00010c00\U00010c48\U00010c80\U00010cb2\U00010cc0" u"\U00010cf2\U00010d00\U00010d23\U00010e80\U00010ea9\U00010eb0\U00010eb1\U00010f00\U00010f1c\U00010f30\U00010f45" u"\U00010f70\U00010f81\U00010fb0\U00010fc4\U00010fe0\U00010ff6\U00011003\U00011037\U00011071\U00011072\U00011083" u"\U000110af\U000110d0\U000110e8\U00011103\U00011126\U00011150\U00011172\U00011183\U000111b2\U000111c1\U000111c4" u"\U00011200\U00011211\U00011213\U0001122b\U0001123f\U00011240\U00011280\U00011286\U0001128a\U0001128d\U0001128f" u"\U0001129d\U0001129f\U000112a8\U000112b0\U000112de\U00011305\U0001130c\U0001130f\U00011310\U00011313\U00011328" u"\U0001132a\U00011330\U00011332\U00011333\U00011335\U00011339\U0001135d\U00011361\U00011400\U00011434\U00011447" u"\U0001144a\U0001145f\U00011461\U00011480\U000114af\U000114c4\U000114c5\U00011580\U000115ae\U000115d8\U000115db" u"\U00011600\U0001162f\U00011680\U000116aa\U00011700\U0001171a\U00011740\U00011746\U00011800\U0001182b\U000118a0" u"\U000118df\U000118ff\U00011906\U0001190c\U00011913\U00011915\U00011916\U00011918\U0001192f\U000119a0\U000119a7" u"\U000119aa\U000119d0\U00011a0b\U00011a32\U00011a5c\U00011a89\U00011ab0\U00011af8\U00011c00\U00011c08\U00011c0a" u"\U00011c2e\U00011c72\U00011c8f\U00011d00\U00011d06\U00011d08\U00011d09\U00011d0b\U00011d30\U00011d60\U00011d65" u"\U00011d67\U00011d68\U00011d6a\U00011d89\U00011ee0\U00011ef2\U00011f04\U00011f10\U00011f12\U00011f33\U00012000" u"\U00012399\U00012400\U0001246e\U00012480\U00012543\U00012f90\U00012ff0\U00013000\U0001342f\U00013441\U00013446" u"\U00014400\U00014646\U00016800\U00016a38\U00016a40\U00016a5e\U00016a70\U00016abe\U00016ad0\U00016aed\U00016b00" u"\U00016b2f\U00016b40\U00016b43\U00016b63\U00016b77\U00016b7d\U00016b8f\U00016e40\U00016e7f\U00016f00\U00016f4a" u"\U00016f93\U00016f9f\U00016fe0\U00016fe1\U00017000\U000187f7\U00018800\U00018cd5\U00018d00\U00018d08\U0001aff0" u"\U0001aff3\U0001aff5\U0001affb\U0001affd\U0001affe\U0001b000\U0001b122\U0001b150\U0001b152\U0001b164\U0001b167" u"\U0001b170\U0001b2fb\U0001bc00\U0001bc6a\U0001bc70\U0001bc7c\U0001bc80\U0001bc88\U0001bc90\U0001bc99\U0001d400" u"\U0001d454\U0001d456\U0001d49c\U0001d49e\U0001d49f\U0001d4a5\U0001d4a6\U0001d4a9\U0001d4ac\U0001d4ae\U0001d4b9" u"\U0001d4bd\U0001d4c3\U0001d4c5\U0001d505\U0001d507\U0001d50a\U0001d50d\U0001d514\U0001d516\U0001d51c\U0001d51e" u"\U0001d539\U0001d53b\U0001d53e\U0001d540\U0001d544\U0001d54a\U0001d550\U0001d552\U0001d6a5\U0001d6a8\U0001d6c0" u"\U0001d6c2\U0001d6da\U0001d6dc\U0001d6fa\U0001d6fc\U0001d714\U0001d716\U0001d734\U0001d736\U0001d74e\U0001d750" u"\U0001d76e\U0001d770\U0001d788\U0001d78a\U0001d7a8\U0001d7aa\U0001d7c2\U0001d7c4\U0001d7cb\U0001df00\U0001df1e" u"\U0001df25\U0001df2a\U0001e030\U0001e06d\U0001e100\U0001e12c\U0001e137\U0001e13d\U0001e290\U0001e2ad\U0001e2c0" u"\U0001e2eb\U0001e4d0\U0001e4eb\U0001e7e0\U0001e7e6\U0001e7e8\U0001e7eb\U0001e7ed\U0001e7ee\U0001e7f0\U0001e7fe" u"\U0001e800\U0001e8c4\U0001e900\U0001e943\U0001ee00\U0001ee03\U0001ee05\U0001ee1f\U0001ee21\U0001ee22\U0001ee29" u"\U0001ee32\U0001ee34\U0001ee37\U0001ee4d\U0001ee4f\U0001ee51\U0001ee52\U0001ee61\U0001ee62\U0001ee67\U0001ee6a" u"\U0001ee6c\U0001ee72\U0001ee74\U0001ee77\U0001ee79\U0001ee7c\U0001ee80\U0001ee89\U0001ee8b\U0001ee9b\U0001eea1" u"\U0001eea3\U0001eea5\U0001eea9\U0001eeab\U0001eebb\U00020000\U0002a6df\U0002a700\U0002b739\U0002b740\U0002b81d" u"\U0002b820\U0002cea1\U0002ceb0\U0002ebe0\U0002f800\U0002fa1d\U00030000\U0003134a" ) unicode_continuation_ch_any = ( u"\u00b7\u0387\u05bf\u05c7\u0670\u0711\u07fd\u09bc\u09d7\u09fe\u0a3c" u"\u0a51\u0a75\u0abc\u0b3c\u0b82\u0bd7\u0c3c\u0cbc\u0cf3\u0d57\u0dca" u"\u0dd6\u0e31\u0eb1\u0f35\u0f37\u0f39\u0fc6\u17dd\u18a9\u1ced\u1cf4" u"\u2054\u20e1\u2d7f\ua66f\ua802\ua806\ua80b\ua82c\ua9e5\uaa43\uaab0" u"\uaac1\ufb1e\uff3f\U000101fd\U000102e0\U00010a3f\U000110c2\U00011173\U0001123e\U00011241\U00011357" u"\U0001145e\U00011940\U000119e4\U00011a47\U00011d3a\U00011d47\U00011f03\U00013440\U00016f4f\U00016fe4\U0001da75" u"\U0001da84\U0001e08f\U0001e2ae" ) unicode_continuation_ch_range = ( u"\u0030\u0039\u0300\u036f\u0483\u0487\u0591\u05bd\u05c1\u05c2\u05c4" u"\u05c5\u0610\u061a\u064b\u0669\u06d6\u06dc\u06df\u06e4\u06e7\u06e8" u"\u06ea\u06ed\u06f0\u06f9\u0730\u074a\u07a6\u07b0\u07c0\u07c9\u07eb" u"\u07f3\u0816\u0819\u081b\u0823\u0825\u0827\u0829\u082d\u0859\u085b" u"\u0898\u089f\u08ca\u08e1\u08e3\u0903\u093a\u093c\u093e\u094f\u0951" u"\u0957\u0962\u0963\u0966\u096f\u0981\u0983\u09be\u09c4\u09c7\u09c8" u"\u09cb\u09cd\u09e2\u09e3\u09e6\u09ef\u0a01\u0a03\u0a3e\u0a42\u0a47" u"\u0a48\u0a4b\u0a4d\u0a66\u0a71\u0a81\u0a83\u0abe\u0ac5\u0ac7\u0ac9" u"\u0acb\u0acd\u0ae2\u0ae3\u0ae6\u0aef\u0afa\u0aff\u0b01\u0b03\u0b3e" u"\u0b44\u0b47\u0b48\u0b4b\u0b4d\u0b55\u0b57\u0b62\u0b63\u0b66\u0b6f" u"\u0bbe\u0bc2\u0bc6\u0bc8\u0bca\u0bcd\u0be6\u0bef\u0c00\u0c04\u0c3e" u"\u0c44\u0c46\u0c48\u0c4a\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66\u0c6f" u"\u0c81\u0c83\u0cbe\u0cc4\u0cc6\u0cc8\u0cca\u0ccd\u0cd5\u0cd6\u0ce2" u"\u0ce3\u0ce6\u0cef\u0d00\u0d03\u0d3b\u0d3c\u0d3e\u0d44\u0d46\u0d48" u"\u0d4a\u0d4d\u0d62\u0d63\u0d66\u0d6f\u0d81\u0d83\u0dcf\u0dd4\u0dd8" u"\u0ddf\u0de6\u0def\u0df2\u0df3\u0e33\u0e3a\u0e47\u0e4e\u0e50\u0e59" u"\u0eb3\u0ebc\u0ec8\u0ece\u0ed0\u0ed9\u0f18\u0f19\u0f20\u0f29\u0f3e" u"\u0f3f\u0f71\u0f84\u0f86\u0f87\u0f8d\u0f97\u0f99\u0fbc\u102b\u103e" u"\u1040\u1049\u1056\u1059\u105e\u1060\u1062\u1064\u1067\u106d\u1071" u"\u1074\u1082\u108d\u108f\u109d\u135d\u135f\u1369\u1371\u1712\u1715" u"\u1732\u1734\u1752\u1753\u1772\u1773\u17b4\u17d3\u17e0\u17e9\u180b" u"\u180d\u180f\u1819\u1920\u192b\u1930\u193b\u1946\u194f\u19d0\u19da" u"\u1a17\u1a1b\u1a55\u1a5e\u1a60\u1a7c\u1a7f\u1a89\u1a90\u1a99\u1ab0" u"\u1abd\u1abf\u1ace\u1b00\u1b04\u1b34\u1b44\u1b50\u1b59\u1b6b\u1b73" u"\u1b80\u1b82\u1ba1\u1bad\u1bb0\u1bb9\u1be6\u1bf3\u1c24\u1c37\u1c40" u"\u1c49\u1c50\u1c59\u1cd0\u1cd2\u1cd4\u1ce8\u1cf7\u1cf9\u1dc0\u1dff" u"\u203f\u2040\u20d0\u20dc\u20e5\u20f0\u2cef\u2cf1\u2de0\u2dff\u302a" u"\u302f\u3099\u309a\ua620\ua629\ua674\ua67d\ua69e\ua69f\ua6f0\ua6f1" u"\ua823\ua827\ua880\ua881\ua8b4\ua8c5\ua8d0\ua8d9\ua8e0\ua8f1\ua8ff" u"\ua909\ua926\ua92d\ua947\ua953\ua980\ua983\ua9b3\ua9c0\ua9d0\ua9d9" u"\ua9f0\ua9f9\uaa29\uaa36\uaa4c\uaa4d\uaa50\uaa59\uaa7b\uaa7d\uaab2" u"\uaab4\uaab7\uaab8\uaabe\uaabf\uaaeb\uaaef\uaaf5\uaaf6\uabe3\uabea" u"\uabec\uabed\uabf0\uabf9\ufe00\ufe0f\ufe20\ufe2f\ufe33\ufe34\ufe4d" u"\ufe4f\uff10\uff19\uff9e\uff9f\U00010376\U0001037a\U000104a0\U000104a9\U00010a01\U00010a03" u"\U00010a05\U00010a06\U00010a0c\U00010a0f\U00010a38\U00010a3a\U00010ae5\U00010ae6\U00010d24\U00010d27\U00010d30" u"\U00010d39\U00010eab\U00010eac\U00010efd\U00010eff\U00010f46\U00010f50\U00010f82\U00010f85\U00011000\U00011002" u"\U00011038\U00011046\U00011066\U00011070\U00011073\U00011074\U0001107f\U00011082\U000110b0\U000110ba\U000110f0" u"\U000110f9\U00011100\U00011102\U00011127\U00011134\U00011136\U0001113f\U00011145\U00011146\U00011180\U00011182" u"\U000111b3\U000111c0\U000111c9\U000111cc\U000111ce\U000111d9\U0001122c\U00011237\U000112df\U000112ea\U000112f0" u"\U000112f9\U00011300\U00011303\U0001133b\U0001133c\U0001133e\U00011344\U00011347\U00011348\U0001134b\U0001134d" u"\U00011362\U00011363\U00011366\U0001136c\U00011370\U00011374\U00011435\U00011446\U00011450\U00011459\U000114b0" u"\U000114c3\U000114d0\U000114d9\U000115af\U000115b5\U000115b8\U000115c0\U000115dc\U000115dd\U00011630\U00011640" u"\U00011650\U00011659\U000116ab\U000116b7\U000116c0\U000116c9\U0001171d\U0001172b\U00011730\U00011739\U0001182c" u"\U0001183a\U000118e0\U000118e9\U00011930\U00011935\U00011937\U00011938\U0001193b\U0001193e\U00011942\U00011943" u"\U00011950\U00011959\U000119d1\U000119d7\U000119da\U000119e0\U00011a01\U00011a0a\U00011a33\U00011a39\U00011a3b" u"\U00011a3e\U00011a51\U00011a5b\U00011a8a\U00011a99\U00011c2f\U00011c36\U00011c38\U00011c3f\U00011c50\U00011c59" u"\U00011c92\U00011ca7\U00011ca9\U00011cb6\U00011d31\U00011d36\U00011d3c\U00011d3d\U00011d3f\U00011d45\U00011d50" u"\U00011d59\U00011d8a\U00011d8e\U00011d90\U00011d91\U00011d93\U00011d97\U00011da0\U00011da9\U00011ef3\U00011ef6" u"\U00011f00\U00011f01\U00011f34\U00011f3a\U00011f3e\U00011f42\U00011f50\U00011f59\U00013447\U00013455\U00016a60" u"\U00016a69\U00016ac0\U00016ac9\U00016af0\U00016af4\U00016b30\U00016b36\U00016b50\U00016b59\U00016f51\U00016f87" u"\U00016f8f\U00016f92\U00016ff0\U00016ff1\U0001bc9d\U0001bc9e\U0001cf00\U0001cf2d\U0001cf30\U0001cf46\U0001d165" u"\U0001d169\U0001d16d\U0001d172\U0001d17b\U0001d182\U0001d185\U0001d18b\U0001d1aa\U0001d1ad\U0001d242\U0001d244" u"\U0001d7ce\U0001d7ff\U0001da00\U0001da36\U0001da3b\U0001da6c\U0001da9b\U0001da9f\U0001daa1\U0001daaf\U0001e000" u"\U0001e006\U0001e008\U0001e018\U0001e01b\U0001e021\U0001e023\U0001e024\U0001e026\U0001e02a\U0001e130\U0001e136" u"\U0001e140\U0001e149\U0001e2ec\U0001e2f9\U0001e4ec\U0001e4f9\U0001e8d0\U0001e8d6\U0001e944\U0001e94a\U0001e950" u"\U0001e959\U0001fbf0\U0001fbf9" ) # END GENERATED CODE ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3167222 Cython-3.0.8/Cython/Compiler/Main.py0000644000175100001770000007671500000000000020070 0ustar00runnerdocker00000000000000# # Cython Top Level # from __future__ import absolute_import, print_function import os import re import sys import io if sys.version_info[:2] < (2, 7) or (3, 0) <= sys.version_info[:2] < (3, 3): sys.stderr.write("Sorry, Cython requires Python 2.7 or 3.3+, found %d.%d\n" % tuple(sys.version_info[:2])) sys.exit(1) try: from __builtin__ import basestring except ImportError: basestring = str # Do not import Parsing here, import it when needed, because Parsing imports # Nodes, which globally needs debug command line options initialized to set a # conditional metaclass. These options are processed by CmdLine called from # main() in this file. # import Parsing from . import Errors from .StringEncoding import EncodedString from .Scanning import PyrexScanner, FileSourceDescriptor from .Errors import PyrexError, CompileError, error, warning from .Symtab import ModuleScope from .. import Utils from . import Options from .Options import CompilationOptions, default_options from .CmdLine import parse_command_line from .Lexicon import (unicode_start_ch_any, unicode_continuation_ch_any, unicode_start_ch_range, unicode_continuation_ch_range) def _make_range_re(chrs): out = [] for i in range(0, len(chrs), 2): out.append(u"{0}-{1}".format(chrs[i], chrs[i+1])) return u"".join(out) # py2 version looked like r"[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$" module_name_pattern = u"[{0}{1}][{0}{2}{1}{3}]*".format( unicode_start_ch_any, _make_range_re(unicode_start_ch_range), unicode_continuation_ch_any, _make_range_re(unicode_continuation_ch_range)) module_name_pattern = re.compile(u"{0}(\\.{0})*$".format(module_name_pattern)) standard_include_path = os.path.abspath( os.path.join(os.path.dirname(os.path.dirname(__file__)), 'Includes')) class Context(object): # This class encapsulates the context needed for compiling # one or more Cython implementation files along with their # associated and imported declaration files. It includes # the root of the module import namespace and the list # of directories to search for include files. # # modules {string : ModuleScope} # include_directories [string] # future_directives [object] # language_level int currently 2 or 3 for Python 2/3 cython_scope = None language_level = None # warn when not set but default to Py2 def __init__(self, include_directories, compiler_directives, cpp=False, language_level=None, options=None): # cython_scope is a hack, set to False by subclasses, in order to break # an infinite loop. # Better code organization would fix it. from . import Builtin, CythonScope self.modules = {"__builtin__" : Builtin.builtin_scope} self.cython_scope = CythonScope.create_cython_scope(self) self.modules["cython"] = self.cython_scope self.include_directories = include_directories self.future_directives = set() self.compiler_directives = compiler_directives self.cpp = cpp self.options = options self.pxds = {} # full name -> node tree self._interned = {} # (type(value), value, *key_args) -> interned_value if language_level is not None: self.set_language_level(language_level) self.legacy_implicit_noexcept = self.compiler_directives.get('legacy_implicit_noexcept', False) self.gdb_debug_outputwriter = None @classmethod def from_options(cls, options): return cls(options.include_path, options.compiler_directives, options.cplus, options.language_level, options=options) def set_language_level(self, level): from .Future import print_function, unicode_literals, absolute_import, division, generator_stop future_directives = set() if level == '3str': level = 3 else: level = int(level) if level >= 3: future_directives.add(unicode_literals) if level >= 3: future_directives.update([print_function, absolute_import, division, generator_stop]) self.language_level = level self.future_directives = future_directives if level >= 3: self.modules['builtins'] = self.modules['__builtin__'] def intern_ustring(self, value, encoding=None): key = (EncodedString, value, encoding) try: return self._interned[key] except KeyError: pass value = EncodedString(value) if encoding: value.encoding = encoding self._interned[key] = value return value # pipeline creation functions can now be found in Pipeline.py def process_pxd(self, source_desc, scope, module_name): from . import Pipeline if isinstance(source_desc, FileSourceDescriptor) and source_desc._file_type == 'pyx': source = CompilationSource(source_desc, module_name, os.getcwd()) result_sink = create_default_resultobj(source, self.options) pipeline = Pipeline.create_pyx_as_pxd_pipeline(self, result_sink) result = Pipeline.run_pipeline(pipeline, source) else: pipeline = Pipeline.create_pxd_pipeline(self, scope, module_name) result = Pipeline.run_pipeline(pipeline, source_desc) return result def nonfatal_error(self, exc): return Errors.report_error(exc) def _split_qualified_name(self, qualified_name, relative_import=False): # Splits qualified_name into parts in form of 2-tuples: (PART_NAME, IS_PACKAGE). qualified_name_parts = qualified_name.split('.') last_part = qualified_name_parts.pop() qualified_name_parts = [(p, True) for p in qualified_name_parts] if last_part != '__init__': # If Last part is __init__, then it is omitted. Otherwise, we need to check whether we can find # __init__.pyx/__init__.py file to determine if last part is package or not. is_package = False for suffix in ('.py', '.pyx'): path = self.search_include_directories( qualified_name, suffix=suffix, source_pos=None, source_file_path=None, sys_path=not relative_import) if path: is_package = self._is_init_file(path) break qualified_name_parts.append((last_part, is_package)) return qualified_name_parts @staticmethod def _is_init_file(path): return os.path.basename(path) in ('__init__.pyx', '__init__.py', '__init__.pxd') if path else False @staticmethod def _check_pxd_filename(pos, pxd_pathname, qualified_name): if not pxd_pathname: return pxd_filename = os.path.basename(pxd_pathname) if '.' in qualified_name and qualified_name == os.path.splitext(pxd_filename)[0]: warning(pos, "Dotted filenames ('%s') are deprecated." " Please use the normal Python package directory layout." % pxd_filename, level=1) def find_module(self, module_name, from_module=None, pos=None, need_pxd=1, absolute_fallback=True, relative_import=False): # Finds and returns the module scope corresponding to # the given relative or absolute module name. If this # is the first time the module has been requested, finds # the corresponding .pxd file and process it. # If from_module is not None, it must be a module scope, # and the module will first be searched for relative to # that module, provided its name is not a dotted name. debug_find_module = 0 if debug_find_module: print("Context.find_module: module_name = %s, from_module = %s, pos = %s, need_pxd = %s" % ( module_name, from_module, pos, need_pxd)) scope = None pxd_pathname = None if from_module: if module_name: # from .module import ... qualified_name = from_module.qualify_name(module_name) else: # from . import ... qualified_name = from_module.qualified_name scope = from_module from_module = None else: qualified_name = module_name if not module_name_pattern.match(qualified_name): raise CompileError(pos or (module_name, 0, 0), u"'%s' is not a valid module name" % module_name) if from_module: if debug_find_module: print("...trying relative import") scope = from_module.lookup_submodule(module_name) if not scope: pxd_pathname = self.find_pxd_file(qualified_name, pos, sys_path=not relative_import) self._check_pxd_filename(pos, pxd_pathname, qualified_name) if pxd_pathname: is_package = self._is_init_file(pxd_pathname) scope = from_module.find_submodule(module_name, as_package=is_package) if not scope: if debug_find_module: print("...trying absolute import") if absolute_fallback: qualified_name = module_name scope = self for name, is_package in self._split_qualified_name(qualified_name, relative_import=relative_import): scope = scope.find_submodule(name, as_package=is_package) if debug_find_module: print("...scope = %s" % scope) if not scope.pxd_file_loaded: if debug_find_module: print("...pxd not loaded") if not pxd_pathname: if debug_find_module: print("...looking for pxd file") # Only look in sys.path if we are explicitly looking # for a .pxd file. pxd_pathname = self.find_pxd_file(qualified_name, pos, sys_path=need_pxd and not relative_import) self._check_pxd_filename(pos, pxd_pathname, qualified_name) if debug_find_module: print("......found %s" % pxd_pathname) if not pxd_pathname and need_pxd: # Set pxd_file_loaded such that we don't need to # look for the non-existing pxd file next time. scope.pxd_file_loaded = True package_pathname = self.search_include_directories( qualified_name, suffix=".py", source_pos=pos, sys_path=not relative_import) if package_pathname and package_pathname.endswith(Utils.PACKAGE_FILES): pass else: error(pos, "'%s.pxd' not found" % qualified_name.replace('.', os.sep)) if pxd_pathname: scope.pxd_file_loaded = True try: if debug_find_module: print("Context.find_module: Parsing %s" % pxd_pathname) rel_path = module_name.replace('.', os.sep) + os.path.splitext(pxd_pathname)[1] if not pxd_pathname.endswith(rel_path): rel_path = pxd_pathname # safety measure to prevent printing incorrect paths source_desc = FileSourceDescriptor(pxd_pathname, rel_path) err, result = self.process_pxd(source_desc, scope, qualified_name) if err: raise err (pxd_codenodes, pxd_scope) = result self.pxds[module_name] = (pxd_codenodes, pxd_scope) except CompileError: pass return scope def find_pxd_file(self, qualified_name, pos=None, sys_path=True, source_file_path=None): # Search include path (and sys.path if sys_path is True) for # the .pxd file corresponding to the given fully-qualified # module name. # Will find either a dotted filename or a file in a # package directory. If a source file position is given, # the directory containing the source file is searched first # for a dotted filename, and its containing package root # directory is searched first for a non-dotted filename. pxd = self.search_include_directories( qualified_name, suffix=".pxd", source_pos=pos, sys_path=sys_path, source_file_path=source_file_path) if pxd is None and Options.cimport_from_pyx: return self.find_pyx_file(qualified_name, pos, sys_path=sys_path) return pxd def find_pyx_file(self, qualified_name, pos=None, sys_path=True, source_file_path=None): # Search include path for the .pyx file corresponding to the # given fully-qualified module name, as for find_pxd_file(). return self.search_include_directories( qualified_name, suffix=".pyx", source_pos=pos, sys_path=sys_path, source_file_path=source_file_path) def find_include_file(self, filename, pos=None, source_file_path=None): # Search list of include directories for filename. # Reports an error and returns None if not found. path = self.search_include_directories( filename, source_pos=pos, include=True, source_file_path=source_file_path) if not path: error(pos, "'%s' not found" % filename) return path def search_include_directories(self, qualified_name, suffix=None, source_pos=None, include=False, sys_path=False, source_file_path=None): include_dirs = self.include_directories if sys_path: include_dirs = include_dirs + sys.path # include_dirs must be hashable for caching in @cached_function include_dirs = tuple(include_dirs + [standard_include_path]) return search_include_directories( include_dirs, qualified_name, suffix or "", source_pos, include, source_file_path) def find_root_package_dir(self, file_path): return Utils.find_root_package_dir(file_path) def check_package_dir(self, dir, package_names): return Utils.check_package_dir(dir, tuple(package_names)) def c_file_out_of_date(self, source_path, output_path): if not os.path.exists(output_path): return 1 c_time = Utils.modification_time(output_path) if Utils.file_newer_than(source_path, c_time): return 1 pxd_path = Utils.replace_suffix(source_path, ".pxd") if os.path.exists(pxd_path) and Utils.file_newer_than(pxd_path, c_time): return 1 for kind, name in self.read_dependency_file(source_path): if kind == "cimport": dep_path = self.find_pxd_file(name, source_file_path=source_path) elif kind == "include": dep_path = self.search_include_directories(name, source_file_path=source_path) else: continue if dep_path and Utils.file_newer_than(dep_path, c_time): return 1 return 0 def find_cimported_module_names(self, source_path): return [ name for kind, name in self.read_dependency_file(source_path) if kind == "cimport" ] def is_package_dir(self, dir_path): return Utils.is_package_dir(dir_path) def read_dependency_file(self, source_path): dep_path = Utils.replace_suffix(source_path, ".dep") if os.path.exists(dep_path): with open(dep_path, "rU") as f: chunks = [ line.split(" ", 1) for line in (l.strip() for l in f) if " " in line ] return chunks else: return () def lookup_submodule(self, name): # Look up a top-level module. Returns None if not found. return self.modules.get(name, None) def find_submodule(self, name, as_package=False): # Find a top-level module, creating a new one if needed. scope = self.lookup_submodule(name) if not scope: scope = ModuleScope(name, parent_module = None, context = self, is_package=as_package) self.modules[name] = scope return scope def parse(self, source_desc, scope, pxd, full_module_name): if not isinstance(source_desc, FileSourceDescriptor): raise RuntimeError("Only file sources for code supported") source_filename = source_desc.filename scope.cpp = self.cpp # Parse the given source file and return a parse tree. num_errors = Errors.get_errors_count() try: with Utils.open_source_file(source_filename) as f: from . import Parsing s = PyrexScanner(f, source_desc, source_encoding = f.encoding, scope = scope, context = self) tree = Parsing.p_module(s, pxd, full_module_name) if self.options.formal_grammar: try: from ..Parser import ConcreteSyntaxTree except ImportError: raise RuntimeError( "Formal grammar can only be used with compiled Cython with an available pgen.") ConcreteSyntaxTree.p_module(source_filename) except UnicodeDecodeError as e: #import traceback #traceback.print_exc() raise self._report_decode_error(source_desc, e) if Errors.get_errors_count() > num_errors: raise CompileError() return tree def _report_decode_error(self, source_desc, exc): msg = exc.args[-1] position = exc.args[2] encoding = exc.args[0] line = 1 column = idx = 0 with io.open(source_desc.filename, "r", encoding='iso8859-1', newline='') as f: for line, data in enumerate(f, 1): idx += len(data) if idx >= position: column = position - (idx - len(data)) + 1 break return error((source_desc, line, column), "Decoding error, missing or incorrect coding= " "at top of source (cannot decode with encoding %r: %s)" % (encoding, msg)) def extract_module_name(self, path, options): # Find fully_qualified module name from the full pathname # of a source file. dir, filename = os.path.split(path) module_name, _ = os.path.splitext(filename) if "." in module_name: return module_name names = [module_name] while self.is_package_dir(dir): parent, package_name = os.path.split(dir) if parent == dir: break names.append(package_name) dir = parent names.reverse() return ".".join(names) def setup_errors(self, options, result): Errors.init_thread() if options.use_listing_file: path = result.listing_file = Utils.replace_suffix(result.main_source_file, ".lis") else: path = None Errors.open_listing_file(path=path, echo_to_stderr=options.errors_to_stderr) def teardown_errors(self, err, options, result): source_desc = result.compilation_source.source_desc if not isinstance(source_desc, FileSourceDescriptor): raise RuntimeError("Only file sources for code supported") Errors.close_listing_file() result.num_errors = Errors.get_errors_count() if result.num_errors > 0: err = True if err and result.c_file: try: Utils.castrate_file(result.c_file, os.stat(source_desc.filename)) except EnvironmentError: pass result.c_file = None def get_output_filename(source_filename, cwd, options): if options.cplus: c_suffix = ".cpp" else: c_suffix = ".c" suggested_file_name = Utils.replace_suffix(source_filename, c_suffix) if options.output_file: out_path = os.path.join(cwd, options.output_file) if os.path.isdir(out_path): return os.path.join(out_path, os.path.basename(suggested_file_name)) else: return out_path else: return suggested_file_name def create_default_resultobj(compilation_source, options): result = CompilationResult() result.main_source_file = compilation_source.source_desc.filename result.compilation_source = compilation_source source_desc = compilation_source.source_desc result.c_file = get_output_filename(source_desc.filename, compilation_source.cwd, options) result.embedded_metadata = options.embedded_metadata return result def run_pipeline(source, options, full_module_name=None, context=None): from . import Pipeline # ensure that the inputs are unicode (for Python 2) if sys.version_info[0] == 2: source = Utils.decode_filename(source) if full_module_name: full_module_name = Utils.decode_filename(full_module_name) source_ext = os.path.splitext(source)[1] options.configure_language_defaults(source_ext[1:]) # py/pyx if context is None: context = Context.from_options(options) # Set up source object cwd = os.getcwd() abs_path = os.path.abspath(source) full_module_name = full_module_name or context.extract_module_name(source, options) full_module_name = EncodedString(full_module_name) Utils.raise_error_if_module_name_forbidden(full_module_name) if options.relative_path_in_code_position_comments: rel_path = full_module_name.replace('.', os.sep) + source_ext if not abs_path.endswith(rel_path): rel_path = source # safety measure to prevent printing incorrect paths else: rel_path = abs_path source_desc = FileSourceDescriptor(abs_path, rel_path) source = CompilationSource(source_desc, full_module_name, cwd) # Set up result object result = create_default_resultobj(source, options) if options.annotate is None: # By default, decide based on whether an html file already exists. html_filename = os.path.splitext(result.c_file)[0] + ".html" if os.path.exists(html_filename): with io.open(html_filename, "r", encoding="UTF-8") as html_file: if u' State %d\n" % (key, state['number'])) for key in ('bol', 'eol', 'eof', 'else'): state = special_to_state.get(key, None) if state: file.write(" %s --> State %d\n" % (key, state['number'])) @cython.locals(char_list=list, i=cython.Py_ssize_t, n=cython.Py_ssize_t, c1=cython.long, c2=cython.long) def chars_to_ranges(self, char_list): char_list.sort() i = 0 n = len(char_list) result = [] while i < n: c1 = ord(char_list[i]) c2 = c1 i += 1 while i < n and ord(char_list[i]) == c2 + 1: i += 1 c2 += 1 result.append((chr(c1), chr(c2))) return tuple(result) def ranges_to_string(self, range_list): return ','.join(map(self.range_to_string, range_list)) def range_to_string(self, range_tuple): (c1, c2) = range_tuple if c1 == c2: return repr(c1) else: return "%s..%s" % (repr(c1), repr(c2)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Plex/Regexps.py0000644000175100001770000003515500000000000017750 0ustar00runnerdocker00000000000000""" Python Lexical Analyser Regular Expressions """ from __future__ import absolute_import import types from . import Errors maxint = 2**31-1 # sentinel value # # Constants # BOL = 'bol' EOL = 'eol' EOF = 'eof' nl_code = ord('\n') # # Helper functions # def chars_to_ranges(s): """ Return a list of character codes consisting of pairs [code1a, code1b, code2a, code2b,...] which cover all the characters in |s|. """ char_list = list(s) char_list.sort() i = 0 n = len(char_list) result = [] while i < n: code1 = ord(char_list[i]) code2 = code1 + 1 i += 1 while i < n and code2 >= ord(char_list[i]): code2 += 1 i += 1 result.append(code1) result.append(code2) return result def uppercase_range(code1, code2): """ If the range of characters from code1 to code2-1 includes any lower case letters, return the corresponding upper case range. """ code3 = max(code1, ord('a')) code4 = min(code2, ord('z') + 1) if code3 < code4: d = ord('A') - ord('a') return (code3 + d, code4 + d) else: return None def lowercase_range(code1, code2): """ If the range of characters from code1 to code2-1 includes any upper case letters, return the corresponding lower case range. """ code3 = max(code1, ord('A')) code4 = min(code2, ord('Z') + 1) if code3 < code4: d = ord('a') - ord('A') return (code3 + d, code4 + d) else: return None def CodeRanges(code_list): """ Given a list of codes as returned by chars_to_ranges, return an RE which will match a character in any of the ranges. """ re_list = [CodeRange(code_list[i], code_list[i + 1]) for i in range(0, len(code_list), 2)] return Alt(*re_list) def CodeRange(code1, code2): """ CodeRange(code1, code2) is an RE which matches any character with a code |c| in the range |code1| <= |c| < |code2|. """ if code1 <= nl_code < code2: return Alt(RawCodeRange(code1, nl_code), RawNewline, RawCodeRange(nl_code + 1, code2)) else: return RawCodeRange(code1, code2) # # Abstract classes # class RE(object): """RE is the base class for regular expression constructors. The following operators are defined on REs: re1 + re2 is an RE which matches |re1| followed by |re2| re1 | re2 is an RE which matches either |re1| or |re2| """ nullable = 1 # True if this RE can match 0 input symbols match_nl = 1 # True if this RE can match a string ending with '\n' str = None # Set to a string to override the class's __str__ result def build_machine(self, machine, initial_state, final_state, match_bol, nocase): """ This method should add states to |machine| to implement this RE, starting at |initial_state| and ending at |final_state|. If |match_bol| is true, the RE must be able to match at the beginning of a line. If nocase is true, upper and lower case letters should be treated as equivalent. """ raise NotImplementedError("%s.build_machine not implemented" % self.__class__.__name__) def build_opt(self, m, initial_state, c): """ Given a state |s| of machine |m|, return a new state reachable from |s| on character |c| or epsilon. """ s = m.new_state() initial_state.link_to(s) initial_state.add_transition(c, s) return s def __add__(self, other): return Seq(self, other) def __or__(self, other): return Alt(self, other) def __str__(self): if self.str: return self.str else: return self.calc_str() def check_re(self, num, value): if not isinstance(value, RE): self.wrong_type(num, value, "Plex.RE instance") def check_string(self, num, value): if type(value) != type(''): self.wrong_type(num, value, "string") def check_char(self, num, value): self.check_string(num, value) if len(value) != 1: raise Errors.PlexValueError("Invalid value for argument %d of Plex.%s." "Expected a string of length 1, got: %s" % ( num, self.__class__.__name__, repr(value))) def wrong_type(self, num, value, expected): if type(value) == types.InstanceType: got = "%s.%s instance" % ( value.__class__.__module__, value.__class__.__name__) else: got = type(value).__name__ raise Errors.PlexTypeError("Invalid type for argument %d of Plex.%s " "(expected %s, got %s" % ( num, self.__class__.__name__, expected, got)) # # Primitive RE constructors # ------------------------- # # These are the basic REs from which all others are built. # def Char(c): """ Char(c) is an RE which matches the character |c|. """ if len(c) == 1: result = CodeRange(ord(c), ord(c) + 1) else: result = SpecialSymbol(c) result.str = "Char(%s)" % repr(c) return result class RawCodeRange(RE): """ RawCodeRange(code1, code2) is a low-level RE which matches any character with a code |c| in the range |code1| <= |c| < |code2|, where the range does not include newline. For internal use only. """ nullable = 0 match_nl = 0 range = None # (code, code) uppercase_range = None # (code, code) or None lowercase_range = None # (code, code) or None def __init__(self, code1, code2): self.range = (code1, code2) self.uppercase_range = uppercase_range(code1, code2) self.lowercase_range = lowercase_range(code1, code2) def build_machine(self, m, initial_state, final_state, match_bol, nocase): if match_bol: initial_state = self.build_opt(m, initial_state, BOL) initial_state.add_transition(self.range, final_state) if nocase: if self.uppercase_range: initial_state.add_transition(self.uppercase_range, final_state) if self.lowercase_range: initial_state.add_transition(self.lowercase_range, final_state) def calc_str(self): return "CodeRange(%d,%d)" % (self.code1, self.code2) class _RawNewline(RE): """ RawNewline is a low-level RE which matches a newline character. For internal use only. """ nullable = 0 match_nl = 1 def build_machine(self, m, initial_state, final_state, match_bol, nocase): if match_bol: initial_state = self.build_opt(m, initial_state, BOL) s = self.build_opt(m, initial_state, EOL) s.add_transition((nl_code, nl_code + 1), final_state) RawNewline = _RawNewline() class SpecialSymbol(RE): """ SpecialSymbol(sym) is an RE which matches the special input symbol |sym|, which is one of BOL, EOL or EOF. """ nullable = 0 match_nl = 0 sym = None def __init__(self, sym): self.sym = sym def build_machine(self, m, initial_state, final_state, match_bol, nocase): # Sequences 'bol bol' and 'bol eof' are impossible, so only need # to allow for bol if sym is eol if match_bol and self.sym == EOL: initial_state = self.build_opt(m, initial_state, BOL) initial_state.add_transition(self.sym, final_state) class Seq(RE): """Seq(re1, re2, re3...) is an RE which matches |re1| followed by |re2| followed by |re3|...""" def __init__(self, *re_list): nullable = 1 for i, re in enumerate(re_list): self.check_re(i, re) nullable = nullable and re.nullable self.re_list = re_list self.nullable = nullable i = len(re_list) match_nl = 0 while i: i -= 1 re = re_list[i] if re.match_nl: match_nl = 1 break if not re.nullable: break self.match_nl = match_nl def build_machine(self, m, initial_state, final_state, match_bol, nocase): re_list = self.re_list if len(re_list) == 0: initial_state.link_to(final_state) else: s1 = initial_state n = len(re_list) for i, re in enumerate(re_list): if i < n - 1: s2 = m.new_state() else: s2 = final_state re.build_machine(m, s1, s2, match_bol, nocase) s1 = s2 match_bol = re.match_nl or (match_bol and re.nullable) def calc_str(self): return "Seq(%s)" % ','.join(map(str, self.re_list)) class Alt(RE): """Alt(re1, re2, re3...) is an RE which matches either |re1| or |re2| or |re3|...""" def __init__(self, *re_list): self.re_list = re_list nullable = 0 match_nl = 0 nullable_res = [] non_nullable_res = [] i = 1 for re in re_list: self.check_re(i, re) if re.nullable: nullable_res.append(re) nullable = 1 else: non_nullable_res.append(re) if re.match_nl: match_nl = 1 i += 1 self.nullable_res = nullable_res self.non_nullable_res = non_nullable_res self.nullable = nullable self.match_nl = match_nl def build_machine(self, m, initial_state, final_state, match_bol, nocase): for re in self.nullable_res: re.build_machine(m, initial_state, final_state, match_bol, nocase) if self.non_nullable_res: if match_bol: initial_state = self.build_opt(m, initial_state, BOL) for re in self.non_nullable_res: re.build_machine(m, initial_state, final_state, 0, nocase) def calc_str(self): return "Alt(%s)" % ','.join(map(str, self.re_list)) class Rep1(RE): """Rep1(re) is an RE which matches one or more repetitions of |re|.""" def __init__(self, re): self.check_re(1, re) self.re = re self.nullable = re.nullable self.match_nl = re.match_nl def build_machine(self, m, initial_state, final_state, match_bol, nocase): s1 = m.new_state() s2 = m.new_state() initial_state.link_to(s1) self.re.build_machine(m, s1, s2, match_bol or self.re.match_nl, nocase) s2.link_to(s1) s2.link_to(final_state) def calc_str(self): return "Rep1(%s)" % self.re class SwitchCase(RE): """ SwitchCase(re, nocase) is an RE which matches the same strings as RE, but treating upper and lower case letters according to |nocase|. If |nocase| is true, case is ignored, otherwise it is not. """ re = None nocase = None def __init__(self, re, nocase): self.re = re self.nocase = nocase self.nullable = re.nullable self.match_nl = re.match_nl def build_machine(self, m, initial_state, final_state, match_bol, nocase): self.re.build_machine(m, initial_state, final_state, match_bol, self.nocase) def calc_str(self): if self.nocase: name = "NoCase" else: name = "Case" return "%s(%s)" % (name, self.re) # # Composite RE constructors # ------------------------- # # These REs are defined in terms of the primitive REs. # Empty = Seq() Empty.__doc__ = \ """ Empty is an RE which matches the empty string. """ Empty.str = "Empty" def Str1(s): """ Str1(s) is an RE which matches the literal string |s|. """ result = Seq(*tuple(map(Char, s))) result.str = "Str(%s)" % repr(s) return result def Str(*strs): """ Str(s) is an RE which matches the literal string |s|. Str(s1, s2, s3, ...) is an RE which matches any of |s1| or |s2| or |s3|... """ if len(strs) == 1: return Str1(strs[0]) else: result = Alt(*tuple(map(Str1, strs))) result.str = "Str(%s)" % ','.join(map(repr, strs)) return result def Any(s): """ Any(s) is an RE which matches any character in the string |s|. """ result = CodeRanges(chars_to_ranges(s)) result.str = "Any(%s)" % repr(s) return result def AnyBut(s): """ AnyBut(s) is an RE which matches any character (including newline) which is not in the string |s|. """ ranges = chars_to_ranges(s) ranges.insert(0, -maxint) ranges.append(maxint) result = CodeRanges(ranges) result.str = "AnyBut(%s)" % repr(s) return result AnyChar = AnyBut("") AnyChar.__doc__ = \ """ AnyChar is an RE which matches any single character (including a newline). """ AnyChar.str = "AnyChar" def Range(s1, s2=None): """ Range(c1, c2) is an RE which matches any single character in the range |c1| to |c2| inclusive. Range(s) where |s| is a string of even length is an RE which matches any single character in the ranges |s[0]| to |s[1]|, |s[2]| to |s[3]|,... """ if s2: result = CodeRange(ord(s1), ord(s2) + 1) result.str = "Range(%s,%s)" % (s1, s2) else: ranges = [] for i in range(0, len(s1), 2): ranges.append(CodeRange(ord(s1[i]), ord(s1[i + 1]) + 1)) result = Alt(*ranges) result.str = "Range(%s)" % repr(s1) return result def Opt(re): """ Opt(re) is an RE which matches either |re| or the empty string. """ result = Alt(re, Empty) result.str = "Opt(%s)" % re return result def Rep(re): """ Rep(re) is an RE which matches zero or more repetitions of |re|. """ result = Opt(Rep1(re)) result.str = "Rep(%s)" % re return result def NoCase(re): """ NoCase(re) is an RE which matches the same strings as RE, but treating upper and lower case letters as equivalent. """ return SwitchCase(re, nocase=1) def Case(re): """ Case(re) is an RE which matches the same strings as RE, but treating upper and lower case letters as distinct, i.e. it cancels the effect of any enclosing NoCase(). """ return SwitchCase(re, nocase=0) # # RE Constants # Bol = Char(BOL) Bol.__doc__ = \ """ Bol is an RE which matches the beginning of a line. """ Bol.str = "Bol" Eol = Char(EOL) Eol.__doc__ = \ """ Eol is an RE which matches the end of a line. """ Eol.str = "Eol" Eof = Char(EOF) Eof.__doc__ = \ """ Eof is an RE which matches the end of the file. """ Eof.str = "Eof" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Plex/Scanners.pxd0000644000175100001770000000302000000000000020234 0ustar00runnerdocker00000000000000from __future__ import absolute_import import cython from Cython.Plex.Actions cimport Action cdef class Scanner: cdef public lexicon cdef public stream cdef public name cdef public unicode buffer cdef public Py_ssize_t buf_start_pos cdef public Py_ssize_t next_pos cdef public Py_ssize_t cur_pos cdef public Py_ssize_t cur_line cdef public Py_ssize_t cur_line_start cdef public Py_ssize_t start_pos cdef tuple current_scanner_position_tuple cdef public tuple last_token_position_tuple cdef public text cdef public initial_state # int? cdef public state_name cdef public list queue cdef public bint trace cdef public cur_char cdef public long input_state cdef public level @cython.locals(input_state=long) cdef inline next_char(self) @cython.locals(action=Action) cpdef tuple read(self) cdef inline unread(self, token, value, position) cdef inline get_current_scan_pos(self) cdef inline tuple scan_a_token(self) ##cdef tuple position(self) # used frequently by Parsing.py @cython.final @cython.locals(cur_pos=Py_ssize_t, cur_line=Py_ssize_t, cur_line_start=Py_ssize_t, input_state=long, next_pos=Py_ssize_t, state=dict, buf_start_pos=Py_ssize_t, buf_len=Py_ssize_t, buf_index=Py_ssize_t, trace=bint, discard=Py_ssize_t, data=unicode, buffer=unicode) cdef run_machine_inlined(self) cdef inline begin(self, state) cdef inline produce(self, value, text = *) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Plex/Scanners.py0000644000175100001770000003121300000000000020076 0ustar00runnerdocker00000000000000# cython: language_level=3str # cython: auto_pickle=False """ Python Lexical Analyser Scanning an input stream """ from __future__ import absolute_import import cython cython.declare(BOL=object, EOL=object, EOF=object, NOT_FOUND=object) # noqa:E402 from . import Errors from .Regexps import BOL, EOL, EOF NOT_FOUND = object() class Scanner(object): """ A Scanner is used to read tokens from a stream of characters using the token set specified by a Plex.Lexicon. Constructor: Scanner(lexicon, stream, name = '') See the docstring of the __init__ method for details. Methods: See the docstrings of the individual methods for more information. read() --> (value, text) Reads the next lexical token from the stream. position() --> (name, line, col) Returns the position of the last token read using the read() method. begin(state_name) Causes scanner to change state. produce(value [, text]) Causes return of a token value to the caller of the Scanner. """ # lexicon = None # Lexicon # stream = None # file-like object # name = '' # buffer = '' # # These positions are used by the scanner to track its internal state: # buf_start_pos = 0 # position in input of start of buffer # next_pos = 0 # position in input of next char to read # cur_pos = 0 # position in input of current char # cur_line = 1 # line number of current char # cur_line_start = 0 # position in input of start of current line # start_pos = 0 # position in input of start of token # current_scanner_position_tuple = ("", 0, 0) # tuple of filename, line number and position in line, really mainly for error reporting # # These positions are used to track what was read from the queue # (which may differ from the internal state when tokens are replaced onto the queue) # last_token_position_tuple = ("", 0, 0) # tuple of filename, line number and position in line # text = None # text of last token read # initial_state = None # Node # state_name = '' # Name of initial state # queue = None # list of tokens and positions to be returned # trace = 0 def __init__(self, lexicon, stream, name='', initial_pos=None): """ Scanner(lexicon, stream, name = '') |lexicon| is a Plex.Lexicon instance specifying the lexical tokens to be recognised. |stream| can be a file object or anything which implements a compatible read() method. |name| is optional, and may be the name of the file being scanned or any other identifying string. """ self.trace = 0 self.buffer = u'' self.buf_start_pos = 0 self.next_pos = 0 self.cur_pos = 0 self.cur_line = 1 self.start_pos = 0 self.current_scanner_position_tuple = ("", 0, 0) self.last_token_position_tuple = ("", 0, 0) self.text = None self.state_name = None self.lexicon = lexicon self.stream = stream self.name = name self.queue = [] self.initial_state = None self.begin('') self.next_pos = 0 self.cur_pos = 0 self.cur_line_start = 0 self.cur_char = BOL self.input_state = 1 if initial_pos is not None: self.cur_line, self.cur_line_start = initial_pos[1], -initial_pos[2] def read(self): """ Read the next lexical token from the stream and return a tuple (value, text), where |value| is the value associated with the token as specified by the Lexicon, and |text| is the actual string read from the stream. Returns (None, '') on end of file. """ queue = self.queue while not queue: self.text, action = self.scan_a_token() if action is None: self.produce(None) self.eof() else: value = action.perform(self, self.text) if value is not None: self.produce(value) result, self.last_token_position_tuple = queue[0] del queue[0] return result def unread(self, token, value, position): self.queue.insert(0, ((token, value), position)) def get_current_scan_pos(self): # distinct from the position of the last token due to the queue return self.current_scanner_position_tuple def scan_a_token(self): """ Read the next input sequence recognised by the machine and return (text, action). Returns ('', None) on end of file. """ self.start_pos = self.cur_pos self.current_scanner_position_tuple = ( self.name, self.cur_line, self.cur_pos - self.cur_line_start ) action = self.run_machine_inlined() if action is not None: if self.trace: print("Scanner: read: Performing %s %d:%d" % ( action, self.start_pos, self.cur_pos)) text = self.buffer[ self.start_pos - self.buf_start_pos: self.cur_pos - self.buf_start_pos] return (text, action) else: if self.cur_pos == self.start_pos: if self.cur_char is EOL: self.next_char() if self.cur_char is None or self.cur_char is EOF: return (u'', None) raise Errors.UnrecognizedInput(self, self.state_name) def run_machine_inlined(self): """ Inlined version of run_machine for speed. """ state = self.initial_state cur_pos = self.cur_pos cur_line = self.cur_line cur_line_start = self.cur_line_start cur_char = self.cur_char input_state = self.input_state next_pos = self.next_pos buffer = self.buffer buf_start_pos = self.buf_start_pos buf_len = len(buffer) b_action, b_cur_pos, b_cur_line, b_cur_line_start, b_cur_char, b_input_state, b_next_pos = \ None, 0, 0, 0, u'', 0, 0 trace = self.trace while 1: if trace: print("State %d, %d/%d:%s -->" % ( state['number'], input_state, cur_pos, repr(cur_char))) # Begin inlined self.save_for_backup() action = state['action'] if action is not None: b_action, b_cur_pos, b_cur_line, b_cur_line_start, b_cur_char, b_input_state, b_next_pos = \ action, cur_pos, cur_line, cur_line_start, cur_char, input_state, next_pos # End inlined self.save_for_backup() c = cur_char new_state = state.get(c, NOT_FOUND) if new_state is NOT_FOUND: new_state = c and state.get('else') if new_state: if trace: print("State %d" % new_state['number']) state = new_state # Begin inlined: self.next_char() if input_state == 1: cur_pos = next_pos # Begin inlined: c = self.read_char() buf_index = next_pos - buf_start_pos if buf_index < buf_len: c = buffer[buf_index] next_pos += 1 else: discard = self.start_pos - buf_start_pos data = self.stream.read(0x1000) buffer = self.buffer[discard:] + data self.buffer = buffer buf_start_pos += discard self.buf_start_pos = buf_start_pos buf_len = len(buffer) buf_index -= discard if data: c = buffer[buf_index] next_pos += 1 else: c = u'' # End inlined: c = self.read_char() if c == u'\n': cur_char = EOL input_state = 2 elif not c: cur_char = EOL input_state = 4 else: cur_char = c elif input_state == 2: # after EoL (1) -> BoL (3) cur_char = u'\n' input_state = 3 elif input_state == 3: # start new code line cur_line += 1 cur_line_start = cur_pos = next_pos cur_char = BOL input_state = 1 elif input_state == 4: # after final line (1) -> EoF (5) cur_char = EOF input_state = 5 else: # input_state == 5 (EoF) cur_char = u'' # End inlined self.next_char() else: # not new_state if trace: print("blocked") # Begin inlined: action = self.back_up() if b_action is not None: (action, cur_pos, cur_line, cur_line_start, cur_char, input_state, next_pos) = \ (b_action, b_cur_pos, b_cur_line, b_cur_line_start, b_cur_char, b_input_state, b_next_pos) else: action = None break # while 1 # End inlined: action = self.back_up() self.cur_pos = cur_pos self.cur_line = cur_line self.cur_line_start = cur_line_start self.cur_char = cur_char self.input_state = input_state self.next_pos = next_pos if trace: if action is not None: print("Doing %s" % action) return action def next_char(self): input_state = self.input_state if self.trace: print("Scanner: next: %s [%d] %d" % (" " * 20, input_state, self.cur_pos)) if input_state == 1: self.cur_pos = self.next_pos c = self.read_char() if c == u'\n': self.cur_char = EOL self.input_state = 2 elif not c: self.cur_char = EOL self.input_state = 4 else: self.cur_char = c elif input_state == 2: self.cur_char = u'\n' self.input_state = 3 elif input_state == 3: self.cur_line += 1 self.cur_line_start = self.cur_pos = self.next_pos self.cur_char = BOL self.input_state = 1 elif input_state == 4: self.cur_char = EOF self.input_state = 5 else: # input_state = 5 self.cur_char = u'' if self.trace: print("--> [%d] %d %r" % (input_state, self.cur_pos, self.cur_char)) def position(self): """ Return a tuple (name, line, col) representing the location of the last token read using the read() method. |name| is the name that was provided to the Scanner constructor; |line| is the line number in the stream (1-based); |col| is the position within the line of the first character of the token (0-based). """ return self.last_token_position_tuple def get_position(self): """ Python accessible wrapper around position(), only for error reporting. """ return self.position() def begin(self, state_name): """Set the current state of the scanner to the named state.""" self.initial_state = ( self.lexicon.get_initial_state(state_name)) self.state_name = state_name def produce(self, value, text=None): """ Called from an action procedure, causes |value| to be returned as the token value from read(). If |text| is supplied, it is returned in place of the scanned text. produce() can be called more than once during a single call to an action procedure, in which case the tokens are queued up and returned one at a time by subsequent calls to read(), until the queue is empty, whereupon scanning resumes. """ if text is None: text = self.text self.queue.append(((value, text), self.current_scanner_position_tuple)) def eof(self): """ Override this method if you want something to be done at end of file. """ pass @property def start_line(self): return self.last_token_position_tuple[1] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Plex/Transitions.pxd0000644000175100001770000000111600000000000021001 0ustar00runnerdocker00000000000000cimport cython cdef long maxint @cython.final cdef class TransitionMap: cdef list map cdef dict special @cython.locals(i=cython.Py_ssize_t, j=cython.Py_ssize_t) cpdef add(self, event, new_state) @cython.locals(i=cython.Py_ssize_t, j=cython.Py_ssize_t) cpdef add_set(self, event, new_set) @cython.locals(i=cython.Py_ssize_t, n=cython.Py_ssize_t, else_set=cython.bint) cpdef iteritems(self) @cython.locals(map=list, lo=cython.Py_ssize_t, mid=cython.Py_ssize_t, hi=cython.Py_ssize_t) cdef split(self, long code) cdef get_special(self, event) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Plex/Transitions.py0000644000175100001770000001515100000000000020642 0ustar00runnerdocker00000000000000# cython: auto_pickle=False """ Plex - Transition Maps This version represents state sets directly as dicts for speed. """ maxint = 2**31-1 # sentinel value class TransitionMap(object): """ A TransitionMap maps an input event to a set of states. An input event is one of: a range of character codes, the empty string (representing an epsilon move), or one of the special symbols BOL, EOL, EOF. For characters, this implementation compactly represents the map by means of a list: [code_0, states_0, code_1, states_1, code_2, states_2, ..., code_n-1, states_n-1, code_n] where |code_i| is a character code, and |states_i| is a set of states corresponding to characters with codes |c| in the range |code_i| <= |c| <= |code_i+1|. The following invariants hold: n >= 1 code_0 == -maxint code_n == maxint code_i < code_i+1 for i in 0..n-1 states_0 == states_n-1 Mappings for the special events '', BOL, EOL, EOF are kept separately in a dictionary. """ def __init__(self, map=None, special=None): if not map: map = [-maxint, {}, maxint] if not special: special = {} self.map = map # The list of codes and states self.special = special # Mapping for special events def add(self, event, new_state): """ Add transition to |new_state| on |event|. """ if type(event) is tuple: code0, code1 = event i = self.split(code0) j = self.split(code1) map = self.map while i < j: map[i + 1][new_state] = 1 i += 2 else: self.get_special(event)[new_state] = 1 def add_set(self, event, new_set): """ Add transitions to the states in |new_set| on |event|. """ if type(event) is tuple: code0, code1 = event i = self.split(code0) j = self.split(code1) map = self.map while i < j: map[i + 1].update(new_set) i += 2 else: self.get_special(event).update(new_set) def get_epsilon(self): """ Return the mapping for epsilon, or None. """ return self.special.get('') def iteritems(self): """ Return the mapping as an iterable of ((code1, code2), state_set) and (special_event, state_set) pairs. """ result = [] map = self.map else_set = map[1] i = 0 n = len(map) - 1 code0 = map[0] while i < n: set = map[i + 1] code1 = map[i + 2] if set or else_set: result.append(((code0, code1), set)) code0 = code1 i += 2 for event, set in self.special.items(): if set: result.append((event, set)) return iter(result) items = iteritems # ------------------- Private methods -------------------- def split(self, code): """ Search the list for the position of the split point for |code|, inserting a new split point if necessary. Returns index |i| such that |code| == |map[i]|. """ # We use a funky variation on binary search. map = self.map hi = len(map) - 1 # Special case: code == map[-1] if code == maxint: return hi # General case lo = 0 # loop invariant: map[lo] <= code < map[hi] and hi - lo >= 2 while hi - lo >= 4: # Find midpoint truncated to even index mid = ((lo + hi) // 2) & ~1 if code < map[mid]: hi = mid else: lo = mid # map[lo] <= code < map[hi] and hi - lo == 2 if map[lo] == code: return lo else: map[hi:hi] = [code, map[hi - 1].copy()] return hi def get_special(self, event): """ Get state set for special event, adding a new entry if necessary. """ special = self.special set = special.get(event, None) if not set: set = {} special[event] = set return set # --------------------- Conversion methods ----------------------- def __str__(self): map_strs = [] map = self.map n = len(map) i = 0 while i < n: code = map[i] if code == -maxint: code_str = "-inf" elif code == maxint: code_str = "inf" else: code_str = str(code) map_strs.append(code_str) i += 1 if i < n: map_strs.append(state_set_str(map[i])) i += 1 special_strs = {} for event, set in self.special.items(): special_strs[event] = state_set_str(set) return "[%s]+%s" % ( ','.join(map_strs), special_strs ) # --------------------- Debugging methods ----------------------- def check(self): """Check data structure integrity.""" if not self.map[-3] < self.map[-1]: print(self) assert 0 def dump(self, file): map = self.map i = 0 n = len(map) - 1 while i < n: self.dump_range(map[i], map[i + 2], map[i + 1], file) i += 2 for event, set in self.special.items(): if set: if not event: event = 'empty' self.dump_trans(event, set, file) def dump_range(self, code0, code1, set, file): if set: if code0 == -maxint: if code1 == maxint: k = "any" else: k = "< %s" % self.dump_char(code1) elif code1 == maxint: k = "> %s" % self.dump_char(code0 - 1) elif code0 == code1 - 1: k = self.dump_char(code0) else: k = "%s..%s" % (self.dump_char(code0), self.dump_char(code1 - 1)) self.dump_trans(k, set, file) def dump_char(self, code): if 0 <= code <= 255: return repr(chr(code)) else: return "chr(%d)" % code def dump_trans(self, key, set, file): file.write(" %s --> %s\n" % (key, self.dump_set(set))) def dump_set(self, set): return state_set_str(set) # # State set manipulation functions # def state_set_str(set): return "[%s]" % ','.join(["S%d" % state.number for state in set]) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Plex/__init__.py0000644000175100001770000000220300000000000020056 0ustar00runnerdocker00000000000000""" Python Lexical Analyser The Plex module provides lexical analysers with similar capabilities to GNU Flex. The following classes and functions are exported; see the attached docstrings for more information. Scanner For scanning a character stream under the direction of a Lexicon. Lexicon For constructing a lexical definition to be used by a Scanner. Str, Any, AnyBut, AnyChar, Seq, Alt, Opt, Rep, Rep1, Bol, Eol, Eof, Empty Regular expression constructors, for building pattern definitions for a Lexicon. State For defining scanner states when creating a Lexicon. TEXT, IGNORE, Begin Actions for associating with patterns when creating a Lexicon. """ # flake8: noqa:F401 from __future__ import absolute_import from .Actions import TEXT, IGNORE, Begin, Method from .Lexicons import Lexicon, State from .Regexps import RE, Seq, Alt, Rep1, Empty, Str, Any, AnyBut, AnyChar, Range from .Regexps import Opt, Rep, Bol, Eol, Eof, Case, NoCase from .Scanners import Scanner ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.012724 Cython-3.0.8/Cython/Runtime/0000755000175100001770000000000000000000000016463 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Runtime/__init__.py0000644000175100001770000000001500000000000020570 0ustar00runnerdocker00000000000000# empty file ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Runtime/refnanny.pyx0000644000175100001770000001472300000000000021054 0ustar00runnerdocker00000000000000# cython: language_level=3, auto_pickle=False from cpython.ref cimport PyObject, Py_INCREF, Py_CLEAR, Py_XDECREF, Py_XINCREF from cpython.exc cimport PyErr_Fetch, PyErr_Restore from cpython.pystate cimport PyThreadState_Get cimport cython loglevel = 0 reflog = [] cdef log(level, action, obj, lineno): if reflog is None: # can happen during finalisation return if loglevel >= level: reflog.append((lineno, action, id(obj))) LOG_NONE, LOG_ALL = range(2) @cython.final cdef class Context(object): cdef readonly object name, filename cdef readonly dict refs cdef readonly list errors cdef readonly Py_ssize_t start def __cinit__(self, name, line=0, filename=None): self.name = name self.start = line self.filename = filename self.refs = {} # id -> (count, [lineno]) self.errors = [] cdef regref(self, obj, Py_ssize_t lineno, bint is_null): log(LOG_ALL, u'regref', u"" if is_null else obj, lineno) if is_null: self.errors.append(f"NULL argument on line {lineno}") return id_ = id(obj) count, linenumbers = self.refs.get(id_, (0, [])) self.refs[id_] = (count + 1, linenumbers) linenumbers.append(lineno) cdef bint delref(self, obj, Py_ssize_t lineno, bint is_null) except -1: # returns whether it is ok to do the decref operation log(LOG_ALL, u'delref', u"" if is_null else obj, lineno) if is_null: self.errors.append(f"NULL argument on line {lineno}") return False id_ = id(obj) count, linenumbers = self.refs.get(id_, (0, [])) if count == 0: self.errors.append(f"Too many decrefs on line {lineno}, reference acquired on lines {linenumbers!r}") return False if count == 1: del self.refs[id_] else: self.refs[id_] = (count - 1, linenumbers) return True cdef end(self): if self.refs: msg = u"References leaked:" for count, linenos in self.refs.itervalues(): msg += f"\n ({count}) acquired on lines: {u', '.join([f'{x}' for x in linenos])}" self.errors.append(msg) return u"\n".join([f'REFNANNY: {error}' for error in self.errors]) if self.errors else None cdef void report_unraisable(filename, Py_ssize_t lineno, object e=None): try: if e is None: import sys e = sys.exc_info()[1] print(f"refnanny raised an exception from {filename}:{lineno}: {e}") finally: return # We absolutely cannot exit with an exception # All Python operations must happen after any existing # exception has been fetched, in case we are called from # exception-handling code. cdef PyObject* SetupContext(char* funcname, Py_ssize_t lineno, char* filename) except NULL: if Context is None: # Context may be None during finalize phase. # In that case, we don't want to be doing anything fancy # like caching and resetting exceptions. return NULL cdef (PyObject*) type = NULL, value = NULL, tb = NULL, result = NULL PyThreadState_Get() # Check that we hold the GIL PyErr_Fetch(&type, &value, &tb) try: ctx = Context(funcname, lineno, filename) Py_INCREF(ctx) result = ctx except Exception, e: report_unraisable(filename, lineno, e) PyErr_Restore(type, value, tb) return result cdef void GOTREF(PyObject* ctx, PyObject* p_obj, Py_ssize_t lineno): if ctx == NULL: return cdef (PyObject*) type = NULL, value = NULL, tb = NULL PyErr_Fetch(&type, &value, &tb) try: (ctx).regref( p_obj if p_obj is not NULL else None, lineno, is_null=p_obj is NULL, ) except: report_unraisable((ctx).filename, lineno=(ctx).start) finally: PyErr_Restore(type, value, tb) return # swallow any exceptions cdef bint GIVEREF_and_report(PyObject* ctx, PyObject* p_obj, Py_ssize_t lineno): if ctx == NULL: return 1 cdef (PyObject*) type = NULL, value = NULL, tb = NULL cdef bint decref_ok = False PyErr_Fetch(&type, &value, &tb) try: decref_ok = (ctx).delref( p_obj if p_obj is not NULL else None, lineno, is_null=p_obj is NULL, ) except: report_unraisable((ctx).filename, lineno=(ctx).start) finally: PyErr_Restore(type, value, tb) return decref_ok # swallow any exceptions cdef void GIVEREF(PyObject* ctx, PyObject* p_obj, Py_ssize_t lineno): GIVEREF_and_report(ctx, p_obj, lineno) cdef void INCREF(PyObject* ctx, PyObject* obj, Py_ssize_t lineno): Py_XINCREF(obj) PyThreadState_Get() # Check that we hold the GIL GOTREF(ctx, obj, lineno) cdef void DECREF(PyObject* ctx, PyObject* obj, Py_ssize_t lineno): if GIVEREF_and_report(ctx, obj, lineno): Py_XDECREF(obj) PyThreadState_Get() # Check that we hold the GIL cdef void FinishContext(PyObject** ctx): if ctx == NULL or ctx[0] == NULL: return cdef (PyObject*) type = NULL, value = NULL, tb = NULL cdef object errors = None cdef Context context PyThreadState_Get() # Check that we hold the GIL PyErr_Fetch(&type, &value, &tb) try: context = ctx[0] errors = context.end() if errors: print(f"{context.filename.decode('latin1')}: {context.name.decode('latin1')}()") print(errors) context = None except: report_unraisable( context.filename if context is not None else None, lineno=context.start if context is not None else 0, ) finally: Py_CLEAR(ctx[0]) PyErr_Restore(type, value, tb) return # swallow any exceptions ctypedef struct RefNannyAPIStruct: void (*INCREF)(PyObject*, PyObject*, Py_ssize_t) void (*DECREF)(PyObject*, PyObject*, Py_ssize_t) void (*GOTREF)(PyObject*, PyObject*, Py_ssize_t) void (*GIVEREF)(PyObject*, PyObject*, Py_ssize_t) PyObject* (*SetupContext)(char*, Py_ssize_t, char*) except NULL void (*FinishContext)(PyObject**) cdef RefNannyAPIStruct api api.INCREF = INCREF api.DECREF = DECREF api.GOTREF = GOTREF api.GIVEREF = GIVEREF api.SetupContext = SetupContext api.FinishContext = FinishContext cdef extern from "Python.h": object PyLong_FromVoidPtr(void*) RefNannyAPI = PyLong_FromVoidPtr(&api) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Shadow.py0000644000175100001770000004157500000000000016653 0ustar00runnerdocker00000000000000# cython.* namespace for pure mode. from __future__ import absolute_import # Possible version formats: "3.1.0", "3.1.0a1", "3.1.0a1.dev0" __version__ = "3.0.8" try: from __builtin__ import basestring except ImportError: basestring = str # BEGIN shameless copy from Cython/minivect/minitypes.py class _ArrayType(object): is_array = True subtypes = ['dtype'] def __init__(self, dtype, ndim, is_c_contig=False, is_f_contig=False, inner_contig=False, broadcasting=None): self.dtype = dtype self.ndim = ndim self.is_c_contig = is_c_contig self.is_f_contig = is_f_contig self.inner_contig = inner_contig or is_c_contig or is_f_contig self.broadcasting = broadcasting def __repr__(self): axes = [":"] * self.ndim if self.is_c_contig: axes[-1] = "::1" elif self.is_f_contig: axes[0] = "::1" return "%s[%s]" % (self.dtype, ", ".join(axes)) def index_type(base_type, item): """ Support array type creation by slicing, e.g. double[:, :] specifies a 2D strided array of doubles. The syntax is the same as for Cython memoryviews. """ class InvalidTypeSpecification(Exception): pass def verify_slice(s): if s.start or s.stop or s.step not in (None, 1): raise InvalidTypeSpecification( "Only a step of 1 may be provided to indicate C or " "Fortran contiguity") if isinstance(item, tuple): step_idx = None for idx, s in enumerate(item): verify_slice(s) if s.step and (step_idx or idx not in (0, len(item) - 1)): raise InvalidTypeSpecification( "Step may only be provided once, and only in the " "first or last dimension.") if s.step == 1: step_idx = idx return _ArrayType(base_type, len(item), is_c_contig=step_idx == len(item) - 1, is_f_contig=step_idx == 0) elif isinstance(item, slice): verify_slice(item) return _ArrayType(base_type, 1, is_c_contig=bool(item.step)) else: # int[8] etc. assert int(item) == item # array size must be a plain integer return array(base_type, item) # END shameless copy compiled = False _Unspecified = object() # Function decorators def _empty_decorator(x): return x def locals(**arg_types): return _empty_decorator def test_assert_path_exists(*paths): return _empty_decorator def test_fail_if_path_exists(*paths): return _empty_decorator class _EmptyDecoratorAndManager(object): def __call__(self, x): return x def __enter__(self): pass def __exit__(self, exc_type, exc_value, traceback): pass class _Optimization(object): pass cclass = ccall = cfunc = _EmptyDecoratorAndManager() annotation_typing = returns = wraparound = boundscheck = initializedcheck = \ nonecheck = embedsignature = cdivision = cdivision_warnings = \ always_allow_keywords = profile = linetrace = infer_types = \ unraisable_tracebacks = freelist = auto_pickle = cpow = trashcan = \ auto_cpdef = c_api_binop_methods = \ allow_none_for_extension_args = callspec = show_performance_hints = \ cpp_locals = py2_import = iterable_coroutine = remove_unreachable = \ lambda _: _EmptyDecoratorAndManager() # Note that fast_getattr is untested and undocumented! fast_getattr = lambda _: _EmptyDecoratorAndManager() exceptval = lambda _=None, check=True: _EmptyDecoratorAndManager() overflowcheck = lambda _: _EmptyDecoratorAndManager() optimize = _Optimization() embedsignature.format = overflowcheck.fold = optimize.use_switch = \ optimize.unpack_method_calls = lambda arg: _EmptyDecoratorAndManager() final = internal = type_version_tag = no_gc_clear = no_gc = total_ordering = \ ufunc = _empty_decorator binding = lambda _: _empty_decorator class warn: undeclared = unreachable = maybe_uninitialized = unused = \ unused_arg = unused_result = \ lambda _: _EmptyDecoratorAndManager() _cython_inline = None def inline(f, *args, **kwds): if isinstance(f, basestring): global _cython_inline if _cython_inline is None: from Cython.Build.Inline import cython_inline as _cython_inline return _cython_inline(f, *args, **kwds) else: assert len(args) == len(kwds) == 0 return f def compile(f): from Cython.Build.Inline import RuntimeCompiledFunction return RuntimeCompiledFunction(f) # Special functions def cdiv(a, b): if a < 0: a = -a b = -b if b < 0: return (a + b + 1) // b return a // b def cmod(a, b): r = a % b if (a * b) < 0 and r: r -= b return r # Emulated language constructs def cast(t, *args, **kwargs): kwargs.pop('typecheck', None) assert not kwargs if isinstance(t, typedef): return t(*args) elif isinstance(t, type): # Doesn't work with old-style classes of Python 2.x if len(args) != 1 or not (args[0] is None or isinstance(args[0], t)): return t(*args) return args[0] def sizeof(arg): return 1 def typeof(arg): return arg.__class__.__name__ # return type(arg) def address(arg): return pointer(type(arg))([arg]) def _is_value_type(t): if isinstance(t, typedef): return _is_value_type(t._basetype) return isinstance(t, type) and issubclass(t, (StructType, UnionType, ArrayType)) def declare(t=None, value=_Unspecified, **kwds): if value is not _Unspecified: return cast(t, value) elif _is_value_type(t): return t() else: return None class _nogil(object): """Support for 'with nogil' statement and @nogil decorator. """ def __call__(self, x): if callable(x): # Used as function decorator => return the function unchanged. return x # Used as conditional context manager or to create an "@nogil(True/False)" decorator => keep going. return self def __enter__(self): pass def __exit__(self, exc_class, exc, tb): return exc_class is None nogil = _nogil() gil = _nogil() with_gil = _nogil() # Actually not a context manager, but compilation will give the right error. del _nogil # Emulated types class CythonMetaType(type): def __getitem__(type, ix): return array(type, ix) CythonTypeObject = CythonMetaType('CythonTypeObject', (object,), {}) class CythonType(CythonTypeObject): def _pointer(self, n=1): for i in range(n): self = pointer(self) return self class PointerType(CythonType): def __init__(self, value=None): if isinstance(value, (ArrayType, PointerType)): self._items = [cast(self._basetype, a) for a in value._items] elif isinstance(value, list): self._items = [cast(self._basetype, a) for a in value] elif value is None or value == 0: self._items = [] else: raise ValueError def __getitem__(self, ix): if ix < 0: raise IndexError("negative indexing not allowed in C") return self._items[ix] def __setitem__(self, ix, value): if ix < 0: raise IndexError("negative indexing not allowed in C") self._items[ix] = cast(self._basetype, value) def __eq__(self, value): if value is None and not self._items: return True elif type(self) != type(value): return False else: return not self._items and not value._items def __repr__(self): return "%s *" % (self._basetype,) class ArrayType(PointerType): def __init__(self, value=None): if value is None: self._items = [None] * self._n else: super(ArrayType, self).__init__(value) class StructType(CythonType): def __init__(self, *posargs, **data): if not (posargs or data): return if posargs and data: raise ValueError('Cannot accept both positional and keyword arguments.') # Allow 'cast_from' as single positional or keyword argument. if data and len(data) == 1 and 'cast_from' in data: cast_from = data.pop('cast_from') elif len(posargs) == 1 and type(posargs[0]) is type(self): cast_from, posargs = posargs[0], () elif posargs: for key, arg in zip(self._members, posargs): setattr(self, key, arg) return else: for key, value in data.items(): if key not in self._members: raise ValueError("Invalid struct attribute for %s: %s" % ( self.__class__.__name__, key)) setattr(self, key, value) return # do cast if data: raise ValueError('Cannot accept keyword arguments when casting.') if type(cast_from) is not type(self): raise ValueError('Cannot cast from %s' % cast_from) for key, value in cast_from.__dict__.items(): setattr(self, key, value) def __setattr__(self, key, value): if key in self._members: self.__dict__[key] = cast(self._members[key], value) else: raise AttributeError("Struct has no member '%s'" % key) class UnionType(CythonType): def __init__(self, cast_from=_Unspecified, **data): if cast_from is not _Unspecified: # do type cast if len(data) > 0: raise ValueError('Cannot accept keyword arguments when casting.') if isinstance(cast_from, dict): datadict = cast_from elif type(cast_from) is type(self): datadict = cast_from.__dict__ else: raise ValueError('Cannot cast from %s' % cast_from) else: datadict = data if len(datadict) > 1: raise AttributeError("Union can only store one field at a time.") for key, value in datadict.items(): setattr(self, key, value) def __setattr__(self, key, value): if key == '__dict__': CythonType.__setattr__(self, key, value) elif key in self._members: self.__dict__ = {key: cast(self._members[key], value)} else: raise AttributeError("Union has no member '%s'" % key) def pointer(basetype): class PointerInstance(PointerType): _basetype = basetype return PointerInstance def array(basetype, n): class ArrayInstance(ArrayType): _basetype = basetype _n = n return ArrayInstance def struct(**members): class StructInstance(StructType): _members = members for key in members: setattr(StructInstance, key, None) return StructInstance def union(**members): class UnionInstance(UnionType): _members = members for key in members: setattr(UnionInstance, key, None) return UnionInstance class typedef(CythonType): def __init__(self, type, name=None): self._basetype = type self.name = name def __call__(self, *arg): value = cast(self._basetype, *arg) return value def __repr__(self): return self.name or str(self._basetype) __getitem__ = index_type class _FusedType(CythonType): __getitem__ = index_type def fused_type(*args): if not args: raise TypeError("Expected at least one type as argument") # Find the numeric type with biggest rank if all types are numeric rank = -1 for type in args: if type not in (py_int, py_long, py_float, py_complex): break if type_ordering.index(type) > rank: result_type = type else: return result_type # Not a simple numeric type, return a fused type instance. The result # isn't really meant to be used, as we can't keep track of the context in # pure-mode. Casting won't do anything in this case. return _FusedType() def _specialized_from_args(signatures, args, kwargs): "Perhaps this should be implemented in a TreeFragment in Cython code" raise Exception("yet to be implemented") py_int = typedef(int, "int") try: py_long = typedef(long, "long") except NameError: # Py3 py_long = typedef(int, "long") py_float = typedef(float, "float") py_complex = typedef(complex, "double complex") # Predefined types int_types = [ 'char', 'short', 'Py_UNICODE', 'int', 'Py_UCS4', 'long', 'longlong', 'Py_hash_t', 'Py_ssize_t', 'size_t', 'ssize_t', 'ptrdiff_t', ] float_types = [ 'longdouble', 'double', 'float', ] complex_types = [ 'longdoublecomplex', 'doublecomplex', 'floatcomplex', 'complex', ] other_types = [ 'bint', 'void', 'Py_tss_t', ] to_repr = { 'longlong': 'long long', 'longdouble': 'long double', 'longdoublecomplex': 'long double complex', 'doublecomplex': 'double complex', 'floatcomplex': 'float complex', }.get gs = globals() # note: cannot simply name the unicode type here as 2to3 gets in the way and replaces it by str try: import __builtin__ as builtins except ImportError: # Py3 import builtins gs['unicode'] = typedef(getattr(builtins, 'unicode', str), 'unicode') del builtins for name in int_types: reprname = to_repr(name, name) gs[name] = typedef(py_int, reprname) if name not in ('Py_UNICODE', 'Py_UCS4', 'Py_hash_t', 'ptrdiff_t') and not name.endswith('size_t'): gs['u'+name] = typedef(py_int, "unsigned " + reprname) gs['s'+name] = typedef(py_int, "signed " + reprname) for name in float_types: gs[name] = typedef(py_float, to_repr(name, name)) for name in complex_types: gs[name] = typedef(py_complex, to_repr(name, name)) bint = typedef(bool, "bint") void = typedef(None, "void") Py_tss_t = typedef(None, "Py_tss_t") for t in int_types: for i in range(1, 4): gs["%s_%s" % ('p'*i, t)] = gs[t]._pointer(i) if 'u'+t in gs: gs["%s_u%s" % ('p'*i, t)] = gs['u'+t]._pointer(i) gs["%s_s%s" % ('p'*i, t)] = gs['s'+t]._pointer(i) for t in float_types + complex_types + other_types: for i in range(1, 4): gs["%s_%s" % ('p'*i, t)] = gs[t]._pointer(i) del t, i NULL = gs['p_void'](0) # looks like 'gs' has some users out there by now... #del gs integral = floating = numeric = _FusedType() type_ordering = [py_int, py_long, py_float, py_complex] class CythonDotParallel(object): """ The cython.parallel module. """ __all__ = ['parallel', 'prange', 'threadid'] def parallel(self, num_threads=None): return nogil def prange(self, start=0, stop=None, step=1, nogil=False, schedule=None, chunksize=None, num_threads=None): if stop is None: stop = start start = 0 return range(start, stop, step) def threadid(self): return 0 # def threadsavailable(self): # return 1 class CythonDotImportedFromElsewhere(object): """ cython.dataclasses just shadows the standard library modules of the same name """ def __init__(self, module): self.__path__ = [] self.__file__ = None self.__name__ = module self.__package__ = module def __getattr__(self, attr): # we typically only expect this to be called once from importlib import import_module import sys try: mod = import_module(self.__name__) except ImportError: # but if they don't exist (Python is not sufficiently up-to-date) then # you can't use them raise AttributeError("%s: the standard library module %s is not available" % (attr, self.__name__)) sys.modules['cython.%s' % self.__name__] = mod return getattr(mod, attr) class CythonCImports(object): """ Simplistic module mock to make cimports sort-of work in Python code. """ def __init__(self, module): self.__path__ = [] self.__file__ = None self.__name__ = module self.__package__ = module def __getattr__(self, item): if item.startswith('__') and item.endswith('__'): raise AttributeError(item) try: return __import__(item) except ImportError: import sys ex = AttributeError(item) if sys.version_info >= (3, 0): ex.__cause__ = None raise ex import math, sys sys.modules['cython.parallel'] = CythonDotParallel() sys.modules['cython.cimports'] = CythonCImports('cython.cimports') sys.modules['cython.cimports.libc'] = CythonCImports('cython.cimports.libc') sys.modules['cython.cimports.libc.math'] = math # In pure Python mode @cython.dataclasses.dataclass and dataclass field should just # shadow the standard library ones (if they are available) dataclasses = sys.modules['cython.dataclasses'] = CythonDotImportedFromElsewhere('dataclasses') del math, sys ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Shadow.pyi0000644000175100001770000000521100000000000017007 0ustar00runnerdocker00000000000000from builtins import (int as py_int, float as py_float, bool as py_bool, str as py_str, complex as py_complex) from typing import (Union, Dict, Any, Sequence, Optional, List, TypeVar, Type, Generic) int = py_int long = py_int longlong = py_int short = py_int char = py_int sint = py_int slong = py_int slonglong = py_int sshort = py_int schar = py_int uint = py_int ulong = py_int ulonglong = py_int ushort = py_int uchar = py_int size_t = py_int Py_ssize_t = py_int Py_UCS4 = Union[py_int, str] Py_UNICODE = Union[py_int, str] float = py_float double = py_float longdouble = py_float complex = py_complex floatcomplex = py_complex doublecomplex = py_complex longdoublecomplex = py_complex bint = py_bool void = Union[None] basestring = py_str unicode = py_str gs: Dict[str, Any] # Should match the return type of globals() _T = TypeVar('_T') class _ArrayType(object, Generic[_T]): is_array: bool subtypes: Sequence[str] dtype: _T ndim: int is_c_contig: bool is_f_contig: bool inner_contig: bool broadcasting: Any # broadcasting is not used, so it's not clear about its type def __init__(self, dtype: _T, ndim: int, is_c_contig: bool = ..., is_f_contig: bool = ..., inner_contig: bool = ..., broadcasting: Any = ...) -> None: ... def __repr__(self) -> str: ... class CythonTypeObject(object): ... class CythonType(CythonTypeObject): ... class PointerType(CythonType, Generic[_T]): def __init__( self, value: Optional[Union[ArrayType[_T], PointerType[_T], List[_T], int]] = ... ) -> None: ... def __getitem__(self, ix: int) -> _T: ... def __setitem__(self, ix: int, value: _T) -> None: ... def __eq__(self, value: object) -> bool: ... def __repr__(self) -> str: ... class ArrayType(PointerType[_T]): def __init__(self) -> None: ... #class StructType(CythonType, Generic[_T]): # def __init__( # self, # value: List[Type[_T]] = ... # ) -> None: ... def index_type( base_type: _T, item: Union[tuple, slice, int]) -> _ArrayType[_T]: ... def pointer(basetype: _T) -> Type[PointerType[_T]]: ... def array(basetype: _T, n: int) -> Type[ArrayType[_T]]: ... #def struct(basetype: _T) -> Type[StructType[_T]]: ... class typedef(CythonType, Generic[_T]): name: str def __init__(self, type: _T, name: Optional[str] = ...) -> None: ... def __call__(self, *arg: Any) -> _T: ... def __repr__(self) -> str: ... __getitem__ = index_type #class _FusedType(CythonType, Generic[_T]): # def __init__(self) -> None: ... #def fused_type(*args: Tuple[_T]) -> Type[FusedType[_T]]: ... ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/StringIOTree.pxd0000644000175100001770000000111500000000000020071 0ustar00runnerdocker00000000000000cimport cython cdef object StringIO @cython.final cdef class StringIOTree: cdef public list prepended_children cdef public object stream cdef public object write cdef public list markers cpdef bint empty(self) @cython.locals(x=StringIOTree) cpdef getvalue(self) @cython.locals(x=StringIOTree) cdef _collect_in(self, list target_list) @cython.locals(child=StringIOTree) cpdef copyto(self, target) cpdef commit(self) #def insert(self, iotree) #def insertion_point(self) @cython.locals(c=StringIOTree) cpdef allmarkers(self) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/StringIOTree.py0000644000175100001770000001315100000000000017731 0ustar00runnerdocker00000000000000# cython: auto_pickle=False r""" Implements a buffer with insertion points. When you know you need to "get back" to a place and write more later, simply call insertion_point() at that spot and get a new StringIOTree object that is "left behind". EXAMPLE: >>> a = StringIOTree() >>> _= a.write('first\n') >>> b = a.insertion_point() >>> _= a.write('third\n') >>> _= b.write('second\n') >>> a.getvalue().split() ['first', 'second', 'third'] >>> c = b.insertion_point() >>> d = c.insertion_point() >>> _= d.write('alpha\n') >>> _= b.write('gamma\n') >>> _= c.write('beta\n') >>> b.getvalue().split() ['second', 'alpha', 'beta', 'gamma'] >>> try: from cStringIO import StringIO ... except ImportError: from io import StringIO >>> i = StringIOTree() >>> d.insert(i) >>> _= i.write('inserted\n') >>> out = StringIO() >>> a.copyto(out) >>> out.getvalue().split() ['first', 'second', 'alpha', 'inserted', 'beta', 'gamma', 'third'] """ from __future__ import absolute_import #, unicode_literals try: # Prefer cStringIO since io.StringIO() does not support writing 'str' in Py2. from cStringIO import StringIO except ImportError: from io import StringIO class StringIOTree(object): """ See module docs. """ def __init__(self, stream=None): self.prepended_children = [] if stream is None: stream = StringIO() self.stream = stream self.write = stream.write self.markers = [] def empty(self): if self.stream.tell(): return False return all([child.empty() for child in self.prepended_children]) if self.prepended_children else True def getvalue(self): content = [] self._collect_in(content) return "".join(content) def _collect_in(self, target_list): for x in self.prepended_children: x._collect_in(target_list) stream_content = self.stream.getvalue() if stream_content: target_list.append(stream_content) def copyto(self, target): """Potentially cheaper than getvalue as no string concatenation needs to happen.""" for child in self.prepended_children: child.copyto(target) stream_content = self.stream.getvalue() if stream_content: target.write(stream_content) def commit(self): # Save what we have written until now so that the buffer # itself is empty -- this makes it ready for insertion if self.stream.tell(): self.prepended_children.append(StringIOTree(self.stream)) self.prepended_children[-1].markers = self.markers self.markers = [] self.stream = StringIO() self.write = self.stream.write def reset(self): self.prepended_children = [] self.markers = [] self.stream = StringIO() self.write = self.stream.write def insert(self, iotree): """ Insert a StringIOTree (and all of its contents) at this location. Further writing to self appears after what is inserted. """ self.commit() self.prepended_children.append(iotree) def insertion_point(self): """ Returns a new StringIOTree, which is left behind at the current position (it what is written to the result will appear right before whatever is next written to self). Calling getvalue() or copyto() on the result will only return the contents written to it. """ # Save what we have written until now # This is so that getvalue on the result doesn't include it. self.commit() # Construct the new forked object to return other = StringIOTree() self.prepended_children.append(other) return other def allmarkers(self): children = self.prepended_children return [m for c in children for m in c.allmarkers()] + self.markers """ # Print the result of allmarkers in a nice human-readable form. Use it only for debugging. # Prints e.g. # /path/to/source.pyx: # cython line 2 maps to 3299-3343 # cython line 4 maps to 2236-2245 2306 3188-3201 # /path/to/othersource.pyx: # cython line 3 maps to 1234-1270 # ... # Note: In the example above, 3343 maps to line 2, 3344 does not. def print_hr_allmarkers(self): from collections import defaultdict markers = self.allmarkers() totmap = defaultdict(lambda: defaultdict(list)) for c_lineno, (cython_desc, cython_lineno) in enumerate(markers): if cython_lineno > 0 and cython_desc.filename is not None: totmap[cython_desc.filename][cython_lineno].append(c_lineno + 1) reprstr = "" if totmap == 0: reprstr += "allmarkers is empty\n" try: sorted(totmap.items()) except: print(totmap) print(totmap.items()) for cython_path, filemap in sorted(totmap.items()): reprstr += cython_path + ":\n" for cython_lineno, c_linenos in sorted(filemap.items()): reprstr += "\tcython line " + str(cython_lineno) + " maps to " i = 0 while i < len(c_linenos): reprstr += str(c_linenos[i]) flag = False while i+1 < len(c_linenos) and c_linenos[i+1] == c_linenos[i]+1: i += 1 flag = True if flag: reprstr += "-" + str(c_linenos[i]) + " " i += 1 reprstr += "\n" import sys sys.stdout.write(reprstr) """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.012724 Cython-3.0.8/Cython/Tempita/0000755000175100001770000000000000000000000016443 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Tempita/__init__.py0000644000175100001770000000023000000000000020547 0ustar00runnerdocker00000000000000# The original Tempita implements all of its templating code here. # Moved it to _tempita.py to make the compilation portable. from ._tempita import * ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Tempita/_looper.py0000644000175100001770000001011000000000000020445 0ustar00runnerdocker00000000000000""" Helper for looping over sequences, particular in templates. Often in a loop in a template it's handy to know what's next up, previously up, if this is the first or last item in the sequence, etc. These can be awkward to manage in a normal Python loop, but using the looper you can get a better sense of the context. Use like:: >>> for loop, item in looper(['a', 'b', 'c']): ... print loop.number, item ... if not loop.last: ... print '---' 1 a --- 2 b --- 3 c """ import sys from Cython.Tempita.compat3 import basestring_ __all__ = ['looper'] class looper(object): """ Helper for looping (particularly in templates) Use this like:: for loop, item in looper(seq): if loop.first: ... """ def __init__(self, seq): self.seq = seq def __iter__(self): return looper_iter(self.seq) def __repr__(self): return '<%s for %r>' % ( self.__class__.__name__, self.seq) class looper_iter(object): def __init__(self, seq): self.seq = list(seq) self.pos = 0 def __iter__(self): return self def __next__(self): if self.pos >= len(self.seq): raise StopIteration result = loop_pos(self.seq, self.pos), self.seq[self.pos] self.pos += 1 return result if sys.version < "3": next = __next__ class loop_pos(object): def __init__(self, seq, pos): self.seq = seq self.pos = pos def __repr__(self): return '' % ( self.seq[self.pos], self.pos) def index(self): return self.pos index = property(index) def number(self): return self.pos + 1 number = property(number) def item(self): return self.seq[self.pos] item = property(item) def __next__(self): try: return self.seq[self.pos + 1] except IndexError: return None __next__ = property(__next__) if sys.version < "3": next = __next__ def previous(self): if self.pos == 0: return None return self.seq[self.pos - 1] previous = property(previous) def odd(self): return not self.pos % 2 odd = property(odd) def even(self): return self.pos % 2 even = property(even) def first(self): return self.pos == 0 first = property(first) def last(self): return self.pos == len(self.seq) - 1 last = property(last) def length(self): return len(self.seq) length = property(length) def first_group(self, getter=None): """ Returns true if this item is the start of a new group, where groups mean that some attribute has changed. The getter can be None (the item itself changes), an attribute name like ``'.attr'``, a function, or a dict key or list index. """ if self.first: return True return self._compare_group(self.item, self.previous, getter) def last_group(self, getter=None): """ Returns true if this item is the end of a new group, where groups mean that some attribute has changed. The getter can be None (the item itself changes), an attribute name like ``'.attr'``, a function, or a dict key or list index. """ if self.last: return True return self._compare_group(self.item, self.__next__, getter) def _compare_group(self, item, other, getter): if getter is None: return item != other elif (isinstance(getter, basestring_) and getter.startswith('.')): getter = getter[1:] if getter.endswith('()'): getter = getter[:-2] return getattr(item, getter)() != getattr(other, getter)() else: return getattr(item, getter) != getattr(other, getter) elif hasattr(getter, '__call__'): return getter(item) != getter(other) else: return item[getter] != other[getter] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Tempita/_tempita.py0000644000175100001770000011142200000000000020620 0ustar00runnerdocker00000000000000# cython: language_level=3str """ A small templating language This implements a small templating language. This language implements if/elif/else, for/continue/break, expressions, and blocks of Python code. The syntax is:: {{any expression (function calls etc)}} {{any expression | filter}} {{for x in y}}...{{endfor}} {{if x}}x{{elif y}}y{{else}}z{{endif}} {{py:x=1}} {{py: def foo(bar): return 'baz' }} {{default var = default_value}} {{# comment}} You use this with the ``Template`` class or the ``sub`` shortcut. The ``Template`` class takes the template string and the name of the template (for errors) and a default namespace. Then (like ``string.Template``) you can call the ``tmpl.substitute(**kw)`` method to make a substitution (or ``tmpl.substitute(a_dict)``). ``sub(content, **kw)`` substitutes the template immediately. You can use ``__name='tmpl.html'`` to set the name of the template. If there are syntax errors ``TemplateError`` will be raised. """ from __future__ import absolute_import import re import sys import os import tokenize from io import StringIO from ._looper import looper from .compat3 import bytes, unicode_, basestring_, next, is_unicode, coerce_text __all__ = ['TemplateError', 'Template', 'sub', 'bunch'] in_re = re.compile(r'\s+in\s+') var_re = re.compile(r'^[a-z_][a-z0-9_]*$', re.I) class TemplateError(Exception): """Exception raised while parsing a template """ def __init__(self, message, position, name=None): Exception.__init__(self, message) self.position = position self.name = name def __str__(self): msg = ' '.join(self.args) if self.position: msg = '%s at line %s column %s' % ( msg, self.position[0], self.position[1]) if self.name: msg += ' in %s' % self.name return msg class _TemplateContinue(Exception): pass class _TemplateBreak(Exception): pass def get_file_template(name, from_template): path = os.path.join(os.path.dirname(from_template.name), name) return from_template.__class__.from_filename( path, namespace=from_template.namespace, get_template=from_template.get_template) class Template(object): default_namespace = { 'start_braces': '{{', 'end_braces': '}}', 'looper': looper, } default_encoding = 'utf8' default_inherit = None def __init__(self, content, name=None, namespace=None, stacklevel=None, get_template=None, default_inherit=None, line_offset=0, delimiters=None, delimeters=None): self.content = content # set delimiters if delimeters: import warnings warnings.warn( "'delimeters' kwarg is being deprecated in favor of correctly" " spelled 'delimiters'. Please adjust your code.", DeprecationWarning ) if delimiters is None: delimiters = delimeters if delimiters is None: delimiters = (self.default_namespace['start_braces'], self.default_namespace['end_braces']) else: #assert len(delimiters) == 2 and all([isinstance(delimiter, basestring) # for delimiter in delimiters]) self.default_namespace = self.__class__.default_namespace.copy() self.default_namespace['start_braces'] = delimiters[0] self.default_namespace['end_braces'] = delimiters[1] self.delimiters = self.delimeters = delimiters # Keep a legacy read-only copy, but don't use it. self._unicode = is_unicode(content) if name is None and stacklevel is not None: try: caller = sys._getframe(stacklevel) except ValueError: pass else: globals = caller.f_globals lineno = caller.f_lineno if '__file__' in globals: name = globals['__file__'] if name.endswith('.pyc') or name.endswith('.pyo'): name = name[:-1] elif '__name__' in globals: name = globals['__name__'] else: name = '' if lineno: name += ':%s' % lineno self.name = name self._parsed = parse(content, name=name, line_offset=line_offset, delimiters=self.delimiters) if namespace is None: namespace = {} self.namespace = namespace self.get_template = get_template if default_inherit is not None: self.default_inherit = default_inherit def from_filename(cls, filename, namespace=None, encoding=None, default_inherit=None, get_template=get_file_template): with open(filename, 'rb') as f: c = f.read() if encoding: c = c.decode(encoding) return cls(content=c, name=filename, namespace=namespace, default_inherit=default_inherit, get_template=get_template) from_filename = classmethod(from_filename) def __repr__(self): return '<%s %s name=%r>' % ( self.__class__.__name__, hex(id(self))[2:], self.name) def substitute(self, *args, **kw): if args: if kw: raise TypeError( "You can only give positional *or* keyword arguments") if len(args) > 1: raise TypeError( "You can only give one positional argument") if not hasattr(args[0], 'items'): raise TypeError( "If you pass in a single argument, you must pass in a dictionary-like object (with a .items() method); you gave %r" % (args[0],)) kw = args[0] ns = kw ns['__template_name__'] = self.name if self.namespace: ns.update(self.namespace) result, defs, inherit = self._interpret(ns) if not inherit: inherit = self.default_inherit if inherit: result = self._interpret_inherit(result, defs, inherit, ns) return result def _interpret(self, ns): __traceback_hide__ = True parts = [] defs = {} self._interpret_codes(self._parsed, ns, out=parts, defs=defs) if '__inherit__' in defs: inherit = defs.pop('__inherit__') else: inherit = None return ''.join(parts), defs, inherit def _interpret_inherit(self, body, defs, inherit_template, ns): __traceback_hide__ = True if not self.get_template: raise TemplateError( 'You cannot use inheritance without passing in get_template', position=None, name=self.name) templ = self.get_template(inherit_template, self) self_ = TemplateObject(self.name) for name, value in defs.items(): setattr(self_, name, value) self_.body = body ns = ns.copy() ns['self'] = self_ return templ.substitute(ns) def _interpret_codes(self, codes, ns, out, defs): __traceback_hide__ = True for item in codes: if isinstance(item, basestring_): out.append(item) else: self._interpret_code(item, ns, out, defs) def _interpret_code(self, code, ns, out, defs): __traceback_hide__ = True name, pos = code[0], code[1] if name == 'py': self._exec(code[2], ns, pos) elif name == 'continue': raise _TemplateContinue() elif name == 'break': raise _TemplateBreak() elif name == 'for': vars, expr, content = code[2], code[3], code[4] expr = self._eval(expr, ns, pos) self._interpret_for(vars, expr, content, ns, out, defs) elif name == 'cond': parts = code[2:] self._interpret_if(parts, ns, out, defs) elif name == 'expr': parts = code[2].split('|') base = self._eval(parts[0], ns, pos) for part in parts[1:]: func = self._eval(part, ns, pos) base = func(base) out.append(self._repr(base, pos)) elif name == 'default': var, expr = code[2], code[3] if var not in ns: result = self._eval(expr, ns, pos) ns[var] = result elif name == 'inherit': expr = code[2] value = self._eval(expr, ns, pos) defs['__inherit__'] = value elif name == 'def': name = code[2] signature = code[3] parts = code[4] ns[name] = defs[name] = TemplateDef(self, name, signature, body=parts, ns=ns, pos=pos) elif name == 'comment': return else: assert 0, "Unknown code: %r" % name def _interpret_for(self, vars, expr, content, ns, out, defs): __traceback_hide__ = True for item in expr: if len(vars) == 1: ns[vars[0]] = item else: if len(vars) != len(item): raise ValueError( 'Need %i items to unpack (got %i items)' % (len(vars), len(item))) for name, value in zip(vars, item): ns[name] = value try: self._interpret_codes(content, ns, out, defs) except _TemplateContinue: continue except _TemplateBreak: break def _interpret_if(self, parts, ns, out, defs): __traceback_hide__ = True # @@: if/else/else gets through for part in parts: assert not isinstance(part, basestring_) name, pos = part[0], part[1] if name == 'else': result = True else: result = self._eval(part[2], ns, pos) if result: self._interpret_codes(part[3], ns, out, defs) break def _eval(self, code, ns, pos): __traceback_hide__ = True try: try: value = eval(code, self.default_namespace, ns) except SyntaxError as e: raise SyntaxError( 'invalid syntax in expression: %s' % code) return value except Exception as e: if getattr(e, 'args', None): arg0 = e.args[0] else: arg0 = coerce_text(e) e.args = (self._add_line_info(arg0, pos),) raise def _exec(self, code, ns, pos): __traceback_hide__ = True try: exec(code, self.default_namespace, ns) except Exception as e: if e.args: e.args = (self._add_line_info(e.args[0], pos),) else: e.args = (self._add_line_info(None, pos),) raise def _repr(self, value, pos): __traceback_hide__ = True try: if value is None: return '' if self._unicode: try: value = unicode_(value) except UnicodeDecodeError: value = bytes(value) else: if not isinstance(value, basestring_): value = coerce_text(value) if (is_unicode(value) and self.default_encoding): value = value.encode(self.default_encoding) except Exception as e: e.args = (self._add_line_info(e.args[0], pos),) raise else: if self._unicode and isinstance(value, bytes): if not self.default_encoding: raise UnicodeDecodeError( 'Cannot decode bytes value %r into unicode ' '(no default_encoding provided)' % value) try: value = value.decode(self.default_encoding) except UnicodeDecodeError as e: raise UnicodeDecodeError( e.encoding, e.object, e.start, e.end, e.reason + ' in string %r' % value) elif not self._unicode and is_unicode(value): if not self.default_encoding: raise UnicodeEncodeError( 'Cannot encode unicode value %r into bytes ' '(no default_encoding provided)' % value) value = value.encode(self.default_encoding) return value def _add_line_info(self, msg, pos): msg = "%s at line %s column %s" % ( msg, pos[0], pos[1]) if self.name: msg += " in file %s" % self.name return msg def sub(content, delimiters=None, **kw): name = kw.get('__name') delimeters = kw.pop('delimeters') if 'delimeters' in kw else None # for legacy code tmpl = Template(content, name=name, delimiters=delimiters, delimeters=delimeters) return tmpl.substitute(kw) def paste_script_template_renderer(content, vars, filename=None): tmpl = Template(content, name=filename) return tmpl.substitute(vars) class bunch(dict): def __init__(self, **kw): for name, value in kw.items(): setattr(self, name, value) def __setattr__(self, name, value): self[name] = value def __getattr__(self, name): try: return self[name] except KeyError: raise AttributeError(name) def __getitem__(self, key): if 'default' in self: try: return dict.__getitem__(self, key) except KeyError: return dict.__getitem__(self, 'default') else: return dict.__getitem__(self, key) def __repr__(self): return '<%s %s>' % ( self.__class__.__name__, ' '.join(['%s=%r' % (k, v) for k, v in sorted(self.items())])) class TemplateDef(object): def __init__(self, template, func_name, func_signature, body, ns, pos, bound_self=None): self._template = template self._func_name = func_name self._func_signature = func_signature self._body = body self._ns = ns self._pos = pos self._bound_self = bound_self def __repr__(self): return '' % ( self._func_name, self._func_signature, self._template.name, self._pos) def __str__(self): return self() def __call__(self, *args, **kw): values = self._parse_signature(args, kw) ns = self._ns.copy() ns.update(values) if self._bound_self is not None: ns['self'] = self._bound_self out = [] subdefs = {} self._template._interpret_codes(self._body, ns, out, subdefs) return ''.join(out) def __get__(self, obj, type=None): if obj is None: return self return self.__class__( self._template, self._func_name, self._func_signature, self._body, self._ns, self._pos, bound_self=obj) def _parse_signature(self, args, kw): values = {} sig_args, var_args, var_kw, defaults = self._func_signature extra_kw = {} for name, value in kw.items(): if not var_kw and name not in sig_args: raise TypeError( 'Unexpected argument %s' % name) if name in sig_args: values[sig_args] = value else: extra_kw[name] = value args = list(args) sig_args = list(sig_args) while args: while sig_args and sig_args[0] in values: sig_args.pop(0) if sig_args: name = sig_args.pop(0) values[name] = args.pop(0) elif var_args: values[var_args] = tuple(args) break else: raise TypeError( 'Extra position arguments: %s' % ', '.join([repr(v) for v in args])) for name, value_expr in defaults.items(): if name not in values: values[name] = self._template._eval( value_expr, self._ns, self._pos) for name in sig_args: if name not in values: raise TypeError( 'Missing argument: %s' % name) if var_kw: values[var_kw] = extra_kw return values class TemplateObject(object): def __init__(self, name): self.__name = name self.get = TemplateObjectGetter(self) def __repr__(self): return '<%s %s>' % (self.__class__.__name__, self.__name) class TemplateObjectGetter(object): def __init__(self, template_obj): self.__template_obj = template_obj def __getattr__(self, attr): return getattr(self.__template_obj, attr, Empty) def __repr__(self): return '<%s around %r>' % (self.__class__.__name__, self.__template_obj) class _Empty(object): def __call__(self, *args, **kw): return self def __str__(self): return '' def __repr__(self): return 'Empty' def __unicode__(self): return u'' def __iter__(self): return iter(()) def __bool__(self): return False if sys.version < "3": __nonzero__ = __bool__ Empty = _Empty() del _Empty ############################################################ ## Lexing and Parsing ############################################################ def lex(s, name=None, trim_whitespace=True, line_offset=0, delimiters=None): """ Lex a string into chunks: >>> lex('hey') ['hey'] >>> lex('hey {{you}}') ['hey ', ('you', (1, 7))] >>> lex('hey {{') Traceback (most recent call last): ... TemplateError: No }} to finish last expression at line 1 column 7 >>> lex('hey }}') Traceback (most recent call last): ... TemplateError: }} outside expression at line 1 column 7 >>> lex('hey {{ {{') Traceback (most recent call last): ... TemplateError: {{ inside expression at line 1 column 10 """ if delimiters is None: delimiters = ( Template.default_namespace['start_braces'], Template.default_namespace['end_braces'] ) in_expr = False chunks = [] last = 0 last_pos = (line_offset + 1, 1) token_re = re.compile(r'%s|%s' % (re.escape(delimiters[0]), re.escape(delimiters[1]))) for match in token_re.finditer(s): expr = match.group(0) pos = find_position(s, match.end(), last, last_pos) if expr == delimiters[0] and in_expr: raise TemplateError('%s inside expression' % delimiters[0], position=pos, name=name) elif expr == delimiters[1] and not in_expr: raise TemplateError('%s outside expression' % delimiters[1], position=pos, name=name) if expr == delimiters[0]: part = s[last:match.start()] if part: chunks.append(part) in_expr = True else: chunks.append((s[last:match.start()], last_pos)) in_expr = False last = match.end() last_pos = pos if in_expr: raise TemplateError('No %s to finish last expression' % delimiters[1], name=name, position=last_pos) part = s[last:] if part: chunks.append(part) if trim_whitespace: chunks = trim_lex(chunks) return chunks statement_re = re.compile(r'^(?:if |elif |for |def |inherit |default |py:)') single_statements = ['else', 'endif', 'endfor', 'enddef', 'continue', 'break'] trail_whitespace_re = re.compile(r'\n\r?[\t ]*$') lead_whitespace_re = re.compile(r'^[\t ]*\n') def trim_lex(tokens): r""" Takes a lexed set of tokens, and removes whitespace when there is a directive on a line by itself: >>> tokens = lex('{{if x}}\nx\n{{endif}}\ny', trim_whitespace=False) >>> tokens [('if x', (1, 3)), '\nx\n', ('endif', (3, 3)), '\ny'] >>> trim_lex(tokens) [('if x', (1, 3)), 'x\n', ('endif', (3, 3)), 'y'] """ last_trim = None for i, current in enumerate(tokens): if isinstance(current, basestring_): # we don't trim this continue item = current[0] if not statement_re.search(item) and item not in single_statements: continue if not i: prev = '' else: prev = tokens[i - 1] if i + 1 >= len(tokens): next_chunk = '' else: next_chunk = tokens[i + 1] if (not isinstance(next_chunk, basestring_) or not isinstance(prev, basestring_)): continue prev_ok = not prev or trail_whitespace_re.search(prev) if i == 1 and not prev.strip(): prev_ok = True if last_trim is not None and last_trim + 2 == i and not prev.strip(): prev_ok = 'last' if (prev_ok and (not next_chunk or lead_whitespace_re.search(next_chunk) or (i == len(tokens) - 2 and not next_chunk.strip()))): if prev: if ((i == 1 and not prev.strip()) or prev_ok == 'last'): tokens[i - 1] = '' else: m = trail_whitespace_re.search(prev) # +1 to leave the leading \n on: prev = prev[:m.start() + 1] tokens[i - 1] = prev if next_chunk: last_trim = i if i == len(tokens) - 2 and not next_chunk.strip(): tokens[i + 1] = '' else: m = lead_whitespace_re.search(next_chunk) next_chunk = next_chunk[m.end():] tokens[i + 1] = next_chunk return tokens def find_position(string, index, last_index, last_pos): """Given a string and index, return (line, column)""" lines = string.count('\n', last_index, index) if lines > 0: column = index - string.rfind('\n', last_index, index) else: column = last_pos[1] + (index - last_index) return (last_pos[0] + lines, column) def parse(s, name=None, line_offset=0, delimiters=None): r""" Parses a string into a kind of AST >>> parse('{{x}}') [('expr', (1, 3), 'x')] >>> parse('foo') ['foo'] >>> parse('{{if x}}test{{endif}}') [('cond', (1, 3), ('if', (1, 3), 'x', ['test']))] >>> parse('series->{{for x in y}}x={{x}}{{endfor}}') ['series->', ('for', (1, 11), ('x',), 'y', ['x=', ('expr', (1, 27), 'x')])] >>> parse('{{for x, y in z:}}{{continue}}{{endfor}}') [('for', (1, 3), ('x', 'y'), 'z', [('continue', (1, 21))])] >>> parse('{{py:x=1}}') [('py', (1, 3), 'x=1')] >>> parse('{{if x}}a{{elif y}}b{{else}}c{{endif}}') [('cond', (1, 3), ('if', (1, 3), 'x', ['a']), ('elif', (1, 12), 'y', ['b']), ('else', (1, 23), None, ['c']))] Some exceptions:: >>> parse('{{continue}}') Traceback (most recent call last): ... TemplateError: continue outside of for loop at line 1 column 3 >>> parse('{{if x}}foo') Traceback (most recent call last): ... TemplateError: No {{endif}} at line 1 column 3 >>> parse('{{else}}') Traceback (most recent call last): ... TemplateError: else outside of an if block at line 1 column 3 >>> parse('{{if x}}{{for x in y}}{{endif}}{{endfor}}') Traceback (most recent call last): ... TemplateError: Unexpected endif at line 1 column 25 >>> parse('{{if}}{{endif}}') Traceback (most recent call last): ... TemplateError: if with no expression at line 1 column 3 >>> parse('{{for x y}}{{endfor}}') Traceback (most recent call last): ... TemplateError: Bad for (no "in") in 'x y' at line 1 column 3 >>> parse('{{py:x=1\ny=2}}') Traceback (most recent call last): ... TemplateError: Multi-line py blocks must start with a newline at line 1 column 3 """ if delimiters is None: delimiters = ( Template.default_namespace['start_braces'], Template.default_namespace['end_braces'] ) tokens = lex(s, name=name, line_offset=line_offset, delimiters=delimiters) result = [] while tokens: next_chunk, tokens = parse_expr(tokens, name) result.append(next_chunk) return result def parse_expr(tokens, name, context=()): if isinstance(tokens[0], basestring_): return tokens[0], tokens[1:] expr, pos = tokens[0] expr = expr.strip() if expr.startswith('py:'): expr = expr[3:].lstrip(' \t') if expr.startswith('\n') or expr.startswith('\r'): expr = expr.lstrip('\r\n') if '\r' in expr: expr = expr.replace('\r\n', '\n') expr = expr.replace('\r', '') expr += '\n' else: if '\n' in expr: raise TemplateError( 'Multi-line py blocks must start with a newline', position=pos, name=name) return ('py', pos, expr), tokens[1:] elif expr in ('continue', 'break'): if 'for' not in context: raise TemplateError( 'continue outside of for loop', position=pos, name=name) return (expr, pos), tokens[1:] elif expr.startswith('if '): return parse_cond(tokens, name, context) elif (expr.startswith('elif ') or expr == 'else'): raise TemplateError( '%s outside of an if block' % expr.split()[0], position=pos, name=name) elif expr in ('if', 'elif', 'for'): raise TemplateError( '%s with no expression' % expr, position=pos, name=name) elif expr in ('endif', 'endfor', 'enddef'): raise TemplateError( 'Unexpected %s' % expr, position=pos, name=name) elif expr.startswith('for '): return parse_for(tokens, name, context) elif expr.startswith('default '): return parse_default(tokens, name, context) elif expr.startswith('inherit '): return parse_inherit(tokens, name, context) elif expr.startswith('def '): return parse_def(tokens, name, context) elif expr.startswith('#'): return ('comment', pos, tokens[0][0]), tokens[1:] return ('expr', pos, tokens[0][0]), tokens[1:] def parse_cond(tokens, name, context): start = tokens[0][1] pieces = [] context = context + ('if',) while 1: if not tokens: raise TemplateError( 'Missing {{endif}}', position=start, name=name) if (isinstance(tokens[0], tuple) and tokens[0][0] == 'endif'): return ('cond', start) + tuple(pieces), tokens[1:] next_chunk, tokens = parse_one_cond(tokens, name, context) pieces.append(next_chunk) def parse_one_cond(tokens, name, context): (first, pos), tokens = tokens[0], tokens[1:] content = [] if first.endswith(':'): first = first[:-1] if first.startswith('if '): part = ('if', pos, first[3:].lstrip(), content) elif first.startswith('elif '): part = ('elif', pos, first[5:].lstrip(), content) elif first == 'else': part = ('else', pos, None, content) else: assert 0, "Unexpected token %r at %s" % (first, pos) while 1: if not tokens: raise TemplateError( 'No {{endif}}', position=pos, name=name) if (isinstance(tokens[0], tuple) and (tokens[0][0] == 'endif' or tokens[0][0].startswith('elif ') or tokens[0][0] == 'else')): return part, tokens next_chunk, tokens = parse_expr(tokens, name, context) content.append(next_chunk) def parse_for(tokens, name, context): first, pos = tokens[0] tokens = tokens[1:] context = ('for',) + context content = [] assert first.startswith('for '), first if first.endswith(':'): first = first[:-1] first = first[3:].strip() match = in_re.search(first) if not match: raise TemplateError( 'Bad for (no "in") in %r' % first, position=pos, name=name) vars = first[:match.start()] if '(' in vars: raise TemplateError( 'You cannot have () in the variable section of a for loop (%r)' % vars, position=pos, name=name) vars = tuple([ v.strip() for v in first[:match.start()].split(',') if v.strip()]) expr = first[match.end():] while 1: if not tokens: raise TemplateError( 'No {{endfor}}', position=pos, name=name) if (isinstance(tokens[0], tuple) and tokens[0][0] == 'endfor'): return ('for', pos, vars, expr, content), tokens[1:] next_chunk, tokens = parse_expr(tokens, name, context) content.append(next_chunk) def parse_default(tokens, name, context): first, pos = tokens[0] assert first.startswith('default ') first = first.split(None, 1)[1] parts = first.split('=', 1) if len(parts) == 1: raise TemplateError( "Expression must be {{default var=value}}; no = found in %r" % first, position=pos, name=name) var = parts[0].strip() if ',' in var: raise TemplateError( "{{default x, y = ...}} is not supported", position=pos, name=name) if not var_re.search(var): raise TemplateError( "Not a valid variable name for {{default}}: %r" % var, position=pos, name=name) expr = parts[1].strip() return ('default', pos, var, expr), tokens[1:] def parse_inherit(tokens, name, context): first, pos = tokens[0] assert first.startswith('inherit ') expr = first.split(None, 1)[1] return ('inherit', pos, expr), tokens[1:] def parse_def(tokens, name, context): first, start = tokens[0] tokens = tokens[1:] assert first.startswith('def ') first = first.split(None, 1)[1] if first.endswith(':'): first = first[:-1] if '(' not in first: func_name = first sig = ((), None, None, {}) elif not first.endswith(')'): raise TemplateError("Function definition doesn't end with ): %s" % first, position=start, name=name) else: first = first[:-1] func_name, sig_text = first.split('(', 1) sig = parse_signature(sig_text, name, start) context = context + ('def',) content = [] while 1: if not tokens: raise TemplateError( 'Missing {{enddef}}', position=start, name=name) if (isinstance(tokens[0], tuple) and tokens[0][0] == 'enddef'): return ('def', start, func_name, sig, content), tokens[1:] next_chunk, tokens = parse_expr(tokens, name, context) content.append(next_chunk) def parse_signature(sig_text, name, pos): tokens = tokenize.generate_tokens(StringIO(sig_text).readline) sig_args = [] var_arg = None var_kw = None defaults = {} def get_token(pos=False): try: tok_type, tok_string, (srow, scol), (erow, ecol), line = next(tokens) except StopIteration: return tokenize.ENDMARKER, '' if pos: return tok_type, tok_string, (srow, scol), (erow, ecol) else: return tok_type, tok_string while 1: var_arg_type = None tok_type, tok_string = get_token() if tok_type == tokenize.ENDMARKER: break if tok_type == tokenize.OP and (tok_string == '*' or tok_string == '**'): var_arg_type = tok_string tok_type, tok_string = get_token() if tok_type != tokenize.NAME: raise TemplateError('Invalid signature: (%s)' % sig_text, position=pos, name=name) var_name = tok_string tok_type, tok_string = get_token() if tok_type == tokenize.ENDMARKER or (tok_type == tokenize.OP and tok_string == ','): if var_arg_type == '*': var_arg = var_name elif var_arg_type == '**': var_kw = var_name else: sig_args.append(var_name) if tok_type == tokenize.ENDMARKER: break continue if var_arg_type is not None: raise TemplateError('Invalid signature: (%s)' % sig_text, position=pos, name=name) if tok_type == tokenize.OP and tok_string == '=': nest_type = None unnest_type = None nest_count = 0 start_pos = end_pos = None parts = [] while 1: tok_type, tok_string, s, e = get_token(True) if start_pos is None: start_pos = s end_pos = e if tok_type == tokenize.ENDMARKER and nest_count: raise TemplateError('Invalid signature: (%s)' % sig_text, position=pos, name=name) if (not nest_count and (tok_type == tokenize.ENDMARKER or (tok_type == tokenize.OP and tok_string == ','))): default_expr = isolate_expression(sig_text, start_pos, end_pos) defaults[var_name] = default_expr sig_args.append(var_name) break parts.append((tok_type, tok_string)) if nest_count and tok_type == tokenize.OP and tok_string == nest_type: nest_count += 1 elif nest_count and tok_type == tokenize.OP and tok_string == unnest_type: nest_count -= 1 if not nest_count: nest_type = unnest_type = None elif not nest_count and tok_type == tokenize.OP and tok_string in ('(', '[', '{'): nest_type = tok_string nest_count = 1 unnest_type = {'(': ')', '[': ']', '{': '}'}[nest_type] return sig_args, var_arg, var_kw, defaults def isolate_expression(string, start_pos, end_pos): srow, scol = start_pos srow -= 1 erow, ecol = end_pos erow -= 1 lines = string.splitlines(True) if srow == erow: return lines[srow][scol:ecol] parts = [lines[srow][scol:]] parts.extend(lines[srow+1:erow]) if erow < len(lines): # It'll sometimes give (end_row_past_finish, 0) parts.append(lines[erow][:ecol]) return ''.join(parts) _fill_command_usage = """\ %prog [OPTIONS] TEMPLATE arg=value Use py:arg=value to set a Python value; otherwise all values are strings. """ def fill_command(args=None): import sys import optparse import pkg_resources import os if args is None: args = sys.argv[1:] dist = pkg_resources.get_distribution('Paste') parser = optparse.OptionParser( version=coerce_text(dist), usage=_fill_command_usage) parser.add_option( '-o', '--output', dest='output', metavar="FILENAME", help="File to write output to (default stdout)") parser.add_option( '--env', dest='use_env', action='store_true', help="Put the environment in as top-level variables") options, args = parser.parse_args(args) if len(args) < 1: print('You must give a template filename') sys.exit(2) template_name = args[0] args = args[1:] vars = {} if options.use_env: vars.update(os.environ) for value in args: if '=' not in value: print('Bad argument: %r' % value) sys.exit(2) name, value = value.split('=', 1) if name.startswith('py:'): name = name[:3] value = eval(value) vars[name] = value if template_name == '-': template_content = sys.stdin.read() template_name = '' else: with open(template_name, 'rb') as f: template_content = f.read() template = Template(template_content, name=template_name) result = template.substitute(vars) if options.output: with open(options.output, 'wb') as f: f.write(result) else: sys.stdout.write(result) if __name__ == '__main__': fill_command() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Tempita/compat3.py0000644000175100001770000000160700000000000020367 0ustar00runnerdocker00000000000000import sys __all__ = ['b', 'basestring_', 'bytes', 'unicode_', 'next', 'is_unicode'] if sys.version < "3": b = bytes = str basestring_ = basestring unicode_ = unicode else: def b(s): if isinstance(s, str): return s.encode('latin1') return bytes(s) basestring_ = (bytes, str) bytes = bytes unicode_ = str text = str if sys.version < "3": def next(obj): return obj.next() else: next = next if sys.version < "3": def is_unicode(obj): return isinstance(obj, unicode) else: def is_unicode(obj): return isinstance(obj, str) def coerce_text(v): if not isinstance(v, basestring_): if sys.version < "3": attr = '__unicode__' else: attr = '__str__' if hasattr(v, attr): return unicode(v) else: return bytes(v) return v ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/TestUtils.py0000644000175100001770000003455700000000000017370 0ustar00runnerdocker00000000000000from __future__ import absolute_import import os import re import unittest import shlex import sys import tempfile import textwrap from io import open from functools import partial from .Compiler import Errors from .CodeWriter import CodeWriter from .Compiler.TreeFragment import TreeFragment, strip_common_indent from .Compiler.Visitor import TreeVisitor, VisitorTransform from .Compiler import TreePath class NodeTypeWriter(TreeVisitor): def __init__(self): super(NodeTypeWriter, self).__init__() self._indents = 0 self.result = [] def visit_Node(self, node): if not self.access_path: name = u"(root)" else: tip = self.access_path[-1] if tip[2] is not None: name = u"%s[%d]" % tip[1:3] else: name = tip[1] self.result.append(u" " * self._indents + u"%s: %s" % (name, node.__class__.__name__)) self._indents += 1 self.visitchildren(node) self._indents -= 1 def treetypes(root): """Returns a string representing the tree by class names. There's a leading and trailing whitespace so that it can be compared by simple string comparison while still making test cases look ok.""" w = NodeTypeWriter() w.visit(root) return u"\n".join([u""] + w.result + [u""]) class CythonTest(unittest.TestCase): def setUp(self): Errors.init_thread() def tearDown(self): Errors.init_thread() def assertLines(self, expected, result): "Checks that the given strings or lists of strings are equal line by line" if not isinstance(expected, list): expected = expected.split(u"\n") if not isinstance(result, list): result = result.split(u"\n") for idx, (expected_line, result_line) in enumerate(zip(expected, result)): self.assertEqual(expected_line, result_line, "Line %d:\nExp: %s\nGot: %s" % (idx, expected_line, result_line)) self.assertEqual(len(expected), len(result), "Unmatched lines. Got:\n%s\nExpected:\n%s" % ("\n".join(expected), u"\n".join(result))) def codeToLines(self, tree): writer = CodeWriter() writer.write(tree) return writer.result.lines def codeToString(self, tree): return "\n".join(self.codeToLines(tree)) def assertCode(self, expected, result_tree): result_lines = self.codeToLines(result_tree) expected_lines = strip_common_indent(expected.split("\n")) for idx, (line, expected_line) in enumerate(zip(result_lines, expected_lines)): self.assertEqual(expected_line, line, "Line %d:\nGot: %s\nExp: %s" % (idx, line, expected_line)) self.assertEqual(len(result_lines), len(expected_lines), "Unmatched lines. Got:\n%s\nExpected:\n%s" % ("\n".join(result_lines), expected)) def assertNodeExists(self, path, result_tree): self.assertNotEqual(TreePath.find_first(result_tree, path), None, "Path '%s' not found in result tree" % path) def fragment(self, code, pxds=None, pipeline=None): "Simply create a tree fragment using the name of the test-case in parse errors." if pxds is None: pxds = {} if pipeline is None: pipeline = [] name = self.id() if name.startswith("__main__."): name = name[len("__main__."):] name = name.replace(".", "_") return TreeFragment(code, name, pxds, pipeline=pipeline) def treetypes(self, root): return treetypes(root) def should_fail(self, func, exc_type=Exception): """Calls "func" and fails if it doesn't raise the right exception (any exception by default). Also returns the exception in question. """ try: func() self.fail("Expected an exception of type %r" % exc_type) except exc_type as e: self.assertTrue(isinstance(e, exc_type)) return e def should_not_fail(self, func): """Calls func and succeeds if and only if no exception is raised (i.e. converts exception raising into a failed testcase). Returns the return value of func.""" try: return func() except Exception as exc: self.fail(str(exc)) class TransformTest(CythonTest): """ Utility base class for transform unit tests. It is based around constructing test trees (either explicitly or by parsing a Cython code string); running the transform, serialize it using a customized Cython serializer (with special markup for nodes that cannot be represented in Cython), and do a string-comparison line-by-line of the result. To create a test case: - Call run_pipeline. The pipeline should at least contain the transform you are testing; pyx should be either a string (passed to the parser to create a post-parse tree) or a node representing input to pipeline. The result will be a transformed result. - Check that the tree is correct. If wanted, assertCode can be used, which takes a code string as expected, and a ModuleNode in result_tree (it serializes the ModuleNode to a string and compares line-by-line). All code strings are first stripped for whitespace lines and then common indentation. Plans: One could have a pxd dictionary parameter to run_pipeline. """ def run_pipeline(self, pipeline, pyx, pxds=None): if pxds is None: pxds = {} tree = self.fragment(pyx, pxds).root # Run pipeline for T in pipeline: tree = T(tree) return tree # For the test C code validation, we have to take care that the test directives (and thus # the match strings) do not just appear in (multiline) C code comments containing the original # Cython source code. Thus, we discard the comments before matching. # This seems a prime case for re.VERBOSE, but it seems to match some of the whitespace. _strip_c_comments = partial(re.compile( re.sub(r'\s+', '', r''' /[*] ( (?: [^*\n] | [*][^/] )* [\n] (?: [^*] | [*][^/] )* ) [*]/ ''') ).sub, '') _strip_cython_code_from_html = partial(re.compile( re.sub(r'\s\s+', '', r''' (?:
        (?:[^<]|<(?!/pre))+
        
)|(?: ]*> (?:[^<]|<(?!/style))+ ) ''') ).sub, '') def _parse_pattern(pattern): start = end = None if pattern.startswith('/'): start, pattern = re.split(r"(?= os.path.getmtime(file_path): write_file(file_path, content, dedent=dedent, encoding=encoding) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.012724 Cython-3.0.8/Cython/Tests/0000755000175100001770000000000000000000000016142 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Tests/TestCodeWriter.py0000644000175100001770000000732700000000000021434 0ustar00runnerdocker00000000000000from Cython.TestUtils import CythonTest class TestCodeWriter(CythonTest): # CythonTest uses the CodeWriter heavily, so do some checking by # roundtripping Cython code through the test framework. # Note that this test is dependent upon the normal Cython parser # to generate the input trees to the CodeWriter. This save *a lot* # of time; better to spend that time writing other tests than perfecting # this one... # Whitespace is very significant in this process: # - always newline on new block (!) # - indent 4 spaces # - 1 space around every operator def t(self, codestr): self.assertCode(codestr, self.fragment(codestr).root) def test_print(self): self.t(u""" print(x + y ** 2) print(x, y, z) print(x + y, x + y * z, x * (y + z)) """) def test_if(self): self.t(u"if x:\n pass") def test_ifelifelse(self): self.t(u""" if x: pass elif y: pass elif z + 34 ** 34 - 2: pass else: pass """) def test_def(self): self.t(u""" def f(x, y, z): pass def f(x = 34, y = 54, z): pass """) def test_cdef(self): self.t(u""" cdef f(x, y, z): pass cdef public void (x = 34, y = 54, z): pass cdef f(int *x, void *y, Value *z): pass cdef f(int **x, void **y, Value **z): pass cdef inline f(int &x, Value &z): pass """) def test_longness_and_signedness(self): self.t(u"def f(unsigned long long long long long int y):\n pass") def test_signed_short(self): self.t(u"def f(signed short int y):\n pass") def test_typed_args(self): self.t(u"def f(int x, unsigned long int y):\n pass") def test_cdef_var(self): self.t(u""" cdef int hello cdef int hello = 4, x = 3, y, z """) def test_for_loop(self): self.t(u""" for x, y, z in f(g(h(34) * 2) + 23): print(x, y, z) else: print(43) """) self.t(u""" for abc in (1, 2, 3): print(x, y, z) else: print(43) """) def test_while_loop(self): self.t(u""" while True: while True: while True: continue """) def test_inplace_assignment(self): self.t(u"x += 43") def test_cascaded_assignment(self): self.t(u"x = y = z = abc = 43") def test_attribute(self): self.t(u"a.x") def test_return_none(self): self.t(u""" def f(x, y, z): return cdef f(x, y, z): return def f(x, y, z): return None cdef f(x, y, z): return None def f(x, y, z): return 1234 cdef f(x, y, z): return 1234 """) if __name__ == "__main__": import unittest unittest.main() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Tests/TestCythonUtils.py0000644000175100001770000001525100000000000021645 0ustar00runnerdocker00000000000000import sys import unittest try: from StringIO import StringIO except ImportError: from io import StringIO # doesn't accept 'str' in Py2 from Cython.Utils import ( _CACHE_NAME_PATTERN, _build_cache_name, _find_cache_attributes, build_hex_version, cached_method, clear_method_caches, try_finally_contextmanager, print_version, normalise_float_repr, ) METHOD_NAME = "cached_next" CACHE_NAME = _build_cache_name(METHOD_NAME) NAMES = CACHE_NAME, METHOD_NAME class Cached(object): @cached_method def cached_next(self, x): return next(x) class TestCythonUtils(unittest.TestCase): def test_build_hex_version(self): self.assertEqual('0x001D00A1', build_hex_version('0.29a1')) self.assertEqual('0x001D03C4', build_hex_version('0.29.3rc4')) self.assertEqual('0x001D00F0', build_hex_version('0.29')) self.assertEqual('0x040000F0', build_hex_version('4.0')) ############################## Cached Methods ############################## def test_cache_method_name(self): method_name = "foo" cache_name = _build_cache_name(method_name) match = _CACHE_NAME_PATTERN.match(cache_name) self.assertIsNot(match, None) self.assertEqual(match.group(1), method_name) def test_requirements_for_Cached(self): obj = Cached() self.assertFalse(hasattr(obj, CACHE_NAME)) self.assertTrue(hasattr(obj, METHOD_NAME)) self.set_of_names_equal(obj, set()) def set_of_names_equal(self, obj, value): self.assertEqual(set(_find_cache_attributes(obj)), value) def test_find_cache_attributes(self): obj = Cached() method_name = "bar" cache_name = _build_cache_name(method_name) setattr(obj, CACHE_NAME, {}) setattr(obj, cache_name, {}) self.assertFalse(hasattr(obj, method_name)) self.set_of_names_equal(obj, {NAMES, (cache_name, method_name)}) def test_cached_method(self): obj = Cached() value = iter(range(3)) # iter for Py2 cache = {(value,): 0} # cache args self.assertEqual(obj.cached_next(value), 0) self.set_of_names_equal(obj, {NAMES}) self.assertEqual(getattr(obj, CACHE_NAME), cache) # use cache self.assertEqual(obj.cached_next(value), 0) self.set_of_names_equal(obj, {NAMES}) self.assertEqual(getattr(obj, CACHE_NAME), cache) def test_clear_method_caches(self): obj = Cached() value = iter(range(3)) # iter for Py2 cache = {(value,): 1} obj.cached_next(value) # cache args clear_method_caches(obj) self.set_of_names_equal(obj, set()) self.assertEqual(obj.cached_next(value), 1) self.set_of_names_equal(obj, {NAMES}) self.assertEqual(getattr(obj, CACHE_NAME), cache) def test_clear_method_caches_with_missing_method(self): obj = Cached() method_name = "bar" cache_name = _build_cache_name(method_name) names = cache_name, method_name setattr(obj, cache_name, object()) self.assertFalse(hasattr(obj, method_name)) self.set_of_names_equal(obj, {names}) clear_method_caches(obj) self.set_of_names_equal(obj, {names}) def test_try_finally_contextmanager(self): states = [] @try_finally_contextmanager def gen(*args, **kwargs): states.append("enter") yield (args, kwargs) states.append("exit") with gen(1, 2, 3, x=4) as call_args: assert states == ["enter"] self.assertEqual(call_args, ((1, 2, 3), {'x': 4})) assert states == ["enter", "exit"] class MyException(RuntimeError): pass del states[:] with self.assertRaises(MyException): with gen(1, 2, y=4) as call_args: assert states == ["enter"] self.assertEqual(call_args, ((1, 2), {'y': 4})) raise MyException("FAIL INSIDE") assert states == ["enter", "exit"] del states[:] with self.assertRaises(StopIteration): with gen(1, 2, y=4) as call_args: assert states == ["enter"] self.assertEqual(call_args, ((1, 2), {'y': 4})) raise StopIteration("STOP") assert states == ["enter", "exit"] def test_print_version(self): orig_stderr = sys.stderr orig_stdout = sys.stdout stderr = sys.stderr = StringIO() stdout = sys.stdout = StringIO() try: print_version() finally: sys.stdout = orig_stdout sys.stderr = orig_stderr stdout = stdout.getvalue() stderr = stderr.getvalue() from .. import __version__ as version self.assertIn(version, stdout) if stderr: # Depends on os.fstat(1/2). self.assertIn(version, stderr) def test_print_version_stdouterr(self): orig_stderr = sys.stderr orig_stdout = sys.stdout stdout = sys.stdout = sys.stderr = StringIO() # same! try: print_version() finally: sys.stdout = orig_stdout sys.stderr = orig_stderr stdout = stdout.getvalue() from .. import __version__ as version self.assertIn(version, stdout) self.assertEqual(stdout.count(version), 1) def test_normalise_float_repr(self): examples = [ ('.0', '.0'), ('.000000', '.0'), ('.1', '.1'), ('1.', '1.'), ('1.0', '1.'), ('1.000000000000000000000', '1.'), ('00000000000000000000001.000000000000000000000', '1.'), ('12345.0025', '12345.0025'), ('1E5', '100000.'), ('.1E-5', '.000001'), ('1.1E-5', '.000011'), ('12.3E-5', '.000123'), ('.1E10', '1000000000.'), ('1.1E10', '11000000000.'), ('123.4E10', '1234000000000.'), ('123.456E0', '123.456'), ('123.456E-1', '12.3456'), ('123.456E-2', '1.23456'), ('123.456E1', '1234.56'), ('123.456E2', '12345.6'), ('2.1E80', '210000000000000000000000000000000000000000000000000000000000000000000000000000000.'), ] for float_str, norm_str in examples: self.assertEqual(float(float_str), float(norm_str)) # safety check for test data result = normalise_float_repr(float_str) self.assertEqual(float(float_str), float(result)) self.assertEqual( result, norm_str, "normalise_float_repr(%r) == %r != %r (%.330f)" % (float_str, result, norm_str, float(float_str)) ) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Tests/TestJediTyper.py0000644000175100001770000001555500000000000021266 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*- # tag: jedi from __future__ import absolute_import import sys import os.path from textwrap import dedent from contextlib import contextmanager from tempfile import NamedTemporaryFile from Cython.Compiler.ParseTreeTransforms import NormalizeTree, InterpretCompilerDirectives from Cython.Compiler import Main, Symtab, Visitor, Options from Cython.TestUtils import TransformTest TOOLS_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'Tools')) @contextmanager def _tempfile(code): code = dedent(code) if not isinstance(code, bytes): code = code.encode('utf8') with NamedTemporaryFile(suffix='.py') as f: f.write(code) f.seek(0) yield f def _test_typing(code, inject=False): sys.path.insert(0, TOOLS_DIR) try: import jedityper finally: sys.path.remove(TOOLS_DIR) lines = [] with _tempfile(code) as f: types = jedityper.analyse(f.name) if inject: lines = jedityper.inject_types(f.name, types) return types, lines class DeclarationsFinder(Visitor.VisitorTransform): directives = None visit_Node = Visitor.VisitorTransform.recurse_to_children def visit_CompilerDirectivesNode(self, node): if not self.directives: self.directives = [] self.directives.append(node) self.visitchildren(node) return node class TestJediTyper(TransformTest): def _test(self, code): return _test_typing(code)[0] def test_typing_global_int_loop(self): code = '''\ for i in range(10): a = i + 1 ''' types = self._test(code) self.assertIn((None, (1, 0)), types) variables = types.pop((None, (1, 0))) self.assertFalse(types) self.assertEqual({'a': set(['int']), 'i': set(['int'])}, variables) def test_typing_function_int_loop(self): code = '''\ def func(x): for i in range(x): a = i + 1 return a ''' types = self._test(code) self.assertIn(('func', (1, 0)), types) variables = types.pop(('func', (1, 0))) self.assertFalse(types) self.assertEqual({'a': set(['int']), 'i': set(['int'])}, variables) def test_conflicting_types_in_function(self): code = '''\ def func(a, b): print(a) a = 1 b += a a = 'abc' return a, str(b) print(func(1.5, 2)) ''' types = self._test(code) self.assertIn(('func', (1, 0)), types) variables = types.pop(('func', (1, 0))) self.assertFalse(types) self.assertEqual({'a': set(['float', 'int', 'str']), 'b': set(['int'])}, variables) def _test_typing_function_char_loop(self): code = '''\ def func(x): l = [] for c in x: l.append(c) return l print(func('abcdefg')) ''' types = self._test(code) self.assertIn(('func', (1, 0)), types) variables = types.pop(('func', (1, 0))) self.assertFalse(types) self.assertEqual({'a': set(['int']), 'i': set(['int'])}, variables) def test_typing_global_list(self): code = '''\ a = [x for x in range(10)] b = list(range(10)) c = a + b d = [0]*10 ''' types = self._test(code) self.assertIn((None, (1, 0)), types) variables = types.pop((None, (1, 0))) self.assertFalse(types) self.assertEqual({'a': set(['list']), 'b': set(['list']), 'c': set(['list']), 'd': set(['list'])}, variables) def test_typing_function_list(self): code = '''\ def func(x): a = [[], []] b = [0]* 10 + a c = a[0] print(func([0]*100)) ''' types = self._test(code) self.assertIn(('func', (1, 0)), types) variables = types.pop(('func', (1, 0))) self.assertFalse(types) self.assertEqual({'a': set(['list']), 'b': set(['list']), 'c': set(['list']), 'x': set(['list'])}, variables) def test_typing_global_dict(self): code = '''\ a = dict() b = {i: i**2 for i in range(10)} c = a ''' types = self._test(code) self.assertIn((None, (1, 0)), types) variables = types.pop((None, (1, 0))) self.assertFalse(types) self.assertEqual({'a': set(['dict']), 'b': set(['dict']), 'c': set(['dict'])}, variables) def test_typing_function_dict(self): code = '''\ def func(x): a = dict() b = {i: i**2 for i in range(10)} c = x print(func({1:2, 'x':7})) ''' types = self._test(code) self.assertIn(('func', (1, 0)), types) variables = types.pop(('func', (1, 0))) self.assertFalse(types) self.assertEqual({'a': set(['dict']), 'b': set(['dict']), 'c': set(['dict']), 'x': set(['dict'])}, variables) def test_typing_global_set(self): code = '''\ a = set() # b = {i for i in range(10)} # jedi does not support set comprehension yet c = a d = {1,2,3} e = a | b ''' types = self._test(code) self.assertIn((None, (1, 0)), types) variables = types.pop((None, (1, 0))) self.assertFalse(types) self.assertEqual({'a': set(['set']), 'c': set(['set']), 'd': set(['set']), 'e': set(['set'])}, variables) def test_typing_function_set(self): code = '''\ def func(x): a = set() # b = {i for i in range(10)} # jedi does not support set comprehension yet c = a d = a | b print(func({1,2,3})) ''' types = self._test(code) self.assertIn(('func', (1, 0)), types) variables = types.pop(('func', (1, 0))) self.assertFalse(types) self.assertEqual({'a': set(['set']), 'c': set(['set']), 'd': set(['set']), 'x': set(['set'])}, variables) class TestTypeInjection(TestJediTyper): """ Subtype of TestJediTyper that additionally tests type injection and compilation. """ def setUp(self): super(TestTypeInjection, self).setUp() compilation_options = Options.CompilationOptions(Options.default_options) ctx = Main.Context.from_options(compilation_options) transform = InterpretCompilerDirectives(ctx, ctx.compiler_directives) transform.module_scope = Symtab.ModuleScope('__main__', None, ctx) self.declarations_finder = DeclarationsFinder() self.pipeline = [NormalizeTree(None), transform, self.declarations_finder] def _test(self, code): types, lines = _test_typing(code, inject=True) tree = self.run_pipeline(self.pipeline, ''.join(lines)) directives = self.declarations_finder.directives # TODO: validate directives return types ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Tests/TestShadow.py0000644000175100001770000000647000000000000020610 0ustar00runnerdocker00000000000000import unittest from Cython import Shadow from Cython.Compiler import Options, CythonScope, PyrexTypes, Errors class TestShadow(unittest.TestCase): def test_all_types_in_shadow(self): cython_scope = CythonScope.create_cython_scope(None) # Not doing load_cythonscope at this stage because it requires a proper context and # Errors.py to be set up missing_types = [] for key in cython_scope.entries.keys(): if key.startswith('__') and key.endswith('__'): continue if key in ('PyTypeObject', 'PyObject_TypeCheck'): # These are declared in Shadow.py for reasons that look to # be an implementation detail, but it isn't our intention for # users to access them from Pure Python mode. continue if not hasattr(Shadow, key): missing_types.append(key) self.assertEqual(missing_types, []) def test_int_types_in_shadow(self): missing_types = [] for int_name in Shadow.int_types: for sign in ['', 'u', 's']: name = sign + int_name if sign and ( int_name in ['Py_UNICODE', 'Py_UCS4', 'Py_ssize_t', 'ssize_t', 'ptrdiff_t', 'Py_hash_t'] or name == "usize_t"): # size_t is special-cased here a little since ssize_t legitimate # but usize_t isn't self.assertNotIn(name, dir(Shadow)) self.assertNotIn('p_' + name, dir(Shadow)) continue if not hasattr(Shadow, name): missing_types.append(name) for ptr in range(1, 4): ptr_name = 'p' * ptr + '_' + name if not hasattr(Shadow, ptr_name): missing_types.append(ptr_name) self.assertEqual(missing_types, []) def test_most_types(self): # TODO it's unfortunately hard to get a definite list of types to confirm that they're # present (because they're obtained by on-the-fly string parsing in `cython_scope.lookup_type`) cython_scope = CythonScope.create_cython_scope(None) # Set up just enough of "Context" and "Errors" that CythonScope.lookup_type can fail class Context: cpp = False language_level = 3 future_directives = [] cython_scope.context = Context Errors.init_thread() missing_types = [] missing_lookups = [] for (signed, longness, name), type_ in PyrexTypes.modifiers_and_name_to_type.items(): if name == 'object': continue # This probably shouldn't be in Shadow if not hasattr(Shadow, name): missing_types.append(name) if not cython_scope.lookup_type(name): missing_lookups.append(name) for ptr in range(1, 4): ptr_name = 'p' * ptr + '_' + name if not hasattr(Shadow, ptr_name): missing_types.append(ptr_name) if not cython_scope.lookup_type(ptr_name): missing_lookups.append(ptr_name) self.assertEqual(missing_types, []) self.assertEqual(missing_lookups, []) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Tests/TestStringIOTree.py0000644000175100001770000000363200000000000021676 0ustar00runnerdocker00000000000000import unittest from Cython import StringIOTree as stringtree code = """ cdef int spam # line 1 cdef ham(): a = 1 b = 2 c = 3 d = 4 def eggs(): pass cpdef bacon(): print spam print 'scotch' print 'tea?' print 'or coffee?' # line 16 """ linemap = dict(enumerate(code.splitlines())) class TestStringIOTree(unittest.TestCase): def setUp(self): self.tree = stringtree.StringIOTree() def test_markers(self): assert not self.tree.allmarkers() def test_insertion(self): self.write_lines((1, 2, 3)) line_4_to_6_insertion_point = self.tree.insertion_point() self.write_lines((7, 8)) line_9_to_13_insertion_point = self.tree.insertion_point() self.write_lines((14, 15, 16)) line_4_insertion_point = line_4_to_6_insertion_point.insertion_point() self.write_lines((5, 6), tree=line_4_to_6_insertion_point) line_9_to_12_insertion_point = ( line_9_to_13_insertion_point.insertion_point()) self.write_line(13, tree=line_9_to_13_insertion_point) self.write_line(4, tree=line_4_insertion_point) self.write_line(9, tree=line_9_to_12_insertion_point) line_10_insertion_point = line_9_to_12_insertion_point.insertion_point() self.write_line(11, tree=line_9_to_12_insertion_point) self.write_line(10, tree=line_10_insertion_point) self.write_line(12, tree=line_9_to_12_insertion_point) self.assertEqual(self.tree.allmarkers(), list(range(1, 17))) self.assertEqual(code.strip(), self.tree.getvalue().strip()) def write_lines(self, linenos, tree=None): for lineno in linenos: self.write_line(lineno, tree=tree) def write_line(self, lineno, tree=None): if tree is None: tree = self.tree tree.markers.append(lineno) tree.write(linemap[lineno] + '\n') ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Tests/TestTestUtils.py0000644000175100001770000000562600000000000021325 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*- import os.path import unittest import tempfile import textwrap import shutil from ..TestUtils import write_file, write_newer_file, _parse_pattern class TestTestUtils(unittest.TestCase): def setUp(self): super(TestTestUtils, self).setUp() self.temp_dir = tempfile.mkdtemp() def tearDown(self): if self.temp_dir and os.path.isdir(self.temp_dir): shutil.rmtree(self.temp_dir) super(TestTestUtils, self).tearDown() def _test_path(self, filename): return os.path.join(self.temp_dir, filename) def _test_write_file(self, content, expected, **kwargs): file_path = self._test_path("abcfile") write_file(file_path, content, **kwargs) assert os.path.isfile(file_path) with open(file_path, 'rb') as f: found = f.read() assert found == expected, (repr(expected), repr(found)) def test_write_file_text(self): text = u"abcüöä" self._test_write_file(text, text.encode('utf8')) def test_write_file_dedent(self): text = u""" A horse is a horse, of course, of course, And no one can talk to a horse of course """ self._test_write_file(text, textwrap.dedent(text).encode('utf8'), dedent=True) def test_write_file_bytes(self): self._test_write_file(b"ab\0c", b"ab\0c") def test_write_newer_file(self): file_path_1 = self._test_path("abcfile1.txt") file_path_2 = self._test_path("abcfile2.txt") write_file(file_path_1, "abc") assert os.path.isfile(file_path_1) write_newer_file(file_path_2, file_path_1, "xyz") assert os.path.isfile(file_path_2) assert os.path.getmtime(file_path_2) > os.path.getmtime(file_path_1) def test_write_newer_file_same(self): file_path = self._test_path("abcfile.txt") write_file(file_path, "abc") mtime = os.path.getmtime(file_path) write_newer_file(file_path, file_path, "xyz") assert os.path.getmtime(file_path) > mtime def test_write_newer_file_fresh(self): file_path = self._test_path("abcfile.txt") assert not os.path.exists(file_path) write_newer_file(file_path, file_path, "xyz") assert os.path.isfile(file_path) def test_parse_pattern(self): self.assertEqual( _parse_pattern("pattern"), (None, None, 'pattern') ) self.assertEqual( _parse_pattern("/start/:pattern"), ('start', None, 'pattern') ) self.assertEqual( _parse_pattern(":/end/ pattern"), (None, 'end', 'pattern') ) self.assertEqual( _parse_pattern("/start/:/end/ pattern"), ('start', 'end', 'pattern') ) self.assertEqual( _parse_pattern("/start/:/end/pattern"), ('start', 'end', 'pattern') ) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Tests/__init__.py0000644000175100001770000000001500000000000020247 0ustar00runnerdocker00000000000000# empty file ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Tests/xmlrunner.py0000644000175100001770000003467100000000000020561 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*- """unittest-xml-reporting is a PyUnit-based TestRunner that can export test results to XML files that can be consumed by a wide range of tools, such as build systems, IDEs and Continuous Integration servers. This module provides the XMLTestRunner class, which is heavily based on the default TextTestRunner. This makes the XMLTestRunner very simple to use. The script below, adapted from the unittest documentation, shows how to use XMLTestRunner in a very simple way. In fact, the only difference between this script and the original one is the last line: import random import unittest import xmlrunner class TestSequenceFunctions(unittest.TestCase): def setUp(self): self.seq = range(10) def test_shuffle(self): # make sure the shuffled sequence does not lose any elements random.shuffle(self.seq) self.seq.sort() self.assertEqual(self.seq, range(10)) def test_choice(self): element = random.choice(self.seq) self.assertTrue(element in self.seq) def test_sample(self): self.assertRaises(ValueError, random.sample, self.seq, 20) for element in random.sample(self.seq, 5): self.assertTrue(element in self.seq) if __name__ == '__main__': unittest.main(testRunner=xmlrunner.XMLTestRunner(output='test-reports')) """ from __future__ import absolute_import import os import sys import time from unittest import TestResult, TextTestResult, TextTestRunner import xml.dom.minidom try: from StringIO import StringIO except ImportError: from io import StringIO # doesn't accept 'str' in Py2 class XMLDocument(xml.dom.minidom.Document): def createCDATAOrText(self, data): if ']]>' in data: return self.createTextNode(data) return self.createCDATASection(data) class _TestInfo(object): """This class is used to keep useful information about the execution of a test method. """ # Possible test outcomes (SUCCESS, FAILURE, ERROR) = range(3) def __init__(self, test_result, test_method, outcome=SUCCESS, err=None): "Create a new instance of _TestInfo." self.test_result = test_result self.test_method = test_method self.outcome = outcome self.err = err self.stdout = test_result.stdout and test_result.stdout.getvalue().strip() or '' self.stderr = test_result.stdout and test_result.stderr.getvalue().strip() or '' def get_elapsed_time(self): """Return the time that shows how long the test method took to execute. """ return self.test_result.stop_time - self.test_result.start_time def get_description(self): "Return a text representation of the test method." return self.test_result.getDescription(self.test_method) def get_error_info(self): """Return a text representation of an exception thrown by a test method. """ if not self.err: return '' return self.test_result._exc_info_to_string( self.err, self.test_method) class _XMLTestResult(TextTestResult): """A test result class that can express test results in a XML report. Used by XMLTestRunner. """ def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1, elapsed_times=True): "Create a new instance of _XMLTestResult." TextTestResult.__init__(self, stream, descriptions, verbosity) self.successes = [] self.callback = None self.elapsed_times = elapsed_times self.output_patched = False def _prepare_callback(self, test_info, target_list, verbose_str, short_str): """Append a _TestInfo to the given target list and sets a callback method to be called by stopTest method. """ target_list.append(test_info) def callback(): """This callback prints the test method outcome to the stream, as well as the elapsed time. """ # Ignore the elapsed times for a more reliable unit testing if not self.elapsed_times: self.start_time = self.stop_time = 0 if self.showAll: self.stream.writeln('(%.3fs) %s' % (test_info.get_elapsed_time(), verbose_str)) elif self.dots: self.stream.write(short_str) self.callback = callback def _patch_standard_output(self): """Replace the stdout and stderr streams with string-based streams in order to capture the tests' output. """ if not self.output_patched: (self.old_stdout, self.old_stderr) = (sys.stdout, sys.stderr) self.output_patched = True (sys.stdout, sys.stderr) = (self.stdout, self.stderr) = \ (StringIO(), StringIO()) def _restore_standard_output(self): "Restore the stdout and stderr streams." (sys.stdout, sys.stderr) = (self.old_stdout, self.old_stderr) self.output_patched = False def startTest(self, test): "Called before execute each test method." self._patch_standard_output() self.start_time = time.time() TestResult.startTest(self, test) if self.showAll: self.stream.write(' ' + self.getDescription(test)) self.stream.write(" ... ") def stopTest(self, test): "Called after execute each test method." self._restore_standard_output() TextTestResult.stopTest(self, test) self.stop_time = time.time() if self.callback and callable(self.callback): self.callback() self.callback = None def addSuccess(self, test): "Called when a test executes successfully." self._prepare_callback(_TestInfo(self, test), self.successes, 'OK', '.') def addFailure(self, test, err): "Called when a test method fails." self._prepare_callback(_TestInfo(self, test, _TestInfo.FAILURE, err), self.failures, 'FAIL', 'F') def addError(self, test, err): "Called when a test method raises an error." self._prepare_callback(_TestInfo(self, test, _TestInfo.ERROR, err), self.errors, 'ERROR', 'E') def printErrorList(self, flavour, errors): "Write some information about the FAIL or ERROR to the stream." for test_info in errors: if isinstance(test_info, tuple): test_info, exc_info = test_info try: t = test_info.get_elapsed_time() except AttributeError: t = 0 try: descr = test_info.get_description() except AttributeError: try: descr = test_info.getDescription() except AttributeError: descr = str(test_info) try: err_info = test_info.get_error_info() except AttributeError: err_info = str(test_info) self.stream.writeln(self.separator1) self.stream.writeln('%s [%.3fs]: %s' % (flavour, t, descr)) self.stream.writeln(self.separator2) self.stream.writeln('%s' % err_info) def _get_info_by_testcase(self): """This method organizes test results by TestCase module. This information is used during the report generation, where a XML report will be generated for each TestCase. """ tests_by_testcase = {} for tests in (self.successes, self.failures, self.errors): for test_info in tests: if not isinstance(test_info, _TestInfo): print("Unexpected test result type: %r" % (test_info,)) continue testcase = type(test_info.test_method) # Ignore module name if it is '__main__' module = testcase.__module__ + '.' if module == '__main__.': module = '' testcase_name = module + testcase.__name__ if testcase_name not in tests_by_testcase: tests_by_testcase[testcase_name] = [] tests_by_testcase[testcase_name].append(test_info) return tests_by_testcase def _report_testsuite(suite_name, tests, xml_document): "Appends the testsuite section to the XML document." testsuite = xml_document.createElement('testsuite') xml_document.appendChild(testsuite) testsuite.setAttribute('name', str(suite_name)) testsuite.setAttribute('tests', str(len(tests))) testsuite.setAttribute('time', '%.3f' % sum([e.get_elapsed_time() for e in tests])) failures = len([1 for e in tests if e.outcome == _TestInfo.FAILURE]) testsuite.setAttribute('failures', str(failures)) errors = len([1 for e in tests if e.outcome == _TestInfo.ERROR]) testsuite.setAttribute('errors', str(errors)) return testsuite _report_testsuite = staticmethod(_report_testsuite) def _report_testcase(suite_name, test_result, xml_testsuite, xml_document): "Appends a testcase section to the XML document." testcase = xml_document.createElement('testcase') xml_testsuite.appendChild(testcase) testcase.setAttribute('classname', str(suite_name)) testcase.setAttribute('name', test_result.test_method.shortDescription() or getattr(test_result.test_method, '_testMethodName', str(test_result.test_method))) testcase.setAttribute('time', '%.3f' % test_result.get_elapsed_time()) if (test_result.outcome != _TestInfo.SUCCESS): elem_name = ('failure', 'error')[test_result.outcome-1] failure = xml_document.createElement(elem_name) testcase.appendChild(failure) failure.setAttribute('type', str(test_result.err[0].__name__)) failure.setAttribute('message', str(test_result.err[1])) error_info = test_result.get_error_info() failureText = xml_document.createCDATAOrText(error_info) failure.appendChild(failureText) _report_testcase = staticmethod(_report_testcase) def _report_output(test_runner, xml_testsuite, xml_document, stdout, stderr): "Appends the system-out and system-err sections to the XML document." systemout = xml_document.createElement('system-out') xml_testsuite.appendChild(systemout) systemout_text = xml_document.createCDATAOrText(stdout) systemout.appendChild(systemout_text) systemerr = xml_document.createElement('system-err') xml_testsuite.appendChild(systemerr) systemerr_text = xml_document.createCDATAOrText(stderr) systemerr.appendChild(systemerr_text) _report_output = staticmethod(_report_output) def generate_reports(self, test_runner): "Generates the XML reports to a given XMLTestRunner object." all_results = self._get_info_by_testcase() if isinstance(test_runner.output, str) and not os.path.exists(test_runner.output): os.makedirs(test_runner.output) for suite, tests in all_results.items(): doc = XMLDocument() # Build the XML file testsuite = _XMLTestResult._report_testsuite(suite, tests, doc) stdout, stderr = [], [] for test in tests: _XMLTestResult._report_testcase(suite, test, testsuite, doc) if test.stdout: stdout.extend(['*****************', test.get_description(), test.stdout]) if test.stderr: stderr.extend(['*****************', test.get_description(), test.stderr]) _XMLTestResult._report_output(test_runner, testsuite, doc, '\n'.join(stdout), '\n'.join(stderr)) xml_content = doc.toprettyxml(indent='\t') if type(test_runner.output) is str: report_file = open('%s%sTEST-%s.xml' % (test_runner.output, os.sep, suite), 'w') try: report_file.write(xml_content) finally: report_file.close() else: # Assume that test_runner.output is a stream test_runner.output.write(xml_content) class XMLTestRunner(TextTestRunner): """A test runner class that outputs the results in JUnit like XML files. """ def __init__(self, output='.', stream=None, descriptions=True, verbose=False, elapsed_times=True): "Create a new instance of XMLTestRunner." if stream is None: stream = sys.stderr verbosity = (1, 2)[verbose] TextTestRunner.__init__(self, stream, descriptions, verbosity) self.output = output self.elapsed_times = elapsed_times def _make_result(self): """Create the TestResult object which will be used to store information about the executed tests. """ return _XMLTestResult(self.stream, self.descriptions, self.verbosity, self.elapsed_times) def run(self, test): "Run the given test case or test suite." # Prepare the test execution result = self._make_result() # Print a nice header self.stream.writeln() self.stream.writeln('Running tests...') self.stream.writeln(result.separator2) # Execute tests start_time = time.time() test(result) stop_time = time.time() time_taken = stop_time - start_time # Generate reports self.stream.writeln() self.stream.writeln('Generating XML reports...') result.generate_reports(self) # Print results result.printErrors() self.stream.writeln(result.separator2) run = result.testsRun self.stream.writeln("Ran %d test%s in %.3fs" % (run, run != 1 and "s" or "", time_taken)) self.stream.writeln() # Error traces if not result.wasSuccessful(): self.stream.write("FAILED (") failed, errored = (len(result.failures), len(result.errors)) if failed: self.stream.write("failures=%d" % failed) if errored: if failed: self.stream.write(", ") self.stream.write("errors=%d" % errored) self.stream.writeln(")") else: self.stream.writeln("OK") return result ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.016724 Cython-3.0.8/Cython/Utility/0000755000175100001770000000000000000000000016503 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Utility/AsyncGen.c0000644000175100001770000013550400000000000020366 0ustar00runnerdocker00000000000000// This is copied from genobject.c in CPython 3.6. // Try to keep it in sync by doing this from time to time: // sed -e 's|__pyx_||ig' Cython/Utility/AsyncGen.c | diff -udw - cpython/Objects/genobject.c | less //////////////////// AsyncGenerator.proto //////////////////// //@requires: Coroutine.c::Coroutine #define __Pyx_AsyncGen_USED typedef struct { __pyx_CoroutineObject coro; PyObject *ag_finalizer; int ag_hooks_inited; int ag_closed; int ag_running_async; } __pyx_PyAsyncGenObject; static PyTypeObject *__pyx__PyAsyncGenWrappedValueType = 0; static PyTypeObject *__pyx__PyAsyncGenASendType = 0; static PyTypeObject *__pyx__PyAsyncGenAThrowType = 0; static PyTypeObject *__pyx_AsyncGenType = 0; #define __Pyx_AsyncGen_CheckExact(obj) __Pyx_IS_TYPE(obj, __pyx_AsyncGenType) #define __pyx_PyAsyncGenASend_CheckExact(o) \ __Pyx_IS_TYPE(o, __pyx__PyAsyncGenASendType) #define __pyx_PyAsyncGenAThrow_CheckExact(o) \ __Pyx_IS_TYPE(o, __pyx__PyAsyncGenAThrowType) static PyObject *__Pyx_async_gen_anext(PyObject *o); static CYTHON_INLINE PyObject *__Pyx_async_gen_asend_iternext(PyObject *o); static PyObject *__Pyx_async_gen_asend_send(PyObject *o, PyObject *arg); static PyObject *__Pyx_async_gen_asend_close(PyObject *o, PyObject *args); static PyObject *__Pyx_async_gen_athrow_close(PyObject *o, PyObject *args); static PyObject *__Pyx__PyAsyncGenValueWrapperNew(PyObject *val); static __pyx_CoroutineObject *__Pyx_AsyncGen_New( __pyx_coroutine_body_t body, PyObject *code, PyObject *closure, PyObject *name, PyObject *qualname, PyObject *module_name) { __pyx_PyAsyncGenObject *gen = PyObject_GC_New(__pyx_PyAsyncGenObject, __pyx_AsyncGenType); if (unlikely(!gen)) return NULL; gen->ag_finalizer = NULL; gen->ag_closed = 0; gen->ag_hooks_inited = 0; gen->ag_running_async = 0; return __Pyx__Coroutine_NewInit((__pyx_CoroutineObject*)gen, body, code, closure, name, qualname, module_name); } static int __pyx_AsyncGen_init(PyObject *module); static void __Pyx_PyAsyncGen_Fini(void); //////////////////// AsyncGenerator.cleanup //////////////////// __Pyx_PyAsyncGen_Fini(); //////////////////// AsyncGeneratorInitFinalizer //////////////////// // this is separated out because it needs more adaptation #if PY_VERSION_HEX < 0x030600B0 static int __Pyx_async_gen_init_hooks(__pyx_PyAsyncGenObject *o) { #if 0 // TODO: implement finalizer support in older Python versions PyThreadState *tstate; PyObject *finalizer; PyObject *firstiter; #endif if (likely(o->ag_hooks_inited)) { return 0; } o->ag_hooks_inited = 1; #if 0 tstate = __Pyx_PyThreadState_Current; finalizer = tstate->async_gen_finalizer; if (finalizer) { Py_INCREF(finalizer); o->ag_finalizer = finalizer; } firstiter = tstate->async_gen_firstiter; if (firstiter) { PyObject *res; Py_INCREF(firstiter); res = __Pyx_PyObject_CallOneArg(firstiter, (PyObject*)o); Py_DECREF(firstiter); if (res == NULL) { return 1; } Py_DECREF(res); } #endif return 0; } #endif //////////////////// AsyncGenerator //////////////////// //@requires: AsyncGeneratorInitFinalizer //@requires: Coroutine.c::Coroutine //@requires: Coroutine.c::ReturnWithStopIteration //@requires: ObjectHandling.c::PyObjectCall2Args //@requires: ObjectHandling.c::PyObject_GenericGetAttrNoDict PyDoc_STRVAR(__Pyx_async_gen_send_doc, "send(arg) -> send 'arg' into generator,\n\ return next yielded value or raise StopIteration."); PyDoc_STRVAR(__Pyx_async_gen_close_doc, "close() -> raise GeneratorExit inside generator."); PyDoc_STRVAR(__Pyx_async_gen_throw_doc, "throw(typ[,val[,tb]]) -> raise exception in generator,\n\ return next yielded value or raise StopIteration."); PyDoc_STRVAR(__Pyx_async_gen_await_doc, "__await__() -> return a representation that can be passed into the 'await' expression."); // COPY STARTS HERE: static PyObject *__Pyx_async_gen_asend_new(__pyx_PyAsyncGenObject *, PyObject *); static PyObject *__Pyx_async_gen_athrow_new(__pyx_PyAsyncGenObject *, PyObject *); static const char *__Pyx_NON_INIT_CORO_MSG = "can't send non-None value to a just-started coroutine"; static const char *__Pyx_ASYNC_GEN_IGNORED_EXIT_MSG = "async generator ignored GeneratorExit"; static const char *__Pyx_ASYNC_GEN_CANNOT_REUSE_SEND_MSG = "cannot reuse already awaited __anext__()/asend()"; static const char *__Pyx_ASYNC_GEN_CANNOT_REUSE_CLOSE_MSG = "cannot reuse already awaited aclose()/athrow()"; typedef enum { __PYX_AWAITABLE_STATE_INIT, /* new awaitable, has not yet been iterated */ __PYX_AWAITABLE_STATE_ITER, /* being iterated */ __PYX_AWAITABLE_STATE_CLOSED, /* closed */ } __pyx_AwaitableState; typedef struct { PyObject_HEAD __pyx_PyAsyncGenObject *ags_gen; /* Can be NULL, when in the __anext__() mode (equivalent of "asend(None)") */ PyObject *ags_sendval; __pyx_AwaitableState ags_state; } __pyx_PyAsyncGenASend; typedef struct { PyObject_HEAD __pyx_PyAsyncGenObject *agt_gen; /* Can be NULL, when in the "aclose()" mode (equivalent of "athrow(GeneratorExit)") */ PyObject *agt_args; __pyx_AwaitableState agt_state; } __pyx_PyAsyncGenAThrow; typedef struct { PyObject_HEAD PyObject *agw_val; } __pyx__PyAsyncGenWrappedValue; #ifndef _PyAsyncGen_MAXFREELIST #define _PyAsyncGen_MAXFREELIST 80 #endif // Freelists boost performance 6-10%; they also reduce memory // fragmentation, as _PyAsyncGenWrappedValue and PyAsyncGenASend // are short-living objects that are instantiated for every // __anext__ call. static __pyx__PyAsyncGenWrappedValue *__Pyx_ag_value_freelist[_PyAsyncGen_MAXFREELIST]; static int __Pyx_ag_value_freelist_free = 0; static __pyx_PyAsyncGenASend *__Pyx_ag_asend_freelist[_PyAsyncGen_MAXFREELIST]; static int __Pyx_ag_asend_freelist_free = 0; #define __pyx__PyAsyncGenWrappedValue_CheckExact(o) \ __Pyx_IS_TYPE(o, __pyx__PyAsyncGenWrappedValueType) static int __Pyx_async_gen_traverse(__pyx_PyAsyncGenObject *gen, visitproc visit, void *arg) { Py_VISIT(gen->ag_finalizer); return __Pyx_Coroutine_traverse((__pyx_CoroutineObject*)gen, visit, arg); } static PyObject * __Pyx_async_gen_repr(__pyx_CoroutineObject *o) { // avoid NULL pointer dereference for qualname during garbage collection return PyUnicode_FromFormat("", o->gi_qualname ? o->gi_qualname : Py_None, o); } #if PY_VERSION_HEX >= 0x030600B0 static int __Pyx_async_gen_init_hooks(__pyx_PyAsyncGenObject *o) { #if !CYTHON_COMPILING_IN_PYPY PyThreadState *tstate; #endif PyObject *finalizer; PyObject *firstiter; if (o->ag_hooks_inited) { return 0; } o->ag_hooks_inited = 1; #if CYTHON_COMPILING_IN_PYPY finalizer = _PyEval_GetAsyncGenFinalizer(); #else tstate = __Pyx_PyThreadState_Current; finalizer = tstate->async_gen_finalizer; #endif if (finalizer) { Py_INCREF(finalizer); o->ag_finalizer = finalizer; } #if CYTHON_COMPILING_IN_PYPY firstiter = _PyEval_GetAsyncGenFirstiter(); #else firstiter = tstate->async_gen_firstiter; #endif if (firstiter) { PyObject *res; #if CYTHON_UNPACK_METHODS PyObject *self; #endif Py_INCREF(firstiter); // at least asyncio stores methods here => optimise the call #if CYTHON_UNPACK_METHODS if (likely(PyMethod_Check(firstiter)) && likely((self = PyMethod_GET_SELF(firstiter)) != NULL)) { PyObject *function = PyMethod_GET_FUNCTION(firstiter); res = __Pyx_PyObject_Call2Args(function, self, (PyObject*)o); } else #endif res = __Pyx_PyObject_CallOneArg(firstiter, (PyObject*)o); Py_DECREF(firstiter); if (unlikely(res == NULL)) { return 1; } Py_DECREF(res); } return 0; } #endif static PyObject * __Pyx_async_gen_anext(PyObject *g) { __pyx_PyAsyncGenObject *o = (__pyx_PyAsyncGenObject*) g; if (unlikely(__Pyx_async_gen_init_hooks(o))) { return NULL; } return __Pyx_async_gen_asend_new(o, NULL); } static PyObject * __Pyx_async_gen_anext_method(PyObject *g, PyObject *arg) { CYTHON_UNUSED_VAR(arg); return __Pyx_async_gen_anext(g); } static PyObject * __Pyx_async_gen_asend(__pyx_PyAsyncGenObject *o, PyObject *arg) { if (unlikely(__Pyx_async_gen_init_hooks(o))) { return NULL; } return __Pyx_async_gen_asend_new(o, arg); } static PyObject * __Pyx_async_gen_aclose(__pyx_PyAsyncGenObject *o, PyObject *arg) { CYTHON_UNUSED_VAR(arg); if (unlikely(__Pyx_async_gen_init_hooks(o))) { return NULL; } return __Pyx_async_gen_athrow_new(o, NULL); } static PyObject * __Pyx_async_gen_athrow(__pyx_PyAsyncGenObject *o, PyObject *args) { if (unlikely(__Pyx_async_gen_init_hooks(o))) { return NULL; } return __Pyx_async_gen_athrow_new(o, args); } static PyObject * __Pyx_async_gen_self_method(PyObject *g, PyObject *arg) { CYTHON_UNUSED_VAR(arg); return __Pyx_NewRef(g); } static PyGetSetDef __Pyx_async_gen_getsetlist[] = { {(char*) "__name__", (getter)__Pyx_Coroutine_get_name, (setter)__Pyx_Coroutine_set_name, (char*) PyDoc_STR("name of the async generator"), 0}, {(char*) "__qualname__", (getter)__Pyx_Coroutine_get_qualname, (setter)__Pyx_Coroutine_set_qualname, (char*) PyDoc_STR("qualified name of the async generator"), 0}, //REMOVED: {(char*) "ag_await", (getter)coro_get_cr_await, NULL, //REMOVED: (char*) PyDoc_STR("object being awaited on, or None")}, {0, 0, 0, 0, 0} /* Sentinel */ }; static PyMemberDef __Pyx_async_gen_memberlist[] = { //REMOVED: {(char*) "ag_frame", T_OBJECT, offsetof(__pyx_PyAsyncGenObject, ag_frame), READONLY}, {(char*) "ag_running", T_BOOL, offsetof(__pyx_PyAsyncGenObject, ag_running_async), READONLY, NULL}, //REMOVED: {(char*) "ag_code", T_OBJECT, offsetof(__pyx_PyAsyncGenObject, ag_code), READONLY}, //ADDED: "ag_await" {(char*) "ag_await", T_OBJECT, offsetof(__pyx_CoroutineObject, yieldfrom), READONLY, (char*) PyDoc_STR("object being awaited on, or None")}, {(char *) "__module__", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_modulename), 0, 0}, #if CYTHON_USE_TYPE_SPECS {(char *) "__weaklistoffset__", T_PYSSIZET, offsetof(__pyx_CoroutineObject, gi_weakreflist), READONLY, 0}, #endif {0, 0, 0, 0, 0} /* Sentinel */ }; PyDoc_STRVAR(__Pyx_async_aclose_doc, "aclose() -> raise GeneratorExit inside generator."); PyDoc_STRVAR(__Pyx_async_asend_doc, "asend(v) -> send 'v' in generator."); PyDoc_STRVAR(__Pyx_async_athrow_doc, "athrow(typ[,val[,tb]]) -> raise exception in generator."); PyDoc_STRVAR(__Pyx_async_aiter_doc, "__aiter__(v) -> return an asynchronous iterator."); PyDoc_STRVAR(__Pyx_async_anext_doc, "__anext__(v) -> continue asynchronous iteration and return the next element."); static PyMethodDef __Pyx_async_gen_methods[] = { {"asend", (PyCFunction)__Pyx_async_gen_asend, METH_O, __Pyx_async_asend_doc}, {"athrow",(PyCFunction)__Pyx_async_gen_athrow, METH_VARARGS, __Pyx_async_athrow_doc}, {"aclose", (PyCFunction)__Pyx_async_gen_aclose, METH_NOARGS, __Pyx_async_aclose_doc}, {"__aiter__", (PyCFunction)__Pyx_async_gen_self_method, METH_NOARGS, __Pyx_async_aiter_doc}, {"__anext__", (PyCFunction)__Pyx_async_gen_anext_method, METH_NOARGS, __Pyx_async_anext_doc}, {0, 0, 0, 0} /* Sentinel */ }; #if CYTHON_USE_TYPE_SPECS static PyType_Slot __pyx_AsyncGenType_slots[] = { {Py_tp_dealloc, (void *)__Pyx_Coroutine_dealloc}, {Py_am_aiter, (void *)PyObject_SelfIter}, {Py_am_anext, (void *)__Pyx_async_gen_anext}, {Py_tp_repr, (void *)__Pyx_async_gen_repr}, {Py_tp_traverse, (void *)__Pyx_async_gen_traverse}, {Py_tp_methods, (void *)__Pyx_async_gen_methods}, {Py_tp_members, (void *)__Pyx_async_gen_memberlist}, {Py_tp_getset, (void *)__Pyx_async_gen_getsetlist}, #if CYTHON_USE_TP_FINALIZE {Py_tp_finalize, (void *)__Pyx_Coroutine_del}, #endif {0, 0}, }; static PyType_Spec __pyx_AsyncGenType_spec = { __PYX_TYPE_MODULE_PREFIX "async_generator", sizeof(__pyx_PyAsyncGenObject), 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ __pyx_AsyncGenType_slots }; #else /* CYTHON_USE_TYPE_SPECS */ #if CYTHON_USE_ASYNC_SLOTS static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_as_async = { 0, /* am_await */ PyObject_SelfIter, /* am_aiter */ (unaryfunc)__Pyx_async_gen_anext, /* am_anext */ #if PY_VERSION_HEX >= 0x030A00A3 0, /*am_send*/ #endif }; #endif static PyTypeObject __pyx_AsyncGenType_type = { PyVarObject_HEAD_INIT(0, 0) "async_generator", /* tp_name */ sizeof(__pyx_PyAsyncGenObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)__Pyx_Coroutine_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ #if CYTHON_USE_ASYNC_SLOTS &__Pyx_async_gen_as_async, /* tp_as_async */ #else 0, /*tp_reserved*/ #endif (reprfunc)__Pyx_async_gen_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */ 0, /* tp_doc */ (traverseproc)__Pyx_async_gen_traverse, /* tp_traverse */ 0, /* tp_clear */ #if CYTHON_USE_ASYNC_SLOTS && CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3 && PY_VERSION_HEX < 0x030500B1 // in order to (mis-)use tp_reserved above, we must also implement tp_richcompare __Pyx_Coroutine_compare, /*tp_richcompare*/ #else 0, /*tp_richcompare*/ #endif offsetof(__pyx_CoroutineObject, gi_weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ __Pyx_async_gen_methods, /* tp_methods */ __Pyx_async_gen_memberlist, /* tp_members */ __Pyx_async_gen_getsetlist, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ #if CYTHON_USE_TP_FINALIZE 0, /*tp_del*/ #else __Pyx_Coroutine_del, /*tp_del*/ #endif 0, /* tp_version_tag */ #if CYTHON_USE_TP_FINALIZE __Pyx_Coroutine_del, /* tp_finalize */ #elif PY_VERSION_HEX >= 0x030400a1 0, /* tp_finalize */ #endif #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if __PYX_NEED_TP_PRINT_SLOT 0, /*tp_print*/ #endif #if PY_VERSION_HEX >= 0x030C0000 0, /*tp_watched*/ #endif #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000 0, /*tp_pypy_flags*/ #endif }; #endif /* CYTHON_USE_TYPE_SPECS */ static int __Pyx_PyAsyncGen_ClearFreeLists(void) { int ret = __Pyx_ag_value_freelist_free + __Pyx_ag_asend_freelist_free; while (__Pyx_ag_value_freelist_free) { __pyx__PyAsyncGenWrappedValue *o; o = __Pyx_ag_value_freelist[--__Pyx_ag_value_freelist_free]; assert(__pyx__PyAsyncGenWrappedValue_CheckExact(o)); __Pyx_PyHeapTypeObject_GC_Del(o); } while (__Pyx_ag_asend_freelist_free) { __pyx_PyAsyncGenASend *o; o = __Pyx_ag_asend_freelist[--__Pyx_ag_asend_freelist_free]; assert(__Pyx_IS_TYPE(o, __pyx__PyAsyncGenASendType)); __Pyx_PyHeapTypeObject_GC_Del(o); } return ret; } static void __Pyx_PyAsyncGen_Fini(void) { __Pyx_PyAsyncGen_ClearFreeLists(); } static PyObject * __Pyx_async_gen_unwrap_value(__pyx_PyAsyncGenObject *gen, PyObject *result) { if (result == NULL) { PyObject *exc_type = PyErr_Occurred(); if (!exc_type) { PyErr_SetNone(__Pyx_PyExc_StopAsyncIteration); gen->ag_closed = 1; } else if (__Pyx_PyErr_GivenExceptionMatches2(exc_type, __Pyx_PyExc_StopAsyncIteration, PyExc_GeneratorExit)) { gen->ag_closed = 1; } gen->ag_running_async = 0; return NULL; } if (__pyx__PyAsyncGenWrappedValue_CheckExact(result)) { /* async yield */ __Pyx_ReturnWithStopIteration(((__pyx__PyAsyncGenWrappedValue*)result)->agw_val); Py_DECREF(result); gen->ag_running_async = 0; return NULL; } return result; } /* ---------- Async Generator ASend Awaitable ------------ */ static void __Pyx_async_gen_asend_dealloc(__pyx_PyAsyncGenASend *o) { PyObject_GC_UnTrack((PyObject *)o); Py_CLEAR(o->ags_gen); Py_CLEAR(o->ags_sendval); if (likely(__Pyx_ag_asend_freelist_free < _PyAsyncGen_MAXFREELIST)) { assert(__pyx_PyAsyncGenASend_CheckExact(o)); __Pyx_ag_asend_freelist[__Pyx_ag_asend_freelist_free++] = o; } else { __Pyx_PyHeapTypeObject_GC_Del(o); } } static int __Pyx_async_gen_asend_traverse(__pyx_PyAsyncGenASend *o, visitproc visit, void *arg) { Py_VISIT(o->ags_gen); Py_VISIT(o->ags_sendval); return 0; } static PyObject * __Pyx_async_gen_asend_send(PyObject *g, PyObject *arg) { __pyx_PyAsyncGenASend *o = (__pyx_PyAsyncGenASend*) g; PyObject *result; if (unlikely(o->ags_state == __PYX_AWAITABLE_STATE_CLOSED)) { PyErr_SetString(PyExc_RuntimeError, __Pyx_ASYNC_GEN_CANNOT_REUSE_SEND_MSG); return NULL; } if (o->ags_state == __PYX_AWAITABLE_STATE_INIT) { if (unlikely(o->ags_gen->ag_running_async)) { PyErr_SetString( PyExc_RuntimeError, "anext(): asynchronous generator is already running"); return NULL; } if (arg == NULL || arg == Py_None) { arg = o->ags_sendval ? o->ags_sendval : Py_None; } o->ags_state = __PYX_AWAITABLE_STATE_ITER; } o->ags_gen->ag_running_async = 1; result = __Pyx_Coroutine_Send((PyObject*)o->ags_gen, arg); result = __Pyx_async_gen_unwrap_value(o->ags_gen, result); if (result == NULL) { o->ags_state = __PYX_AWAITABLE_STATE_CLOSED; } return result; } static CYTHON_INLINE PyObject * __Pyx_async_gen_asend_iternext(PyObject *o) { return __Pyx_async_gen_asend_send(o, Py_None); } static PyObject * __Pyx_async_gen_asend_throw(__pyx_PyAsyncGenASend *o, PyObject *args) { PyObject *result; if (unlikely(o->ags_state == __PYX_AWAITABLE_STATE_CLOSED)) { PyErr_SetString(PyExc_RuntimeError, __Pyx_ASYNC_GEN_CANNOT_REUSE_SEND_MSG); return NULL; } result = __Pyx_Coroutine_Throw((PyObject*)o->ags_gen, args); result = __Pyx_async_gen_unwrap_value(o->ags_gen, result); if (result == NULL) { o->ags_state = __PYX_AWAITABLE_STATE_CLOSED; } return result; } static PyObject * __Pyx_async_gen_asend_close(PyObject *g, PyObject *args) { __pyx_PyAsyncGenASend *o = (__pyx_PyAsyncGenASend*) g; CYTHON_UNUSED_VAR(args); o->ags_state = __PYX_AWAITABLE_STATE_CLOSED; Py_RETURN_NONE; } static PyMethodDef __Pyx_async_gen_asend_methods[] = { {"send", (PyCFunction)__Pyx_async_gen_asend_send, METH_O, __Pyx_async_gen_send_doc}, {"throw", (PyCFunction)__Pyx_async_gen_asend_throw, METH_VARARGS, __Pyx_async_gen_throw_doc}, {"close", (PyCFunction)__Pyx_async_gen_asend_close, METH_NOARGS, __Pyx_async_gen_close_doc}, {"__await__", (PyCFunction)__Pyx_async_gen_self_method, METH_NOARGS, __Pyx_async_gen_await_doc}, {0, 0, 0, 0} /* Sentinel */ }; #if CYTHON_USE_TYPE_SPECS static PyType_Slot __pyx__PyAsyncGenASendType_slots[] = { {Py_tp_dealloc, (void *)__Pyx_async_gen_asend_dealloc}, {Py_am_await, (void *)PyObject_SelfIter}, {Py_tp_traverse, (void *)__Pyx_async_gen_asend_traverse}, {Py_tp_methods, (void *)__Pyx_async_gen_asend_methods}, {Py_tp_iter, (void *)PyObject_SelfIter}, {Py_tp_iternext, (void *)__Pyx_async_gen_asend_iternext}, {0, 0}, }; static PyType_Spec __pyx__PyAsyncGenASendType_spec = { __PYX_TYPE_MODULE_PREFIX "async_generator_asend", sizeof(__pyx_PyAsyncGenASend), 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ __pyx__PyAsyncGenASendType_slots }; #else /* CYTHON_USE_TYPE_SPECS */ #if CYTHON_USE_ASYNC_SLOTS static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_asend_as_async = { PyObject_SelfIter, /* am_await */ 0, /* am_aiter */ 0, /* am_anext */ #if PY_VERSION_HEX >= 0x030A00A3 0, /*am_send*/ #endif }; #endif static PyTypeObject __pyx__PyAsyncGenASendType_type = { PyVarObject_HEAD_INIT(0, 0) "async_generator_asend", /* tp_name */ sizeof(__pyx_PyAsyncGenASend), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)__Pyx_async_gen_asend_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ #if CYTHON_USE_ASYNC_SLOTS &__Pyx_async_gen_asend_as_async, /* tp_as_async */ #else 0, /*tp_reserved*/ #endif 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)__Pyx_async_gen_asend_traverse, /* tp_traverse */ 0, /* tp_clear */ #if CYTHON_USE_ASYNC_SLOTS && CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3 && PY_VERSION_HEX < 0x030500B1 // in order to (mis-)use tp_reserved above, we must also implement tp_richcompare __Pyx_Coroutine_compare, /*tp_richcompare*/ #else 0, /*tp_richcompare*/ #endif 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)__Pyx_async_gen_asend_iternext, /* tp_iternext */ __Pyx_async_gen_asend_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0, /* tp_version_tag */ #if PY_VERSION_HEX >= 0x030400a1 0, /* tp_finalize */ #endif #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if __PYX_NEED_TP_PRINT_SLOT 0, /*tp_print*/ #endif #if PY_VERSION_HEX >= 0x030C0000 0, /*tp_watched*/ #endif #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000 0, /*tp_pypy_flags*/ #endif }; #endif /* CYTHON_USE_TYPE_SPECS */ static PyObject * __Pyx_async_gen_asend_new(__pyx_PyAsyncGenObject *gen, PyObject *sendval) { __pyx_PyAsyncGenASend *o; if (likely(__Pyx_ag_asend_freelist_free)) { __Pyx_ag_asend_freelist_free--; o = __Pyx_ag_asend_freelist[__Pyx_ag_asend_freelist_free]; _Py_NewReference((PyObject *)o); } else { o = PyObject_GC_New(__pyx_PyAsyncGenASend, __pyx__PyAsyncGenASendType); if (unlikely(o == NULL)) { return NULL; } } Py_INCREF(gen); o->ags_gen = gen; Py_XINCREF(sendval); o->ags_sendval = sendval; o->ags_state = __PYX_AWAITABLE_STATE_INIT; PyObject_GC_Track((PyObject*)o); return (PyObject*)o; } /* ---------- Async Generator Value Wrapper ------------ */ static void __Pyx_async_gen_wrapped_val_dealloc(__pyx__PyAsyncGenWrappedValue *o) { PyObject_GC_UnTrack((PyObject *)o); Py_CLEAR(o->agw_val); if (likely(__Pyx_ag_value_freelist_free < _PyAsyncGen_MAXFREELIST)) { assert(__pyx__PyAsyncGenWrappedValue_CheckExact(o)); __Pyx_ag_value_freelist[__Pyx_ag_value_freelist_free++] = o; } else { __Pyx_PyHeapTypeObject_GC_Del(o); } } static int __Pyx_async_gen_wrapped_val_traverse(__pyx__PyAsyncGenWrappedValue *o, visitproc visit, void *arg) { Py_VISIT(o->agw_val); return 0; } #if CYTHON_USE_TYPE_SPECS static PyType_Slot __pyx__PyAsyncGenWrappedValueType_slots[] = { {Py_tp_dealloc, (void *)__Pyx_async_gen_wrapped_val_dealloc}, {Py_tp_traverse, (void *)__Pyx_async_gen_wrapped_val_traverse}, {0, 0}, }; static PyType_Spec __pyx__PyAsyncGenWrappedValueType_spec = { __PYX_TYPE_MODULE_PREFIX "async_generator_wrapped_value", sizeof(__pyx__PyAsyncGenWrappedValue), 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ __pyx__PyAsyncGenWrappedValueType_slots }; #else /* CYTHON_USE_TYPE_SPECS */ static PyTypeObject __pyx__PyAsyncGenWrappedValueType_type = { PyVarObject_HEAD_INIT(0, 0) "async_generator_wrapped_value", /* tp_name */ sizeof(__pyx__PyAsyncGenWrappedValue), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)__Pyx_async_gen_wrapped_val_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)__Pyx_async_gen_wrapped_val_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0, /* tp_version_tag */ #if PY_VERSION_HEX >= 0x030400a1 0, /* tp_finalize */ #endif #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if __PYX_NEED_TP_PRINT_SLOT 0, /*tp_print*/ #endif #if PY_VERSION_HEX >= 0x030C0000 0, /*tp_watched*/ #endif #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000 0, /*tp_pypy_flags*/ #endif }; #endif /* CYTHON_USE_TYPE_SPECS */ static PyObject * __Pyx__PyAsyncGenValueWrapperNew(PyObject *val) { // NOTE: steals a reference to val ! __pyx__PyAsyncGenWrappedValue *o; assert(val); if (likely(__Pyx_ag_value_freelist_free)) { __Pyx_ag_value_freelist_free--; o = __Pyx_ag_value_freelist[__Pyx_ag_value_freelist_free]; assert(__pyx__PyAsyncGenWrappedValue_CheckExact(o)); _Py_NewReference((PyObject*)o); } else { o = PyObject_GC_New(__pyx__PyAsyncGenWrappedValue, __pyx__PyAsyncGenWrappedValueType); if (unlikely(!o)) { Py_DECREF(val); return NULL; } } o->agw_val = val; // no Py_INCREF(val) - steals reference! PyObject_GC_Track((PyObject*)o); return (PyObject*)o; } /* ---------- Async Generator AThrow awaitable ------------ */ static void __Pyx_async_gen_athrow_dealloc(__pyx_PyAsyncGenAThrow *o) { PyObject_GC_UnTrack((PyObject *)o); Py_CLEAR(o->agt_gen); Py_CLEAR(o->agt_args); __Pyx_PyHeapTypeObject_GC_Del(o); } static int __Pyx_async_gen_athrow_traverse(__pyx_PyAsyncGenAThrow *o, visitproc visit, void *arg) { Py_VISIT(o->agt_gen); Py_VISIT(o->agt_args); return 0; } static PyObject * __Pyx_async_gen_athrow_send(__pyx_PyAsyncGenAThrow *o, PyObject *arg) { __pyx_CoroutineObject *gen = (__pyx_CoroutineObject*)o->agt_gen; PyObject *retval, *exc_type; if (unlikely(o->agt_state == __PYX_AWAITABLE_STATE_CLOSED)) { PyErr_SetString(PyExc_RuntimeError, __Pyx_ASYNC_GEN_CANNOT_REUSE_CLOSE_MSG); return NULL; } if (unlikely(gen->resume_label == -1)) { // already run past the end o->agt_state = __PYX_AWAITABLE_STATE_CLOSED; PyErr_SetNone(PyExc_StopIteration); return NULL; } if (o->agt_state == __PYX_AWAITABLE_STATE_INIT) { if (unlikely(o->agt_gen->ag_running_async)) { o->agt_state = __PYX_AWAITABLE_STATE_CLOSED; if (o->agt_args == NULL) { PyErr_SetString( PyExc_RuntimeError, "aclose(): asynchronous generator is already running"); } else { PyErr_SetString( PyExc_RuntimeError, "athrow(): asynchronous generator is already running"); } return NULL; } if (unlikely(o->agt_gen->ag_closed)) { o->agt_state = __PYX_AWAITABLE_STATE_CLOSED; PyErr_SetNone(__Pyx_PyExc_StopAsyncIteration); return NULL; } if (unlikely(arg != Py_None)) { PyErr_SetString(PyExc_RuntimeError, __Pyx_NON_INIT_CORO_MSG); return NULL; } o->agt_state = __PYX_AWAITABLE_STATE_ITER; o->agt_gen->ag_running_async = 1; if (o->agt_args == NULL) { /* aclose() mode */ o->agt_gen->ag_closed = 1; retval = __Pyx__Coroutine_Throw((PyObject*)gen, /* Do not close generator when PyExc_GeneratorExit is passed */ PyExc_GeneratorExit, NULL, NULL, NULL, 0); if (retval && __pyx__PyAsyncGenWrappedValue_CheckExact(retval)) { Py_DECREF(retval); goto yield_close; } } else { PyObject *typ; PyObject *tb = NULL; PyObject *val = NULL; if (unlikely(!PyArg_UnpackTuple(o->agt_args, "athrow", 1, 3, &typ, &val, &tb))) { return NULL; } retval = __Pyx__Coroutine_Throw((PyObject*)gen, /* Do not close generator when PyExc_GeneratorExit is passed */ typ, val, tb, o->agt_args, 0); retval = __Pyx_async_gen_unwrap_value(o->agt_gen, retval); } if (retval == NULL) { goto check_error; } return retval; } assert (o->agt_state == __PYX_AWAITABLE_STATE_ITER); retval = __Pyx_Coroutine_Send((PyObject *)gen, arg); if (o->agt_args) { return __Pyx_async_gen_unwrap_value(o->agt_gen, retval); } else { /* aclose() mode */ if (retval) { if (unlikely(__pyx__PyAsyncGenWrappedValue_CheckExact(retval))) { Py_DECREF(retval); goto yield_close; } else { return retval; } } else { goto check_error; } } yield_close: o->agt_gen->ag_running_async = 0; o->agt_state = __PYX_AWAITABLE_STATE_CLOSED; PyErr_SetString( PyExc_RuntimeError, __Pyx_ASYNC_GEN_IGNORED_EXIT_MSG); return NULL; check_error: o->agt_gen->ag_running_async = 0; o->agt_state = __PYX_AWAITABLE_STATE_CLOSED; exc_type = PyErr_Occurred(); if (__Pyx_PyErr_GivenExceptionMatches2(exc_type, __Pyx_PyExc_StopAsyncIteration, PyExc_GeneratorExit)) { if (o->agt_args == NULL) { // when aclose() is called we don't want to propagate // StopAsyncIteration or GeneratorExit; just raise // StopIteration, signalling that this 'aclose()' await // is done. PyErr_Clear(); PyErr_SetNone(PyExc_StopIteration); } } return NULL; } static PyObject * __Pyx_async_gen_athrow_throw(__pyx_PyAsyncGenAThrow *o, PyObject *args) { PyObject *retval; if (unlikely(o->agt_state == __PYX_AWAITABLE_STATE_CLOSED)) { PyErr_SetString(PyExc_RuntimeError, __Pyx_ASYNC_GEN_CANNOT_REUSE_CLOSE_MSG); return NULL; } retval = __Pyx_Coroutine_Throw((PyObject*)o->agt_gen, args); if (o->agt_args) { return __Pyx_async_gen_unwrap_value(o->agt_gen, retval); } else { // aclose() mode PyObject *exc_type; if (unlikely(retval && __pyx__PyAsyncGenWrappedValue_CheckExact(retval))) { o->agt_gen->ag_running_async = 0; o->agt_state = __PYX_AWAITABLE_STATE_CLOSED; Py_DECREF(retval); PyErr_SetString(PyExc_RuntimeError, __Pyx_ASYNC_GEN_IGNORED_EXIT_MSG); return NULL; } exc_type = PyErr_Occurred(); if (__Pyx_PyErr_GivenExceptionMatches2(exc_type, __Pyx_PyExc_StopAsyncIteration, PyExc_GeneratorExit)) { // when aclose() is called we don't want to propagate // StopAsyncIteration or GeneratorExit; just raise // StopIteration, signalling that this 'aclose()' await // is done. PyErr_Clear(); PyErr_SetNone(PyExc_StopIteration); } return retval; } } static PyObject * __Pyx_async_gen_athrow_iternext(__pyx_PyAsyncGenAThrow *o) { return __Pyx_async_gen_athrow_send(o, Py_None); } static PyObject * __Pyx_async_gen_athrow_close(PyObject *g, PyObject *args) { __pyx_PyAsyncGenAThrow *o = (__pyx_PyAsyncGenAThrow*) g; CYTHON_UNUSED_VAR(args); o->agt_state = __PYX_AWAITABLE_STATE_CLOSED; Py_RETURN_NONE; } static PyMethodDef __Pyx_async_gen_athrow_methods[] = { {"send", (PyCFunction)__Pyx_async_gen_athrow_send, METH_O, __Pyx_async_gen_send_doc}, {"throw", (PyCFunction)__Pyx_async_gen_athrow_throw, METH_VARARGS, __Pyx_async_gen_throw_doc}, {"close", (PyCFunction)__Pyx_async_gen_athrow_close, METH_NOARGS, __Pyx_async_gen_close_doc}, {"__await__", (PyCFunction)__Pyx_async_gen_self_method, METH_NOARGS, __Pyx_async_gen_await_doc}, {0, 0, 0, 0} /* Sentinel */ }; #if CYTHON_USE_TYPE_SPECS static PyType_Slot __pyx__PyAsyncGenAThrowType_slots[] = { {Py_tp_dealloc, (void *)__Pyx_async_gen_athrow_dealloc}, {Py_am_await, (void *)PyObject_SelfIter}, {Py_tp_traverse, (void *)__Pyx_async_gen_athrow_traverse}, {Py_tp_iter, (void *)PyObject_SelfIter}, {Py_tp_iternext, (void *)__Pyx_async_gen_athrow_iternext}, {Py_tp_methods, (void *)__Pyx_async_gen_athrow_methods}, {Py_tp_getattro, (void *)__Pyx_PyObject_GenericGetAttrNoDict}, {0, 0}, }; static PyType_Spec __pyx__PyAsyncGenAThrowType_spec = { __PYX_TYPE_MODULE_PREFIX "async_generator_athrow", sizeof(__pyx_PyAsyncGenAThrow), 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ __pyx__PyAsyncGenAThrowType_slots }; #else /* CYTHON_USE_TYPE_SPECS */ #if CYTHON_USE_ASYNC_SLOTS static __Pyx_PyAsyncMethodsStruct __Pyx_async_gen_athrow_as_async = { PyObject_SelfIter, /* am_await */ 0, /* am_aiter */ 0, /* am_anext */ #if PY_VERSION_HEX >= 0x030A00A3 0, /*am_send*/ #endif }; #endif static PyTypeObject __pyx__PyAsyncGenAThrowType_type = { PyVarObject_HEAD_INIT(0, 0) "async_generator_athrow", /* tp_name */ sizeof(__pyx_PyAsyncGenAThrow), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)__Pyx_async_gen_athrow_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ #if CYTHON_USE_ASYNC_SLOTS &__Pyx_async_gen_athrow_as_async, /* tp_as_async */ #else 0, /*tp_reserved*/ #endif 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)__Pyx_async_gen_athrow_traverse, /* tp_traverse */ 0, /* tp_clear */ #if CYTHON_USE_ASYNC_SLOTS && CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3 && PY_VERSION_HEX < 0x030500B1 // in order to (mis-)use tp_reserved above, we must also implement tp_richcompare __Pyx_Coroutine_compare, /*tp_richcompare*/ #else 0, /*tp_richcompare*/ #endif 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)__Pyx_async_gen_athrow_iternext, /* tp_iternext */ __Pyx_async_gen_athrow_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0, /* tp_version_tag */ #if PY_VERSION_HEX >= 0x030400a1 0, /* tp_finalize */ #endif #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if __PYX_NEED_TP_PRINT_SLOT 0, /*tp_print*/ #endif #if PY_VERSION_HEX >= 0x030C0000 0, /*tp_watched*/ #endif #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000 0, /*tp_pypy_flags*/ #endif }; #endif /* CYTHON_USE_TYPE_SPECS */ static PyObject * __Pyx_async_gen_athrow_new(__pyx_PyAsyncGenObject *gen, PyObject *args) { __pyx_PyAsyncGenAThrow *o; o = PyObject_GC_New(__pyx_PyAsyncGenAThrow, __pyx__PyAsyncGenAThrowType); if (unlikely(o == NULL)) { return NULL; } o->agt_gen = gen; o->agt_args = args; o->agt_state = __PYX_AWAITABLE_STATE_INIT; Py_INCREF(gen); Py_XINCREF(args); PyObject_GC_Track((PyObject*)o); return (PyObject*)o; } /* ---------- global type sharing ------------ */ static int __pyx_AsyncGen_init(PyObject *module) { #if CYTHON_USE_TYPE_SPECS __pyx_AsyncGenType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_AsyncGenType_spec, NULL); #else CYTHON_MAYBE_UNUSED_VAR(module); // on Windows, C-API functions can't be used in slots statically __pyx_AsyncGenType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict; __pyx_AsyncGenType = __Pyx_FetchCommonType(&__pyx_AsyncGenType_type); #endif if (unlikely(!__pyx_AsyncGenType)) return -1; #if CYTHON_USE_TYPE_SPECS __pyx__PyAsyncGenAThrowType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx__PyAsyncGenAThrowType_spec, NULL); #else __pyx__PyAsyncGenAThrowType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict; __pyx__PyAsyncGenAThrowType = __Pyx_FetchCommonType(&__pyx__PyAsyncGenAThrowType_type); #endif if (unlikely(!__pyx__PyAsyncGenAThrowType)) return -1; #if CYTHON_USE_TYPE_SPECS __pyx__PyAsyncGenWrappedValueType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx__PyAsyncGenWrappedValueType_spec, NULL); #else __pyx__PyAsyncGenWrappedValueType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict; __pyx__PyAsyncGenWrappedValueType = __Pyx_FetchCommonType(&__pyx__PyAsyncGenWrappedValueType_type); #endif if (unlikely(!__pyx__PyAsyncGenWrappedValueType)) return -1; #if CYTHON_USE_TYPE_SPECS __pyx__PyAsyncGenASendType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx__PyAsyncGenASendType_spec, NULL); #else __pyx__PyAsyncGenASendType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict; __pyx__PyAsyncGenASendType = __Pyx_FetchCommonType(&__pyx__PyAsyncGenASendType_type); #endif if (unlikely(!__pyx__PyAsyncGenASendType)) return -1; return 0; } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Utility/Buffer.c0000644000175100001770000007232600000000000020072 0ustar00runnerdocker00000000000000/////////////// BufferStructDeclare.proto /////////////// /* structs for buffer access */ typedef struct { Py_ssize_t shape, strides, suboffsets; } __Pyx_Buf_DimInfo; typedef struct { size_t refcount; Py_buffer pybuffer; } __Pyx_Buffer; typedef struct { __Pyx_Buffer *rcbuffer; char *data; __Pyx_Buf_DimInfo diminfo[{{max_dims}}]; } __Pyx_LocalBuf_ND; /////////////// BufferIndexError.proto /////////////// static void __Pyx_RaiseBufferIndexError(int axis); /*proto*/ /////////////// BufferIndexError /////////////// static void __Pyx_RaiseBufferIndexError(int axis) { PyErr_Format(PyExc_IndexError, "Out of bounds on buffer access (axis %d)", axis); } /////////////// BufferIndexErrorNogil.proto /////////////// //@requires: BufferIndexError static void __Pyx_RaiseBufferIndexErrorNogil(int axis); /*proto*/ /////////////// BufferIndexErrorNogil /////////////// static void __Pyx_RaiseBufferIndexErrorNogil(int axis) { #ifdef WITH_THREAD PyGILState_STATE gilstate = PyGILState_Ensure(); #endif __Pyx_RaiseBufferIndexError(axis); #ifdef WITH_THREAD PyGILState_Release(gilstate); #endif } /////////////// BufferFallbackError.proto /////////////// static void __Pyx_RaiseBufferFallbackError(void); /*proto*/ /////////////// BufferFallbackError /////////////// static void __Pyx_RaiseBufferFallbackError(void) { PyErr_SetString(PyExc_ValueError, "Buffer acquisition failed on assignment; and then reacquiring the old buffer failed too!"); } /////////////// BufferFormatStructs.proto /////////////// //@proto_block: utility_code_proto_before_types /* Run-time type information about structs used with buffers */ struct __Pyx_StructField_; #define __PYX_BUF_FLAGS_PACKED_STRUCT (1 << 0) typedef struct { const char* name; /* for error messages only */ struct __Pyx_StructField_* fields; size_t size; /* sizeof(type) */ size_t arraysize[8]; /* length of array in each dimension */ int ndim; char typegroup; /* _R_eal, _C_omplex, Signed _I_nt, _U_nsigned int, _S_truct, _P_ointer, _O_bject, c_H_ar */ char is_unsigned; int flags; } __Pyx_TypeInfo; typedef struct __Pyx_StructField_ { __Pyx_TypeInfo* type; const char* name; size_t offset; } __Pyx_StructField; typedef struct { __Pyx_StructField* field; size_t parent_offset; } __Pyx_BufFmt_StackElem; typedef struct { __Pyx_StructField root; __Pyx_BufFmt_StackElem* head; size_t fmt_offset; size_t new_count, enc_count; size_t struct_alignment; int is_complex; char enc_type; char new_packmode; char enc_packmode; char is_valid_array; } __Pyx_BufFmt_Context; /////////////// GetAndReleaseBuffer.proto /////////////// #if PY_MAJOR_VERSION < 3 static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags); static void __Pyx_ReleaseBuffer(Py_buffer *view); #else #define __Pyx_GetBuffer PyObject_GetBuffer #define __Pyx_ReleaseBuffer PyBuffer_Release #endif /////////////// GetAndReleaseBuffer /////////////// #if PY_MAJOR_VERSION < 3 static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { __Pyx_TypeName obj_type_name; if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags); {{for type_ptr, getbuffer, releasebuffer in types}} {{if getbuffer}} if (__Pyx_TypeCheck(obj, {{type_ptr}})) return {{getbuffer}}(obj, view, flags); {{endif}} {{endfor}} obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj)); PyErr_Format(PyExc_TypeError, "'" __Pyx_FMT_TYPENAME "' does not have the buffer interface", obj_type_name); __Pyx_DECREF_TypeName(obj_type_name); return -1; } static void __Pyx_ReleaseBuffer(Py_buffer *view) { PyObject *obj = view->obj; if (!obj) return; if (PyObject_CheckBuffer(obj)) { PyBuffer_Release(view); return; } if ((0)) {} {{for type_ptr, getbuffer, releasebuffer in types}} {{if releasebuffer}} else if (__Pyx_TypeCheck(obj, {{type_ptr}})) {{releasebuffer}}(obj, view); {{endif}} {{endfor}} view->obj = NULL; Py_DECREF(obj); } #endif /* PY_MAJOR_VERSION < 3 */ /////////////// BufferGetAndValidate.proto /////////////// #define __Pyx_GetBufferAndValidate(buf, obj, dtype, flags, nd, cast, stack) \ ((obj == Py_None || obj == NULL) ? \ (__Pyx_ZeroBuffer(buf), 0) : \ __Pyx__GetBufferAndValidate(buf, obj, dtype, flags, nd, cast, stack)) static int __Pyx__GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack); static void __Pyx_ZeroBuffer(Py_buffer* buf); static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info);/*proto*/ static Py_ssize_t __Pyx_minusones[] = { {{ ", ".join(["-1"] * max_dims) }} }; static Py_ssize_t __Pyx_zeros[] = { {{ ", ".join(["0"] * max_dims) }} }; /////////////// BufferGetAndValidate /////////////// //@requires: BufferFormatCheck static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) { if (unlikely(info->buf == NULL)) return; if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL; __Pyx_ReleaseBuffer(info); } static void __Pyx_ZeroBuffer(Py_buffer* buf) { buf->buf = NULL; buf->obj = NULL; buf->strides = __Pyx_zeros; buf->shape = __Pyx_zeros; buf->suboffsets = __Pyx_minusones; } static int __Pyx__GetBufferAndValidate( Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack) { buf->buf = NULL; if (unlikely(__Pyx_GetBuffer(obj, buf, flags) == -1)) { __Pyx_ZeroBuffer(buf); return -1; } // From this point on, we have acquired the buffer and must release it on errors. if (unlikely(buf->ndim != nd)) { PyErr_Format(PyExc_ValueError, "Buffer has wrong number of dimensions (expected %d, got %d)", nd, buf->ndim); goto fail; } if (!cast) { __Pyx_BufFmt_Context ctx; __Pyx_BufFmt_Init(&ctx, stack, dtype); if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail; } if (unlikely((size_t)buf->itemsize != dtype->size)) { PyErr_Format(PyExc_ValueError, "Item size of buffer (%" CYTHON_FORMAT_SSIZE_T "d byte%s) does not match size of '%s' (%" CYTHON_FORMAT_SSIZE_T "d byte%s)", buf->itemsize, (buf->itemsize > 1) ? "s" : "", dtype->name, (Py_ssize_t)dtype->size, (dtype->size > 1) ? "s" : ""); goto fail; } if (buf->suboffsets == NULL) buf->suboffsets = __Pyx_minusones; return 0; fail:; __Pyx_SafeReleaseBuffer(buf); return -1; } /////////////// BufferFormatCheck.proto /////////////// // Buffer format string checking // // Buffer type checking. Utility code for checking that acquired // buffers match our assumptions. We only need to check ndim and // the format string; the access mode/flags is checked by the // exporter. See: // // https://docs.python.org/3/library/struct.html // https://www.python.org/dev/peps/pep-3118/#additions-to-the-struct-string-syntax // // The alignment code is copied from _struct.c in Python. static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts); static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, __Pyx_BufFmt_StackElem* stack, __Pyx_TypeInfo* type); /*proto*/ /////////////// BufferFormatCheck /////////////// //@requires: ModuleSetupCode.c::IsLittleEndian //@requires: BufferFormatStructs static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, __Pyx_BufFmt_StackElem* stack, __Pyx_TypeInfo* type) { stack[0].field = &ctx->root; stack[0].parent_offset = 0; ctx->root.type = type; ctx->root.name = "buffer dtype"; ctx->root.offset = 0; ctx->head = stack; ctx->head->field = &ctx->root; ctx->fmt_offset = 0; ctx->head->parent_offset = 0; ctx->new_packmode = '@'; ctx->enc_packmode = '@'; ctx->new_count = 1; ctx->enc_count = 0; ctx->enc_type = 0; ctx->is_complex = 0; ctx->is_valid_array = 0; ctx->struct_alignment = 0; while (type->typegroup == 'S') { ++ctx->head; ctx->head->field = type->fields; ctx->head->parent_offset = 0; type = type->fields->type; } } static int __Pyx_BufFmt_ParseNumber(const char** ts) { int count; const char* t = *ts; if (*t < '0' || *t > '9') { return -1; } else { count = *t++ - '0'; while (*t >= '0' && *t <= '9') { count *= 10; count += *t++ - '0'; } } *ts = t; return count; } static int __Pyx_BufFmt_ExpectNumber(const char **ts) { int number = __Pyx_BufFmt_ParseNumber(ts); if (number == -1) /* First char was not a digit */ PyErr_Format(PyExc_ValueError,\ "Does not understand character buffer dtype format string ('%c')", **ts); return number; } static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) { PyErr_Format(PyExc_ValueError, "Unexpected format string character: '%c'", ch); } static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) { switch (ch) { case '?': return "'bool'"; case 'c': return "'char'"; case 'b': return "'signed char'"; case 'B': return "'unsigned char'"; case 'h': return "'short'"; case 'H': return "'unsigned short'"; case 'i': return "'int'"; case 'I': return "'unsigned int'"; case 'l': return "'long'"; case 'L': return "'unsigned long'"; case 'q': return "'long long'"; case 'Q': return "'unsigned long long'"; case 'f': return (is_complex ? "'complex float'" : "'float'"); case 'd': return (is_complex ? "'complex double'" : "'double'"); case 'g': return (is_complex ? "'complex long double'" : "'long double'"); case 'T': return "a struct"; case 'O': return "Python object"; case 'P': return "a pointer"; case 's': case 'p': return "a string"; case 0: return "end"; default: return "unparsable format string"; } } static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) { switch (ch) { case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; case 'h': case 'H': return 2; case 'i': case 'I': case 'l': case 'L': return 4; case 'q': case 'Q': return 8; case 'f': return (is_complex ? 8 : 4); case 'd': return (is_complex ? 16 : 8); case 'g': { PyErr_SetString(PyExc_ValueError, "Python does not define a standard format string size for long double ('g').."); return 0; } case 'O': case 'P': return sizeof(void*); default: __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) { switch (ch) { case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; case 'h': case 'H': return sizeof(short); case 'i': case 'I': return sizeof(int); case 'l': case 'L': return sizeof(long); #ifdef HAVE_LONG_LONG case 'q': case 'Q': return sizeof(PY_LONG_LONG); #endif case 'f': return sizeof(float) * (is_complex ? 2 : 1); case 'd': return sizeof(double) * (is_complex ? 2 : 1); case 'g': return sizeof(long double) * (is_complex ? 2 : 1); case 'O': case 'P': return sizeof(void*); default: { __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } } typedef struct { char c; short x; } __Pyx_st_short; typedef struct { char c; int x; } __Pyx_st_int; typedef struct { char c; long x; } __Pyx_st_long; typedef struct { char c; float x; } __Pyx_st_float; typedef struct { char c; double x; } __Pyx_st_double; typedef struct { char c; long double x; } __Pyx_st_longdouble; typedef struct { char c; void *x; } __Pyx_st_void_p; #ifdef HAVE_LONG_LONG typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong; #endif static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) { CYTHON_UNUSED_VAR(is_complex); switch (ch) { case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short); case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int); case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long); #ifdef HAVE_LONG_LONG case 'q': case 'Q': return sizeof(__Pyx_st_longlong) - sizeof(PY_LONG_LONG); #endif case 'f': return sizeof(__Pyx_st_float) - sizeof(float); case 'd': return sizeof(__Pyx_st_double) - sizeof(double); case 'g': return sizeof(__Pyx_st_longdouble) - sizeof(long double); case 'P': case 'O': return sizeof(__Pyx_st_void_p) - sizeof(void*); default: __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } /* These are for computing the padding at the end of the struct to align on the first member of the struct. This will probably the same as above, but we don't have any guarantees. */ typedef struct { short x; char c; } __Pyx_pad_short; typedef struct { int x; char c; } __Pyx_pad_int; typedef struct { long x; char c; } __Pyx_pad_long; typedef struct { float x; char c; } __Pyx_pad_float; typedef struct { double x; char c; } __Pyx_pad_double; typedef struct { long double x; char c; } __Pyx_pad_longdouble; typedef struct { void *x; char c; } __Pyx_pad_void_p; #ifdef HAVE_LONG_LONG typedef struct { PY_LONG_LONG x; char c; } __Pyx_pad_longlong; #endif static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, int is_complex) { CYTHON_UNUSED_VAR(is_complex); switch (ch) { case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; case 'h': case 'H': return sizeof(__Pyx_pad_short) - sizeof(short); case 'i': case 'I': return sizeof(__Pyx_pad_int) - sizeof(int); case 'l': case 'L': return sizeof(__Pyx_pad_long) - sizeof(long); #ifdef HAVE_LONG_LONG case 'q': case 'Q': return sizeof(__Pyx_pad_longlong) - sizeof(PY_LONG_LONG); #endif case 'f': return sizeof(__Pyx_pad_float) - sizeof(float); case 'd': return sizeof(__Pyx_pad_double) - sizeof(double); case 'g': return sizeof(__Pyx_pad_longdouble) - sizeof(long double); case 'P': case 'O': return sizeof(__Pyx_pad_void_p) - sizeof(void*); default: __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) { switch (ch) { case 'c': return 'H'; case 'b': case 'h': case 'i': case 'l': case 'q': case 's': case 'p': return 'I'; case '?': case 'B': case 'H': case 'I': case 'L': case 'Q': return 'U'; case 'f': case 'd': case 'g': return (is_complex ? 'C' : 'R'); case 'O': return 'O'; case 'P': return 'P'; default: { __Pyx_BufFmt_RaiseUnexpectedChar(ch); return 0; } } } static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) { if (ctx->head == NULL || ctx->head->field == &ctx->root) { const char* expected; const char* quote; if (ctx->head == NULL) { expected = "end"; quote = ""; } else { expected = ctx->head->field->type->name; quote = "'"; } PyErr_Format(PyExc_ValueError, "Buffer dtype mismatch, expected %s%s%s but got %s", quote, expected, quote, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex)); } else { __Pyx_StructField* field = ctx->head->field; __Pyx_StructField* parent = (ctx->head - 1)->field; PyErr_Format(PyExc_ValueError, "Buffer dtype mismatch, expected '%s' but got %s in '%s.%s'", field->type->name, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex), parent->type->name, field->name); } } static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) { char group; size_t size, offset, arraysize = 1; /* printf("processing... %s\n", ctx->head->field->type->name); */ if (ctx->enc_type == 0) return 0; /* Validate array size */ if (ctx->head->field->type->arraysize[0]) { int i, ndim = 0; /* handle strings ('s' and 'p') */ if (ctx->enc_type == 's' || ctx->enc_type == 'p') { ctx->is_valid_array = ctx->head->field->type->ndim == 1; ndim = 1; if (ctx->enc_count != ctx->head->field->type->arraysize[0]) { PyErr_Format(PyExc_ValueError, "Expected a dimension of size %zu, got %zu", ctx->head->field->type->arraysize[0], ctx->enc_count); return -1; } } if (!ctx->is_valid_array) { PyErr_Format(PyExc_ValueError, "Expected %d dimensions, got %d", ctx->head->field->type->ndim, ndim); return -1; } for (i = 0; i < ctx->head->field->type->ndim; i++) { arraysize *= ctx->head->field->type->arraysize[i]; } ctx->is_valid_array = 0; ctx->enc_count = 1; } group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex); do { __Pyx_StructField* field = ctx->head->field; __Pyx_TypeInfo* type = field->type; if (ctx->enc_packmode == '@' || ctx->enc_packmode == '^') { size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex); } else { size = __Pyx_BufFmt_TypeCharToStandardSize(ctx->enc_type, ctx->is_complex); } if (ctx->enc_packmode == '@') { size_t align_at = __Pyx_BufFmt_TypeCharToAlignment(ctx->enc_type, ctx->is_complex); size_t align_mod_offset; if (align_at == 0) return -1; align_mod_offset = ctx->fmt_offset % align_at; if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset; if (ctx->struct_alignment == 0) ctx->struct_alignment = __Pyx_BufFmt_TypeCharToPadding(ctx->enc_type, ctx->is_complex); } if (type->size != size || type->typegroup != group) { if (type->typegroup == 'C' && type->fields != NULL) { /* special case -- treat as struct rather than complex number */ size_t parent_offset = ctx->head->parent_offset + field->offset; ++ctx->head; ctx->head->field = type->fields; ctx->head->parent_offset = parent_offset; continue; } if ((type->typegroup == 'H' || group == 'H') && type->size == size) { /* special case -- chars don't care about sign */ } else { __Pyx_BufFmt_RaiseExpected(ctx); return -1; } } offset = ctx->head->parent_offset + field->offset; if (ctx->fmt_offset != offset) { PyErr_Format(PyExc_ValueError, "Buffer dtype mismatch; next field is at offset %" CYTHON_FORMAT_SSIZE_T "d but %" CYTHON_FORMAT_SSIZE_T "d expected", (Py_ssize_t)ctx->fmt_offset, (Py_ssize_t)offset); return -1; } ctx->fmt_offset += size; if (arraysize) ctx->fmt_offset += (arraysize - 1) * size; --ctx->enc_count; /* Consume from buffer string */ /* Done checking, move to next field, pushing or popping struct stack if needed */ while (1) { if (field == &ctx->root) { ctx->head = NULL; if (ctx->enc_count != 0) { __Pyx_BufFmt_RaiseExpected(ctx); return -1; } break; /* breaks both loops as ctx->enc_count == 0 */ } ctx->head->field = ++field; if (field->type == NULL) { --ctx->head; field = ctx->head->field; continue; } else if (field->type->typegroup == 'S') { size_t parent_offset = ctx->head->parent_offset + field->offset; if (field->type->fields->type == NULL) continue; /* empty struct */ field = field->type->fields; ++ctx->head; ctx->head->field = field; ctx->head->parent_offset = parent_offset; break; } else { break; } } } while (ctx->enc_count); ctx->enc_type = 0; ctx->is_complex = 0; return 0; } // Parse an array in the format string (e.g. (1,2,3)) // Return 0 on success, -1 on error static int __pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp) { const char *ts = *tsp; int i = 0, number, ndim; ++ts; if (ctx->new_count != 1) { PyErr_SetString(PyExc_ValueError, "Cannot handle repeated arrays in format string"); return -1; } /* Process the previous element */ if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return -1; // store ndim now, as field advanced by __Pyx_BufFmt_ProcessTypeChunk call ndim = ctx->head->field->type->ndim; /* Parse all numbers in the format string */ while (*ts && *ts != ')') { // ignore space characters (not using isspace() due to C/C++ problem on MacOS-X) switch (*ts) { case ' ': case '\f': case '\r': case '\n': case '\t': case '\v': continue; default: break; /* not a 'break' in the loop */ } number = __Pyx_BufFmt_ExpectNumber(&ts); if (number == -1) return -1; if (i < ndim && (size_t) number != ctx->head->field->type->arraysize[i]) { PyErr_Format(PyExc_ValueError, "Expected a dimension of size %zu, got %d", ctx->head->field->type->arraysize[i], number); return -1; } if (*ts != ',' && *ts != ')') { PyErr_Format(PyExc_ValueError, "Expected a comma in format string, got '%c'", *ts); return -1; } if (*ts == ',') ts++; i++; } if (i != ndim) { PyErr_Format(PyExc_ValueError, "Expected %d dimension(s), got %d", ctx->head->field->type->ndim, i); return -1; } if (!*ts) { PyErr_SetString(PyExc_ValueError, "Unexpected end of format string, expected ')'"); return -1; } ctx->is_valid_array = 1; ctx->new_count = 1; *tsp = ++ts; return 0; } static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) { int got_Z = 0; while (1) { /* puts(ts); */ switch(*ts) { case 0: if (ctx->enc_type != 0 && ctx->head == NULL) { __Pyx_BufFmt_RaiseExpected(ctx); return NULL; } if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; if (ctx->head != NULL) { __Pyx_BufFmt_RaiseExpected(ctx); return NULL; } return ts; case ' ': case '\r': case '\n': ++ts; break; case '<': if (!__Pyx_Is_Little_Endian()) { PyErr_SetString(PyExc_ValueError, "Little-endian buffer not supported on big-endian compiler"); return NULL; } ctx->new_packmode = '='; ++ts; break; case '>': case '!': if (__Pyx_Is_Little_Endian()) { PyErr_SetString(PyExc_ValueError, "Big-endian buffer not supported on little-endian compiler"); return NULL; } ctx->new_packmode = '='; ++ts; break; case '=': case '@': case '^': ctx->new_packmode = *ts++; break; case 'T': /* substruct */ { const char* ts_after_sub; size_t i, struct_count = ctx->new_count; size_t struct_alignment = ctx->struct_alignment; ctx->new_count = 1; ++ts; if (*ts != '{') { PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'"); return NULL; } if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; ctx->enc_type = 0; /* Erase processed last struct element */ ctx->enc_count = 0; ctx->struct_alignment = 0; ++ts; ts_after_sub = ts; for (i = 0; i != struct_count; ++i) { ts_after_sub = __Pyx_BufFmt_CheckString(ctx, ts); if (!ts_after_sub) return NULL; } ts = ts_after_sub; if (struct_alignment) ctx->struct_alignment = struct_alignment; } break; case '}': /* end of substruct; either repeat or move on */ { size_t alignment = ctx->struct_alignment; ++ts; if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; ctx->enc_type = 0; /* Erase processed last struct element */ if (alignment && ctx->fmt_offset % alignment) { /* Pad struct on size of the first member */ ctx->fmt_offset += alignment - (ctx->fmt_offset % alignment); } } return ts; case 'x': if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; ctx->fmt_offset += ctx->new_count; ctx->new_count = 1; ctx->enc_count = 0; ctx->enc_type = 0; ctx->enc_packmode = ctx->new_packmode; ++ts; break; case 'Z': got_Z = 1; ++ts; if (*ts != 'f' && *ts != 'd' && *ts != 'g') { __Pyx_BufFmt_RaiseUnexpectedChar('Z'); return NULL; } CYTHON_FALLTHROUGH; case '?': case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I': case 'l': case 'L': case 'q': case 'Q': case 'f': case 'd': case 'g': case 'O': case 'p': if ((ctx->enc_type == *ts) && (got_Z == ctx->is_complex) && (ctx->enc_packmode == ctx->new_packmode) && (!ctx->is_valid_array)) { /* Continue pooling same type */ ctx->enc_count += ctx->new_count; ctx->new_count = 1; got_Z = 0; ++ts; break; } CYTHON_FALLTHROUGH; case 's': /* 's' or new type (cannot be added to current pool) */ if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; ctx->enc_count = ctx->new_count; ctx->enc_packmode = ctx->new_packmode; ctx->enc_type = *ts; ctx->is_complex = got_Z; ++ts; ctx->new_count = 1; got_Z = 0; break; case ':': ++ts; while(*ts != ':') ++ts; ++ts; break; case '(': if (__pyx_buffmt_parse_array(ctx, &ts) < 0) return NULL; break; default: { int number = __Pyx_BufFmt_ExpectNumber(&ts); if (number == -1) return NULL; ctx->new_count = (size_t)number; } } } } /////////////// TypeInfoCompare.proto /////////////// static int __pyx_typeinfo_cmp(__Pyx_TypeInfo *a, __Pyx_TypeInfo *b); /////////////// TypeInfoCompare /////////////// //@requires: BufferFormatStructs // See if two dtypes are equal static int __pyx_typeinfo_cmp(__Pyx_TypeInfo *a, __Pyx_TypeInfo *b) { int i; if (!a || !b) return 0; if (a == b) return 1; if (a->size != b->size || a->typegroup != b->typegroup || a->is_unsigned != b->is_unsigned || a->ndim != b->ndim) { if (a->typegroup == 'H' || b->typegroup == 'H') { /* Special case for chars */ return a->size == b->size; } else { return 0; } } if (a->ndim) { /* Verify multidimensional C arrays */ for (i = 0; i < a->ndim; i++) if (a->arraysize[i] != b->arraysize[i]) return 0; } if (a->typegroup == 'S') { /* Check for packed struct */ if (a->flags != b->flags) return 0; /* compare all struct fields */ if (a->fields || b->fields) { /* Check if both have fields */ if (!(a->fields && b->fields)) return 0; /* compare */ for (i = 0; a->fields[i].type && b->fields[i].type; i++) { __Pyx_StructField *field_a = a->fields + i; __Pyx_StructField *field_b = b->fields + i; if (field_a->offset != field_b->offset || !__pyx_typeinfo_cmp(field_a->type, field_b->type)) return 0; } /* If all fields are processed, we have a match */ return !a->fields[i].type && !b->fields[i].type; } } return 1; } /////////////// TypeInfoToFormat.proto /////////////// struct __pyx_typeinfo_string { char string[3]; }; static struct __pyx_typeinfo_string __Pyx_TypeInfoToFormat(__Pyx_TypeInfo *type); /////////////// TypeInfoToFormat /////////////// //@requires: BufferFormatStructs // See also MemoryView.pyx:BufferFormatFromTypeInfo static struct __pyx_typeinfo_string __Pyx_TypeInfoToFormat(__Pyx_TypeInfo *type) { struct __pyx_typeinfo_string result = { {0} }; char *buf = (char *) result.string; size_t size = type->size; switch (type->typegroup) { case 'H': *buf = 'c'; break; case 'I': case 'U': if (size == 1) *buf = (type->is_unsigned) ? 'B' : 'b'; else if (size == 2) *buf = (type->is_unsigned) ? 'H' : 'h'; else if (size == 4) *buf = (type->is_unsigned) ? 'I' : 'i'; else if (size == 8) *buf = (type->is_unsigned) ? 'Q' : 'q'; break; case 'P': *buf = 'P'; break; case 'C': { __Pyx_TypeInfo complex_type = *type; complex_type.typegroup = 'R'; complex_type.size /= 2; *buf++ = 'Z'; *buf = __Pyx_TypeInfoToFormat(&complex_type).string[0]; break; } case 'R': if (size == 4) *buf = 'f'; else if (size == 8) *buf = 'd'; else *buf = 'g'; break; } return result; } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Utility/Builtins.c0000644000175100001770000004565500000000000020457 0ustar00runnerdocker00000000000000/* * Special implementations of built-in functions and methods. * * Optional optimisations for builtins are in Optimize.c. * * General object operations and protocols are in ObjectHandling.c. */ //////////////////// Globals.proto //////////////////// static PyObject* __Pyx_Globals(void); /*proto*/ //////////////////// Globals //////////////////// //@substitute: naming //@requires: ObjectHandling.c::GetAttr // This is a stub implementation until we have something more complete. // Currently, we only handle the most common case of a read-only dict // of Python names. Supporting cdef names in the module and write // access requires a rewrite as a dedicated class. static PyObject* __Pyx_Globals(void) { return __Pyx_NewRef($moddict_cname); } //////////////////// PyExecGlobals.proto //////////////////// static PyObject* __Pyx_PyExecGlobals(PyObject*); //////////////////// PyExecGlobals //////////////////// //@substitute: naming //@requires: PyExec static PyObject* __Pyx_PyExecGlobals(PyObject* code) { return __Pyx_PyExec2(code, $moddict_cname); } //////////////////// PyExec.proto //////////////////// static PyObject* __Pyx_PyExec3(PyObject*, PyObject*, PyObject*); static CYTHON_INLINE PyObject* __Pyx_PyExec2(PyObject*, PyObject*); //////////////////// PyExec //////////////////// //@substitute: naming static CYTHON_INLINE PyObject* __Pyx_PyExec2(PyObject* o, PyObject* globals) { return __Pyx_PyExec3(o, globals, NULL); } static PyObject* __Pyx_PyExec3(PyObject* o, PyObject* globals, PyObject* locals) { PyObject* result; PyObject* s = 0; char *code = 0; if (!globals || globals == Py_None) { globals = $moddict_cname; } else if (unlikely(!PyDict_Check(globals))) { __Pyx_TypeName globals_type_name = __Pyx_PyType_GetName(Py_TYPE(globals)); PyErr_Format(PyExc_TypeError, "exec() arg 2 must be a dict, not " __Pyx_FMT_TYPENAME, globals_type_name); __Pyx_DECREF_TypeName(globals_type_name); goto bad; } if (!locals || locals == Py_None) { locals = globals; } if (__Pyx_PyDict_GetItemStr(globals, PYIDENT("__builtins__")) == NULL) { if (unlikely(PyDict_SetItem(globals, PYIDENT("__builtins__"), PyEval_GetBuiltins()) < 0)) goto bad; } if (PyCode_Check(o)) { if (unlikely(__Pyx_PyCode_HasFreeVars((PyCodeObject *)o))) { PyErr_SetString(PyExc_TypeError, "code object passed to exec() may not contain free variables"); goto bad; } #if PY_VERSION_HEX < 0x030200B1 || (CYTHON_COMPILING_IN_PYPY && PYPY_VERSION_NUM < 0x07030400) result = PyEval_EvalCode((PyCodeObject *)o, globals, locals); #else result = PyEval_EvalCode(o, globals, locals); #endif } else { PyCompilerFlags cf; cf.cf_flags = 0; #if PY_VERSION_HEX >= 0x030800A3 cf.cf_feature_version = PY_MINOR_VERSION; #endif if (PyUnicode_Check(o)) { cf.cf_flags = PyCF_SOURCE_IS_UTF8; s = PyUnicode_AsUTF8String(o); if (unlikely(!s)) goto bad; o = s; #if PY_MAJOR_VERSION >= 3 } else if (unlikely(!PyBytes_Check(o))) { #else } else if (unlikely(!PyString_Check(o))) { #endif __Pyx_TypeName o_type_name = __Pyx_PyType_GetName(Py_TYPE(o)); PyErr_Format(PyExc_TypeError, "exec: arg 1 must be string, bytes or code object, got " __Pyx_FMT_TYPENAME, o_type_name); __Pyx_DECREF_TypeName(o_type_name); goto bad; } #if PY_MAJOR_VERSION >= 3 code = PyBytes_AS_STRING(o); #else code = PyString_AS_STRING(o); #endif if (PyEval_MergeCompilerFlags(&cf)) { result = PyRun_StringFlags(code, Py_file_input, globals, locals, &cf); } else { result = PyRun_String(code, Py_file_input, globals, locals); } Py_XDECREF(s); } return result; bad: Py_XDECREF(s); return 0; } //////////////////// GetAttr3.proto //////////////////// static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); /*proto*/ //////////////////// GetAttr3 //////////////////// //@requires: ObjectHandling.c::PyObjectGetAttrStr //@requires: Exceptions.c::PyThreadStateGet //@requires: Exceptions.c::PyErrFetchRestore //@requires: Exceptions.c::PyErrExceptionMatches #if __PYX_LIMITED_VERSION_HEX < 0x030d00A1 static PyObject *__Pyx_GetAttr3Default(PyObject *d) { __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign if (unlikely(!__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) return NULL; __Pyx_PyErr_Clear(); Py_INCREF(d); return d; } #endif static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) { PyObject *r; #if __PYX_LIMITED_VERSION_HEX >= 0x030d00A1 int res = PyObject_GetOptionalAttr(o, n, &r); // On failure (res == -1), r is set to NULL. return (res != 0) ? r : __Pyx_NewRef(d); #else #if CYTHON_USE_TYPE_SLOTS if (likely(PyString_Check(n))) { r = __Pyx_PyObject_GetAttrStrNoError(o, n); if (unlikely(!r) && likely(!PyErr_Occurred())) { r = __Pyx_NewRef(d); } return r; } #endif r = PyObject_GetAttr(o, n); return (likely(r)) ? r : __Pyx_GetAttr3Default(d); #endif } //////////////////// HasAttr.proto //////////////////// #if __PYX_LIMITED_VERSION_HEX >= 0x030d00A1 #define __Pyx_HasAttr(o, n) PyObject_HasAttrWithError(o, n) #else static CYTHON_INLINE int __Pyx_HasAttr(PyObject *, PyObject *); /*proto*/ #endif //////////////////// HasAttr //////////////////// //@requires: ObjectHandling.c::GetAttr #if __PYX_LIMITED_VERSION_HEX < 0x030d00A1 static CYTHON_INLINE int __Pyx_HasAttr(PyObject *o, PyObject *n) { PyObject *r; if (unlikely(!__Pyx_PyBaseString_Check(n))) { PyErr_SetString(PyExc_TypeError, "hasattr(): attribute name must be string"); return -1; } r = __Pyx_GetAttr(o, n); if (!r) { PyErr_Clear(); return 0; } else { Py_DECREF(r); return 1; } } #endif //////////////////// Intern.proto //////////////////// static PyObject* __Pyx_Intern(PyObject* s); /* proto */ //////////////////// Intern //////////////////// //@requires: ObjectHandling.c::RaiseUnexpectedTypeError static PyObject* __Pyx_Intern(PyObject* s) { if (unlikely(!PyString_CheckExact(s))) { __Pyx_RaiseUnexpectedTypeError("str", s); return NULL; } Py_INCREF(s); #if PY_MAJOR_VERSION >= 3 PyUnicode_InternInPlace(&s); #else PyString_InternInPlace(&s); #endif return s; } //////////////////// abs_longlong.proto //////////////////// static CYTHON_INLINE PY_LONG_LONG __Pyx_abs_longlong(PY_LONG_LONG x) { #if defined (__cplusplus) && __cplusplus >= 201103L return std::abs(x); #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L return llabs(x); #elif defined (_MSC_VER) // abs() is defined for long, but 64-bits type on MSVC is long long. // Use MS-specific _abs64() instead, which returns the original (negative) value for abs(-MAX-1) return _abs64(x); #elif defined (__GNUC__) // gcc or clang on 64 bit windows. return __builtin_llabs(x); #else if (sizeof(PY_LONG_LONG) <= sizeof(Py_ssize_t)) return __Pyx_sst_abs(x); return (x<0) ? -x : x; #endif } //////////////////// py_abs.proto //////////////////// #if CYTHON_USE_PYLONG_INTERNALS static PyObject *__Pyx_PyLong_AbsNeg(PyObject *num);/*proto*/ #define __Pyx_PyNumber_Absolute(x) \ ((likely(PyLong_CheckExact(x))) ? \ (likely(__Pyx_PyLong_IsNonNeg(x)) ? (Py_INCREF(x), (x)) : __Pyx_PyLong_AbsNeg(x)) : \ PyNumber_Absolute(x)) #else #define __Pyx_PyNumber_Absolute(x) PyNumber_Absolute(x) #endif //////////////////// py_abs //////////////////// #if CYTHON_USE_PYLONG_INTERNALS static PyObject *__Pyx_PyLong_AbsNeg(PyObject *n) { #if PY_VERSION_HEX >= 0x030C00A7 if (likely(__Pyx_PyLong_IsCompact(n))) { return PyLong_FromSize_t(__Pyx_PyLong_CompactValueUnsigned(n)); } #else if (likely(Py_SIZE(n) == -1)) { // digits are unsigned return PyLong_FromUnsignedLong(__Pyx_PyLong_Digits(n)[0]); } #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030d0000 { PyObject *copy = _PyLong_Copy((PyLongObject*)n); if (likely(copy)) { #if PY_VERSION_HEX >= 0x030C00A7 // clear the sign bits to set the sign from SIGN_NEGATIVE (2) to positive (0) ((PyLongObject*)copy)->long_value.lv_tag = ((PyLongObject*)copy)->long_value.lv_tag & ~_PyLong_SIGN_MASK; #else // negate the size to swap the sign __Pyx_SET_SIZE(copy, -Py_SIZE(copy)); #endif } return copy; } #else return PyNumber_Negative(n); #endif } #endif //////////////////// pow2.proto //////////////////// #define __Pyx_PyNumber_Power2(a, b) PyNumber_Power(a, b, Py_None) //////////////////// int_pyucs4.proto //////////////////// static CYTHON_INLINE int __Pyx_int_from_UCS4(Py_UCS4 uchar); //////////////////// int_pyucs4 //////////////////// static int __Pyx_int_from_UCS4(Py_UCS4 uchar) { int digit = Py_UNICODE_TODIGIT(uchar); if (unlikely(digit < 0)) { PyErr_Format(PyExc_ValueError, "invalid literal for int() with base 10: '%c'", (int) uchar); return -1; } return digit; } //////////////////// float_pyucs4.proto //////////////////// static CYTHON_INLINE double __Pyx_double_from_UCS4(Py_UCS4 uchar); //////////////////// float_pyucs4 //////////////////// static double __Pyx_double_from_UCS4(Py_UCS4 uchar) { double digit = Py_UNICODE_TONUMERIC(uchar); if (unlikely(digit < 0.0)) { PyErr_Format(PyExc_ValueError, "could not convert string to float: '%c'", (int) uchar); return -1.0; } return digit; } //////////////////// object_ord.proto //////////////////// //@requires: TypeConversion.c::UnicodeAsUCS4 #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyObject_Ord(c) \ (likely(PyUnicode_Check(c)) ? (long)__Pyx_PyUnicode_AsPy_UCS4(c) : __Pyx__PyObject_Ord(c)) #else #define __Pyx_PyObject_Ord(c) __Pyx__PyObject_Ord(c) #endif static long __Pyx__PyObject_Ord(PyObject* c); /*proto*/ //////////////////// object_ord //////////////////// static long __Pyx__PyObject_Ord(PyObject* c) { Py_ssize_t size; if (PyBytes_Check(c)) { size = PyBytes_GET_SIZE(c); if (likely(size == 1)) { return (unsigned char) PyBytes_AS_STRING(c)[0]; } #if PY_MAJOR_VERSION < 3 } else if (PyUnicode_Check(c)) { return (long)__Pyx_PyUnicode_AsPy_UCS4(c); #endif #if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) } else if (PyByteArray_Check(c)) { size = PyByteArray_GET_SIZE(c); if (likely(size == 1)) { return (unsigned char) PyByteArray_AS_STRING(c)[0]; } #endif } else { // FIXME: support character buffers - but CPython doesn't support them either __Pyx_TypeName c_type_name = __Pyx_PyType_GetName(Py_TYPE(c)); PyErr_Format(PyExc_TypeError, "ord() expected string of length 1, but " __Pyx_FMT_TYPENAME " found", c_type_name); __Pyx_DECREF_TypeName(c_type_name); return (long)(Py_UCS4)-1; } PyErr_Format(PyExc_TypeError, "ord() expected a character, but string of length %zd found", size); return (long)(Py_UCS4)-1; } //////////////////// py_dict_keys.proto //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_Keys(PyObject* d); /*proto*/ //////////////////// py_dict_keys //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_Keys(PyObject* d) { if (PY_MAJOR_VERSION >= 3) return CALL_UNBOUND_METHOD(PyDict_Type, "keys", d); else return PyDict_Keys(d); } //////////////////// py_dict_values.proto //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_Values(PyObject* d); /*proto*/ //////////////////// py_dict_values //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_Values(PyObject* d) { if (PY_MAJOR_VERSION >= 3) return CALL_UNBOUND_METHOD(PyDict_Type, "values", d); else return PyDict_Values(d); } //////////////////// py_dict_items.proto //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_Items(PyObject* d); /*proto*/ //////////////////// py_dict_items //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_Items(PyObject* d) { if (PY_MAJOR_VERSION >= 3) return CALL_UNBOUND_METHOD(PyDict_Type, "items", d); else return PyDict_Items(d); } //////////////////// py_dict_iterkeys.proto //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_IterKeys(PyObject* d); /*proto*/ //////////////////// py_dict_iterkeys //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_IterKeys(PyObject* d) { if (PY_MAJOR_VERSION >= 3) return CALL_UNBOUND_METHOD(PyDict_Type, "keys", d); else return CALL_UNBOUND_METHOD(PyDict_Type, "iterkeys", d); } //////////////////// py_dict_itervalues.proto //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_IterValues(PyObject* d); /*proto*/ //////////////////// py_dict_itervalues //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_IterValues(PyObject* d) { if (PY_MAJOR_VERSION >= 3) return CALL_UNBOUND_METHOD(PyDict_Type, "values", d); else return CALL_UNBOUND_METHOD(PyDict_Type, "itervalues", d); } //////////////////// py_dict_iteritems.proto //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_IterItems(PyObject* d); /*proto*/ //////////////////// py_dict_iteritems //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_IterItems(PyObject* d) { if (PY_MAJOR_VERSION >= 3) return CALL_UNBOUND_METHOD(PyDict_Type, "items", d); else return CALL_UNBOUND_METHOD(PyDict_Type, "iteritems", d); } //////////////////// py_dict_viewkeys.proto //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewKeys(PyObject* d); /*proto*/ //////////////////// py_dict_viewkeys //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewKeys(PyObject* d) { if (PY_MAJOR_VERSION >= 3) return CALL_UNBOUND_METHOD(PyDict_Type, "keys", d); else return CALL_UNBOUND_METHOD(PyDict_Type, "viewkeys", d); } //////////////////// py_dict_viewvalues.proto //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewValues(PyObject* d); /*proto*/ //////////////////// py_dict_viewvalues //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewValues(PyObject* d) { if (PY_MAJOR_VERSION >= 3) return CALL_UNBOUND_METHOD(PyDict_Type, "values", d); else return CALL_UNBOUND_METHOD(PyDict_Type, "viewvalues", d); } //////////////////// py_dict_viewitems.proto //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewItems(PyObject* d); /*proto*/ //////////////////// py_dict_viewitems //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewItems(PyObject* d) { if (PY_MAJOR_VERSION >= 3) return CALL_UNBOUND_METHOD(PyDict_Type, "items", d); else return CALL_UNBOUND_METHOD(PyDict_Type, "viewitems", d); } //////////////////// pyfrozenset_new.proto //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyFrozenSet_New(PyObject* it); //////////////////// pyfrozenset_new //////////////////// //@substitute: naming static CYTHON_INLINE PyObject* __Pyx_PyFrozenSet_New(PyObject* it) { if (it) { PyObject* result; #if CYTHON_COMPILING_IN_PYPY // PyPy currently lacks PyFrozenSet_CheckExact() and PyFrozenSet_New() PyObject* args; args = PyTuple_Pack(1, it); if (unlikely(!args)) return NULL; result = PyObject_Call((PyObject*)&PyFrozenSet_Type, args, NULL); Py_DECREF(args); return result; #else if (PyFrozenSet_CheckExact(it)) { Py_INCREF(it); return it; } result = PyFrozenSet_New(it); if (unlikely(!result)) return NULL; if ((PY_VERSION_HEX >= 0x031000A1) || likely(PySet_GET_SIZE(result))) return result; // empty frozenset is a singleton (on Python <3.10) // seems wasteful, but CPython does the same Py_DECREF(result); #endif } #if CYTHON_USE_TYPE_SLOTS return PyFrozenSet_Type.tp_new(&PyFrozenSet_Type, $empty_tuple, NULL); #else return PyObject_Call((PyObject*)&PyFrozenSet_Type, $empty_tuple, NULL); #endif } //////////////////// PySet_Update.proto //////////////////// static CYTHON_INLINE int __Pyx_PySet_Update(PyObject* set, PyObject* it); /*proto*/ //////////////////// PySet_Update //////////////////// static CYTHON_INLINE int __Pyx_PySet_Update(PyObject* set, PyObject* it) { PyObject *retval; #if CYTHON_USE_TYPE_SLOTS && !CYTHON_COMPILING_IN_PYPY if (PyAnySet_Check(it)) { if (PySet_GET_SIZE(it) == 0) return 0; // fast and safe case: CPython will update our result set and return it retval = PySet_Type.tp_as_number->nb_inplace_or(set, it); if (likely(retval == set)) { Py_DECREF(retval); return 0; } if (unlikely(!retval)) return -1; // unusual result, fall through to set.update() call below Py_DECREF(retval); } #endif retval = CALL_UNBOUND_METHOD(PySet_Type, "update", set, it); if (unlikely(!retval)) return -1; Py_DECREF(retval); return 0; } ///////////////// memoryview_get_from_buffer.proto //////////////////// // buffer is in limited api from Py3.11 #if !CYTHON_COMPILING_IN_LIMITED_API || CYTHON_LIMITED_API >= 0x030b0000 #define __Pyx_PyMemoryView_Get_{{name}}(o) PyMemoryView_GET_BUFFER(o)->{{name}} #else {{py: out_types = dict( ndim='int', readonly='int', len='Py_ssize_t', itemsize='Py_ssize_t') }} // can't get format like this unfortunately. It's unicode via getattr {{py: out_type = out_types[name]}} static {{out_type}} __Pyx_PyMemoryView_Get_{{name}}(PyObject *obj); /* proto */ #endif ////////////// memoryview_get_from_buffer ///////////////////////// #if !CYTHON_COMPILING_IN_LIMITED_API || CYTHON_LIMITED_API >= 0x030b0000 #else {{py: out_types = dict( ndim='int', readonly='int', len='Py_ssize_t', itemsize='Py_ssize_t') }} {{py: out_type = out_types[name]}} static {{out_type}} __Pyx_PyMemoryView_Get_{{name}}(PyObject *obj) { {{out_type}} result; PyObject *attr = PyObject_GetAttr(obj, PYIDENT("{{name}}")); if (!attr) { goto bad; } {{if out_type == 'int'}} // I'm not worrying about overflow here because // ultimately it comes from a C struct that's an int result = PyLong_AsLong(attr); {{elif out_type == 'Py_ssize_t'}} result = PyLong_AsSsize_t(attr); {{endif}} Py_DECREF(attr); return result; bad: Py_XDECREF(attr); return -1; } #endif ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Utility/CConvert.pyx0000644000175100001770000001050300000000000020767 0ustar00runnerdocker00000000000000#################### FromPyStructUtility #################### cdef extern from *: ctypedef struct PyTypeObject: char* tp_name PyTypeObject *Py_TYPE(obj) bint PyMapping_Check(obj) object PyErr_Format(exc, const char *format, ...) int __Pyx_RaiseUnexpectedTypeError(const char *expected, object obj) except 0 @cname("{{funcname}}") cdef {{struct_type}} {{funcname}}(obj) except *: cdef {{struct_type}} result if not PyMapping_Check(obj): __Pyx_RaiseUnexpectedTypeError(b"a mapping", obj) {{for member in var_entries:}} try: value = obj['{{member.name}}'] except KeyError: raise ValueError("No value specified for struct attribute '{{member.name}}'") result.{{member.name}} = value {{endfor}} return result #################### FromPyUnionUtility #################### cdef extern from *: ctypedef struct PyTypeObject: char* tp_name PyTypeObject *Py_TYPE(obj) bint PyMapping_Check(obj) object PyErr_Format(exc, const char *format, ...) int __Pyx_RaiseUnexpectedTypeError(const char *expected, object obj) except 0 @cname("{{funcname}}") cdef {{struct_type}} {{funcname}}(obj) except *: cdef {{struct_type}} result cdef Py_ssize_t length if not PyMapping_Check(obj): __Pyx_RaiseUnexpectedTypeError(b"a mapping", obj) last_found = None length = len(obj) if length: {{for member in var_entries:}} if '{{member.name}}' in obj: if last_found is not None: raise ValueError("More than one union attribute passed: '%s' and '%s'" % (last_found, '{{member.name}}')) last_found = '{{member.name}}' result.{{member.cname}} = obj['{{member.name}}'] length -= 1 if not length: return result {{endfor}} if last_found is None: raise ValueError("No value specified for any of the union attributes (%s)" % '{{", ".join(member.name for member in var_entries)}}') return result #################### cfunc.to_py #################### @cname("{{cname}}") cdef object {{cname}}({{return_type.ctype}} (*f)({{ ', '.join(arg.type_cname for arg in args) }}) {{except_clause}}): def wrap({{ ', '.join('{arg.ctype} {arg.name}'.format(arg=arg) for arg in args) }}): """wrap({{', '.join(('{arg.name}: {arg.type_displayname}'.format(arg=arg) if arg.type_displayname else arg.name) for arg in args)}}){{if return_type.type_displayname}} -> {{return_type.type_displayname}}{{endif}}""" {{'' if return_type.type.is_void else 'return '}}f({{ ', '.join(arg.name for arg in args) }}) return wrap #################### carray.from_py #################### cdef extern from *: object PyErr_Format(exc, const char *format, ...) @cname("{{cname}}") cdef int {{cname}}(object o, {{base_type}} *v, Py_ssize_t length) except -1: cdef Py_ssize_t i = length try: i = len(o) except (TypeError, OverflowError): pass if i == length: for i, item in enumerate(o): if i >= length: break v[i] = item else: i += 1 # convert index to length if i == length: return 0 PyErr_Format( IndexError, ("too many values found during array assignment, expected %zd" if i >= length else "not enough values found during array assignment, expected %zd, got %zd"), length, i) #################### carray.to_py #################### cdef extern from *: void Py_INCREF(object o) tuple PyTuple_New(Py_ssize_t size) list PyList_New(Py_ssize_t size) void PyTuple_SET_ITEM(object p, Py_ssize_t pos, object o) void PyList_SET_ITEM(object p, Py_ssize_t pos, object o) @cname("{{cname}}") cdef inline list {{cname}}({{base_type}} *v, Py_ssize_t length): cdef size_t i cdef object value l = PyList_New(length) for i in range(length): value = v[i] Py_INCREF(value) PyList_SET_ITEM(l, i, value) return l @cname("{{to_tuple_cname}}") cdef inline tuple {{to_tuple_cname}}({{base_type}} *v, Py_ssize_t length): cdef size_t i cdef object value t = PyTuple_New(length) for i in range(length): value = v[i] Py_INCREF(value) PyTuple_SET_ITEM(t, i, value) return t ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Utility/CMath.c0000644000175100001770000000500600000000000017644 0ustar00runnerdocker00000000000000 /////////////// CDivisionWarning.proto /////////////// static int __Pyx_cdivision_warning(const char *, int); /* proto */ /////////////// CDivisionWarning /////////////// static int __Pyx_cdivision_warning(const char *filename, int lineno) { #if CYTHON_COMPILING_IN_PYPY // avoid compiler warnings filename++; lineno++; return PyErr_Warn(PyExc_RuntimeWarning, "division with oppositely signed operands, C and Python semantics differ"); #else return PyErr_WarnExplicit(PyExc_RuntimeWarning, "division with oppositely signed operands, C and Python semantics differ", filename, lineno, __Pyx_MODULE_NAME, NULL); #endif } /////////////// DivInt.proto /////////////// static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */ /////////////// DivInt /////////////// static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) { %(type)s q = a / b; %(type)s r = a - q*b; q -= ((r != 0) & ((r ^ b) < 0)); return q; } /////////////// ModInt.proto /////////////// static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */ /////////////// ModInt /////////////// static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) { %(type)s r = a %% b; r += ((r != 0) & ((r ^ b) < 0)) * b; return r; } /////////////// ModFloat.proto /////////////// static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */ /////////////// ModFloat /////////////// static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) { %(type)s r = fmod%(math_h_modifier)s(a, b); r += ((r != 0) & ((r < 0) ^ (b < 0))) * b; return r; } /////////////// IntPow.proto /////////////// static CYTHON_INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */ /////////////// IntPow /////////////// static CYTHON_INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) { %(type)s t = b; switch (e) { case 3: t *= b; CYTHON_FALLTHROUGH; case 2: t *= b; CYTHON_FALLTHROUGH; case 1: return t; case 0: return 1; } #if %(signed)s if (unlikely(e<0)) return 0; #endif t = 1; while (likely(e)) { t *= (b * (e&1)) | ((~e)&1); /* 1 or b */ b *= b; e >>= 1; } return t; } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Utility/CommonStructures.c0000644000175100001770000001112200000000000022200 0ustar00runnerdocker00000000000000/////////////// FetchSharedCythonModule.proto /////// static PyObject *__Pyx_FetchSharedCythonABIModule(void); /////////////// FetchSharedCythonModule //////////// static PyObject *__Pyx_FetchSharedCythonABIModule(void) { return __Pyx_PyImport_AddModuleRef((char*) __PYX_ABI_MODULE_NAME); } /////////////// FetchCommonType.proto /////////////// #if !CYTHON_USE_TYPE_SPECS static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type); #else static PyTypeObject* __Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases); #endif /////////////// FetchCommonType /////////////// //@requires:ExtensionTypes.c::FixUpExtensionType //@requires: FetchSharedCythonModule //@requires:StringTools.c::IncludeStringH static int __Pyx_VerifyCachedType(PyObject *cached_type, const char *name, Py_ssize_t basicsize, Py_ssize_t expected_basicsize) { if (!PyType_Check(cached_type)) { PyErr_Format(PyExc_TypeError, "Shared Cython type %.200s is not a type object", name); return -1; } if (basicsize != expected_basicsize) { PyErr_Format(PyExc_TypeError, "Shared Cython type %.200s has the wrong size, try recompiling", name); return -1; } return 0; } #if !CYTHON_USE_TYPE_SPECS static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) { PyObject* abi_module; const char* object_name; PyTypeObject *cached_type = NULL; abi_module = __Pyx_FetchSharedCythonABIModule(); if (!abi_module) return NULL; // get the final part of the object name (after the last dot) object_name = strrchr(type->tp_name, '.'); object_name = object_name ? object_name+1 : type->tp_name; cached_type = (PyTypeObject*) PyObject_GetAttrString(abi_module, object_name); if (cached_type) { if (__Pyx_VerifyCachedType( (PyObject *)cached_type, object_name, cached_type->tp_basicsize, type->tp_basicsize) < 0) { goto bad; } goto done; } if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad; PyErr_Clear(); if (PyType_Ready(type) < 0) goto bad; if (PyObject_SetAttrString(abi_module, object_name, (PyObject *)type) < 0) goto bad; Py_INCREF(type); cached_type = type; done: Py_DECREF(abi_module); // NOTE: always returns owned reference, or NULL on error return cached_type; bad: Py_XDECREF(cached_type); cached_type = NULL; goto done; } #else static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) { PyObject *abi_module, *cached_type = NULL; // get the final part of the object name (after the last dot) const char* object_name = strrchr(spec->name, '.'); object_name = object_name ? object_name+1 : spec->name; abi_module = __Pyx_FetchSharedCythonABIModule(); if (!abi_module) return NULL; cached_type = PyObject_GetAttrString(abi_module, object_name); if (cached_type) { Py_ssize_t basicsize; #if CYTHON_COMPILING_IN_LIMITED_API PyObject *py_basicsize; py_basicsize = PyObject_GetAttrString(cached_type, "__basicsize__"); if (unlikely(!py_basicsize)) goto bad; basicsize = PyLong_AsSsize_t(py_basicsize); Py_DECREF(py_basicsize); py_basicsize = 0; if (unlikely(basicsize == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad; #else basicsize = likely(PyType_Check(cached_type)) ? ((PyTypeObject*) cached_type)->tp_basicsize : -1; #endif if (__Pyx_VerifyCachedType( cached_type, object_name, basicsize, spec->basicsize) < 0) { goto bad; } goto done; } if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad; PyErr_Clear(); // We pass the ABI module reference to avoid keeping the user module alive by foreign type usages. CYTHON_UNUSED_VAR(module); cached_type = __Pyx_PyType_FromModuleAndSpec(abi_module, spec, bases); if (unlikely(!cached_type)) goto bad; if (unlikely(__Pyx_fix_up_extension_type_from_spec(spec, (PyTypeObject *) cached_type) < 0)) goto bad; if (PyObject_SetAttrString(abi_module, object_name, cached_type) < 0) goto bad; done: Py_DECREF(abi_module); // NOTE: always returns owned reference, or NULL on error assert(cached_type == NULL || PyType_Check(cached_type)); return (PyTypeObject *) cached_type; bad: Py_XDECREF(cached_type); cached_type = NULL; goto done; } #endif ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Utility/Complex.c0000644000175100001770000003245100000000000020263 0ustar00runnerdocker00000000000000/////////////// Header.proto /////////////// //@proto_block: h_code #if !defined(CYTHON_CCOMPLEX) #if defined(__cplusplus) #define CYTHON_CCOMPLEX 1 #elif (defined(_Complex_I) && !defined(_MSC_VER)) || ((defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_COMPLEX__) && !defined(_MSC_VER)) // should exist since C99, but only C11 defines a test to detect it. // MSVC defines "_Complex_I" but not "_Complex". See https://github.com/cython/cython/issues/5512 #define CYTHON_CCOMPLEX 1 #else #define CYTHON_CCOMPLEX 0 #endif #endif #if CYTHON_CCOMPLEX #ifdef __cplusplus #include #else #include #endif #endif #if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__) #undef _Complex_I #define _Complex_I 1.0fj #endif /////////////// RealImag.proto /////////////// #if CYTHON_CCOMPLEX #ifdef __cplusplus #define __Pyx_CREAL(z) ((z).real()) #define __Pyx_CIMAG(z) ((z).imag()) #else #define __Pyx_CREAL(z) (__real__(z)) #define __Pyx_CIMAG(z) (__imag__(z)) #endif #else #define __Pyx_CREAL(z) ((z).real) #define __Pyx_CIMAG(z) ((z).imag) #endif #if defined(__cplusplus) && CYTHON_CCOMPLEX \ && (defined(_WIN32) || defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 5 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 )) || __cplusplus >= 201103) #define __Pyx_SET_CREAL(z,x) ((z).real(x)) #define __Pyx_SET_CIMAG(z,y) ((z).imag(y)) #else #define __Pyx_SET_CREAL(z,x) __Pyx_CREAL(z) = (x) #define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y) #endif /////////////// RealImag_Cy.proto /////////////// // alternative version of RealImag.proto for the case where // we definitely want to force it to use the Cython utility // code version of complex. // Because integer complex types simply aren't covered by // the C or C++ standards // (although practically will probably work in C++). #define __Pyx_CREAL_Cy(z) ((z).real) #define __Pyx_CIMAG_Cy(z) ((z).imag) #define __Pyx_SET_CREAL_Cy(z,x) __Pyx_CREAL_Cy(z) = (x) #define __Pyx_SET_CIMAG_Cy(z,y) __Pyx_CIMAG_cy(z) = (y) /////////////// RealImag_CyTypedef.proto ////////// //@requires: RealImag //@requires: RealImag_Cy #if __cplusplus // C++ is fine with complexes based on typedefs because the template sees through them #define __Pyx_CREAL_CyTypedef(z) __Pyx_CREAL(z) #define __Pyx_CIMAG_CyTypedef(z) __Pyx_CIMAG(z) #define __Pyx_SET_CREAL_CyTypedef(z,x) __Pyx_SET_CREAL(z) #define __Pyx_SET_CIMAG_CyTypedef(z,x) __Pyx_SET_CIMAG(z) #else // C isn't #define __Pyx_CREAL_CyTypedef(z) __Pyx_CREAL_Cy(z) #define __Pyx_CIMAG_CyTypedef(z) __Pyx_CIMAG_Cy(z) #define __Pyx_SET_CREAL_CyTypedef(z,x) __Pyx_SET_CREAL_Cy(z) #define __Pyx_SET_CIMAG_CyTypedef(z,x) __Pyx_SET_CIMAG_Cy(z) #endif /////////////// Declarations.proto /////////////// //@proto_block: complex_type_declarations #if CYTHON_CCOMPLEX && ({{is_float}}) && (!{{is_extern_float_typedef}} || __cplusplus) #ifdef __cplusplus typedef ::std::complex< {{real_type}} > {{type_name}}; #else typedef {{real_type}} _Complex {{type_name}}; #endif #else typedef struct { {{real_type}} real, imag; } {{type_name}}; #endif static CYTHON_INLINE {{type}} {{type_name}}_from_parts({{real_type}}, {{real_type}}); /////////////// Declarations /////////////// #if CYTHON_CCOMPLEX && ({{is_float}}) && (!{{is_extern_float_typedef}} || __cplusplus) #ifdef __cplusplus static CYTHON_INLINE {{type}} {{type_name}}_from_parts({{real_type}} x, {{real_type}} y) { return ::std::complex< {{real_type}} >(x, y); } #else static CYTHON_INLINE {{type}} {{type_name}}_from_parts({{real_type}} x, {{real_type}} y) { return x + y*({{type}})_Complex_I; } #endif #else static CYTHON_INLINE {{type}} {{type_name}}_from_parts({{real_type}} x, {{real_type}} y) { {{type}} z; z.real = x; z.imag = y; return z; } #endif /////////////// ToPy.proto /////////////// {{py: func_suffix = "_CyTypedef" if is_extern_float_typedef else ("" if is_float else "_Cy")}} #define __pyx_PyComplex_FromComplex{{func_suffix}}(z) \ PyComplex_FromDoubles((double)__Pyx_CREAL{{func_suffix}}(z), \ (double)__Pyx_CIMAG{{func_suffix}}(z)) /////////////// FromPy.proto /////////////// static {{type}} __Pyx_PyComplex_As_{{type_name}}(PyObject*); /////////////// FromPy /////////////// static {{type}} __Pyx_PyComplex_As_{{type_name}}(PyObject* o) { Py_complex cval; #if !CYTHON_COMPILING_IN_PYPY if (PyComplex_CheckExact(o)) cval = ((PyComplexObject *)o)->cval; else #endif cval = PyComplex_AsCComplex(o); return {{type_name}}_from_parts( ({{real_type}})cval.real, ({{real_type}})cval.imag); } /////////////// Arithmetic.proto /////////////// #if CYTHON_CCOMPLEX && ({{is_float}}) && (!{{is_extern_float_typedef}} || __cplusplus) #define __Pyx_c_eq{{func_suffix}}(a, b) ((a)==(b)) #define __Pyx_c_sum{{func_suffix}}(a, b) ((a)+(b)) #define __Pyx_c_diff{{func_suffix}}(a, b) ((a)-(b)) #define __Pyx_c_prod{{func_suffix}}(a, b) ((a)*(b)) #define __Pyx_c_quot{{func_suffix}}(a, b) ((a)/(b)) #define __Pyx_c_neg{{func_suffix}}(a) (-(a)) #ifdef __cplusplus #define __Pyx_c_is_zero{{func_suffix}}(z) ((z)==({{real_type}})0) #define __Pyx_c_conj{{func_suffix}}(z) (::std::conj(z)) #if {{is_float}} #define __Pyx_c_abs{{func_suffix}}(z) (::std::abs(z)) #define __Pyx_c_pow{{func_suffix}}(a, b) (::std::pow(a, b)) #endif #else #define __Pyx_c_is_zero{{func_suffix}}(z) ((z)==0) #define __Pyx_c_conj{{func_suffix}}(z) (conj{{m}}(z)) #if {{is_float}} #define __Pyx_c_abs{{func_suffix}}(z) (cabs{{m}}(z)) #define __Pyx_c_pow{{func_suffix}}(a, b) (cpow{{m}}(a, b)) #endif #endif #else static CYTHON_INLINE int __Pyx_c_eq{{func_suffix}}({{type}}, {{type}}); static CYTHON_INLINE {{type}} __Pyx_c_sum{{func_suffix}}({{type}}, {{type}}); static CYTHON_INLINE {{type}} __Pyx_c_diff{{func_suffix}}({{type}}, {{type}}); static CYTHON_INLINE {{type}} __Pyx_c_prod{{func_suffix}}({{type}}, {{type}}); static CYTHON_INLINE {{type}} __Pyx_c_quot{{func_suffix}}({{type}}, {{type}}); static CYTHON_INLINE {{type}} __Pyx_c_neg{{func_suffix}}({{type}}); static CYTHON_INLINE int __Pyx_c_is_zero{{func_suffix}}({{type}}); static CYTHON_INLINE {{type}} __Pyx_c_conj{{func_suffix}}({{type}}); #if {{is_float}} static CYTHON_INLINE {{real_type}} __Pyx_c_abs{{func_suffix}}({{type}}); static CYTHON_INLINE {{type}} __Pyx_c_pow{{func_suffix}}({{type}}, {{type}}); #endif #endif /////////////// Arithmetic /////////////// #if CYTHON_CCOMPLEX && ({{is_float}}) && (!{{is_extern_float_typedef}} || __cplusplus) #else static CYTHON_INLINE int __Pyx_c_eq{{func_suffix}}({{type}} a, {{type}} b) { return (a.real == b.real) && (a.imag == b.imag); } static CYTHON_INLINE {{type}} __Pyx_c_sum{{func_suffix}}({{type}} a, {{type}} b) { {{type}} z; z.real = a.real + b.real; z.imag = a.imag + b.imag; return z; } static CYTHON_INLINE {{type}} __Pyx_c_diff{{func_suffix}}({{type}} a, {{type}} b) { {{type}} z; z.real = a.real - b.real; z.imag = a.imag - b.imag; return z; } static CYTHON_INLINE {{type}} __Pyx_c_prod{{func_suffix}}({{type}} a, {{type}} b) { {{type}} z; z.real = a.real * b.real - a.imag * b.imag; z.imag = a.real * b.imag + a.imag * b.real; return z; } #if {{is_float}} static CYTHON_INLINE {{type}} __Pyx_c_quot{{func_suffix}}({{type}} a, {{type}} b) { if (b.imag == 0) { return {{type_name}}_from_parts(a.real / b.real, a.imag / b.real); } else if (fabs{{m}}(b.real) >= fabs{{m}}(b.imag)) { if (b.real == 0 && b.imag == 0) { return {{type_name}}_from_parts(a.real / b.real, a.imag / b.imag); } else { {{real_type}} r = b.imag / b.real; {{real_type}} s = ({{real_type}})(1.0) / (b.real + b.imag * r); return {{type_name}}_from_parts( (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); } } else { {{real_type}} r = b.real / b.imag; {{real_type}} s = ({{real_type}})(1.0) / (b.imag + b.real * r); return {{type_name}}_from_parts( (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); } } #else static CYTHON_INLINE {{type}} __Pyx_c_quot{{func_suffix}}({{type}} a, {{type}} b) { if (b.imag == 0) { return {{type_name}}_from_parts(a.real / b.real, a.imag / b.real); } else { {{real_type}} denom = b.real * b.real + b.imag * b.imag; return {{type_name}}_from_parts( (a.real * b.real + a.imag * b.imag) / denom, (a.imag * b.real - a.real * b.imag) / denom); } } #endif static CYTHON_INLINE {{type}} __Pyx_c_neg{{func_suffix}}({{type}} a) { {{type}} z; z.real = -a.real; z.imag = -a.imag; return z; } static CYTHON_INLINE int __Pyx_c_is_zero{{func_suffix}}({{type}} a) { return (a.real == 0) && (a.imag == 0); } static CYTHON_INLINE {{type}} __Pyx_c_conj{{func_suffix}}({{type}} a) { {{type}} z; z.real = a.real; z.imag = -a.imag; return z; } #if {{is_float}} static CYTHON_INLINE {{real_type}} __Pyx_c_abs{{func_suffix}}({{type}} z) { #if !defined(HAVE_HYPOT) || defined(_MSC_VER) return sqrt{{m}}(z.real*z.real + z.imag*z.imag); #else return hypot{{m}}(z.real, z.imag); #endif } static CYTHON_INLINE {{type}} __Pyx_c_pow{{func_suffix}}({{type}} a, {{type}} b) { {{type}} z; {{real_type}} r, lnr, theta, z_r, z_theta; if (b.imag == 0 && b.real == (int)b.real) { if (b.real < 0) { {{real_type}} denom = a.real * a.real + a.imag * a.imag; a.real = a.real / denom; a.imag = -a.imag / denom; b.real = -b.real; } switch ((int)b.real) { case 0: z.real = 1; z.imag = 0; return z; case 1: return a; case 2: return __Pyx_c_prod{{func_suffix}}(a, a); case 3: z = __Pyx_c_prod{{func_suffix}}(a, a); return __Pyx_c_prod{{func_suffix}}(z, a); case 4: z = __Pyx_c_prod{{func_suffix}}(a, a); return __Pyx_c_prod{{func_suffix}}(z, z); } } if (a.imag == 0) { if (a.real == 0) { return a; } else if ((b.imag == 0) && (a.real >= 0)) { z.real = pow{{m}}(a.real, b.real); z.imag = 0; return z; } else if (a.real > 0) { r = a.real; theta = 0; } else { r = -a.real; theta = atan2{{m}}(0.0, -1.0); } } else { r = __Pyx_c_abs{{func_suffix}}(a); theta = atan2{{m}}(a.imag, a.real); } lnr = log{{m}}(r); z_r = exp{{m}}(lnr * b.real - theta * b.imag); z_theta = theta * b.real + lnr * b.imag; z.real = z_r * cos{{m}}(z_theta); z.imag = z_r * sin{{m}}(z_theta); return z; } #endif #endif /////////////// SoftComplexToDouble.proto ////////////////// static double __Pyx_SoftComplexToDouble(__pyx_t_double_complex value, int have_gil); /* proto */ /////////////// SoftComplexToDouble ////////////////// //@requires: RealImag static double __Pyx_SoftComplexToDouble(__pyx_t_double_complex value, int have_gil) { // This isn't an absolutely perfect match for the Python behaviour: // In Python the type would be determined right after the number is // created (usually '**'), while here it's determined when coerced // to a PyObject, which may be a few operations later. if (unlikely(__Pyx_CIMAG(value))) { PyGILState_STATE gilstate; if (!have_gil) gilstate = PyGILState_Ensure(); PyErr_SetString(PyExc_TypeError, "Cannot convert 'complex' with non-zero imaginary component to 'double' " "(this most likely comes from the '**' operator; " "use 'cython.cpow(True)' to return 'nan' instead of a " "complex number)."); if (!have_gil) PyGILState_Release(gilstate); return -1.; } return __Pyx_CREAL(value); } ///////// SoftComplexToPy.proto /////////////////////// static PyObject *__pyx_Py_FromSoftComplex(__pyx_t_double_complex value); /* proto */ //////// SoftComplexToPy //////////////// //@requires: RealImag static PyObject *__pyx_Py_FromSoftComplex(__pyx_t_double_complex value) { if (__Pyx_CIMAG(value)) { return PyComplex_FromDoubles(__Pyx_CREAL(value), __Pyx_CIMAG(value)); } else { return PyFloat_FromDouble(__Pyx_CREAL(value)); } } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Utility/Coroutine.c0000644000175100001770000030104000000000000020614 0ustar00runnerdocker00000000000000//////////////////// GeneratorYieldFrom.proto //////////////////// static CYTHON_INLINE PyObject* __Pyx_Generator_Yield_From(__pyx_CoroutineObject *gen, PyObject *source); //////////////////// GeneratorYieldFrom //////////////////// //@requires: Generator #if CYTHON_USE_TYPE_SLOTS static void __Pyx_PyIter_CheckErrorAndDecref(PyObject *source) { __Pyx_TypeName source_type_name = __Pyx_PyType_GetName(Py_TYPE(source)); PyErr_Format(PyExc_TypeError, "iter() returned non-iterator of type '" __Pyx_FMT_TYPENAME "'", source_type_name); __Pyx_DECREF_TypeName(source_type_name); Py_DECREF(source); } #endif static CYTHON_INLINE PyObject* __Pyx_Generator_Yield_From(__pyx_CoroutineObject *gen, PyObject *source) { PyObject *source_gen, *retval; #ifdef __Pyx_Coroutine_USED if (__Pyx_Coroutine_Check(source)) { // TODO: this should only happen for types.coroutine()ed generators, but we can't determine that here Py_INCREF(source); source_gen = source; retval = __Pyx_Generator_Next(source); } else #endif { #if CYTHON_USE_TYPE_SLOTS if (likely(Py_TYPE(source)->tp_iter)) { source_gen = Py_TYPE(source)->tp_iter(source); if (unlikely(!source_gen)) return NULL; if (unlikely(!PyIter_Check(source_gen))) { __Pyx_PyIter_CheckErrorAndDecref(source_gen); return NULL; } } else // CPython also allows non-iterable sequences to be iterated over #endif { source_gen = PyObject_GetIter(source); if (unlikely(!source_gen)) return NULL; } // source_gen is now the iterator, make the first next() call retval = __Pyx_PyObject_GetIterNextFunc(source_gen)(source_gen); } if (likely(retval)) { gen->yieldfrom = source_gen; return retval; } Py_DECREF(source_gen); return NULL; } //////////////////// CoroutineYieldFrom.proto //////////////////// static CYTHON_INLINE PyObject* __Pyx_Coroutine_Yield_From(__pyx_CoroutineObject *gen, PyObject *source); //////////////////// CoroutineYieldFrom //////////////////// //@requires: Coroutine //@requires: GetAwaitIter static PyObject* __Pyx__Coroutine_Yield_From_Generic(__pyx_CoroutineObject *gen, PyObject *source) { PyObject *retval; PyObject *source_gen = __Pyx__Coroutine_GetAwaitableIter(source); if (unlikely(!source_gen)) { return NULL; } // source_gen is now the iterator, make the first next() call if (__Pyx_Coroutine_Check(source_gen)) { retval = __Pyx_Generator_Next(source_gen); } else { retval = __Pyx_PyObject_GetIterNextFunc(source_gen)(source_gen); } if (retval) { gen->yieldfrom = source_gen; return retval; } Py_DECREF(source_gen); return NULL; } static CYTHON_INLINE PyObject* __Pyx_Coroutine_Yield_From(__pyx_CoroutineObject *gen, PyObject *source) { PyObject *retval; if (__Pyx_Coroutine_Check(source)) { if (unlikely(((__pyx_CoroutineObject*)source)->yieldfrom)) { PyErr_SetString( PyExc_RuntimeError, "coroutine is being awaited already"); return NULL; } retval = __Pyx_Generator_Next(source); #ifdef __Pyx_AsyncGen_USED // inlined "__pyx_PyAsyncGenASend" handling to avoid the series of generic calls } else if (__pyx_PyAsyncGenASend_CheckExact(source)) { retval = __Pyx_async_gen_asend_iternext(source); #endif } else { return __Pyx__Coroutine_Yield_From_Generic(gen, source); } if (retval) { Py_INCREF(source); gen->yieldfrom = source; } return retval; } //////////////////// GetAwaitIter.proto //////////////////// static CYTHON_INLINE PyObject *__Pyx_Coroutine_GetAwaitableIter(PyObject *o); /*proto*/ static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *o); /*proto*/ //////////////////// GetAwaitIter //////////////////// //@requires: ObjectHandling.c::PyObjectGetMethod //@requires: ObjectHandling.c::PyObjectCallNoArg //@requires: ObjectHandling.c::PyObjectCallOneArg static CYTHON_INLINE PyObject *__Pyx_Coroutine_GetAwaitableIter(PyObject *o) { #ifdef __Pyx_Coroutine_USED if (__Pyx_Coroutine_Check(o)) { return __Pyx_NewRef(o); } #endif return __Pyx__Coroutine_GetAwaitableIter(o); } static void __Pyx_Coroutine_AwaitableIterError(PyObject *source) { #if PY_VERSION_HEX >= 0x030600B3 && PY_VERSION_HEX < 0x030d0000 || defined(_PyErr_FormatFromCause) __Pyx_TypeName source_type_name = __Pyx_PyType_GetName(Py_TYPE(source)); _PyErr_FormatFromCause(PyExc_TypeError, "'async for' received an invalid object from __anext__: " __Pyx_FMT_TYPENAME, source_type_name); __Pyx_DECREF_TypeName(source_type_name); #elif PY_MAJOR_VERSION >= 3 PyObject *exc, *val, *val2, *tb; __Pyx_TypeName source_type_name = __Pyx_PyType_GetName(Py_TYPE(source)); assert(PyErr_Occurred()); PyErr_Fetch(&exc, &val, &tb); PyErr_NormalizeException(&exc, &val, &tb); if (tb != NULL) { PyException_SetTraceback(val, tb); Py_DECREF(tb); } Py_DECREF(exc); assert(!PyErr_Occurred()); PyErr_Format(PyExc_TypeError, "'async for' received an invalid object from __anext__: " __Pyx_FMT_TYPENAME, source_type_name); __Pyx_DECREF_TypeName(source_type_name); PyErr_Fetch(&exc, &val2, &tb); PyErr_NormalizeException(&exc, &val2, &tb); Py_INCREF(val); PyException_SetCause(val2, val); PyException_SetContext(val2, val); PyErr_Restore(exc, val2, tb); #else // since Py2 does not have exception chaining, it's better to avoid shadowing exceptions there CYTHON_UNUSED_VAR(source); #endif } // adapted from genobject.c in Py3.5 static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *obj) { PyObject *res; #if CYTHON_USE_ASYNC_SLOTS __Pyx_PyAsyncMethodsStruct* am = __Pyx_PyType_AsAsync(obj); if (likely(am && am->am_await)) { res = (*am->am_await)(obj); } else #endif #if PY_VERSION_HEX >= 0x030500B2 || defined(PyCoro_CheckExact) if (PyCoro_CheckExact(obj)) { return __Pyx_NewRef(obj); } else #endif #if CYTHON_COMPILING_IN_CPYTHON && defined(CO_ITERABLE_COROUTINE) #if PY_VERSION_HEX >= 0x030C00A6 if (PyGen_CheckExact(obj) && (PyGen_GetCode((PyGenObject*)obj)->co_flags & CO_ITERABLE_COROUTINE)) { #else if (PyGen_CheckExact(obj) && ((PyGenObject*)obj)->gi_code && ((PyCodeObject *)((PyGenObject*)obj)->gi_code)->co_flags & CO_ITERABLE_COROUTINE) { #endif // Python generator marked with "@types.coroutine" decorator return __Pyx_NewRef(obj); } else #endif { PyObject *method = NULL; int is_method = __Pyx_PyObject_GetMethod(obj, PYIDENT("__await__"), &method); if (likely(is_method)) { res = __Pyx_PyObject_CallOneArg(method, obj); } else if (likely(method)) { res = __Pyx_PyObject_CallNoArg(method); } else goto slot_error; Py_DECREF(method); } if (unlikely(!res)) { // surprisingly, CPython replaces the exception here... __Pyx_Coroutine_AwaitableIterError(obj); goto bad; } if (unlikely(!PyIter_Check(res))) { __Pyx_TypeName res_type_name = __Pyx_PyType_GetName(Py_TYPE(res)); PyErr_Format(PyExc_TypeError, "__await__() returned non-iterator of type '" __Pyx_FMT_TYPENAME "'", res_type_name); __Pyx_DECREF_TypeName(res_type_name); Py_CLEAR(res); } else { int is_coroutine = 0; #ifdef __Pyx_Coroutine_USED is_coroutine |= __Pyx_Coroutine_Check(res); #endif #if PY_VERSION_HEX >= 0x030500B2 || defined(PyCoro_CheckExact) is_coroutine |= PyCoro_CheckExact(res); #endif if (unlikely(is_coroutine)) { /* __await__ must return an *iterator*, not a coroutine or another awaitable (see PEP 492) */ PyErr_SetString(PyExc_TypeError, "__await__() returned a coroutine"); Py_CLEAR(res); } } return res; slot_error: { __Pyx_TypeName obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj)); PyErr_Format(PyExc_TypeError, "object " __Pyx_FMT_TYPENAME " can't be used in 'await' expression", obj_type_name); __Pyx_DECREF_TypeName(obj_type_name); } bad: return NULL; } //////////////////// AsyncIter.proto //////////////////// static CYTHON_INLINE PyObject *__Pyx_Coroutine_GetAsyncIter(PyObject *o); /*proto*/ static CYTHON_INLINE PyObject *__Pyx_Coroutine_AsyncIterNext(PyObject *o); /*proto*/ //////////////////// AsyncIter //////////////////// //@requires: GetAwaitIter //@requires: ObjectHandling.c::PyObjectCallMethod0 static PyObject *__Pyx_Coroutine_GetAsyncIter_Generic(PyObject *obj) { __Pyx_TypeName obj_type_name; #if PY_VERSION_HEX < 0x030500B1 { PyObject *iter = __Pyx_PyObject_CallMethod0(obj, PYIDENT("__aiter__")); if (likely(iter)) return iter; // FIXME: for the sake of a nicely conforming exception message, assume any AttributeError meant '__aiter__' if (!PyErr_ExceptionMatches(PyExc_AttributeError)) return NULL; } #else // avoid C warning about 'unused function' (void)&__Pyx_PyObject_CallMethod0; #endif obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj)); PyErr_Format(PyExc_TypeError, "'async for' requires an object with __aiter__ method, got " __Pyx_FMT_TYPENAME, obj_type_name); __Pyx_DECREF_TypeName(obj_type_name); return NULL; } static CYTHON_INLINE PyObject *__Pyx_Coroutine_GetAsyncIter(PyObject *obj) { #ifdef __Pyx_AsyncGen_USED if (__Pyx_AsyncGen_CheckExact(obj)) { return __Pyx_NewRef(obj); } #endif #if CYTHON_USE_ASYNC_SLOTS { __Pyx_PyAsyncMethodsStruct* am = __Pyx_PyType_AsAsync(obj); if (likely(am && am->am_aiter)) { return (*am->am_aiter)(obj); } } #endif return __Pyx_Coroutine_GetAsyncIter_Generic(obj); } static PyObject *__Pyx__Coroutine_AsyncIterNext(PyObject *obj) { #if PY_VERSION_HEX < 0x030500B1 { PyObject *value = __Pyx_PyObject_CallMethod0(obj, PYIDENT("__anext__")); if (likely(value)) return value; } // FIXME: for the sake of a nicely conforming exception message, assume any AttributeError meant '__anext__' if (PyErr_ExceptionMatches(PyExc_AttributeError)) #endif { __Pyx_TypeName obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj)); PyErr_Format(PyExc_TypeError, "'async for' requires an object with __anext__ method, got " __Pyx_FMT_TYPENAME, obj_type_name); __Pyx_DECREF_TypeName(obj_type_name); } return NULL; } static CYTHON_INLINE PyObject *__Pyx_Coroutine_AsyncIterNext(PyObject *obj) { #ifdef __Pyx_AsyncGen_USED if (__Pyx_AsyncGen_CheckExact(obj)) { return __Pyx_async_gen_anext(obj); } #endif #if CYTHON_USE_ASYNC_SLOTS { __Pyx_PyAsyncMethodsStruct* am = __Pyx_PyType_AsAsync(obj); if (likely(am && am->am_anext)) { return (*am->am_anext)(obj); } } #endif return __Pyx__Coroutine_AsyncIterNext(obj); } //////////////////// pep479.proto //////////////////// static void __Pyx_Generator_Replace_StopIteration(int in_async_gen); /*proto*/ //////////////////// pep479 //////////////////// //@requires: Exceptions.c::GetException static void __Pyx_Generator_Replace_StopIteration(int in_async_gen) { PyObject *exc, *val, *tb, *cur_exc; __Pyx_PyThreadState_declare #ifdef __Pyx_StopAsyncIteration_USED int is_async_stopiteration = 0; #endif CYTHON_MAYBE_UNUSED_VAR(in_async_gen); cur_exc = PyErr_Occurred(); if (likely(!__Pyx_PyErr_GivenExceptionMatches(cur_exc, PyExc_StopIteration))) { #ifdef __Pyx_StopAsyncIteration_USED if (in_async_gen && unlikely(__Pyx_PyErr_GivenExceptionMatches(cur_exc, __Pyx_PyExc_StopAsyncIteration))) { is_async_stopiteration = 1; } else #endif return; } __Pyx_PyThreadState_assign // Chain exceptions by moving Stop(Async)Iteration to exc_info before creating the RuntimeError. // In Py2.x, no chaining happens, but the exception still stays visible in exc_info. __Pyx_GetException(&exc, &val, &tb); Py_XDECREF(exc); Py_XDECREF(val); Py_XDECREF(tb); PyErr_SetString(PyExc_RuntimeError, #ifdef __Pyx_StopAsyncIteration_USED is_async_stopiteration ? "async generator raised StopAsyncIteration" : in_async_gen ? "async generator raised StopIteration" : #endif "generator raised StopIteration"); } //////////////////// CoroutineBase.proto //////////////////// //@substitute: naming struct __pyx_CoroutineObject; typedef PyObject *(*__pyx_coroutine_body_t)(struct __pyx_CoroutineObject *, PyThreadState *, PyObject *); #if CYTHON_USE_EXC_INFO_STACK // See https://bugs.python.org/issue25612 #define __Pyx_ExcInfoStruct _PyErr_StackItem #else // Minimal replacement struct for Py<3.7, without the Py3.7 exception state stack. typedef struct { PyObject *exc_type; PyObject *exc_value; PyObject *exc_traceback; } __Pyx_ExcInfoStruct; #endif typedef struct __pyx_CoroutineObject { PyObject_HEAD __pyx_coroutine_body_t body; PyObject *closure; __Pyx_ExcInfoStruct gi_exc_state; PyObject *gi_weakreflist; PyObject *classobj; PyObject *yieldfrom; PyObject *gi_name; PyObject *gi_qualname; PyObject *gi_modulename; PyObject *gi_code; PyObject *gi_frame; int resume_label; // using T_BOOL for property below requires char value char is_running; } __pyx_CoroutineObject; static __pyx_CoroutineObject *__Pyx__Coroutine_New( PyTypeObject *type, __pyx_coroutine_body_t body, PyObject *code, PyObject *closure, PyObject *name, PyObject *qualname, PyObject *module_name); /*proto*/ static __pyx_CoroutineObject *__Pyx__Coroutine_NewInit( __pyx_CoroutineObject *gen, __pyx_coroutine_body_t body, PyObject *code, PyObject *closure, PyObject *name, PyObject *qualname, PyObject *module_name); /*proto*/ static CYTHON_INLINE void __Pyx_Coroutine_ExceptionClear(__Pyx_ExcInfoStruct *self); static int __Pyx_Coroutine_clear(PyObject *self); /*proto*/ static PyObject *__Pyx_Coroutine_Send(PyObject *self, PyObject *value); /*proto*/ static PyObject *__Pyx_Coroutine_Close(PyObject *self); /*proto*/ static PyObject *__Pyx_Coroutine_Throw(PyObject *gen, PyObject *args); /*proto*/ // macros for exception state swapping instead of inline functions to make use of the local thread state context #if CYTHON_USE_EXC_INFO_STACK #define __Pyx_Coroutine_SwapException(self) #define __Pyx_Coroutine_ResetAndClearException(self) __Pyx_Coroutine_ExceptionClear(&(self)->gi_exc_state) #else #define __Pyx_Coroutine_SwapException(self) { \ __Pyx_ExceptionSwap(&(self)->gi_exc_state.exc_type, &(self)->gi_exc_state.exc_value, &(self)->gi_exc_state.exc_traceback); \ __Pyx_Coroutine_ResetFrameBackpointer(&(self)->gi_exc_state); \ } #define __Pyx_Coroutine_ResetAndClearException(self) { \ __Pyx_ExceptionReset((self)->gi_exc_state.exc_type, (self)->gi_exc_state.exc_value, (self)->gi_exc_state.exc_traceback); \ (self)->gi_exc_state.exc_type = (self)->gi_exc_state.exc_value = (self)->gi_exc_state.exc_traceback = NULL; \ } #endif #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyGen_FetchStopIterationValue(pvalue) \ __Pyx_PyGen__FetchStopIterationValue($local_tstate_cname, pvalue) #else #define __Pyx_PyGen_FetchStopIterationValue(pvalue) \ __Pyx_PyGen__FetchStopIterationValue(__Pyx_PyThreadState_Current, pvalue) #endif static int __Pyx_PyGen__FetchStopIterationValue(PyThreadState *tstate, PyObject **pvalue); /*proto*/ static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__Pyx_ExcInfoStruct *exc_state); /*proto*/ //////////////////// Coroutine.proto //////////////////// #define __Pyx_Coroutine_USED #define __Pyx_Coroutine_CheckExact(obj) __Pyx_IS_TYPE(obj, __pyx_CoroutineType) // __Pyx_Coroutine_Check(obj): see override for IterableCoroutine below #define __Pyx_Coroutine_Check(obj) __Pyx_Coroutine_CheckExact(obj) #define __Pyx_CoroutineAwait_CheckExact(obj) __Pyx_IS_TYPE(obj, __pyx_CoroutineAwaitType) #define __Pyx_Coroutine_New(body, code, closure, name, qualname, module_name) \ __Pyx__Coroutine_New(__pyx_CoroutineType, body, code, closure, name, qualname, module_name) static int __pyx_Coroutine_init(PyObject *module); /*proto*/ static PyObject *__Pyx__Coroutine_await(PyObject *coroutine); /*proto*/ typedef struct { PyObject_HEAD PyObject *coroutine; } __pyx_CoroutineAwaitObject; static PyObject *__Pyx_CoroutineAwait_Close(__pyx_CoroutineAwaitObject *self, PyObject *arg); /*proto*/ static PyObject *__Pyx_CoroutineAwait_Throw(__pyx_CoroutineAwaitObject *self, PyObject *args); /*proto*/ //////////////////// Generator.proto //////////////////// #define __Pyx_Generator_USED #define __Pyx_Generator_CheckExact(obj) __Pyx_IS_TYPE(obj, __pyx_GeneratorType) #define __Pyx_Generator_New(body, code, closure, name, qualname, module_name) \ __Pyx__Coroutine_New(__pyx_GeneratorType, body, code, closure, name, qualname, module_name) static PyObject *__Pyx_Generator_Next(PyObject *self); static int __pyx_Generator_init(PyObject *module); /*proto*/ //////////////////// AsyncGen //////////////////// //@requires: AsyncGen.c::AsyncGenerator // -> empty, only delegates to separate file //////////////////// CoroutineBase //////////////////// //@substitute: naming //@requires: Exceptions.c::PyErrFetchRestore //@requires: Exceptions.c::PyThreadStateGet //@requires: Exceptions.c::SwapException //@requires: Exceptions.c::RaiseException //@requires: Exceptions.c::SaveResetException //@requires: ObjectHandling.c::PyObjectCallMethod1 //@requires: ObjectHandling.c::PyObjectCallNoArg //@requires: ObjectHandling.c::PyObjectCallOneArg //@requires: ObjectHandling.c::PyObjectFastCall //@requires: ObjectHandling.c::PyObjectGetAttrStr //@requires: ObjectHandling.c::PyObjectGetAttrStrNoError //@requires: CommonStructures.c::FetchCommonType //@requires: ModuleSetupCode.c::IncludeStructmemberH #include #if PY_VERSION_HEX >= 0x030b00a6 #ifndef Py_BUILD_CORE #define Py_BUILD_CORE 1 #endif #include "internal/pycore_frame.h" #endif #define __Pyx_Coroutine_Undelegate(gen) Py_CLEAR((gen)->yieldfrom) // If StopIteration exception is set, fetches its 'value' // attribute if any, otherwise sets pvalue to None. // // Returns 0 if no exception or StopIteration is set. // If any other exception is set, returns -1 and leaves // pvalue unchanged. static int __Pyx_PyGen__FetchStopIterationValue(PyThreadState *$local_tstate_cname, PyObject **pvalue) { PyObject *et, *ev, *tb; PyObject *value = NULL; CYTHON_UNUSED_VAR($local_tstate_cname); __Pyx_ErrFetch(&et, &ev, &tb); if (!et) { Py_XDECREF(tb); Py_XDECREF(ev); Py_INCREF(Py_None); *pvalue = Py_None; return 0; } // most common case: plain StopIteration without or with separate argument if (likely(et == PyExc_StopIteration)) { if (!ev) { Py_INCREF(Py_None); value = Py_None; } #if PY_VERSION_HEX >= 0x030300A0 else if (likely(__Pyx_IS_TYPE(ev, (PyTypeObject*)PyExc_StopIteration))) { value = ((PyStopIterationObject *)ev)->value; Py_INCREF(value); Py_DECREF(ev); } #endif // PyErr_SetObject() and friends put the value directly into ev else if (unlikely(PyTuple_Check(ev))) { // if it's a tuple, it is interpreted as separate constructor arguments (surprise!) if (PyTuple_GET_SIZE(ev) >= 1) { #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS value = PyTuple_GET_ITEM(ev, 0); Py_INCREF(value); #else value = PySequence_ITEM(ev, 0); #endif } else { Py_INCREF(Py_None); value = Py_None; } Py_DECREF(ev); } else if (!__Pyx_TypeCheck(ev, (PyTypeObject*)PyExc_StopIteration)) { // 'steal' reference to ev value = ev; } if (likely(value)) { Py_XDECREF(tb); Py_DECREF(et); *pvalue = value; return 0; } } else if (!__Pyx_PyErr_GivenExceptionMatches(et, PyExc_StopIteration)) { __Pyx_ErrRestore(et, ev, tb); return -1; } // otherwise: normalise and check what that gives us PyErr_NormalizeException(&et, &ev, &tb); if (unlikely(!PyObject_TypeCheck(ev, (PyTypeObject*)PyExc_StopIteration))) { // looks like normalisation failed - raise the new exception __Pyx_ErrRestore(et, ev, tb); return -1; } Py_XDECREF(tb); Py_DECREF(et); #if PY_VERSION_HEX >= 0x030300A0 value = ((PyStopIterationObject *)ev)->value; Py_INCREF(value); Py_DECREF(ev); #else { PyObject* args = __Pyx_PyObject_GetAttrStr(ev, PYIDENT("args")); Py_DECREF(ev); if (likely(args)) { value = PySequence_GetItem(args, 0); Py_DECREF(args); } if (unlikely(!value)) { __Pyx_ErrRestore(NULL, NULL, NULL); Py_INCREF(Py_None); value = Py_None; } } #endif *pvalue = value; return 0; } static CYTHON_INLINE void __Pyx_Coroutine_ExceptionClear(__Pyx_ExcInfoStruct *exc_state) { #if PY_VERSION_HEX >= 0x030B00a4 Py_CLEAR(exc_state->exc_value); #else PyObject *t, *v, *tb; t = exc_state->exc_type; v = exc_state->exc_value; tb = exc_state->exc_traceback; exc_state->exc_type = NULL; exc_state->exc_value = NULL; exc_state->exc_traceback = NULL; Py_XDECREF(t); Py_XDECREF(v); Py_XDECREF(tb); #endif } #define __Pyx_Coroutine_AlreadyRunningError(gen) (__Pyx__Coroutine_AlreadyRunningError(gen), (PyObject*)NULL) static void __Pyx__Coroutine_AlreadyRunningError(__pyx_CoroutineObject *gen) { const char *msg; CYTHON_MAYBE_UNUSED_VAR(gen); if ((0)) { #ifdef __Pyx_Coroutine_USED } else if (__Pyx_Coroutine_Check((PyObject*)gen)) { msg = "coroutine already executing"; #endif #ifdef __Pyx_AsyncGen_USED } else if (__Pyx_AsyncGen_CheckExact((PyObject*)gen)) { msg = "async generator already executing"; #endif } else { msg = "generator already executing"; } PyErr_SetString(PyExc_ValueError, msg); } #define __Pyx_Coroutine_NotStartedError(gen) (__Pyx__Coroutine_NotStartedError(gen), (PyObject*)NULL) static void __Pyx__Coroutine_NotStartedError(PyObject *gen) { const char *msg; CYTHON_MAYBE_UNUSED_VAR(gen); if ((0)) { #ifdef __Pyx_Coroutine_USED } else if (__Pyx_Coroutine_Check(gen)) { msg = "can't send non-None value to a just-started coroutine"; #endif #ifdef __Pyx_AsyncGen_USED } else if (__Pyx_AsyncGen_CheckExact(gen)) { msg = "can't send non-None value to a just-started async generator"; #endif } else { msg = "can't send non-None value to a just-started generator"; } PyErr_SetString(PyExc_TypeError, msg); } #define __Pyx_Coroutine_AlreadyTerminatedError(gen, value, closing) (__Pyx__Coroutine_AlreadyTerminatedError(gen, value, closing), (PyObject*)NULL) static void __Pyx__Coroutine_AlreadyTerminatedError(PyObject *gen, PyObject *value, int closing) { CYTHON_MAYBE_UNUSED_VAR(gen); CYTHON_MAYBE_UNUSED_VAR(closing); #ifdef __Pyx_Coroutine_USED if (!closing && __Pyx_Coroutine_Check(gen)) { // `self` is an exhausted coroutine: raise an error, // except when called from gen_close(), which should // always be a silent method. PyErr_SetString(PyExc_RuntimeError, "cannot reuse already awaited coroutine"); } else #endif if (value) { // `gen` is an exhausted generator: // only set exception if called from send(). #ifdef __Pyx_AsyncGen_USED if (__Pyx_AsyncGen_CheckExact(gen)) PyErr_SetNone(__Pyx_PyExc_StopAsyncIteration); else #endif PyErr_SetNone(PyExc_StopIteration); } } static PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value, int closing) { __Pyx_PyThreadState_declare PyThreadState *tstate; __Pyx_ExcInfoStruct *exc_state; PyObject *retval; assert(!self->is_running); if (unlikely(self->resume_label == 0)) { if (unlikely(value && value != Py_None)) { return __Pyx_Coroutine_NotStartedError((PyObject*)self); } } if (unlikely(self->resume_label == -1)) { return __Pyx_Coroutine_AlreadyTerminatedError((PyObject*)self, value, closing); } #if CYTHON_FAST_THREAD_STATE __Pyx_PyThreadState_assign tstate = $local_tstate_cname; #else tstate = __Pyx_PyThreadState_Current; #endif // Traceback/Frame rules pre-Py3.7: // - on entry, save external exception state in self->gi_exc_state, restore it on exit // - on exit, keep internally generated exceptions in self->gi_exc_state, clear everything else // - on entry, set "f_back" pointer of internal exception traceback to (current) outer call frame // - on exit, clear "f_back" of internal exception traceback // - do not touch external frames and tracebacks // Traceback/Frame rules for Py3.7+ (CYTHON_USE_EXC_INFO_STACK): // - on entry, push internal exception state in self->gi_exc_state on the exception stack // - on exit, keep internally generated exceptions in self->gi_exc_state, clear everything else // - on entry, set "f_back" pointer of internal exception traceback to (current) outer call frame // - on exit, clear "f_back" of internal exception traceback // - do not touch external frames and tracebacks exc_state = &self->gi_exc_state; if (exc_state->exc_value) { #if CYTHON_COMPILING_IN_PYPY // FIXME: what to do in PyPy? #else // Generators always return to their most recent caller, not // necessarily their creator. PyObject *exc_tb; #if PY_VERSION_HEX >= 0x030B00a4 && !CYTHON_COMPILING_IN_CPYTHON // owned reference! exc_tb = PyException_GetTraceback(exc_state->exc_value); #elif PY_VERSION_HEX >= 0x030B00a4 exc_tb = ((PyBaseExceptionObject*) exc_state->exc_value)->traceback; #else exc_tb = exc_state->exc_traceback; #endif if (exc_tb) { PyTracebackObject *tb = (PyTracebackObject *) exc_tb; PyFrameObject *f = tb->tb_frame; assert(f->f_back == NULL); #if PY_VERSION_HEX >= 0x030B00A1 // PyThreadState_GetFrame returns NULL if there isn't a current frame // which is a valid state so no need to check f->f_back = PyThreadState_GetFrame(tstate); #else Py_XINCREF(tstate->frame); f->f_back = tstate->frame; #endif #if PY_VERSION_HEX >= 0x030B00a4 && !CYTHON_COMPILING_IN_CPYTHON Py_DECREF(exc_tb); #endif } #endif } #if CYTHON_USE_EXC_INFO_STACK // See https://bugs.python.org/issue25612 exc_state->previous_item = tstate->exc_info; tstate->exc_info = exc_state; #else if (exc_state->exc_type) { // We were in an except handler when we left, // restore the exception state which was put aside. __Pyx_ExceptionSwap(&exc_state->exc_type, &exc_state->exc_value, &exc_state->exc_traceback); // self->exc_* now holds the exception state of the caller } else { // save away the exception state of the caller __Pyx_Coroutine_ExceptionClear(exc_state); __Pyx_ExceptionSave(&exc_state->exc_type, &exc_state->exc_value, &exc_state->exc_traceback); } #endif self->is_running = 1; retval = self->body(self, tstate, value); self->is_running = 0; #if CYTHON_USE_EXC_INFO_STACK // See https://bugs.python.org/issue25612 exc_state = &self->gi_exc_state; tstate->exc_info = exc_state->previous_item; exc_state->previous_item = NULL; // Cut off the exception frame chain so that we can reconnect it on re-entry above. __Pyx_Coroutine_ResetFrameBackpointer(exc_state); #endif return retval; } static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__Pyx_ExcInfoStruct *exc_state) { // Don't keep the reference to f_back any longer than necessary. It // may keep a chain of frames alive or it could create a reference // cycle. #if CYTHON_COMPILING_IN_PYPY // FIXME: what to do in PyPy? CYTHON_UNUSED_VAR(exc_state); #else PyObject *exc_tb; #if PY_VERSION_HEX >= 0x030B00a4 if (!exc_state->exc_value) return; // owned reference! exc_tb = PyException_GetTraceback(exc_state->exc_value); #else exc_tb = exc_state->exc_traceback; #endif if (likely(exc_tb)) { PyTracebackObject *tb = (PyTracebackObject *) exc_tb; PyFrameObject *f = tb->tb_frame; Py_CLEAR(f->f_back); #if PY_VERSION_HEX >= 0x030B00a4 Py_DECREF(exc_tb); #endif } #endif } static CYTHON_INLINE PyObject *__Pyx_Coroutine_MethodReturn(PyObject* gen, PyObject *retval) { CYTHON_MAYBE_UNUSED_VAR(gen); if (unlikely(!retval)) { __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign if (!__Pyx_PyErr_Occurred()) { // method call must not terminate with NULL without setting an exception PyObject *exc = PyExc_StopIteration; #ifdef __Pyx_AsyncGen_USED if (__Pyx_AsyncGen_CheckExact(gen)) exc = __Pyx_PyExc_StopAsyncIteration; #endif __Pyx_PyErr_SetNone(exc); } } return retval; } #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03030000 && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3) static CYTHON_INLINE PyObject *__Pyx_PyGen_Send(PyGenObject *gen, PyObject *arg) { #if PY_VERSION_HEX <= 0x030A00A1 return _PyGen_Send(gen, arg); #else PyObject *result; // PyIter_Send() asserts non-NULL arg if (PyIter_Send((PyObject*)gen, arg ? arg : Py_None, &result) == PYGEN_RETURN) { if (PyAsyncGen_CheckExact(gen)) { assert(result == Py_None); PyErr_SetNone(PyExc_StopAsyncIteration); } else if (result == Py_None) { PyErr_SetNone(PyExc_StopIteration); } else { #if PY_VERSION_HEX < 0x030d00A1 _PyGen_SetStopIterationValue(result); #else if (!PyTuple_Check(result) && !PyExceptionInstance_Check(result)) { // delay instantiation if possible PyErr_SetObject(PyExc_StopIteration, result); } else { PyObject *exc = __Pyx_PyObject_CallOneArg(PyExc_StopIteration, result); if (likely(exc != NULL)) { PyErr_SetObject(PyExc_StopIteration, exc); Py_DECREF(exc); } } #endif } Py_DECREF(result); result = NULL; } return result; #endif } #endif static CYTHON_INLINE PyObject *__Pyx_Coroutine_FinishDelegation(__pyx_CoroutineObject *gen) { PyObject *ret; PyObject *val = NULL; __Pyx_Coroutine_Undelegate(gen); __Pyx_PyGen__FetchStopIterationValue(__Pyx_PyThreadState_Current, &val); // val == NULL on failure => pass on exception ret = __Pyx_Coroutine_SendEx(gen, val, 0); Py_XDECREF(val); return ret; } static PyObject *__Pyx_Coroutine_Send(PyObject *self, PyObject *value) { PyObject *retval; __pyx_CoroutineObject *gen = (__pyx_CoroutineObject*) self; PyObject *yf = gen->yieldfrom; if (unlikely(gen->is_running)) return __Pyx_Coroutine_AlreadyRunningError(gen); if (yf) { PyObject *ret; // FIXME: does this really need an INCREF() ? //Py_INCREF(yf); gen->is_running = 1; #ifdef __Pyx_Generator_USED if (__Pyx_Generator_CheckExact(yf)) { ret = __Pyx_Coroutine_Send(yf, value); } else #endif #ifdef __Pyx_Coroutine_USED if (__Pyx_Coroutine_Check(yf)) { ret = __Pyx_Coroutine_Send(yf, value); } else #endif #ifdef __Pyx_AsyncGen_USED if (__pyx_PyAsyncGenASend_CheckExact(yf)) { ret = __Pyx_async_gen_asend_send(yf, value); } else #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03030000 && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3) // _PyGen_Send() is not exported before Py3.6 if (PyGen_CheckExact(yf)) { ret = __Pyx_PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value); } else #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03050000 && defined(PyCoro_CheckExact) && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3) // _PyGen_Send() is not exported before Py3.6 if (PyCoro_CheckExact(yf)) { ret = __Pyx_PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value); } else #endif { if (value == Py_None) ret = __Pyx_PyObject_GetIterNextFunc(yf)(yf); else ret = __Pyx_PyObject_CallMethod1(yf, PYIDENT("send"), value); } gen->is_running = 0; //Py_DECREF(yf); if (likely(ret)) { return ret; } retval = __Pyx_Coroutine_FinishDelegation(gen); } else { retval = __Pyx_Coroutine_SendEx(gen, value, 0); } return __Pyx_Coroutine_MethodReturn(self, retval); } // This helper function is used by gen_close and gen_throw to // close a subiterator being delegated to by yield-from. static int __Pyx_Coroutine_CloseIter(__pyx_CoroutineObject *gen, PyObject *yf) { PyObject *retval = NULL; int err = 0; #ifdef __Pyx_Generator_USED if (__Pyx_Generator_CheckExact(yf)) { retval = __Pyx_Coroutine_Close(yf); if (!retval) return -1; } else #endif #ifdef __Pyx_Coroutine_USED if (__Pyx_Coroutine_Check(yf)) { retval = __Pyx_Coroutine_Close(yf); if (!retval) return -1; } else if (__Pyx_CoroutineAwait_CheckExact(yf)) { retval = __Pyx_CoroutineAwait_Close((__pyx_CoroutineAwaitObject*)yf, NULL); if (!retval) return -1; } else #endif #ifdef __Pyx_AsyncGen_USED if (__pyx_PyAsyncGenASend_CheckExact(yf)) { retval = __Pyx_async_gen_asend_close(yf, NULL); // cannot fail } else if (__pyx_PyAsyncGenAThrow_CheckExact(yf)) { retval = __Pyx_async_gen_athrow_close(yf, NULL); // cannot fail } else #endif { PyObject *meth; gen->is_running = 1; meth = __Pyx_PyObject_GetAttrStrNoError(yf, PYIDENT("close")); if (unlikely(!meth)) { if (unlikely(PyErr_Occurred())) { PyErr_WriteUnraisable(yf); } } else { retval = __Pyx_PyObject_CallNoArg(meth); Py_DECREF(meth); if (unlikely(!retval)) err = -1; } gen->is_running = 0; } Py_XDECREF(retval); return err; } static PyObject *__Pyx_Generator_Next(PyObject *self) { __pyx_CoroutineObject *gen = (__pyx_CoroutineObject*) self; PyObject *yf = gen->yieldfrom; if (unlikely(gen->is_running)) return __Pyx_Coroutine_AlreadyRunningError(gen); if (yf) { PyObject *ret; // FIXME: does this really need an INCREF() ? //Py_INCREF(yf); // YieldFrom code ensures that yf is an iterator gen->is_running = 1; #ifdef __Pyx_Generator_USED if (__Pyx_Generator_CheckExact(yf)) { ret = __Pyx_Generator_Next(yf); } else #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03030000 && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3) // _PyGen_Send() is not exported before Py3.6 if (PyGen_CheckExact(yf)) { ret = __Pyx_PyGen_Send((PyGenObject*)yf, NULL); } else #endif #ifdef __Pyx_Coroutine_USED if (__Pyx_Coroutine_Check(yf)) { ret = __Pyx_Coroutine_Send(yf, Py_None); } else #endif ret = __Pyx_PyObject_GetIterNextFunc(yf)(yf); gen->is_running = 0; //Py_DECREF(yf); if (likely(ret)) { return ret; } return __Pyx_Coroutine_FinishDelegation(gen); } return __Pyx_Coroutine_SendEx(gen, Py_None, 0); } static PyObject *__Pyx_Coroutine_Close_Method(PyObject *self, PyObject *arg) { CYTHON_UNUSED_VAR(arg); return __Pyx_Coroutine_Close(self); } static PyObject *__Pyx_Coroutine_Close(PyObject *self) { __pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self; PyObject *retval, *raised_exception; PyObject *yf = gen->yieldfrom; int err = 0; if (unlikely(gen->is_running)) return __Pyx_Coroutine_AlreadyRunningError(gen); if (yf) { Py_INCREF(yf); err = __Pyx_Coroutine_CloseIter(gen, yf); __Pyx_Coroutine_Undelegate(gen); Py_DECREF(yf); } if (err == 0) PyErr_SetNone(PyExc_GeneratorExit); retval = __Pyx_Coroutine_SendEx(gen, NULL, 1); if (unlikely(retval)) { const char *msg; Py_DECREF(retval); if ((0)) { #ifdef __Pyx_Coroutine_USED } else if (__Pyx_Coroutine_Check(self)) { msg = "coroutine ignored GeneratorExit"; #endif #ifdef __Pyx_AsyncGen_USED } else if (__Pyx_AsyncGen_CheckExact(self)) { #if PY_VERSION_HEX < 0x03060000 msg = "async generator ignored GeneratorExit - might require Python 3.6+ finalisation (PEP 525)"; #else msg = "async generator ignored GeneratorExit"; #endif #endif } else { msg = "generator ignored GeneratorExit"; } PyErr_SetString(PyExc_RuntimeError, msg); return NULL; } raised_exception = PyErr_Occurred(); if (likely(!raised_exception || __Pyx_PyErr_GivenExceptionMatches2(raised_exception, PyExc_GeneratorExit, PyExc_StopIteration))) { // ignore these errors if (raised_exception) PyErr_Clear(); Py_INCREF(Py_None); return Py_None; } return NULL; } static PyObject *__Pyx__Coroutine_Throw(PyObject *self, PyObject *typ, PyObject *val, PyObject *tb, PyObject *args, int close_on_genexit) { __pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self; PyObject *yf = gen->yieldfrom; if (unlikely(gen->is_running)) return __Pyx_Coroutine_AlreadyRunningError(gen); if (yf) { PyObject *ret; Py_INCREF(yf); if (__Pyx_PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit) && close_on_genexit) { // Asynchronous generators *should not* be closed right away. // We have to allow some awaits to work it through, hence the // `close_on_genexit` parameter here. int err = __Pyx_Coroutine_CloseIter(gen, yf); Py_DECREF(yf); __Pyx_Coroutine_Undelegate(gen); if (err < 0) return __Pyx_Coroutine_MethodReturn(self, __Pyx_Coroutine_SendEx(gen, NULL, 0)); goto throw_here; } gen->is_running = 1; if (0 #ifdef __Pyx_Generator_USED || __Pyx_Generator_CheckExact(yf) #endif #ifdef __Pyx_Coroutine_USED || __Pyx_Coroutine_Check(yf) #endif ) { ret = __Pyx__Coroutine_Throw(yf, typ, val, tb, args, close_on_genexit); #ifdef __Pyx_Coroutine_USED } else if (__Pyx_CoroutineAwait_CheckExact(yf)) { ret = __Pyx__Coroutine_Throw(((__pyx_CoroutineAwaitObject*)yf)->coroutine, typ, val, tb, args, close_on_genexit); #endif } else { PyObject *meth = __Pyx_PyObject_GetAttrStrNoError(yf, PYIDENT("throw")); if (unlikely(!meth)) { Py_DECREF(yf); if (unlikely(PyErr_Occurred())) { gen->is_running = 0; return NULL; } __Pyx_Coroutine_Undelegate(gen); gen->is_running = 0; goto throw_here; } if (likely(args)) { ret = __Pyx_PyObject_Call(meth, args, NULL); } else { // "tb" or even "val" might be NULL, but that also correctly terminates the argument list PyObject *cargs[4] = {NULL, typ, val, tb}; ret = __Pyx_PyObject_FastCall(meth, cargs+1, 3 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET); } Py_DECREF(meth); } gen->is_running = 0; Py_DECREF(yf); if (!ret) { ret = __Pyx_Coroutine_FinishDelegation(gen); } return __Pyx_Coroutine_MethodReturn(self, ret); } throw_here: __Pyx_Raise(typ, val, tb, NULL); return __Pyx_Coroutine_MethodReturn(self, __Pyx_Coroutine_SendEx(gen, NULL, 0)); } static PyObject *__Pyx_Coroutine_Throw(PyObject *self, PyObject *args) { PyObject *typ; PyObject *val = NULL; PyObject *tb = NULL; if (unlikely(!PyArg_UnpackTuple(args, (char *)"throw", 1, 3, &typ, &val, &tb))) return NULL; return __Pyx__Coroutine_Throw(self, typ, val, tb, args, 1); } static CYTHON_INLINE int __Pyx_Coroutine_traverse_excstate(__Pyx_ExcInfoStruct *exc_state, visitproc visit, void *arg) { #if PY_VERSION_HEX >= 0x030B00a4 Py_VISIT(exc_state->exc_value); #else Py_VISIT(exc_state->exc_type); Py_VISIT(exc_state->exc_value); Py_VISIT(exc_state->exc_traceback); #endif return 0; } static int __Pyx_Coroutine_traverse(__pyx_CoroutineObject *gen, visitproc visit, void *arg) { Py_VISIT(gen->closure); Py_VISIT(gen->classobj); Py_VISIT(gen->yieldfrom); return __Pyx_Coroutine_traverse_excstate(&gen->gi_exc_state, visit, arg); } static int __Pyx_Coroutine_clear(PyObject *self) { __pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self; Py_CLEAR(gen->closure); Py_CLEAR(gen->classobj); Py_CLEAR(gen->yieldfrom); __Pyx_Coroutine_ExceptionClear(&gen->gi_exc_state); #ifdef __Pyx_AsyncGen_USED if (__Pyx_AsyncGen_CheckExact(self)) { Py_CLEAR(((__pyx_PyAsyncGenObject*)gen)->ag_finalizer); } #endif Py_CLEAR(gen->gi_code); Py_CLEAR(gen->gi_frame); Py_CLEAR(gen->gi_name); Py_CLEAR(gen->gi_qualname); Py_CLEAR(gen->gi_modulename); return 0; } static void __Pyx_Coroutine_dealloc(PyObject *self) { __pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self; PyObject_GC_UnTrack(gen); if (gen->gi_weakreflist != NULL) PyObject_ClearWeakRefs(self); if (gen->resume_label >= 0) { // Generator is paused or unstarted, so we need to close PyObject_GC_Track(self); #if PY_VERSION_HEX >= 0x030400a1 && CYTHON_USE_TP_FINALIZE if (unlikely(PyObject_CallFinalizerFromDealloc(self))) #else Py_TYPE(gen)->tp_del(self); if (unlikely(Py_REFCNT(self) > 0)) #endif { // resurrected. :( return; } PyObject_GC_UnTrack(self); } #ifdef __Pyx_AsyncGen_USED if (__Pyx_AsyncGen_CheckExact(self)) { /* We have to handle this case for asynchronous generators right here, because this code has to be between UNTRACK and GC_Del. */ Py_CLEAR(((__pyx_PyAsyncGenObject*)self)->ag_finalizer); } #endif __Pyx_Coroutine_clear(self); __Pyx_PyHeapTypeObject_GC_Del(gen); } static void __Pyx_Coroutine_del(PyObject *self) { PyObject *error_type, *error_value, *error_traceback; __pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self; __Pyx_PyThreadState_declare if (gen->resume_label < 0) { // already terminated => nothing to clean up return; } #if !CYTHON_USE_TP_FINALIZE // Temporarily resurrect the object. assert(self->ob_refcnt == 0); __Pyx_SET_REFCNT(self, 1); #endif __Pyx_PyThreadState_assign // Save the current exception, if any. __Pyx_ErrFetch(&error_type, &error_value, &error_traceback); #ifdef __Pyx_AsyncGen_USED if (__Pyx_AsyncGen_CheckExact(self)) { __pyx_PyAsyncGenObject *agen = (__pyx_PyAsyncGenObject*)self; PyObject *finalizer = agen->ag_finalizer; if (finalizer && !agen->ag_closed) { PyObject *res = __Pyx_PyObject_CallOneArg(finalizer, self); if (unlikely(!res)) { PyErr_WriteUnraisable(self); } else { Py_DECREF(res); } // Restore the saved exception. __Pyx_ErrRestore(error_type, error_value, error_traceback); return; } } #endif if (unlikely(gen->resume_label == 0 && !error_value)) { #ifdef __Pyx_Coroutine_USED #ifdef __Pyx_Generator_USED // only warn about (async) coroutines if (!__Pyx_Generator_CheckExact(self)) #endif { // untrack dead object as we are executing Python code (which might trigger GC) PyObject_GC_UnTrack(self); #if PY_MAJOR_VERSION >= 3 /* PY_VERSION_HEX >= 0x03030000*/ || defined(PyErr_WarnFormat) if (unlikely(PyErr_WarnFormat(PyExc_RuntimeWarning, 1, "coroutine '%.50S' was never awaited", gen->gi_qualname) < 0)) PyErr_WriteUnraisable(self); #else {PyObject *msg; char *cmsg; #if CYTHON_COMPILING_IN_PYPY msg = NULL; cmsg = (char*) "coroutine was never awaited"; #else char *cname; PyObject *qualname; qualname = gen->gi_qualname; cname = PyString_AS_STRING(qualname); msg = PyString_FromFormat("coroutine '%.50s' was never awaited", cname); if (unlikely(!msg)) { PyErr_Clear(); cmsg = (char*) "coroutine was never awaited"; } else { cmsg = PyString_AS_STRING(msg); } #endif if (unlikely(PyErr_WarnEx(PyExc_RuntimeWarning, cmsg, 1) < 0)) PyErr_WriteUnraisable(self); Py_XDECREF(msg);} #endif PyObject_GC_Track(self); } #endif /*__Pyx_Coroutine_USED*/ } else { PyObject *res = __Pyx_Coroutine_Close(self); if (unlikely(!res)) { if (PyErr_Occurred()) PyErr_WriteUnraisable(self); } else { Py_DECREF(res); } } // Restore the saved exception. __Pyx_ErrRestore(error_type, error_value, error_traceback); #if !CYTHON_USE_TP_FINALIZE // Undo the temporary resurrection; can't use DECREF here, it would // cause a recursive call. assert(Py_REFCNT(self) > 0); if (likely(--self->ob_refcnt == 0)) { // this is the normal path out return; } // close() resurrected it! Make it look like the original Py_DECREF // never happened. { Py_ssize_t refcnt = Py_REFCNT(self); _Py_NewReference(self); __Pyx_SET_REFCNT(self, refcnt); } #if CYTHON_COMPILING_IN_CPYTHON assert(PyType_IS_GC(Py_TYPE(self)) && _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED); // If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so // we need to undo that. _Py_DEC_REFTOTAL; #endif // If Py_TRACE_REFS, _Py_NewReference re-added self to the object // chain, so no more to do there. // If COUNT_ALLOCS, the original decref bumped tp_frees, and // _Py_NewReference bumped tp_allocs: both of those need to be // undone. #ifdef COUNT_ALLOCS --Py_TYPE(self)->tp_frees; --Py_TYPE(self)->tp_allocs; #endif #endif } static PyObject * __Pyx_Coroutine_get_name(__pyx_CoroutineObject *self, void *context) { PyObject *name = self->gi_name; CYTHON_UNUSED_VAR(context); // avoid NULL pointer dereference during garbage collection if (unlikely(!name)) name = Py_None; Py_INCREF(name); return name; } static int __Pyx_Coroutine_set_name(__pyx_CoroutineObject *self, PyObject *value, void *context) { CYTHON_UNUSED_VAR(context); #if PY_MAJOR_VERSION >= 3 if (unlikely(value == NULL || !PyUnicode_Check(value))) #else if (unlikely(value == NULL || !PyString_Check(value))) #endif { PyErr_SetString(PyExc_TypeError, "__name__ must be set to a string object"); return -1; } Py_INCREF(value); __Pyx_Py_XDECREF_SET(self->gi_name, value); return 0; } static PyObject * __Pyx_Coroutine_get_qualname(__pyx_CoroutineObject *self, void *context) { PyObject *name = self->gi_qualname; CYTHON_UNUSED_VAR(context); // avoid NULL pointer dereference during garbage collection if (unlikely(!name)) name = Py_None; Py_INCREF(name); return name; } static int __Pyx_Coroutine_set_qualname(__pyx_CoroutineObject *self, PyObject *value, void *context) { CYTHON_UNUSED_VAR(context); #if PY_MAJOR_VERSION >= 3 if (unlikely(value == NULL || !PyUnicode_Check(value))) #else if (unlikely(value == NULL || !PyString_Check(value))) #endif { PyErr_SetString(PyExc_TypeError, "__qualname__ must be set to a string object"); return -1; } Py_INCREF(value); __Pyx_Py_XDECREF_SET(self->gi_qualname, value); return 0; } static PyObject * __Pyx_Coroutine_get_frame(__pyx_CoroutineObject *self, void *context) { PyObject *frame = self->gi_frame; CYTHON_UNUSED_VAR(context); if (!frame) { if (unlikely(!self->gi_code)) { // Avoid doing something stupid, e.g. during garbage collection. Py_RETURN_NONE; } frame = (PyObject *) PyFrame_New( PyThreadState_Get(), /*PyThreadState *tstate,*/ (PyCodeObject*) self->gi_code, /*PyCodeObject *code,*/ $moddict_cname, /*PyObject *globals,*/ 0 /*PyObject *locals*/ ); if (unlikely(!frame)) return NULL; // keep the frame cached once it's created self->gi_frame = frame; } Py_INCREF(frame); return frame; } static __pyx_CoroutineObject *__Pyx__Coroutine_New( PyTypeObject* type, __pyx_coroutine_body_t body, PyObject *code, PyObject *closure, PyObject *name, PyObject *qualname, PyObject *module_name) { __pyx_CoroutineObject *gen = PyObject_GC_New(__pyx_CoroutineObject, type); if (unlikely(!gen)) return NULL; return __Pyx__Coroutine_NewInit(gen, body, code, closure, name, qualname, module_name); } static __pyx_CoroutineObject *__Pyx__Coroutine_NewInit( __pyx_CoroutineObject *gen, __pyx_coroutine_body_t body, PyObject *code, PyObject *closure, PyObject *name, PyObject *qualname, PyObject *module_name) { gen->body = body; gen->closure = closure; Py_XINCREF(closure); gen->is_running = 0; gen->resume_label = 0; gen->classobj = NULL; gen->yieldfrom = NULL; #if PY_VERSION_HEX >= 0x030B00a4 gen->gi_exc_state.exc_value = NULL; #else gen->gi_exc_state.exc_type = NULL; gen->gi_exc_state.exc_value = NULL; gen->gi_exc_state.exc_traceback = NULL; #endif #if CYTHON_USE_EXC_INFO_STACK gen->gi_exc_state.previous_item = NULL; #endif gen->gi_weakreflist = NULL; Py_XINCREF(qualname); gen->gi_qualname = qualname; Py_XINCREF(name); gen->gi_name = name; Py_XINCREF(module_name); gen->gi_modulename = module_name; Py_XINCREF(code); gen->gi_code = code; gen->gi_frame = NULL; PyObject_GC_Track(gen); return gen; } //////////////////// Coroutine //////////////////// //@requires: CoroutineBase //@requires: PatchGeneratorABC //@requires: ObjectHandling.c::PyObject_GenericGetAttrNoDict static void __Pyx_CoroutineAwait_dealloc(PyObject *self) { PyObject_GC_UnTrack(self); Py_CLEAR(((__pyx_CoroutineAwaitObject*)self)->coroutine); __Pyx_PyHeapTypeObject_GC_Del(self); } static int __Pyx_CoroutineAwait_traverse(__pyx_CoroutineAwaitObject *self, visitproc visit, void *arg) { Py_VISIT(self->coroutine); return 0; } static int __Pyx_CoroutineAwait_clear(__pyx_CoroutineAwaitObject *self) { Py_CLEAR(self->coroutine); return 0; } static PyObject *__Pyx_CoroutineAwait_Next(__pyx_CoroutineAwaitObject *self) { return __Pyx_Generator_Next(self->coroutine); } static PyObject *__Pyx_CoroutineAwait_Send(__pyx_CoroutineAwaitObject *self, PyObject *value) { return __Pyx_Coroutine_Send(self->coroutine, value); } static PyObject *__Pyx_CoroutineAwait_Throw(__pyx_CoroutineAwaitObject *self, PyObject *args) { return __Pyx_Coroutine_Throw(self->coroutine, args); } static PyObject *__Pyx_CoroutineAwait_Close(__pyx_CoroutineAwaitObject *self, PyObject *arg) { CYTHON_UNUSED_VAR(arg); return __Pyx_Coroutine_Close(self->coroutine); } static PyObject *__Pyx_CoroutineAwait_self(PyObject *self) { Py_INCREF(self); return self; } #if !CYTHON_COMPILING_IN_PYPY static PyObject *__Pyx_CoroutineAwait_no_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { CYTHON_UNUSED_VAR(type); CYTHON_UNUSED_VAR(args); CYTHON_UNUSED_VAR(kwargs); PyErr_SetString(PyExc_TypeError, "cannot instantiate type, use 'await coroutine' instead"); return NULL; } #endif // In earlier versions of Python an object with no __dict__ and not __slots__ is assumed // to be pickleable by default. Coroutine-wrappers have significant state so shouldn't be. // Therefore provide a default implementation. // Something similar applies to heaptypes (i.e. with type_specs) with protocols 0 and 1 // even in more recent versions. // We are applying this to all Python versions (hence the commented out version guard) // to make the behaviour explicit. // #if PY_VERSION_HEX < 0x03060000 || CYTHON_USE_TYPE_SPECS static PyObject *__Pyx_CoroutineAwait_reduce_ex(__pyx_CoroutineAwaitObject *self, PyObject *arg) { CYTHON_UNUSED_VAR(arg); PyErr_Format(PyExc_TypeError, "cannot pickle '%.200s' object", Py_TYPE(self)->tp_name); return NULL; } // #endif static PyMethodDef __pyx_CoroutineAwait_methods[] = { {"send", (PyCFunction) __Pyx_CoroutineAwait_Send, METH_O, (char*) PyDoc_STR("send(arg) -> send 'arg' into coroutine,\nreturn next yielded value or raise StopIteration.")}, {"throw", (PyCFunction) __Pyx_CoroutineAwait_Throw, METH_VARARGS, (char*) PyDoc_STR("throw(typ[,val[,tb]]) -> raise exception in coroutine,\nreturn next yielded value or raise StopIteration.")}, {"close", (PyCFunction) __Pyx_CoroutineAwait_Close, METH_NOARGS, (char*) PyDoc_STR("close() -> raise GeneratorExit inside coroutine.")}, // only needed with type-specs or version<3.6, but included in all versions for clarity // #if PY_VERSION_HEX < 0x03060000 || CYTHON_USE_TYPE_SPECS {"__reduce_ex__", (PyCFunction) __Pyx_CoroutineAwait_reduce_ex, METH_O, 0}, {"__reduce__", (PyCFunction) __Pyx_CoroutineAwait_reduce_ex, METH_NOARGS, 0}, // #endif {0, 0, 0, 0} }; #if CYTHON_USE_TYPE_SPECS static PyType_Slot __pyx_CoroutineAwaitType_slots[] = { {Py_tp_dealloc, (void *)__Pyx_CoroutineAwait_dealloc}, {Py_tp_traverse, (void *)__Pyx_CoroutineAwait_traverse}, {Py_tp_clear, (void *)__Pyx_CoroutineAwait_clear}, #if !CYTHON_COMPILING_IN_PYPY {Py_tp_new, (void *)__Pyx_CoroutineAwait_no_new}, #endif {Py_tp_methods, (void *)__pyx_CoroutineAwait_methods}, {Py_tp_iter, (void *)__Pyx_CoroutineAwait_self}, {Py_tp_iternext, (void *)__Pyx_CoroutineAwait_Next}, {0, 0}, }; static PyType_Spec __pyx_CoroutineAwaitType_spec = { __PYX_TYPE_MODULE_PREFIX "coroutine_wrapper", sizeof(__pyx_CoroutineAwaitObject), 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ __pyx_CoroutineAwaitType_slots }; #else /* CYTHON_USE_TYPE_SPECS */ static PyTypeObject __pyx_CoroutineAwaitType_type = { PyVarObject_HEAD_INIT(0, 0) __PYX_TYPE_MODULE_PREFIX "coroutine_wrapper", /*tp_name*/ sizeof(__pyx_CoroutineAwaitObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor) __Pyx_CoroutineAwait_dealloc,/*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_as_async resp. tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ PyDoc_STR("A wrapper object implementing __await__ for coroutines."), /*tp_doc*/ (traverseproc) __Pyx_CoroutineAwait_traverse, /*tp_traverse*/ (inquiry) __Pyx_CoroutineAwait_clear, /*tp_clear*/ 0, /*tp_richcompare*/ 0, /*tp_weaklistoffset*/ __Pyx_CoroutineAwait_self, /*tp_iter*/ (iternextfunc) __Pyx_CoroutineAwait_Next, /*tp_iternext*/ __pyx_CoroutineAwait_methods, /*tp_methods*/ 0 , /*tp_members*/ 0 , /*tp_getset*/ 0, /*tp_base*/ 0, /*tp_dict*/ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ 0, /*tp_dictoffset*/ 0, /*tp_init*/ 0, /*tp_alloc*/ #if !CYTHON_COMPILING_IN_PYPY __Pyx_CoroutineAwait_no_new, /*tp_new*/ #else 0, /*tp_new*/ #endif 0, /*tp_free*/ 0, /*tp_is_gc*/ 0, /*tp_bases*/ 0, /*tp_mro*/ 0, /*tp_cache*/ 0, /*tp_subclasses*/ 0, /*tp_weaklist*/ 0, /*tp_del*/ 0, /*tp_version_tag*/ #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if __PYX_NEED_TP_PRINT_SLOT 0, /*tp_print*/ #endif #if PY_VERSION_HEX >= 0x030C0000 0, /*tp_watched*/ #endif #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000 0, /*tp_pypy_flags*/ #endif }; #endif /* CYTHON_USE_TYPE_SPECS */ #if PY_VERSION_HEX < 0x030500B1 || defined(__Pyx_IterableCoroutine_USED) || CYTHON_USE_ASYNC_SLOTS static CYTHON_INLINE PyObject *__Pyx__Coroutine_await(PyObject *coroutine) { __pyx_CoroutineAwaitObject *await = PyObject_GC_New(__pyx_CoroutineAwaitObject, __pyx_CoroutineAwaitType); if (unlikely(!await)) return NULL; Py_INCREF(coroutine); await->coroutine = coroutine; PyObject_GC_Track(await); return (PyObject*)await; } #endif #if PY_VERSION_HEX < 0x030500B1 static PyObject *__Pyx_Coroutine_await_method(PyObject *coroutine, PyObject *arg) { CYTHON_UNUSED_VAR(arg); return __Pyx__Coroutine_await(coroutine); } #endif #if defined(__Pyx_IterableCoroutine_USED) || CYTHON_USE_ASYNC_SLOTS static PyObject *__Pyx_Coroutine_await(PyObject *coroutine) { if (unlikely(!coroutine || !__Pyx_Coroutine_Check(coroutine))) { PyErr_SetString(PyExc_TypeError, "invalid input, expected coroutine"); return NULL; } return __Pyx__Coroutine_await(coroutine); } #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3 && PY_VERSION_HEX < 0x030500B1 static PyObject *__Pyx_Coroutine_compare(PyObject *obj, PyObject *other, int op) { PyObject* result; switch (op) { case Py_EQ: result = (other == obj) ? Py_True : Py_False; break; case Py_NE: result = (other != obj) ? Py_True : Py_False; break; default: result = Py_NotImplemented; } Py_INCREF(result); return result; } #endif static PyMethodDef __pyx_Coroutine_methods[] = { {"send", (PyCFunction) __Pyx_Coroutine_Send, METH_O, (char*) PyDoc_STR("send(arg) -> send 'arg' into coroutine,\nreturn next iterated value or raise StopIteration.")}, {"throw", (PyCFunction) __Pyx_Coroutine_Throw, METH_VARARGS, (char*) PyDoc_STR("throw(typ[,val[,tb]]) -> raise exception in coroutine,\nreturn next iterated value or raise StopIteration.")}, {"close", (PyCFunction) __Pyx_Coroutine_Close_Method, METH_NOARGS, (char*) PyDoc_STR("close() -> raise GeneratorExit inside coroutine.")}, #if PY_VERSION_HEX < 0x030500B1 {"__await__", (PyCFunction) __Pyx_Coroutine_await_method, METH_NOARGS, (char*) PyDoc_STR("__await__() -> return an iterator to be used in await expression.")}, #endif {0, 0, 0, 0} }; static PyMemberDef __pyx_Coroutine_memberlist[] = { {(char *) "cr_running", T_BOOL, offsetof(__pyx_CoroutineObject, is_running), READONLY, NULL}, {(char*) "cr_await", T_OBJECT, offsetof(__pyx_CoroutineObject, yieldfrom), READONLY, (char*) PyDoc_STR("object being awaited, or None")}, {(char*) "cr_code", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_code), READONLY, NULL}, {(char *) "__module__", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_modulename), 0, 0}, #if CYTHON_USE_TYPE_SPECS {(char *) "__weaklistoffset__", T_PYSSIZET, offsetof(__pyx_CoroutineObject, gi_weakreflist), READONLY, 0}, #endif {0, 0, 0, 0, 0} }; static PyGetSetDef __pyx_Coroutine_getsets[] = { {(char *) "__name__", (getter)__Pyx_Coroutine_get_name, (setter)__Pyx_Coroutine_set_name, (char*) PyDoc_STR("name of the coroutine"), 0}, {(char *) "__qualname__", (getter)__Pyx_Coroutine_get_qualname, (setter)__Pyx_Coroutine_set_qualname, (char*) PyDoc_STR("qualified name of the coroutine"), 0}, {(char *) "cr_frame", (getter)__Pyx_Coroutine_get_frame, NULL, (char*) PyDoc_STR("Frame of the coroutine"), 0}, {0, 0, 0, 0, 0} }; #if CYTHON_USE_TYPE_SPECS static PyType_Slot __pyx_CoroutineType_slots[] = { {Py_tp_dealloc, (void *)__Pyx_Coroutine_dealloc}, {Py_am_await, (void *)&__Pyx_Coroutine_await}, {Py_tp_traverse, (void *)__Pyx_Coroutine_traverse}, {Py_tp_methods, (void *)__pyx_Coroutine_methods}, {Py_tp_members, (void *)__pyx_Coroutine_memberlist}, {Py_tp_getset, (void *)__pyx_Coroutine_getsets}, {Py_tp_getattro, (void *) __Pyx_PyObject_GenericGetAttrNoDict}, #if CYTHON_USE_TP_FINALIZE {Py_tp_finalize, (void *)__Pyx_Coroutine_del}, #endif {0, 0}, }; static PyType_Spec __pyx_CoroutineType_spec = { __PYX_TYPE_MODULE_PREFIX "coroutine", sizeof(__pyx_CoroutineObject), 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ __pyx_CoroutineType_slots }; #else /* CYTHON_USE_TYPE_SPECS */ #if CYTHON_USE_ASYNC_SLOTS static __Pyx_PyAsyncMethodsStruct __pyx_Coroutine_as_async = { __Pyx_Coroutine_await, /*am_await*/ 0, /*am_aiter*/ 0, /*am_anext*/ #if PY_VERSION_HEX >= 0x030A00A3 0, /*am_send*/ #endif }; #endif static PyTypeObject __pyx_CoroutineType_type = { PyVarObject_HEAD_INIT(0, 0) __PYX_TYPE_MODULE_PREFIX "coroutine", /*tp_name*/ sizeof(__pyx_CoroutineObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor) __Pyx_Coroutine_dealloc,/*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ #if CYTHON_USE_ASYNC_SLOTS &__pyx_Coroutine_as_async, /*tp_as_async (tp_reserved) - Py3 only! */ #else 0, /*tp_reserved*/ #endif 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ 0, /*tp_doc*/ (traverseproc) __Pyx_Coroutine_traverse, /*tp_traverse*/ 0, /*tp_clear*/ #if CYTHON_USE_ASYNC_SLOTS && CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3 && PY_VERSION_HEX < 0x030500B1 // in order to (mis-)use tp_reserved above, we must also implement tp_richcompare __Pyx_Coroutine_compare, /*tp_richcompare*/ #else 0, /*tp_richcompare*/ #endif offsetof(__pyx_CoroutineObject, gi_weakreflist), /*tp_weaklistoffset*/ // no tp_iter() as iterator is only available through __await__() 0, /*tp_iter*/ 0, /*tp_iternext*/ __pyx_Coroutine_methods, /*tp_methods*/ __pyx_Coroutine_memberlist, /*tp_members*/ __pyx_Coroutine_getsets, /*tp_getset*/ 0, /*tp_base*/ 0, /*tp_dict*/ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ 0, /*tp_dictoffset*/ 0, /*tp_init*/ 0, /*tp_alloc*/ 0, /*tp_new*/ 0, /*tp_free*/ 0, /*tp_is_gc*/ 0, /*tp_bases*/ 0, /*tp_mro*/ 0, /*tp_cache*/ 0, /*tp_subclasses*/ 0, /*tp_weaklist*/ #if CYTHON_USE_TP_FINALIZE 0, /*tp_del*/ #else __Pyx_Coroutine_del, /*tp_del*/ #endif 0, /*tp_version_tag*/ #if CYTHON_USE_TP_FINALIZE __Pyx_Coroutine_del, /*tp_finalize*/ #elif PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if __PYX_NEED_TP_PRINT_SLOT 0, /*tp_print*/ #endif #if PY_VERSION_HEX >= 0x030C0000 0, /*tp_watched*/ #endif #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000 0, /*tp_pypy_flags*/ #endif }; #endif /* CYTHON_USE_TYPE_SPECS */ static int __pyx_Coroutine_init(PyObject *module) { CYTHON_MAYBE_UNUSED_VAR(module); // on Windows, C-API functions can't be used in slots statically #if CYTHON_USE_TYPE_SPECS __pyx_CoroutineType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_CoroutineType_spec, NULL); #else __pyx_CoroutineType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict; __pyx_CoroutineType = __Pyx_FetchCommonType(&__pyx_CoroutineType_type); #endif if (unlikely(!__pyx_CoroutineType)) return -1; #ifdef __Pyx_IterableCoroutine_USED if (unlikely(__pyx_IterableCoroutine_init(module) == -1)) return -1; #endif #if CYTHON_USE_TYPE_SPECS __pyx_CoroutineAwaitType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_CoroutineAwaitType_spec, NULL); #else __pyx_CoroutineAwaitType = __Pyx_FetchCommonType(&__pyx_CoroutineAwaitType_type); #endif if (unlikely(!__pyx_CoroutineAwaitType)) return -1; return 0; } //////////////////// IterableCoroutine.proto //////////////////// #define __Pyx_IterableCoroutine_USED #undef __Pyx_Coroutine_Check #define __Pyx_Coroutine_Check(obj) (__Pyx_Coroutine_CheckExact(obj) || __Pyx_IS_TYPE(obj, __pyx_IterableCoroutineType)) #define __Pyx_IterableCoroutine_New(body, code, closure, name, qualname, module_name) \ __Pyx__Coroutine_New(__pyx_IterableCoroutineType, body, code, closure, name, qualname, module_name) static int __pyx_IterableCoroutine_init(PyObject *module);/*proto*/ //////////////////// IterableCoroutine //////////////////// //@requires: Coroutine //@requires: CommonStructures.c::FetchCommonType #if CYTHON_USE_TYPE_SPECS static PyType_Slot __pyx_IterableCoroutineType_slots[] = { {Py_tp_dealloc, (void *)__Pyx_Coroutine_dealloc}, {Py_am_await, (void *)&__Pyx_Coroutine_await}, {Py_tp_traverse, (void *)__Pyx_Coroutine_traverse}, {Py_tp_iter, (void *)__Pyx_Coroutine_await}, {Py_tp_iternext, (void *)__Pyx_Generator_Next}, {Py_tp_methods, (void *)__pyx_Coroutine_methods}, {Py_tp_members, (void *)__pyx_Coroutine_memberlist}, {Py_tp_getset, (void *)__pyx_Coroutine_getsets}, {Py_tp_getattro, (void *) __Pyx_PyObject_GenericGetAttrNoDict}, #if CYTHON_USE_TP_FINALIZE {Py_tp_finalize, (void *)__Pyx_Coroutine_del}, #endif {0, 0}, }; static PyType_Spec __pyx_IterableCoroutineType_spec = { __PYX_TYPE_MODULE_PREFIX "iterable_coroutine", sizeof(__pyx_CoroutineObject), 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ __pyx_IterableCoroutineType_slots }; #else /* CYTHON_USE_TYPE_SPECS */ static PyTypeObject __pyx_IterableCoroutineType_type = { PyVarObject_HEAD_INIT(0, 0) __PYX_TYPE_MODULE_PREFIX "iterable_coroutine", /*tp_name*/ sizeof(__pyx_CoroutineObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor) __Pyx_Coroutine_dealloc,/*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ #if CYTHON_USE_ASYNC_SLOTS &__pyx_Coroutine_as_async, /*tp_as_async (tp_reserved) - Py3 only! */ #else 0, /*tp_reserved*/ #endif 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ 0, /*tp_doc*/ (traverseproc) __Pyx_Coroutine_traverse, /*tp_traverse*/ 0, /*tp_clear*/ #if CYTHON_USE_ASYNC_SLOTS && CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3 && PY_VERSION_HEX < 0x030500B1 // in order to (mis-)use tp_reserved above, we must also implement tp_richcompare __Pyx_Coroutine_compare, /*tp_richcompare*/ #else 0, /*tp_richcompare*/ #endif offsetof(__pyx_CoroutineObject, gi_weakreflist), /*tp_weaklistoffset*/ // enable iteration for legacy support of asyncio yield-from protocol __Pyx_Coroutine_await, /*tp_iter*/ (iternextfunc) __Pyx_Generator_Next, /*tp_iternext*/ __pyx_Coroutine_methods, /*tp_methods*/ __pyx_Coroutine_memberlist, /*tp_members*/ __pyx_Coroutine_getsets, /*tp_getset*/ 0, /*tp_base*/ 0, /*tp_dict*/ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ 0, /*tp_dictoffset*/ 0, /*tp_init*/ 0, /*tp_alloc*/ 0, /*tp_new*/ 0, /*tp_free*/ 0, /*tp_is_gc*/ 0, /*tp_bases*/ 0, /*tp_mro*/ 0, /*tp_cache*/ 0, /*tp_subclasses*/ 0, /*tp_weaklist*/ #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_del*/ #else __Pyx_Coroutine_del, /*tp_del*/ #endif 0, /*tp_version_tag*/ #if PY_VERSION_HEX >= 0x030400a1 && !CYTHON_COMPILING_IN_PYPY __Pyx_Coroutine_del, /*tp_finalize*/ #endif #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if __PYX_NEED_TP_PRINT_SLOT 0, /*tp_print*/ #endif #if PY_VERSION_HEX >= 0x030C0000 0, /*tp_watched*/ #endif #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000 0, /*tp_pypy_flags*/ #endif }; #endif /* CYTHON_USE_TYPE_SPECS */ static int __pyx_IterableCoroutine_init(PyObject *module) { #if CYTHON_USE_TYPE_SPECS __pyx_IterableCoroutineType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_IterableCoroutineType_spec, NULL); #else CYTHON_UNUSED_VAR(module); __pyx_IterableCoroutineType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict; __pyx_IterableCoroutineType = __Pyx_FetchCommonType(&__pyx_IterableCoroutineType_type); #endif if (unlikely(!__pyx_IterableCoroutineType)) return -1; return 0; } //////////////////// Generator //////////////////// //@requires: CoroutineBase //@requires: PatchGeneratorABC //@requires: ObjectHandling.c::PyObject_GenericGetAttrNoDict static PyMethodDef __pyx_Generator_methods[] = { {"send", (PyCFunction) __Pyx_Coroutine_Send, METH_O, (char*) PyDoc_STR("send(arg) -> send 'arg' into generator,\nreturn next yielded value or raise StopIteration.")}, {"throw", (PyCFunction) __Pyx_Coroutine_Throw, METH_VARARGS, (char*) PyDoc_STR("throw(typ[,val[,tb]]) -> raise exception in generator,\nreturn next yielded value or raise StopIteration.")}, {"close", (PyCFunction) __Pyx_Coroutine_Close_Method, METH_NOARGS, (char*) PyDoc_STR("close() -> raise GeneratorExit inside generator.")}, {0, 0, 0, 0} }; static PyMemberDef __pyx_Generator_memberlist[] = { {(char *) "gi_running", T_BOOL, offsetof(__pyx_CoroutineObject, is_running), READONLY, NULL}, {(char*) "gi_yieldfrom", T_OBJECT, offsetof(__pyx_CoroutineObject, yieldfrom), READONLY, (char*) PyDoc_STR("object being iterated by 'yield from', or None")}, {(char*) "gi_code", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_code), READONLY, NULL}, {(char *) "__module__", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_modulename), 0, 0}, #if CYTHON_USE_TYPE_SPECS {(char *) "__weaklistoffset__", T_PYSSIZET, offsetof(__pyx_CoroutineObject, gi_weakreflist), READONLY, 0}, #endif {0, 0, 0, 0, 0} }; static PyGetSetDef __pyx_Generator_getsets[] = { {(char *) "__name__", (getter)__Pyx_Coroutine_get_name, (setter)__Pyx_Coroutine_set_name, (char*) PyDoc_STR("name of the generator"), 0}, {(char *) "__qualname__", (getter)__Pyx_Coroutine_get_qualname, (setter)__Pyx_Coroutine_set_qualname, (char*) PyDoc_STR("qualified name of the generator"), 0}, {(char *) "gi_frame", (getter)__Pyx_Coroutine_get_frame, NULL, (char*) PyDoc_STR("Frame of the generator"), 0}, {0, 0, 0, 0, 0} }; #if CYTHON_USE_TYPE_SPECS static PyType_Slot __pyx_GeneratorType_slots[] = { {Py_tp_dealloc, (void *)__Pyx_Coroutine_dealloc}, {Py_tp_traverse, (void *)__Pyx_Coroutine_traverse}, {Py_tp_iter, (void *)PyObject_SelfIter}, {Py_tp_iternext, (void *)__Pyx_Generator_Next}, {Py_tp_methods, (void *)__pyx_Generator_methods}, {Py_tp_members, (void *)__pyx_Generator_memberlist}, {Py_tp_getset, (void *)__pyx_Generator_getsets}, {Py_tp_getattro, (void *) __Pyx_PyObject_GenericGetAttrNoDict}, #if CYTHON_USE_TP_FINALIZE {Py_tp_finalize, (void *)__Pyx_Coroutine_del}, #endif {0, 0}, }; static PyType_Spec __pyx_GeneratorType_spec = { __PYX_TYPE_MODULE_PREFIX "generator", sizeof(__pyx_CoroutineObject), 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ __pyx_GeneratorType_slots }; #else /* CYTHON_USE_TYPE_SPECS */ static PyTypeObject __pyx_GeneratorType_type = { PyVarObject_HEAD_INIT(0, 0) __PYX_TYPE_MODULE_PREFIX "generator", /*tp_name*/ sizeof(__pyx_CoroutineObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor) __Pyx_Coroutine_dealloc,/*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_as_async*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ 0, /*tp_doc*/ (traverseproc) __Pyx_Coroutine_traverse, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ offsetof(__pyx_CoroutineObject, gi_weakreflist), /*tp_weaklistoffset*/ 0, /*tp_iter*/ (iternextfunc) __Pyx_Generator_Next, /*tp_iternext*/ __pyx_Generator_methods, /*tp_methods*/ __pyx_Generator_memberlist, /*tp_members*/ __pyx_Generator_getsets, /*tp_getset*/ 0, /*tp_base*/ 0, /*tp_dict*/ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ 0, /*tp_dictoffset*/ 0, /*tp_init*/ 0, /*tp_alloc*/ 0, /*tp_new*/ 0, /*tp_free*/ 0, /*tp_is_gc*/ 0, /*tp_bases*/ 0, /*tp_mro*/ 0, /*tp_cache*/ 0, /*tp_subclasses*/ 0, /*tp_weaklist*/ #if CYTHON_USE_TP_FINALIZE 0, /*tp_del*/ #else __Pyx_Coroutine_del, /*tp_del*/ #endif 0, /*tp_version_tag*/ #if CYTHON_USE_TP_FINALIZE __Pyx_Coroutine_del, /*tp_finalize*/ #elif PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if __PYX_NEED_TP_PRINT_SLOT 0, /*tp_print*/ #endif #if PY_VERSION_HEX >= 0x030C0000 0, /*tp_watched*/ #endif #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000 0, /*tp_pypy_flags*/ #endif }; #endif /* CYTHON_USE_TYPE_SPECS */ static int __pyx_Generator_init(PyObject *module) { #if CYTHON_USE_TYPE_SPECS __pyx_GeneratorType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_GeneratorType_spec, NULL); #else CYTHON_UNUSED_VAR(module); // on Windows, C-API functions can't be used in slots statically __pyx_GeneratorType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict; __pyx_GeneratorType_type.tp_iter = PyObject_SelfIter; __pyx_GeneratorType = __Pyx_FetchCommonType(&__pyx_GeneratorType_type); #endif if (unlikely(!__pyx_GeneratorType)) { return -1; } return 0; } /////////////// ReturnWithStopIteration.proto /////////////// #define __Pyx_ReturnWithStopIteration(value) \ if (value == Py_None) PyErr_SetNone(PyExc_StopIteration); else __Pyx__ReturnWithStopIteration(value) static void __Pyx__ReturnWithStopIteration(PyObject* value); /*proto*/ /////////////// ReturnWithStopIteration /////////////// //@requires: Exceptions.c::PyErrFetchRestore //@requires: Exceptions.c::PyThreadStateGet //@substitute: naming // 1) Instantiating an exception just to pass back a value is costly. // 2) CPython 3.12 cannot separate exception type and value // 3) Passing a tuple as value into PyErr_SetObject() passes its items on as arguments. // 4) Passing an exception as value will interpret it as an exception on unpacking and raise it (or unpack its value). // 5) If there is currently an exception being handled, we need to chain it. static void __Pyx__ReturnWithStopIteration(PyObject* value) { PyObject *exc, *args; #if CYTHON_COMPILING_IN_CPYTHON __Pyx_PyThreadState_declare if (PY_VERSION_HEX >= 0x030C00A6 || unlikely(PyTuple_Check(value) || PyExceptionInstance_Check(value))) { args = PyTuple_New(1); if (unlikely(!args)) return; Py_INCREF(value); PyTuple_SET_ITEM(args, 0, value); exc = PyType_Type.tp_call(PyExc_StopIteration, args, NULL); Py_DECREF(args); if (!exc) return; } else { // it's safe to avoid instantiating the exception Py_INCREF(value); exc = value; } #if CYTHON_FAST_THREAD_STATE __Pyx_PyThreadState_assign #if CYTHON_USE_EXC_INFO_STACK if (!$local_tstate_cname->exc_info->exc_value) #else if (!$local_tstate_cname->exc_type) #endif { // no chaining needed => avoid the overhead in PyErr_SetObject() Py_INCREF(PyExc_StopIteration); __Pyx_ErrRestore(PyExc_StopIteration, exc, NULL); return; } #endif #else args = PyTuple_Pack(1, value); if (unlikely(!args)) return; exc = PyObject_Call(PyExc_StopIteration, args, NULL); Py_DECREF(args); if (unlikely(!exc)) return; #endif PyErr_SetObject(PyExc_StopIteration, exc); Py_DECREF(exc); } //////////////////// PatchModuleWithCoroutine.proto //////////////////// static PyObject* __Pyx_Coroutine_patch_module(PyObject* module, const char* py_code); /*proto*/ //////////////////// PatchModuleWithCoroutine //////////////////// //@substitute: naming static PyObject* __Pyx_Coroutine_patch_module(PyObject* module, const char* py_code) { #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) int result; PyObject *globals, *result_obj; globals = PyDict_New(); if (unlikely(!globals)) goto ignore; result = PyDict_SetItemString(globals, "_cython_coroutine_type", #ifdef __Pyx_Coroutine_USED (PyObject*)__pyx_CoroutineType); #else Py_None); #endif if (unlikely(result < 0)) goto ignore; result = PyDict_SetItemString(globals, "_cython_generator_type", #ifdef __Pyx_Generator_USED (PyObject*)__pyx_GeneratorType); #else Py_None); #endif if (unlikely(result < 0)) goto ignore; if (unlikely(PyDict_SetItemString(globals, "_module", module) < 0)) goto ignore; if (unlikely(PyDict_SetItemString(globals, "__builtins__", $builtins_cname) < 0)) goto ignore; result_obj = PyRun_String(py_code, Py_file_input, globals, globals); if (unlikely(!result_obj)) goto ignore; Py_DECREF(result_obj); Py_DECREF(globals); return module; ignore: Py_XDECREF(globals); PyErr_WriteUnraisable(module); if (unlikely(PyErr_WarnEx(PyExc_RuntimeWarning, "Cython module failed to patch module with custom type", 1) < 0)) { Py_DECREF(module); module = NULL; } #else // avoid "unused" warning py_code++; #endif return module; } //////////////////// PatchGeneratorABC.proto //////////////////// // register with Generator/Coroutine ABCs in 'collections.abc' // see https://bugs.python.org/issue24018 static int __Pyx_patch_abc(void); /*proto*/ //////////////////// PatchGeneratorABC //////////////////// //@requires: PatchModuleWithCoroutine #ifndef CYTHON_REGISTER_ABCS #define CYTHON_REGISTER_ABCS 1 #endif #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) static PyObject* __Pyx_patch_abc_module(PyObject *module); /*proto*/ static PyObject* __Pyx_patch_abc_module(PyObject *module) { module = __Pyx_Coroutine_patch_module( module, CSTRING("""\ if _cython_generator_type is not None: try: Generator = _module.Generator except AttributeError: pass else: Generator.register(_cython_generator_type) if _cython_coroutine_type is not None: try: Coroutine = _module.Coroutine except AttributeError: pass else: Coroutine.register(_cython_coroutine_type) """) ); return module; } #endif static int __Pyx_patch_abc(void) { #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) static int abc_patched = 0; if (CYTHON_REGISTER_ABCS && !abc_patched) { PyObject *module; module = PyImport_ImportModule((PY_MAJOR_VERSION >= 3) ? "collections.abc" : "collections"); if (unlikely(!module)) { PyErr_WriteUnraisable(NULL); if (unlikely(PyErr_WarnEx(PyExc_RuntimeWarning, ((PY_MAJOR_VERSION >= 3) ? "Cython module failed to register with collections.abc module" : "Cython module failed to register with collections module"), 1) < 0)) { return -1; } } else { module = __Pyx_patch_abc_module(module); abc_patched = 1; if (unlikely(!module)) return -1; Py_DECREF(module); } // also register with "backports_abc" module if available, just in case module = PyImport_ImportModule("backports_abc"); if (module) { module = __Pyx_patch_abc_module(module); Py_XDECREF(module); } if (!module) { PyErr_Clear(); } } #else // avoid "unused" warning for __Pyx_Coroutine_patch_module() if ((0)) __Pyx_Coroutine_patch_module(NULL, NULL); #endif return 0; } //////////////////// PatchAsyncIO.proto //////////////////// // run after importing "asyncio" to patch Cython generator support into it static PyObject* __Pyx_patch_asyncio(PyObject* module); /*proto*/ //////////////////// PatchAsyncIO //////////////////// //@requires: ImportExport.c::Import //@requires: PatchModuleWithCoroutine //@requires: PatchInspect static PyObject* __Pyx_patch_asyncio(PyObject* module) { #if PY_VERSION_HEX < 0x030500B2 && \ (defined(__Pyx_Coroutine_USED) || defined(__Pyx_Generator_USED)) && \ (!defined(CYTHON_PATCH_ASYNCIO) || CYTHON_PATCH_ASYNCIO) PyObject *patch_module = NULL; static int asyncio_patched = 0; if (unlikely((!asyncio_patched) && module)) { PyObject *package; package = __Pyx_Import(PYIDENT("asyncio.coroutines"), NULL, 0); if (package) { patch_module = __Pyx_Coroutine_patch_module( PyObject_GetAttrString(package, "coroutines"), CSTRING("""\ try: coro_types = _module._COROUTINE_TYPES except AttributeError: pass else: if _cython_coroutine_type is not None and _cython_coroutine_type not in coro_types: coro_types = tuple(coro_types) + (_cython_coroutine_type,) if _cython_generator_type is not None and _cython_generator_type not in coro_types: coro_types = tuple(coro_types) + (_cython_generator_type,) _module._COROUTINE_TYPES = coro_types """) ); } else { PyErr_Clear(); // Always enable fallback: even if we compile against 3.4.2, we might be running on 3.4.1 at some point. //#if PY_VERSION_HEX < 0x03040200 // Py3.4.1 used to have asyncio.tasks instead of asyncio.coroutines package = __Pyx_Import(PYIDENT("asyncio.tasks"), NULL, 0); if (unlikely(!package)) goto asyncio_done; patch_module = __Pyx_Coroutine_patch_module( PyObject_GetAttrString(package, "tasks"), CSTRING("""\ if hasattr(_module, 'iscoroutine'): old_types = getattr(_module.iscoroutine, '_cython_coroutine_types', None) if old_types is None or not isinstance(old_types, set): old_types = set() def cy_wrap(orig_func, type=type, cython_coroutine_types=old_types): def cy_iscoroutine(obj): return type(obj) in cython_coroutine_types or orig_func(obj) cy_iscoroutine._cython_coroutine_types = cython_coroutine_types return cy_iscoroutine _module.iscoroutine = cy_wrap(_module.iscoroutine) if _cython_coroutine_type is not None: old_types.add(_cython_coroutine_type) if _cython_generator_type is not None: old_types.add(_cython_generator_type) """) ); //#endif // Py < 0x03040200 } Py_DECREF(package); if (unlikely(!patch_module)) goto ignore; //#if PY_VERSION_HEX < 0x03040200 asyncio_done: PyErr_Clear(); //#endif asyncio_patched = 1; #ifdef __Pyx_Generator_USED // now patch inspect.isgenerator() by looking up the imported module in the patched asyncio module { PyObject *inspect_module; if (patch_module) { inspect_module = PyObject_GetAttr(patch_module, PYIDENT("inspect")); Py_DECREF(patch_module); } else { inspect_module = __Pyx_Import(PYIDENT("inspect"), NULL, 0); } if (unlikely(!inspect_module)) goto ignore; inspect_module = __Pyx_patch_inspect(inspect_module); if (unlikely(!inspect_module)) { Py_DECREF(module); module = NULL; } Py_XDECREF(inspect_module); } #else // avoid "unused" warning for __Pyx_patch_inspect() if ((0)) return __Pyx_patch_inspect(module); #endif } return module; ignore: PyErr_WriteUnraisable(module); if (unlikely(PyErr_WarnEx(PyExc_RuntimeWarning, "Cython module failed to patch asyncio package with custom generator type", 1) < 0)) { Py_DECREF(module); module = NULL; } #else // avoid "unused" warning for __Pyx_Coroutine_patch_module() if ((0)) return __Pyx_patch_inspect(__Pyx_Coroutine_patch_module(module, NULL)); #endif return module; } //////////////////// PatchInspect.proto //////////////////// // run after importing "inspect" to patch Cython generator support into it static PyObject* __Pyx_patch_inspect(PyObject* module); /*proto*/ //////////////////// PatchInspect //////////////////// //@requires: PatchModuleWithCoroutine static PyObject* __Pyx_patch_inspect(PyObject* module) { #if defined(__Pyx_Generator_USED) && (!defined(CYTHON_PATCH_INSPECT) || CYTHON_PATCH_INSPECT) static int inspect_patched = 0; if (unlikely((!inspect_patched) && module)) { module = __Pyx_Coroutine_patch_module( module, CSTRING("""\ old_types = getattr(_module.isgenerator, '_cython_generator_types', None) if old_types is None or not isinstance(old_types, set): old_types = set() def cy_wrap(orig_func, type=type, cython_generator_types=old_types): def cy_isgenerator(obj): return type(obj) in cython_generator_types or orig_func(obj) cy_isgenerator._cython_generator_types = cython_generator_types return cy_isgenerator _module.isgenerator = cy_wrap(_module.isgenerator) old_types.add(_cython_generator_type) """) ); inspect_patched = 1; } #else // avoid "unused" warning for __Pyx_Coroutine_patch_module() if ((0)) return __Pyx_Coroutine_patch_module(module, NULL); #endif return module; } //////////////////// StopAsyncIteration.proto //////////////////// #define __Pyx_StopAsyncIteration_USED static PyObject *__Pyx_PyExc_StopAsyncIteration; static int __pyx_StopAsyncIteration_init(PyObject *module); /*proto*/ //////////////////// StopAsyncIteration //////////////////// #if PY_VERSION_HEX < 0x030500B1 #if CYTHON_USE_TYPE_SPECS #error Using async coroutines with type specs requires Python 3.5 or later. #else static PyTypeObject __Pyx__PyExc_StopAsyncIteration_type = { PyVarObject_HEAD_INIT(0, 0) "StopAsyncIteration", /*tp_name*/ sizeof(PyBaseExceptionObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ 0, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare / reserved*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ PyDoc_STR("Signal the end from iterator.__anext__()."), /*tp_doc*/ 0, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ 0, /*tp_weaklistoffset*/ 0, /*tp_iter*/ 0, /*tp_iternext*/ 0, /*tp_methods*/ 0, /*tp_members*/ 0, /*tp_getset*/ 0, /*tp_base*/ 0, /*tp_dict*/ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ 0, /*tp_dictoffset*/ 0, /*tp_init*/ 0, /*tp_alloc*/ 0, /*tp_new*/ 0, /*tp_free*/ 0, /*tp_is_gc*/ 0, /*tp_bases*/ 0, /*tp_mro*/ 0, /*tp_cache*/ 0, /*tp_subclasses*/ 0, /*tp_weaklist*/ 0, /*tp_del*/ 0, /*tp_version_tag*/ #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif #if CYTHON_COMPILING_IN_PYPY && PYPY_VERSION_NUM+0 >= 0x06000000 0, /*tp_pypy_flags*/ #endif }; #endif #endif static int __pyx_StopAsyncIteration_init(PyObject *module) { CYTHON_UNUSED_VAR(module); #if PY_VERSION_HEX >= 0x030500B1 __Pyx_PyExc_StopAsyncIteration = PyExc_StopAsyncIteration; #else PyObject *builtins = PyEval_GetBuiltins(); if (likely(builtins)) { PyObject *exc = PyMapping_GetItemString(builtins, (char*) "StopAsyncIteration"); if (exc) { __Pyx_PyExc_StopAsyncIteration = exc; return 0; } } PyErr_Clear(); __Pyx__PyExc_StopAsyncIteration_type.tp_traverse = ((PyTypeObject*)PyExc_BaseException)->tp_traverse; __Pyx__PyExc_StopAsyncIteration_type.tp_clear = ((PyTypeObject*)PyExc_BaseException)->tp_clear; __Pyx__PyExc_StopAsyncIteration_type.tp_dictoffset = ((PyTypeObject*)PyExc_BaseException)->tp_dictoffset; __Pyx__PyExc_StopAsyncIteration_type.tp_base = (PyTypeObject*)PyExc_Exception; __Pyx_PyExc_StopAsyncIteration = (PyObject*) __Pyx_FetchCommonType(&__Pyx__PyExc_StopAsyncIteration_type); if (unlikely(!__Pyx_PyExc_StopAsyncIteration)) return -1; if (likely(builtins) && unlikely(PyMapping_SetItemString(builtins, (char*) "StopAsyncIteration", __Pyx_PyExc_StopAsyncIteration) < 0)) return -1; #endif return 0; } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Utility/CpdefEnums.pyx0000644000175100001770000001260700000000000021304 0ustar00runnerdocker00000000000000#################### EnumBase #################### cimport cython cdef extern from *: int PY_VERSION_HEX cdef object __Pyx_OrderedDict if PY_VERSION_HEX >= 0x03060000: __Pyx_OrderedDict = dict else: from collections import OrderedDict as __Pyx_OrderedDict @cython.internal cdef class __Pyx_EnumMeta(type): def __init__(cls, name, parents, dct): type.__init__(cls, name, parents, dct) cls.__members__ = __Pyx_OrderedDict() def __iter__(cls): return iter(cls.__members__.values()) def __getitem__(cls, name): return cls.__members__[name] # @cython.internal cdef object __Pyx_EnumBase class __Pyx_EnumBase(int, metaclass=__Pyx_EnumMeta): def __new__(cls, value, name=None): for v in cls: if v == value: return v if name is None: raise ValueError("Unknown enum value: '%s'" % value) res = int.__new__(cls, value) res.name = name setattr(cls, name, res) cls.__members__[name] = res return res def __repr__(self): return "<%s.%s: %d>" % (self.__class__.__name__, self.name, self) def __str__(self): return "%s.%s" % (self.__class__.__name__, self.name) if PY_VERSION_HEX >= 0x03040000: from enum import IntEnum as __Pyx_EnumBase cdef object __Pyx_FlagBase class __Pyx_FlagBase(int, metaclass=__Pyx_EnumMeta): def __new__(cls, value, name=None): for v in cls: if v == value: return v res = int.__new__(cls, value) if name is None: # some bitwise combination, no validation here res.name = "" else: res.name = name setattr(cls, name, res) cls.__members__[name] = res return res def __repr__(self): return "<%s.%s: %d>" % (self.__class__.__name__, self.name, self) def __str__(self): return "%s.%s" % (self.__class__.__name__, self.name) if PY_VERSION_HEX >= 0x03060000: from enum import IntFlag as __Pyx_FlagBase #################### EnumType #################### #@requires: EnumBase cdef extern from *: object {{enum_to_pyint_func}}({{name}} value) cdef dict __Pyx_globals = globals() if PY_VERSION_HEX >= 0x03060000: # create new IntFlag() - the assumption is that C enums are sufficiently commonly # used as flags that this is the most appropriate base class {{name}} = __Pyx_FlagBase('{{name}}', [ {{for item in items}} ('{{item}}', {{enum_to_pyint_func}}({{item}})), {{endfor}} # Try to look up the module name dynamically if possible ], module=__Pyx_globals.get("__module__", '{{static_modname}}')) if PY_VERSION_HEX >= 0x030B0000: # Python 3.11 starts making the behaviour of flags stricter # (only including powers of 2 when iterating). Since we're using # "flag" because C enums *might* be used as flags, not because # we want strict flag behaviour, manually undo some of this. {{name}}._member_names_ = list({{name}}.__members__) {{if enum_doc is not None}} {{name}}.__doc__ = {{ repr(enum_doc) }} {{endif}} {{for item in items}} __Pyx_globals['{{item}}'] = {{name}}.{{item}} {{endfor}} else: class {{name}}(__Pyx_FlagBase): {{ repr(enum_doc) if enum_doc is not None else 'pass' }} {{for item in items}} __Pyx_globals['{{item}}'] = {{name}}({{enum_to_pyint_func}}({{item}}), '{{item}}') {{endfor}} #################### CppScopedEnumType #################### #@requires: EnumBase cdef dict __Pyx_globals = globals() if PY_VERSION_HEX >= 0x03040000: __Pyx_globals["{{name}}"] = __Pyx_EnumBase('{{name}}', [ {{for item in items}} ('{{item}}', <{{underlying_type}}>({{name}}.{{item}})), {{endfor}} ], module=__Pyx_globals.get("__module__", '{{static_modname}}')) else: __Pyx_globals["{{name}}"] = type('{{name}}', (__Pyx_EnumBase,), {}) {{for item in items}} __Pyx_globals["{{name}}"](<{{underlying_type}}>({{name}}.{{item}}), '{{item}}') {{endfor}} {{if enum_doc is not None}} __Pyx_globals["{{name}}"].__doc__ = {{ repr(enum_doc) }} {{endif}} #################### EnumTypeToPy #################### @cname("{{funcname}}") cdef {{funcname}}({{name}} c_val): cdef object __pyx_enum # There's a complication here: the Python enum wrapping is only generated # for enums defined in the same module that they're used in. Therefore, if # the enum was cimported from a different module, we try to import it. # If that fails we return an int equivalent as the next best option. {{if module_name}} try: from {{module_name}} import {{name}} as __pyx_enum except ImportError: import warnings warnings.warn( f"enum class {{name}} not importable from {{module_name}}. " "You are probably using a cpdef enum declared in a .pxd file that " "does not have a .py or .pyx file.") return <{{underlying_type}}>c_val {{else}} __pyx_enum = {{name}} {{endif}} # TODO - Cython only manages to optimize C enums to a switch currently if 0: pass {{for item in items}} elif c_val == {{name}}.{{item}}: return __pyx_enum.{{item}} {{endfor}} else: underlying_c_val = <{{underlying_type}}>c_val {{if is_flag}} return __pyx_enum(underlying_c_val) {{else}} raise ValueError(f"{underlying_c_val} is not a valid {{name}}") {{endif}} ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Utility/CppConvert.pyx0000644000175100001770000001561600000000000021341 0ustar00runnerdocker00000000000000# TODO: Figure out how many of the pass-by-value copies the compiler can eliminate. #################### string.from_py #################### cdef extern from *: cdef cppclass string "{{type}}": string() except + string(char* c_str, size_t size) except + cdef const char* __Pyx_PyObject_AsStringAndSize(object, Py_ssize_t*) except NULL @cname("{{cname}}") cdef string {{cname}}(object o) except *: cdef Py_ssize_t length = 0 cdef const char* data = __Pyx_PyObject_AsStringAndSize(o, &length) return string(data, length) #################### string.to_py #################### #cimport cython #from libcpp.string cimport string cdef extern from *: cdef cppclass string "{{type}}": char* data() size_t size() {{for py_type in ['PyObject', 'PyUnicode', 'PyStr', 'PyBytes', 'PyByteArray']}} cdef extern from *: cdef object __Pyx_{{py_type}}_FromStringAndSize(const char*, size_t) @cname("{{cname.replace("PyObject", py_type, 1)}}") cdef inline object {{cname.replace("PyObject", py_type, 1)}}(const string& s): return __Pyx_{{py_type}}_FromStringAndSize(s.data(), s.size()) {{endfor}} #################### vector.from_py #################### cdef extern from *: cdef cppclass vector "std::vector" [T]: void push_back(T&) except + @cname("{{cname}}") cdef vector[X] {{cname}}(object o) except *: cdef vector[X] v for item in o: v.push_back(item) return v #################### vector.to_py #################### cdef extern from *: cdef cppclass vector "std::vector" [T]: size_t size() T& operator[](size_t) cdef extern from "Python.h": void Py_INCREF(object) list PyList_New(Py_ssize_t size) void PyList_SET_ITEM(object list, Py_ssize_t i, object o) const Py_ssize_t PY_SSIZE_T_MAX @cname("{{cname}}") cdef object {{cname}}(const vector[X]& v): if v.size() > PY_SSIZE_T_MAX: raise MemoryError() v_size_signed = v.size() o = PyList_New(v_size_signed) cdef Py_ssize_t i cdef object item for i in range(v_size_signed): item = v[i] Py_INCREF(item) PyList_SET_ITEM(o, i, item) return o #################### list.from_py #################### cdef extern from *: cdef cppclass cpp_list "std::list" [T]: void push_back(T&) except + @cname("{{cname}}") cdef cpp_list[X] {{cname}}(object o) except *: cdef cpp_list[X] l for item in o: l.push_back(item) return l #################### list.to_py #################### cimport cython cdef extern from *: cdef cppclass cpp_list "std::list" [T]: cppclass const_iterator: T& operator*() const_iterator operator++() bint operator!=(const_iterator) const_iterator begin() const_iterator end() size_t size() cdef extern from "Python.h": void Py_INCREF(object) list PyList_New(Py_ssize_t size) void PyList_SET_ITEM(object list, Py_ssize_t i, object o) cdef Py_ssize_t PY_SSIZE_T_MAX @cname("{{cname}}") cdef object {{cname}}(const cpp_list[X]& v): if v.size() > PY_SSIZE_T_MAX: raise MemoryError() o = PyList_New( v.size()) cdef object item cdef Py_ssize_t i = 0 cdef cpp_list[X].const_iterator iter = v.begin() while iter != v.end(): item = cython.operator.dereference(iter) Py_INCREF(item) PyList_SET_ITEM(o, i, item) cython.operator.preincrement(iter) i += 1 return o #################### set.from_py #################### cdef extern from *: cdef cppclass set "std::{{maybe_unordered}}set" [T]: void insert(T&) except + @cname("{{cname}}") cdef set[X] {{cname}}(object o) except *: cdef set[X] s for item in o: s.insert(item) return s #################### set.to_py #################### cimport cython cdef extern from *: cdef cppclass cpp_set "std::{{maybe_unordered}}set" [T]: cppclass const_iterator: T& operator*() const_iterator operator++() bint operator!=(const_iterator) const_iterator begin() const_iterator end() @cname("{{cname}}") cdef object {{cname}}(const cpp_set[X]& s): return {v for v in s} #################### pair.from_py #################### cdef extern from *: cdef cppclass pair "std::pair" [T, U]: pair() except + pair(T&, U&) except + @cname("{{cname}}") cdef pair[X,Y] {{cname}}(object o) except *: x, y = o return pair[X,Y](x, y) #################### pair.to_py #################### cdef extern from *: cdef cppclass pair "std::pair" [T, U]: T first U second @cname("{{cname}}") cdef object {{cname}}(const pair[X,Y]& p): return p.first, p.second #################### map.from_py #################### cdef extern from *: cdef cppclass pair "std::pair" [T, U]: pair(T&, U&) except + cdef cppclass map "std::{{maybe_unordered}}map" [T, U]: void insert(pair[T, U]&) except + cdef cppclass vector "std::vector" [T]: pass int PY_MAJOR_VERSION @cname("{{cname}}") cdef map[X,Y] {{cname}}(object o) except *: cdef map[X,Y] m if PY_MAJOR_VERSION < 3: for key, value in o.iteritems(): m.insert(pair[X,Y](key, value)) else: for key, value in o.items(): m.insert(pair[X,Y](key, value)) return m #################### map.to_py #################### # TODO: Work out const so that this can take a const # reference rather than pass by value. cimport cython cdef extern from *: cdef cppclass map "std::{{maybe_unordered}}map" [T, U]: cppclass value_type: T first U second cppclass const_iterator: value_type& operator*() const_iterator operator++() bint operator!=(const_iterator) const_iterator begin() const_iterator end() @cname("{{cname}}") cdef object {{cname}}(const map[X,Y]& s): o = {} cdef const map[X,Y].value_type *key_value cdef map[X,Y].const_iterator iter = s.begin() while iter != s.end(): key_value = &cython.operator.dereference(iter) o[key_value.first] = key_value.second cython.operator.preincrement(iter) return o #################### complex.from_py #################### cdef extern from *: cdef cppclass std_complex "std::complex" [T]: std_complex() std_complex(T, T) except + @cname("{{cname}}") cdef std_complex[X] {{cname}}(object o) except *: cdef double complex z = o return std_complex[X](z.real, z.imag) #################### complex.to_py #################### cdef extern from *: cdef cppclass std_complex "std::complex" [T]: X real() X imag() @cname("{{cname}}") cdef object {{cname}}(const std_complex[X]& z): cdef double complex tmp tmp.real = z.real() tmp.imag = z.imag() return tmp ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3327222 Cython-3.0.8/Cython/Utility/CppSupport.cpp0000644000175100001770000001150600000000000021331 0ustar00runnerdocker00000000000000/////////////// CppExceptionConversion.proto /////////////// #ifndef __Pyx_CppExn2PyErr #include #include #include #include static void __Pyx_CppExn2PyErr() { // Catch a handful of different errors here and turn them into the // equivalent Python errors. try { if (PyErr_Occurred()) ; // let the latest Python exn pass through and ignore the current one else throw; } catch (const std::bad_alloc& exn) { PyErr_SetString(PyExc_MemoryError, exn.what()); } catch (const std::bad_cast& exn) { PyErr_SetString(PyExc_TypeError, exn.what()); } catch (const std::bad_typeid& exn) { PyErr_SetString(PyExc_TypeError, exn.what()); } catch (const std::domain_error& exn) { PyErr_SetString(PyExc_ValueError, exn.what()); } catch (const std::invalid_argument& exn) { PyErr_SetString(PyExc_ValueError, exn.what()); } catch (const std::ios_base::failure& exn) { // Unfortunately, in standard C++ we have no way of distinguishing EOF // from other errors here; be careful with the exception mask PyErr_SetString(PyExc_IOError, exn.what()); } catch (const std::out_of_range& exn) { // Change out_of_range to IndexError PyErr_SetString(PyExc_IndexError, exn.what()); } catch (const std::overflow_error& exn) { PyErr_SetString(PyExc_OverflowError, exn.what()); } catch (const std::range_error& exn) { PyErr_SetString(PyExc_ArithmeticError, exn.what()); } catch (const std::underflow_error& exn) { PyErr_SetString(PyExc_ArithmeticError, exn.what()); } catch (const std::exception& exn) { PyErr_SetString(PyExc_RuntimeError, exn.what()); } catch (...) { PyErr_SetString(PyExc_RuntimeError, "Unknown exception"); } } #endif /////////////// PythranConversion.proto /////////////// template auto __Pyx_pythran_to_python(T &&value) -> decltype(to_python( typename pythonic::returnable::type>::type>::type{std::forward(value)})) { using returnable_type = typename pythonic::returnable::type>::type>::type; return to_python(returnable_type{std::forward(value)}); } #define __Pyx_PythranShapeAccessor(x) (pythonic::builtins::getattr(pythonic::types::attr::SHAPE{}, x)) ////////////// MoveIfSupported.proto ////////////////// #if CYTHON_USE_CPP_STD_MOVE #include #define __PYX_STD_MOVE_IF_SUPPORTED(x) std::move(x) #else #define __PYX_STD_MOVE_IF_SUPPORTED(x) x #endif ////////////// EnumClassDecl.proto ////////////////// //@proto_block: utility_code_proto_before_types #if defined (_MSC_VER) #if _MSC_VER >= 1910 #define __PYX_ENUM_CLASS_DECL enum #else #define __PYX_ENUM_CLASS_DECL #endif #else #define __PYX_ENUM_CLASS_DECL enum #endif ////////////// OptionalLocals.proto //////////////// //@proto_block: utility_code_proto_before_types #include #if defined(CYTHON_USE_BOOST_OPTIONAL) // fallback mode - std::optional is preferred but this gives // people with a less up-to-date compiler a chance #include #define __Pyx_Optional_BaseType boost::optional #else #include // since std::optional is a C++17 features, a templated using declaration should be safe // (although it could be replaced with a define) template using __Pyx_Optional_BaseType = std::optional; #endif // This class reuses as much of the implementation of std::optional as possible. // The only place it differs significantly is the assignment operators, which use // "emplace" (thus requiring move/copy constructors, but not move/copy // assignment operators). This is preferred because it lets us work with assignable // types (for example those with const members) template class __Pyx_Optional_Type : private __Pyx_Optional_BaseType { public: using __Pyx_Optional_BaseType::__Pyx_Optional_BaseType; using __Pyx_Optional_BaseType::has_value; using __Pyx_Optional_BaseType::operator*; using __Pyx_Optional_BaseType::operator->; #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600) __Pyx_Optional_Type& operator=(const __Pyx_Optional_Type& rhs) { this->emplace(*rhs); return *this; } __Pyx_Optional_Type& operator=(__Pyx_Optional_Type&& rhs) { this->emplace(std::move(*rhs)); return *this; } template __Pyx_Optional_Type& operator=(U&& rhs) { this->emplace(std::forward(rhs)); return *this; } #else // Note - the "cpp_locals" feature is designed to require C++14. // This pre-c++11 fallback is largely untested, and definitely won't work // in all the cases that the more modern version does using __Pyx_Optional_BaseType::operator=; // the chances are emplace can't work... #endif }; ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/CythonFunction.c0000644000175100001770000017504500000000000021635 0ustar00runnerdocker00000000000000 //////////////////// CythonFunctionShared.proto //////////////////// #define __Pyx_CyFunction_USED #define __Pyx_CYFUNCTION_STATICMETHOD 0x01 #define __Pyx_CYFUNCTION_CLASSMETHOD 0x02 #define __Pyx_CYFUNCTION_CCLASS 0x04 #define __Pyx_CYFUNCTION_COROUTINE 0x08 #define __Pyx_CyFunction_GetClosure(f) \ (((__pyx_CyFunctionObject *) (f))->func_closure) #if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API #define __Pyx_CyFunction_GetClassObj(f) \ (((__pyx_CyFunctionObject *) (f))->func_classobj) #else #define __Pyx_CyFunction_GetClassObj(f) \ ((PyObject*) ((PyCMethodObject *) (f))->mm_class) #endif #define __Pyx_CyFunction_SetClassObj(f, classobj) \ __Pyx__CyFunction_SetClassObj((__pyx_CyFunctionObject *) (f), (classobj)) #define __Pyx_CyFunction_Defaults(type, f) \ ((type *)(((__pyx_CyFunctionObject *) (f))->defaults)) #define __Pyx_CyFunction_SetDefaultsGetter(f, g) \ ((__pyx_CyFunctionObject *) (f))->defaults_getter = (g) typedef struct { #if CYTHON_COMPILING_IN_LIMITED_API PyObject_HEAD // We can't "inherit" from func, but we can use it as a data store PyObject *func; #elif PY_VERSION_HEX < 0x030900B1 PyCFunctionObject func; #else // PEP-573: PyCFunctionObject + mm_class PyCMethodObject func; #endif #if CYTHON_BACKPORT_VECTORCALL __pyx_vectorcallfunc func_vectorcall; #endif #if PY_VERSION_HEX < 0x030500A0 || CYTHON_COMPILING_IN_LIMITED_API PyObject *func_weakreflist; #endif PyObject *func_dict; PyObject *func_name; PyObject *func_qualname; PyObject *func_doc; PyObject *func_globals; PyObject *func_code; PyObject *func_closure; #if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API // No-args super() class cell PyObject *func_classobj; #endif // Dynamic default args and annotations void *defaults; int defaults_pyobjects; size_t defaults_size; /* used by FusedFunction for copying defaults */ int flags; // Defaults info PyObject *defaults_tuple; /* Const defaults tuple */ PyObject *defaults_kwdict; /* Const kwonly defaults dict */ PyObject *(*defaults_getter)(PyObject *); PyObject *func_annotations; /* function annotations dict */ // Coroutine marker PyObject *func_is_coroutine; } __pyx_CyFunctionObject; #undef __Pyx_CyOrPyCFunction_Check #define __Pyx_CyFunction_Check(obj) __Pyx_TypeCheck(obj, __pyx_CyFunctionType) #define __Pyx_CyOrPyCFunction_Check(obj) __Pyx_TypeCheck2(obj, __pyx_CyFunctionType, &PyCFunction_Type) #define __Pyx_CyFunction_CheckExact(obj) __Pyx_IS_TYPE(obj, __pyx_CyFunctionType) static CYTHON_INLINE int __Pyx__IsSameCyOrCFunction(PyObject *func, void *cfunc);/*proto*/ #undef __Pyx_IsSameCFunction #define __Pyx_IsSameCFunction(func, cfunc) __Pyx__IsSameCyOrCFunction(func, cfunc) static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject* op, PyMethodDef *ml, int flags, PyObject* qualname, PyObject *closure, PyObject *module, PyObject *globals, PyObject* code); static CYTHON_INLINE void __Pyx__CyFunction_SetClassObj(__pyx_CyFunctionObject* f, PyObject* classobj); static CYTHON_INLINE void *__Pyx_CyFunction_InitDefaults(PyObject *m, size_t size, int pyobjects); static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsTuple(PyObject *m, PyObject *tuple); static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsKwDict(PyObject *m, PyObject *dict); static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *m, PyObject *dict); static int __pyx_CyFunction_init(PyObject *module); #if CYTHON_METH_FASTCALL static PyObject * __Pyx_CyFunction_Vectorcall_NOARGS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); static PyObject * __Pyx_CyFunction_Vectorcall_O(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); #if CYTHON_BACKPORT_VECTORCALL #define __Pyx_CyFunction_func_vectorcall(f) (((__pyx_CyFunctionObject*)f)->func_vectorcall) #else #define __Pyx_CyFunction_func_vectorcall(f) (((PyCFunctionObject*)f)->vectorcall) #endif #endif //////////////////// CythonFunctionShared //////////////////// //@substitute: naming //@requires: CommonStructures.c::FetchCommonType //@requires: ObjectHandling.c::PyMethodNew //@requires: ObjectHandling.c::PyVectorcallFastCallDict //@requires: ModuleSetupCode.c::IncludeStructmemberH //@requires: ObjectHandling.c::PyObjectGetAttrStr #if CYTHON_COMPILING_IN_LIMITED_API static CYTHON_INLINE int __Pyx__IsSameCyOrCFunction(PyObject *func, void *cfunc) { if (__Pyx_CyFunction_Check(func)) { return PyCFunction_GetFunction(((__pyx_CyFunctionObject*)func)->func) == (PyCFunction) cfunc; } else if (PyCFunction_Check(func)) { return PyCFunction_GetFunction(func) == (PyCFunction) cfunc; } return 0; } #else static CYTHON_INLINE int __Pyx__IsSameCyOrCFunction(PyObject *func, void *cfunc) { return __Pyx_CyOrPyCFunction_Check(func) && __Pyx_CyOrPyCFunction_GET_FUNCTION(func) == (PyCFunction) cfunc; } #endif static CYTHON_INLINE void __Pyx__CyFunction_SetClassObj(__pyx_CyFunctionObject* f, PyObject* classobj) { #if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API __Pyx_Py_XDECREF_SET( __Pyx_CyFunction_GetClassObj(f), ((classobj) ? __Pyx_NewRef(classobj) : NULL)); #else __Pyx_Py_XDECREF_SET( // assigning to "mm_class", which is a "PyTypeObject*" ((PyCMethodObject *) (f))->mm_class, (PyTypeObject*)((classobj) ? __Pyx_NewRef(classobj) : NULL)); #endif } static PyObject * __Pyx_CyFunction_get_doc(__pyx_CyFunctionObject *op, void *closure) { CYTHON_UNUSED_VAR(closure); if (unlikely(op->func_doc == NULL)) { #if CYTHON_COMPILING_IN_LIMITED_API op->func_doc = PyObject_GetAttrString(op->func, "__doc__"); if (unlikely(!op->func_doc)) return NULL; #else if (((PyCFunctionObject*)op)->m_ml->ml_doc) { #if PY_MAJOR_VERSION >= 3 op->func_doc = PyUnicode_FromString(((PyCFunctionObject*)op)->m_ml->ml_doc); #else op->func_doc = PyString_FromString(((PyCFunctionObject*)op)->m_ml->ml_doc); #endif if (unlikely(op->func_doc == NULL)) return NULL; } else { Py_INCREF(Py_None); return Py_None; } #endif /* CYTHON_COMPILING_IN_LIMITED_API */ } Py_INCREF(op->func_doc); return op->func_doc; } static int __Pyx_CyFunction_set_doc(__pyx_CyFunctionObject *op, PyObject *value, void *context) { CYTHON_UNUSED_VAR(context); if (value == NULL) { // Mark as deleted value = Py_None; } Py_INCREF(value); __Pyx_Py_XDECREF_SET(op->func_doc, value); return 0; } static PyObject * __Pyx_CyFunction_get_name(__pyx_CyFunctionObject *op, void *context) { CYTHON_UNUSED_VAR(context); if (unlikely(op->func_name == NULL)) { #if CYTHON_COMPILING_IN_LIMITED_API op->func_name = PyObject_GetAttrString(op->func, "__name__"); #elif PY_MAJOR_VERSION >= 3 op->func_name = PyUnicode_InternFromString(((PyCFunctionObject*)op)->m_ml->ml_name); #else op->func_name = PyString_InternFromString(((PyCFunctionObject*)op)->m_ml->ml_name); #endif /* CYTHON_COMPILING_IN_LIMITED_API */ if (unlikely(op->func_name == NULL)) return NULL; } Py_INCREF(op->func_name); return op->func_name; } static int __Pyx_CyFunction_set_name(__pyx_CyFunctionObject *op, PyObject *value, void *context) { CYTHON_UNUSED_VAR(context); #if PY_MAJOR_VERSION >= 3 if (unlikely(value == NULL || !PyUnicode_Check(value))) #else if (unlikely(value == NULL || !PyString_Check(value))) #endif { PyErr_SetString(PyExc_TypeError, "__name__ must be set to a string object"); return -1; } Py_INCREF(value); __Pyx_Py_XDECREF_SET(op->func_name, value); return 0; } static PyObject * __Pyx_CyFunction_get_qualname(__pyx_CyFunctionObject *op, void *context) { CYTHON_UNUSED_VAR(context); Py_INCREF(op->func_qualname); return op->func_qualname; } static int __Pyx_CyFunction_set_qualname(__pyx_CyFunctionObject *op, PyObject *value, void *context) { CYTHON_UNUSED_VAR(context); #if PY_MAJOR_VERSION >= 3 if (unlikely(value == NULL || !PyUnicode_Check(value))) #else if (unlikely(value == NULL || !PyString_Check(value))) #endif { PyErr_SetString(PyExc_TypeError, "__qualname__ must be set to a string object"); return -1; } Py_INCREF(value); __Pyx_Py_XDECREF_SET(op->func_qualname, value); return 0; } static PyObject * __Pyx_CyFunction_get_dict(__pyx_CyFunctionObject *op, void *context) { CYTHON_UNUSED_VAR(context); if (unlikely(op->func_dict == NULL)) { op->func_dict = PyDict_New(); if (unlikely(op->func_dict == NULL)) return NULL; } Py_INCREF(op->func_dict); return op->func_dict; } static int __Pyx_CyFunction_set_dict(__pyx_CyFunctionObject *op, PyObject *value, void *context) { CYTHON_UNUSED_VAR(context); if (unlikely(value == NULL)) { PyErr_SetString(PyExc_TypeError, "function's dictionary may not be deleted"); return -1; } if (unlikely(!PyDict_Check(value))) { PyErr_SetString(PyExc_TypeError, "setting function's dictionary to a non-dict"); return -1; } Py_INCREF(value); __Pyx_Py_XDECREF_SET(op->func_dict, value); return 0; } static PyObject * __Pyx_CyFunction_get_globals(__pyx_CyFunctionObject *op, void *context) { CYTHON_UNUSED_VAR(context); Py_INCREF(op->func_globals); return op->func_globals; } static PyObject * __Pyx_CyFunction_get_closure(__pyx_CyFunctionObject *op, void *context) { CYTHON_UNUSED_VAR(op); CYTHON_UNUSED_VAR(context); Py_INCREF(Py_None); return Py_None; } static PyObject * __Pyx_CyFunction_get_code(__pyx_CyFunctionObject *op, void *context) { PyObject* result = (op->func_code) ? op->func_code : Py_None; CYTHON_UNUSED_VAR(context); Py_INCREF(result); return result; } static int __Pyx_CyFunction_init_defaults(__pyx_CyFunctionObject *op) { int result = 0; PyObject *res = op->defaults_getter((PyObject *) op); if (unlikely(!res)) return -1; // Cache result #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS op->defaults_tuple = PyTuple_GET_ITEM(res, 0); Py_INCREF(op->defaults_tuple); op->defaults_kwdict = PyTuple_GET_ITEM(res, 1); Py_INCREF(op->defaults_kwdict); #else op->defaults_tuple = __Pyx_PySequence_ITEM(res, 0); if (unlikely(!op->defaults_tuple)) result = -1; else { op->defaults_kwdict = __Pyx_PySequence_ITEM(res, 1); if (unlikely(!op->defaults_kwdict)) result = -1; } #endif Py_DECREF(res); return result; } static int __Pyx_CyFunction_set_defaults(__pyx_CyFunctionObject *op, PyObject* value, void *context) { CYTHON_UNUSED_VAR(context); if (!value) { // del => explicit None to prevent rebuilding value = Py_None; } else if (unlikely(value != Py_None && !PyTuple_Check(value))) { PyErr_SetString(PyExc_TypeError, "__defaults__ must be set to a tuple object"); return -1; } PyErr_WarnEx(PyExc_RuntimeWarning, "changes to cyfunction.__defaults__ will not " "currently affect the values used in function calls", 1); Py_INCREF(value); __Pyx_Py_XDECREF_SET(op->defaults_tuple, value); return 0; } static PyObject * __Pyx_CyFunction_get_defaults(__pyx_CyFunctionObject *op, void *context) { PyObject* result = op->defaults_tuple; CYTHON_UNUSED_VAR(context); if (unlikely(!result)) { if (op->defaults_getter) { if (unlikely(__Pyx_CyFunction_init_defaults(op) < 0)) return NULL; result = op->defaults_tuple; } else { result = Py_None; } } Py_INCREF(result); return result; } static int __Pyx_CyFunction_set_kwdefaults(__pyx_CyFunctionObject *op, PyObject* value, void *context) { CYTHON_UNUSED_VAR(context); if (!value) { // del => explicit None to prevent rebuilding value = Py_None; } else if (unlikely(value != Py_None && !PyDict_Check(value))) { PyErr_SetString(PyExc_TypeError, "__kwdefaults__ must be set to a dict object"); return -1; } PyErr_WarnEx(PyExc_RuntimeWarning, "changes to cyfunction.__kwdefaults__ will not " "currently affect the values used in function calls", 1); Py_INCREF(value); __Pyx_Py_XDECREF_SET(op->defaults_kwdict, value); return 0; } static PyObject * __Pyx_CyFunction_get_kwdefaults(__pyx_CyFunctionObject *op, void *context) { PyObject* result = op->defaults_kwdict; CYTHON_UNUSED_VAR(context); if (unlikely(!result)) { if (op->defaults_getter) { if (unlikely(__Pyx_CyFunction_init_defaults(op) < 0)) return NULL; result = op->defaults_kwdict; } else { result = Py_None; } } Py_INCREF(result); return result; } static int __Pyx_CyFunction_set_annotations(__pyx_CyFunctionObject *op, PyObject* value, void *context) { CYTHON_UNUSED_VAR(context); if (!value || value == Py_None) { value = NULL; } else if (unlikely(!PyDict_Check(value))) { PyErr_SetString(PyExc_TypeError, "__annotations__ must be set to a dict object"); return -1; } Py_XINCREF(value); __Pyx_Py_XDECREF_SET(op->func_annotations, value); return 0; } static PyObject * __Pyx_CyFunction_get_annotations(__pyx_CyFunctionObject *op, void *context) { PyObject* result = op->func_annotations; CYTHON_UNUSED_VAR(context); if (unlikely(!result)) { result = PyDict_New(); if (unlikely(!result)) return NULL; op->func_annotations = result; } Py_INCREF(result); return result; } static PyObject * __Pyx_CyFunction_get_is_coroutine(__pyx_CyFunctionObject *op, void *context) { int is_coroutine; CYTHON_UNUSED_VAR(context); if (op->func_is_coroutine) { return __Pyx_NewRef(op->func_is_coroutine); } is_coroutine = op->flags & __Pyx_CYFUNCTION_COROUTINE; #if PY_VERSION_HEX >= 0x03050000 if (is_coroutine) { PyObject *module, *fromlist, *marker = PYIDENT("_is_coroutine"); fromlist = PyList_New(1); if (unlikely(!fromlist)) return NULL; Py_INCREF(marker); #if CYTHON_ASSUME_SAFE_MACROS PyList_SET_ITEM(fromlist, 0, marker); #else if (unlikely(PyList_SetItem(fromlist, 0, marker) < 0)) { Py_DECREF(marker); Py_DECREF(fromlist); return NULL; } #endif module = PyImport_ImportModuleLevelObject(PYIDENT("asyncio.coroutines"), NULL, NULL, fromlist, 0); Py_DECREF(fromlist); if (unlikely(!module)) goto ignore; op->func_is_coroutine = __Pyx_PyObject_GetAttrStr(module, marker); Py_DECREF(module); if (likely(op->func_is_coroutine)) { return __Pyx_NewRef(op->func_is_coroutine); } ignore: PyErr_Clear(); } #endif op->func_is_coroutine = __Pyx_PyBool_FromLong(is_coroutine); return __Pyx_NewRef(op->func_is_coroutine); } //#if PY_VERSION_HEX >= 0x030400C1 //static PyObject * //__Pyx_CyFunction_get_signature(__pyx_CyFunctionObject *op, void *context) { // PyObject *inspect_module, *signature_class, *signature; // CYTHON_UNUSED_VAR(context); // // from inspect import Signature // inspect_module = PyImport_ImportModuleLevelObject(PYIDENT("inspect"), NULL, NULL, NULL, 0); // if (unlikely(!inspect_module)) // goto bad; // signature_class = __Pyx_PyObject_GetAttrStr(inspect_module, PYIDENT("Signature")); // Py_DECREF(inspect_module); // if (unlikely(!signature_class)) // goto bad; // // return Signature.from_function(op) // signature = PyObject_CallMethodObjArgs(signature_class, PYIDENT("from_function"), op, NULL); // Py_DECREF(signature_class); // if (likely(signature)) // return signature; //bad: // // make sure we raise an AttributeError from this property on any errors // if (!PyErr_ExceptionMatches(PyExc_AttributeError)) // PyErr_SetString(PyExc_AttributeError, "failed to calculate __signature__"); // return NULL; //} //#endif #if CYTHON_COMPILING_IN_LIMITED_API static PyObject * __Pyx_CyFunction_get_module(__pyx_CyFunctionObject *op, void *context) { CYTHON_UNUSED_VAR(context); return PyObject_GetAttrString(op->func, "__module__"); } static int __Pyx_CyFunction_set_module(__pyx_CyFunctionObject *op, PyObject* value, void *context) { CYTHON_UNUSED_VAR(context); return PyObject_SetAttrString(op->func, "__module__", value); } #endif static PyGetSetDef __pyx_CyFunction_getsets[] = { {(char *) "func_doc", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0}, {(char *) "__doc__", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0}, {(char *) "func_name", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0}, {(char *) "__name__", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0}, {(char *) "__qualname__", (getter)__Pyx_CyFunction_get_qualname, (setter)__Pyx_CyFunction_set_qualname, 0, 0}, {(char *) "func_dict", (getter)__Pyx_CyFunction_get_dict, (setter)__Pyx_CyFunction_set_dict, 0, 0}, {(char *) "__dict__", (getter)__Pyx_CyFunction_get_dict, (setter)__Pyx_CyFunction_set_dict, 0, 0}, {(char *) "func_globals", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0}, {(char *) "__globals__", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0}, {(char *) "func_closure", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0}, {(char *) "__closure__", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0}, {(char *) "func_code", (getter)__Pyx_CyFunction_get_code, 0, 0, 0}, {(char *) "__code__", (getter)__Pyx_CyFunction_get_code, 0, 0, 0}, {(char *) "func_defaults", (getter)__Pyx_CyFunction_get_defaults, (setter)__Pyx_CyFunction_set_defaults, 0, 0}, {(char *) "__defaults__", (getter)__Pyx_CyFunction_get_defaults, (setter)__Pyx_CyFunction_set_defaults, 0, 0}, {(char *) "__kwdefaults__", (getter)__Pyx_CyFunction_get_kwdefaults, (setter)__Pyx_CyFunction_set_kwdefaults, 0, 0}, {(char *) "__annotations__", (getter)__Pyx_CyFunction_get_annotations, (setter)__Pyx_CyFunction_set_annotations, 0, 0}, {(char *) "_is_coroutine", (getter)__Pyx_CyFunction_get_is_coroutine, 0, 0, 0}, //#if PY_VERSION_HEX >= 0x030400C1 // {(char *) "__signature__", (getter)__Pyx_CyFunction_get_signature, 0, 0, 0}, //#endif #if CYTHON_COMPILING_IN_LIMITED_API {"__module__", (getter)__Pyx_CyFunction_get_module, (setter)__Pyx_CyFunction_set_module, 0, 0}, #endif {0, 0, 0, 0, 0} }; static PyMemberDef __pyx_CyFunction_members[] = { #if !CYTHON_COMPILING_IN_LIMITED_API {(char *) "__module__", T_OBJECT, offsetof(PyCFunctionObject, m_module), 0, 0}, #endif #if CYTHON_USE_TYPE_SPECS {(char *) "__dictoffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_dict), READONLY, 0}, #if CYTHON_METH_FASTCALL #if CYTHON_BACKPORT_VECTORCALL {(char *) "__vectorcalloffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_vectorcall), READONLY, 0}, #else #if !CYTHON_COMPILING_IN_LIMITED_API {(char *) "__vectorcalloffset__", T_PYSSIZET, offsetof(PyCFunctionObject, vectorcall), READONLY, 0}, #endif #endif #endif #if PY_VERSION_HEX < 0x030500A0 || CYTHON_COMPILING_IN_LIMITED_API {(char *) "__weaklistoffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_weakreflist), READONLY, 0}, #else {(char *) "__weaklistoffset__", T_PYSSIZET, offsetof(PyCFunctionObject, m_weakreflist), READONLY, 0}, #endif #endif {0, 0, 0, 0, 0} }; static PyObject * __Pyx_CyFunction_reduce(__pyx_CyFunctionObject *m, PyObject *args) { CYTHON_UNUSED_VAR(args); #if PY_MAJOR_VERSION >= 3 Py_INCREF(m->func_qualname); return m->func_qualname; #else return PyString_FromString(((PyCFunctionObject*)m)->m_ml->ml_name); #endif } static PyMethodDef __pyx_CyFunction_methods[] = { {"__reduce__", (PyCFunction)__Pyx_CyFunction_reduce, METH_VARARGS, 0}, {0, 0, 0, 0} }; #if PY_VERSION_HEX < 0x030500A0 || CYTHON_COMPILING_IN_LIMITED_API #define __Pyx_CyFunction_weakreflist(cyfunc) ((cyfunc)->func_weakreflist) #else #define __Pyx_CyFunction_weakreflist(cyfunc) (((PyCFunctionObject*)cyfunc)->m_weakreflist) #endif static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject *op, PyMethodDef *ml, int flags, PyObject* qualname, PyObject *closure, PyObject *module, PyObject* globals, PyObject* code) { #if !CYTHON_COMPILING_IN_LIMITED_API PyCFunctionObject *cf = (PyCFunctionObject*) op; #endif if (unlikely(op == NULL)) return NULL; #if CYTHON_COMPILING_IN_LIMITED_API // Note that we end up with a circular reference to op. This isn't // a disaster, but in an ideal world it'd be nice to avoid it. op->func = PyCFunction_NewEx(ml, (PyObject*)op, module); if (unlikely(!op->func)) return NULL; #endif op->flags = flags; __Pyx_CyFunction_weakreflist(op) = NULL; #if !CYTHON_COMPILING_IN_LIMITED_API cf->m_ml = ml; cf->m_self = (PyObject *) op; #endif Py_XINCREF(closure); op->func_closure = closure; #if !CYTHON_COMPILING_IN_LIMITED_API Py_XINCREF(module); cf->m_module = module; #endif op->func_dict = NULL; op->func_name = NULL; Py_INCREF(qualname); op->func_qualname = qualname; op->func_doc = NULL; #if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API op->func_classobj = NULL; #else ((PyCMethodObject*)op)->mm_class = NULL; #endif op->func_globals = globals; Py_INCREF(op->func_globals); Py_XINCREF(code); op->func_code = code; // Dynamic Default args op->defaults_pyobjects = 0; op->defaults_size = 0; op->defaults = NULL; op->defaults_tuple = NULL; op->defaults_kwdict = NULL; op->defaults_getter = NULL; op->func_annotations = NULL; op->func_is_coroutine = NULL; #if CYTHON_METH_FASTCALL switch (ml->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | METH_KEYWORDS | METH_METHOD)) { case METH_NOARGS: __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_NOARGS; break; case METH_O: __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_O; break; // case METH_FASTCALL is not used case METH_METHOD | METH_FASTCALL | METH_KEYWORDS: __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD; break; case METH_FASTCALL | METH_KEYWORDS: __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS; break; // case METH_VARARGS is not used case METH_VARARGS | METH_KEYWORDS: __Pyx_CyFunction_func_vectorcall(op) = NULL; break; default: PyErr_SetString(PyExc_SystemError, "Bad call flags for CyFunction"); Py_DECREF(op); return NULL; } #endif return (PyObject *) op; } static int __Pyx_CyFunction_clear(__pyx_CyFunctionObject *m) { Py_CLEAR(m->func_closure); #if CYTHON_COMPILING_IN_LIMITED_API Py_CLEAR(m->func); #else Py_CLEAR(((PyCFunctionObject*)m)->m_module); #endif Py_CLEAR(m->func_dict); Py_CLEAR(m->func_name); Py_CLEAR(m->func_qualname); Py_CLEAR(m->func_doc); Py_CLEAR(m->func_globals); Py_CLEAR(m->func_code); #if !CYTHON_COMPILING_IN_LIMITED_API #if PY_VERSION_HEX < 0x030900B1 Py_CLEAR(__Pyx_CyFunction_GetClassObj(m)); #else { PyObject *cls = (PyObject*) ((PyCMethodObject *) (m))->mm_class; ((PyCMethodObject *) (m))->mm_class = NULL; Py_XDECREF(cls); } #endif #endif Py_CLEAR(m->defaults_tuple); Py_CLEAR(m->defaults_kwdict); Py_CLEAR(m->func_annotations); Py_CLEAR(m->func_is_coroutine); if (m->defaults) { PyObject **pydefaults = __Pyx_CyFunction_Defaults(PyObject *, m); int i; for (i = 0; i < m->defaults_pyobjects; i++) Py_XDECREF(pydefaults[i]); PyObject_Free(m->defaults); m->defaults = NULL; } return 0; } static void __Pyx__CyFunction_dealloc(__pyx_CyFunctionObject *m) { if (__Pyx_CyFunction_weakreflist(m) != NULL) PyObject_ClearWeakRefs((PyObject *) m); __Pyx_CyFunction_clear(m); __Pyx_PyHeapTypeObject_GC_Del(m); } static void __Pyx_CyFunction_dealloc(__pyx_CyFunctionObject *m) { PyObject_GC_UnTrack(m); __Pyx__CyFunction_dealloc(m); } static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit, void *arg) { Py_VISIT(m->func_closure); #if CYTHON_COMPILING_IN_LIMITED_API Py_VISIT(m->func); #else Py_VISIT(((PyCFunctionObject*)m)->m_module); #endif Py_VISIT(m->func_dict); Py_VISIT(m->func_name); Py_VISIT(m->func_qualname); Py_VISIT(m->func_doc); Py_VISIT(m->func_globals); Py_VISIT(m->func_code); #if !CYTHON_COMPILING_IN_LIMITED_API Py_VISIT(__Pyx_CyFunction_GetClassObj(m)); #endif Py_VISIT(m->defaults_tuple); Py_VISIT(m->defaults_kwdict); Py_VISIT(m->func_is_coroutine); if (m->defaults) { PyObject **pydefaults = __Pyx_CyFunction_Defaults(PyObject *, m); int i; for (i = 0; i < m->defaults_pyobjects; i++) Py_VISIT(pydefaults[i]); } return 0; } static PyObject* __Pyx_CyFunction_repr(__pyx_CyFunctionObject *op) { #if PY_MAJOR_VERSION >= 3 return PyUnicode_FromFormat("", op->func_qualname, (void *)op); #else return PyString_FromFormat("", PyString_AsString(op->func_qualname), (void *)op); #endif } static PyObject * __Pyx_CyFunction_CallMethod(PyObject *func, PyObject *self, PyObject *arg, PyObject *kw) { // originally copied from PyCFunction_Call() in CPython's Objects/methodobject.c #if CYTHON_COMPILING_IN_LIMITED_API PyObject *f = ((__pyx_CyFunctionObject*)func)->func; PyObject *py_name = NULL; PyCFunction meth; int flags; meth = PyCFunction_GetFunction(f); if (unlikely(!meth)) return NULL; flags = PyCFunction_GetFlags(f); if (unlikely(flags < 0)) return NULL; #else PyCFunctionObject* f = (PyCFunctionObject*)func; PyCFunction meth = f->m_ml->ml_meth; int flags = f->m_ml->ml_flags; #endif Py_ssize_t size; switch (flags & (METH_VARARGS | METH_KEYWORDS | METH_NOARGS | METH_O)) { case METH_VARARGS: if (likely(kw == NULL || PyDict_Size(kw) == 0)) return (*meth)(self, arg); break; case METH_VARARGS | METH_KEYWORDS: return (*(PyCFunctionWithKeywords)(void*)meth)(self, arg, kw); case METH_NOARGS: if (likely(kw == NULL || PyDict_Size(kw) == 0)) { #if CYTHON_ASSUME_SAFE_MACROS size = PyTuple_GET_SIZE(arg); #else size = PyTuple_Size(arg); if (unlikely(size < 0)) return NULL; #endif if (likely(size == 0)) return (*meth)(self, NULL); #if CYTHON_COMPILING_IN_LIMITED_API py_name = __Pyx_CyFunction_get_name((__pyx_CyFunctionObject*)func, NULL); if (!py_name) return NULL; PyErr_Format(PyExc_TypeError, "%.200S() takes no arguments (%" CYTHON_FORMAT_SSIZE_T "d given)", py_name, size); Py_DECREF(py_name); #else PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments (%" CYTHON_FORMAT_SSIZE_T "d given)", f->m_ml->ml_name, size); #endif return NULL; } break; case METH_O: if (likely(kw == NULL || PyDict_Size(kw) == 0)) { #if CYTHON_ASSUME_SAFE_MACROS size = PyTuple_GET_SIZE(arg); #else size = PyTuple_Size(arg); if (unlikely(size < 0)) return NULL; #endif if (likely(size == 1)) { PyObject *result, *arg0; #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS arg0 = PyTuple_GET_ITEM(arg, 0); #else arg0 = __Pyx_PySequence_ITEM(arg, 0); if (unlikely(!arg0)) return NULL; #endif result = (*meth)(self, arg0); #if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS) Py_DECREF(arg0); #endif return result; } #if CYTHON_COMPILING_IN_LIMITED_API py_name = __Pyx_CyFunction_get_name((__pyx_CyFunctionObject*)func, NULL); if (!py_name) return NULL; PyErr_Format(PyExc_TypeError, "%.200S() takes exactly one argument (%" CYTHON_FORMAT_SSIZE_T "d given)", py_name, size); Py_DECREF(py_name); #else PyErr_Format(PyExc_TypeError, "%.200s() takes exactly one argument (%" CYTHON_FORMAT_SSIZE_T "d given)", f->m_ml->ml_name, size); #endif return NULL; } break; default: PyErr_SetString(PyExc_SystemError, "Bad call flags for CyFunction"); return NULL; } #if CYTHON_COMPILING_IN_LIMITED_API py_name = __Pyx_CyFunction_get_name((__pyx_CyFunctionObject*)func, NULL); if (!py_name) return NULL; PyErr_Format(PyExc_TypeError, "%.200S() takes no keyword arguments", py_name); Py_DECREF(py_name); #else PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", f->m_ml->ml_name); #endif return NULL; } static CYTHON_INLINE PyObject *__Pyx_CyFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *self, *result; #if CYTHON_COMPILING_IN_LIMITED_API // PyCFunction_GetSelf returns a borrowed reference self = PyCFunction_GetSelf(((__pyx_CyFunctionObject*)func)->func); if (unlikely(!self) && PyErr_Occurred()) return NULL; #else self = ((PyCFunctionObject*)func)->m_self; #endif result = __Pyx_CyFunction_CallMethod(func, self, arg, kw); return result; } static PyObject *__Pyx_CyFunction_CallAsMethod(PyObject *func, PyObject *args, PyObject *kw) { PyObject *result; __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *) func; #if CYTHON_METH_FASTCALL // Prefer vectorcall if available. This is not the typical case, as // CPython would normally use vectorcall directly instead of tp_call. __pyx_vectorcallfunc vc = __Pyx_CyFunction_func_vectorcall(cyfunc); if (vc) { #if CYTHON_ASSUME_SAFE_MACROS return __Pyx_PyVectorcall_FastCallDict(func, vc, &PyTuple_GET_ITEM(args, 0), (size_t)PyTuple_GET_SIZE(args), kw); #else // avoid unused function warning (void) &__Pyx_PyVectorcall_FastCallDict; return PyVectorcall_Call(func, args, kw); #endif } #endif if ((cyfunc->flags & __Pyx_CYFUNCTION_CCLASS) && !(cyfunc->flags & __Pyx_CYFUNCTION_STATICMETHOD)) { Py_ssize_t argc; PyObject *new_args; PyObject *self; #if CYTHON_ASSUME_SAFE_MACROS argc = PyTuple_GET_SIZE(args); #else argc = PyTuple_Size(args); if (unlikely(!argc) < 0) return NULL; #endif new_args = PyTuple_GetSlice(args, 1, argc); if (unlikely(!new_args)) return NULL; self = PyTuple_GetItem(args, 0); if (unlikely(!self)) { Py_DECREF(new_args); #if PY_MAJOR_VERSION > 2 PyErr_Format(PyExc_TypeError, "unbound method %.200S() needs an argument", cyfunc->func_qualname); #else // %S doesn't work in PyErr_Format on Py2 and replicating // the formatting seems more trouble than it's worth // (so produce a less useful error message). PyErr_SetString(PyExc_TypeError, "unbound method needs an argument"); #endif return NULL; } result = __Pyx_CyFunction_CallMethod(func, self, new_args, kw); Py_DECREF(new_args); } else { result = __Pyx_CyFunction_Call(func, args, kw); } return result; } #if CYTHON_METH_FASTCALL // Check that kwnames is empty (if you want to allow keyword arguments, // simply pass kwnames=NULL) and figure out what to do with "self". // Return value: // 1: self = args[0] // 0: self = cyfunc->func.m_self // -1: error static CYTHON_INLINE int __Pyx_CyFunction_Vectorcall_CheckArgs(__pyx_CyFunctionObject *cyfunc, Py_ssize_t nargs, PyObject *kwnames) { int ret = 0; if ((cyfunc->flags & __Pyx_CYFUNCTION_CCLASS) && !(cyfunc->flags & __Pyx_CYFUNCTION_STATICMETHOD)) { if (unlikely(nargs < 1)) { PyErr_Format(PyExc_TypeError, "%.200s() needs an argument", ((PyCFunctionObject*)cyfunc)->m_ml->ml_name); return -1; } ret = 1; } if (unlikely(kwnames) && unlikely(PyTuple_GET_SIZE(kwnames))) { PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", ((PyCFunctionObject*)cyfunc)->m_ml->ml_name); return -1; } return ret; } static PyObject * __Pyx_CyFunction_Vectorcall_NOARGS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) { __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func; PyMethodDef* def = ((PyCFunctionObject*)cyfunc)->m_ml; #if CYTHON_BACKPORT_VECTORCALL Py_ssize_t nargs = (Py_ssize_t)nargsf; #else Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); #endif PyObject *self; switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, kwnames)) { case 1: self = args[0]; args += 1; nargs -= 1; break; case 0: self = ((PyCFunctionObject*)cyfunc)->m_self; break; default: return NULL; } if (unlikely(nargs != 0)) { PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments (%" CYTHON_FORMAT_SSIZE_T "d given)", def->ml_name, nargs); return NULL; } return def->ml_meth(self, NULL); } static PyObject * __Pyx_CyFunction_Vectorcall_O(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) { __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func; PyMethodDef* def = ((PyCFunctionObject*)cyfunc)->m_ml; #if CYTHON_BACKPORT_VECTORCALL Py_ssize_t nargs = (Py_ssize_t)nargsf; #else Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); #endif PyObject *self; switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, kwnames)) { case 1: self = args[0]; args += 1; nargs -= 1; break; case 0: self = ((PyCFunctionObject*)cyfunc)->m_self; break; default: return NULL; } if (unlikely(nargs != 1)) { PyErr_Format(PyExc_TypeError, "%.200s() takes exactly one argument (%" CYTHON_FORMAT_SSIZE_T "d given)", def->ml_name, nargs); return NULL; } return def->ml_meth(self, args[0]); } static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) { __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func; PyMethodDef* def = ((PyCFunctionObject*)cyfunc)->m_ml; #if CYTHON_BACKPORT_VECTORCALL Py_ssize_t nargs = (Py_ssize_t)nargsf; #else Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); #endif PyObject *self; switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, NULL)) { case 1: self = args[0]; args += 1; nargs -= 1; break; case 0: self = ((PyCFunctionObject*)cyfunc)->m_self; break; default: return NULL; } return ((_PyCFunctionFastWithKeywords)(void(*)(void))def->ml_meth)(self, args, nargs, kwnames); } static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) { __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func; PyMethodDef* def = ((PyCFunctionObject*)cyfunc)->m_ml; PyTypeObject *cls = (PyTypeObject *) __Pyx_CyFunction_GetClassObj(cyfunc); #if CYTHON_BACKPORT_VECTORCALL Py_ssize_t nargs = (Py_ssize_t)nargsf; #else Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); #endif PyObject *self; switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, NULL)) { case 1: self = args[0]; args += 1; nargs -= 1; break; case 0: self = ((PyCFunctionObject*)cyfunc)->m_self; break; default: return NULL; } return ((__Pyx_PyCMethod)(void(*)(void))def->ml_meth)(self, cls, args, (size_t)nargs, kwnames); } #endif #if CYTHON_USE_TYPE_SPECS static PyType_Slot __pyx_CyFunctionType_slots[] = { {Py_tp_dealloc, (void *)__Pyx_CyFunction_dealloc}, {Py_tp_repr, (void *)__Pyx_CyFunction_repr}, {Py_tp_call, (void *)__Pyx_CyFunction_CallAsMethod}, {Py_tp_traverse, (void *)__Pyx_CyFunction_traverse}, {Py_tp_clear, (void *)__Pyx_CyFunction_clear}, {Py_tp_methods, (void *)__pyx_CyFunction_methods}, {Py_tp_members, (void *)__pyx_CyFunction_members}, {Py_tp_getset, (void *)__pyx_CyFunction_getsets}, {Py_tp_descr_get, (void *)__Pyx_PyMethod_New}, {0, 0}, }; static PyType_Spec __pyx_CyFunctionType_spec = { __PYX_TYPE_MODULE_PREFIX "cython_function_or_method", sizeof(__pyx_CyFunctionObject), 0, #ifdef Py_TPFLAGS_METHOD_DESCRIPTOR Py_TPFLAGS_METHOD_DESCRIPTOR | #endif #if (defined(_Py_TPFLAGS_HAVE_VECTORCALL) && CYTHON_METH_FASTCALL) _Py_TPFLAGS_HAVE_VECTORCALL | #endif Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /*tp_flags*/ __pyx_CyFunctionType_slots }; #else /* CYTHON_USE_TYPE_SPECS */ static PyTypeObject __pyx_CyFunctionType_type = { PyVarObject_HEAD_INIT(0, 0) __PYX_TYPE_MODULE_PREFIX "cython_function_or_method", /*tp_name*/ sizeof(__pyx_CyFunctionObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor) __Pyx_CyFunction_dealloc, /*tp_dealloc*/ #if !CYTHON_METH_FASTCALL 0, /*tp_print*/ #elif CYTHON_BACKPORT_VECTORCALL (printfunc)offsetof(__pyx_CyFunctionObject, func_vectorcall), /*tp_vectorcall_offset backported into tp_print*/ #else offsetof(PyCFunctionObject, vectorcall), /*tp_vectorcall_offset*/ #endif 0, /*tp_getattr*/ 0, /*tp_setattr*/ #if PY_MAJOR_VERSION < 3 0, /*tp_compare*/ #else 0, /*tp_as_async*/ #endif (reprfunc) __Pyx_CyFunction_repr, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ __Pyx_CyFunction_CallAsMethod, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ #ifdef Py_TPFLAGS_METHOD_DESCRIPTOR Py_TPFLAGS_METHOD_DESCRIPTOR | #endif #if defined(_Py_TPFLAGS_HAVE_VECTORCALL) && CYTHON_METH_FASTCALL _Py_TPFLAGS_HAVE_VECTORCALL | #endif Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 0, /*tp_doc*/ (traverseproc) __Pyx_CyFunction_traverse, /*tp_traverse*/ (inquiry) __Pyx_CyFunction_clear, /*tp_clear*/ 0, /*tp_richcompare*/ #if PY_VERSION_HEX < 0x030500A0 offsetof(__pyx_CyFunctionObject, func_weakreflist), /*tp_weaklistoffset*/ #else offsetof(PyCFunctionObject, m_weakreflist), /*tp_weaklistoffset*/ #endif 0, /*tp_iter*/ 0, /*tp_iternext*/ __pyx_CyFunction_methods, /*tp_methods*/ __pyx_CyFunction_members, /*tp_members*/ __pyx_CyFunction_getsets, /*tp_getset*/ 0, /*tp_base*/ 0, /*tp_dict*/ __Pyx_PyMethod_New, /*tp_descr_get*/ 0, /*tp_descr_set*/ offsetof(__pyx_CyFunctionObject, func_dict),/*tp_dictoffset*/ 0, /*tp_init*/ 0, /*tp_alloc*/ 0, /*tp_new*/ 0, /*tp_free*/ 0, /*tp_is_gc*/ 0, /*tp_bases*/ 0, /*tp_mro*/ 0, /*tp_cache*/ 0, /*tp_subclasses*/ 0, /*tp_weaklist*/ 0, /*tp_del*/ 0, /*tp_version_tag*/ #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if __PYX_NEED_TP_PRINT_SLOT 0, /*tp_print*/ #endif #if PY_VERSION_HEX >= 0x030C0000 0, /*tp_watched*/ #endif #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000 0, /*tp_pypy_flags*/ #endif }; #endif /* CYTHON_USE_TYPE_SPECS */ static int __pyx_CyFunction_init(PyObject *module) { #if CYTHON_USE_TYPE_SPECS __pyx_CyFunctionType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_CyFunctionType_spec, NULL); #else CYTHON_UNUSED_VAR(module); __pyx_CyFunctionType = __Pyx_FetchCommonType(&__pyx_CyFunctionType_type); #endif if (unlikely(__pyx_CyFunctionType == NULL)) { return -1; } return 0; } static CYTHON_INLINE void *__Pyx_CyFunction_InitDefaults(PyObject *func, size_t size, int pyobjects) { __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; m->defaults = PyObject_Malloc(size); if (unlikely(!m->defaults)) return PyErr_NoMemory(); memset(m->defaults, 0, size); m->defaults_pyobjects = pyobjects; m->defaults_size = size; return m->defaults; } static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsTuple(PyObject *func, PyObject *tuple) { __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; m->defaults_tuple = tuple; Py_INCREF(tuple); } static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsKwDict(PyObject *func, PyObject *dict) { __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; m->defaults_kwdict = dict; Py_INCREF(dict); } static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *func, PyObject *dict) { __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; m->func_annotations = dict; Py_INCREF(dict); } //////////////////// CythonFunction.proto //////////////////// static PyObject *__Pyx_CyFunction_New(PyMethodDef *ml, int flags, PyObject* qualname, PyObject *closure, PyObject *module, PyObject *globals, PyObject* code); //////////////////// CythonFunction //////////////////// //@requires: CythonFunctionShared static PyObject *__Pyx_CyFunction_New(PyMethodDef *ml, int flags, PyObject* qualname, PyObject *closure, PyObject *module, PyObject* globals, PyObject* code) { PyObject *op = __Pyx_CyFunction_Init( PyObject_GC_New(__pyx_CyFunctionObject, __pyx_CyFunctionType), ml, flags, qualname, closure, module, globals, code ); if (likely(op)) { PyObject_GC_Track(op); } return op; } //////////////////// CyFunctionClassCell.proto //////////////////// static int __Pyx_CyFunction_InitClassCell(PyObject *cyfunctions, PyObject *classobj);/*proto*/ //////////////////// CyFunctionClassCell //////////////////// //@requires: CythonFunctionShared static int __Pyx_CyFunction_InitClassCell(PyObject *cyfunctions, PyObject *classobj) { Py_ssize_t i, count = PyList_GET_SIZE(cyfunctions); for (i = 0; i < count; i++) { __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS PyList_GET_ITEM(cyfunctions, i); #else PySequence_ITEM(cyfunctions, i); if (unlikely(!m)) return -1; #endif __Pyx_CyFunction_SetClassObj(m, classobj); #if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS) Py_DECREF((PyObject*)m); #endif } return 0; } //////////////////// FusedFunction.proto //////////////////// typedef struct { __pyx_CyFunctionObject func; PyObject *__signatures__; PyObject *self; } __pyx_FusedFunctionObject; static PyObject *__pyx_FusedFunction_New(PyMethodDef *ml, int flags, PyObject *qualname, PyObject *closure, PyObject *module, PyObject *globals, PyObject *code); static int __pyx_FusedFunction_clear(__pyx_FusedFunctionObject *self); static int __pyx_FusedFunction_init(PyObject *module); #define __Pyx_FusedFunction_USED //////////////////// FusedFunction //////////////////// //@requires: CythonFunctionShared static PyObject * __pyx_FusedFunction_New(PyMethodDef *ml, int flags, PyObject *qualname, PyObject *closure, PyObject *module, PyObject *globals, PyObject *code) { PyObject *op = __Pyx_CyFunction_Init( // __pyx_CyFunctionObject is correct below since that's the cast that we want. PyObject_GC_New(__pyx_CyFunctionObject, __pyx_FusedFunctionType), ml, flags, qualname, closure, module, globals, code ); if (likely(op)) { __pyx_FusedFunctionObject *fusedfunc = (__pyx_FusedFunctionObject *) op; fusedfunc->__signatures__ = NULL; fusedfunc->self = NULL; PyObject_GC_Track(op); } return op; } static void __pyx_FusedFunction_dealloc(__pyx_FusedFunctionObject *self) { PyObject_GC_UnTrack(self); Py_CLEAR(self->self); Py_CLEAR(self->__signatures__); __Pyx__CyFunction_dealloc((__pyx_CyFunctionObject *) self); } static int __pyx_FusedFunction_traverse(__pyx_FusedFunctionObject *self, visitproc visit, void *arg) { Py_VISIT(self->self); Py_VISIT(self->__signatures__); return __Pyx_CyFunction_traverse((__pyx_CyFunctionObject *) self, visit, arg); } static int __pyx_FusedFunction_clear(__pyx_FusedFunctionObject *self) { Py_CLEAR(self->self); Py_CLEAR(self->__signatures__); return __Pyx_CyFunction_clear((__pyx_CyFunctionObject *) self); } static PyObject * __pyx_FusedFunction_descr_get(PyObject *self, PyObject *obj, PyObject *type) { __pyx_FusedFunctionObject *func, *meth; func = (__pyx_FusedFunctionObject *) self; if (func->self || func->func.flags & __Pyx_CYFUNCTION_STATICMETHOD) { // Do not allow rebinding and don't do anything for static methods Py_INCREF(self); return self; } if (obj == Py_None) obj = NULL; if (func->func.flags & __Pyx_CYFUNCTION_CLASSMETHOD) obj = type; if (obj == NULL) { // We aren't actually binding to anything, save the effort of rebinding Py_INCREF(self); return self; } meth = (__pyx_FusedFunctionObject *) __pyx_FusedFunction_New( ((PyCFunctionObject *) func)->m_ml, ((__pyx_CyFunctionObject *) func)->flags, ((__pyx_CyFunctionObject *) func)->func_qualname, ((__pyx_CyFunctionObject *) func)->func_closure, ((PyCFunctionObject *) func)->m_module, ((__pyx_CyFunctionObject *) func)->func_globals, ((__pyx_CyFunctionObject *) func)->func_code); if (unlikely(!meth)) return NULL; // defaults needs copying fully rather than just copying the pointer // since otherwise it will be freed on destruction of meth despite // belonging to func rather than meth if (func->func.defaults) { PyObject **pydefaults; int i; if (unlikely(!__Pyx_CyFunction_InitDefaults( (PyObject*)meth, func->func.defaults_size, func->func.defaults_pyobjects))) { Py_XDECREF((PyObject*)meth); return NULL; } memcpy(meth->func.defaults, func->func.defaults, func->func.defaults_size); pydefaults = __Pyx_CyFunction_Defaults(PyObject *, meth); for (i = 0; i < meth->func.defaults_pyobjects; i++) Py_XINCREF(pydefaults[i]); } __Pyx_CyFunction_SetClassObj(meth, __Pyx_CyFunction_GetClassObj(func)); Py_XINCREF(func->__signatures__); meth->__signatures__ = func->__signatures__; Py_XINCREF(func->func.defaults_tuple); meth->func.defaults_tuple = func->func.defaults_tuple; Py_XINCREF(obj); meth->self = obj; return (PyObject *) meth; } static PyObject * _obj_to_string(PyObject *obj) { if (PyUnicode_CheckExact(obj)) return __Pyx_NewRef(obj); #if PY_MAJOR_VERSION == 2 else if (PyString_Check(obj)) return PyUnicode_FromEncodedObject(obj, NULL, "strict"); #endif else if (PyType_Check(obj)) return PyObject_GetAttr(obj, PYIDENT("__name__")); else return PyObject_Unicode(obj); } static PyObject * __pyx_FusedFunction_getitem(__pyx_FusedFunctionObject *self, PyObject *idx) { PyObject *signature = NULL; PyObject *unbound_result_func; PyObject *result_func = NULL; if (unlikely(self->__signatures__ == NULL)) { PyErr_SetString(PyExc_TypeError, "Function is not fused"); return NULL; } if (PyTuple_Check(idx)) { Py_ssize_t n = PyTuple_GET_SIZE(idx); PyObject *list = PyList_New(n); int i; if (unlikely(!list)) return NULL; for (i = 0; i < n; i++) { PyObject *string; #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS PyObject *item = PyTuple_GET_ITEM(idx, i); #else PyObject *item = PySequence_ITEM(idx, i); if (unlikely(!item)) goto __pyx_err; #endif string = _obj_to_string(item); #if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS) Py_DECREF(item); #endif if (unlikely(!string)) goto __pyx_err; PyList_SET_ITEM(list, i, string); } signature = PyUnicode_Join(PYUNICODE("|"), list); __pyx_err:; Py_DECREF(list); } else { signature = _obj_to_string(idx); } if (unlikely(!signature)) return NULL; unbound_result_func = PyObject_GetItem(self->__signatures__, signature); if (likely(unbound_result_func)) { if (self->self) { __pyx_FusedFunctionObject *unbound = (__pyx_FusedFunctionObject *) unbound_result_func; // TODO: move this to InitClassCell __Pyx_CyFunction_SetClassObj(unbound, __Pyx_CyFunction_GetClassObj(self)); result_func = __pyx_FusedFunction_descr_get(unbound_result_func, self->self, self->self); } else { result_func = unbound_result_func; Py_INCREF(result_func); } } Py_DECREF(signature); Py_XDECREF(unbound_result_func); return result_func; } static PyObject * __pyx_FusedFunction_callfunction(PyObject *func, PyObject *args, PyObject *kw) { __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *) func; int static_specialized = (cyfunc->flags & __Pyx_CYFUNCTION_STATICMETHOD && !((__pyx_FusedFunctionObject *) func)->__signatures__); if ((cyfunc->flags & __Pyx_CYFUNCTION_CCLASS) && !static_specialized) { return __Pyx_CyFunction_CallAsMethod(func, args, kw); } else { return __Pyx_CyFunction_Call(func, args, kw); } } // Note: the 'self' from method binding is passed in in the args tuple, // whereas PyCFunctionObject's m_self is passed in as the first // argument to the C function. For extension methods we need // to pass 'self' as 'm_self' and not as the first element of the // args tuple. static PyObject * __pyx_FusedFunction_call(PyObject *func, PyObject *args, PyObject *kw) { __pyx_FusedFunctionObject *binding_func = (__pyx_FusedFunctionObject *) func; Py_ssize_t argc = PyTuple_GET_SIZE(args); PyObject *new_args = NULL; __pyx_FusedFunctionObject *new_func = NULL; PyObject *result = NULL; int is_staticmethod = binding_func->func.flags & __Pyx_CYFUNCTION_STATICMETHOD; if (binding_func->self) { // Bound method call, put 'self' in the args tuple PyObject *self; Py_ssize_t i; new_args = PyTuple_New(argc + 1); if (unlikely(!new_args)) return NULL; self = binding_func->self; Py_INCREF(self); PyTuple_SET_ITEM(new_args, 0, self); self = NULL; for (i = 0; i < argc; i++) { #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS PyObject *item = PyTuple_GET_ITEM(args, i); Py_INCREF(item); #else PyObject *item = PySequence_ITEM(args, i); if (unlikely(!item)) goto bad; #endif PyTuple_SET_ITEM(new_args, i + 1, item); } args = new_args; } if (binding_func->__signatures__) { PyObject *tup; if (is_staticmethod && binding_func->func.flags & __Pyx_CYFUNCTION_CCLASS) { // FIXME: this seems wrong, but we must currently pass the signatures dict as 'self' argument tup = PyTuple_Pack(3, args, kw == NULL ? Py_None : kw, binding_func->func.defaults_tuple); if (unlikely(!tup)) goto bad; new_func = (__pyx_FusedFunctionObject *) __Pyx_CyFunction_CallMethod( func, binding_func->__signatures__, tup, NULL); } else { tup = PyTuple_Pack(4, binding_func->__signatures__, args, kw == NULL ? Py_None : kw, binding_func->func.defaults_tuple); if (unlikely(!tup)) goto bad; new_func = (__pyx_FusedFunctionObject *) __pyx_FusedFunction_callfunction(func, tup, NULL); } Py_DECREF(tup); if (unlikely(!new_func)) goto bad; __Pyx_CyFunction_SetClassObj(new_func, __Pyx_CyFunction_GetClassObj(binding_func)); func = (PyObject *) new_func; } result = __pyx_FusedFunction_callfunction(func, args, kw); bad: Py_XDECREF(new_args); Py_XDECREF((PyObject *) new_func); return result; } static PyMemberDef __pyx_FusedFunction_members[] = { {(char *) "__signatures__", T_OBJECT, offsetof(__pyx_FusedFunctionObject, __signatures__), READONLY, 0}, {(char *) "__self__", T_OBJECT_EX, offsetof(__pyx_FusedFunctionObject, self), READONLY, 0}, {0, 0, 0, 0, 0}, }; static PyGetSetDef __pyx_FusedFunction_getsets[] = { // __doc__ is None for the fused function type, but we need it to be // a descriptor for the instance's __doc__, so rebuild the descriptor in our subclass // (all other descriptors are inherited) {(char *) "__doc__", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0}, {0, 0, 0, 0, 0} }; #if CYTHON_USE_TYPE_SPECS static PyType_Slot __pyx_FusedFunctionType_slots[] = { {Py_tp_dealloc, (void *)__pyx_FusedFunction_dealloc}, {Py_tp_call, (void *)__pyx_FusedFunction_call}, {Py_tp_traverse, (void *)__pyx_FusedFunction_traverse}, {Py_tp_clear, (void *)__pyx_FusedFunction_clear}, {Py_tp_members, (void *)__pyx_FusedFunction_members}, {Py_tp_getset, (void *)__pyx_FusedFunction_getsets}, {Py_tp_descr_get, (void *)__pyx_FusedFunction_descr_get}, {Py_mp_subscript, (void *)__pyx_FusedFunction_getitem}, {0, 0}, }; static PyType_Spec __pyx_FusedFunctionType_spec = { __PYX_TYPE_MODULE_PREFIX "fused_cython_function", sizeof(__pyx_FusedFunctionObject), 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /*tp_flags*/ __pyx_FusedFunctionType_slots }; #else /* !CYTHON_USE_TYPE_SPECS */ static PyMappingMethods __pyx_FusedFunction_mapping_methods = { 0, (binaryfunc) __pyx_FusedFunction_getitem, 0, }; static PyTypeObject __pyx_FusedFunctionType_type = { PyVarObject_HEAD_INIT(0, 0) __PYX_TYPE_MODULE_PREFIX "fused_cython_function", /*tp_name*/ sizeof(__pyx_FusedFunctionObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor) __pyx_FusedFunction_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ #if PY_MAJOR_VERSION < 3 0, /*tp_compare*/ #else 0, /*tp_as_async*/ #endif 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ &__pyx_FusedFunction_mapping_methods, /*tp_as_mapping*/ 0, /*tp_hash*/ (ternaryfunc) __pyx_FusedFunction_call, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 0, /*tp_doc*/ (traverseproc) __pyx_FusedFunction_traverse, /*tp_traverse*/ (inquiry) __pyx_FusedFunction_clear,/*tp_clear*/ 0, /*tp_richcompare*/ 0, /*tp_weaklistoffset*/ 0, /*tp_iter*/ 0, /*tp_iternext*/ 0, /*tp_methods*/ __pyx_FusedFunction_members, /*tp_members*/ __pyx_FusedFunction_getsets, /*tp_getset*/ // NOTE: tp_base may be changed later during module initialisation when importing CyFunction across modules. &__pyx_CyFunctionType_type, /*tp_base*/ 0, /*tp_dict*/ __pyx_FusedFunction_descr_get, /*tp_descr_get*/ 0, /*tp_descr_set*/ 0, /*tp_dictoffset*/ 0, /*tp_init*/ 0, /*tp_alloc*/ 0, /*tp_new*/ 0, /*tp_free*/ 0, /*tp_is_gc*/ 0, /*tp_bases*/ 0, /*tp_mro*/ 0, /*tp_cache*/ 0, /*tp_subclasses*/ 0, /*tp_weaklist*/ 0, /*tp_del*/ 0, /*tp_version_tag*/ #if PY_VERSION_HEX >= 0x030400a1 0, /*tp_finalize*/ #endif #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) 0, /*tp_vectorcall*/ #endif #if __PYX_NEED_TP_PRINT_SLOT 0, /*tp_print*/ #endif #if PY_VERSION_HEX >= 0x030C0000 0, /*tp_watched*/ #endif #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000 0, /*tp_pypy_flags*/ #endif }; #endif static int __pyx_FusedFunction_init(PyObject *module) { #if CYTHON_USE_TYPE_SPECS PyObject *bases = PyTuple_Pack(1, __pyx_CyFunctionType); if (unlikely(!bases)) { return -1; } __pyx_FusedFunctionType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_FusedFunctionType_spec, bases); Py_DECREF(bases); #else CYTHON_UNUSED_VAR(module); // Set base from __Pyx_FetchCommonTypeFromSpec, in case it's different from the local static value. __pyx_FusedFunctionType_type.tp_base = __pyx_CyFunctionType; __pyx_FusedFunctionType = __Pyx_FetchCommonType(&__pyx_FusedFunctionType_type); #endif if (unlikely(__pyx_FusedFunctionType == NULL)) { return -1; } return 0; } //////////////////// ClassMethod.proto //////////////////// #include "descrobject.h" CYTHON_UNUSED static PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/ //////////////////// ClassMethod //////////////////// static PyObject* __Pyx_Method_ClassMethod(PyObject *method) { #if CYTHON_COMPILING_IN_PYPY && PYPY_VERSION_NUM <= 0x05080000 if (PyObject_TypeCheck(method, &PyWrapperDescr_Type)) { // cdef classes return PyClassMethod_New(method); } #else #if CYTHON_COMPILING_IN_PYPY // special C-API function only in PyPy >= 5.9 if (PyMethodDescr_Check(method)) #else #if PY_MAJOR_VERSION == 2 // PyMethodDescr_Type is not exposed in the CPython C-API in Py2. static PyTypeObject *methoddescr_type = NULL; if (unlikely(methoddescr_type == NULL)) { PyObject *meth = PyObject_GetAttrString((PyObject*)&PyList_Type, "append"); if (unlikely(!meth)) return NULL; methoddescr_type = Py_TYPE(meth); Py_DECREF(meth); } #else PyTypeObject *methoddescr_type = &PyMethodDescr_Type; #endif if (__Pyx_TypeCheck(method, methoddescr_type)) #endif { // cdef classes PyMethodDescrObject *descr = (PyMethodDescrObject *)method; #if PY_VERSION_HEX < 0x03020000 PyTypeObject *d_type = descr->d_type; #else PyTypeObject *d_type = descr->d_common.d_type; #endif return PyDescr_NewClassMethod(d_type, descr->d_method); } #endif else if (PyMethod_Check(method)) { // python classes return PyClassMethod_New(PyMethod_GET_FUNCTION(method)); } else { return PyClassMethod_New(method); } } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/Dataclasses.c0000644000175100001770000001614700000000000021107 0ustar00runnerdocker00000000000000///////////////////// ModuleLoader.proto ////////////////////////// static PyObject* __Pyx_LoadInternalModule(const char* name, const char* fallback_code); /* proto */ //////////////////// ModuleLoader /////////////////////// //@requires: CommonStructures.c::FetchSharedCythonModule static PyObject* __Pyx_LoadInternalModule(const char* name, const char* fallback_code) { // We want to be able to use the contents of the standard library dataclasses module where available. // If those objects aren't available (due to Python version) then a simple fallback is substituted // instead, which largely just fails with a not-implemented error. // // The fallbacks are placed in the "shared abi module" as a convenient internal place to // store them PyObject *shared_abi_module = 0, *module = 0; #if __PYX_LIMITED_VERSION_HEX >= 0x030d00A1 PyObject *result; #endif shared_abi_module = __Pyx_FetchSharedCythonABIModule(); if (!shared_abi_module) return NULL; #if __PYX_LIMITED_VERSION_HEX >= 0x030d00A1 if (PyObject_GetOptionalAttrString(shared_abi_module, name, &result) != 0) { Py_DECREF(shared_abi_module); return result; } #else if (PyObject_HasAttrString(shared_abi_module, name)) { PyObject* result = PyObject_GetAttrString(shared_abi_module, name); Py_DECREF(shared_abi_module); return result; } #endif // the best and simplest case is simply to defer to the standard library (if available) module = PyImport_ImportModule(name); if (!module) { PyObject *localDict, *runValue, *builtins, *modulename; if (!PyErr_ExceptionMatches(PyExc_ImportError)) goto bad; PyErr_Clear(); /* this is reasonably likely (especially on older versions of Python) */ #if PY_MAJOR_VERSION < 3 modulename = PyBytes_FromFormat("_cython_" CYTHON_ABI ".%s", name); #else modulename = PyUnicode_FromFormat("_cython_" CYTHON_ABI ".%s", name); #endif if (!modulename) goto bad; #if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_CPYTHON module = PyImport_AddModuleObject(modulename); /* borrowed */ #else module = PyImport_AddModule(PyBytes_AsString(modulename)); /* borrowed */ #endif Py_DECREF(modulename); if (!module) goto bad; Py_INCREF(module); if (PyObject_SetAttrString(shared_abi_module, name, module) < 0) goto bad; localDict = PyModule_GetDict(module); /* borrowed */ if (!localDict) goto bad; builtins = PyEval_GetBuiltins(); /* borrowed */ if (!builtins) goto bad; if (PyDict_SetItemString(localDict, "__builtins__", builtins) <0) goto bad; runValue = PyRun_String(fallback_code, Py_file_input, localDict, localDict); if (!runValue) goto bad; Py_DECREF(runValue); } goto shared_cleanup; bad: Py_CLEAR(module); shared_cleanup: Py_XDECREF(shared_abi_module); return module; } ///////////////////// SpecificModuleLoader.proto ////////////////////// //@substitute: tempita static PyObject* __Pyx_Load_{{cname}}_Module(void); /* proto */ //////////////////// SpecificModuleLoader /////////////////////// //@requires: ModuleLoader static PyObject* __Pyx_Load_{{cname}}_Module(void) { return __Pyx_LoadInternalModule("{{cname}}", {{py_code}}); } //////////////////// DataclassesCallHelper.proto //////////////////////// static PyObject* __Pyx_DataclassesCallHelper(PyObject *callable, PyObject *kwds); /* proto */ //////////////////// DataclassesCallHelper //////////////////////// //@substitute: naming // The signature of a few of the dataclasses module functions has // been expanded over the years. Cython always passes the full set // of arguments from the most recent version we know of, so needs // to remove any arguments that don't exist on earlier versions. #if PY_MAJOR_VERSION >= 3 static int __Pyx_DataclassesCallHelper_FilterToDict(PyObject *callable, PyObject *kwds, PyObject *new_kwds, PyObject *args_list, int is_kwonly) { Py_ssize_t size, i; size = PySequence_Size(args_list); if (size == -1) return -1; for (i=0; i' _HAS_DEFAULT_FACTORY = _HAS_DEFAULT_FACTORY_CLASS() def dataclass(*args, **kwds): raise NotImplementedError("Standard library 'dataclasses' module" "is unavailable, likely due to the version of Python you're using.") # Markers for the various kinds of fields and pseudo-fields. class _FIELD_BASE: def __init__(self, name): self.name = name def __repr__(self): return self.name _FIELD = _FIELD_BASE('_FIELD') _FIELD_CLASSVAR = _FIELD_BASE('_FIELD_CLASSVAR') _FIELD_INITVAR = _FIELD_BASE('_FIELD_INITVAR') def field(*ignore, **kwds): default = kwds.pop("default", MISSING) default_factory = kwds.pop("default_factory", MISSING) init = kwds.pop("init", True) repr = kwds.pop("repr", True) hash = kwds.pop("hash", None) compare = kwds.pop("compare", True) metadata = kwds.pop("metadata", None) kw_only = kwds.pop("kw_only", None) if kwds: raise ValueError("field received unexpected keyword arguments: %s" % list(kwds.keys())) if default is not MISSING and default_factory is not MISSING: raise ValueError('cannot specify both default and default_factory') if ignore: raise ValueError("'field' does not take any positional arguments") return Field(default, default_factory, init, repr, hash, compare, metadata, kw_only) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/Embed.c0000644000175100001770000001641400000000000017671 0ustar00runnerdocker00000000000000//////////////////// MainFunction //////////////////// #ifdef __FreeBSD__ #include #endif #if PY_MAJOR_VERSION < 3 int %(main_method)s(int argc, char** argv) #elif defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS) int %(wmain_method)s(int argc, wchar_t **argv) #else static int __Pyx_main(int argc, wchar_t **argv) #endif { /* 754 requires that FP exceptions run in "no stop" mode by default, * and until C vendors implement C99's ways to control FP exceptions, * Python requires non-stop mode. Alas, some platforms enable FP * exceptions by default. Here we disable them. */ #ifdef __FreeBSD__ fp_except_t m; m = fpgetmask(); fpsetmask(m & ~FP_X_OFL); #endif #if PY_VERSION_HEX < 0x03080000 if (argc && argv) Py_SetProgramName(argv[0]); #endif #if PY_MAJOR_VERSION < 3 if (PyImport_AppendInittab("%(module_name)s", init%(module_name)s) < 0) return 1; #else if (PyImport_AppendInittab("%(module_name)s", PyInit_%(module_name)s) < 0) return 1; #endif #if PY_VERSION_HEX < 0x03080000 Py_Initialize(); if (argc && argv) PySys_SetArgv(argc, argv); #else { PyStatus status; PyConfig config; PyConfig_InitPythonConfig(&config); // Disable parsing command line arguments config.parse_argv = 0; if (argc && argv) { status = PyConfig_SetString(&config, &config.program_name, argv[0]); if (PyStatus_Exception(status)) { PyConfig_Clear(&config); return 1; } status = PyConfig_SetArgv(&config, argc, argv); if (PyStatus_Exception(status)) { PyConfig_Clear(&config); return 1; } } status = Py_InitializeFromConfig(&config); if (PyStatus_Exception(status)) { PyConfig_Clear(&config); return 1; } PyConfig_Clear(&config); } #endif { /* init module '%(module_name)s' as '__main__' */ PyObject* m = NULL; %(module_is_main)s = 1; m = PyImport_ImportModule("%(module_name)s"); if (!m && PyErr_Occurred()) { PyErr_Print(); /* This exits with the right code if SystemExit. */ #if PY_MAJOR_VERSION < 3 if (Py_FlushLine()) PyErr_Clear(); #endif return 1; } Py_XDECREF(m); } #if PY_VERSION_HEX < 0x03060000 Py_Finalize(); #else if (Py_FinalizeEx() < 0) return 2; #endif return 0; } #if PY_MAJOR_VERSION >= 3 && !defined(_WIN32) && !defined(WIN32) && !defined(MS_WINDOWS) #include #if PY_VERSION_HEX < 0x03050000 static wchar_t* __Pyx_char2wchar(char* arg) { wchar_t *res; #ifdef HAVE_BROKEN_MBSTOWCS /* Some platforms have a broken implementation of * mbstowcs which does not count the characters that * would result from conversion. Use an upper bound. */ size_t argsize = strlen(arg); #else size_t argsize = mbstowcs(NULL, arg, 0); #endif size_t count; unsigned char *in; wchar_t *out; #ifdef HAVE_MBRTOWC mbstate_t mbs; #endif if (argsize != (size_t)-1) { res = (wchar_t *)malloc((argsize+1)*sizeof(wchar_t)); if (!res) goto oom; count = mbstowcs(res, arg, argsize+1); if (count != (size_t)-1) { wchar_t *tmp; /* Only use the result if it contains no surrogate characters. */ for (tmp = res; *tmp != 0 && (*tmp < 0xd800 || *tmp > 0xdfff); tmp++) ; if (*tmp == 0) return res; } free(res); } /* Conversion failed. Fall back to escaping with surrogateescape. */ #ifdef HAVE_MBRTOWC /* Try conversion with mbrtwoc (C99), and escape non-decodable bytes. */ /* Overallocate; as multi-byte characters are in the argument, the actual output could use less memory. */ argsize = strlen(arg) + 1; res = (wchar_t *)malloc(argsize*sizeof(wchar_t)); if (!res) goto oom; in = (unsigned char*)arg; out = res; memset(&mbs, 0, sizeof mbs); while (argsize) { size_t converted = mbrtowc(out, (char*)in, argsize, &mbs); if (converted == 0) /* Reached end of string; null char stored. */ break; if (converted == (size_t)-2) { /* Incomplete character. This should never happen, since we provide everything that we have - unless there is a bug in the C library, or I misunderstood how mbrtowc works. */ fprintf(stderr, "unexpected mbrtowc result -2\\n"); free(res); return NULL; } if (converted == (size_t)-1) { /* Conversion error. Escape as UTF-8b, and start over in the initial shift state. */ *out++ = 0xdc00 + *in++; argsize--; memset(&mbs, 0, sizeof mbs); continue; } if (*out >= 0xd800 && *out <= 0xdfff) { /* Surrogate character. Escape the original byte sequence with surrogateescape. */ argsize -= converted; while (converted--) *out++ = 0xdc00 + *in++; continue; } /* successfully converted some bytes */ in += converted; argsize -= converted; out++; } #else /* Cannot use C locale for escaping; manually escape as if charset is ASCII (i.e. escape all bytes > 128. This will still roundtrip correctly in the locale's charset, which must be an ASCII superset. */ res = (wchar_t *)malloc((strlen(arg)+1)*sizeof(wchar_t)); if (!res) goto oom; in = (unsigned char*)arg; out = res; while(*in) if(*in < 128) *out++ = *in++; else *out++ = 0xdc00 + *in++; *out = 0; #endif return res; oom: fprintf(stderr, "out of memory\\n"); return NULL; } #endif int %(main_method)s(int argc, char **argv) { if (!argc) { return __Pyx_main(0, NULL); } else { int i, res; wchar_t **argv_copy = (wchar_t **)malloc(sizeof(wchar_t*)*argc); /* We need a second copy, as Python might modify the first one. */ wchar_t **argv_copy2 = (wchar_t **)malloc(sizeof(wchar_t*)*argc); char *oldloc = strdup(setlocale(LC_ALL, NULL)); if (!argv_copy || !argv_copy2 || !oldloc) { fprintf(stderr, "out of memory\\n"); free(argv_copy); free(argv_copy2); free(oldloc); return 1; } res = 0; setlocale(LC_ALL, ""); for (i = 0; i < argc; i++) { argv_copy2[i] = argv_copy[i] = #if PY_VERSION_HEX < 0x03050000 __Pyx_char2wchar(argv[i]); #else Py_DecodeLocale(argv[i], NULL); #endif if (!argv_copy[i]) res = 1; /* failure, but continue to simplify cleanup */ } setlocale(LC_ALL, oldloc); free(oldloc); if (res == 0) res = __Pyx_main(argc, argv_copy); for (i = 0; i < argc; i++) { #if PY_VERSION_HEX < 0x03050000 free(argv_copy2[i]); #else PyMem_RawFree(argv_copy2[i]); #endif } free(argv_copy); free(argv_copy2); return res; } } #endif ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/Exceptions.c0000644000175100001770000011405300000000000020774 0ustar00runnerdocker00000000000000// Exception raising code // // Exceptions are raised by __Pyx_Raise() and stored as plain // type/value/tb in PyThreadState->curexc_*. When being caught by an // 'except' statement, curexc_* is moved over to exc_* by // __Pyx_GetException() /////////////// AssertionsEnabled.init /////////////// if (likely(__Pyx_init_assertions_enabled() == 0)); else // error propagation code is appended automatically /////////////// AssertionsEnabled.proto /////////////// #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) #define __Pyx_init_assertions_enabled() (0) #define __pyx_assertions_enabled() (1) #elif CYTHON_COMPILING_IN_LIMITED_API || (CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030C0000) // Py_OptimizeFlag is deprecated in Py3.12+ and not available in the Limited API. static int __pyx_assertions_enabled_flag; #define __pyx_assertions_enabled() (__pyx_assertions_enabled_flag) static int __Pyx_init_assertions_enabled(void) { PyObject *builtins, *debug, *debug_str; int flag; builtins = PyEval_GetBuiltins(); if (!builtins) goto bad; debug_str = PyUnicode_FromStringAndSize("__debug__", 9); if (!debug_str) goto bad; debug = PyObject_GetItem(builtins, debug_str); Py_DECREF(debug_str); if (!debug) goto bad; flag = PyObject_IsTrue(debug); Py_DECREF(debug); if (flag == -1) goto bad; __pyx_assertions_enabled_flag = flag; return 0; bad: __pyx_assertions_enabled_flag = 1; // We (rarely) may not have an exception set, but the calling code will call PyErr_Occurred() either way. return -1; } #else #define __Pyx_init_assertions_enabled() (0) #define __pyx_assertions_enabled() (!Py_OptimizeFlag) #endif /////////////// ErrOccurredWithGIL.proto /////////////// static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void); /* proto */ /////////////// ErrOccurredWithGIL /////////////// static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void) { int err; #ifdef WITH_THREAD PyGILState_STATE _save = PyGILState_Ensure(); #endif err = !!PyErr_Occurred(); #ifdef WITH_THREAD PyGILState_Release(_save); #endif return err; } /////////////// PyThreadStateGet.proto /////////////// //@substitute: naming #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyThreadState_declare PyThreadState *$local_tstate_cname; #define __Pyx_PyThreadState_assign $local_tstate_cname = __Pyx_PyThreadState_Current; #if PY_VERSION_HEX >= 0x030C00A6 #define __Pyx_PyErr_Occurred() ($local_tstate_cname->current_exception != NULL) #define __Pyx_PyErr_CurrentExceptionType() ($local_tstate_cname->current_exception ? (PyObject*) Py_TYPE($local_tstate_cname->current_exception) : (PyObject*) NULL) #else #define __Pyx_PyErr_Occurred() ($local_tstate_cname->curexc_type != NULL) #define __Pyx_PyErr_CurrentExceptionType() ($local_tstate_cname->curexc_type) #endif #else // !CYTHON_FAST_THREAD_STATE #define __Pyx_PyThreadState_declare #define __Pyx_PyThreadState_assign #define __Pyx_PyErr_Occurred() (PyErr_Occurred() != NULL) #define __Pyx_PyErr_CurrentExceptionType() PyErr_Occurred() #endif /////////////// PyErrExceptionMatches.proto /////////////// //@substitute: naming #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState($local_tstate_cname, err) static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err); #else #define __Pyx_PyErr_ExceptionMatches(err) PyErr_ExceptionMatches(err) #endif /////////////// PyErrExceptionMatches /////////////// #if CYTHON_FAST_THREAD_STATE static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { Py_ssize_t i, n; n = PyTuple_GET_SIZE(tuple); #if PY_MAJOR_VERSION >= 3 // the tighter subtype checking in Py3 allows faster out-of-order comparison for (i=0; i= 0x030C00A6 PyObject *current_exception = tstate->current_exception; if (unlikely(!current_exception)) return 0; exc_type = (PyObject*) Py_TYPE(current_exception); if (exc_type == err) return 1; #else exc_type = tstate->curexc_type; if (exc_type == err) return 1; if (unlikely(!exc_type)) return 0; #endif #if CYTHON_AVOID_BORROWED_REFS Py_INCREF(exc_type); #endif if (unlikely(PyTuple_Check(err))) { result = __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err); } else { result = __Pyx_PyErr_GivenExceptionMatches(exc_type, err); } #if CYTHON_AVOID_BORROWED_REFS Py_DECREF(exc_type); #endif return result; } #endif /////////////// PyErrFetchRestore.proto /////////////// //@substitute: naming //@requires: PyThreadStateGet #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) #define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) #define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) #define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState($local_tstate_cname, type, value, tb) #define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState($local_tstate_cname, type, value, tb) static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); /*proto*/ static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); /*proto*/ #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A6 #define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) #else #define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) #endif #else #define __Pyx_PyErr_Clear() PyErr_Clear() #define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) #define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) #define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) #define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) #define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) #define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) #define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) #endif /////////////// PyErrFetchRestore /////////////// #if CYTHON_FAST_THREAD_STATE static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { #if PY_VERSION_HEX >= 0x030C00A6 PyObject *tmp_value; assert(type == NULL || (value != NULL && type == (PyObject*) Py_TYPE(value))); if (value) { #if CYTHON_COMPILING_IN_CPYTHON if (unlikely(((PyBaseExceptionObject*) value)->traceback != tb)) #endif // If this fails, we may lose the traceback but still set the expected exception below. PyException_SetTraceback(value, tb); } tmp_value = tstate->current_exception; tstate->current_exception = value; Py_XDECREF(tmp_value); Py_XDECREF(type); Py_XDECREF(tb); #else PyObject *tmp_type, *tmp_value, *tmp_tb; tmp_type = tstate->curexc_type; tmp_value = tstate->curexc_value; tmp_tb = tstate->curexc_traceback; tstate->curexc_type = type; tstate->curexc_value = value; tstate->curexc_traceback = tb; Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); #endif } static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { #if PY_VERSION_HEX >= 0x030C00A6 PyObject* exc_value; exc_value = tstate->current_exception; tstate->current_exception = 0; *value = exc_value; *type = NULL; *tb = NULL; if (exc_value) { *type = (PyObject*) Py_TYPE(exc_value); Py_INCREF(*type); #if CYTHON_COMPILING_IN_CPYTHON *tb = ((PyBaseExceptionObject*) exc_value)->traceback; Py_XINCREF(*tb); #else *tb = PyException_GetTraceback(exc_value); #endif } #else *type = tstate->curexc_type; *value = tstate->curexc_value; *tb = tstate->curexc_traceback; tstate->curexc_type = 0; tstate->curexc_value = 0; tstate->curexc_traceback = 0; #endif } #endif /////////////// RaiseException.proto /////////////// static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); /*proto*/ /////////////// RaiseException /////////////// //@requires: PyErrFetchRestore //@requires: PyThreadStateGet // The following function is based on do_raise() from ceval.c. There // are separate versions for Python2 and Python3 as exception handling // has changed quite a lot between the two versions. #if PY_MAJOR_VERSION < 3 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { __Pyx_PyThreadState_declare CYTHON_UNUSED_VAR(cause); /* 'cause' is only used in Py3 */ Py_XINCREF(type); if (!value || value == Py_None) value = NULL; else Py_INCREF(value); if (!tb || tb == Py_None) tb = NULL; else { Py_INCREF(tb); if (!PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "raise: arg 3 must be a traceback or None"); goto raise_error; } } if (PyType_Check(type)) { /* instantiate the type now (we don't know when and how it will be caught) */ #if CYTHON_COMPILING_IN_PYPY /* PyPy can't handle value == NULL */ if (!value) { Py_INCREF(Py_None); value = Py_None; } #endif PyErr_NormalizeException(&type, &value, &tb); } else { /* Raising an instance. The value should be a dummy. */ if (value) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto raise_error; } /* Normalize to raise , */ value = type; type = (PyObject*) Py_TYPE(type); Py_INCREF(type); if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { PyErr_SetString(PyExc_TypeError, "raise: exception class must be a subclass of BaseException"); goto raise_error; } } __Pyx_PyThreadState_assign __Pyx_ErrRestore(type, value, tb); return; raise_error: Py_XDECREF(value); Py_XDECREF(type); Py_XDECREF(tb); return; } #else /* Python 3+ */ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { PyObject* owned_instance = NULL; if (tb == Py_None) { tb = 0; } else if (tb && !PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "raise: arg 3 must be a traceback or None"); goto bad; } if (value == Py_None) value = 0; if (PyExceptionInstance_Check(type)) { if (value) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto bad; } value = type; type = (PyObject*) Py_TYPE(value); } else if (PyExceptionClass_Check(type)) { // make sure value is an exception instance of type PyObject *instance_class = NULL; if (value && PyExceptionInstance_Check(value)) { instance_class = (PyObject*) Py_TYPE(value); if (instance_class != type) { int is_subclass = PyObject_IsSubclass(instance_class, type); if (!is_subclass) { instance_class = NULL; } else if (unlikely(is_subclass == -1)) { // error on subclass test goto bad; } else { // believe the instance type = instance_class; } } } if (!instance_class) { // instantiate the type now (we don't know when and how it will be caught) // assuming that 'value' is an argument to the type's constructor // not using PyErr_NormalizeException() to avoid ref-counting problems PyObject *args; if (!value) args = PyTuple_New(0); else if (PyTuple_Check(value)) { Py_INCREF(value); args = value; } else args = PyTuple_Pack(1, value); if (!args) goto bad; owned_instance = PyObject_Call(type, args, NULL); Py_DECREF(args); if (!owned_instance) goto bad; value = owned_instance; if (!PyExceptionInstance_Check(value)) { PyErr_Format(PyExc_TypeError, "calling %R should have returned an instance of " "BaseException, not %R", type, Py_TYPE(value)); goto bad; } } } else { PyErr_SetString(PyExc_TypeError, "raise: exception class must be a subclass of BaseException"); goto bad; } if (cause) { PyObject *fixed_cause; if (cause == Py_None) { // raise ... from None fixed_cause = NULL; } else if (PyExceptionClass_Check(cause)) { fixed_cause = PyObject_CallObject(cause, NULL); if (fixed_cause == NULL) goto bad; } else if (PyExceptionInstance_Check(cause)) { fixed_cause = cause; Py_INCREF(fixed_cause); } else { PyErr_SetString(PyExc_TypeError, "exception causes must derive from " "BaseException"); goto bad; } PyException_SetCause(value, fixed_cause); } PyErr_SetObject(type, value); if (tb) { #if PY_VERSION_HEX >= 0x030C00A6 // If this fails, we just get a different exception, so ignore the return value. PyException_SetTraceback(value, tb); #elif CYTHON_FAST_THREAD_STATE PyThreadState *tstate = __Pyx_PyThreadState_Current; PyObject* tmp_tb = tstate->curexc_traceback; if (tb != tmp_tb) { Py_INCREF(tb); tstate->curexc_traceback = tb; Py_XDECREF(tmp_tb); } #else PyObject *tmp_type, *tmp_value, *tmp_tb; PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); Py_INCREF(tb); PyErr_Restore(tmp_type, tmp_value, tb); Py_XDECREF(tmp_tb); #endif } bad: Py_XDECREF(owned_instance); return; } #endif /////////////// GetTopmostException.proto /////////////// #if CYTHON_USE_EXC_INFO_STACK && CYTHON_FAST_THREAD_STATE static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate); #endif /////////////// GetTopmostException /////////////// #if CYTHON_USE_EXC_INFO_STACK && CYTHON_FAST_THREAD_STATE // Copied from errors.c in CPython. static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate) { _PyErr_StackItem *exc_info = tstate->exc_info; while ((exc_info->exc_value == NULL || exc_info->exc_value == Py_None) && exc_info->previous_item != NULL) { exc_info = exc_info->previous_item; } return exc_info; } #endif /////////////// GetException.proto /////////////// //@substitute: naming //@requires: PyThreadStateGet #if CYTHON_FAST_THREAD_STATE #define __Pyx_GetException(type, value, tb) __Pyx__GetException($local_tstate_cname, type, value, tb) static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); /*proto*/ #else static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/ #endif /////////////// GetException /////////////// #if CYTHON_FAST_THREAD_STATE static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) #else static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) #endif { PyObject *local_type = NULL, *local_value, *local_tb = NULL; #if CYTHON_FAST_THREAD_STATE PyObject *tmp_type, *tmp_value, *tmp_tb; #if PY_VERSION_HEX >= 0x030C00A6 local_value = tstate->current_exception; tstate->current_exception = 0; if (likely(local_value)) { local_type = (PyObject*) Py_TYPE(local_value); Py_INCREF(local_type); local_tb = PyException_GetTraceback(local_value); } #else local_type = tstate->curexc_type; local_value = tstate->curexc_value; local_tb = tstate->curexc_traceback; tstate->curexc_type = 0; tstate->curexc_value = 0; tstate->curexc_traceback = 0; #endif #else PyErr_Fetch(&local_type, &local_value, &local_tb); #endif PyErr_NormalizeException(&local_type, &local_value, &local_tb); #if CYTHON_FAST_THREAD_STATE && PY_VERSION_HEX >= 0x030C00A6 if (unlikely(tstate->current_exception)) #elif CYTHON_FAST_THREAD_STATE if (unlikely(tstate->curexc_type)) #else if (unlikely(PyErr_Occurred())) #endif goto bad; #if PY_MAJOR_VERSION >= 3 if (local_tb) { if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0)) goto bad; } #endif // traceback may be NULL for freshly raised exceptions Py_XINCREF(local_tb); // exception state may be temporarily empty in parallel loops (race condition) Py_XINCREF(local_type); Py_XINCREF(local_value); *type = local_type; *value = local_value; *tb = local_tb; #if CYTHON_FAST_THREAD_STATE #if CYTHON_USE_EXC_INFO_STACK { _PyErr_StackItem *exc_info = tstate->exc_info; #if PY_VERSION_HEX >= 0x030B00a4 tmp_value = exc_info->exc_value; exc_info->exc_value = local_value; tmp_type = NULL; tmp_tb = NULL; Py_XDECREF(local_type); Py_XDECREF(local_tb); #else tmp_type = exc_info->exc_type; tmp_value = exc_info->exc_value; tmp_tb = exc_info->exc_traceback; exc_info->exc_type = local_type; exc_info->exc_value = local_value; exc_info->exc_traceback = local_tb; #endif } #else tmp_type = tstate->exc_type; tmp_value = tstate->exc_value; tmp_tb = tstate->exc_traceback; tstate->exc_type = local_type; tstate->exc_value = local_value; tstate->exc_traceback = local_tb; #endif // Make sure tstate is in a consistent state when we XDECREF // these objects (DECREF may run arbitrary code). Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); #else PyErr_SetExcInfo(local_type, local_value, local_tb); #endif return 0; bad: *type = 0; *value = 0; *tb = 0; Py_XDECREF(local_type); Py_XDECREF(local_value); Py_XDECREF(local_tb); return -1; } /////////////// ReRaiseException.proto /////////////// static CYTHON_INLINE void __Pyx_ReraiseException(void); /*proto*/ /////////////// ReRaiseException /////////////// //@requires: GetTopmostException static CYTHON_INLINE void __Pyx_ReraiseException(void) { PyObject *type = NULL, *value = NULL, *tb = NULL; #if CYTHON_FAST_THREAD_STATE PyThreadState *tstate = PyThreadState_GET(); #if CYTHON_USE_EXC_INFO_STACK _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); value = exc_info->exc_value; #if PY_VERSION_HEX >= 0x030B00a4 if (unlikely(value == Py_None)) { value = NULL; } else if (value) { Py_INCREF(value); type = (PyObject*) Py_TYPE(value); Py_INCREF(type); tb = PyException_GetTraceback(value); } #else type = exc_info->exc_type; tb = exc_info->exc_traceback; Py_XINCREF(type); Py_XINCREF(value); Py_XINCREF(tb); #endif #else type = tstate->exc_type; value = tstate->exc_value; tb = tstate->exc_traceback; Py_XINCREF(type); Py_XINCREF(value); Py_XINCREF(tb); #endif #else PyErr_GetExcInfo(&type, &value, &tb); #endif if (unlikely(!type || type == Py_None)) { Py_XDECREF(type); Py_XDECREF(value); Py_XDECREF(tb); // message copied from Py3 PyErr_SetString(PyExc_RuntimeError, "No active exception to reraise"); } else { PyErr_Restore(type, value, tb); } } /////////////// SaveResetException.proto /////////////// //@substitute: naming //@requires: PyThreadStateGet #if CYTHON_FAST_THREAD_STATE #define __Pyx_ExceptionSave(type, value, tb) __Pyx__ExceptionSave($local_tstate_cname, type, value, tb) static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); /*proto*/ #define __Pyx_ExceptionReset(type, value, tb) __Pyx__ExceptionReset($local_tstate_cname, type, value, tb) static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); /*proto*/ #else #define __Pyx_ExceptionSave(type, value, tb) PyErr_GetExcInfo(type, value, tb) #define __Pyx_ExceptionReset(type, value, tb) PyErr_SetExcInfo(type, value, tb) #endif /////////////// SaveResetException /////////////// //@requires: GetTopmostException #if CYTHON_FAST_THREAD_STATE static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { #if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4 _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); PyObject *exc_value = exc_info->exc_value; if (exc_value == NULL || exc_value == Py_None) { *value = NULL; *type = NULL; *tb = NULL; } else { *value = exc_value; Py_INCREF(*value); *type = (PyObject*) Py_TYPE(exc_value); Py_INCREF(*type); *tb = PyException_GetTraceback(exc_value); } #elif CYTHON_USE_EXC_INFO_STACK _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); *type = exc_info->exc_type; *value = exc_info->exc_value; *tb = exc_info->exc_traceback; Py_XINCREF(*type); Py_XINCREF(*value); Py_XINCREF(*tb); #else *type = tstate->exc_type; *value = tstate->exc_value; *tb = tstate->exc_traceback; Py_XINCREF(*type); Py_XINCREF(*value); Py_XINCREF(*tb); #endif } static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { #if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4 _PyErr_StackItem *exc_info = tstate->exc_info; PyObject *tmp_value = exc_info->exc_value; exc_info->exc_value = value; Py_XDECREF(tmp_value); // TODO: avoid passing these at all Py_XDECREF(type); Py_XDECREF(tb); #else PyObject *tmp_type, *tmp_value, *tmp_tb; #if CYTHON_USE_EXC_INFO_STACK _PyErr_StackItem *exc_info = tstate->exc_info; tmp_type = exc_info->exc_type; tmp_value = exc_info->exc_value; tmp_tb = exc_info->exc_traceback; exc_info->exc_type = type; exc_info->exc_value = value; exc_info->exc_traceback = tb; #else tmp_type = tstate->exc_type; tmp_value = tstate->exc_value; tmp_tb = tstate->exc_traceback; tstate->exc_type = type; tstate->exc_value = value; tstate->exc_traceback = tb; #endif Py_XDECREF(tmp_type); Py_XDECREF(tmp_value); Py_XDECREF(tmp_tb); #endif } #endif /////////////// SwapException.proto /////////////// //@substitute: naming //@requires: PyThreadStateGet #if CYTHON_FAST_THREAD_STATE #define __Pyx_ExceptionSwap(type, value, tb) __Pyx__ExceptionSwap($local_tstate_cname, type, value, tb) static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); /*proto*/ #else static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb); /*proto*/ #endif /////////////// SwapException /////////////// #if CYTHON_FAST_THREAD_STATE static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { PyObject *tmp_type, *tmp_value, *tmp_tb; #if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4 _PyErr_StackItem *exc_info = tstate->exc_info; tmp_value = exc_info->exc_value; exc_info->exc_value = *value; if (tmp_value == NULL || tmp_value == Py_None) { Py_XDECREF(tmp_value); tmp_value = NULL; tmp_type = NULL; tmp_tb = NULL; } else { // TODO: avoid swapping these at all tmp_type = (PyObject*) Py_TYPE(tmp_value); Py_INCREF(tmp_type); #if CYTHON_COMPILING_IN_CPYTHON tmp_tb = ((PyBaseExceptionObject*) tmp_value)->traceback; Py_XINCREF(tmp_tb); #else tmp_tb = PyException_GetTraceback(tmp_value); #endif } #elif CYTHON_USE_EXC_INFO_STACK _PyErr_StackItem *exc_info = tstate->exc_info; tmp_type = exc_info->exc_type; tmp_value = exc_info->exc_value; tmp_tb = exc_info->exc_traceback; exc_info->exc_type = *type; exc_info->exc_value = *value; exc_info->exc_traceback = *tb; #else tmp_type = tstate->exc_type; tmp_value = tstate->exc_value; tmp_tb = tstate->exc_traceback; tstate->exc_type = *type; tstate->exc_value = *value; tstate->exc_traceback = *tb; #endif *type = tmp_type; *value = tmp_value; *tb = tmp_tb; } #else static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb) { PyObject *tmp_type, *tmp_value, *tmp_tb; PyErr_GetExcInfo(&tmp_type, &tmp_value, &tmp_tb); PyErr_SetExcInfo(*type, *value, *tb); *type = tmp_type; *value = tmp_value; *tb = tmp_tb; } #endif /////////////// WriteUnraisableException.proto /////////////// static void __Pyx_WriteUnraisable(const char *name, int clineno, int lineno, const char *filename, int full_traceback, int nogil); /*proto*/ /////////////// WriteUnraisableException /////////////// //@requires: PyErrFetchRestore //@requires: PyThreadStateGet static void __Pyx_WriteUnraisable(const char *name, int clineno, int lineno, const char *filename, int full_traceback, int nogil) { PyObject *old_exc, *old_val, *old_tb; PyObject *ctx; __Pyx_PyThreadState_declare #ifdef WITH_THREAD PyGILState_STATE state; if (nogil) state = PyGILState_Ensure(); /* arbitrary, to suppress warning */ else state = (PyGILState_STATE)0; #endif CYTHON_UNUSED_VAR(clineno); CYTHON_UNUSED_VAR(lineno); CYTHON_UNUSED_VAR(filename); CYTHON_MAYBE_UNUSED_VAR(nogil); __Pyx_PyThreadState_assign __Pyx_ErrFetch(&old_exc, &old_val, &old_tb); if (full_traceback) { Py_XINCREF(old_exc); Py_XINCREF(old_val); Py_XINCREF(old_tb); __Pyx_ErrRestore(old_exc, old_val, old_tb); PyErr_PrintEx(1); } #if PY_MAJOR_VERSION < 3 ctx = PyString_FromString(name); #else ctx = PyUnicode_FromString(name); #endif __Pyx_ErrRestore(old_exc, old_val, old_tb); if (!ctx) { PyErr_WriteUnraisable(Py_None); } else { PyErr_WriteUnraisable(ctx); Py_DECREF(ctx); } #ifdef WITH_THREAD if (nogil) PyGILState_Release(state); #endif } /////////////// CLineInTraceback.proto /////////////// #ifdef CYTHON_CLINE_IN_TRACEBACK /* 0 or 1 to disable/enable C line display in tracebacks at C compile time */ #define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) #else static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line);/*proto*/ #endif /////////////// CLineInTraceback /////////////// //@requires: ObjectHandling.c::PyObjectGetAttrStrNoError //@requires: ObjectHandling.c::PyDictVersioning //@requires: PyErrFetchRestore //@substitute: naming #ifndef CYTHON_CLINE_IN_TRACEBACK static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) { PyObject *use_cline; PyObject *ptype, *pvalue, *ptraceback; #if CYTHON_COMPILING_IN_CPYTHON PyObject **cython_runtime_dict; #endif CYTHON_MAYBE_UNUSED_VAR(tstate); if (unlikely(!${cython_runtime_cname})) { // Very early error where the runtime module is not set up yet. return c_line; } __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); #if CYTHON_COMPILING_IN_CPYTHON cython_runtime_dict = _PyObject_GetDictPtr(${cython_runtime_cname}); if (likely(cython_runtime_dict)) { __PYX_PY_DICT_LOOKUP_IF_MODIFIED( use_cline, *cython_runtime_dict, __Pyx_PyDict_GetItemStr(*cython_runtime_dict, PYIDENT("cline_in_traceback"))) } else #endif { PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStrNoError(${cython_runtime_cname}, PYIDENT("cline_in_traceback")); if (use_cline_obj) { use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; Py_DECREF(use_cline_obj); } else { PyErr_Clear(); use_cline = NULL; } } if (!use_cline) { c_line = 0; // No need to handle errors here when we reset the exception state just afterwards. (void) PyObject_SetAttr(${cython_runtime_cname}, PYIDENT("cline_in_traceback"), Py_False); } else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { c_line = 0; } __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); return c_line; } #endif /////////////// AddTraceback.proto /////////////// static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename); /*proto*/ /////////////// AddTraceback /////////////// //@requires: ModuleSetupCode.c::CodeObjectCache //@requires: CLineInTraceback //@substitute: naming #include "compile.h" #include "frameobject.h" #include "traceback.h" #if PY_VERSION_HEX >= 0x030b00a6 && !CYTHON_COMPILING_IN_LIMITED_API #ifndef Py_BUILD_CORE #define Py_BUILD_CORE 1 #endif #include "internal/pycore_frame.h" #endif #if CYTHON_COMPILING_IN_LIMITED_API static PyObject *__Pyx_PyCode_Replace_For_AddTraceback(PyObject *code, PyObject *scratch_dict, PyObject *firstlineno, PyObject *name) { PyObject *replace = NULL; if (unlikely(PyDict_SetItemString(scratch_dict, "co_firstlineno", firstlineno))) return NULL; if (unlikely(PyDict_SetItemString(scratch_dict, "co_name", name))) return NULL; replace = PyObject_GetAttrString(code, "replace"); if (likely(replace)) { PyObject *result; result = PyObject_Call(replace, $empty_tuple, scratch_dict); Py_DECREF(replace); return result; } PyErr_Clear(); #if __PYX_LIMITED_VERSION_HEX < 0x030780000 // If we're here, we're probably on Python <=3.7 which doesn't have code.replace. // In this we take a lazy interpreted route (without regard to performance // since it's fairly old and this is mostly just to get something working) { PyObject *compiled = NULL, *result = NULL; if (unlikely(PyDict_SetItemString(scratch_dict, "code", code))) return NULL; if (unlikely(PyDict_SetItemString(scratch_dict, "type", (PyObject*)(&PyType_Type)))) return NULL; compiled = Py_CompileString( "out = type(code)(\n" " code.co_argcount, code.co_kwonlyargcount, code.co_nlocals, code.co_stacksize,\n" " code.co_flags, code.co_code, code.co_consts, code.co_names,\n" " code.co_varnames, code.co_filename, co_name, co_firstlineno,\n" " code.co_lnotab)\n", "", Py_file_input); if (!compiled) return NULL; result = PyEval_EvalCode(compiled, scratch_dict, scratch_dict); Py_DECREF(compiled); if (!result) PyErr_Print(); Py_DECREF(result); result = PyDict_GetItemString(scratch_dict, "out"); if (result) Py_INCREF(result); return result; } #else return NULL; #endif } static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename) { PyObject *code_object = NULL, *py_py_line = NULL, *py_funcname = NULL, *dict = NULL; PyObject *replace = NULL, *getframe = NULL, *frame = NULL; PyObject *exc_type, *exc_value, *exc_traceback; int success = 0; if (c_line) { // Avoid "unused" warning as long as we don't use this. (void) $cfilenm_cname; (void) __Pyx_CLineForTraceback(__Pyx_PyThreadState_Current, c_line); } // DW - this is a horrendous hack, but I'm quite proud of it. Essentially // we need to generate a frame with the right line number/filename/funcname. // We do this by compiling a small bit of code that uses sys._getframe to get a // frame, and then customizing the details of the code to match. // We then run the code object and use the generated frame to set the traceback. PyErr_Fetch(&exc_type, &exc_value, &exc_traceback); code_object = Py_CompileString("_getframe()", filename, Py_eval_input); if (unlikely(!code_object)) goto bad; py_py_line = PyLong_FromLong(py_line); if (unlikely(!py_py_line)) goto bad; py_funcname = PyUnicode_FromString(funcname); if (unlikely(!py_funcname)) goto bad; dict = PyDict_New(); if (unlikely(!dict)) goto bad; { PyObject *old_code_object = code_object; code_object = __Pyx_PyCode_Replace_For_AddTraceback(code_object, dict, py_py_line, py_funcname); Py_DECREF(old_code_object); } if (unlikely(!code_object)) goto bad; // Note that getframe is borrowed getframe = PySys_GetObject("_getframe"); if (unlikely(!getframe)) goto bad; // reuse dict as globals (nothing conflicts, and it saves an allocation) if (unlikely(PyDict_SetItemString(dict, "_getframe", getframe))) goto bad; frame = PyEval_EvalCode(code_object, dict, dict); if (unlikely(!frame) || frame == Py_None) goto bad; success = 1; bad: PyErr_Restore(exc_type, exc_value, exc_traceback); Py_XDECREF(code_object); Py_XDECREF(py_py_line); Py_XDECREF(py_funcname); Py_XDECREF(dict); Py_XDECREF(replace); if (success) { // Unfortunately an easy way to check the type of frame isn't in the // limited API. The check against None should cover the most // likely wrong answer though. PyTraceBack_Here( // Python < 0x03090000 didn't expose PyFrameObject // but they all expose struct _frame as an opaque type (struct _frame*)frame); } Py_XDECREF(frame); } #else static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( const char *funcname, int c_line, int py_line, const char *filename) { PyCodeObject *py_code = NULL; PyObject *py_funcname = NULL; #if PY_MAJOR_VERSION < 3 PyObject *py_srcfile = NULL; py_srcfile = PyString_FromString(filename); if (!py_srcfile) goto bad; #endif if (c_line) { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, $cfilenm_cname, c_line); if (!py_funcname) goto bad; #else py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, $cfilenm_cname, c_line); if (!py_funcname) goto bad; funcname = PyUnicode_AsUTF8(py_funcname); if (!funcname) goto bad; #endif } else { #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromString(funcname); if (!py_funcname) goto bad; #endif } #if PY_MAJOR_VERSION < 3 py_code = __Pyx_PyCode_New( 0, /*int argcount,*/ 0, /*int posonlyargcount,*/ 0, /*int kwonlyargcount,*/ 0, /*int nlocals,*/ 0, /*int stacksize,*/ 0, /*int flags,*/ $empty_bytes, /*PyObject *code,*/ $empty_tuple, /*PyObject *consts,*/ $empty_tuple, /*PyObject *names,*/ $empty_tuple, /*PyObject *varnames,*/ $empty_tuple, /*PyObject *freevars,*/ $empty_tuple, /*PyObject *cellvars,*/ py_srcfile, /*PyObject *filename,*/ py_funcname, /*PyObject *name,*/ py_line, /*int firstlineno,*/ $empty_bytes /*PyObject *lnotab*/ ); Py_DECREF(py_srcfile); #else py_code = PyCode_NewEmpty(filename, funcname, py_line); #endif Py_XDECREF(py_funcname); /* XDECREF since it's only set on Py3 if cline */ return py_code; bad: Py_XDECREF(py_funcname); #if PY_MAJOR_VERSION < 3 Py_XDECREF(py_srcfile); #endif return NULL; } static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename) { PyCodeObject *py_code = 0; PyFrameObject *py_frame = 0; PyThreadState *tstate = __Pyx_PyThreadState_Current; PyObject *ptype, *pvalue, *ptraceback; if (c_line) { c_line = __Pyx_CLineForTraceback(tstate, c_line); } // Negate to avoid collisions between py and c lines. py_code = $global_code_object_cache_find(c_line ? -c_line : py_line); if (!py_code) { __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); py_code = __Pyx_CreateCodeObjectForTraceback( funcname, c_line, py_line, filename); if (!py_code) { /* If the code object creation fails, then we should clear the fetched exception references and propagate the new exception */ Py_XDECREF(ptype); Py_XDECREF(pvalue); Py_XDECREF(ptraceback); goto bad; } __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); $global_code_object_cache_insert(c_line ? -c_line : py_line, py_code); } py_frame = PyFrame_New( tstate, /*PyThreadState *tstate,*/ py_code, /*PyCodeObject *code,*/ $moddict_cname, /*PyObject *globals,*/ 0 /*PyObject *locals*/ ); if (!py_frame) goto bad; __Pyx_PyFrame_SetLineNumber(py_frame, py_line); PyTraceBack_Here(py_frame); bad: Py_XDECREF(py_code); Py_XDECREF(py_frame); } #endif ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/ExtensionTypes.c0000644000175100001770000006151100000000000021654 0ustar00runnerdocker00000000000000/////////////// FixUpExtensionType.proto /////////////// #if CYTHON_USE_TYPE_SPECS static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject *type); /*proto*/ #endif /////////////// FixUpExtensionType /////////////// //@requires:ModuleSetupCode.c::IncludeStructmemberH //@requires:StringTools.c::IncludeStringH #if CYTHON_USE_TYPE_SPECS static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject *type) { #if PY_VERSION_HEX > 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API CYTHON_UNUSED_VAR(spec); CYTHON_UNUSED_VAR(type); #else // Set tp_weakreflist, tp_dictoffset, tp_vectorcalloffset // Copied and adapted from https://bugs.python.org/issue38140 const PyType_Slot *slot = spec->slots; while (slot && slot->slot && slot->slot != Py_tp_members) slot++; if (slot && slot->slot == Py_tp_members) { int changed = 0; #if !(PY_VERSION_HEX <= 0x030900b1 && CYTHON_COMPILING_IN_CPYTHON) const #endif PyMemberDef *memb = (PyMemberDef*) slot->pfunc; while (memb && memb->name) { if (memb->name[0] == '_' && memb->name[1] == '_') { #if PY_VERSION_HEX < 0x030900b1 if (strcmp(memb->name, "__weaklistoffset__") == 0) { // The PyMemberDef must be a Py_ssize_t and readonly. assert(memb->type == T_PYSSIZET); assert(memb->flags == READONLY); type->tp_weaklistoffset = memb->offset; // FIXME: is it even worth calling PyType_Modified() here? changed = 1; } else if (strcmp(memb->name, "__dictoffset__") == 0) { // The PyMemberDef must be a Py_ssize_t and readonly. assert(memb->type == T_PYSSIZET); assert(memb->flags == READONLY); type->tp_dictoffset = memb->offset; // FIXME: is it even worth calling PyType_Modified() here? changed = 1; } #if CYTHON_METH_FASTCALL else if (strcmp(memb->name, "__vectorcalloffset__") == 0) { // The PyMemberDef must be a Py_ssize_t and readonly. assert(memb->type == T_PYSSIZET); assert(memb->flags == READONLY); #if PY_VERSION_HEX >= 0x030800b4 type->tp_vectorcall_offset = memb->offset; #else type->tp_print = (printfunc) memb->offset; #endif // FIXME: is it even worth calling PyType_Modified() here? changed = 1; } #endif #else if ((0)); #endif #if PY_VERSION_HEX <= 0x030900b1 && CYTHON_COMPILING_IN_CPYTHON else if (strcmp(memb->name, "__module__") == 0) { // PyType_FromSpec() in CPython <= 3.9b1 overwrites this field with a constant string. // See https://bugs.python.org/issue40703 PyObject *descr; // The PyMemberDef must be an object and normally readable, possibly writable. assert(memb->type == T_OBJECT); assert(memb->flags == 0 || memb->flags == READONLY); descr = PyDescr_NewMember(type, memb); if (unlikely(!descr)) return -1; if (unlikely(PyDict_SetItem(type->tp_dict, PyDescr_NAME(descr), descr) < 0)) { Py_DECREF(descr); return -1; } Py_DECREF(descr); changed = 1; } #endif } memb++; } if (changed) PyType_Modified(type); } #endif return 0; } #endif /////////////// ValidateBasesTuple.proto /////////////// #if CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_LIMITED_API || CYTHON_USE_TYPE_SPECS static int __Pyx_validate_bases_tuple(const char *type_name, Py_ssize_t dictoffset, PyObject *bases); /*proto*/ #endif /////////////// ValidateBasesTuple /////////////// #if CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_LIMITED_API || CYTHON_USE_TYPE_SPECS static int __Pyx_validate_bases_tuple(const char *type_name, Py_ssize_t dictoffset, PyObject *bases) { // Loop over all bases (except the first) and check that those // really are heap types. Otherwise, it would not be safe to // subclass them. // // We also check tp_dictoffset: it is unsafe to inherit // tp_dictoffset from a base class because the object structures // would not be compatible. So, if our extension type doesn't set // tp_dictoffset (i.e. there is no __dict__ attribute in the object // structure), we need to check that none of the base classes sets // it either. Py_ssize_t i, n; #if CYTHON_ASSUME_SAFE_MACROS n = PyTuple_GET_SIZE(bases); #else n = PyTuple_Size(bases); if (n < 0) return -1; #endif for (i = 1; i < n; i++) /* Skip first base */ { #if CYTHON_AVOID_BORROWED_REFS PyObject *b0 = PySequence_GetItem(bases, i); if (!b0) return -1; #elif CYTHON_ASSUME_SAFE_MACROS PyObject *b0 = PyTuple_GET_ITEM(bases, i); #else PyObject *b0 = PyTuple_GetItem(bases, i); if (!b0) return -1; #endif PyTypeObject *b; #if PY_MAJOR_VERSION < 3 /* Disallow old-style classes */ if (PyClass_Check(b0)) { PyErr_Format(PyExc_TypeError, "base class '%.200s' is an old-style class", PyString_AS_STRING(((PyClassObject*)b0)->cl_name)); #if CYTHON_AVOID_BORROWED_REFS Py_DECREF(b0); #endif return -1; } #endif b = (PyTypeObject*) b0; if (!__Pyx_PyType_HasFeature(b, Py_TPFLAGS_HEAPTYPE)) { __Pyx_TypeName b_name = __Pyx_PyType_GetName(b); PyErr_Format(PyExc_TypeError, "base class '" __Pyx_FMT_TYPENAME "' is not a heap type", b_name); __Pyx_DECREF_TypeName(b_name); #if CYTHON_AVOID_BORROWED_REFS Py_DECREF(b0); #endif return -1; } if (dictoffset == 0) { Py_ssize_t b_dictoffset = 0; #if CYTHON_USE_TYPE_SLOTS || CYTHON_COMPILING_IN_PYPY b_dictoffset = b->tp_dictoffset; #else PyObject *py_b_dictoffset = PyObject_GetAttrString((PyObject*)b, "__dictoffset__"); if (!py_b_dictoffset) goto dictoffset_return; b_dictoffset = PyLong_AsSsize_t(py_b_dictoffset); Py_DECREF(py_b_dictoffset); if (b_dictoffset == -1 && PyErr_Occurred()) goto dictoffset_return; #endif if (b_dictoffset) { { __Pyx_TypeName b_name = __Pyx_PyType_GetName(b); PyErr_Format(PyExc_TypeError, "extension type '%.200s' has no __dict__ slot, " "but base type '" __Pyx_FMT_TYPENAME "' has: " "either add 'cdef dict __dict__' to the extension type " "or add '__slots__ = [...]' to the base type", type_name, b_name); __Pyx_DECREF_TypeName(b_name); } #if !(CYTHON_USE_TYPE_SLOTS || CYTHON_COMPILING_IN_PYPY) dictoffset_return: #endif #if CYTHON_AVOID_BORROWED_REFS Py_DECREF(b0); #endif return -1; } } #if CYTHON_AVOID_BORROWED_REFS Py_DECREF(b0); #endif } return 0; } #endif /////////////// PyType_Ready.proto /////////////// // unused when using type specs CYTHON_UNUSED static int __Pyx_PyType_Ready(PyTypeObject *t);/*proto*/ /////////////// PyType_Ready /////////////// //@requires: ObjectHandling.c::PyObjectCallMethod0 //@requires: ValidateBasesTuple // Wrapper around PyType_Ready() with some runtime checks and fixes // to deal with multiple inheritance. static int __Pyx_PyType_Ready(PyTypeObject *t) { // FIXME: is this really suitable for CYTHON_COMPILING_IN_LIMITED_API? #if CYTHON_USE_TYPE_SPECS || !(CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_LIMITED_API) || defined(PYSTON_MAJOR_VERSION) // avoid C warning about unused helper function (void)__Pyx_PyObject_CallMethod0; #if CYTHON_USE_TYPE_SPECS (void)__Pyx_validate_bases_tuple; #endif return PyType_Ready(t); #else int r; PyObject *bases = __Pyx_PyType_GetSlot(t, tp_bases, PyObject*); if (bases && unlikely(__Pyx_validate_bases_tuple(t->tp_name, t->tp_dictoffset, bases) == -1)) return -1; #if PY_VERSION_HEX >= 0x03050000 && !defined(PYSTON_MAJOR_VERSION) { // Make sure GC does not pick up our non-heap type as heap type with this hack! // For details, see https://github.com/cython/cython/issues/3603 int gc_was_enabled; #if PY_VERSION_HEX >= 0x030A00b1 // finally added in Py3.10 :) gc_was_enabled = PyGC_Disable(); (void)__Pyx_PyObject_CallMethod0; #else // Call gc.disable() as a backwards compatible fallback, but only if needed. PyObject *ret, *py_status; PyObject *gc = NULL; #if PY_VERSION_HEX >= 0x030700a1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM+0 >= 0x07030400) // https://foss.heptapod.net/pypy/pypy/-/issues/3385 gc = PyImport_GetModule(PYUNICODE("gc")); #endif if (unlikely(!gc)) gc = PyImport_Import(PYUNICODE("gc")); if (unlikely(!gc)) return -1; py_status = __Pyx_PyObject_CallMethod0(gc, PYUNICODE("isenabled")); if (unlikely(!py_status)) { Py_DECREF(gc); return -1; } gc_was_enabled = __Pyx_PyObject_IsTrue(py_status); Py_DECREF(py_status); if (gc_was_enabled > 0) { ret = __Pyx_PyObject_CallMethod0(gc, PYUNICODE("disable")); if (unlikely(!ret)) { Py_DECREF(gc); return -1; } Py_DECREF(ret); } else if (unlikely(gc_was_enabled == -1)) { Py_DECREF(gc); return -1; } #endif // As of https://bugs.python.org/issue22079 // PyType_Ready enforces that all bases of a non-heap type are // non-heap. We know that this is the case for the solid base but // other bases are heap allocated and are kept alive through the // tp_bases reference. // Other than this check, the Py_TPFLAGS_HEAPTYPE flag is unused // in PyType_Ready(). t->tp_flags |= Py_TPFLAGS_HEAPTYPE; #if PY_VERSION_HEX >= 0x030A0000 // As of https://github.com/python/cpython/pull/25520 // PyType_Ready marks types as immutable if they are static types // and requires the Py_TPFLAGS_IMMUTABLETYPE flag to mark types as // immutable // Manually set the Py_TPFLAGS_IMMUTABLETYPE flag, since the type // is immutable t->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE; #endif #else // avoid C warning about unused helper function (void)__Pyx_PyObject_CallMethod0; #endif r = PyType_Ready(t); #if PY_VERSION_HEX >= 0x03050000 && !defined(PYSTON_MAJOR_VERSION) t->tp_flags &= ~Py_TPFLAGS_HEAPTYPE; #if PY_VERSION_HEX >= 0x030A00b1 if (gc_was_enabled) PyGC_Enable(); #else if (gc_was_enabled) { PyObject *tp, *v, *tb; PyErr_Fetch(&tp, &v, &tb); ret = __Pyx_PyObject_CallMethod0(gc, PYUNICODE("enable")); if (likely(ret || r == -1)) { Py_XDECREF(ret); // do not overwrite exceptions raised by PyType_Ready() above PyErr_Restore(tp, v, tb); } else { // PyType_Ready() succeeded, but gc.enable() failed. Py_XDECREF(tp); Py_XDECREF(v); Py_XDECREF(tb); r = -1; } } Py_DECREF(gc); #endif } #endif return r; #endif } /////////////// PyTrashcan.proto /////////////// // These macros are taken from https://github.com/python/cpython/pull/11841 // Unlike the Py_TRASHCAN_SAFE_BEGIN/Py_TRASHCAN_SAFE_END macros, they // allow dealing correctly with subclasses. // This requires CPython version >= 2.7.4 // (or >= 3.2.4 but we don't support such old Python 3 versions anyway) #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03080000 // https://github.com/python/cpython/pull/11841 merged so Cython reimplementation // is no longer necessary #define __Pyx_TRASHCAN_BEGIN Py_TRASHCAN_BEGIN #define __Pyx_TRASHCAN_END Py_TRASHCAN_END #elif CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x02070400 #define __Pyx_TRASHCAN_BEGIN_CONDITION(op, cond) \ do { \ PyThreadState *_tstate = NULL; \ // If "cond" is false, then _tstate remains NULL and the deallocator // is run normally without involving the trashcan if (cond) { \ _tstate = PyThreadState_GET(); \ if (_tstate->trash_delete_nesting >= PyTrash_UNWIND_LEVEL) { \ // Store the object (to be deallocated later) and jump past // Py_TRASHCAN_END, skipping the body of the deallocator _PyTrash_thread_deposit_object((PyObject*)(op)); \ break; \ } \ ++_tstate->trash_delete_nesting; \ } // The body of the deallocator is here. #define __Pyx_TRASHCAN_END \ if (_tstate) { \ --_tstate->trash_delete_nesting; \ if (_tstate->trash_delete_later && _tstate->trash_delete_nesting <= 0) \ _PyTrash_thread_destroy_chain(); \ } \ } while (0); #define __Pyx_TRASHCAN_BEGIN(op, dealloc) __Pyx_TRASHCAN_BEGIN_CONDITION(op, \ __Pyx_PyObject_GetSlot(op, tp_dealloc, destructor) == (destructor)(dealloc)) #else // The trashcan is a no-op on other Python implementations // or old CPython versions #define __Pyx_TRASHCAN_BEGIN(op, dealloc) #define __Pyx_TRASHCAN_END #endif /////////////// CallNextTpDealloc.proto /////////////// static void __Pyx_call_next_tp_dealloc(PyObject* obj, destructor current_tp_dealloc); /////////////// CallNextTpDealloc /////////////// static void __Pyx_call_next_tp_dealloc(PyObject* obj, destructor current_tp_dealloc) { PyTypeObject* type = Py_TYPE(obj); destructor tp_dealloc = NULL; /* try to find the first parent type that has a different tp_dealloc() function */ while (type && __Pyx_PyType_GetSlot(type, tp_dealloc, destructor) != current_tp_dealloc) type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*); while (type && (tp_dealloc = __Pyx_PyType_GetSlot(type, tp_dealloc, destructor)) == current_tp_dealloc) type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*); if (type) tp_dealloc(obj); } /////////////// CallNextTpTraverse.proto /////////////// static int __Pyx_call_next_tp_traverse(PyObject* obj, visitproc v, void *a, traverseproc current_tp_traverse); /////////////// CallNextTpTraverse /////////////// static int __Pyx_call_next_tp_traverse(PyObject* obj, visitproc v, void *a, traverseproc current_tp_traverse) { PyTypeObject* type = Py_TYPE(obj); traverseproc tp_traverse = NULL; /* try to find the first parent type that has a different tp_traverse() function */ while (type && __Pyx_PyType_GetSlot(type, tp_traverse, traverseproc) != current_tp_traverse) type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*); while (type && (tp_traverse = __Pyx_PyType_GetSlot(type, tp_traverse, traverseproc)) == current_tp_traverse) type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*); if (type && tp_traverse) return tp_traverse(obj, v, a); // FIXME: really ignore? return 0; } /////////////// CallNextTpClear.proto /////////////// static void __Pyx_call_next_tp_clear(PyObject* obj, inquiry current_tp_clear); /////////////// CallNextTpClear /////////////// static void __Pyx_call_next_tp_clear(PyObject* obj, inquiry current_tp_clear) { PyTypeObject* type = Py_TYPE(obj); inquiry tp_clear = NULL; /* try to find the first parent type that has a different tp_clear() function */ while (type && __Pyx_PyType_GetSlot(type, tp_clear, inquiry) != current_tp_clear) type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*); while (type && (tp_clear = __Pyx_PyType_GetSlot(type, tp_clear, inquiry)) == current_tp_clear) type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*); if (type && tp_clear) tp_clear(obj); } /////////////// SetupReduce.proto /////////////// #if !CYTHON_COMPILING_IN_LIMITED_API static int __Pyx_setup_reduce(PyObject* type_obj); #endif /////////////// SetupReduce /////////////// //@requires: ObjectHandling.c::PyObjectGetAttrStrNoError //@requires: ObjectHandling.c::PyObjectGetAttrStr //@substitute: naming #if !CYTHON_COMPILING_IN_LIMITED_API static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) { int ret; PyObject *name_attr; name_attr = __Pyx_PyObject_GetAttrStrNoError(meth, PYIDENT("__name__")); if (likely(name_attr)) { ret = PyObject_RichCompareBool(name_attr, name, Py_EQ); } else { ret = -1; } if (unlikely(ret < 0)) { PyErr_Clear(); ret = 0; } Py_XDECREF(name_attr); return ret; } static int __Pyx_setup_reduce(PyObject* type_obj) { int ret = 0; PyObject *object_reduce = NULL; PyObject *object_getstate = NULL; PyObject *object_reduce_ex = NULL; PyObject *reduce = NULL; PyObject *reduce_ex = NULL; PyObject *reduce_cython = NULL; PyObject *setstate = NULL; PyObject *setstate_cython = NULL; PyObject *getstate = NULL; #if CYTHON_USE_PYTYPE_LOOKUP getstate = _PyType_Lookup((PyTypeObject*)type_obj, PYIDENT("__getstate__")); #else getstate = __Pyx_PyObject_GetAttrStrNoError(type_obj, PYIDENT("__getstate__")); if (!getstate && PyErr_Occurred()) { goto __PYX_BAD; } #endif if (getstate) { // Python 3.11 introduces object.__getstate__. Because it's version-specific failure to find it should not be an error #if CYTHON_USE_PYTYPE_LOOKUP object_getstate = _PyType_Lookup(&PyBaseObject_Type, PYIDENT("__getstate__")); #else object_getstate = __Pyx_PyObject_GetAttrStrNoError((PyObject*)&PyBaseObject_Type, PYIDENT("__getstate__")); if (!object_getstate && PyErr_Occurred()) { goto __PYX_BAD; } #endif if (object_getstate != getstate) { goto __PYX_GOOD; } } #if CYTHON_USE_PYTYPE_LOOKUP object_reduce_ex = _PyType_Lookup(&PyBaseObject_Type, PYIDENT("__reduce_ex__")); if (!object_reduce_ex) goto __PYX_BAD; #else object_reduce_ex = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, PYIDENT("__reduce_ex__")); if (!object_reduce_ex) goto __PYX_BAD; #endif reduce_ex = __Pyx_PyObject_GetAttrStr(type_obj, PYIDENT("__reduce_ex__")); if (unlikely(!reduce_ex)) goto __PYX_BAD; if (reduce_ex == object_reduce_ex) { #if CYTHON_USE_PYTYPE_LOOKUP object_reduce = _PyType_Lookup(&PyBaseObject_Type, PYIDENT("__reduce__")); if (!object_reduce) goto __PYX_BAD; #else object_reduce = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, PYIDENT("__reduce__")); if (!object_reduce) goto __PYX_BAD; #endif reduce = __Pyx_PyObject_GetAttrStr(type_obj, PYIDENT("__reduce__")); if (unlikely(!reduce)) goto __PYX_BAD; if (reduce == object_reduce || __Pyx_setup_reduce_is_named(reduce, PYIDENT("__reduce_cython__"))) { reduce_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, PYIDENT("__reduce_cython__")); if (likely(reduce_cython)) { ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__reduce__"), reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__reduce_cython__")); if (unlikely(ret < 0)) goto __PYX_BAD; } else if (reduce == object_reduce || PyErr_Occurred()) { // Ignore if we're done, i.e. if 'reduce' already has the right name and the original is gone. // Otherwise: error. goto __PYX_BAD; } setstate = __Pyx_PyObject_GetAttrStrNoError(type_obj, PYIDENT("__setstate__")); if (!setstate) PyErr_Clear(); if (!setstate || __Pyx_setup_reduce_is_named(setstate, PYIDENT("__setstate_cython__"))) { setstate_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, PYIDENT("__setstate_cython__")); if (likely(setstate_cython)) { ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__setstate__"), setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__setstate_cython__")); if (unlikely(ret < 0)) goto __PYX_BAD; } else if (!setstate || PyErr_Occurred()) { // Ignore if we're done, i.e. if 'setstate' already has the right name and the original is gone. // Otherwise: error. goto __PYX_BAD; } } PyType_Modified((PyTypeObject*)type_obj); } } goto __PYX_GOOD; __PYX_BAD: if (!PyErr_Occurred()) { __Pyx_TypeName type_obj_name = __Pyx_PyType_GetName((PyTypeObject*)type_obj); PyErr_Format(PyExc_RuntimeError, "Unable to initialize pickling for " __Pyx_FMT_TYPENAME, type_obj_name); __Pyx_DECREF_TypeName(type_obj_name); } ret = -1; __PYX_GOOD: #if !CYTHON_USE_PYTYPE_LOOKUP Py_XDECREF(object_reduce); Py_XDECREF(object_reduce_ex); Py_XDECREF(object_getstate); Py_XDECREF(getstate); #endif Py_XDECREF(reduce); Py_XDECREF(reduce_ex); Py_XDECREF(reduce_cython); Py_XDECREF(setstate); Py_XDECREF(setstate_cython); return ret; } #endif /////////////// BinopSlot /////////////// static CYTHON_INLINE PyObject *{{func_name}}_maybe_call_slot(PyTypeObject* type, PyObject *left, PyObject *right {{extra_arg_decl}}) { {{slot_type}} slot; #if CYTHON_USE_TYPE_SLOTS || PY_MAJOR_VERSION < 3 || CYTHON_COMPILING_IN_PYPY slot = type->tp_as_number ? type->tp_as_number->{{slot_name}} : NULL; #else slot = ({{slot_type}}) PyType_GetSlot(type, Py_{{slot_name}}); #endif return slot ? slot(left, right {{extra_arg}}) : __Pyx_NewRef(Py_NotImplemented); } static PyObject *{{func_name}}(PyObject *left, PyObject *right {{extra_arg_decl}}) { int maybe_self_is_left, maybe_self_is_right = 0; maybe_self_is_left = Py_TYPE(left) == Py_TYPE(right) #if CYTHON_USE_TYPE_SLOTS || (Py_TYPE(left)->tp_as_number && Py_TYPE(left)->tp_as_number->{{slot_name}} == &{{func_name}}) #endif || __Pyx_TypeCheck(left, {{type_cname}}); // Optimize for the common case where the left operation is defined (and successful). {{if not overloads_left}} maybe_self_is_right = Py_TYPE(left) == Py_TYPE(right) #if CYTHON_USE_TYPE_SLOTS || (Py_TYPE(right)->tp_as_number && Py_TYPE(right)->tp_as_number->{{slot_name}} == &{{func_name}}) #endif || __Pyx_TypeCheck(right, {{type_cname}}); {{endif}} if (maybe_self_is_left) { PyObject *res; {{if overloads_right and not overloads_left}} if (maybe_self_is_right) { res = {{call_right}}; if (res != Py_NotImplemented) return res; Py_DECREF(res); // Don't bother calling it again. maybe_self_is_right = 0; } {{endif}} res = {{call_left}}; if (res != Py_NotImplemented) return res; Py_DECREF(res); } {{if overloads_left}} maybe_self_is_right = Py_TYPE(left) == Py_TYPE(right) #if CYTHON_USE_TYPE_SLOTS || (Py_TYPE(right)->tp_as_number && Py_TYPE(right)->tp_as_number->{{slot_name}} == &{{func_name}}) #endif || PyType_IsSubtype(Py_TYPE(right), {{type_cname}}); {{endif}} if (maybe_self_is_right) { return {{call_right}}; } return __Pyx_NewRef(Py_NotImplemented); } /////////////// ValidateExternBase.proto /////////////// static int __Pyx_validate_extern_base(PyTypeObject *base); /* proto */ /////////////// ValidateExternBase /////////////// //@requires: ObjectHandling.c::FormatTypeName static int __Pyx_validate_extern_base(PyTypeObject *base) { Py_ssize_t itemsize; #if CYTHON_COMPILING_IN_LIMITED_API PyObject *py_itemsize; #endif #if !CYTHON_COMPILING_IN_LIMITED_API itemsize = ((PyTypeObject *)base)->tp_itemsize; #else py_itemsize = PyObject_GetAttrString((PyObject*)base, "__itemsize__"); if (!py_itemsize) return -1; itemsize = PyLong_AsSsize_t(py_itemsize); Py_DECREF(py_itemsize); py_itemsize = 0; if (itemsize == (Py_ssize_t)-1 && PyErr_Occurred()) return -1; #endif if (itemsize) { __Pyx_TypeName b_name = __Pyx_PyType_GetName(base); PyErr_Format(PyExc_TypeError, "inheritance from PyVarObject types like '" __Pyx_FMT_TYPENAME "' not currently supported", b_name); __Pyx_DECREF_TypeName(b_name); return -1; } return 0; } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/FunctionArguments.c0000644000175100001770000005040400000000000022325 0ustar00runnerdocker00000000000000//////////////////// ArgTypeTest.proto //////////////////// #define __Pyx_ArgTypeTest(obj, type, none_allowed, name, exact) \ ((likely(__Pyx_IS_TYPE(obj, type) | (none_allowed && (obj == Py_None)))) ? 1 : \ __Pyx__ArgTypeTest(obj, type, name, exact)) static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact); /*proto*/ //////////////////// ArgTypeTest //////////////////// static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact) { __Pyx_TypeName type_name; __Pyx_TypeName obj_type_name; if (unlikely(!type)) { PyErr_SetString(PyExc_SystemError, "Missing type object"); return 0; } else if (exact) { #if PY_MAJOR_VERSION == 2 if ((type == &PyBaseString_Type) && likely(__Pyx_PyBaseString_CheckExact(obj))) return 1; #endif } else { if (likely(__Pyx_TypeCheck(obj, type))) return 1; } type_name = __Pyx_PyType_GetName(type); obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj)); PyErr_Format(PyExc_TypeError, "Argument '%.200s' has incorrect type (expected " __Pyx_FMT_TYPENAME ", got " __Pyx_FMT_TYPENAME ")", name, type_name, obj_type_name); __Pyx_DECREF_TypeName(type_name); __Pyx_DECREF_TypeName(obj_type_name); return 0; } //////////////////// RaiseArgTupleInvalid.proto //////////////////// static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/ //////////////////// RaiseArgTupleInvalid //////////////////// // __Pyx_RaiseArgtupleInvalid raises the correct exception when too // many or too few positional arguments were found. This handles // Py_ssize_t formatting correctly. static void __Pyx_RaiseArgtupleInvalid( const char* func_name, int exact, Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found) { Py_ssize_t num_expected; const char *more_or_less; if (num_found < num_min) { num_expected = num_min; more_or_less = "at least"; } else { num_expected = num_max; more_or_less = "at most"; } if (exact) { more_or_less = "exactly"; } PyErr_Format(PyExc_TypeError, "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", func_name, more_or_less, num_expected, (num_expected == 1) ? "" : "s", num_found); } //////////////////// RaiseKeywordRequired.proto //////////////////// static void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/ //////////////////// RaiseKeywordRequired //////////////////// static void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name) { PyErr_Format(PyExc_TypeError, #if PY_MAJOR_VERSION >= 3 "%s() needs keyword-only argument %U", func_name, kw_name); #else "%s() needs keyword-only argument %s", func_name, PyString_AS_STRING(kw_name)); #endif } //////////////////// RaiseDoubleKeywords.proto //////////////////// static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); /*proto*/ //////////////////// RaiseDoubleKeywords //////////////////// static void __Pyx_RaiseDoubleKeywordsError( const char* func_name, PyObject* kw_name) { PyErr_Format(PyExc_TypeError, #if PY_MAJOR_VERSION >= 3 "%s() got multiple values for keyword argument '%U'", func_name, kw_name); #else "%s() got multiple values for keyword argument '%s'", func_name, PyString_AsString(kw_name)); #endif } //////////////////// RaiseMappingExpected.proto //////////////////// static void __Pyx_RaiseMappingExpectedError(PyObject* arg); /*proto*/ //////////////////// RaiseMappingExpected //////////////////// static void __Pyx_RaiseMappingExpectedError(PyObject* arg) { __Pyx_TypeName arg_type_name = __Pyx_PyType_GetName(Py_TYPE(arg)); PyErr_Format(PyExc_TypeError, "'" __Pyx_FMT_TYPENAME "' object is not a mapping", arg_type_name); __Pyx_DECREF_TypeName(arg_type_name); } //////////////////// KeywordStringCheck.proto //////////////////// static int __Pyx_CheckKeywordStrings(PyObject *kw, const char* function_name, int kw_allowed); /*proto*/ //////////////////// KeywordStringCheck //////////////////// // __Pyx_CheckKeywordStrings raises an error if non-string keywords // were passed to a function, or if any keywords were passed to a // function that does not accept them. // // The "kw" argument is either a dict (for METH_VARARGS) or a tuple // (for METH_FASTCALL). static int __Pyx_CheckKeywordStrings( PyObject *kw, const char* function_name, int kw_allowed) { PyObject* key = 0; Py_ssize_t pos = 0; #if CYTHON_COMPILING_IN_PYPY /* PyPy appears to check keywords at call time, not at unpacking time => not much to do here */ if (!kw_allowed && PyDict_Next(kw, &pos, &key, 0)) goto invalid_keyword; return 1; #else if (CYTHON_METH_FASTCALL && likely(PyTuple_Check(kw))) { Py_ssize_t kwsize; #if CYTHON_ASSUME_SAFE_MACROS kwsize = PyTuple_GET_SIZE(kw); #else kwsize = PyTuple_Size(kw); if (kwsize < 0) return 0; #endif if (unlikely(kwsize == 0)) return 1; if (!kw_allowed) { #if CYTHON_ASSUME_SAFE_MACROS key = PyTuple_GET_ITEM(kw, 0); #else key = PyTuple_GetItem(kw, pos); if (!key) return 0; #endif goto invalid_keyword; } #if PY_VERSION_HEX < 0x03090000 // On CPython >= 3.9, the FASTCALL protocol guarantees that keyword // names are strings (see https://bugs.python.org/issue37540) for (pos = 0; pos < kwsize; pos++) { #if CYTHON_ASSUME_SAFE_MACROS key = PyTuple_GET_ITEM(kw, pos); #else key = PyTuple_GetItem(kw, pos); if (!key) return 0; #endif if (unlikely(!PyUnicode_Check(key))) goto invalid_keyword_type; } #endif return 1; } while (PyDict_Next(kw, &pos, &key, 0)) { #if PY_MAJOR_VERSION < 3 if (unlikely(!PyString_Check(key))) #endif if (unlikely(!PyUnicode_Check(key))) goto invalid_keyword_type; } if (!kw_allowed && unlikely(key)) goto invalid_keyword; return 1; invalid_keyword_type: PyErr_Format(PyExc_TypeError, "%.200s() keywords must be strings", function_name); return 0; #endif invalid_keyword: #if PY_MAJOR_VERSION < 3 PyErr_Format(PyExc_TypeError, "%.200s() got an unexpected keyword argument '%.200s'", function_name, PyString_AsString(key)); #else PyErr_Format(PyExc_TypeError, "%s() got an unexpected keyword argument '%U'", function_name, key); #endif return 0; } //////////////////// ParseKeywords.proto //////////////////// static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject *const *kwvalues, PyObject **argnames[], PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, const char* function_name); /*proto*/ //////////////////// ParseKeywords //////////////////// //@requires: RaiseDoubleKeywords // __Pyx_ParseOptionalKeywords copies the optional/unknown keyword // arguments from kwds into the dict kwds2. If kwds2 is NULL, unknown // keywords will raise an invalid keyword error. // // When not using METH_FASTCALL, kwds is a dict and kwvalues is NULL. // Otherwise, kwds is a tuple with keyword names and kwvalues is a C // array with the corresponding values. // // Three kinds of errors are checked: 1) non-string keywords, 2) // unexpected keywords and 3) overlap with positional arguments. // // If num_posargs is greater 0, it denotes the number of positional // arguments that were passed and that must therefore not appear // amongst the keywords as well. // // This method does not check for required keyword arguments. static int __Pyx_ParseOptionalKeywords( PyObject *kwds, PyObject *const *kwvalues, PyObject **argnames[], PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, const char* function_name) { PyObject *key = 0, *value = 0; Py_ssize_t pos = 0; PyObject*** name; PyObject*** first_kw_arg = argnames + num_pos_args; int kwds_is_tuple = CYTHON_METH_FASTCALL && likely(PyTuple_Check(kwds)); while (1) { // clean up key and value when the loop is "continued" Py_XDECREF(key); key = NULL; Py_XDECREF(value); value = NULL; if (kwds_is_tuple) { Py_ssize_t size; #if CYTHON_ASSUME_SAFE_MACROS size = PyTuple_GET_SIZE(kwds); #else size = PyTuple_Size(kwds); if (size < 0) goto bad; #endif if (pos >= size) break; #if CYTHON_AVOID_BORROWED_REFS // Get an owned reference to key. key = __Pyx_PySequence_ITEM(kwds, pos); if (!key) goto bad; #elif CYTHON_ASSUME_SAFE_MACROS key = PyTuple_GET_ITEM(kwds, pos); #else key = PyTuple_GetItem(kwds, pos); if (!key) goto bad; #endif value = kwvalues[pos]; pos++; } else { if (!PyDict_Next(kwds, &pos, &key, &value)) break; // It's unfortunately hard to avoid borrowed references (briefly) with PyDict_Next #if CYTHON_AVOID_BORROWED_REFS // Own the reference to match the behaviour above. Py_INCREF(key); #endif } name = first_kw_arg; while (*name && (**name != key)) name++; if (*name) { values[name-argnames] = value; #if CYTHON_AVOID_BORROWED_REFS Py_INCREF(value); /* transfer ownership of value to values */ Py_DECREF(key); #endif key = NULL; value = NULL; continue; } // Now make sure we own both references since we're doing non-trivial Python operations. #if !CYTHON_AVOID_BORROWED_REFS Py_INCREF(key); #endif Py_INCREF(value); name = first_kw_arg; #if PY_MAJOR_VERSION < 3 if (likely(PyString_Check(key))) { while (*name) { if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) && _PyString_Eq(**name, key)) { values[name-argnames] = value; #if CYTHON_AVOID_BORROWED_REFS value = NULL; /* ownership transferred to values */ #endif break; } name++; } if (*name) continue; else { // not found after positional args, check for duplicate PyObject*** argname = argnames; while (argname != first_kw_arg) { if ((**argname == key) || ( (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) && _PyString_Eq(**argname, key))) { goto arg_passed_twice; } argname++; } } } else #endif if (likely(PyUnicode_Check(key))) { while (*name) { int cmp = ( #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 (__Pyx_PyUnicode_GET_LENGTH(**name) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : #endif // In Py2, we may need to convert the argument name from str to unicode for comparison. PyUnicode_Compare(**name, key) ); if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; if (cmp == 0) { values[name-argnames] = value; #if CYTHON_AVOID_BORROWED_REFS value = NULL; /* ownership transferred to values */ #endif break; } name++; } if (*name) continue; else { // not found after positional args, check for duplicate PyObject*** argname = argnames; while (argname != first_kw_arg) { int cmp = (**argname == key) ? 0 : #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 (__Pyx_PyUnicode_GET_LENGTH(**argname) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : #endif // need to convert argument name from bytes to unicode for comparison PyUnicode_Compare(**argname, key); if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; if (cmp == 0) goto arg_passed_twice; argname++; } } } else goto invalid_keyword_type; if (kwds2) { if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; } else { goto invalid_keyword; } } Py_XDECREF(key); Py_XDECREF(value); return 0; arg_passed_twice: __Pyx_RaiseDoubleKeywordsError(function_name, key); goto bad; invalid_keyword_type: PyErr_Format(PyExc_TypeError, "%.200s() keywords must be strings", function_name); goto bad; invalid_keyword: #if PY_MAJOR_VERSION < 3 PyErr_Format(PyExc_TypeError, "%.200s() got an unexpected keyword argument '%.200s'", function_name, PyString_AsString(key)); #else PyErr_Format(PyExc_TypeError, "%s() got an unexpected keyword argument '%U'", function_name, key); #endif bad: Py_XDECREF(key); Py_XDECREF(value); return -1; } //////////////////// MergeKeywords.proto //////////////////// static int __Pyx_MergeKeywords(PyObject *kwdict, PyObject *source_mapping); /*proto*/ //////////////////// MergeKeywords //////////////////// //@requires: RaiseDoubleKeywords //@requires: Optimize.c::dict_iter static int __Pyx_MergeKeywords(PyObject *kwdict, PyObject *source_mapping) { PyObject *iter, *key = NULL, *value = NULL; int source_is_dict, result; Py_ssize_t orig_length, ppos = 0; iter = __Pyx_dict_iterator(source_mapping, 0, PYIDENT("items"), &orig_length, &source_is_dict); if (unlikely(!iter)) { // slow fallback: try converting to dict, then iterate PyObject *args; if (unlikely(!PyErr_ExceptionMatches(PyExc_AttributeError))) goto bad; PyErr_Clear(); args = PyTuple_Pack(1, source_mapping); if (likely(args)) { PyObject *fallback = PyObject_Call((PyObject*)&PyDict_Type, args, NULL); Py_DECREF(args); if (likely(fallback)) { iter = __Pyx_dict_iterator(fallback, 1, PYIDENT("items"), &orig_length, &source_is_dict); Py_DECREF(fallback); } } if (unlikely(!iter)) goto bad; } while (1) { result = __Pyx_dict_iter_next(iter, orig_length, &ppos, &key, &value, NULL, source_is_dict); if (unlikely(result < 0)) goto bad; if (!result) break; if (unlikely(PyDict_Contains(kwdict, key))) { __Pyx_RaiseDoubleKeywordsError("function", key); result = -1; } else { result = PyDict_SetItem(kwdict, key, value); } Py_DECREF(key); Py_DECREF(value); if (unlikely(result < 0)) goto bad; } Py_XDECREF(iter); return 0; bad: Py_XDECREF(iter); return -1; } /////////////// fastcall.proto /////////////// // We define various functions and macros with two variants: //..._FASTCALL and ..._VARARGS // The first is used when METH_FASTCALL is enabled and the second is used // otherwise. If the Python implementation does not support METH_FASTCALL // (because it's an old version of CPython or it's not CPython at all), // then the ..._FASTCALL macros simply alias ..._VARARGS #if CYTHON_AVOID_BORROWED_REFS // This is the only case where we request an owned reference. #define __Pyx_Arg_VARARGS(args, i) PySequence_GetItem(args, i) #elif CYTHON_ASSUME_SAFE_MACROS #define __Pyx_Arg_VARARGS(args, i) PyTuple_GET_ITEM(args, i) #else #define __Pyx_Arg_VARARGS(args, i) PyTuple_GetItem(args, i) #endif #if CYTHON_AVOID_BORROWED_REFS #define __Pyx_Arg_NewRef_VARARGS(arg) __Pyx_NewRef(arg) #define __Pyx_Arg_XDECREF_VARARGS(arg) Py_XDECREF(arg) #else #define __Pyx_Arg_NewRef_VARARGS(arg) arg /* no-op */ #define __Pyx_Arg_XDECREF_VARARGS(arg) /* no-op - arg is borrowed */ #endif #define __Pyx_NumKwargs_VARARGS(kwds) PyDict_Size(kwds) #define __Pyx_KwValues_VARARGS(args, nargs) NULL #define __Pyx_GetKwValue_VARARGS(kw, kwvalues, s) __Pyx_PyDict_GetItemStrWithError(kw, s) #define __Pyx_KwargsAsDict_VARARGS(kw, kwvalues) PyDict_Copy(kw) #if CYTHON_METH_FASTCALL #define __Pyx_Arg_FASTCALL(args, i) args[i] #define __Pyx_NumKwargs_FASTCALL(kwds) PyTuple_GET_SIZE(kwds) #define __Pyx_KwValues_FASTCALL(args, nargs) ((args) + (nargs)) static CYTHON_INLINE PyObject * __Pyx_GetKwValue_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues, PyObject *s); #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030d0000 CYTHON_UNUSED static PyObject *__Pyx_KwargsAsDict_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues);/*proto*/ #else #define __Pyx_KwargsAsDict_FASTCALL(kw, kwvalues) _PyStack_AsDict(kwvalues, kw) #endif #define __Pyx_Arg_NewRef_FASTCALL(arg) arg /* no-op, __Pyx_Arg_FASTCALL is direct and this needs to have the same reference counting */ #define __Pyx_Arg_XDECREF_FASTCALL(arg) /* no-op - arg was returned from array */ #else #define __Pyx_Arg_FASTCALL __Pyx_Arg_VARARGS #define __Pyx_NumKwargs_FASTCALL __Pyx_NumKwargs_VARARGS #define __Pyx_KwValues_FASTCALL __Pyx_KwValues_VARARGS #define __Pyx_GetKwValue_FASTCALL __Pyx_GetKwValue_VARARGS #define __Pyx_KwargsAsDict_FASTCALL __Pyx_KwargsAsDict_VARARGS #define __Pyx_Arg_NewRef_FASTCALL(arg) __Pyx_Arg_NewRef_VARARGS(arg) #define __Pyx_Arg_XDECREF_FASTCALL(arg) __Pyx_Arg_XDECREF_VARARGS(arg) #endif #if CYTHON_COMPILING_IN_CPYTHON && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS #define __Pyx_ArgsSlice_VARARGS(args, start, stop) __Pyx_PyTuple_FromArray(&__Pyx_Arg_VARARGS(args, start), stop - start) #define __Pyx_ArgsSlice_FASTCALL(args, start, stop) __Pyx_PyTuple_FromArray(&__Pyx_Arg_FASTCALL(args, start), stop - start) #else /* Not CPython, so certainly no METH_FASTCALL support */ #define __Pyx_ArgsSlice_VARARGS(args, start, stop) PyTuple_GetSlice(args, start, stop) #define __Pyx_ArgsSlice_FASTCALL(args, start, stop) PyTuple_GetSlice(args, start, stop) #endif /////////////// fastcall /////////////// //@requires: ObjectHandling.c::TupleAndListFromArray //@requires: StringTools.c::UnicodeEquals #if CYTHON_METH_FASTCALL // kwnames: tuple with names of keyword arguments // kwvalues: C array with values of keyword arguments // s: str with the keyword name to look for static CYTHON_INLINE PyObject * __Pyx_GetKwValue_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues, PyObject *s) { // Search the kwnames array for s and return the corresponding value. // We do two loops: a first one to compare pointers (which will find a // match if the name in kwnames is interned, given that s is interned // by Cython). A second loop compares the actual strings. Py_ssize_t i, n = PyTuple_GET_SIZE(kwnames); for (i = 0; i < n; i++) { if (s == PyTuple_GET_ITEM(kwnames, i)) return kwvalues[i]; } for (i = 0; i < n; i++) { int eq = __Pyx_PyUnicode_Equals(s, PyTuple_GET_ITEM(kwnames, i), Py_EQ); if (unlikely(eq != 0)) { if (unlikely(eq < 0)) return NULL; /* error */ return kwvalues[i]; } } return NULL; /* not found (no exception set) */ } #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030d0000 CYTHON_UNUSED static PyObject *__Pyx_KwargsAsDict_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues) { Py_ssize_t i, nkwargs = PyTuple_GET_SIZE(kwnames); PyObject *dict; dict = PyDict_New(); if (unlikely(!dict)) return NULL; for (i=0; i= 3 static PyObject *__Pyx_ImportDottedModule_WalkParts(PyObject *module, PyObject *name, PyObject *parts_tuple); /*proto*/ #endif /////////////// ImportDottedModule /////////////// //@requires: Import #if PY_MAJOR_VERSION >= 3 static PyObject *__Pyx__ImportDottedModule_Error(PyObject *name, PyObject *parts_tuple, Py_ssize_t count) { PyObject *partial_name = NULL, *slice = NULL, *sep = NULL; if (unlikely(PyErr_Occurred())) { PyErr_Clear(); } if (likely(PyTuple_GET_SIZE(parts_tuple) == count)) { partial_name = name; } else { slice = PySequence_GetSlice(parts_tuple, 0, count); if (unlikely(!slice)) goto bad; sep = PyUnicode_FromStringAndSize(".", 1); if (unlikely(!sep)) goto bad; partial_name = PyUnicode_Join(sep, slice); } PyErr_Format( #if PY_MAJOR_VERSION < 3 PyExc_ImportError, "No module named '%s'", PyString_AS_STRING(partial_name)); #else #if PY_VERSION_HEX >= 0x030600B1 PyExc_ModuleNotFoundError, #else PyExc_ImportError, #endif "No module named '%U'", partial_name); #endif bad: Py_XDECREF(sep); Py_XDECREF(slice); Py_XDECREF(partial_name); return NULL; } #endif #if PY_MAJOR_VERSION >= 3 static PyObject *__Pyx__ImportDottedModule_Lookup(PyObject *name) { PyObject *imported_module; #if PY_VERSION_HEX < 0x030700A1 || (CYTHON_COMPILING_IN_PYPY && PYPY_VERSION_NUM < 0x07030400) PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) return NULL; imported_module = __Pyx_PyDict_GetItemStr(modules, name); Py_XINCREF(imported_module); #else imported_module = PyImport_GetModule(name); #endif return imported_module; } #endif #if PY_MAJOR_VERSION >= 3 static PyObject *__Pyx_ImportDottedModule_WalkParts(PyObject *module, PyObject *name, PyObject *parts_tuple) { Py_ssize_t i, nparts; nparts = PyTuple_GET_SIZE(parts_tuple); for (i=1; i < nparts && module; i++) { PyObject *part, *submodule; #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS part = PyTuple_GET_ITEM(parts_tuple, i); #else part = PySequence_ITEM(parts_tuple, i); #endif submodule = __Pyx_PyObject_GetAttrStrNoError(module, part); // We stop if the attribute isn't found, i.e. if submodule is NULL here. #if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS) Py_DECREF(part); #endif Py_DECREF(module); module = submodule; } if (unlikely(!module)) { return __Pyx__ImportDottedModule_Error(name, parts_tuple, i); } return module; } #endif static PyObject *__Pyx__ImportDottedModule(PyObject *name, PyObject *parts_tuple) { #if PY_MAJOR_VERSION < 3 PyObject *module, *from_list, *star = PYIDENT("*"); CYTHON_UNUSED_VAR(parts_tuple); from_list = PyList_New(1); if (unlikely(!from_list)) return NULL; Py_INCREF(star); PyList_SET_ITEM(from_list, 0, star); module = __Pyx_Import(name, from_list, 0); Py_DECREF(from_list); return module; #else PyObject *imported_module; PyObject *module = __Pyx_Import(name, NULL, 0); if (!parts_tuple || unlikely(!module)) return module; // Look up module in sys.modules, which is safer than the attribute lookups below. imported_module = __Pyx__ImportDottedModule_Lookup(name); if (likely(imported_module)) { Py_DECREF(module); return imported_module; } PyErr_Clear(); return __Pyx_ImportDottedModule_WalkParts(module, name, parts_tuple); #endif } static PyObject *__Pyx_ImportDottedModule(PyObject *name, PyObject *parts_tuple) { #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030400B1 PyObject *module = __Pyx__ImportDottedModule_Lookup(name); if (likely(module)) { // CPython guards against thread-concurrent initialisation in importlib. // In this case, we let PyImport_ImportModuleLevelObject() handle the locking. PyObject *spec = __Pyx_PyObject_GetAttrStrNoError(module, PYIDENT("__spec__")); if (likely(spec)) { PyObject *unsafe = __Pyx_PyObject_GetAttrStrNoError(spec, PYIDENT("_initializing")); if (likely(!unsafe || !__Pyx_PyObject_IsTrue(unsafe))) { Py_DECREF(spec); spec = NULL; } Py_XDECREF(unsafe); } if (likely(!spec)) { // Not in initialisation phase => use modules as is. PyErr_Clear(); return module; } Py_DECREF(spec); Py_DECREF(module); } else if (PyErr_Occurred()) { PyErr_Clear(); } #endif return __Pyx__ImportDottedModule(name, parts_tuple); } /////////////// ImportDottedModuleRelFirst.proto /////////////// static PyObject *__Pyx_ImportDottedModuleRelFirst(PyObject *name, PyObject *parts_tuple); /*proto*/ /////////////// ImportDottedModuleRelFirst /////////////// //@requires: ImportDottedModule //@requires: Import static PyObject *__Pyx_ImportDottedModuleRelFirst(PyObject *name, PyObject *parts_tuple) { PyObject *module; PyObject *from_list = NULL; #if PY_MAJOR_VERSION < 3 PyObject *star = PYIDENT("*"); from_list = PyList_New(1); if (unlikely(!from_list)) return NULL; Py_INCREF(star); PyList_SET_ITEM(from_list, 0, star); #endif module = __Pyx_Import(name, from_list, -1); Py_XDECREF(from_list); if (module) { #if PY_MAJOR_VERSION >= 3 if (parts_tuple) { module = __Pyx_ImportDottedModule_WalkParts(module, name, parts_tuple); } #endif return module; } if (unlikely(!PyErr_ExceptionMatches(PyExc_ImportError))) return NULL; PyErr_Clear(); // try absolute import return __Pyx_ImportDottedModule(name, parts_tuple); } /////////////// Import.proto /////////////// static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); /*proto*/ /////////////// Import /////////////// //@requires: ObjectHandling.c::PyObjectGetAttrStr //@requires:StringTools.c::IncludeStringH //@substitute: naming static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) { PyObject *module = 0; PyObject *empty_dict = 0; PyObject *empty_list = 0; #if PY_MAJOR_VERSION < 3 PyObject *py_import; py_import = __Pyx_PyObject_GetAttrStr($builtins_cname, PYIDENT("__import__")); if (unlikely(!py_import)) goto bad; if (!from_list) { empty_list = PyList_New(0); if (unlikely(!empty_list)) goto bad; from_list = empty_list; } #endif empty_dict = PyDict_New(); if (unlikely(!empty_dict)) goto bad; { #if PY_MAJOR_VERSION >= 3 if (level == -1) { if (strchr(__Pyx_MODULE_NAME, '.') != NULL) { /* try package relative import first */ module = PyImport_ImportModuleLevelObject( name, $moddict_cname, empty_dict, from_list, 1); if (unlikely(!module)) { if (unlikely(!PyErr_ExceptionMatches(PyExc_ImportError))) goto bad; PyErr_Clear(); } } level = 0; /* try absolute import on failure */ } #endif if (!module) { #if PY_MAJOR_VERSION < 3 PyObject *py_level = PyInt_FromLong(level); if (unlikely(!py_level)) goto bad; module = PyObject_CallFunctionObjArgs(py_import, name, $moddict_cname, empty_dict, from_list, py_level, (PyObject *)NULL); Py_DECREF(py_level); #else module = PyImport_ImportModuleLevelObject( name, $moddict_cname, empty_dict, from_list, level); #endif } } bad: Py_XDECREF(empty_dict); Py_XDECREF(empty_list); #if PY_MAJOR_VERSION < 3 Py_XDECREF(py_import); #endif return module; } /////////////// ImportFrom.proto /////////////// static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name); /*proto*/ /////////////// ImportFrom /////////////// //@requires: ObjectHandling.c::PyObjectGetAttrStr static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name) { PyObject* value = __Pyx_PyObject_GetAttrStr(module, name); if (unlikely(!value) && PyErr_ExceptionMatches(PyExc_AttributeError)) { // 'name' may refer to a (sub-)module which has not finished initialization // yet, and may not be assigned as an attribute to its parent, so try // finding it by full name. const char* module_name_str = 0; PyObject* module_name = 0; PyObject* module_dot = 0; PyObject* full_name = 0; PyErr_Clear(); module_name_str = PyModule_GetName(module); if (unlikely(!module_name_str)) { goto modbad; } module_name = PyUnicode_FromString(module_name_str); if (unlikely(!module_name)) { goto modbad; } module_dot = PyUnicode_Concat(module_name, PYUNICODE(".")); if (unlikely(!module_dot)) { goto modbad; } full_name = PyUnicode_Concat(module_dot, name); if (unlikely(!full_name)) { goto modbad; } #if PY_VERSION_HEX < 0x030700A1 || (CYTHON_COMPILING_IN_PYPY && PYPY_VERSION_NUM < 0x07030400) { PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) goto modbad; value = PyObject_GetItem(modules, full_name); } #else value = PyImport_GetModule(full_name); #endif modbad: Py_XDECREF(full_name); Py_XDECREF(module_dot); Py_XDECREF(module_name); } if (unlikely(!value)) { PyErr_Format(PyExc_ImportError, #if PY_MAJOR_VERSION < 3 "cannot import name %.230s", PyString_AS_STRING(name)); #else "cannot import name %S", name); #endif } return value; } /////////////// ImportStar /////////////// //@substitute: naming /* import_all_from is an unexposed function from ceval.c */ static int __Pyx_import_all_from(PyObject *locals, PyObject *v) { PyObject *all = PyObject_GetAttrString(v, "__all__"); PyObject *dict, *name, *value; int skip_leading_underscores = 0; int pos, err; if (all == NULL) { if (!PyErr_ExceptionMatches(PyExc_AttributeError)) return -1; /* Unexpected error */ PyErr_Clear(); dict = PyObject_GetAttrString(v, "__dict__"); if (dict == NULL) { if (!PyErr_ExceptionMatches(PyExc_AttributeError)) return -1; PyErr_SetString(PyExc_ImportError, "from-import-* object has no __dict__ and no __all__"); return -1; } #if PY_MAJOR_VERSION < 3 all = PyObject_CallMethod(dict, (char *)"keys", NULL); #else all = PyMapping_Keys(dict); #endif Py_DECREF(dict); if (all == NULL) return -1; skip_leading_underscores = 1; } for (pos = 0, err = 0; ; pos++) { name = PySequence_GetItem(all, pos); if (name == NULL) { if (!PyErr_ExceptionMatches(PyExc_IndexError)) err = -1; else PyErr_Clear(); break; } if (skip_leading_underscores && #if PY_MAJOR_VERSION < 3 likely(PyString_Check(name)) && PyString_AS_STRING(name)[0] == '_') #else likely(PyUnicode_Check(name)) && likely(__Pyx_PyUnicode_GET_LENGTH(name)) && __Pyx_PyUnicode_READ_CHAR(name, 0) == '_') #endif { Py_DECREF(name); continue; } value = PyObject_GetAttr(v, name); if (value == NULL) err = -1; else if (PyDict_CheckExact(locals)) err = PyDict_SetItem(locals, name, value); else err = PyObject_SetItem(locals, name, value); Py_DECREF(name); Py_XDECREF(value); if (err != 0) break; } Py_DECREF(all); return err; } static int ${import_star}(PyObject* m) { int i; int ret = -1; char* s; PyObject *locals = 0; PyObject *list = 0; #if PY_MAJOR_VERSION >= 3 PyObject *utf8_name = 0; #endif PyObject *name; PyObject *item; locals = PyDict_New(); if (!locals) goto bad; if (__Pyx_import_all_from(locals, m) < 0) goto bad; list = PyDict_Items(locals); if (!list) goto bad; for(i=0; i= 3 utf8_name = PyUnicode_AsUTF8String(name); if (!utf8_name) goto bad; s = PyBytes_AS_STRING(utf8_name); if (${import_star_set}(item, name, s) < 0) goto bad; Py_DECREF(utf8_name); utf8_name = 0; #else s = PyString_AsString(name); if (!s) goto bad; if (${import_star_set}(item, name, s) < 0) goto bad; #endif } ret = 0; bad: Py_XDECREF(locals); Py_XDECREF(list); #if PY_MAJOR_VERSION >= 3 Py_XDECREF(utf8_name); #endif return ret; } /////////////// SetPackagePathFromImportLib.proto /////////////// // PY_VERSION_HEX >= 0x03030000 #if PY_MAJOR_VERSION >= 3 && !CYTHON_PEP489_MULTI_PHASE_INIT static int __Pyx_SetPackagePathFromImportLib(PyObject *module_name); #else #define __Pyx_SetPackagePathFromImportLib(a) 0 #endif /////////////// SetPackagePathFromImportLib /////////////// //@substitute: naming // PY_VERSION_HEX >= 0x03030000 #if PY_MAJOR_VERSION >= 3 && !CYTHON_PEP489_MULTI_PHASE_INIT static int __Pyx_SetPackagePathFromImportLib(PyObject *module_name) { PyObject *importlib, *osmod, *ossep, *parts, *package_path; PyObject *file_path = NULL; int result; PyObject *spec; // package_path = [importlib.util.find_spec(module_name).origin.rsplit(os.sep, 1)[0]] importlib = PyImport_ImportModule("importlib.util"); if (unlikely(!importlib)) goto bad; spec = PyObject_CallMethod(importlib, "find_spec", "(O)", module_name); Py_DECREF(importlib); if (unlikely(!spec)) goto bad; file_path = PyObject_GetAttrString(spec, "origin"); Py_DECREF(spec); if (unlikely(!file_path)) goto bad; if (unlikely(PyObject_SetAttrString($module_cname, "__file__", file_path) < 0)) goto bad; osmod = PyImport_ImportModule("os"); if (unlikely(!osmod)) goto bad; ossep = PyObject_GetAttrString(osmod, "sep"); Py_DECREF(osmod); if (unlikely(!ossep)) goto bad; parts = PyObject_CallMethod(file_path, "rsplit", "(Oi)", ossep, 1); Py_DECREF(file_path); file_path = NULL; Py_DECREF(ossep); if (unlikely(!parts)) goto bad; package_path = Py_BuildValue("[O]", PyList_GET_ITEM(parts, 0)); Py_DECREF(parts); if (unlikely(!package_path)) goto bad; goto set_path; bad: PyErr_WriteUnraisable(module_name); Py_XDECREF(file_path); // set an empty path list on failure PyErr_Clear(); package_path = PyList_New(0); if (unlikely(!package_path)) return -1; set_path: result = PyObject_SetAttrString($module_cname, "__path__", package_path); Py_DECREF(package_path); return result; } #endif /////////////// TypeImport.proto /////////////// //@substitute: naming #ifndef __PYX_HAVE_RT_ImportType_proto_$cyversion #define __PYX_HAVE_RT_ImportType_proto_$cyversion #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #include #endif #if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || __cplusplus >= 201103L #define __PYX_GET_STRUCT_ALIGNMENT_$cyversion(s) alignof(s) #else // best guess at what the alignment could be since we can't measure it #define __PYX_GET_STRUCT_ALIGNMENT_$cyversion(s) sizeof(void*) #endif enum __Pyx_ImportType_CheckSize_$cyversion { __Pyx_ImportType_CheckSize_Error_$cyversion = 0, __Pyx_ImportType_CheckSize_Warn_$cyversion = 1, __Pyx_ImportType_CheckSize_Ignore_$cyversion = 2 }; static PyTypeObject *__Pyx_ImportType_$cyversion(PyObject* module, const char *module_name, const char *class_name, size_t size, size_t alignment, enum __Pyx_ImportType_CheckSize_$cyversion check_size); /*proto*/ #endif /////////////// TypeImport /////////////// //@substitute: naming #ifndef __PYX_HAVE_RT_ImportType_$cyversion #define __PYX_HAVE_RT_ImportType_$cyversion static PyTypeObject *__Pyx_ImportType_$cyversion(PyObject *module, const char *module_name, const char *class_name, size_t size, size_t alignment, enum __Pyx_ImportType_CheckSize_$cyversion check_size) { PyObject *result = 0; char warning[200]; Py_ssize_t basicsize; Py_ssize_t itemsize; #if CYTHON_COMPILING_IN_LIMITED_API PyObject *py_basicsize; PyObject *py_itemsize; #endif result = PyObject_GetAttrString(module, class_name); if (!result) goto bad; if (!PyType_Check(result)) { PyErr_Format(PyExc_TypeError, "%.200s.%.200s is not a type object", module_name, class_name); goto bad; } #if !CYTHON_COMPILING_IN_LIMITED_API basicsize = ((PyTypeObject *)result)->tp_basicsize; itemsize = ((PyTypeObject *)result)->tp_itemsize; #else py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); if (!py_basicsize) goto bad; basicsize = PyLong_AsSsize_t(py_basicsize); Py_DECREF(py_basicsize); py_basicsize = 0; if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) goto bad; py_itemsize = PyObject_GetAttrString(result, "__itemsize__"); if (!py_itemsize) goto bad; itemsize = PyLong_AsSsize_t(py_itemsize); Py_DECREF(py_itemsize); py_itemsize = 0; if (itemsize == (Py_ssize_t)-1 && PyErr_Occurred()) goto bad; #endif if (itemsize) { // If itemsize is smaller than the alignment the struct can end up with some extra // padding at the end. In this case we need to work out the maximum size that // the padding could be when calculating the range of valid struct sizes. if (size % alignment) { // if this is true we've probably calculated the alignment wrongly // (most likely because alignof isn't available) alignment = size % alignment; } if (itemsize < (Py_ssize_t)alignment) itemsize = (Py_ssize_t)alignment; } if ((size_t)(basicsize + itemsize) < size) { PyErr_Format(PyExc_ValueError, "%.200s.%.200s size changed, may indicate binary incompatibility. " "Expected %zd from C header, got %zd from PyObject", module_name, class_name, size, basicsize+itemsize); goto bad; } // varobjects almost have structs between basicsize and basicsize + itemsize // but the struct isn't always one of the two limiting values if (check_size == __Pyx_ImportType_CheckSize_Error_$cyversion && ((size_t)basicsize > size || (size_t)(basicsize + itemsize) < size)) { PyErr_Format(PyExc_ValueError, "%.200s.%.200s size changed, may indicate binary incompatibility. " "Expected %zd from C header, got %zd-%zd from PyObject", module_name, class_name, size, basicsize, basicsize+itemsize); goto bad; } else if (check_size == __Pyx_ImportType_CheckSize_Warn_$cyversion && (size_t)basicsize > size) { PyOS_snprintf(warning, sizeof(warning), "%s.%s size changed, may indicate binary incompatibility. " "Expected %zd from C header, got %zd from PyObject", module_name, class_name, size, basicsize); if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; } /* check_size == __Pyx_ImportType_CheckSize_Ignore does not warn nor error */ return (PyTypeObject *)result; bad: Py_XDECREF(result); return NULL; } #endif /////////////// FunctionImport.proto /////////////// //@substitute: naming static int __Pyx_ImportFunction_$cyversion(PyObject *module, const char *funcname, void (**f)(void), const char *sig); /*proto*/ /////////////// FunctionImport /////////////// //@substitute: naming #ifndef __PYX_HAVE_RT_ImportFunction_$cyversion #define __PYX_HAVE_RT_ImportFunction_$cyversion static int __Pyx_ImportFunction_$cyversion(PyObject *module, const char *funcname, void (**f)(void), const char *sig) { PyObject *d = 0; PyObject *cobj = 0; union { void (*fp)(void); void *p; } tmp; d = PyObject_GetAttrString(module, (char *)"$api_name"); if (!d) goto bad; cobj = PyDict_GetItemString(d, funcname); if (!cobj) { PyErr_Format(PyExc_ImportError, "%.200s does not export expected C function %.200s", PyModule_GetName(module), funcname); goto bad; } if (!PyCapsule_IsValid(cobj, sig)) { PyErr_Format(PyExc_TypeError, "C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)", PyModule_GetName(module), funcname, sig, PyCapsule_GetName(cobj)); goto bad; } tmp.p = PyCapsule_GetPointer(cobj, sig); *f = tmp.fp; if (!(*f)) goto bad; Py_DECREF(d); return 0; bad: Py_XDECREF(d); return -1; } #endif /////////////// FunctionExport.proto /////////////// static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig); /*proto*/ /////////////// FunctionExport /////////////// //@substitute: naming static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig) { PyObject *d = 0; PyObject *cobj = 0; union { void (*fp)(void); void *p; } tmp; d = PyObject_GetAttrString($module_cname, (char *)"$api_name"); if (!d) { PyErr_Clear(); d = PyDict_New(); if (!d) goto bad; Py_INCREF(d); if (PyModule_AddObject($module_cname, (char *)"$api_name", d) < 0) goto bad; } tmp.fp = f; cobj = PyCapsule_New(tmp.p, sig, 0); if (!cobj) goto bad; if (PyDict_SetItemString(d, name, cobj) < 0) goto bad; Py_DECREF(cobj); Py_DECREF(d); return 0; bad: Py_XDECREF(cobj); Py_XDECREF(d); return -1; } /////////////// VoidPtrImport.proto /////////////// //@substitute: naming static int __Pyx_ImportVoidPtr_$cyversion(PyObject *module, const char *name, void **p, const char *sig); /*proto*/ /////////////// VoidPtrImport /////////////// //@substitute: naming #ifndef __PYX_HAVE_RT_ImportVoidPtr_$cyversion #define __PYX_HAVE_RT_ImportVoidPtr_$cyversion static int __Pyx_ImportVoidPtr_$cyversion(PyObject *module, const char *name, void **p, const char *sig) { PyObject *d = 0; PyObject *cobj = 0; d = PyObject_GetAttrString(module, (char *)"$api_name"); if (!d) goto bad; cobj = PyDict_GetItemString(d, name); if (!cobj) { PyErr_Format(PyExc_ImportError, "%.200s does not export expected C variable %.200s", PyModule_GetName(module), name); goto bad; } if (!PyCapsule_IsValid(cobj, sig)) { PyErr_Format(PyExc_TypeError, "C variable %.200s.%.200s has wrong signature (expected %.500s, got %.500s)", PyModule_GetName(module), name, sig, PyCapsule_GetName(cobj)); goto bad; } *p = PyCapsule_GetPointer(cobj, sig); if (!(*p)) goto bad; Py_DECREF(d); return 0; bad: Py_XDECREF(d); return -1; } #endif /////////////// VoidPtrExport.proto /////////////// static int __Pyx_ExportVoidPtr(PyObject *name, void *p, const char *sig); /*proto*/ /////////////// VoidPtrExport /////////////// //@substitute: naming //@requires: ObjectHandling.c::PyObjectSetAttrStr static int __Pyx_ExportVoidPtr(PyObject *name, void *p, const char *sig) { PyObject *d; PyObject *cobj = 0; d = PyDict_GetItem($moddict_cname, PYIDENT("$api_name")); Py_XINCREF(d); if (!d) { d = PyDict_New(); if (!d) goto bad; if (__Pyx_PyObject_SetAttrStr($module_cname, PYIDENT("$api_name"), d) < 0) goto bad; } cobj = PyCapsule_New(p, sig, 0); if (!cobj) goto bad; if (PyDict_SetItem(d, name, cobj) < 0) goto bad; Py_DECREF(cobj); Py_DECREF(d); return 0; bad: Py_XDECREF(cobj); Py_XDECREF(d); return -1; } /////////////// SetVTable.proto /////////////// static int __Pyx_SetVtable(PyTypeObject* typeptr , void* vtable); /*proto*/ /////////////// SetVTable /////////////// static int __Pyx_SetVtable(PyTypeObject *type, void *vtable) { PyObject *ob = PyCapsule_New(vtable, 0, 0); if (unlikely(!ob)) goto bad; #if CYTHON_COMPILING_IN_LIMITED_API if (unlikely(PyObject_SetAttr((PyObject *) type, PYIDENT("__pyx_vtable__"), ob) < 0)) #else if (unlikely(PyDict_SetItem(type->tp_dict, PYIDENT("__pyx_vtable__"), ob) < 0)) #endif goto bad; Py_DECREF(ob); return 0; bad: Py_XDECREF(ob); return -1; } /////////////// GetVTable.proto /////////////// static void* __Pyx_GetVtable(PyTypeObject *type); /*proto*/ /////////////// GetVTable /////////////// static void* __Pyx_GetVtable(PyTypeObject *type) { void* ptr; #if CYTHON_COMPILING_IN_LIMITED_API PyObject *ob = PyObject_GetAttr((PyObject *)type, PYIDENT("__pyx_vtable__")); #else PyObject *ob = PyObject_GetItem(type->tp_dict, PYIDENT("__pyx_vtable__")); #endif if (!ob) goto bad; ptr = PyCapsule_GetPointer(ob, 0); if (!ptr && !PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, "invalid vtable found for imported type"); Py_DECREF(ob); return ptr; bad: Py_XDECREF(ob); return NULL; } /////////////// MergeVTables.proto /////////////// //@requires: GetVTable // TODO: find a way to make this work with the Limited API! #if !CYTHON_COMPILING_IN_LIMITED_API static int __Pyx_MergeVtables(PyTypeObject *type); /*proto*/ #endif /////////////// MergeVTables /////////////// #if !CYTHON_COMPILING_IN_LIMITED_API static int __Pyx_MergeVtables(PyTypeObject *type) { int i; void** base_vtables; __Pyx_TypeName tp_base_name; __Pyx_TypeName base_name; void* unknown = (void*)-1; PyObject* bases = type->tp_bases; int base_depth = 0; { PyTypeObject* base = type->tp_base; while (base) { base_depth += 1; base = base->tp_base; } } base_vtables = (void**) malloc(sizeof(void*) * (size_t)(base_depth + 1)); base_vtables[0] = unknown; // Could do MRO resolution of individual methods in the future, assuming // compatible vtables, but for now simply require a common vtable base. // Note that if the vtables of various bases are extended separately, // resolution isn't possible and we must reject it just as when the // instance struct is so extended. (It would be good to also do this // check when a multiple-base class is created in pure Python as well.) for (i = 1; i < PyTuple_GET_SIZE(bases); i++) { void* base_vtable = __Pyx_GetVtable(((PyTypeObject*)PyTuple_GET_ITEM(bases, i))); if (base_vtable != NULL) { int j; PyTypeObject* base = type->tp_base; for (j = 0; j < base_depth; j++) { if (base_vtables[j] == unknown) { base_vtables[j] = __Pyx_GetVtable(base); base_vtables[j + 1] = unknown; } if (base_vtables[j] == base_vtable) { break; } else if (base_vtables[j] == NULL) { // No more potential matching bases (with vtables). goto bad; } base = base->tp_base; } } } PyErr_Clear(); free(base_vtables); return 0; bad: tp_base_name = __Pyx_PyType_GetName(type->tp_base); base_name = __Pyx_PyType_GetName((PyTypeObject*)PyTuple_GET_ITEM(bases, i)); PyErr_Format(PyExc_TypeError, "multiple bases have vtable conflict: '" __Pyx_FMT_TYPENAME "' and '" __Pyx_FMT_TYPENAME "'", tp_base_name, base_name); __Pyx_DECREF_TypeName(tp_base_name); __Pyx_DECREF_TypeName(base_name); free(base_vtables); return -1; } #endif /////////////// ImportNumPyArray.proto /////////////// static PyObject *__pyx_numpy_ndarray = NULL; static PyObject* __Pyx_ImportNumPyArrayTypeIfAvailable(void); /*proto*/ /////////////// ImportNumPyArray.cleanup /////////////// Py_CLEAR(__pyx_numpy_ndarray); /////////////// ImportNumPyArray /////////////// //@requires: ImportExport.c::Import static PyObject* __Pyx__ImportNumPyArray(void) { PyObject *numpy_module, *ndarray_object = NULL; numpy_module = __Pyx_Import(PYIDENT("numpy"), NULL, 0); if (likely(numpy_module)) { ndarray_object = PyObject_GetAttrString(numpy_module, "ndarray"); Py_DECREF(numpy_module); } if (unlikely(!ndarray_object)) { // ImportError, AttributeError, ... PyErr_Clear(); } if (unlikely(!ndarray_object || !PyObject_TypeCheck(ndarray_object, &PyType_Type))) { Py_XDECREF(ndarray_object); Py_INCREF(Py_None); ndarray_object = Py_None; } return ndarray_object; } static CYTHON_INLINE PyObject* __Pyx_ImportNumPyArrayTypeIfAvailable(void) { if (unlikely(!__pyx_numpy_ndarray)) { __pyx_numpy_ndarray = __Pyx__ImportNumPyArray(); } Py_INCREF(__pyx_numpy_ndarray); return __pyx_numpy_ndarray; } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/MemoryView.pyx0000644000175100001770000014065600000000000021364 0ustar00runnerdocker00000000000000#################### View.MemoryView #################### # cython: language_level=3str # cython: binding=False # This utility provides cython.array and cython.view.memoryview from __future__ import absolute_import cimport cython # from cpython cimport ... cdef extern from "Python.h": ctypedef struct PyObject int PyIndex_Check(object) PyObject *PyExc_IndexError PyObject *PyExc_ValueError cdef extern from "pythread.h": ctypedef void *PyThread_type_lock PyThread_type_lock PyThread_allocate_lock() void PyThread_free_lock(PyThread_type_lock) cdef extern from "": void *memset(void *b, int c, size_t len) cdef extern from *: bint __PYX_CYTHON_ATOMICS_ENABLED() int __Pyx_GetBuffer(object, Py_buffer *, int) except -1 void __Pyx_ReleaseBuffer(Py_buffer *) ctypedef struct PyObject ctypedef Py_ssize_t Py_intptr_t void Py_INCREF(PyObject *) void Py_DECREF(PyObject *) void* PyMem_Malloc(size_t n) void PyMem_Free(void *p) void* PyObject_Malloc(size_t n) void PyObject_Free(void *p) cdef struct __pyx_memoryview "__pyx_memoryview_obj": Py_buffer view PyObject *obj __Pyx_TypeInfo *typeinfo ctypedef struct {{memviewslice_name}}: __pyx_memoryview *memview char *data Py_ssize_t shape[{{max_dims}}] Py_ssize_t strides[{{max_dims}}] Py_ssize_t suboffsets[{{max_dims}}] void __PYX_INC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil) void __PYX_XCLEAR_MEMVIEW({{memviewslice_name}} *memslice, int have_gil) ctypedef struct __pyx_buffer "Py_buffer": PyObject *obj PyObject *Py_None cdef enum: PyBUF_C_CONTIGUOUS, PyBUF_F_CONTIGUOUS, PyBUF_ANY_CONTIGUOUS PyBUF_FORMAT PyBUF_WRITABLE PyBUF_STRIDES PyBUF_INDIRECT PyBUF_ND PyBUF_RECORDS PyBUF_RECORDS_RO ctypedef struct __Pyx_TypeInfo: pass cdef extern from *: ctypedef int __pyx_atomic_int_type {{memviewslice_name}} slice_copy_contig "__pyx_memoryview_copy_new_contig"( __Pyx_memviewslice *from_mvs, char *mode, int ndim, size_t sizeof_dtype, int contig_flag, bint dtype_is_object) except * nogil bint slice_is_contig "__pyx_memviewslice_is_contig" ( {{memviewslice_name}} mvs, char order, int ndim) nogil bint slices_overlap "__pyx_slices_overlap" ({{memviewslice_name}} *slice1, {{memviewslice_name}} *slice2, int ndim, size_t itemsize) nogil cdef extern from "": void *malloc(size_t) nogil void free(void *) nogil void *memcpy(void *dest, void *src, size_t n) nogil # the sequence abstract base class cdef object __pyx_collections_abc_Sequence "__pyx_collections_abc_Sequence" try: if __import__("sys").version_info >= (3, 3): __pyx_collections_abc_Sequence = __import__("collections.abc").abc.Sequence else: __pyx_collections_abc_Sequence = __import__("collections").Sequence except: # it isn't a big problem if this fails __pyx_collections_abc_Sequence = None # ### cython.array class # @cython.collection_type("sequence") @cname("__pyx_array") cdef class array: cdef: char *data Py_ssize_t len char *format int ndim Py_ssize_t *_shape Py_ssize_t *_strides Py_ssize_t itemsize unicode mode # FIXME: this should have been a simple 'char' bytes _format void (*callback_free_data)(void *data) noexcept # cdef object _memview cdef bint free_data cdef bint dtype_is_object def __cinit__(array self, tuple shape, Py_ssize_t itemsize, format not None, mode="c", bint allocate_buffer=True): cdef int idx cdef Py_ssize_t dim self.ndim = len(shape) self.itemsize = itemsize if not self.ndim: raise ValueError, "Empty shape tuple for cython.array" if itemsize <= 0: raise ValueError, "itemsize <= 0 for cython.array" if not isinstance(format, bytes): format = format.encode('ASCII') self._format = format # keep a reference to the byte string self.format = self._format # use single malloc() for both shape and strides self._shape = PyObject_Malloc(sizeof(Py_ssize_t)*self.ndim*2) self._strides = self._shape + self.ndim if not self._shape: raise MemoryError, "unable to allocate shape and strides." # cdef Py_ssize_t dim, stride for idx, dim in enumerate(shape): if dim <= 0: raise ValueError, f"Invalid shape in axis {idx}: {dim}." self._shape[idx] = dim cdef char order if mode == 'c': order = b'C' self.mode = u'c' elif mode == 'fortran': order = b'F' self.mode = u'fortran' else: raise ValueError, f"Invalid mode, expected 'c' or 'fortran', got {mode}" self.len = fill_contig_strides_array(self._shape, self._strides, itemsize, self.ndim, order) self.free_data = allocate_buffer self.dtype_is_object = format == b'O' if allocate_buffer: _allocate_buffer(self) @cname('getbuffer') def __getbuffer__(self, Py_buffer *info, int flags): cdef int bufmode = -1 if flags & (PyBUF_C_CONTIGUOUS | PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS): if self.mode == u"c": bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS elif self.mode == u"fortran": bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS if not (flags & bufmode): raise ValueError, "Can only create a buffer that is contiguous in memory." info.buf = self.data info.len = self.len if flags & PyBUF_STRIDES: info.ndim = self.ndim info.shape = self._shape info.strides = self._strides else: info.ndim = 1 info.shape = &self.len if flags & PyBUF_ND else NULL info.strides = NULL info.suboffsets = NULL info.itemsize = self.itemsize info.readonly = 0 info.format = self.format if flags & PyBUF_FORMAT else NULL info.obj = self def __dealloc__(array self): if self.callback_free_data != NULL: self.callback_free_data(self.data) elif self.free_data and self.data is not NULL: if self.dtype_is_object: refcount_objects_in_slice(self.data, self._shape, self._strides, self.ndim, inc=False) free(self.data) PyObject_Free(self._shape) @property def memview(self): return self.get_memview() @cname('get_memview') cdef get_memview(self): flags = PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT|PyBUF_WRITABLE return memoryview(self, flags, self.dtype_is_object) def __len__(self): return self._shape[0] def __getattr__(self, attr): return getattr(self.memview, attr) def __getitem__(self, item): return self.memview[item] def __setitem__(self, item, value): self.memview[item] = value # Sequence methods try: count = __pyx_collections_abc_Sequence.count index = __pyx_collections_abc_Sequence.index except: pass @cname("__pyx_array_allocate_buffer") cdef int _allocate_buffer(array self) except -1: # use malloc() for backwards compatibility # in case external code wants to change the data pointer cdef Py_ssize_t i cdef PyObject **p self.free_data = True self.data = malloc(self.len) if not self.data: raise MemoryError, "unable to allocate array data." if self.dtype_is_object: p = self.data for i in range(self.len // self.itemsize): p[i] = Py_None Py_INCREF(Py_None) return 0 @cname("__pyx_array_new") cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format, char *c_mode, char *buf): cdef array result cdef str mode = "fortran" if c_mode[0] == b'f' else "c" # this often comes from a constant C string. if buf is NULL: result = array.__new__(array, shape, itemsize, format, mode) else: result = array.__new__(array, shape, itemsize, format, mode, allocate_buffer=False) result.data = buf return result # ### Memoryview constants and cython.view.memoryview class # # Disable generic_contiguous, as it makes trouble verifying contiguity: # - 'contiguous' or '::1' means the dimension is contiguous with dtype # - 'indirect_contiguous' means a contiguous list of pointers # - dtype contiguous must be contiguous in the first or last dimension # from the start, or from the dimension following the last indirect dimension # # e.g. # int[::indirect_contiguous, ::contiguous, :] # # is valid (list of pointers to 2d fortran-contiguous array), but # # int[::generic_contiguous, ::contiguous, :] # # would mean you'd have assert dimension 0 to be indirect (and pointer contiguous) at runtime. # So it doesn't bring any performance benefit, and it's only confusing. @cname('__pyx_MemviewEnum') cdef class Enum(object): cdef object name def __init__(self, name): self.name = name def __repr__(self): return self.name cdef generic = Enum("") cdef strided = Enum("") # default cdef indirect = Enum("") # Disable generic_contiguous, as it is a troublemaker #cdef generic_contiguous = Enum("") cdef contiguous = Enum("") cdef indirect_contiguous = Enum("") # 'follow' is implied when the first or last axis is ::1 # pre-allocate thread locks for reuse ## note that this could be implemented in a more beautiful way in "normal" Cython, ## but this code gets merged into the user module and not everything works there. cdef int __pyx_memoryview_thread_locks_used = 0 cdef PyThread_type_lock[{{THREAD_LOCKS_PREALLOCATED}}] __pyx_memoryview_thread_locks = [ {{for _ in range(THREAD_LOCKS_PREALLOCATED)}} PyThread_allocate_lock(), {{endfor}} ] @cname('__pyx_memoryview') cdef class memoryview: cdef object obj cdef object _size cdef object _array_interface cdef PyThread_type_lock lock cdef __pyx_atomic_int_type acquisition_count cdef Py_buffer view cdef int flags cdef bint dtype_is_object cdef __Pyx_TypeInfo *typeinfo def __cinit__(memoryview self, object obj, int flags, bint dtype_is_object=False): self.obj = obj self.flags = flags if type(self) is memoryview or obj is not None: __Pyx_GetBuffer(obj, &self.view, flags) if self.view.obj == NULL: (<__pyx_buffer *> &self.view).obj = Py_None Py_INCREF(Py_None) if not __PYX_CYTHON_ATOMICS_ENABLED(): global __pyx_memoryview_thread_locks_used if __pyx_memoryview_thread_locks_used < {{THREAD_LOCKS_PREALLOCATED}}: self.lock = __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] __pyx_memoryview_thread_locks_used += 1 if self.lock is NULL: self.lock = PyThread_allocate_lock() if self.lock is NULL: raise MemoryError if flags & PyBUF_FORMAT: self.dtype_is_object = (self.view.format[0] == b'O' and self.view.format[1] == b'\0') else: self.dtype_is_object = dtype_is_object assert (&self.acquisition_count) % sizeof(__pyx_atomic_int_type) == 0 self.typeinfo = NULL def __dealloc__(memoryview self): if self.obj is not None: __Pyx_ReleaseBuffer(&self.view) elif (<__pyx_buffer *> &self.view).obj == Py_None: # Undo the incref in __cinit__() above. (<__pyx_buffer *> &self.view).obj = NULL Py_DECREF(Py_None) cdef int i global __pyx_memoryview_thread_locks_used if self.lock != NULL: for i in range(__pyx_memoryview_thread_locks_used): if __pyx_memoryview_thread_locks[i] is self.lock: __pyx_memoryview_thread_locks_used -= 1 if i != __pyx_memoryview_thread_locks_used: __pyx_memoryview_thread_locks[i], __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] = ( __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used], __pyx_memoryview_thread_locks[i]) break else: PyThread_free_lock(self.lock) cdef char *get_item_pointer(memoryview self, object index) except NULL: cdef Py_ssize_t dim cdef char *itemp = self.view.buf for dim, idx in enumerate(index): itemp = pybuffer_index(&self.view, itemp, idx, dim) return itemp #@cname('__pyx_memoryview_getitem') def __getitem__(memoryview self, object index): if index is Ellipsis: return self have_slices, indices = _unellipsify(index, self.view.ndim) cdef char *itemp if have_slices: return memview_slice(self, indices) else: itemp = self.get_item_pointer(indices) return self.convert_item_to_object(itemp) def __setitem__(memoryview self, object index, object value): if self.view.readonly: raise TypeError, "Cannot assign to read-only memoryview" have_slices, index = _unellipsify(index, self.view.ndim) if have_slices: obj = self.is_slice(value) if obj: self.setitem_slice_assignment(self[index], obj) else: self.setitem_slice_assign_scalar(self[index], value) else: self.setitem_indexed(index, value) cdef is_slice(self, obj): if not isinstance(obj, memoryview): try: obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, self.dtype_is_object) except TypeError: return None return obj cdef setitem_slice_assignment(self, dst, src): cdef {{memviewslice_name}} dst_slice cdef {{memviewslice_name}} src_slice cdef {{memviewslice_name}} msrc = get_slice_from_memview(src, &src_slice)[0] cdef {{memviewslice_name}} mdst = get_slice_from_memview(dst, &dst_slice)[0] memoryview_copy_contents(msrc, mdst, src.ndim, dst.ndim, self.dtype_is_object) cdef setitem_slice_assign_scalar(self, memoryview dst, value): cdef int array[128] cdef void *tmp = NULL cdef void *item cdef {{memviewslice_name}} *dst_slice cdef {{memviewslice_name}} tmp_slice dst_slice = get_slice_from_memview(dst, &tmp_slice) if self.view.itemsize > sizeof(array): tmp = PyMem_Malloc(self.view.itemsize) if tmp == NULL: raise MemoryError item = tmp else: item = array try: if self.dtype_is_object: ( item)[0] = value else: self.assign_item_from_object( item, value) # It would be easy to support indirect dimensions, but it's easier # to disallow :) if self.view.suboffsets != NULL: assert_direct_dimensions(self.view.suboffsets, self.view.ndim) slice_assign_scalar(dst_slice, dst.view.ndim, self.view.itemsize, item, self.dtype_is_object) finally: PyMem_Free(tmp) cdef setitem_indexed(self, index, value): cdef char *itemp = self.get_item_pointer(index) self.assign_item_from_object(itemp, value) cdef convert_item_to_object(self, char *itemp): """Only used if instantiated manually by the user, or if Cython doesn't know how to convert the type""" import struct cdef bytes bytesitem # Do a manual and complete check here instead of this easy hack bytesitem = itemp[:self.view.itemsize] try: result = struct.unpack(self.view.format, bytesitem) except struct.error: raise ValueError, "Unable to convert item to object" else: if len(self.view.format) == 1: return result[0] return result cdef assign_item_from_object(self, char *itemp, object value): """Only used if instantiated manually by the user, or if Cython doesn't know how to convert the type""" import struct cdef char c cdef bytes bytesvalue cdef Py_ssize_t i if isinstance(value, tuple): bytesvalue = struct.pack(self.view.format, *value) else: bytesvalue = struct.pack(self.view.format, value) for i, c in enumerate(bytesvalue): itemp[i] = c @cname('getbuffer') def __getbuffer__(self, Py_buffer *info, int flags): if flags & PyBUF_WRITABLE and self.view.readonly: raise ValueError, "Cannot create writable memory view from read-only memoryview" if flags & PyBUF_ND: info.shape = self.view.shape else: info.shape = NULL if flags & PyBUF_STRIDES: info.strides = self.view.strides else: info.strides = NULL if flags & PyBUF_INDIRECT: info.suboffsets = self.view.suboffsets else: info.suboffsets = NULL if flags & PyBUF_FORMAT: info.format = self.view.format else: info.format = NULL info.buf = self.view.buf info.ndim = self.view.ndim info.itemsize = self.view.itemsize info.len = self.view.len info.readonly = self.view.readonly info.obj = self # Some properties that have the same semantics as in NumPy @property def T(self): cdef _memoryviewslice result = memoryview_copy(self) transpose_memslice(&result.from_slice) return result @property def base(self): return self._get_base() cdef _get_base(self): return self.obj @property def shape(self): return tuple([length for length in self.view.shape[:self.view.ndim]]) @property def strides(self): if self.view.strides == NULL: # Note: we always ask for strides, so if this is not set it's a bug raise ValueError, "Buffer view does not expose strides" return tuple([stride for stride in self.view.strides[:self.view.ndim]]) @property def suboffsets(self): if self.view.suboffsets == NULL: return (-1,) * self.view.ndim return tuple([suboffset for suboffset in self.view.suboffsets[:self.view.ndim]]) @property def ndim(self): return self.view.ndim @property def itemsize(self): return self.view.itemsize @property def nbytes(self): return self.size * self.view.itemsize @property def size(self): if self._size is None: result = 1 for length in self.view.shape[:self.view.ndim]: result *= length self._size = result return self._size def __len__(self): if self.view.ndim >= 1: return self.view.shape[0] return 0 def __repr__(self): return "" % (self.base.__class__.__name__, id(self)) def __str__(self): return "" % (self.base.__class__.__name__,) # Support the same attributes as memoryview slices def is_c_contig(self): cdef {{memviewslice_name}} *mslice cdef {{memviewslice_name}} tmp mslice = get_slice_from_memview(self, &tmp) return slice_is_contig(mslice[0], 'C', self.view.ndim) def is_f_contig(self): cdef {{memviewslice_name}} *mslice cdef {{memviewslice_name}} tmp mslice = get_slice_from_memview(self, &tmp) return slice_is_contig(mslice[0], 'F', self.view.ndim) def copy(self): cdef {{memviewslice_name}} mslice cdef int flags = self.flags & ~PyBUF_F_CONTIGUOUS slice_copy(self, &mslice) mslice = slice_copy_contig(&mslice, "c", self.view.ndim, self.view.itemsize, flags|PyBUF_C_CONTIGUOUS, self.dtype_is_object) return memoryview_copy_from_slice(self, &mslice) def copy_fortran(self): cdef {{memviewslice_name}} src, dst cdef int flags = self.flags & ~PyBUF_C_CONTIGUOUS slice_copy(self, &src) dst = slice_copy_contig(&src, "fortran", self.view.ndim, self.view.itemsize, flags|PyBUF_F_CONTIGUOUS, self.dtype_is_object) return memoryview_copy_from_slice(self, &dst) @cname('__pyx_memoryview_new') cdef memoryview_cwrapper(object o, int flags, bint dtype_is_object, __Pyx_TypeInfo *typeinfo): cdef memoryview result = memoryview(o, flags, dtype_is_object) result.typeinfo = typeinfo return result @cname('__pyx_memoryview_check') cdef inline bint memoryview_check(object o) noexcept: return isinstance(o, memoryview) cdef tuple _unellipsify(object index, int ndim): """ Replace all ellipses with full slices and fill incomplete indices with full slices. """ cdef Py_ssize_t idx tup = index if isinstance(index, tuple) else (index,) result = [slice(None)] * ndim have_slices = False seen_ellipsis = False idx = 0 for item in tup: if item is Ellipsis: if not seen_ellipsis: idx += ndim - len(tup) seen_ellipsis = True have_slices = True else: if isinstance(item, slice): have_slices = True elif not PyIndex_Check(item): raise TypeError, f"Cannot index with type '{type(item)}'" result[idx] = item idx += 1 nslices = ndim - idx return have_slices or nslices, tuple(result) cdef int assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim) except -1: for suboffset in suboffsets[:ndim]: if suboffset >= 0: raise ValueError, "Indirect dimensions not supported" return 0 # return type just used as an error flag # ### Slicing a memoryview # @cname('__pyx_memview_slice') cdef memoryview memview_slice(memoryview memview, object indices): cdef int new_ndim = 0, suboffset_dim = -1, dim cdef bint negative_step cdef {{memviewslice_name}} src, dst cdef {{memviewslice_name}} *p_src # dst is copied by value in memoryview_fromslice -- initialize it # src is never copied memset(&dst, 0, sizeof(dst)) cdef _memoryviewslice memviewsliceobj assert memview.view.ndim > 0 if isinstance(memview, _memoryviewslice): memviewsliceobj = memview p_src = &memviewsliceobj.from_slice else: slice_copy(memview, &src) p_src = &src # Note: don't use variable src at this point # SubNote: we should be able to declare variables in blocks... # memoryview_fromslice() will inc our dst slice dst.memview = p_src.memview dst.data = p_src.data # Put everything in temps to avoid this bloody warning: # "Argument evaluation order in C function call is undefined and # may not be as expected" cdef {{memviewslice_name}} *p_dst = &dst cdef int *p_suboffset_dim = &suboffset_dim cdef Py_ssize_t start, stop, step, cindex cdef bint have_start, have_stop, have_step for dim, index in enumerate(indices): if PyIndex_Check(index): cindex = index slice_memviewslice( p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim], dim, new_ndim, p_suboffset_dim, cindex, 0, 0, # start, stop, step 0, 0, 0, # have_{start,stop,step} False) elif index is None: p_dst.shape[new_ndim] = 1 p_dst.strides[new_ndim] = 0 p_dst.suboffsets[new_ndim] = -1 new_ndim += 1 else: start = index.start or 0 stop = index.stop or 0 step = index.step or 0 have_start = index.start is not None have_stop = index.stop is not None have_step = index.step is not None slice_memviewslice( p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim], dim, new_ndim, p_suboffset_dim, start, stop, step, have_start, have_stop, have_step, True) new_ndim += 1 if isinstance(memview, _memoryviewslice): return memoryview_fromslice(dst, new_ndim, memviewsliceobj.to_object_func, memviewsliceobj.to_dtype_func, memview.dtype_is_object) else: return memoryview_fromslice(dst, new_ndim, NULL, NULL, memview.dtype_is_object) # ### Slicing in a single dimension of a memoryviewslice # @cname('__pyx_memoryview_slice_memviewslice') cdef int slice_memviewslice( {{memviewslice_name}} *dst, Py_ssize_t shape, Py_ssize_t stride, Py_ssize_t suboffset, int dim, int new_ndim, int *suboffset_dim, Py_ssize_t start, Py_ssize_t stop, Py_ssize_t step, int have_start, int have_stop, int have_step, bint is_slice) except -1 nogil: """ Create a new slice dst given slice src. dim - the current src dimension (indexing will make dimensions disappear) new_dim - the new dst dimension suboffset_dim - pointer to a single int initialized to -1 to keep track of where slicing offsets should be added """ cdef Py_ssize_t new_shape cdef bint negative_step if not is_slice: # index is a normal integer-like index if start < 0: start += shape if not 0 <= start < shape: _err_dim(PyExc_IndexError, "Index out of bounds (axis %d)", dim) else: # index is a slice if have_step: negative_step = step < 0 if step == 0: _err_dim(PyExc_ValueError, "Step may not be zero (axis %d)", dim) else: negative_step = False step = 1 # check our bounds and set defaults if have_start: if start < 0: start += shape if start < 0: start = 0 elif start >= shape: if negative_step: start = shape - 1 else: start = shape else: if negative_step: start = shape - 1 else: start = 0 if have_stop: if stop < 0: stop += shape if stop < 0: stop = 0 elif stop > shape: stop = shape else: if negative_step: stop = -1 else: stop = shape # len = ceil( (stop - start) / step ) with cython.cdivision(True): new_shape = (stop - start) // step if (stop - start) - step * new_shape: new_shape += 1 if new_shape < 0: new_shape = 0 # shape/strides/suboffsets dst.strides[new_ndim] = stride * step dst.shape[new_ndim] = new_shape dst.suboffsets[new_ndim] = suboffset # Add the slicing or indexing offsets to the right suboffset or base data * if suboffset_dim[0] < 0: dst.data += start * stride else: dst.suboffsets[suboffset_dim[0]] += start * stride if suboffset >= 0: if not is_slice: if new_ndim == 0: dst.data = ( dst.data)[0] + suboffset else: _err_dim(PyExc_IndexError, "All dimensions preceding dimension %d " "must be indexed and not sliced", dim) else: suboffset_dim[0] = new_ndim return 0 # ### Index a memoryview # @cname('__pyx_pybuffer_index') cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index, Py_ssize_t dim) except NULL: cdef Py_ssize_t shape, stride, suboffset = -1 cdef Py_ssize_t itemsize = view.itemsize cdef char *resultp if view.ndim == 0: shape = view.len // itemsize stride = itemsize else: shape = view.shape[dim] stride = view.strides[dim] if view.suboffsets != NULL: suboffset = view.suboffsets[dim] if index < 0: index += view.shape[dim] if index < 0: raise IndexError, f"Out of bounds on buffer access (axis {dim})" if index >= shape: raise IndexError, f"Out of bounds on buffer access (axis {dim})" resultp = bufp + index * stride if suboffset >= 0: resultp = ( resultp)[0] + suboffset return resultp # ### Transposing a memoryviewslice # @cname('__pyx_memslice_transpose') cdef int transpose_memslice({{memviewslice_name}} *memslice) except -1 nogil: cdef int ndim = memslice.memview.view.ndim cdef Py_ssize_t *shape = memslice.shape cdef Py_ssize_t *strides = memslice.strides # reverse strides and shape cdef int i, j for i in range(ndim // 2): j = ndim - 1 - i strides[i], strides[j] = strides[j], strides[i] shape[i], shape[j] = shape[j], shape[i] if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0: _err(PyExc_ValueError, "Cannot transpose memoryview with indirect dimensions") return 0 # ### Creating new memoryview objects from slices and memoryviews # @cython.collection_type("sequence") @cname('__pyx_memoryviewslice') cdef class _memoryviewslice(memoryview): "Internal class for passing memoryview slices to Python" # We need this to keep our shape/strides/suboffset pointers valid cdef {{memviewslice_name}} from_slice # We need this only to print it's class' name cdef object from_object cdef object (*to_object_func)(char *) cdef int (*to_dtype_func)(char *, object) except 0 def __dealloc__(self): __PYX_XCLEAR_MEMVIEW(&self.from_slice, 1) cdef convert_item_to_object(self, char *itemp): if self.to_object_func != NULL: return self.to_object_func(itemp) else: return memoryview.convert_item_to_object(self, itemp) cdef assign_item_from_object(self, char *itemp, object value): if self.to_dtype_func != NULL: self.to_dtype_func(itemp, value) else: memoryview.assign_item_from_object(self, itemp, value) cdef _get_base(self): return self.from_object # Sequence methods try: count = __pyx_collections_abc_Sequence.count index = __pyx_collections_abc_Sequence.index except: pass try: if __pyx_collections_abc_Sequence: # The main value of registering _memoryviewslice as a # Sequence is that it can be used in structural pattern # matching in Python 3.10+ __pyx_collections_abc_Sequence.register(_memoryviewslice) __pyx_collections_abc_Sequence.register(array) except: pass # ignore failure, it's a minor issue @cname('__pyx_memoryview_fromslice') cdef memoryview_fromslice({{memviewslice_name}} memviewslice, int ndim, object (*to_object_func)(char *), int (*to_dtype_func)(char *, object) except 0, bint dtype_is_object): cdef _memoryviewslice result if memviewslice.memview == Py_None: return None # assert 0 < ndim <= memviewslice.memview.view.ndim, ( # ndim, memviewslice.memview.view.ndim) result = _memoryviewslice.__new__(_memoryviewslice, None, 0, dtype_is_object) result.from_slice = memviewslice __PYX_INC_MEMVIEW(&memviewslice, 1) result.from_object = ( memviewslice.memview)._get_base() result.typeinfo = memviewslice.memview.typeinfo result.view = memviewslice.memview.view result.view.buf = memviewslice.data result.view.ndim = ndim (<__pyx_buffer *> &result.view).obj = Py_None Py_INCREF(Py_None) if (memviewslice.memview).flags & PyBUF_WRITABLE: result.flags = PyBUF_RECORDS else: result.flags = PyBUF_RECORDS_RO result.view.shape = result.from_slice.shape result.view.strides = result.from_slice.strides # only set suboffsets if actually used, otherwise set to NULL to improve compatibility result.view.suboffsets = NULL for suboffset in result.from_slice.suboffsets[:ndim]: if suboffset >= 0: result.view.suboffsets = result.from_slice.suboffsets break result.view.len = result.view.itemsize for length in result.view.shape[:ndim]: result.view.len *= length result.to_object_func = to_object_func result.to_dtype_func = to_dtype_func return result @cname('__pyx_memoryview_get_slice_from_memoryview') cdef {{memviewslice_name}} *get_slice_from_memview(memoryview memview, {{memviewslice_name}} *mslice) except NULL: cdef _memoryviewslice obj if isinstance(memview, _memoryviewslice): obj = memview return &obj.from_slice else: slice_copy(memview, mslice) return mslice @cname('__pyx_memoryview_slice_copy') cdef void slice_copy(memoryview memview, {{memviewslice_name}} *dst) noexcept: cdef int dim cdef (Py_ssize_t*) shape, strides, suboffsets shape = memview.view.shape strides = memview.view.strides suboffsets = memview.view.suboffsets dst.memview = <__pyx_memoryview *> memview dst.data = memview.view.buf for dim in range(memview.view.ndim): dst.shape[dim] = shape[dim] dst.strides[dim] = strides[dim] dst.suboffsets[dim] = suboffsets[dim] if suboffsets else -1 @cname('__pyx_memoryview_copy_object') cdef memoryview_copy(memoryview memview): "Create a new memoryview object" cdef {{memviewslice_name}} memviewslice slice_copy(memview, &memviewslice) return memoryview_copy_from_slice(memview, &memviewslice) @cname('__pyx_memoryview_copy_object_from_slice') cdef memoryview_copy_from_slice(memoryview memview, {{memviewslice_name}} *memviewslice): """ Create a new memoryview object from a given memoryview object and slice. """ cdef object (*to_object_func)(char *) cdef int (*to_dtype_func)(char *, object) except 0 if isinstance(memview, _memoryviewslice): to_object_func = (<_memoryviewslice> memview).to_object_func to_dtype_func = (<_memoryviewslice> memview).to_dtype_func else: to_object_func = NULL to_dtype_func = NULL return memoryview_fromslice(memviewslice[0], memview.view.ndim, to_object_func, to_dtype_func, memview.dtype_is_object) # ### Copy the contents of a memoryview slices # cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) noexcept nogil: return -arg if arg < 0 else arg @cname('__pyx_get_best_slice_order') cdef char get_best_order({{memviewslice_name}} *mslice, int ndim) noexcept nogil: """ Figure out the best memory access order for a given slice. """ cdef int i cdef Py_ssize_t c_stride = 0 cdef Py_ssize_t f_stride = 0 for i in range(ndim - 1, -1, -1): if mslice.shape[i] > 1: c_stride = mslice.strides[i] break for i in range(ndim): if mslice.shape[i] > 1: f_stride = mslice.strides[i] break if abs_py_ssize_t(c_stride) <= abs_py_ssize_t(f_stride): return 'C' else: return 'F' @cython.cdivision(True) cdef void _copy_strided_to_strided(char *src_data, Py_ssize_t *src_strides, char *dst_data, Py_ssize_t *dst_strides, Py_ssize_t *src_shape, Py_ssize_t *dst_shape, int ndim, size_t itemsize) noexcept nogil: # Note: src_extent is 1 if we're broadcasting # dst_extent always >= src_extent as we don't do reductions cdef Py_ssize_t i cdef Py_ssize_t src_extent = src_shape[0] cdef Py_ssize_t dst_extent = dst_shape[0] cdef Py_ssize_t src_stride = src_strides[0] cdef Py_ssize_t dst_stride = dst_strides[0] if ndim == 1: if (src_stride > 0 and dst_stride > 0 and src_stride == itemsize == dst_stride): memcpy(dst_data, src_data, itemsize * dst_extent) else: for i in range(dst_extent): memcpy(dst_data, src_data, itemsize) src_data += src_stride dst_data += dst_stride else: for i in range(dst_extent): _copy_strided_to_strided(src_data, src_strides + 1, dst_data, dst_strides + 1, src_shape + 1, dst_shape + 1, ndim - 1, itemsize) src_data += src_stride dst_data += dst_stride cdef void copy_strided_to_strided({{memviewslice_name}} *src, {{memviewslice_name}} *dst, int ndim, size_t itemsize) noexcept nogil: _copy_strided_to_strided(src.data, src.strides, dst.data, dst.strides, src.shape, dst.shape, ndim, itemsize) @cname('__pyx_memoryview_slice_get_size') cdef Py_ssize_t slice_get_size({{memviewslice_name}} *src, int ndim) noexcept nogil: "Return the size of the memory occupied by the slice in number of bytes" cdef Py_ssize_t shape, size = src.memview.view.itemsize for shape in src.shape[:ndim]: size *= shape return size @cname('__pyx_fill_contig_strides_array') cdef Py_ssize_t fill_contig_strides_array( Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t stride, int ndim, char order) noexcept nogil: """ Fill the strides array for a slice with C or F contiguous strides. This is like PyBuffer_FillContiguousStrides, but compatible with py < 2.6 """ cdef int idx if order == 'F': for idx in range(ndim): strides[idx] = stride stride *= shape[idx] else: for idx in range(ndim - 1, -1, -1): strides[idx] = stride stride *= shape[idx] return stride @cname('__pyx_memoryview_copy_data_to_temp') cdef void *copy_data_to_temp({{memviewslice_name}} *src, {{memviewslice_name}} *tmpslice, char order, int ndim) except NULL nogil: """ Copy a direct slice to temporary contiguous memory. The caller should free the result when done. """ cdef int i cdef void *result cdef size_t itemsize = src.memview.view.itemsize cdef size_t size = slice_get_size(src, ndim) result = malloc(size) if not result: _err_no_memory() # tmpslice[0] = src tmpslice.data = result tmpslice.memview = src.memview for i in range(ndim): tmpslice.shape[i] = src.shape[i] tmpslice.suboffsets[i] = -1 fill_contig_strides_array(&tmpslice.shape[0], &tmpslice.strides[0], itemsize, ndim, order) # We need to broadcast strides again for i in range(ndim): if tmpslice.shape[i] == 1: tmpslice.strides[i] = 0 if slice_is_contig(src[0], order, ndim): memcpy(result, src.data, size) else: copy_strided_to_strided(src, tmpslice, ndim, itemsize) return result # Use 'with gil' functions and avoid 'with gil' blocks, as the code within the blocks # has temporaries that need the GIL to clean up @cname('__pyx_memoryview_err_extents') cdef int _err_extents(int i, Py_ssize_t extent1, Py_ssize_t extent2) except -1 with gil: raise ValueError, f"got differing extents in dimension {i} (got {extent1} and {extent2})" @cname('__pyx_memoryview_err_dim') cdef int _err_dim(PyObject *error, str msg, int dim) except -1 with gil: raise error, msg % dim @cname('__pyx_memoryview_err') cdef int _err(PyObject *error, str msg) except -1 with gil: raise error, msg @cname('__pyx_memoryview_err_no_memory') cdef int _err_no_memory() except -1 with gil: raise MemoryError @cname('__pyx_memoryview_copy_contents') cdef int memoryview_copy_contents({{memviewslice_name}} src, {{memviewslice_name}} dst, int src_ndim, int dst_ndim, bint dtype_is_object) except -1 nogil: """ Copy memory from slice src to slice dst. Check for overlapping memory and verify the shapes. """ cdef void *tmpdata = NULL cdef size_t itemsize = src.memview.view.itemsize cdef int i cdef char order = get_best_order(&src, src_ndim) cdef bint broadcasting = False cdef bint direct_copy = False cdef {{memviewslice_name}} tmp if src_ndim < dst_ndim: broadcast_leading(&src, src_ndim, dst_ndim) elif dst_ndim < src_ndim: broadcast_leading(&dst, dst_ndim, src_ndim) cdef int ndim = max(src_ndim, dst_ndim) for i in range(ndim): if src.shape[i] != dst.shape[i]: if src.shape[i] == 1: broadcasting = True src.strides[i] = 0 else: _err_extents(i, dst.shape[i], src.shape[i]) if src.suboffsets[i] >= 0: _err_dim(PyExc_ValueError, "Dimension %d is not direct", i) if slices_overlap(&src, &dst, ndim, itemsize): # slices overlap, copy to temp, copy temp to dst if not slice_is_contig(src, order, ndim): order = get_best_order(&dst, ndim) tmpdata = copy_data_to_temp(&src, &tmp, order, ndim) src = tmp if not broadcasting: # See if both slices have equal contiguity, in that case perform a # direct copy. This only works when we are not broadcasting. if slice_is_contig(src, 'C', ndim): direct_copy = slice_is_contig(dst, 'C', ndim) elif slice_is_contig(src, 'F', ndim): direct_copy = slice_is_contig(dst, 'F', ndim) if direct_copy: # Contiguous slices with same order refcount_copying(&dst, dtype_is_object, ndim, inc=False) memcpy(dst.data, src.data, slice_get_size(&src, ndim)) refcount_copying(&dst, dtype_is_object, ndim, inc=True) free(tmpdata) return 0 if order == 'F' == get_best_order(&dst, ndim): # see if both slices have Fortran order, transpose them to match our # C-style indexing order transpose_memslice(&src) transpose_memslice(&dst) refcount_copying(&dst, dtype_is_object, ndim, inc=False) copy_strided_to_strided(&src, &dst, ndim, itemsize) refcount_copying(&dst, dtype_is_object, ndim, inc=True) free(tmpdata) return 0 @cname('__pyx_memoryview_broadcast_leading') cdef void broadcast_leading({{memviewslice_name}} *mslice, int ndim, int ndim_other) noexcept nogil: cdef int i cdef int offset = ndim_other - ndim for i in range(ndim - 1, -1, -1): mslice.shape[i + offset] = mslice.shape[i] mslice.strides[i + offset] = mslice.strides[i] mslice.suboffsets[i + offset] = mslice.suboffsets[i] for i in range(offset): mslice.shape[i] = 1 mslice.strides[i] = mslice.strides[0] mslice.suboffsets[i] = -1 # ### Take care of refcounting the objects in slices. Do this separately from any copying, ### to minimize acquiring the GIL # @cname('__pyx_memoryview_refcount_copying') cdef void refcount_copying({{memviewslice_name}} *dst, bint dtype_is_object, int ndim, bint inc) noexcept nogil: # incref or decref the objects in the destination slice if the dtype is object if dtype_is_object: refcount_objects_in_slice_with_gil(dst.data, dst.shape, dst.strides, ndim, inc) @cname('__pyx_memoryview_refcount_objects_in_slice_with_gil') cdef void refcount_objects_in_slice_with_gil(char *data, Py_ssize_t *shape, Py_ssize_t *strides, int ndim, bint inc) noexcept with gil: refcount_objects_in_slice(data, shape, strides, ndim, inc) @cname('__pyx_memoryview_refcount_objects_in_slice') cdef void refcount_objects_in_slice(char *data, Py_ssize_t *shape, Py_ssize_t *strides, int ndim, bint inc) noexcept: cdef Py_ssize_t i cdef Py_ssize_t stride = strides[0] for i in range(shape[0]): if ndim == 1: if inc: Py_INCREF(( data)[0]) else: Py_DECREF(( data)[0]) else: refcount_objects_in_slice(data, shape + 1, strides + 1, ndim - 1, inc) data += stride # ### Scalar to slice assignment # @cname('__pyx_memoryview_slice_assign_scalar') cdef void slice_assign_scalar({{memviewslice_name}} *dst, int ndim, size_t itemsize, void *item, bint dtype_is_object) noexcept nogil: refcount_copying(dst, dtype_is_object, ndim, inc=False) _slice_assign_scalar(dst.data, dst.shape, dst.strides, ndim, itemsize, item) refcount_copying(dst, dtype_is_object, ndim, inc=True) @cname('__pyx_memoryview__slice_assign_scalar') cdef void _slice_assign_scalar(char *data, Py_ssize_t *shape, Py_ssize_t *strides, int ndim, size_t itemsize, void *item) noexcept nogil: cdef Py_ssize_t i cdef Py_ssize_t stride = strides[0] cdef Py_ssize_t extent = shape[0] if ndim == 1: for i in range(extent): memcpy(data, item, itemsize) data += stride else: for i in range(extent): _slice_assign_scalar(data, shape + 1, strides + 1, ndim - 1, itemsize, item) data += stride ############### BufferFormatFromTypeInfo ############### cdef extern from *: ctypedef struct __Pyx_StructField cdef enum: __PYX_BUF_FLAGS_PACKED_STRUCT __PYX_BUF_FLAGS_INTEGER_COMPLEX ctypedef struct __Pyx_TypeInfo: char* name __Pyx_StructField* fields size_t size size_t arraysize[8] int ndim char typegroup char is_unsigned int flags ctypedef struct __Pyx_StructField: __Pyx_TypeInfo* type char* name size_t offset ctypedef struct __Pyx_BufFmt_StackElem: __Pyx_StructField* field size_t parent_offset #ctypedef struct __Pyx_BufFmt_Context: # __Pyx_StructField root __Pyx_BufFmt_StackElem* head struct __pyx_typeinfo_string: char string[3] __pyx_typeinfo_string __Pyx_TypeInfoToFormat(__Pyx_TypeInfo *) @cname('__pyx_format_from_typeinfo') cdef bytes format_from_typeinfo(__Pyx_TypeInfo *type): cdef __Pyx_StructField *field cdef __pyx_typeinfo_string fmt cdef bytes part, result cdef Py_ssize_t i if type.typegroup == 'S': assert type.fields != NULL assert type.fields.type != NULL if type.flags & __PYX_BUF_FLAGS_PACKED_STRUCT: alignment = b'^' else: alignment = b'' parts = [b"T{"] field = type.fields while field.type: part = format_from_typeinfo(field.type) parts.append(part + b':' + field.name + b':') field += 1 result = alignment.join(parts) + b'}' else: fmt = __Pyx_TypeInfoToFormat(type) result = fmt.string if type.arraysize[0]: extents = [f"{type.arraysize[i]}" for i in range(type.ndim)] result = f"({u','.join(extents)})".encode('ascii') + result return result ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/MemoryView_C.c0000644000175100001770000007563700000000000021236 0ustar00runnerdocker00000000000000////////// MemviewSliceStruct.proto ////////// //@proto_block: utility_code_proto_before_types /* memoryview slice struct */ struct {{memview_struct_name}}; typedef struct { struct {{memview_struct_name}} *memview; char *data; Py_ssize_t shape[{{max_dims}}]; Py_ssize_t strides[{{max_dims}}]; Py_ssize_t suboffsets[{{max_dims}}]; } {{memviewslice_name}}; // used for "len(memviewslice)" #define __Pyx_MemoryView_Len(m) (m.shape[0]) /////////// Atomics.proto ///////////// //@proto_block: utility_code_proto_before_types #include #ifndef CYTHON_ATOMICS #define CYTHON_ATOMICS 1 #endif // using CYTHON_ATOMICS as a cdef extern bint in the Cython memoryview code // interacts badly with "import *". Therefore, define a helper function-like macro #define __PYX_CYTHON_ATOMICS_ENABLED() CYTHON_ATOMICS #define __pyx_atomic_int_type int #define __pyx_nonatomic_int_type int // For standard C/C++ atomics, get the headers first so we have ATOMIC_INT_LOCK_FREE // defined when we decide to use them. #if CYTHON_ATOMICS && (defined(__STDC_VERSION__) && \ (__STDC_VERSION__ >= 201112L) && \ !defined(__STDC_NO_ATOMICS__)) #include #elif CYTHON_ATOMICS && (defined(__cplusplus) && ( \ (__cplusplus >= 201103L) || \ (defined(_MSC_VER) && _MSC_VER >= 1700))) #include #endif #if CYTHON_ATOMICS && (defined(__STDC_VERSION__) && \ (__STDC_VERSION__ >= 201112L) && \ !defined(__STDC_NO_ATOMICS__) && \ ATOMIC_INT_LOCK_FREE == 2) // C11 atomics are available and ATOMIC_INT_LOCK_FREE is definitely on #undef __pyx_atomic_int_type #define __pyx_atomic_int_type atomic_int #define __pyx_atomic_incr_aligned(value) atomic_fetch_add_explicit(value, 1, memory_order_relaxed) #define __pyx_atomic_decr_aligned(value) atomic_fetch_sub_explicit(value, 1, memory_order_acq_rel) #if defined(__PYX_DEBUG_ATOMICS) && defined(_MSC_VER) #pragma message ("Using standard C atomics") #elif defined(__PYX_DEBUG_ATOMICS) #warning "Using standard C atomics" #endif #elif CYTHON_ATOMICS && (defined(__cplusplus) && ( \ (__cplusplus >= 201103L) || \ /*_MSC_VER 1700 is Visual Studio 2012 */ \ (defined(_MSC_VER) && _MSC_VER >= 1700)) && \ ATOMIC_INT_LOCK_FREE == 2) // C++11 atomics are available and ATOMIC_INT_LOCK_FREE is definitely on #undef __pyx_atomic_int_type #define __pyx_atomic_int_type std::atomic_int #define __pyx_atomic_incr_aligned(value) std::atomic_fetch_add_explicit(value, 1, std::memory_order_relaxed) #define __pyx_atomic_decr_aligned(value) std::atomic_fetch_sub_explicit(value, 1, std::memory_order_acq_rel) #if defined(__PYX_DEBUG_ATOMICS) && defined(_MSC_VER) #pragma message ("Using standard C++ atomics") #elif defined(__PYX_DEBUG_ATOMICS) #warning "Using standard C++ atomics" #endif #elif CYTHON_ATOMICS && (__GNUC__ >= 5 || (__GNUC__ == 4 && \ (__GNUC_MINOR__ > 1 || \ (__GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ >= 2)))) /* gcc >= 4.1.2 */ #define __pyx_atomic_incr_aligned(value) __sync_fetch_and_add(value, 1) #define __pyx_atomic_decr_aligned(value) __sync_fetch_and_sub(value, 1) #ifdef __PYX_DEBUG_ATOMICS #warning "Using GNU atomics" #endif #elif CYTHON_ATOMICS && defined(_MSC_VER) /* msvc */ #include #undef __pyx_atomic_int_type #define __pyx_atomic_int_type long #undef __pyx_nonatomic_int_type #define __pyx_nonatomic_int_type long #pragma intrinsic (_InterlockedExchangeAdd) #define __pyx_atomic_incr_aligned(value) _InterlockedExchangeAdd(value, 1) #define __pyx_atomic_decr_aligned(value) _InterlockedExchangeAdd(value, -1) #ifdef __PYX_DEBUG_ATOMICS #pragma message ("Using MSVC atomics") #endif #else #undef CYTHON_ATOMICS #define CYTHON_ATOMICS 0 #ifdef __PYX_DEBUG_ATOMICS #warning "Not using atomics" #endif #endif #if CYTHON_ATOMICS #define __pyx_add_acquisition_count(memview) \ __pyx_atomic_incr_aligned(__pyx_get_slice_count_pointer(memview)) #define __pyx_sub_acquisition_count(memview) \ __pyx_atomic_decr_aligned(__pyx_get_slice_count_pointer(memview)) #else #define __pyx_add_acquisition_count(memview) \ __pyx_add_acquisition_count_locked(__pyx_get_slice_count_pointer(memview), memview->lock) #define __pyx_sub_acquisition_count(memview) \ __pyx_sub_acquisition_count_locked(__pyx_get_slice_count_pointer(memview), memview->lock) #endif /////////////// ObjectToMemviewSlice.proto /////////////// static CYTHON_INLINE {{memviewslice_name}} {{funcname}}(PyObject *, int writable_flag); ////////// MemviewSliceInit.proto ////////// #define __Pyx_BUF_MAX_NDIMS %(BUF_MAX_NDIMS)d #define __Pyx_MEMVIEW_DIRECT 1 #define __Pyx_MEMVIEW_PTR 2 #define __Pyx_MEMVIEW_FULL 4 #define __Pyx_MEMVIEW_CONTIG 8 #define __Pyx_MEMVIEW_STRIDED 16 #define __Pyx_MEMVIEW_FOLLOW 32 #define __Pyx_IS_C_CONTIG 1 #define __Pyx_IS_F_CONTIG 2 static int __Pyx_init_memviewslice( struct __pyx_memoryview_obj *memview, int ndim, __Pyx_memviewslice *memviewslice, int memview_is_new_reference); static CYTHON_INLINE int __pyx_add_acquisition_count_locked( __pyx_atomic_int_type *acquisition_count, PyThread_type_lock lock); static CYTHON_INLINE int __pyx_sub_acquisition_count_locked( __pyx_atomic_int_type *acquisition_count, PyThread_type_lock lock); #define __pyx_get_slice_count_pointer(memview) (&memview->acquisition_count) #define __PYX_INC_MEMVIEW(slice, have_gil) __Pyx_INC_MEMVIEW(slice, have_gil, __LINE__) #define __PYX_XCLEAR_MEMVIEW(slice, have_gil) __Pyx_XCLEAR_MEMVIEW(slice, have_gil, __LINE__) static CYTHON_INLINE void __Pyx_INC_MEMVIEW({{memviewslice_name}} *, int, int); static CYTHON_INLINE void __Pyx_XCLEAR_MEMVIEW({{memviewslice_name}} *, int, int); /////////////// MemviewSliceIndex.proto /////////////// static CYTHON_INLINE char *__pyx_memviewslice_index_full( const char *bufp, Py_ssize_t idx, Py_ssize_t stride, Py_ssize_t suboffset); /////////////// ObjectToMemviewSlice /////////////// //@requires: MemviewSliceValidateAndInit static CYTHON_INLINE {{memviewslice_name}} {{funcname}}(PyObject *obj, int writable_flag) { {{memviewslice_name}} result = {{memslice_init}}; __Pyx_BufFmt_StackElem stack[{{struct_nesting_depth}}]; int axes_specs[] = { {{axes_specs}} }; int retcode; if (obj == Py_None) { /* We don't bother to refcount None */ result.memview = (struct __pyx_memoryview_obj *) Py_None; return result; } retcode = __Pyx_ValidateAndInit_memviewslice(axes_specs, {{c_or_f_flag}}, {{buf_flag}} | writable_flag, {{ndim}}, &{{dtype_typeinfo}}, stack, &result, obj); if (unlikely(retcode == -1)) goto __pyx_fail; return result; __pyx_fail: result.memview = NULL; result.data = NULL; return result; } /////////////// MemviewSliceValidateAndInit.proto /////////////// static int __Pyx_ValidateAndInit_memviewslice( int *axes_specs, int c_or_f_flag, int buf_flags, int ndim, __Pyx_TypeInfo *dtype, __Pyx_BufFmt_StackElem stack[], __Pyx_memviewslice *memviewslice, PyObject *original_obj); /////////////// MemviewSliceValidateAndInit /////////////// //@requires: Buffer.c::TypeInfoCompare //@requires: Buffer.c::BufferFormatStructs //@requires: Buffer.c::BufferFormatCheck static int __pyx_check_strides(Py_buffer *buf, int dim, int ndim, int spec) { if (buf->shape[dim] <= 1) return 1; if (buf->strides) { if (spec & __Pyx_MEMVIEW_CONTIG) { if (spec & (__Pyx_MEMVIEW_PTR|__Pyx_MEMVIEW_FULL)) { if (unlikely(buf->strides[dim] != sizeof(void *))) { PyErr_Format(PyExc_ValueError, "Buffer is not indirectly contiguous " "in dimension %d.", dim); goto fail; } } else if (unlikely(buf->strides[dim] != buf->itemsize)) { PyErr_SetString(PyExc_ValueError, "Buffer and memoryview are not contiguous " "in the same dimension."); goto fail; } } if (spec & __Pyx_MEMVIEW_FOLLOW) { Py_ssize_t stride = buf->strides[dim]; if (stride < 0) stride = -stride; if (unlikely(stride < buf->itemsize)) { PyErr_SetString(PyExc_ValueError, "Buffer and memoryview are not contiguous " "in the same dimension."); goto fail; } } } else { if (unlikely(spec & __Pyx_MEMVIEW_CONTIG && dim != ndim - 1)) { PyErr_Format(PyExc_ValueError, "C-contiguous buffer is not contiguous in " "dimension %d", dim); goto fail; } else if (unlikely(spec & (__Pyx_MEMVIEW_PTR))) { PyErr_Format(PyExc_ValueError, "C-contiguous buffer is not indirect in " "dimension %d", dim); goto fail; } else if (unlikely(buf->suboffsets)) { PyErr_SetString(PyExc_ValueError, "Buffer exposes suboffsets but no strides"); goto fail; } } return 1; fail: return 0; } static int __pyx_check_suboffsets(Py_buffer *buf, int dim, int ndim, int spec) { CYTHON_UNUSED_VAR(ndim); // Todo: without PyBUF_INDIRECT we may not have suboffset information, i.e., the // ptr may not be set to NULL but may be uninitialized? if (spec & __Pyx_MEMVIEW_DIRECT) { if (unlikely(buf->suboffsets && buf->suboffsets[dim] >= 0)) { PyErr_Format(PyExc_ValueError, "Buffer not compatible with direct access " "in dimension %d.", dim); goto fail; } } if (spec & __Pyx_MEMVIEW_PTR) { if (unlikely(!buf->suboffsets || (buf->suboffsets[dim] < 0))) { PyErr_Format(PyExc_ValueError, "Buffer is not indirectly accessible " "in dimension %d.", dim); goto fail; } } return 1; fail: return 0; } static int __pyx_verify_contig(Py_buffer *buf, int ndim, int c_or_f_flag) { int i; if (c_or_f_flag & __Pyx_IS_F_CONTIG) { Py_ssize_t stride = 1; for (i = 0; i < ndim; i++) { if (unlikely(stride * buf->itemsize != buf->strides[i] && buf->shape[i] > 1)) { PyErr_SetString(PyExc_ValueError, "Buffer not fortran contiguous."); goto fail; } stride = stride * buf->shape[i]; } } else if (c_or_f_flag & __Pyx_IS_C_CONTIG) { Py_ssize_t stride = 1; for (i = ndim - 1; i >- 1; i--) { if (unlikely(stride * buf->itemsize != buf->strides[i] && buf->shape[i] > 1)) { PyErr_SetString(PyExc_ValueError, "Buffer not C contiguous."); goto fail; } stride = stride * buf->shape[i]; } } return 1; fail: return 0; } static int __Pyx_ValidateAndInit_memviewslice( int *axes_specs, int c_or_f_flag, int buf_flags, int ndim, __Pyx_TypeInfo *dtype, __Pyx_BufFmt_StackElem stack[], __Pyx_memviewslice *memviewslice, PyObject *original_obj) { struct __pyx_memoryview_obj *memview, *new_memview; __Pyx_RefNannyDeclarations Py_buffer *buf; int i, spec = 0, retval = -1; __Pyx_BufFmt_Context ctx; int from_memoryview = __pyx_memoryview_check(original_obj); __Pyx_RefNannySetupContext("ValidateAndInit_memviewslice", 0); if (from_memoryview && __pyx_typeinfo_cmp(dtype, ((struct __pyx_memoryview_obj *) original_obj)->typeinfo)) { /* We have a matching dtype, skip format parsing */ memview = (struct __pyx_memoryview_obj *) original_obj; new_memview = NULL; } else { memview = (struct __pyx_memoryview_obj *) __pyx_memoryview_new( original_obj, buf_flags, 0, dtype); new_memview = memview; if (unlikely(!memview)) goto fail; } buf = &memview->view; if (unlikely(buf->ndim != ndim)) { PyErr_Format(PyExc_ValueError, "Buffer has wrong number of dimensions (expected %d, got %d)", ndim, buf->ndim); goto fail; } if (new_memview) { __Pyx_BufFmt_Init(&ctx, stack, dtype); if (unlikely(!__Pyx_BufFmt_CheckString(&ctx, buf->format))) goto fail; } if (unlikely((unsigned) buf->itemsize != dtype->size)) { PyErr_Format(PyExc_ValueError, "Item size of buffer (%" CYTHON_FORMAT_SSIZE_T "u byte%s) " "does not match size of '%s' (%" CYTHON_FORMAT_SSIZE_T "u byte%s)", buf->itemsize, (buf->itemsize > 1) ? "s" : "", dtype->name, dtype->size, (dtype->size > 1) ? "s" : ""); goto fail; } /* Check axes */ if (buf->len > 0) { // 0-sized arrays do not undergo these checks since their strides are // irrelevant and they are always both C- and F-contiguous. for (i = 0; i < ndim; i++) { spec = axes_specs[i]; if (unlikely(!__pyx_check_strides(buf, i, ndim, spec))) goto fail; if (unlikely(!__pyx_check_suboffsets(buf, i, ndim, spec))) goto fail; } /* Check contiguity */ if (unlikely(buf->strides && !__pyx_verify_contig(buf, ndim, c_or_f_flag))) goto fail; } /* Initialize */ if (unlikely(__Pyx_init_memviewslice(memview, ndim, memviewslice, new_memview != NULL) == -1)) { goto fail; } retval = 0; goto no_fail; fail: Py_XDECREF(new_memview); retval = -1; no_fail: __Pyx_RefNannyFinishContext(); return retval; } ////////// MemviewSliceInit ////////// static int __Pyx_init_memviewslice(struct __pyx_memoryview_obj *memview, int ndim, {{memviewslice_name}} *memviewslice, int memview_is_new_reference) { __Pyx_RefNannyDeclarations int i, retval=-1; Py_buffer *buf = &memview->view; __Pyx_RefNannySetupContext("init_memviewslice", 0); if (unlikely(memviewslice->memview || memviewslice->data)) { PyErr_SetString(PyExc_ValueError, "memviewslice is already initialized!"); goto fail; } if (buf->strides) { for (i = 0; i < ndim; i++) { memviewslice->strides[i] = buf->strides[i]; } } else { Py_ssize_t stride = buf->itemsize; for (i = ndim - 1; i >= 0; i--) { memviewslice->strides[i] = stride; stride *= buf->shape[i]; } } for (i = 0; i < ndim; i++) { memviewslice->shape[i] = buf->shape[i]; if (buf->suboffsets) { memviewslice->suboffsets[i] = buf->suboffsets[i]; } else { memviewslice->suboffsets[i] = -1; } } memviewslice->memview = memview; memviewslice->data = (char *)buf->buf; if (__pyx_add_acquisition_count(memview) == 0 && !memview_is_new_reference) { Py_INCREF(memview); } retval = 0; goto no_fail; fail: /* Don't decref, the memoryview may be borrowed. Let the caller do the cleanup */ /* __Pyx_XDECREF(memviewslice->memview); */ memviewslice->memview = 0; memviewslice->data = 0; retval = -1; no_fail: __Pyx_RefNannyFinishContext(); return retval; } #ifndef Py_NO_RETURN // available since Py3.3 #define Py_NO_RETURN #endif static void __pyx_fatalerror(const char *fmt, ...) Py_NO_RETURN { va_list vargs; char msg[200]; #if PY_VERSION_HEX >= 0x030A0000 || defined(HAVE_STDARG_PROTOTYPES) va_start(vargs, fmt); #else va_start(vargs); #endif vsnprintf(msg, 200, fmt, vargs); va_end(vargs); Py_FatalError(msg); } static CYTHON_INLINE int __pyx_add_acquisition_count_locked(__pyx_atomic_int_type *acquisition_count, PyThread_type_lock lock) { int result; PyThread_acquire_lock(lock, 1); result = (*acquisition_count)++; PyThread_release_lock(lock); return result; } static CYTHON_INLINE int __pyx_sub_acquisition_count_locked(__pyx_atomic_int_type *acquisition_count, PyThread_type_lock lock) { int result; PyThread_acquire_lock(lock, 1); result = (*acquisition_count)--; PyThread_release_lock(lock); return result; } static CYTHON_INLINE void __Pyx_INC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil, int lineno) { __pyx_nonatomic_int_type old_acquisition_count; struct {{memview_struct_name}} *memview = memslice->memview; if (unlikely(!memview || (PyObject *) memview == Py_None)) { // Allow uninitialized memoryview assignment and do not ref-count None. return; } old_acquisition_count = __pyx_add_acquisition_count(memview); if (unlikely(old_acquisition_count <= 0)) { if (likely(old_acquisition_count == 0)) { // First acquisition => keep the memoryview object alive. if (have_gil) { Py_INCREF((PyObject *) memview); } else { PyGILState_STATE _gilstate = PyGILState_Ensure(); Py_INCREF((PyObject *) memview); PyGILState_Release(_gilstate); } } else { __pyx_fatalerror("Acquisition count is %d (line %d)", old_acquisition_count+1, lineno); } } } static CYTHON_INLINE void __Pyx_XCLEAR_MEMVIEW({{memviewslice_name}} *memslice, int have_gil, int lineno) { __pyx_nonatomic_int_type old_acquisition_count; struct {{memview_struct_name}} *memview = memslice->memview; if (unlikely(!memview || (PyObject *) memview == Py_None)) { // Do not ref-count None. memslice->memview = NULL; return; } old_acquisition_count = __pyx_sub_acquisition_count(memview); memslice->data = NULL; if (likely(old_acquisition_count > 1)) { // Still other slices out there => we do not own the reference. memslice->memview = NULL; } else if (likely(old_acquisition_count == 1)) { // Last slice => discard owned Python reference to memoryview object. if (have_gil) { Py_CLEAR(memslice->memview); } else { PyGILState_STATE _gilstate = PyGILState_Ensure(); Py_CLEAR(memslice->memview); PyGILState_Release(_gilstate); } } else { __pyx_fatalerror("Acquisition count is %d (line %d)", old_acquisition_count-1, lineno); } } ////////// MemviewSliceCopyTemplate.proto ////////// static {{memviewslice_name}} __pyx_memoryview_copy_new_contig(const __Pyx_memviewslice *from_mvs, const char *mode, int ndim, size_t sizeof_dtype, int contig_flag, int dtype_is_object); ////////// MemviewSliceCopyTemplate ////////// static {{memviewslice_name}} __pyx_memoryview_copy_new_contig(const __Pyx_memviewslice *from_mvs, const char *mode, int ndim, size_t sizeof_dtype, int contig_flag, int dtype_is_object) { __Pyx_RefNannyDeclarations int i; __Pyx_memviewslice new_mvs = {{memslice_init}}; struct __pyx_memoryview_obj *from_memview = from_mvs->memview; Py_buffer *buf = &from_memview->view; PyObject *shape_tuple = NULL; PyObject *temp_int = NULL; struct __pyx_array_obj *array_obj = NULL; struct __pyx_memoryview_obj *memview_obj = NULL; __Pyx_RefNannySetupContext("__pyx_memoryview_copy_new_contig", 0); for (i = 0; i < ndim; i++) { if (unlikely(from_mvs->suboffsets[i] >= 0)) { PyErr_Format(PyExc_ValueError, "Cannot copy memoryview slice with " "indirect dimensions (axis %d)", i); goto fail; } } shape_tuple = PyTuple_New(ndim); if (unlikely(!shape_tuple)) { goto fail; } __Pyx_GOTREF(shape_tuple); for(i = 0; i < ndim; i++) { temp_int = PyInt_FromSsize_t(from_mvs->shape[i]); if(unlikely(!temp_int)) { goto fail; } else { PyTuple_SET_ITEM(shape_tuple, i, temp_int); temp_int = NULL; } } array_obj = __pyx_array_new(shape_tuple, sizeof_dtype, buf->format, (char *) mode, NULL); if (unlikely(!array_obj)) { goto fail; } __Pyx_GOTREF(array_obj); memview_obj = (struct __pyx_memoryview_obj *) __pyx_memoryview_new( (PyObject *) array_obj, contig_flag, dtype_is_object, from_mvs->memview->typeinfo); if (unlikely(!memview_obj)) goto fail; /* initialize new_mvs */ if (unlikely(__Pyx_init_memviewslice(memview_obj, ndim, &new_mvs, 1) < 0)) goto fail; if (unlikely(__pyx_memoryview_copy_contents(*from_mvs, new_mvs, ndim, ndim, dtype_is_object) < 0)) goto fail; goto no_fail; fail: __Pyx_XDECREF(new_mvs.memview); new_mvs.memview = NULL; new_mvs.data = NULL; no_fail: __Pyx_XDECREF(shape_tuple); __Pyx_XDECREF(temp_int); __Pyx_XDECREF(array_obj); __Pyx_RefNannyFinishContext(); return new_mvs; } ////////// CopyContentsUtility.proto ///////// #define {{func_cname}}(slice) \ __pyx_memoryview_copy_new_contig(&slice, "{{mode}}", {{ndim}}, \ sizeof({{dtype_decl}}), {{contig_flag}}, \ {{dtype_is_object}}) ////////// OverlappingSlices.proto ////////// static int __pyx_slices_overlap({{memviewslice_name}} *slice1, {{memviewslice_name}} *slice2, int ndim, size_t itemsize); ////////// OverlappingSlices ////////// /* Based on numpy's core/src/multiarray/array_assign.c */ /* Gets a half-open range [start, end) which contains the array data */ static void __pyx_get_array_memory_extents({{memviewslice_name}} *slice, void **out_start, void **out_end, int ndim, size_t itemsize) { char *start, *end; int i; start = end = slice->data; for (i = 0; i < ndim; i++) { Py_ssize_t stride = slice->strides[i]; Py_ssize_t extent = slice->shape[i]; if (extent == 0) { *out_start = *out_end = start; return; } else { if (stride > 0) end += stride * (extent - 1); else start += stride * (extent - 1); } } /* Return a half-open range */ *out_start = start; *out_end = end + itemsize; } /* Returns 1 if the arrays have overlapping data, 0 otherwise */ static int __pyx_slices_overlap({{memviewslice_name}} *slice1, {{memviewslice_name}} *slice2, int ndim, size_t itemsize) { void *start1, *end1, *start2, *end2; __pyx_get_array_memory_extents(slice1, &start1, &end1, ndim, itemsize); __pyx_get_array_memory_extents(slice2, &start2, &end2, ndim, itemsize); return (start1 < end2) && (start2 < end1); } ////////// MemviewSliceCheckContig.proto ////////// #define __pyx_memviewslice_is_contig_{{contig_type}}{{ndim}}(slice) \ __pyx_memviewslice_is_contig(slice, '{{contig_type}}', {{ndim}}) ////////// MemviewSliceIsContig.proto ////////// static int __pyx_memviewslice_is_contig(const {{memviewslice_name}} mvs, char order, int ndim);/*proto*/ ////////// MemviewSliceIsContig ////////// static int __pyx_memviewslice_is_contig(const {{memviewslice_name}} mvs, char order, int ndim) { int i, index, step, start; Py_ssize_t itemsize = mvs.memview->view.itemsize; if (order == 'F') { step = 1; start = 0; } else { step = -1; start = ndim - 1; } for (i = 0; i < ndim; i++) { index = start + step * i; if (mvs.suboffsets[index] >= 0 || mvs.strides[index] != itemsize) return 0; itemsize *= mvs.shape[index]; } return 1; } /////////////// MemviewSliceIndex /////////////// static CYTHON_INLINE char * __pyx_memviewslice_index_full(const char *bufp, Py_ssize_t idx, Py_ssize_t stride, Py_ssize_t suboffset) { bufp = bufp + idx * stride; if (suboffset >= 0) { bufp = *((char **) bufp) + suboffset; } return (char *) bufp; } /////////////// MemviewDtypeToObject.proto /////////////// {{if to_py_function}} static CYTHON_INLINE PyObject *{{get_function}}(const char *itemp); /* proto */ {{endif}} {{if from_py_function}} static CYTHON_INLINE int {{set_function}}(const char *itemp, PyObject *obj); /* proto */ {{endif}} /////////////// MemviewDtypeToObject /////////////// {{#__pyx_memview__to_object}} /* Convert a dtype to or from a Python object */ {{if to_py_function}} static CYTHON_INLINE PyObject *{{get_function}}(const char *itemp) { return (PyObject *) {{to_py_function}}(*({{dtype}} *) itemp); } {{endif}} {{if from_py_function}} static CYTHON_INLINE int {{set_function}}(const char *itemp, PyObject *obj) { {{dtype}} value = {{from_py_function}}(obj); if (unlikely({{error_condition}})) return 0; *({{dtype}} *) itemp = value; return 1; } {{endif}} /////////////// MemviewObjectToObject.proto /////////////// /* Function callbacks (for memoryview object) for dtype object */ static PyObject *{{get_function}}(const char *itemp); /* proto */ static int {{set_function}}(const char *itemp, PyObject *obj); /* proto */ /////////////// MemviewObjectToObject /////////////// static PyObject *{{get_function}}(const char *itemp) { PyObject *result = *(PyObject **) itemp; Py_INCREF(result); return result; } static int {{set_function}}(const char *itemp, PyObject *obj) { Py_INCREF(obj); Py_DECREF(*(PyObject **) itemp); *(PyObject **) itemp = obj; return 1; } /////////// ToughSlice ////////// /* Dimension is indexed with 'start:stop:step' */ if (unlikely(__pyx_memoryview_slice_memviewslice( &{{dst}}, {{src}}.shape[{{dim}}], {{src}}.strides[{{dim}}], {{src}}.suboffsets[{{dim}}], {{dim}}, {{new_ndim}}, &{{get_suboffset_dim()}}, {{start}}, {{stop}}, {{step}}, {{int(have_start)}}, {{int(have_stop)}}, {{int(have_step)}}, 1) < 0)) { {{error_goto}} } ////////// SimpleSlice ////////// /* Dimension is indexed with ':' only */ {{dst}}.shape[{{new_ndim}}] = {{src}}.shape[{{dim}}]; {{dst}}.strides[{{new_ndim}}] = {{src}}.strides[{{dim}}]; {{if access == 'direct'}} {{dst}}.suboffsets[{{new_ndim}}] = -1; {{else}} {{dst}}.suboffsets[{{new_ndim}}] = {{src}}.suboffsets[{{dim}}]; if ({{src}}.suboffsets[{{dim}}] >= 0) {{get_suboffset_dim()}} = {{new_ndim}}; {{endif}} ////////// SliceIndex ////////// // Dimension is indexed with an integer, we could use the ToughSlice // approach, but this is faster { Py_ssize_t __pyx_tmp_idx = {{idx}}; {{if wraparound or boundscheck}} Py_ssize_t __pyx_tmp_shape = {{src}}.shape[{{dim}}]; {{endif}} Py_ssize_t __pyx_tmp_stride = {{src}}.strides[{{dim}}]; {{if wraparound}} if (__pyx_tmp_idx < 0) __pyx_tmp_idx += __pyx_tmp_shape; {{endif}} {{if boundscheck}} if (unlikely(!__Pyx_is_valid_index(__pyx_tmp_idx, __pyx_tmp_shape))) { {{if not have_gil}} #ifdef WITH_THREAD PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); #endif {{endif}} PyErr_SetString(PyExc_IndexError, "Index out of bounds (axis {{dim}})"); {{if not have_gil}} #ifdef WITH_THREAD PyGILState_Release(__pyx_gilstate_save); #endif {{endif}} {{error_goto}} } {{endif}} {{if all_dimensions_direct}} {{dst}}.data += __pyx_tmp_idx * __pyx_tmp_stride; {{else}} if ({{get_suboffset_dim()}} < 0) { {{dst}}.data += __pyx_tmp_idx * __pyx_tmp_stride; /* This dimension is the first dimension, or is preceded by */ /* direct or indirect dimensions that are indexed away. */ /* Hence suboffset_dim must be less than zero, and we can have */ /* our data pointer refer to another block by dereferencing. */ /* slice.data -> B -> C becomes slice.data -> C */ {{if indirect}} { Py_ssize_t __pyx_tmp_suboffset = {{src}}.suboffsets[{{dim}}]; {{if generic}} if (__pyx_tmp_suboffset >= 0) {{endif}} {{dst}}.data = *((char **) {{dst}}.data) + __pyx_tmp_suboffset; } {{endif}} } else { {{dst}}.suboffsets[{{get_suboffset_dim()}}] += __pyx_tmp_idx * __pyx_tmp_stride; /* Note: dimension can not be indirect, the compiler will have */ /* issued an error */ } {{endif}} } ////////// FillStrided1DScalar.proto ////////// static void __pyx_fill_slice_{{dtype_name}}({{type_decl}} *p, Py_ssize_t extent, Py_ssize_t stride, size_t itemsize, void *itemp); ////////// FillStrided1DScalar ////////// /* Fill a slice with a scalar value. The dimension is direct and strided or contiguous */ /* This can be used as a callback for the memoryview object to efficiently assign a scalar */ /* Currently unused */ static void __pyx_fill_slice_{{dtype_name}}({{type_decl}} *p, Py_ssize_t extent, Py_ssize_t stride, size_t itemsize, void *itemp) { Py_ssize_t i; {{type_decl}} item = *(({{type_decl}} *) itemp); {{type_decl}} *endp; stride /= sizeof({{type_decl}}); endp = p + stride * extent; while (p < endp) { *p = item; p += stride; } } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/ModuleSetupCode.c0000644000175100001770000024561300000000000021723 0ustar00runnerdocker00000000000000/////////////// InitLimitedAPI /////////////// #if defined(CYTHON_LIMITED_API) && 0 /* disabled: enabling Py_LIMITED_API needs more work */ #ifndef Py_LIMITED_API #if CYTHON_LIMITED_API+0 > 0x03030000 #define Py_LIMITED_API CYTHON_LIMITED_API #else #define Py_LIMITED_API 0x03030000 #endif #endif #endif /////////////// CModulePreamble /////////////// #include /* For offsetof */ #ifndef offsetof #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) #endif #if !defined(_WIN32) && !defined(WIN32) && !defined(MS_WINDOWS) #ifndef __stdcall #define __stdcall #endif #ifndef __cdecl #define __cdecl #endif #ifndef __fastcall #define __fastcall #endif #endif #ifndef DL_IMPORT #define DL_IMPORT(t) t #endif #ifndef DL_EXPORT #define DL_EXPORT(t) t #endif // For use in DL_IMPORT/DL_EXPORT macros. #define __PYX_COMMA , #ifndef HAVE_LONG_LONG // CPython has required PY_LONG_LONG support for years, even if HAVE_LONG_LONG is not defined for us #define HAVE_LONG_LONG #endif #ifndef PY_LONG_LONG #define PY_LONG_LONG LONG_LONG #endif #ifndef Py_HUGE_VAL #define Py_HUGE_VAL HUGE_VAL #endif // For the limited API it often makes sense to use Py_LIMITED_API rather than PY_VERSION_HEX // when doing version checks. #define __PYX_LIMITED_VERSION_HEX PY_VERSION_HEX #if defined(GRAALVM_PYTHON) /* For very preliminary testing purposes. Most variables are set the same as PyPy. The existence of this section does not imply that anything works or is even tested */ // GRAALVM_PYTHON test comes before PyPy test because GraalPython unhelpfully defines PYPY_VERSION #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_CPYTHON 0 #define CYTHON_COMPILING_IN_LIMITED_API 0 #define CYTHON_COMPILING_IN_GRAAL 1 #define CYTHON_COMPILING_IN_NOGIL 0 #undef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 0 #undef CYTHON_USE_TYPE_SPECS #define CYTHON_USE_TYPE_SPECS 0 #undef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 0 #if PY_VERSION_HEX < 0x03050000 #undef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 0 #elif !defined(CYTHON_USE_ASYNC_SLOTS) #define CYTHON_USE_ASYNC_SLOTS 1 #endif #undef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 0 #undef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 0 #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #undef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 0 #undef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 1 #undef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 0 #undef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 0 #undef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 0 #undef CYTHON_FAST_GIL #define CYTHON_FAST_GIL 0 #undef CYTHON_METH_FASTCALL #define CYTHON_METH_FASTCALL 0 #undef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 0 #ifndef CYTHON_PEP487_INIT_SUBCLASS #define CYTHON_PEP487_INIT_SUBCLASS (PY_MAJOR_VERSION >= 3) #endif #undef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT 1 #undef CYTHON_USE_MODULE_STATE #define CYTHON_USE_MODULE_STATE 0 #undef CYTHON_USE_TP_FINALIZE #define CYTHON_USE_TP_FINALIZE 0 #undef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 #endif #elif defined(PYPY_VERSION) #define CYTHON_COMPILING_IN_PYPY 1 #define CYTHON_COMPILING_IN_CPYTHON 0 #define CYTHON_COMPILING_IN_LIMITED_API 0 #define CYTHON_COMPILING_IN_GRAAL 0 #define CYTHON_COMPILING_IN_NOGIL 0 #undef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 0 #ifndef CYTHON_USE_TYPE_SPECS #define CYTHON_USE_TYPE_SPECS 0 #endif #undef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 0 #if PY_VERSION_HEX < 0x03050000 #undef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 0 #elif !defined(CYTHON_USE_ASYNC_SLOTS) #define CYTHON_USE_ASYNC_SLOTS 1 #endif #undef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 0 #undef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 0 #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #undef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 0 #undef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 1 #undef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 0 #undef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 0 #undef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 0 #undef CYTHON_FAST_GIL #define CYTHON_FAST_GIL 0 #undef CYTHON_METH_FASTCALL #define CYTHON_METH_FASTCALL 0 #undef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 0 #ifndef CYTHON_PEP487_INIT_SUBCLASS #define CYTHON_PEP487_INIT_SUBCLASS (PY_MAJOR_VERSION >= 3) #endif #if PY_VERSION_HEX < 0x03090000 #undef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT 0 #elif !defined(CYTHON_PEP489_MULTI_PHASE_INIT) #define CYTHON_PEP489_MULTI_PHASE_INIT 1 #endif #undef CYTHON_USE_MODULE_STATE #define CYTHON_USE_MODULE_STATE 0 #undef CYTHON_USE_TP_FINALIZE #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1 && PYPY_VERSION_NUM >= 0x07030C00) #undef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 #endif #elif defined(CYTHON_LIMITED_API) // EXPERIMENTAL !! #ifdef Py_LIMITED_API #undef __PYX_LIMITED_VERSION_HEX #define __PYX_LIMITED_VERSION_HEX Py_LIMITED_API #endif #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_CPYTHON 0 #define CYTHON_COMPILING_IN_LIMITED_API 1 #define CYTHON_COMPILING_IN_GRAAL 0 #define CYTHON_COMPILING_IN_NOGIL 0 // CYTHON_CLINE_IN_TRACEBACK is currently disabled for the Limited API #undef CYTHON_CLINE_IN_TRACEBACK #define CYTHON_CLINE_IN_TRACEBACK 0 #undef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 0 #undef CYTHON_USE_TYPE_SPECS #define CYTHON_USE_TYPE_SPECS 1 #undef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 0 #undef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 0 #undef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 0 #undef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 0 #ifndef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #endif #undef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 0 #ifndef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 0 #endif #undef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 0 #undef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 0 #undef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 0 #undef CYTHON_FAST_GIL #define CYTHON_FAST_GIL 0 #undef CYTHON_METH_FASTCALL #define CYTHON_METH_FASTCALL 0 #undef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 0 #ifndef CYTHON_PEP487_INIT_SUBCLASS #define CYTHON_PEP487_INIT_SUBCLASS 1 #endif #undef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT 0 #undef CYTHON_USE_MODULE_STATE #define CYTHON_USE_MODULE_STATE 1 #ifndef CYTHON_USE_TP_FINALIZE // PyObject_CallFinalizerFromDealloc is missing and not easily replaced #define CYTHON_USE_TP_FINALIZE 0 #endif #undef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 #endif #elif defined(Py_GIL_DISABLED) || defined(Py_NOGIL) #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_CPYTHON 0 #define CYTHON_COMPILING_IN_LIMITED_API 0 #define CYTHON_COMPILING_IN_GRAAL 0 #define CYTHON_COMPILING_IN_NOGIL 1 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif #undef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 0 #ifndef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 1 #endif #undef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 0 #ifndef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 1 #endif #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #undef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 0 #ifndef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 0 #endif #ifndef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 1 #endif #ifndef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 1 #endif #undef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 0 #undef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 0 #ifndef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT 1 #endif #ifndef CYTHON_USE_TP_FINALIZE #define CYTHON_USE_TP_FINALIZE 1 #endif #undef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS 0 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 #else #define CYTHON_COMPILING_IN_PYPY 0 #define CYTHON_COMPILING_IN_CPYTHON 1 #define CYTHON_COMPILING_IN_LIMITED_API 0 #define CYTHON_COMPILING_IN_GRAAL 0 #define CYTHON_COMPILING_IN_NOGIL 0 #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif #ifndef CYTHON_USE_TYPE_SPECS #define CYTHON_USE_TYPE_SPECS 0 #endif #ifndef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 1 #endif #if PY_MAJOR_VERSION < 3 #undef CYTHON_USE_ASYNC_SLOTS #define CYTHON_USE_ASYNC_SLOTS 0 #elif !defined(CYTHON_USE_ASYNC_SLOTS) #define CYTHON_USE_ASYNC_SLOTS 1 #endif #ifndef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 1 #endif #ifndef CYTHON_USE_PYLIST_INTERNALS #define CYTHON_USE_PYLIST_INTERNALS 1 #endif #ifndef CYTHON_USE_UNICODE_INTERNALS #define CYTHON_USE_UNICODE_INTERNALS 1 #endif #if PY_VERSION_HEX < 0x030300F0 || PY_VERSION_HEX >= 0x030B00A2 // Python 3.11a2 hid _PyLong_FormatAdvancedWriter and _PyFloat_FormatAdvancedWriter // therefore disable unicode writer until a better alternative appears #undef CYTHON_USE_UNICODE_WRITER #define CYTHON_USE_UNICODE_WRITER 0 #elif !defined(CYTHON_USE_UNICODE_WRITER) #define CYTHON_USE_UNICODE_WRITER 1 #endif // CYTHON_AVOID_BORROWED_REFS - Avoid borrowed references and always request owned references directly instead. #ifndef CYTHON_AVOID_BORROWED_REFS #define CYTHON_AVOID_BORROWED_REFS 0 #endif // CYTHON_ASSUME_SAFE_MACROS - Assume that macro calls do not fail and do not raise exceptions. #ifndef CYTHON_ASSUME_SAFE_MACROS #define CYTHON_ASSUME_SAFE_MACROS 1 #endif #ifndef CYTHON_UNPACK_METHODS #define CYTHON_UNPACK_METHODS 1 #endif #ifndef CYTHON_FAST_THREAD_STATE #define CYTHON_FAST_THREAD_STATE 1 #endif #ifndef CYTHON_FAST_GIL // Py3<3.5.2 does not support _PyThreadState_UncheckedGet(). // FIXME: FastGIL can probably be supported also in CPython 3.12 but needs to be adapted. #define CYTHON_FAST_GIL (PY_MAJOR_VERSION < 3 || PY_VERSION_HEX >= 0x03060000 && PY_VERSION_HEX < 0x030C00A6) #endif #ifndef CYTHON_METH_FASTCALL // CPython 3.6 introduced METH_FASTCALL but with slightly different // semantics. It became stable starting from CPython 3.7. #define CYTHON_METH_FASTCALL (PY_VERSION_HEX >= 0x030700A1) #endif #ifndef CYTHON_FAST_PYCALL #define CYTHON_FAST_PYCALL 1 #endif #ifndef CYTHON_PEP487_INIT_SUBCLASS #define CYTHON_PEP487_INIT_SUBCLASS 1 #endif #if PY_VERSION_HEX < 0x03050000 #undef CYTHON_PEP489_MULTI_PHASE_INIT #define CYTHON_PEP489_MULTI_PHASE_INIT 0 #elif !defined(CYTHON_PEP489_MULTI_PHASE_INIT) #define CYTHON_PEP489_MULTI_PHASE_INIT 1 #endif // CYTHON_USE_MODULE_STATE - Use a module state/globals struct tied to the module object. #ifndef CYTHON_USE_MODULE_STATE // EXPERIMENTAL !! #define CYTHON_USE_MODULE_STATE 0 #endif #if PY_VERSION_HEX < 0x030400a1 #undef CYTHON_USE_TP_FINALIZE #define CYTHON_USE_TP_FINALIZE 0 #elif !defined(CYTHON_USE_TP_FINALIZE) #define CYTHON_USE_TP_FINALIZE 1 #endif #if PY_VERSION_HEX < 0x030600B1 #undef CYTHON_USE_DICT_VERSIONS #define CYTHON_USE_DICT_VERSIONS 0 #elif !defined(CYTHON_USE_DICT_VERSIONS) // Python 3.12a5 deprecated "ma_version_tag" #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX < 0x030C00A5) #endif #if PY_VERSION_HEX < 0x030700A3 #undef CYTHON_USE_EXC_INFO_STACK #define CYTHON_USE_EXC_INFO_STACK 0 #elif !defined(CYTHON_USE_EXC_INFO_STACK) #define CYTHON_USE_EXC_INFO_STACK 1 #endif #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC #define CYTHON_UPDATE_DESCRIPTOR_DOC 1 #endif #endif #if !defined(CYTHON_FAST_PYCCALL) #define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) #endif #if !defined(CYTHON_VECTORCALL) #define CYTHON_VECTORCALL (CYTHON_FAST_PYCCALL && PY_VERSION_HEX >= 0x030800B1) #endif /* Whether to use METH_FASTCALL with a fake backported implementation of vectorcall */ #define CYTHON_BACKPORT_VECTORCALL (CYTHON_METH_FASTCALL && PY_VERSION_HEX < 0x030800B1) #if CYTHON_USE_PYLONG_INTERNALS #if PY_MAJOR_VERSION < 3 #include "longintrepr.h" #endif /* These short defines can easily conflict with other code */ #undef SHIFT #undef BASE #undef MASK /* Compile-time sanity check that these are indeed equal. Github issue #2670. */ #ifdef SIZEOF_VOID_P enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; #endif #endif #ifndef __has_attribute #define __has_attribute(x) 0 #endif #ifndef __has_cpp_attribute #define __has_cpp_attribute(x) 0 #endif // restrict #ifndef CYTHON_RESTRICT #if defined(__GNUC__) #define CYTHON_RESTRICT __restrict__ #elif defined(_MSC_VER) && _MSC_VER >= 1400 #define CYTHON_RESTRICT __restrict #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define CYTHON_RESTRICT restrict #else #define CYTHON_RESTRICT #endif #endif // unused attribute #ifndef CYTHON_UNUSED #if defined(__cplusplus) /* for clang __has_cpp_attribute(maybe_unused) is true even before C++17 * but leads to warnings with -pedantic, since it is a C++17 feature */ #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) #if __has_cpp_attribute(maybe_unused) #define CYTHON_UNUSED [[maybe_unused]] #endif #endif #endif #endif #ifndef CYTHON_UNUSED # if defined(__GNUC__) # if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) # define CYTHON_UNUSED __attribute__ ((__unused__)) # else # define CYTHON_UNUSED # endif # elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) # define CYTHON_UNUSED __attribute__ ((__unused__)) # else # define CYTHON_UNUSED # endif #endif #ifndef CYTHON_UNUSED_VAR # if defined(__cplusplus) template void CYTHON_UNUSED_VAR( const T& ) { } # else # define CYTHON_UNUSED_VAR(x) (void)(x) # endif #endif #ifndef CYTHON_MAYBE_UNUSED_VAR #define CYTHON_MAYBE_UNUSED_VAR(x) CYTHON_UNUSED_VAR(x) #endif #ifndef CYTHON_NCP_UNUSED # if CYTHON_COMPILING_IN_CPYTHON # define CYTHON_NCP_UNUSED # else # define CYTHON_NCP_UNUSED CYTHON_UNUSED # endif #endif #ifndef CYTHON_USE_CPP_STD_MOVE // msvc doesn't set __cplusplus to a useful value #if defined(__cplusplus) && ( \ __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)) #define CYTHON_USE_CPP_STD_MOVE 1 #else #define CYTHON_USE_CPP_STD_MOVE 0 #endif #endif #define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) #ifdef _MSC_VER #ifndef _MSC_STDINT_H_ #if _MSC_VER < 1300 typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; #else typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; #endif #endif #if _MSC_VER < 1300 #ifdef _WIN64 typedef unsigned long long __pyx_uintptr_t; #else typedef unsigned int __pyx_uintptr_t; #endif #else #ifdef _WIN64 typedef unsigned __int64 __pyx_uintptr_t; #else typedef unsigned __int32 __pyx_uintptr_t; #endif #endif #else #include typedef uintptr_t __pyx_uintptr_t; #endif #ifndef CYTHON_FALLTHROUGH #if defined(__cplusplus) /* for clang __has_cpp_attribute(fallthrough) is true even before C++17 * but leads to warnings with -pedantic, since it is a C++17 feature */ #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) #if __has_cpp_attribute(fallthrough) #define CYTHON_FALLTHROUGH [[fallthrough]] #endif #endif #ifndef CYTHON_FALLTHROUGH #if __has_cpp_attribute(clang::fallthrough) #define CYTHON_FALLTHROUGH [[clang::fallthrough]] #elif __has_cpp_attribute(gnu::fallthrough) #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] #endif #endif #endif #ifndef CYTHON_FALLTHROUGH #if __has_attribute(fallthrough) #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) #else #define CYTHON_FALLTHROUGH #endif #endif #if defined(__clang__) && defined(__apple_build_version__) #if __apple_build_version__ < 7000000 /* Xcode < 7.0 */ #undef CYTHON_FALLTHROUGH #define CYTHON_FALLTHROUGH #endif #endif #endif #ifdef __cplusplus template struct __PYX_IS_UNSIGNED_IMPL {static const bool value = T(0) < T(-1);}; #define __PYX_IS_UNSIGNED(type) (__PYX_IS_UNSIGNED_IMPL::value) #else #define __PYX_IS_UNSIGNED(type) (((type)-1) > 0) #endif #if CYTHON_COMPILING_IN_PYPY == 1 #define __PYX_NEED_TP_PRINT_SLOT (PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x030A0000) #else #define __PYX_NEED_TP_PRINT_SLOT (PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000) #endif // reinterpret // TODO: refactor existing code to use those macros #define __PYX_REINTERPRET_FUNCION(func_pointer, other_pointer) ((func_pointer)(void(*)(void))(other_pointer)) // #define __PYX_REINTERPRET_POINTER(pointer_type, pointer) ((pointer_type)(void *)(pointer)) // #define __PYX_RUNTIME_REINTERPRET(type, var) (*(type *)(&var)) /////////////// CInitCode /////////////// // inline attribute #ifndef CYTHON_INLINE #if defined(__clang__) #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) #elif defined(__GNUC__) #define CYTHON_INLINE __inline__ #elif defined(_MSC_VER) #define CYTHON_INLINE __inline #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define CYTHON_INLINE inline #else #define CYTHON_INLINE #endif #endif /////////////// CppInitCode /////////////// #ifndef __cplusplus #error "Cython files generated with the C++ option must be compiled with a C++ compiler." #endif // inline attribute #ifndef CYTHON_INLINE #if defined(__clang__) #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) #else #define CYTHON_INLINE inline #endif #endif // Work around clang bug https://stackoverflow.com/questions/21847816/c-invoke-nested-template-class-destructor template void __Pyx_call_destructor(T& x) { x.~T(); } // Used for temporary variables of "reference" type. template class __Pyx_FakeReference { public: __Pyx_FakeReference() : ptr(NULL) { } // __Pyx_FakeReference(T& ref) : ptr(&ref) { } // Const version needed as Cython doesn't know about const overloads (e.g. for stl containers). __Pyx_FakeReference(const T& ref) : ptr(const_cast(&ref)) { } T *operator->() { return ptr; } T *operator&() { return ptr; } operator T&() { return *ptr; } // TODO(robertwb): Delegate all operators (or auto-generate unwrapping code where needed). template bool operator ==(const U& other) const { return *ptr == other; } template bool operator !=(const U& other) const { return *ptr != other; } template bool operator==(const __Pyx_FakeReference& other) const { return *ptr == *other.ptr; } template bool operator!=(const __Pyx_FakeReference& other) const { return *ptr != *other.ptr; } private: T *ptr; }; /////////////// PythonCompatibility /////////////// #define __PYX_BUILD_PY_SSIZE_T "n" #define CYTHON_FORMAT_SSIZE_T "z" #if PY_MAJOR_VERSION < 3 #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" #define __Pyx_DefaultClassType PyClass_Type #define __Pyx_PyCode_New(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \ PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) #else #define __Pyx_BUILTIN_MODULE_NAME "builtins" #define __Pyx_DefaultClassType PyType_Type #if CYTHON_COMPILING_IN_LIMITED_API // Note that the limited API doesn't know about PyCodeObject, so the type of this // is PyObject (unlike for the main API) static CYTHON_INLINE PyObject* __Pyx_PyCode_New(int a, int p, int k, int l, int s, int f, PyObject *code, PyObject *c, PyObject* n, PyObject *v, PyObject *fv, PyObject *cell, PyObject* fn, PyObject *name, int fline, PyObject *lnos) { // Backout option for generating a code object. // PyCode_NewEmpty isn't in the limited API. Therefore the two options are // 1. Python call of the code type with a long list of positional args. // 2. Generate a code object by compiling some trivial code, and customize. // We use the second because it's less sensitive to changes in the code type // constructor with version. PyObject *exception_table = NULL; PyObject *types_module=NULL, *code_type=NULL, *result=NULL; #if __PYX_LIMITED_VERSION_HEX < 0x030B0000 PyObject *version_info; /* borrowed */ PyObject *py_minor_version = NULL; #endif long minor_version = 0; PyObject *type, *value, *traceback; // we must be able to call this while an exception is happening - thus clear then restore the state PyErr_Fetch(&type, &value, &traceback); #if __PYX_LIMITED_VERSION_HEX >= 0x030B0000 minor_version = 11; // we don't yet need to distinguish between versions > 11 // Note that from 3.13, when we do, we can use Py_Version #else if (!(version_info = PySys_GetObject("version_info"))) goto end; if (!(py_minor_version = PySequence_GetItem(version_info, 1))) goto end; minor_version = PyLong_AsLong(py_minor_version); Py_DECREF(py_minor_version); if (minor_version == -1 && PyErr_Occurred()) goto end; #endif if (!(types_module = PyImport_ImportModule("types"))) goto end; if (!(code_type = PyObject_GetAttrString(types_module, "CodeType"))) goto end; if (minor_version <= 7) { // 3.7: // code(argcount, kwonlyargcount, nlocals, stacksize, flags, codestring, // constants, names, varnames, filename, name, firstlineno, // lnotab[, freevars[, cellvars]]) (void)p; result = PyObject_CallFunction(code_type, "iiiiiOOOOOOiOO", a, k, l, s, f, code, c, n, v, fn, name, fline, lnos, fv, cell); } else if (minor_version <= 10) { // 3.8, 3.9, 3.10 // code(argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize, // flags, codestring, constants, names, varnames, filename, name, // firstlineno, lnotab[, freevars[, cellvars]]) // 3.10 switches lnotab for linetable, but is otherwise the same result = PyObject_CallFunction(code_type, "iiiiiiOOOOOOiOO", a,p, k, l, s, f, code, c, n, v, fn, name, fline, lnos, fv, cell); } else { // 3.11, 3.12 // code(argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize, // flags, codestring, constants, names, varnames, filename, name, // qualname, firstlineno, linetable, exceptiontable, freevars=(), cellvars=(), /) // We use name and qualname for simplicity if (!(exception_table = PyBytes_FromStringAndSize(NULL, 0))) goto end; result = PyObject_CallFunction(code_type, "iiiiiiOOOOOOOiOO", a,p, k, l, s, f, code, c, n, v, fn, name, name, fline, lnos, exception_table, fv, cell); } end: Py_XDECREF(code_type); Py_XDECREF(exception_table); Py_XDECREF(types_module); if (type) { PyErr_Restore(type, value, traceback); } return result; } // Cython uses these constants but they are not available in the limited API. // (it'd be nice if there was a more robust way of looking these up) #ifndef CO_OPTIMIZED #define CO_OPTIMIZED 0x0001 #endif #ifndef CO_NEWLOCALS #define CO_NEWLOCALS 0x0002 #endif #ifndef CO_VARARGS #define CO_VARARGS 0x0004 #endif #ifndef CO_VARKEYWORDS #define CO_VARKEYWORDS 0x0008 #endif #ifndef CO_ASYNC_GENERATOR #define CO_ASYNC_GENERATOR 0x0200 #endif #ifndef CO_GENERATOR #define CO_GENERATOR 0x0020 #endif #ifndef CO_COROUTINE #define CO_COROUTINE 0x0080 #endif #elif PY_VERSION_HEX >= 0x030B0000 static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int p, int k, int l, int s, int f, PyObject *code, PyObject *c, PyObject* n, PyObject *v, PyObject *fv, PyObject *cell, PyObject* fn, PyObject *name, int fline, PyObject *lnos) { // As earlier versions, but // 1. pass an empty bytes string as exception_table // 2. pass name as qualname (TODO this might implementing properly in future) PyCodeObject *result; PyObject *empty_bytes = PyBytes_FromStringAndSize("", 0); /* we don't have access to __pyx_empty_bytes here */ if (!empty_bytes) return NULL; result = #if PY_VERSION_HEX >= 0x030C0000 PyUnstable_Code_NewWithPosOnlyArgs #else PyCode_NewWithPosOnlyArgs #endif (a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, name, fline, lnos, empty_bytes); Py_DECREF(empty_bytes); return result; } #elif PY_VERSION_HEX >= 0x030800B2 && !CYTHON_COMPILING_IN_PYPY #define __Pyx_PyCode_New(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \ PyCode_NewWithPosOnlyArgs(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) #else #define __Pyx_PyCode_New(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \ PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) #endif #endif #if PY_VERSION_HEX >= 0x030900A4 || defined(Py_IS_TYPE) #define __Pyx_IS_TYPE(ob, type) Py_IS_TYPE(ob, type) #else #define __Pyx_IS_TYPE(ob, type) (((const PyObject*)ob)->ob_type == (type)) #endif #if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_Is) #define __Pyx_Py_Is(x, y) Py_Is(x, y) #else #define __Pyx_Py_Is(x, y) ((x) == (y)) #endif #if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_IsNone) #define __Pyx_Py_IsNone(ob) Py_IsNone(ob) #else #define __Pyx_Py_IsNone(ob) __Pyx_Py_Is((ob), Py_None) #endif #if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_IsTrue) #define __Pyx_Py_IsTrue(ob) Py_IsTrue(ob) #else #define __Pyx_Py_IsTrue(ob) __Pyx_Py_Is((ob), Py_True) #endif #if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_IsFalse) #define __Pyx_Py_IsFalse(ob) Py_IsFalse(ob) #else #define __Pyx_Py_IsFalse(ob) __Pyx_Py_Is((ob), Py_False) #endif #define __Pyx_NoneAsNull(obj) (__Pyx_Py_IsNone(obj) ? NULL : (obj)) #if PY_VERSION_HEX >= 0x030900F0 && !CYTHON_COMPILING_IN_PYPY #define __Pyx_PyObject_GC_IsFinalized(o) PyObject_GC_IsFinalized(o) #else #define __Pyx_PyObject_GC_IsFinalized(o) _PyGC_FINALIZED(o) #endif #ifndef CO_COROUTINE #define CO_COROUTINE 0x80 #endif #ifndef CO_ASYNC_GENERATOR #define CO_ASYNC_GENERATOR 0x200 #endif #ifndef Py_TPFLAGS_CHECKTYPES #define Py_TPFLAGS_CHECKTYPES 0 #endif #ifndef Py_TPFLAGS_HAVE_INDEX #define Py_TPFLAGS_HAVE_INDEX 0 #endif #ifndef Py_TPFLAGS_HAVE_NEWBUFFER #define Py_TPFLAGS_HAVE_NEWBUFFER 0 #endif #ifndef Py_TPFLAGS_HAVE_FINALIZE #define Py_TPFLAGS_HAVE_FINALIZE 0 #endif #ifndef Py_TPFLAGS_SEQUENCE #define Py_TPFLAGS_SEQUENCE 0 #endif #ifndef Py_TPFLAGS_MAPPING #define Py_TPFLAGS_MAPPING 0 #endif #ifndef METH_STACKLESS // already defined for Stackless Python (all versions) and C-Python >= 3.7 // value if defined: Stackless Python < 3.6: 0x80 else 0x100 #define METH_STACKLESS 0 #endif #if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) // new in CPython 3.6, but changed in 3.7 - see // positional-only parameters: // https://bugs.python.org/issue29464 // const args: // https://bugs.python.org/issue32240 #ifndef METH_FASTCALL #define METH_FASTCALL 0x80 #endif typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); // new in CPython 3.7, used to be old signature of _PyCFunctionFast() in 3.6 typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); #else #define __Pyx_PyCFunctionFast _PyCFunctionFast #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords #endif #if CYTHON_METH_FASTCALL #define __Pyx_METH_FASTCALL METH_FASTCALL #define __Pyx_PyCFunction_FastCall __Pyx_PyCFunctionFast #define __Pyx_PyCFunction_FastCallWithKeywords __Pyx_PyCFunctionFastWithKeywords #else #define __Pyx_METH_FASTCALL METH_VARARGS #define __Pyx_PyCFunction_FastCall PyCFunction #define __Pyx_PyCFunction_FastCallWithKeywords PyCFunctionWithKeywords #endif #if CYTHON_VECTORCALL #define __pyx_vectorcallfunc vectorcallfunc #define __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET PY_VECTORCALL_ARGUMENTS_OFFSET #define __Pyx_PyVectorcall_NARGS(n) PyVectorcall_NARGS((size_t)(n)) #elif CYTHON_BACKPORT_VECTORCALL typedef PyObject *(*__pyx_vectorcallfunc)(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames); #define __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET ((size_t)1 << (8 * sizeof(size_t) - 1)) #define __Pyx_PyVectorcall_NARGS(n) ((Py_ssize_t)(((size_t)(n)) & ~__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)) #else #define __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET 0 #define __Pyx_PyVectorcall_NARGS(n) ((Py_ssize_t)(n)) #endif // These PyCFunction related macros get redefined in CythonFunction.c. // We need our own copies because the inline functions in CPython have a type-check assert // that breaks with a CyFunction in debug mode. #if PY_MAJOR_VERSION >= 0x030900B1 #define __Pyx_PyCFunction_CheckExact(func) PyCFunction_CheckExact(func) #else #define __Pyx_PyCFunction_CheckExact(func) PyCFunction_Check(func) #endif #define __Pyx_CyOrPyCFunction_Check(func) PyCFunction_Check(func) #if CYTHON_COMPILING_IN_CPYTHON #define __Pyx_CyOrPyCFunction_GET_FUNCTION(func) (((PyCFunctionObject*)(func))->m_ml->ml_meth) #elif !CYTHON_COMPILING_IN_LIMITED_API // It's probably easier for non-CPythons to support PyCFunction_GET_FUNCTION() than the object struct layout. #define __Pyx_CyOrPyCFunction_GET_FUNCTION(func) PyCFunction_GET_FUNCTION(func) // Unused in CYTHON_COMPILING_IN_LIMITED_API. #endif #if CYTHON_COMPILING_IN_CPYTHON #define __Pyx_CyOrPyCFunction_GET_FLAGS(func) (((PyCFunctionObject*)(func))->m_ml->ml_flags) static CYTHON_INLINE PyObject* __Pyx_CyOrPyCFunction_GET_SELF(PyObject *func) { return (__Pyx_CyOrPyCFunction_GET_FLAGS(func) & METH_STATIC) ? NULL : ((PyCFunctionObject*)func)->m_self; } // Only used if CYTHON_COMPILING_IN_CPYTHON. #endif static CYTHON_INLINE int __Pyx__IsSameCFunction(PyObject *func, void *cfunc) { #if CYTHON_COMPILING_IN_LIMITED_API return PyCFunction_Check(func) && PyCFunction_GetFunction(func) == (PyCFunction) cfunc; #else return PyCFunction_Check(func) && PyCFunction_GET_FUNCTION(func) == (PyCFunction) cfunc; #endif } #define __Pyx_IsSameCFunction(func, cfunc) __Pyx__IsSameCFunction(func, cfunc) // PEP-573: PyCFunction holds reference to defining class (PyCMethodObject) #if __PYX_LIMITED_VERSION_HEX < 0x030900B1 #define __Pyx_PyType_FromModuleAndSpec(m, s, b) ((void)m, PyType_FromSpecWithBases(s, b)) typedef PyObject *(*__Pyx_PyCMethod)(PyObject *, PyTypeObject *, PyObject *const *, size_t, PyObject *); #else #define __Pyx_PyType_FromModuleAndSpec(m, s, b) PyType_FromModuleAndSpec(m, s, b) #define __Pyx_PyCMethod PyCMethod #endif #ifndef METH_METHOD #define METH_METHOD 0x200 #endif #if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) #define PyObject_Malloc(s) PyMem_Malloc(s) #define PyObject_Free(p) PyMem_Free(p) #define PyObject_Realloc(p) PyMem_Realloc(p) #endif #if CYTHON_COMPILING_IN_LIMITED_API #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) #define __Pyx_PyFrame_SetLineNumber(frame, lineno) #else #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) #endif #if CYTHON_COMPILING_IN_LIMITED_API #define __Pyx_PyThreadState_Current PyThreadState_Get() #elif !CYTHON_FAST_THREAD_STATE #define __Pyx_PyThreadState_Current PyThreadState_GET() #elif PY_VERSION_HEX >= 0x030d00A1 //#elif PY_VERSION_HEX >= 0x03050200 // Actually added in 3.5.2, but compiling against that does not guarantee that we get imported there. #define __Pyx_PyThreadState_Current PyThreadState_GetUnchecked() #elif PY_VERSION_HEX >= 0x03060000 //#elif PY_VERSION_HEX >= 0x03050200 // Actually added in 3.5.2, but compiling against that does not guarantee that we get imported there. #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() #elif PY_VERSION_HEX >= 0x03000000 #define __Pyx_PyThreadState_Current PyThreadState_GET() #else #define __Pyx_PyThreadState_Current _PyThreadState_Current #endif #if CYTHON_COMPILING_IN_LIMITED_API static CYTHON_INLINE void *__Pyx_PyModule_GetState(PyObject *op) { void *result; result = PyModule_GetState(op); if (!result) Py_FatalError("Couldn't find the module state"); return result; } #endif #define __Pyx_PyObject_GetSlot(obj, name, func_ctype) __Pyx_PyType_GetSlot(Py_TYPE(obj), name, func_ctype) #if CYTHON_COMPILING_IN_LIMITED_API #define __Pyx_PyType_GetSlot(type, name, func_ctype) ((func_ctype) PyType_GetSlot((type), Py_##name)) #else #define __Pyx_PyType_GetSlot(type, name, func_ctype) ((type)->name) #endif // TSS (Thread Specific Storage) API #if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) #include "pythread.h" #define Py_tss_NEEDS_INIT 0 typedef int Py_tss_t; static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { *key = PyThread_create_key(); return 0; /* PyThread_create_key reports success always */ } static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); *key = Py_tss_NEEDS_INIT; return key; } static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { PyObject_Free(key); } static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { return *key != Py_tss_NEEDS_INIT; } static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { PyThread_delete_key(*key); *key = Py_tss_NEEDS_INIT; } static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { return PyThread_set_key_value(*key, value); } static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { return PyThread_get_key_value(*key); } // PyThread_delete_key_value(key) is equivalent to PyThread_set_key_value(key, NULL) // PyThread_ReInitTLS() is a no-op #endif /* TSS (Thread Specific Storage) API */ #if PY_MAJOR_VERSION < 3 #if CYTHON_COMPILING_IN_PYPY #if PYPY_VERSION_NUM < 0x07030600 #if defined(__cplusplus) && __cplusplus >= 201402L [[deprecated("`with nogil:` inside a nogil function will not release the GIL in PyPy2 < 7.3.6")]] #elif defined(__GNUC__) || defined(__clang__) __attribute__ ((__deprecated__("`with nogil:` inside a nogil function will not release the GIL in PyPy2 < 7.3.6"))) #elif defined(_MSC_VER) __declspec(deprecated("`with nogil:` inside a nogil function will not release the GIL in PyPy2 < 7.3.6")) #endif static CYTHON_INLINE int PyGILState_Check(void) { // PyGILState_Check is used to decide whether to release the GIL when we don't // know that we have it. For PyPy2 it isn't possible to check. // Therefore assume that we don't have the GIL (which causes us not to release it, // but is "safe") return 0; } #else // PYPY_VERSION_NUM < 0x07030600 // PyPy2 >= 7.3.6 has PyGILState_Check #endif // PYPY_VERSION_NUM < 0x07030600 #else // https://stackoverflow.com/a/25666624 static CYTHON_INLINE int PyGILState_Check(void) { PyThreadState * tstate = _PyThreadState_Current; return tstate && (tstate == PyGILState_GetThisThreadState()); } #endif #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030d0000 || defined(_PyDict_NewPresized) #define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) #else #define __Pyx_PyDict_NewPresized(n) PyDict_New() #endif #if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) #else #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX > 0x030600B4 && PY_VERSION_HEX < 0x030d0000 && CYTHON_USE_UNICODE_INTERNALS // _PyDict_GetItem_KnownHash() existed from CPython 3.5 to 3.12, but it was // dropping exceptions in 3.5. Since 3.6, exceptions are kept. #define __Pyx_PyDict_GetItemStrWithError(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStr(PyObject *dict, PyObject *name) { PyObject *res = __Pyx_PyDict_GetItemStrWithError(dict, name); if (res == NULL) PyErr_Clear(); return res; } #elif PY_MAJOR_VERSION >= 3 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07020000) #define __Pyx_PyDict_GetItemStrWithError PyDict_GetItemWithError #define __Pyx_PyDict_GetItemStr PyDict_GetItem #else static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStrWithError(PyObject *dict, PyObject *name) { // This is tricky - we should return a borrowed reference but not swallow non-KeyError exceptions. 8-| // But: this function is only used in Py2 and older PyPys, // and currently only for argument parsing and other non-correctness-critical lookups // and we know that 'name' is an interned 'str' with pre-calculated hash value (only comparisons can fail), // thus, performance matters more than correctness here, especially in the "not found" case. #if CYTHON_COMPILING_IN_PYPY // So we ignore any exceptions in old PyPys ... return PyDict_GetItem(dict, name); #else // and hack together a stripped-down and modified PyDict_GetItem() in CPython 2. PyDictEntry *ep; PyDictObject *mp = (PyDictObject*) dict; long hash = ((PyStringObject *) name)->ob_shash; assert(hash != -1); /* hash values of interned strings are always initialised */ ep = (mp->ma_lookup)(mp, name, hash); if (ep == NULL) { // error occurred return NULL; } // found or not found return ep->me_value; #endif } #define __Pyx_PyDict_GetItemStr PyDict_GetItem #endif /* Type slots */ #if CYTHON_USE_TYPE_SLOTS #define __Pyx_PyType_GetFlags(tp) (((PyTypeObject *)tp)->tp_flags) #define __Pyx_PyType_HasFeature(type, feature) ((__Pyx_PyType_GetFlags(type) & (feature)) != 0) #define __Pyx_PyObject_GetIterNextFunc(obj) (Py_TYPE(obj)->tp_iternext) #else #define __Pyx_PyType_GetFlags(tp) (PyType_GetFlags((PyTypeObject *)tp)) #define __Pyx_PyType_HasFeature(type, feature) PyType_HasFeature(type, feature) #define __Pyx_PyObject_GetIterNextFunc(obj) PyIter_Next #endif #if CYTHON_COMPILING_IN_LIMITED_API // Using PyObject_GenericSetAttr to bypass types immutability protection feels // a little hacky, but it does work in the limited API . // (It doesn't work on PyPy but that probably isn't a bug.) #define __Pyx_SetItemOnTypeDict(tp, k, v) PyObject_GenericSetAttr((PyObject*)tp, k, v) #else #define __Pyx_SetItemOnTypeDict(tp, k, v) PyDict_SetItem(tp->tp_dict, k, v) #endif #if CYTHON_USE_TYPE_SPECS && PY_VERSION_HEX >= 0x03080000 // In Py3.8+, instances of heap types need to decref their type on deallocation. // https://bugs.python.org/issue35810 #define __Pyx_PyHeapTypeObject_GC_Del(obj) { \ PyTypeObject *type = Py_TYPE((PyObject*)obj); \ assert(__Pyx_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)); \ PyObject_GC_Del(obj); \ Py_DECREF(type); \ } #else #define __Pyx_PyHeapTypeObject_GC_Del(obj) PyObject_GC_Del(obj) #endif #if CYTHON_COMPILING_IN_LIMITED_API #define CYTHON_PEP393_ENABLED 1 #define __Pyx_PyUnicode_READY(op) (0) #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GetLength(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_ReadChar(u, i) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((void)u, 1114111U) #define __Pyx_PyUnicode_KIND(u) ((void)u, (0)) // __Pyx_PyUnicode_DATA() and __Pyx_PyUnicode_READ() must go together, e.g. for iteration. #define __Pyx_PyUnicode_DATA(u) ((void*)u) #define __Pyx_PyUnicode_READ(k, d, i) ((void)k, PyUnicode_ReadChar((PyObject*)(d), i)) //#define __Pyx_PyUnicode_WRITE(k, d, i, ch) /* not available */ #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GetLength(u)) #elif PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) /* new Py3.3 unicode type (PEP 393) */ #define CYTHON_PEP393_ENABLED 1 #if PY_VERSION_HEX >= 0x030C0000 // Py3.12 / PEP-623 removed wstr type unicode strings and all of the PyUnicode_READY() machinery. #define __Pyx_PyUnicode_READY(op) (0) #else #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ? \ 0 : _PyUnicode_Ready((PyObject *)(op))) #endif #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) #define __Pyx_PyUnicode_KIND(u) ((int)PyUnicode_KIND(u)) #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, (Py_UCS4) ch) #if PY_VERSION_HEX >= 0x030C0000 #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) #else #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000 // Avoid calling deprecated C-API functions in Py3.9+ that PEP-623 schedules for removal in Py3.12. // https://www.python.org/dev/peps/pep-0623/ #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length)) #else #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) #endif #endif #else #define CYTHON_PEP393_ENABLED 0 #define PyUnicode_1BYTE_KIND 1 #define PyUnicode_2BYTE_KIND 2 #define PyUnicode_4BYTE_KIND 4 #define __Pyx_PyUnicode_READY(op) (0) #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535U : 1114111U) #define __Pyx_PyUnicode_KIND(u) ((int)sizeof(Py_UNICODE)) #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) // (void)(k) => avoid unused variable warning due to macro: #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = (Py_UNICODE) ch) #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) #endif #if CYTHON_COMPILING_IN_PYPY #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) #else #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ? \ PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) #endif #if CYTHON_COMPILING_IN_PYPY #if !defined(PyUnicode_DecodeUnicodeEscape) #define PyUnicode_DecodeUnicodeEscape(s, size, errors) PyUnicode_Decode(s, size, "unicode_escape", errors) #endif #if !defined(PyUnicode_Contains) || (PY_MAJOR_VERSION == 2 && PYPY_VERSION_NUM < 0x07030500) #undef PyUnicode_Contains #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) #endif #if !defined(PyByteArray_Check) #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) #endif #if !defined(PyObject_Format) #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) #endif #endif // ("..." % x) must call PyNumber_Remainder() if x is a string subclass that implements "__rmod__()". #define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) #define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) #else #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) #endif #if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) #define PyObject_ASCII(o) PyObject_Repr(o) #endif #if PY_MAJOR_VERSION >= 3 #define PyBaseString_Type PyUnicode_Type #define PyStringObject PyUnicodeObject #define PyString_Type PyUnicode_Type #define PyString_Check PyUnicode_Check #define PyString_CheckExact PyUnicode_CheckExact // PyPy3 used to define "PyObject_Unicode" #ifndef PyObject_Unicode #define PyObject_Unicode PyObject_Str #endif #endif #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) #else #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) #endif #if CYTHON_COMPILING_IN_CPYTHON #define __Pyx_PySequence_ListKeepNew(obj) \ (likely(PyList_CheckExact(obj) && Py_REFCNT(obj) == 1) ? __Pyx_NewRef(obj) : PySequence_List(obj)) #else #define __Pyx_PySequence_ListKeepNew(obj) PySequence_List(obj) #endif #ifndef PySet_CheckExact #define PySet_CheckExact(obj) __Pyx_IS_TYPE(obj, &PySet_Type) #endif #if PY_VERSION_HEX >= 0x030900A4 #define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt) #define __Pyx_SET_SIZE(obj, size) Py_SET_SIZE(obj, size) #else #define __Pyx_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt) #define __Pyx_SET_SIZE(obj, size) Py_SIZE(obj) = (size) #endif #if CYTHON_ASSUME_SAFE_MACROS #define __Pyx_PySequence_ITEM(o, i) PySequence_ITEM(o, i) #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) #define __Pyx_PyTuple_SET_ITEM(o, i, v) (PyTuple_SET_ITEM(o, i, v), (0)) #define __Pyx_PyList_SET_ITEM(o, i, v) (PyList_SET_ITEM(o, i, v), (0)) #define __Pyx_PyTuple_GET_SIZE(o) PyTuple_GET_SIZE(o) #define __Pyx_PyList_GET_SIZE(o) PyList_GET_SIZE(o) #define __Pyx_PySet_GET_SIZE(o) PySet_GET_SIZE(o) #define __Pyx_PyBytes_GET_SIZE(o) PyBytes_GET_SIZE(o) #define __Pyx_PyByteArray_GET_SIZE(o) PyByteArray_GET_SIZE(o) #else #define __Pyx_PySequence_ITEM(o, i) PySequence_GetItem(o, i) // NOTE: might fail with exception => check for -1 #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) // Note that this doesn't leak a reference to whatever's at o[i] #define __Pyx_PyTuple_SET_ITEM(o, i, v) PyTuple_SetItem(o, i, v) #define __Pyx_PyList_SET_ITEM(o, i, v) PyList_SetItem(o, i, v) #define __Pyx_PyTuple_GET_SIZE(o) PyTuple_Size(o) #define __Pyx_PyList_GET_SIZE(o) PyList_Size(o) #define __Pyx_PySet_GET_SIZE(o) PySet_Size(o) #define __Pyx_PyBytes_GET_SIZE(o) PyBytes_Size(o) #define __Pyx_PyByteArray_GET_SIZE(o) PyByteArray_Size(o) #endif #if PY_VERSION_HEX >= 0x030d00A1 #define __Pyx_PyImport_AddModuleRef(name) PyImport_AddModuleRef(name) #else static CYTHON_INLINE PyObject *__Pyx_PyImport_AddModuleRef(const char *name) { PyObject *module = PyImport_AddModule(name); Py_XINCREF(module); return module; } #endif #if PY_MAJOR_VERSION >= 3 #define PyIntObject PyLongObject #define PyInt_Type PyLong_Type #define PyInt_Check(op) PyLong_Check(op) #define PyInt_CheckExact(op) PyLong_CheckExact(op) #define __Pyx_Py3Int_Check(op) PyLong_Check(op) #define __Pyx_Py3Int_CheckExact(op) PyLong_CheckExact(op) #define PyInt_FromString PyLong_FromString #define PyInt_FromUnicode PyLong_FromUnicode #define PyInt_FromLong PyLong_FromLong #define PyInt_FromSize_t PyLong_FromSize_t #define PyInt_FromSsize_t PyLong_FromSsize_t #define PyInt_AsLong PyLong_AsLong #define PyInt_AS_LONG PyLong_AS_LONG #define PyInt_AsSsize_t PyLong_AsSsize_t #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask #define PyNumber_Int PyNumber_Long #else #define __Pyx_Py3Int_Check(op) (PyLong_Check(op) || PyInt_Check(op)) #define __Pyx_Py3Int_CheckExact(op) (PyLong_CheckExact(op) || PyInt_CheckExact(op)) #endif #if PY_MAJOR_VERSION >= 3 #define PyBoolObject PyLongObject #endif #if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY #ifndef PyUnicode_InternFromString #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) #endif #endif #if PY_VERSION_HEX < 0x030200A4 typedef long Py_hash_t; #define __Pyx_PyInt_FromHash_t PyInt_FromLong #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsHash_t #else #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsSsize_t #endif // backport of PyAsyncMethods from Py3.5 to older Py3.x versions // (mis-)using the "tp_reserved" type slot which is re-activated as "tp_as_async" in Py3.5 #if CYTHON_USE_ASYNC_SLOTS #if PY_VERSION_HEX >= 0x030500B1 #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) #else #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) #endif #else #define __Pyx_PyType_AsAsync(obj) NULL #endif #ifndef __Pyx_PyAsyncMethodsStruct typedef struct { unaryfunc am_await; unaryfunc am_aiter; unaryfunc am_anext; } __Pyx_PyAsyncMethodsStruct; #endif /////////////// IncludeStructmemberH.proto /////////////// #include /////////////// SmallCodeConfig.proto /////////////// #ifndef CYTHON_SMALL_CODE #if defined(__clang__) #define CYTHON_SMALL_CODE #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) #define CYTHON_SMALL_CODE __attribute__((cold)) #else #define CYTHON_SMALL_CODE #endif #endif /////////////// PyModInitFuncType.proto /////////////// #ifndef CYTHON_NO_PYINIT_EXPORT #define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC #elif PY_MAJOR_VERSION < 3 // Py2: define this to void manually because PyMODINIT_FUNC adds __declspec(dllexport) to it's definition. #ifdef __cplusplus #define __Pyx_PyMODINIT_FUNC extern "C" void #else #define __Pyx_PyMODINIT_FUNC void #endif #else // Py3+: define this to PyObject * manually because PyMODINIT_FUNC adds __declspec(dllexport) to it's definition. #ifdef __cplusplus #define __Pyx_PyMODINIT_FUNC extern "C" PyObject * #else #define __Pyx_PyMODINIT_FUNC PyObject * #endif #endif /////////////// FastTypeChecks.proto /////////////// #if CYTHON_COMPILING_IN_CPYTHON #define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) #define __Pyx_TypeCheck2(obj, type1, type2) __Pyx_IsAnySubtype2(Py_TYPE(obj), (PyTypeObject *)type1, (PyTypeObject *)type2) static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b);/*proto*/ static CYTHON_INLINE int __Pyx_IsAnySubtype2(PyTypeObject *cls, PyTypeObject *a, PyTypeObject *b);/*proto*/ static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type);/*proto*/ static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2);/*proto*/ #else #define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) #define __Pyx_TypeCheck2(obj, type1, type2) (PyObject_TypeCheck(obj, (PyTypeObject *)type1) || PyObject_TypeCheck(obj, (PyTypeObject *)type2)) #define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) #define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) #endif #define __Pyx_PyErr_ExceptionMatches2(err1, err2) __Pyx_PyErr_GivenExceptionMatches2(__Pyx_PyErr_CurrentExceptionType(), err1, err2) #define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) /////////////// FastTypeChecks /////////////// //@requires: Exceptions.c::PyThreadStateGet //@requires: Exceptions.c::PyErrFetchRestore #if CYTHON_COMPILING_IN_CPYTHON static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { while (a) { a = __Pyx_PyType_GetSlot(a, tp_base, PyTypeObject*); if (a == b) return 1; } return b == &PyBaseObject_Type; } static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { PyObject *mro; if (a == b) return 1; mro = a->tp_mro; if (likely(mro)) { Py_ssize_t i, n; n = PyTuple_GET_SIZE(mro); for (i = 0; i < n; i++) { if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) return 1; } return 0; } // should only get here for incompletely initialised types, i.e. never under normal usage patterns return __Pyx_InBases(a, b); } static CYTHON_INLINE int __Pyx_IsAnySubtype2(PyTypeObject *cls, PyTypeObject *a, PyTypeObject *b) { PyObject *mro; if (cls == a || cls == b) return 1; mro = cls->tp_mro; if (likely(mro)) { Py_ssize_t i, n; n = PyTuple_GET_SIZE(mro); for (i = 0; i < n; i++) { PyObject *base = PyTuple_GET_ITEM(mro, i); if (base == (PyObject *)a || base == (PyObject *)b) return 1; } return 0; } // should only get here for incompletely initialised types, i.e. never under normal usage patterns return __Pyx_InBases(cls, a) || __Pyx_InBases(cls, b); } #if PY_MAJOR_VERSION == 2 static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { // PyObject_IsSubclass() can recurse and therefore is not safe PyObject *exception, *value, *tb; int res; __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ErrFetch(&exception, &value, &tb); res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; // This function must not fail, so print the error here (which also clears it) if (unlikely(res == -1)) { PyErr_WriteUnraisable(err); res = 0; } if (!res) { res = PyObject_IsSubclass(err, exc_type2); // This function must not fail, so print the error here (which also clears it) if (unlikely(res == -1)) { PyErr_WriteUnraisable(err); res = 0; } } __Pyx_ErrRestore(exception, value, tb); return res; } #else static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { if (exc_type1) { return __Pyx_IsAnySubtype2((PyTypeObject*)err, (PyTypeObject*)exc_type1, (PyTypeObject*)exc_type2); } else { return __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); } } #endif // so far, we only call PyErr_GivenExceptionMatches() with an exception type (not instance) as first argument // => optimise for that case static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { Py_ssize_t i, n; assert(PyExceptionClass_Check(exc_type)); n = PyTuple_GET_SIZE(tuple); #if PY_MAJOR_VERSION >= 3 // the tighter subtype checking in Py3 allows faster out-of-order comparison for (i=0; i pure safety check assertions. assert(PyExceptionClass_Check(exc_type1)); assert(PyExceptionClass_Check(exc_type2)); if (likely(err == exc_type1 || err == exc_type2)) return 1; if (likely(PyExceptionClass_Check(err))) { return __Pyx_inner_PyErr_GivenExceptionMatches2(err, exc_type1, exc_type2); } return (PyErr_GivenExceptionMatches(err, exc_type1) || PyErr_GivenExceptionMatches(err, exc_type2)); } #endif /////////////// MathInitCode /////////////// #if defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS) #if !defined(_USE_MATH_DEFINES) #define _USE_MATH_DEFINES #endif #endif #include #ifdef NAN #define __PYX_NAN() ((float) NAN) #else static CYTHON_INLINE float __PYX_NAN() { // Initialize NaN. The sign is irrelevant, an exponent with all bits 1 and // a nonzero mantissa means NaN. If the first bit in the mantissa is 1, it is // a quiet NaN. float value; memset(&value, 0xFF, sizeof(value)); return value; } #endif #if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) #define __Pyx_truncl trunc #else #define __Pyx_truncl truncl #endif /////////////// UtilityFunctionPredeclarations.proto /////////////// typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; /*proto*/ /////////////// ForceInitThreads.proto /////////////// //@proto_block: utility_code_proto_before_types #ifndef __PYX_FORCE_INIT_THREADS #define __PYX_FORCE_INIT_THREADS 0 #endif /////////////// InitThreads.init /////////////// #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x030700F0 PyEval_InitThreads(); #endif /////////////// ModuleCreationPEP489 /////////////// //@substitute: naming //#if CYTHON_PEP489_MULTI_PHASE_INIT static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { #if PY_VERSION_HEX >= 0x030700A1 static PY_INT64_T main_interpreter_id = -1; PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); if (main_interpreter_id == -1) { main_interpreter_id = current_id; return (unlikely(current_id == -1)) ? -1 : 0; } else if (unlikely(main_interpreter_id != current_id)) #else static PyInterpreterState *main_interpreter = NULL; PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; if (!main_interpreter) { main_interpreter = current_interpreter; } else if (unlikely(main_interpreter != current_interpreter)) #endif { PyErr_SetString( PyExc_ImportError, "Interpreter change detected - this module can only be loaded into one interpreter per process."); return -1; } return 0; } #if CYTHON_COMPILING_IN_LIMITED_API static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *module, const char* from_name, const char* to_name, int allow_none) #else static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) #endif { PyObject *value = PyObject_GetAttrString(spec, from_name); int result = 0; if (likely(value)) { if (allow_none || value != Py_None) { #if CYTHON_COMPILING_IN_LIMITED_API result = PyModule_AddObject(module, to_name, value); #else result = PyDict_SetItemString(moddict, to_name, value); #endif } Py_DECREF(value); } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { PyErr_Clear(); } else { result = -1; } return result; } static CYTHON_SMALL_CODE PyObject* ${pymodule_create_func_cname}(PyObject *spec, PyModuleDef *def) { PyObject *module = NULL, *moddict, *modname; CYTHON_UNUSED_VAR(def); // For now, we only have exactly one module instance. if (__Pyx_check_single_interpreter()) return NULL; if (${module_cname}) return __Pyx_NewRef(${module_cname}); modname = PyObject_GetAttrString(spec, "name"); if (unlikely(!modname)) goto bad; module = PyModule_NewObject(modname); Py_DECREF(modname); if (unlikely(!module)) goto bad; #if CYTHON_COMPILING_IN_LIMITED_API moddict = module; #else moddict = PyModule_GetDict(module); if (unlikely(!moddict)) goto bad; // moddict is a borrowed reference #endif if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; return module; bad: Py_XDECREF(module); return NULL; } //#endif /////////////// CodeObjectCache.proto /////////////// #if !CYTHON_COMPILING_IN_LIMITED_API typedef struct { PyCodeObject* code_object; int code_line; } __Pyx_CodeObjectCacheEntry; struct __Pyx_CodeObjectCache { int count; int max_count; __Pyx_CodeObjectCacheEntry* entries; }; static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); static PyCodeObject *__pyx_find_code_object(int code_line); static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); #endif /////////////// CodeObjectCache /////////////// // Note that errors are simply ignored in the code below. // This is just a cache, if a lookup or insertion fails - so what? #if !CYTHON_COMPILING_IN_LIMITED_API static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { int start = 0, mid = 0, end = count - 1; if (end >= 0 && code_line > entries[end].code_line) { return count; } while (start < end) { mid = start + (end - start) / 2; if (code_line < entries[mid].code_line) { end = mid; } else if (code_line > entries[mid].code_line) { start = mid + 1; } else { return mid; } } if (code_line <= entries[mid].code_line) { return mid; } else { return mid + 1; } } static PyCodeObject *__pyx_find_code_object(int code_line) { PyCodeObject* code_object; int pos; if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { return NULL; } pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { return NULL; } code_object = __pyx_code_cache.entries[pos].code_object; Py_INCREF(code_object); return code_object; } static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { int pos, i; __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; if (unlikely(!code_line)) { return; } if (unlikely(!entries)) { entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); if (likely(entries)) { __pyx_code_cache.entries = entries; __pyx_code_cache.max_count = 64; __pyx_code_cache.count = 1; entries[0].code_line = code_line; entries[0].code_object = code_object; Py_INCREF(code_object); } return; } pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { PyCodeObject* tmp = entries[pos].code_object; entries[pos].code_object = code_object; Py_DECREF(tmp); return; } if (__pyx_code_cache.count == __pyx_code_cache.max_count) { int new_max = __pyx_code_cache.max_count + 64; entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( __pyx_code_cache.entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry)); if (unlikely(!entries)) { return; } __pyx_code_cache.entries = entries; __pyx_code_cache.max_count = new_max; } for (i=__pyx_code_cache.count; i>pos; i--) { entries[i] = entries[i-1]; } entries[pos].code_line = code_line; entries[pos].code_object = code_object; __pyx_code_cache.count++; Py_INCREF(code_object); } #endif /////////////// CodeObjectCache.cleanup /////////////// #if !CYTHON_COMPILING_IN_LIMITED_API if (__pyx_code_cache.entries) { __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; int i, count = __pyx_code_cache.count; __pyx_code_cache.count = 0; __pyx_code_cache.max_count = 0; __pyx_code_cache.entries = NULL; for (i=0; i= 0x030B00A4 return Py_Version & ~0xFFUL; #else const char* rt_version = Py_GetVersion(); unsigned long version = 0; unsigned long factor = 0x01000000UL; unsigned int digit = 0; int i = 0; while (factor) { while ('0' <= rt_version[i] && rt_version[i] <= '9') { digit = digit * 10 + (unsigned int) (rt_version[i] - '0'); ++i; } version += factor * digit; if (rt_version[i] != '.') break; digit = 0; factor >>= 8; ++i; } return version; #endif } static int __Pyx_check_binary_version(unsigned long ct_version, unsigned long rt_version, int allow_newer) { // runtime version is: -1 => older, 0 => equal, 1 => newer const unsigned long MAJOR_MINOR = 0xFFFF0000UL; if ((rt_version & MAJOR_MINOR) == (ct_version & MAJOR_MINOR)) return 0; if (likely(allow_newer && (rt_version & MAJOR_MINOR) > (ct_version & MAJOR_MINOR))) return 1; { char message[200]; PyOS_snprintf(message, sizeof(message), "compile time Python version %d.%d " "of module '%.100s' " "%s " "runtime version %d.%d", (int) (ct_version >> 24), (int) ((ct_version >> 16) & 0xFF), __Pyx_MODULE_NAME, (allow_newer) ? "was newer than" : "does not match", (int) (rt_version >> 24), (int) ((rt_version >> 16) & 0xFF) ); // returns 0 or -1 return PyErr_WarnEx(NULL, message, 1); } } /////////////// IsLittleEndian.proto /////////////// static CYTHON_INLINE int __Pyx_Is_Little_Endian(void); /////////////// IsLittleEndian /////////////// static CYTHON_INLINE int __Pyx_Is_Little_Endian(void) { union { uint32_t u32; uint8_t u8[4]; } S; S.u32 = 0x01020304; return S.u8[0] == 4; } /////////////// Refnanny.proto /////////////// #ifndef CYTHON_REFNANNY #define CYTHON_REFNANNY 0 #endif #if CYTHON_REFNANNY typedef struct { void (*INCREF)(void*, PyObject*, Py_ssize_t); void (*DECREF)(void*, PyObject*, Py_ssize_t); void (*GOTREF)(void*, PyObject*, Py_ssize_t); void (*GIVEREF)(void*, PyObject*, Py_ssize_t); void* (*SetupContext)(const char*, Py_ssize_t, const char*); void (*FinishContext)(void**); } __Pyx_RefNannyAPIStruct; static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); /*proto*/ #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; #ifdef WITH_THREAD #define __Pyx_RefNannySetupContext(name, acquire_gil) \ if (acquire_gil) { \ PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); \ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), (__LINE__), (__FILE__)); \ PyGILState_Release(__pyx_gilstate_save); \ } else { \ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), (__LINE__), (__FILE__)); \ } #define __Pyx_RefNannyFinishContextNogil() { \ PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); \ __Pyx_RefNannyFinishContext(); \ PyGILState_Release(__pyx_gilstate_save); \ } #else #define __Pyx_RefNannySetupContext(name, acquire_gil) \ __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), (__LINE__), (__FILE__)) #define __Pyx_RefNannyFinishContextNogil() __Pyx_RefNannyFinishContext() #endif #define __Pyx_RefNannyFinishContextNogil() { \ PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); \ __Pyx_RefNannyFinishContext(); \ PyGILState_Release(__pyx_gilstate_save); \ } #define __Pyx_RefNannyFinishContext() \ __Pyx_RefNanny->FinishContext(&__pyx_refnanny) #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), (__LINE__)) #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), (__LINE__)) #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), (__LINE__)) #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), (__LINE__)) #define __Pyx_XINCREF(r) do { if((r) == NULL); else {__Pyx_INCREF(r); }} while(0) #define __Pyx_XDECREF(r) do { if((r) == NULL); else {__Pyx_DECREF(r); }} while(0) #define __Pyx_XGOTREF(r) do { if((r) == NULL); else {__Pyx_GOTREF(r); }} while(0) #define __Pyx_XGIVEREF(r) do { if((r) == NULL); else {__Pyx_GIVEREF(r);}} while(0) #else #define __Pyx_RefNannyDeclarations #define __Pyx_RefNannySetupContext(name, acquire_gil) #define __Pyx_RefNannyFinishContextNogil() #define __Pyx_RefNannyFinishContext() #define __Pyx_INCREF(r) Py_INCREF(r) #define __Pyx_DECREF(r) Py_DECREF(r) #define __Pyx_GOTREF(r) #define __Pyx_GIVEREF(r) #define __Pyx_XINCREF(r) Py_XINCREF(r) #define __Pyx_XDECREF(r) Py_XDECREF(r) #define __Pyx_XGOTREF(r) #define __Pyx_XGIVEREF(r) #endif /* CYTHON_REFNANNY */ #define __Pyx_Py_XDECREF_SET(r, v) do { \ PyObject *tmp = (PyObject *) r; \ r = v; Py_XDECREF(tmp); \ } while (0) #define __Pyx_XDECREF_SET(r, v) do { \ PyObject *tmp = (PyObject *) r; \ r = v; __Pyx_XDECREF(tmp); \ } while (0) #define __Pyx_DECREF_SET(r, v) do { \ PyObject *tmp = (PyObject *) r; \ r = v; __Pyx_DECREF(tmp); \ } while (0) #define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) #define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) /////////////// Refnanny /////////////// #if CYTHON_REFNANNY static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { PyObject *m = NULL, *p = NULL; void *r = NULL; m = PyImport_ImportModule(modname); if (!m) goto end; p = PyObject_GetAttrString(m, "RefNannyAPI"); if (!p) goto end; r = PyLong_AsVoidPtr(p); end: Py_XDECREF(p); Py_XDECREF(m); return (__Pyx_RefNannyAPIStruct *)r; } #endif /* CYTHON_REFNANNY */ /////////////// ImportRefnannyAPI /////////////// #if CYTHON_REFNANNY __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); if (!__Pyx_RefNanny) { PyErr_Clear(); __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); if (!__Pyx_RefNanny) Py_FatalError("failed to import 'refnanny' module"); } #endif /////////////// RegisterModuleCleanup.proto /////////////// //@substitute: naming static void ${cleanup_cname}(PyObject *self); /*proto*/ #if PY_MAJOR_VERSION < 3 || CYTHON_COMPILING_IN_PYPY static int __Pyx_RegisterCleanup(void); /*proto*/ #else #define __Pyx_RegisterCleanup() (0) #endif /////////////// RegisterModuleCleanup /////////////// //@substitute: naming #if PY_MAJOR_VERSION < 3 || CYTHON_COMPILING_IN_PYPY static PyObject* ${cleanup_cname}_atexit(PyObject *module, PyObject *unused) { CYTHON_UNUSED_VAR(unused); ${cleanup_cname}(module); Py_INCREF(Py_None); return Py_None; } static int __Pyx_RegisterCleanup(void) { // Don't use Py_AtExit because that has a 32-call limit and is called // after python finalization. // Also, we try to prepend the cleanup function to "atexit._exithandlers" // in Py2 because CPython runs them last-to-first. Being run last allows // user exit code to run before us that may depend on the globals // and cached objects that we are about to clean up. static PyMethodDef cleanup_def = { "__cleanup", (PyCFunction)${cleanup_cname}_atexit, METH_NOARGS, 0}; PyObject *cleanup_func = 0; PyObject *atexit = 0; PyObject *reg = 0; PyObject *args = 0; PyObject *res = 0; int ret = -1; cleanup_func = PyCFunction_New(&cleanup_def, 0); if (!cleanup_func) goto bad; atexit = PyImport_ImportModule("atexit"); if (!atexit) goto bad; reg = PyObject_GetAttrString(atexit, "_exithandlers"); if (reg && PyList_Check(reg)) { PyObject *a, *kw; a = PyTuple_New(0); kw = PyDict_New(); if (!a || !kw) { Py_XDECREF(a); Py_XDECREF(kw); goto bad; } args = PyTuple_Pack(3, cleanup_func, a, kw); Py_DECREF(a); Py_DECREF(kw); if (!args) goto bad; ret = PyList_Insert(reg, 0, args); } else { if (!reg) PyErr_Clear(); Py_XDECREF(reg); reg = PyObject_GetAttrString(atexit, "register"); if (!reg) goto bad; args = PyTuple_Pack(1, cleanup_func); if (!args) goto bad; res = PyObject_CallObject(reg, args); if (!res) goto bad; ret = 0; } bad: Py_XDECREF(cleanup_func); Py_XDECREF(atexit); Py_XDECREF(reg); Py_XDECREF(args); Py_XDECREF(res); return ret; } #endif /////////////// FastGil.init /////////////// #ifdef WITH_THREAD __Pyx_FastGilFuncInit(); #endif /////////////// NoFastGil.proto /////////////// //@proto_block: utility_code_proto_before_types #define __Pyx_PyGILState_Ensure PyGILState_Ensure #define __Pyx_PyGILState_Release PyGILState_Release #define __Pyx_FastGIL_Remember() #define __Pyx_FastGIL_Forget() #define __Pyx_FastGilFuncInit() /////////////// FastGil.proto /////////////// //@proto_block: utility_code_proto_before_types #if CYTHON_FAST_GIL struct __Pyx_FastGilVtab { PyGILState_STATE (*Fast_PyGILState_Ensure)(void); void (*Fast_PyGILState_Release)(PyGILState_STATE oldstate); void (*FastGIL_Remember)(void); void (*FastGIL_Forget)(void); }; static void __Pyx_FastGIL_Noop(void) {} static struct __Pyx_FastGilVtab __Pyx_FastGilFuncs = { PyGILState_Ensure, PyGILState_Release, __Pyx_FastGIL_Noop, __Pyx_FastGIL_Noop }; static void __Pyx_FastGilFuncInit(void); #define __Pyx_PyGILState_Ensure __Pyx_FastGilFuncs.Fast_PyGILState_Ensure #define __Pyx_PyGILState_Release __Pyx_FastGilFuncs.Fast_PyGILState_Release #define __Pyx_FastGIL_Remember __Pyx_FastGilFuncs.FastGIL_Remember #define __Pyx_FastGIL_Forget __Pyx_FastGilFuncs.FastGIL_Forget #ifdef WITH_THREAD #ifndef CYTHON_THREAD_LOCAL #if defined(__cplusplus) && __cplusplus >= 201103L #define CYTHON_THREAD_LOCAL thread_local #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112 #define CYTHON_THREAD_LOCAL _Thread_local #elif defined(__GNUC__) #define CYTHON_THREAD_LOCAL __thread #elif defined(_MSC_VER) #define CYTHON_THREAD_LOCAL __declspec(thread) #endif #endif #endif #else #define __Pyx_PyGILState_Ensure PyGILState_Ensure #define __Pyx_PyGILState_Release PyGILState_Release #define __Pyx_FastGIL_Remember() #define __Pyx_FastGIL_Forget() #define __Pyx_FastGilFuncInit() #endif /////////////// FastGil /////////////// // The implementations of PyGILState_Ensure/Release calls PyThread_get_key_value // several times which is turns out to be quite slow (slower in fact than // acquiring the GIL itself). Simply storing it in a thread local for the // common case is much faster. // To make optimal use of this thread local, we attempt to share it between // modules. #if CYTHON_FAST_GIL #define __Pyx_FastGIL_ABI_module __PYX_ABI_MODULE_NAME #define __Pyx_FastGIL_PyCapsuleName "FastGilFuncs" #define __Pyx_FastGIL_PyCapsule \ __Pyx_FastGIL_ABI_module "." __Pyx_FastGIL_PyCapsuleName #ifdef CYTHON_THREAD_LOCAL #include "pythread.h" #include "pystate.h" static CYTHON_THREAD_LOCAL PyThreadState *__Pyx_FastGil_tcur = NULL; static CYTHON_THREAD_LOCAL int __Pyx_FastGil_tcur_depth = 0; static int __Pyx_FastGil_autoTLSkey = -1; static CYTHON_INLINE void __Pyx_FastGIL_Remember0(void) { ++__Pyx_FastGil_tcur_depth; } static CYTHON_INLINE void __Pyx_FastGIL_Forget0(void) { if (--__Pyx_FastGil_tcur_depth == 0) { __Pyx_FastGil_tcur = NULL; } } static CYTHON_INLINE PyThreadState *__Pyx_FastGil_get_tcur(void) { PyThreadState *tcur = __Pyx_FastGil_tcur; if (tcur == NULL) { tcur = __Pyx_FastGil_tcur = (PyThreadState*)PyThread_get_key_value(__Pyx_FastGil_autoTLSkey); } return tcur; } static PyGILState_STATE __Pyx_FastGil_PyGILState_Ensure(void) { int current; PyThreadState *tcur; __Pyx_FastGIL_Remember0(); tcur = __Pyx_FastGil_get_tcur(); if (tcur == NULL) { // Uninitialized, need to initialize now. return PyGILState_Ensure(); } current = tcur == __Pyx_PyThreadState_Current; if (current == 0) { PyEval_RestoreThread(tcur); } ++tcur->gilstate_counter; return current ? PyGILState_LOCKED : PyGILState_UNLOCKED; } static void __Pyx_FastGil_PyGILState_Release(PyGILState_STATE oldstate) { PyThreadState *tcur = __Pyx_FastGil_get_tcur(); __Pyx_FastGIL_Forget0(); if (tcur->gilstate_counter == 1) { // This is the last lock, do all the cleanup as well. PyGILState_Release(oldstate); } else { --tcur->gilstate_counter; if (oldstate == PyGILState_UNLOCKED) { PyEval_SaveThread(); } } } static void __Pyx_FastGilFuncInit0(void) { /* Try to detect autoTLSkey. */ int key; void* this_thread_state = (void*) PyGILState_GetThisThreadState(); for (key = 0; key < 100; key++) { if (PyThread_get_key_value(key) == this_thread_state) { __Pyx_FastGil_autoTLSkey = key; break; } } if (__Pyx_FastGil_autoTLSkey != -1) { PyObject* capsule = NULL; PyObject* abi_module = NULL; __Pyx_PyGILState_Ensure = __Pyx_FastGil_PyGILState_Ensure; __Pyx_PyGILState_Release = __Pyx_FastGil_PyGILState_Release; __Pyx_FastGIL_Remember = __Pyx_FastGIL_Remember0; __Pyx_FastGIL_Forget = __Pyx_FastGIL_Forget0; capsule = PyCapsule_New(&__Pyx_FastGilFuncs, __Pyx_FastGIL_PyCapsule, NULL); if (capsule) { abi_module = __Pyx_PyImport_AddModuleRef(__Pyx_FastGIL_ABI_module); if (abi_module) { PyObject_SetAttrString(abi_module, __Pyx_FastGIL_PyCapsuleName, capsule); Py_DECREF(abi_module); } } Py_XDECREF(capsule); } } #else static void __Pyx_FastGilFuncInit0(void) { } #endif static void __Pyx_FastGilFuncInit(void) { struct __Pyx_FastGilVtab* shared = (struct __Pyx_FastGilVtab*)PyCapsule_Import(__Pyx_FastGIL_PyCapsule, 1); if (shared) { __Pyx_FastGilFuncs = *shared; } else { PyErr_Clear(); __Pyx_FastGilFuncInit0(); } } #endif ///////////////////// UtilityCodePragmas ///////////////////////// #ifdef _MSC_VER #pragma warning( push ) /* Warning 4127: conditional expression is constant * Cython uses constant conditional expressions to allow in inline functions to be optimized at * compile-time, so this warning is not useful */ #pragma warning( disable : 4127 ) #endif ///////////////////// UtilityCodePragmasEnd ////////////////////// #ifdef _MSC_VER #pragma warning( pop ) /* undo whatever Cython has done to warnings */ #endif ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/NumpyImportArray.c0000644000175100001770000000376100000000000022160 0ustar00runnerdocker00000000000000///////////////////////// NumpyImportArray.init //////////////////// // comment below is deliberately kept in the generated C file to // help users debug where this came from: /* * Cython has automatically inserted a call to _import_array since * you didn't include one when you cimported numpy. To disable this * add the line * numpy._import_array */ #ifdef NPY_FEATURE_VERSION /* This is a public define that makes us reasonably confident it's "real" Numpy */ // NO_IMPORT_ARRAY is Numpy's mechanism for indicating that import_array is handled elsewhere #ifndef NO_IMPORT_ARRAY /* https://numpy.org/doc/stable/reference/c-api/array.html#c.NO_IMPORT_ARRAY */ if (unlikely(_import_array() == -1)) { PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import " "(auto-generated because you didn't call 'numpy.import_array()' after cimporting numpy; " "use 'numpy._import_array' to disable if you are certain you don't need it)."); } #endif #endif ///////////////////////// NumpyImportUFunc.init //////////////////// // Unlike import_array, this is generated by the @cython.ufunc decorator // so we're confident the right headers are present and don't need to override them { // NO_IMPORT_UFUNC is Numpy's mechanism for indicating that import_umath is handled elsewhere #ifndef NO_IMPORT_UFUNC /* https://numpy.org/doc/stable/reference/c-api/ufunc.html#c.NO_IMPORT_UFUNC */ if (unlikely(_import_umath() == -1)) { PyErr_SetString(PyExc_ImportError, "numpy.core.umath failed to import " "(auto-generated by @cython.ufunc)."); } #else if ((0)) {} #endif // NO_IMPORT_ARRAY is Numpy's mechanism for indicating that import_array is handled elsewhere #ifndef NO_IMPORT_ARRAY /* https://numpy.org/doc/stable/reference/c-api/array.html#c.NO_IMPORT_ARRAY */ else if (unlikely(_import_array() == -1)) { PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import " "(auto-generated by @cython.ufunc)."); } #endif } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/ObjectHandling.c0000644000175100001770000034351400000000000021534 0ustar00runnerdocker00000000000000/* * General object operations and protocol implementations, * including their specialisations for certain builtins. * * Optional optimisations for builtins are in Optimize.c. * * Required replacements of builtins are in Builtins.c. */ /////////////// RaiseNoneIterError.proto /////////////// static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void); /////////////// RaiseNoneIterError /////////////// static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) { PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); } /////////////// RaiseTooManyValuesToUnpack.proto /////////////// static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected); /////////////// RaiseTooManyValuesToUnpack /////////////// static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) { PyErr_Format(PyExc_ValueError, "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected); } /////////////// RaiseNeedMoreValuesToUnpack.proto /////////////// static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); /////////////// RaiseNeedMoreValuesToUnpack /////////////// static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { PyErr_Format(PyExc_ValueError, "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack", index, (index == 1) ? "" : "s"); } /////////////// UnpackTupleError.proto /////////////// static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/ /////////////// UnpackTupleError /////////////// //@requires: RaiseNoneIterError //@requires: RaiseNeedMoreValuesToUnpack //@requires: RaiseTooManyValuesToUnpack static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) { if (t == Py_None) { __Pyx_RaiseNoneNotIterableError(); } else if (PyTuple_GET_SIZE(t) < index) { __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t)); } else { __Pyx_RaiseTooManyValuesError(index); } } /////////////// UnpackItemEndCheck.proto /////////////// static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected); /*proto*/ /////////////// UnpackItemEndCheck /////////////// //@requires: RaiseTooManyValuesToUnpack //@requires: IterFinish static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected) { if (unlikely(retval)) { Py_DECREF(retval); __Pyx_RaiseTooManyValuesError(expected); return -1; } return __Pyx_IterFinish(); } /////////////// UnpackTuple2.proto /////////////// #define __Pyx_unpack_tuple2(tuple, value1, value2, is_tuple, has_known_size, decref_tuple) \ (likely(is_tuple || PyTuple_Check(tuple)) ? \ (likely(has_known_size || PyTuple_GET_SIZE(tuple) == 2) ? \ __Pyx_unpack_tuple2_exact(tuple, value1, value2, decref_tuple) : \ (__Pyx_UnpackTupleError(tuple, 2), -1)) : \ __Pyx_unpack_tuple2_generic(tuple, value1, value2, has_known_size, decref_tuple)) static CYTHON_INLINE int __Pyx_unpack_tuple2_exact( PyObject* tuple, PyObject** value1, PyObject** value2, int decref_tuple); static int __Pyx_unpack_tuple2_generic( PyObject* tuple, PyObject** value1, PyObject** value2, int has_known_size, int decref_tuple); /////////////// UnpackTuple2 /////////////// //@requires: UnpackItemEndCheck //@requires: UnpackTupleError //@requires: RaiseNeedMoreValuesToUnpack static CYTHON_INLINE int __Pyx_unpack_tuple2_exact( PyObject* tuple, PyObject** pvalue1, PyObject** pvalue2, int decref_tuple) { PyObject *value1 = NULL, *value2 = NULL; #if CYTHON_COMPILING_IN_PYPY value1 = PySequence_ITEM(tuple, 0); if (unlikely(!value1)) goto bad; value2 = PySequence_ITEM(tuple, 1); if (unlikely(!value2)) goto bad; #else value1 = PyTuple_GET_ITEM(tuple, 0); Py_INCREF(value1); value2 = PyTuple_GET_ITEM(tuple, 1); Py_INCREF(value2); #endif if (decref_tuple) { Py_DECREF(tuple); } *pvalue1 = value1; *pvalue2 = value2; return 0; #if CYTHON_COMPILING_IN_PYPY bad: Py_XDECREF(value1); Py_XDECREF(value2); if (decref_tuple) { Py_XDECREF(tuple); } return -1; #endif } static int __Pyx_unpack_tuple2_generic(PyObject* tuple, PyObject** pvalue1, PyObject** pvalue2, int has_known_size, int decref_tuple) { Py_ssize_t index; PyObject *value1 = NULL, *value2 = NULL, *iter = NULL; iternextfunc iternext; iter = PyObject_GetIter(tuple); if (unlikely(!iter)) goto bad; if (decref_tuple) { Py_DECREF(tuple); tuple = NULL; } iternext = __Pyx_PyObject_GetIterNextFunc(iter); value1 = iternext(iter); if (unlikely(!value1)) { index = 0; goto unpacking_failed; } value2 = iternext(iter); if (unlikely(!value2)) { index = 1; goto unpacking_failed; } if (!has_known_size && unlikely(__Pyx_IternextUnpackEndCheck(iternext(iter), 2))) goto bad; Py_DECREF(iter); *pvalue1 = value1; *pvalue2 = value2; return 0; unpacking_failed: if (!has_known_size && __Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); bad: Py_XDECREF(iter); Py_XDECREF(value1); Py_XDECREF(value2); if (decref_tuple) { Py_XDECREF(tuple); } return -1; } /////////////// IterNext.proto /////////////// #define __Pyx_PyIter_Next(obj) __Pyx_PyIter_Next2(obj, NULL) static CYTHON_INLINE PyObject *__Pyx_PyIter_Next2(PyObject *, PyObject *); /*proto*/ /////////////// IterNext /////////////// //@requires: Exceptions.c::PyThreadStateGet //@requires: Exceptions.c::PyErrFetchRestore static PyObject *__Pyx_PyIter_Next2Default(PyObject* defval) { PyObject* exc_type; __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign exc_type = __Pyx_PyErr_CurrentExceptionType(); if (unlikely(exc_type)) { if (!defval || unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) return NULL; __Pyx_PyErr_Clear(); Py_INCREF(defval); return defval; } if (defval) { Py_INCREF(defval); return defval; } __Pyx_PyErr_SetNone(PyExc_StopIteration); return NULL; } static void __Pyx_PyIter_Next_ErrorNoIterator(PyObject *iterator) { __Pyx_TypeName iterator_type_name = __Pyx_PyType_GetName(Py_TYPE(iterator)); PyErr_Format(PyExc_TypeError, __Pyx_FMT_TYPENAME " object is not an iterator", iterator_type_name); __Pyx_DECREF_TypeName(iterator_type_name); } // originally copied from Py3's builtin_next() static CYTHON_INLINE PyObject *__Pyx_PyIter_Next2(PyObject* iterator, PyObject* defval) { PyObject* next; // We always do a quick slot check because calling PyIter_Check() is so wasteful. iternextfunc iternext = Py_TYPE(iterator)->tp_iternext; if (likely(iternext)) { #if CYTHON_USE_TYPE_SLOTS || CYTHON_COMPILING_IN_PYPY next = iternext(iterator); if (likely(next)) return next; #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030d0000 if (unlikely(iternext == &_PyObject_NextNotImplemented)) return NULL; #endif #else // Since the slot was set, assume that PyIter_Next() will likely succeed, and properly fail otherwise. // Note: PyIter_Next() crashes in CPython if "tp_iternext" is NULL. next = PyIter_Next(iterator); if (likely(next)) return next; #endif } else if (CYTHON_USE_TYPE_SLOTS || unlikely(!PyIter_Check(iterator))) { // If CYTHON_USE_TYPE_SLOTS, then the slot was not set and we don't have an iterable. // Otherwise, don't trust "tp_iternext" and rely on PyIter_Check(). __Pyx_PyIter_Next_ErrorNoIterator(iterator); return NULL; } #if !CYTHON_USE_TYPE_SLOTS else { // We have an iterator with an empty "tp_iternext", but didn't call next() on it yet. next = PyIter_Next(iterator); if (likely(next)) return next; } #endif return __Pyx_PyIter_Next2Default(defval); } /////////////// IterFinish.proto /////////////// static CYTHON_INLINE int __Pyx_IterFinish(void); /*proto*/ /////////////// IterFinish /////////////// //@requires: Exceptions.c::PyThreadStateGet //@requires: Exceptions.c::PyErrFetchRestore // When PyIter_Next(iter) has returned NULL in order to signal termination, // this function does the right cleanup and returns 0 on success. If it // detects an error that occurred in the iterator, it returns -1. static CYTHON_INLINE int __Pyx_IterFinish(void) { PyObject* exc_type; __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign exc_type = __Pyx_PyErr_CurrentExceptionType(); if (unlikely(exc_type)) { if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) return -1; __Pyx_PyErr_Clear(); return 0; } return 0; } /////////////// ObjectGetItem.proto /////////////// #if CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject *key);/*proto*/ #else #define __Pyx_PyObject_GetItem(obj, key) PyObject_GetItem(obj, key) #endif /////////////// ObjectGetItem /////////////// // //@requires: GetItemInt - added in IndexNode as it uses templating. //@requires: PyObjectGetAttrStrNoError //@requires: PyObjectCallOneArg #if CYTHON_USE_TYPE_SLOTS static PyObject *__Pyx_PyObject_GetIndex(PyObject *obj, PyObject *index) { // Get element from sequence object `obj` at index `index`. PyObject *runerr = NULL; Py_ssize_t key_value; key_value = __Pyx_PyIndex_AsSsize_t(index); if (likely(key_value != -1 || !(runerr = PyErr_Occurred()))) { return __Pyx_GetItemInt_Fast(obj, key_value, 0, 1, 1); } // Error handling code -- only manage OverflowError differently. if (PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError)) { __Pyx_TypeName index_type_name = __Pyx_PyType_GetName(Py_TYPE(index)); PyErr_Clear(); PyErr_Format(PyExc_IndexError, "cannot fit '" __Pyx_FMT_TYPENAME "' into an index-sized integer", index_type_name); __Pyx_DECREF_TypeName(index_type_name); } return NULL; } static PyObject *__Pyx_PyObject_GetItem_Slow(PyObject *obj, PyObject *key) { __Pyx_TypeName obj_type_name; // Handles less common slow-path checks for GetItem if (likely(PyType_Check(obj))) { PyObject *meth = __Pyx_PyObject_GetAttrStrNoError(obj, PYIDENT("__class_getitem__")); if (!meth) { PyErr_Clear(); } else { PyObject *result = __Pyx_PyObject_CallOneArg(meth, key); Py_DECREF(meth); return result; } } obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj)); PyErr_Format(PyExc_TypeError, "'" __Pyx_FMT_TYPENAME "' object is not subscriptable", obj_type_name); __Pyx_DECREF_TypeName(obj_type_name); return NULL; } static PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject *key) { PyTypeObject *tp = Py_TYPE(obj); PyMappingMethods *mm = tp->tp_as_mapping; PySequenceMethods *sm = tp->tp_as_sequence; if (likely(mm && mm->mp_subscript)) { return mm->mp_subscript(obj, key); } if (likely(sm && sm->sq_item)) { return __Pyx_PyObject_GetIndex(obj, key); } return __Pyx_PyObject_GetItem_Slow(obj, key); } #endif /////////////// DictGetItem.proto /////////////// #if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key);/*proto*/ #define __Pyx_PyObject_Dict_GetItem(obj, name) \ (likely(PyDict_CheckExact(obj)) ? \ __Pyx_PyDict_GetItem(obj, name) : PyObject_GetItem(obj, name)) #else #define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key) #define __Pyx_PyObject_Dict_GetItem(obj, name) PyObject_GetItem(obj, name) #endif /////////////// DictGetItem /////////////// #if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) { PyObject *value; value = PyDict_GetItemWithError(d, key); if (unlikely(!value)) { if (!PyErr_Occurred()) { if (unlikely(PyTuple_Check(key))) { // CPython interprets tuples as separate arguments => must wrap them in another tuple. PyObject* args = PyTuple_Pack(1, key); if (likely(args)) { PyErr_SetObject(PyExc_KeyError, args); Py_DECREF(args); } } else { // Avoid tuple packing if possible. PyErr_SetObject(PyExc_KeyError, key); } } return NULL; } Py_INCREF(value); return value; } #endif /////////////// GetItemInt.proto /////////////// //@substitute: tempita #define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \ (__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \ __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck) : \ (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) : \ __Pyx_GetItemInt_Generic(o, to_py_func(i)))) {{for type in ['List', 'Tuple']}} #define __Pyx_GetItemInt_{{type}}(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \ (__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \ __Pyx_GetItemInt_{{type}}_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) : \ (PyErr_SetString(PyExc_IndexError, "{{ type.lower() }} index out of range"), (PyObject*)NULL)) static CYTHON_INLINE PyObject *__Pyx_GetItemInt_{{type}}_Fast(PyObject *o, Py_ssize_t i, int wraparound, int boundscheck); {{endfor}} static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j); static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list, int wraparound, int boundscheck); /////////////// GetItemInt /////////////// //@substitute: tempita static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { PyObject *r; if (unlikely(!j)) return NULL; r = PyObject_GetItem(o, j); Py_DECREF(j); return r; } {{for type in ['List', 'Tuple']}} static CYTHON_INLINE PyObject *__Pyx_GetItemInt_{{type}}_Fast(PyObject *o, Py_ssize_t i, CYTHON_NCP_UNUSED int wraparound, CYTHON_NCP_UNUSED int boundscheck) { #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS Py_ssize_t wrapped_i = i; if (wraparound & unlikely(i < 0)) { wrapped_i += Py{{type}}_GET_SIZE(o); } if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, Py{{type}}_GET_SIZE(o)))) { PyObject *r = Py{{type}}_GET_ITEM(o, wrapped_i); Py_INCREF(r); return r; } return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); #else return PySequence_GetItem(o, i); #endif } {{endfor}} static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list, CYTHON_NCP_UNUSED int wraparound, CYTHON_NCP_UNUSED int boundscheck) { #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS && CYTHON_USE_TYPE_SLOTS if (is_list || PyList_CheckExact(o)) { Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o); if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o))))) { PyObject *r = PyList_GET_ITEM(o, n); Py_INCREF(r); return r; } } else if (PyTuple_CheckExact(o)) { Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o); if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyTuple_GET_SIZE(o)))) { PyObject *r = PyTuple_GET_ITEM(o, n); Py_INCREF(r); return r; } } else { // inlined PySequence_GetItem() + special cased length overflow PyMappingMethods *mm = Py_TYPE(o)->tp_as_mapping; PySequenceMethods *sm = Py_TYPE(o)->tp_as_sequence; if (mm && mm->mp_subscript) { PyObject *r, *key = PyInt_FromSsize_t(i); if (unlikely(!key)) return NULL; r = mm->mp_subscript(o, key); Py_DECREF(key); return r; } if (likely(sm && sm->sq_item)) { if (wraparound && unlikely(i < 0) && likely(sm->sq_length)) { Py_ssize_t l = sm->sq_length(o); if (likely(l >= 0)) { i += l; } else { // if length > max(Py_ssize_t), maybe the object can wrap around itself? if (!PyErr_ExceptionMatches(PyExc_OverflowError)) return NULL; PyErr_Clear(); } } return sm->sq_item(o, i); } } #else // PySequence_GetItem behaves differently to PyObject_GetItem for i<0 // and possibly some other cases so can't generally be substituted if (is_list || !PyMapping_Check(o)) { return PySequence_GetItem(o, i); } #endif return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); } /////////////// SetItemInt.proto /////////////// #define __Pyx_SetItemInt(o, i, v, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \ (__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \ __Pyx_SetItemInt_Fast(o, (Py_ssize_t)i, v, is_list, wraparound, boundscheck) : \ (is_list ? (PyErr_SetString(PyExc_IndexError, "list assignment index out of range"), -1) : \ __Pyx_SetItemInt_Generic(o, to_py_func(i), v))) static int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v); static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int is_list, int wraparound, int boundscheck); /////////////// SetItemInt /////////////// static int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) { int r; if (unlikely(!j)) return -1; r = PyObject_SetItem(o, j, v); Py_DECREF(j); return r; } static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int is_list, CYTHON_NCP_UNUSED int wraparound, CYTHON_NCP_UNUSED int boundscheck) { #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS && CYTHON_USE_TYPE_SLOTS if (is_list || PyList_CheckExact(o)) { Py_ssize_t n = (!wraparound) ? i : ((likely(i >= 0)) ? i : i + PyList_GET_SIZE(o)); if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o)))) { PyObject* old = PyList_GET_ITEM(o, n); Py_INCREF(v); PyList_SET_ITEM(o, n, v); Py_DECREF(old); return 1; } } else { // inlined PySequence_SetItem() + special cased length overflow PyMappingMethods *mm = Py_TYPE(o)->tp_as_mapping; PySequenceMethods *sm = Py_TYPE(o)->tp_as_sequence; if (mm && mm->mp_ass_subscript) { int r; PyObject *key = PyInt_FromSsize_t(i); if (unlikely(!key)) return -1; r = mm->mp_ass_subscript(o, key, v); Py_DECREF(key); return r; } if (likely(sm && sm->sq_ass_item)) { if (wraparound && unlikely(i < 0) && likely(sm->sq_length)) { Py_ssize_t l = sm->sq_length(o); if (likely(l >= 0)) { i += l; } else { // if length > max(Py_ssize_t), maybe the object can wrap around itself? if (!PyErr_ExceptionMatches(PyExc_OverflowError)) return -1; PyErr_Clear(); } } return sm->sq_ass_item(o, i, v); } } #else // PySequence_SetItem behaves differently to PyObject_SetItem for i<0 // and possibly some other cases so can't generally be substituted if (is_list || !PyMapping_Check(o)) { return PySequence_SetItem(o, i, v); } #endif return __Pyx_SetItemInt_Generic(o, PyInt_FromSsize_t(i), v); } /////////////// DelItemInt.proto /////////////// #define __Pyx_DelItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \ (__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \ __Pyx_DelItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound) : \ (is_list ? (PyErr_SetString(PyExc_IndexError, "list assignment index out of range"), -1) : \ __Pyx_DelItem_Generic(o, to_py_func(i)))) static int __Pyx_DelItem_Generic(PyObject *o, PyObject *j); static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list, int wraparound); /////////////// DelItemInt /////////////// static int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) { int r; if (unlikely(!j)) return -1; r = PyObject_DelItem(o, j); Py_DECREF(j); return r; } static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list, CYTHON_NCP_UNUSED int wraparound) { #if !CYTHON_USE_TYPE_SLOTS // PySequence_DelItem behaves differently to PyObject_DelItem for i<0 // and possibly some other cases so can't generally be substituted if (is_list || !PyMapping_Check(o)) { return PySequence_DelItem(o, i); } #else // inlined PySequence_DelItem() + special cased length overflow PyMappingMethods *mm = Py_TYPE(o)->tp_as_mapping; PySequenceMethods *sm = Py_TYPE(o)->tp_as_sequence; if ((!is_list) && mm && mm->mp_ass_subscript) { PyObject *key = PyInt_FromSsize_t(i); return likely(key) ? mm->mp_ass_subscript(o, key, (PyObject *)NULL) : -1; } if (likely(sm && sm->sq_ass_item)) { if (wraparound && unlikely(i < 0) && likely(sm->sq_length)) { Py_ssize_t l = sm->sq_length(o); if (likely(l >= 0)) { i += l; } else { // if length > max(Py_ssize_t), maybe the object can wrap around itself? if (!PyErr_ExceptionMatches(PyExc_OverflowError)) return -1; PyErr_Clear(); } } return sm->sq_ass_item(o, i, (PyObject *)NULL); } #endif return __Pyx_DelItem_Generic(o, PyInt_FromSsize_t(i)); } /////////////// SliceObject.proto /////////////// // we pass pointer addresses to show the C compiler what is NULL and what isn't {{if access == 'Get'}} static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice( PyObject* obj, Py_ssize_t cstart, Py_ssize_t cstop, PyObject** py_start, PyObject** py_stop, PyObject** py_slice, int has_cstart, int has_cstop, int wraparound); {{else}} #define __Pyx_PyObject_DelSlice(obj, cstart, cstop, py_start, py_stop, py_slice, has_cstart, has_cstop, wraparound) \ __Pyx_PyObject_SetSlice(obj, (PyObject*)NULL, cstart, cstop, py_start, py_stop, py_slice, has_cstart, has_cstop, wraparound) // we pass pointer addresses to show the C compiler what is NULL and what isn't static CYTHON_INLINE int __Pyx_PyObject_SetSlice( PyObject* obj, PyObject* value, Py_ssize_t cstart, Py_ssize_t cstop, PyObject** py_start, PyObject** py_stop, PyObject** py_slice, int has_cstart, int has_cstop, int wraparound); {{endif}} /////////////// SliceObject /////////////// {{if access == 'Get'}} static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice(PyObject* obj, {{else}} static CYTHON_INLINE int __Pyx_PyObject_SetSlice(PyObject* obj, PyObject* value, {{endif}} Py_ssize_t cstart, Py_ssize_t cstop, PyObject** _py_start, PyObject** _py_stop, PyObject** _py_slice, int has_cstart, int has_cstop, int wraparound) { __Pyx_TypeName obj_type_name; #if CYTHON_USE_TYPE_SLOTS PyMappingMethods* mp; #if PY_MAJOR_VERSION < 3 PySequenceMethods* ms = Py_TYPE(obj)->tp_as_sequence; if (likely(ms && ms->sq_{{if access == 'Set'}}ass_{{endif}}slice)) { if (!has_cstart) { if (_py_start && (*_py_start != Py_None)) { cstart = __Pyx_PyIndex_AsSsize_t(*_py_start); if ((cstart == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad; } else cstart = 0; } if (!has_cstop) { if (_py_stop && (*_py_stop != Py_None)) { cstop = __Pyx_PyIndex_AsSsize_t(*_py_stop); if ((cstop == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad; } else cstop = PY_SSIZE_T_MAX; } if (wraparound && unlikely((cstart < 0) | (cstop < 0)) && likely(ms->sq_length)) { Py_ssize_t l = ms->sq_length(obj); if (likely(l >= 0)) { if (cstop < 0) { cstop += l; if (cstop < 0) cstop = 0; } if (cstart < 0) { cstart += l; if (cstart < 0) cstart = 0; } } else { // if length > max(Py_ssize_t), maybe the object can wrap around itself? if (!PyErr_ExceptionMatches(PyExc_OverflowError)) goto bad; PyErr_Clear(); } } {{if access == 'Get'}} return ms->sq_slice(obj, cstart, cstop); {{else}} return ms->sq_ass_slice(obj, cstart, cstop, value); {{endif}} } #else CYTHON_UNUSED_VAR(wraparound); #endif mp = Py_TYPE(obj)->tp_as_mapping; {{if access == 'Get'}} if (likely(mp && mp->mp_subscript)) {{else}} if (likely(mp && mp->mp_ass_subscript)) {{endif}} #else CYTHON_UNUSED_VAR(wraparound); #endif { {{if access == 'Get'}}PyObject*{{else}}int{{endif}} result; PyObject *py_slice, *py_start, *py_stop; if (_py_slice) { py_slice = *_py_slice; } else { PyObject* owned_start = NULL; PyObject* owned_stop = NULL; if (_py_start) { py_start = *_py_start; } else { if (has_cstart) { owned_start = py_start = PyInt_FromSsize_t(cstart); if (unlikely(!py_start)) goto bad; } else py_start = Py_None; } if (_py_stop) { py_stop = *_py_stop; } else { if (has_cstop) { owned_stop = py_stop = PyInt_FromSsize_t(cstop); if (unlikely(!py_stop)) { Py_XDECREF(owned_start); goto bad; } } else py_stop = Py_None; } py_slice = PySlice_New(py_start, py_stop, Py_None); Py_XDECREF(owned_start); Py_XDECREF(owned_stop); if (unlikely(!py_slice)) goto bad; } #if CYTHON_USE_TYPE_SLOTS {{if access == 'Get'}} result = mp->mp_subscript(obj, py_slice); #else result = PyObject_GetItem(obj, py_slice); {{else}} result = mp->mp_ass_subscript(obj, py_slice, value); #else result = value ? PyObject_SetItem(obj, py_slice, value) : PyObject_DelItem(obj, py_slice); {{endif}} #endif if (!_py_slice) { Py_DECREF(py_slice); } return result; } obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj)); PyErr_Format(PyExc_TypeError, {{if access == 'Get'}} "'" __Pyx_FMT_TYPENAME "' object is unsliceable", obj_type_name); {{else}} "'" __Pyx_FMT_TYPENAME "' object does not support slice %.10s", obj_type_name, value ? "assignment" : "deletion"); {{endif}} __Pyx_DECREF_TypeName(obj_type_name); bad: return {{if access == 'Get'}}NULL{{else}}-1{{endif}}; } /////////////// TupleAndListFromArray.proto /////////////// #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyList_FromArray(PyObject *const *src, Py_ssize_t n); static CYTHON_INLINE PyObject* __Pyx_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n); #endif /////////////// TupleAndListFromArray /////////////// //@substitute: naming #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE void __Pyx_copy_object_array(PyObject *const *CYTHON_RESTRICT src, PyObject** CYTHON_RESTRICT dest, Py_ssize_t length) { PyObject *v; Py_ssize_t i; for (i = 0; i < length; i++) { v = dest[i] = src[i]; Py_INCREF(v); } } static CYTHON_INLINE PyObject * __Pyx_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n) { PyObject *res; if (n <= 0) { Py_INCREF($empty_tuple); return $empty_tuple; } res = PyTuple_New(n); if (unlikely(res == NULL)) return NULL; __Pyx_copy_object_array(src, ((PyTupleObject*)res)->ob_item, n); return res; } static CYTHON_INLINE PyObject * __Pyx_PyList_FromArray(PyObject *const *src, Py_ssize_t n) { PyObject *res; if (n <= 0) { return PyList_New(0); } res = PyList_New(n); if (unlikely(res == NULL)) return NULL; __Pyx_copy_object_array(src, ((PyListObject*)res)->ob_item, n); return res; } #endif /////////////// SliceTupleAndList.proto /////////////// #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyList_GetSlice(PyObject* src, Py_ssize_t start, Py_ssize_t stop); static CYTHON_INLINE PyObject* __Pyx_PyTuple_GetSlice(PyObject* src, Py_ssize_t start, Py_ssize_t stop); #else #define __Pyx_PyList_GetSlice(seq, start, stop) PySequence_GetSlice(seq, start, stop) #define __Pyx_PyTuple_GetSlice(seq, start, stop) PySequence_GetSlice(seq, start, stop) #endif /////////////// SliceTupleAndList /////////////// //@requires: TupleAndListFromArray //@substitute: tempita #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE void __Pyx_crop_slice(Py_ssize_t* _start, Py_ssize_t* _stop, Py_ssize_t* _length) { Py_ssize_t start = *_start, stop = *_stop, length = *_length; if (start < 0) { start += length; if (start < 0) start = 0; } if (stop < 0) stop += length; else if (stop > length) stop = length; *_length = stop - start; *_start = start; *_stop = stop; } {{for type in ['List', 'Tuple']}} static CYTHON_INLINE PyObject* __Pyx_Py{{type}}_GetSlice( PyObject* src, Py_ssize_t start, Py_ssize_t stop) { Py_ssize_t length = Py{{type}}_GET_SIZE(src); __Pyx_crop_slice(&start, &stop, &length); {{if type=='List'}} if (length <= 0) { // Avoid undefined behaviour when accessing `ob_item` of an empty list. return PyList_New(0); } {{endif}} return __Pyx_Py{{type}}_FromArray(((Py{{type}}Object*)src)->ob_item + start, length); } {{endfor}} #endif /////////////// CalculateMetaclass.proto /////////////// static PyObject *__Pyx_CalculateMetaclass(PyTypeObject *metaclass, PyObject *bases); /////////////// CalculateMetaclass /////////////// static PyObject *__Pyx_CalculateMetaclass(PyTypeObject *metaclass, PyObject *bases) { Py_ssize_t i, nbases; #if CYTHON_ASSUME_SAFE_MACROS nbases = PyTuple_GET_SIZE(bases); #else nbases = PyTuple_Size(bases); if (nbases < 0) return NULL; #endif for (i=0; i < nbases; i++) { PyTypeObject *tmptype; #if CYTHON_ASSUME_SAFE_MACROS PyObject *tmp = PyTuple_GET_ITEM(bases, i); #else PyObject *tmp = PyTuple_GetItem(bases, i); if (!tmp) return NULL; #endif tmptype = Py_TYPE(tmp); #if PY_MAJOR_VERSION < 3 if (tmptype == &PyClass_Type) continue; #endif if (!metaclass) { metaclass = tmptype; continue; } if (PyType_IsSubtype(metaclass, tmptype)) continue; if (PyType_IsSubtype(tmptype, metaclass)) { metaclass = tmptype; continue; } // else: PyErr_SetString(PyExc_TypeError, "metaclass conflict: " "the metaclass of a derived class " "must be a (non-strict) subclass " "of the metaclasses of all its bases"); return NULL; } if (!metaclass) { #if PY_MAJOR_VERSION < 3 metaclass = &PyClass_Type; #else metaclass = &PyType_Type; #endif } // make owned reference Py_INCREF((PyObject*) metaclass); return (PyObject*) metaclass; } /////////////// FindInheritedMetaclass.proto /////////////// static PyObject *__Pyx_FindInheritedMetaclass(PyObject *bases); /*proto*/ /////////////// FindInheritedMetaclass /////////////// //@requires: PyObjectGetAttrStr //@requires: CalculateMetaclass static PyObject *__Pyx_FindInheritedMetaclass(PyObject *bases) { PyObject *metaclass; if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) { PyTypeObject *metatype; #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS PyObject *base = PyTuple_GET_ITEM(bases, 0); #else PyObject *base = PySequence_ITEM(bases, 0); #endif #if PY_MAJOR_VERSION < 3 PyObject* basetype = __Pyx_PyObject_GetAttrStr(base, PYIDENT("__class__")); if (basetype) { metatype = (PyType_Check(basetype)) ? ((PyTypeObject*) basetype) : NULL; } else { PyErr_Clear(); metatype = Py_TYPE(base); basetype = (PyObject*) metatype; Py_INCREF(basetype); } #else metatype = Py_TYPE(base); #endif metaclass = __Pyx_CalculateMetaclass(metatype, bases); #if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS) Py_DECREF(base); #endif #if PY_MAJOR_VERSION < 3 Py_DECREF(basetype); #endif } else { // no bases => use default metaclass #if PY_MAJOR_VERSION < 3 metaclass = (PyObject *) &PyClass_Type; #else metaclass = (PyObject *) &PyType_Type; #endif Py_INCREF(metaclass); } return metaclass; } /////////////// Py3MetaclassGet.proto /////////////// static PyObject *__Pyx_Py3MetaclassGet(PyObject *bases, PyObject *mkw); /*proto*/ /////////////// Py3MetaclassGet /////////////// //@requires: FindInheritedMetaclass //@requires: CalculateMetaclass static PyObject *__Pyx_Py3MetaclassGet(PyObject *bases, PyObject *mkw) { PyObject *metaclass = mkw ? __Pyx_PyDict_GetItemStr(mkw, PYIDENT("metaclass")) : NULL; if (metaclass) { Py_INCREF(metaclass); if (PyDict_DelItem(mkw, PYIDENT("metaclass")) < 0) { Py_DECREF(metaclass); return NULL; } if (PyType_Check(metaclass)) { PyObject* orig = metaclass; metaclass = __Pyx_CalculateMetaclass((PyTypeObject*) metaclass, bases); Py_DECREF(orig); } return metaclass; } return __Pyx_FindInheritedMetaclass(bases); } /////////////// CreateClass.proto /////////////// static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, PyObject *qualname, PyObject *modname); /*proto*/ /////////////// CreateClass /////////////// //@requires: FindInheritedMetaclass //@requires: CalculateMetaclass static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, PyObject *qualname, PyObject *modname) { PyObject *result; PyObject *metaclass; if (unlikely(PyDict_SetItem(dict, PYIDENT("__module__"), modname) < 0)) return NULL; #if PY_VERSION_HEX >= 0x03030000 if (unlikely(PyDict_SetItem(dict, PYIDENT("__qualname__"), qualname) < 0)) return NULL; #else CYTHON_MAYBE_UNUSED_VAR(qualname); #endif /* Python2 __metaclass__ */ metaclass = __Pyx_PyDict_GetItemStr(dict, PYIDENT("__metaclass__")); if (metaclass) { Py_INCREF(metaclass); if (PyType_Check(metaclass)) { PyObject* orig = metaclass; metaclass = __Pyx_CalculateMetaclass((PyTypeObject*) metaclass, bases); Py_DECREF(orig); } } else { metaclass = __Pyx_FindInheritedMetaclass(bases); } if (unlikely(!metaclass)) return NULL; result = PyObject_CallFunctionObjArgs(metaclass, name, bases, dict, NULL); Py_DECREF(metaclass); return result; } /////////////// Py3UpdateBases.proto /////////////// static PyObject* __Pyx_PEP560_update_bases(PyObject *bases); /* proto */ /////////////// Py3UpdateBases ///////////////////// //@requires: PyObjectCallOneArg //@requires: PyObjectGetAttrStrNoError /* Shamelessly adapted from cpython/bltinmodule.c update_bases */ static PyObject* __Pyx_PEP560_update_bases(PyObject *bases) { Py_ssize_t i, j, size_bases; PyObject *base, *meth, *new_base, *result, *new_bases = NULL; /*assert(PyTuple_Check(bases));*/ size_bases = PyTuple_GET_SIZE(bases); for (i = 0; i < size_bases; i++) { // original code in CPython: base = args[i]; base = PyTuple_GET_ITEM(bases, i); if (PyType_Check(base)) { if (new_bases) { // If we already have made a replacement, then we append every normal base, // otherwise just skip it. if (PyList_Append(new_bases, base) < 0) { goto error; } } continue; } // original code in CPython: // if (_PyObject_LookupAttrId(base, &PyId___mro_entries__, &meth) < 0) { meth = __Pyx_PyObject_GetAttrStrNoError(base, PYIDENT("__mro_entries__")); if (!meth && PyErr_Occurred()) { goto error; } if (!meth) { if (new_bases) { if (PyList_Append(new_bases, base) < 0) { goto error; } } continue; } new_base = __Pyx_PyObject_CallOneArg(meth, bases); Py_DECREF(meth); if (!new_base) { goto error; } if (!PyTuple_Check(new_base)) { PyErr_SetString(PyExc_TypeError, "__mro_entries__ must return a tuple"); Py_DECREF(new_base); goto error; } if (!new_bases) { // If this is a first successful replacement, create new_bases list and // copy previously encountered bases. if (!(new_bases = PyList_New(i))) { goto error; } for (j = 0; j < i; j++) { // original code in CPython: base = args[j]; base = PyTuple_GET_ITEM(bases, j); PyList_SET_ITEM(new_bases, j, base); Py_INCREF(base); } } j = PyList_GET_SIZE(new_bases); if (PyList_SetSlice(new_bases, j, j, new_base) < 0) { goto error; } Py_DECREF(new_base); } if (!new_bases) { // unlike the CPython implementation, always return a new reference Py_INCREF(bases); return bases; } result = PyList_AsTuple(new_bases); Py_DECREF(new_bases); return result; error: Py_XDECREF(new_bases); return NULL; } /////////////// Py3ClassCreate.proto /////////////// static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name, PyObject *qualname, PyObject *mkw, PyObject *modname, PyObject *doc); /*proto*/ static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObject *bases, PyObject *dict, PyObject *mkw, int calculate_metaclass, int allow_py2_metaclass); /*proto*/ /////////////// Py3ClassCreate /////////////// //@substitute: naming //@requires: PyObjectGetAttrStrNoError //@requires: CalculateMetaclass //@requires: PyObjectFastCall //@requires: PyObjectCall2Args //@requires: PyObjectLookupSpecial // only in fallback code: //@requires: GetBuiltinName static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name, PyObject *qualname, PyObject *mkw, PyObject *modname, PyObject *doc) { PyObject *ns; if (metaclass) { PyObject *prep = __Pyx_PyObject_GetAttrStrNoError(metaclass, PYIDENT("__prepare__")); if (prep) { PyObject *pargs[3] = {NULL, name, bases}; ns = __Pyx_PyObject_FastCallDict(prep, pargs+1, 2 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET, mkw); Py_DECREF(prep); } else { if (unlikely(PyErr_Occurred())) return NULL; ns = PyDict_New(); } } else { ns = PyDict_New(); } if (unlikely(!ns)) return NULL; /* Required here to emulate assignment order */ if (unlikely(PyObject_SetItem(ns, PYIDENT("__module__"), modname) < 0)) goto bad; #if PY_VERSION_HEX >= 0x03030000 if (unlikely(PyObject_SetItem(ns, PYIDENT("__qualname__"), qualname) < 0)) goto bad; #else CYTHON_MAYBE_UNUSED_VAR(qualname); #endif if (unlikely(doc && PyObject_SetItem(ns, PYIDENT("__doc__"), doc) < 0)) goto bad; return ns; bad: Py_DECREF(ns); return NULL; } #if PY_VERSION_HEX < 0x030600A4 && CYTHON_PEP487_INIT_SUBCLASS // https://www.python.org/dev/peps/pep-0487/ static int __Pyx_SetNamesPEP487(PyObject *type_obj) { PyTypeObject *type = (PyTypeObject*) type_obj; PyObject *names_to_set, *key, *value, *set_name, *tmp; Py_ssize_t i = 0; #if CYTHON_USE_TYPE_SLOTS names_to_set = PyDict_Copy(type->tp_dict); #else { PyObject *d = PyObject_GetAttr(type_obj, PYIDENT("__dict__")); names_to_set = NULL; if (likely(d)) { // d may not be a dict, e.g. PyDictProxy in PyPy2. PyObject *names_to_set = PyDict_New(); int ret = likely(names_to_set) ? PyDict_Update(names_to_set, d) : -1; Py_DECREF(d); if (unlikely(ret < 0)) Py_CLEAR(names_to_set); } } #endif if (unlikely(names_to_set == NULL)) goto bad; while (PyDict_Next(names_to_set, &i, &key, &value)) { set_name = __Pyx_PyObject_LookupSpecialNoError(value, PYIDENT("__set_name__")); if (unlikely(set_name != NULL)) { tmp = __Pyx_PyObject_Call2Args(set_name, type_obj, key); Py_DECREF(set_name); if (unlikely(tmp == NULL)) { __Pyx_TypeName value_type_name = __Pyx_PyType_GetName(Py_TYPE(value)); __Pyx_TypeName type_name = __Pyx_PyType_GetName(type); PyErr_Format(PyExc_RuntimeError, #if PY_MAJOR_VERSION >= 3 "Error calling __set_name__ on '" __Pyx_FMT_TYPENAME "' instance %R " "in '" __Pyx_FMT_TYPENAME "'", value_type_name, key, type_name); #else "Error calling __set_name__ on '" __Pyx_FMT_TYPENAME "' instance %.100s in '" __Pyx_FMT_TYPENAME "'", value_type_name, PyString_Check(key) ? PyString_AS_STRING(key) : "?", type_name); #endif goto bad; } else { Py_DECREF(tmp); } } else if (unlikely(PyErr_Occurred())) { goto bad; } } Py_DECREF(names_to_set); return 0; bad: Py_XDECREF(names_to_set); return -1; } static PyObject *__Pyx_InitSubclassPEP487(PyObject *type_obj, PyObject *mkw) { #if CYTHON_USE_TYPE_SLOTS && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS // Stripped-down version of "super(type_obj, type_obj).__init_subclass__(**mkw)" in CPython 3.8. PyTypeObject *type = (PyTypeObject*) type_obj; PyObject *mro = type->tp_mro; Py_ssize_t i, nbases; if (unlikely(!mro)) goto done; // avoid "unused" warning (void) &__Pyx_GetBuiltinName; Py_INCREF(mro); nbases = PyTuple_GET_SIZE(mro); // Skip over the type itself and 'object'. assert(PyTuple_GET_ITEM(mro, 0) == type_obj); for (i = 1; i < nbases-1; i++) { PyObject *base, *dict, *meth; base = PyTuple_GET_ITEM(mro, i); dict = ((PyTypeObject *)base)->tp_dict; meth = __Pyx_PyDict_GetItemStrWithError(dict, PYIDENT("__init_subclass__")); if (unlikely(meth)) { descrgetfunc f = Py_TYPE(meth)->tp_descr_get; PyObject *res; Py_INCREF(meth); if (likely(f)) { res = f(meth, NULL, type_obj); Py_DECREF(meth); if (unlikely(!res)) goto bad; meth = res; } res = __Pyx_PyObject_FastCallDict(meth, NULL, 0, mkw); Py_DECREF(meth); if (unlikely(!res)) goto bad; Py_DECREF(res); goto done; } else if (unlikely(PyErr_Occurred())) { goto bad; } } done: Py_XDECREF(mro); return type_obj; bad: Py_XDECREF(mro); Py_DECREF(type_obj); return NULL; // CYTHON_USE_TYPE_SLOTS && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS #else // Generic fallback: "super(type_obj, type_obj).__init_subclass__(**mkw)", as used in CPython 3.8. PyObject *super_type, *super, *func, *res; #if CYTHON_COMPILING_IN_PYPY && !defined(PySuper_Type) super_type = __Pyx_GetBuiltinName(PYIDENT("super")); #else super_type = (PyObject*) &PySuper_Type; // avoid "unused" warning (void) &__Pyx_GetBuiltinName; #endif super = likely(super_type) ? __Pyx_PyObject_Call2Args(super_type, type_obj, type_obj) : NULL; #if CYTHON_COMPILING_IN_PYPY && !defined(PySuper_Type) Py_XDECREF(super_type); #endif if (unlikely(!super)) { Py_CLEAR(type_obj); goto done; } func = __Pyx_PyObject_GetAttrStrNoError(super, PYIDENT("__init_subclass__")); Py_DECREF(super); if (likely(!func)) { if (unlikely(PyErr_Occurred())) Py_CLEAR(type_obj); goto done; } res = __Pyx_PyObject_FastCallDict(func, NULL, 0, mkw); Py_DECREF(func); if (unlikely(!res)) Py_CLEAR(type_obj); Py_XDECREF(res); done: return type_obj; #endif } // PY_VERSION_HEX < 0x030600A4 && CYTHON_PEP487_INIT_SUBCLASS #endif static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObject *bases, PyObject *dict, PyObject *mkw, int calculate_metaclass, int allow_py2_metaclass) { PyObject *result; PyObject *owned_metaclass = NULL; PyObject *margs[4] = {NULL, name, bases, dict}; if (allow_py2_metaclass) { /* honour Python2 __metaclass__ for backward compatibility */ owned_metaclass = PyObject_GetItem(dict, PYIDENT("__metaclass__")); if (owned_metaclass) { metaclass = owned_metaclass; } else if (likely(PyErr_ExceptionMatches(PyExc_KeyError))) { PyErr_Clear(); } else { return NULL; } } if (calculate_metaclass && (!metaclass || PyType_Check(metaclass))) { metaclass = __Pyx_CalculateMetaclass((PyTypeObject*) metaclass, bases); Py_XDECREF(owned_metaclass); if (unlikely(!metaclass)) return NULL; owned_metaclass = metaclass; } result = __Pyx_PyObject_FastCallDict(metaclass, margs+1, 3 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET, #if PY_VERSION_HEX < 0x030600A4 // Before PEP-487, type(a,b,c) did not accept any keyword arguments, so guard at least against that case. (metaclass == (PyObject*)&PyType_Type) ? NULL : mkw #else mkw #endif ); Py_XDECREF(owned_metaclass); #if PY_VERSION_HEX < 0x030600A4 && CYTHON_PEP487_INIT_SUBCLASS if (likely(result) && likely(PyType_Check(result))) { if (unlikely(__Pyx_SetNamesPEP487(result) < 0)) { Py_CLEAR(result); } else { result = __Pyx_InitSubclassPEP487(result, mkw); } } #else // avoid "unused" warning (void) &__Pyx_GetBuiltinName; #endif return result; } /////////////// ExtTypeTest.proto /////////////// static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/ /////////////// ExtTypeTest /////////////// static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { __Pyx_TypeName obj_type_name; __Pyx_TypeName type_name; if (unlikely(!type)) { PyErr_SetString(PyExc_SystemError, "Missing type object"); return 0; } if (likely(__Pyx_TypeCheck(obj, type))) return 1; obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj)); type_name = __Pyx_PyType_GetName(type); PyErr_Format(PyExc_TypeError, "Cannot convert " __Pyx_FMT_TYPENAME " to " __Pyx_FMT_TYPENAME, obj_type_name, type_name); __Pyx_DECREF_TypeName(obj_type_name); __Pyx_DECREF_TypeName(type_name); return 0; } /////////////// CallableCheck.proto /////////////// #if CYTHON_USE_TYPE_SLOTS && PY_MAJOR_VERSION >= 3 #define __Pyx_PyCallable_Check(obj) (Py_TYPE(obj)->tp_call != NULL) #else #define __Pyx_PyCallable_Check(obj) PyCallable_Check(obj) #endif /////////////// PyDictContains.proto /////////////// static CYTHON_INLINE int __Pyx_PyDict_ContainsTF(PyObject* item, PyObject* dict, int eq) { int result = PyDict_Contains(dict, item); return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); } /////////////// PySetContains.proto /////////////// static CYTHON_INLINE int __Pyx_PySet_ContainsTF(PyObject* key, PyObject* set, int eq); /* proto */ /////////////// PySetContains /////////////// //@requires: Builtins.c::pyfrozenset_new static int __Pyx_PySet_ContainsUnhashable(PyObject *set, PyObject *key) { int result = -1; if (PySet_Check(key) && PyErr_ExceptionMatches(PyExc_TypeError)) { /* Convert key to frozenset */ PyObject *tmpkey; PyErr_Clear(); tmpkey = __Pyx_PyFrozenSet_New(key); if (tmpkey != NULL) { result = PySet_Contains(set, tmpkey); Py_DECREF(tmpkey); } } return result; } static CYTHON_INLINE int __Pyx_PySet_ContainsTF(PyObject* key, PyObject* set, int eq) { int result = PySet_Contains(set, key); if (unlikely(result < 0)) { result = __Pyx_PySet_ContainsUnhashable(set, key); } return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); } /////////////// PySequenceContains.proto /////////////// static CYTHON_INLINE int __Pyx_PySequence_ContainsTF(PyObject* item, PyObject* seq, int eq) { int result = PySequence_Contains(seq, item); return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); } /////////////// PyBoolOrNullFromLong.proto /////////////// static CYTHON_INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) { return unlikely(b < 0) ? NULL : __Pyx_PyBool_FromLong(b); } /////////////// GetBuiltinName.proto /////////////// static PyObject *__Pyx_GetBuiltinName(PyObject *name); /*proto*/ /////////////// GetBuiltinName /////////////// //@requires: PyObjectGetAttrStrNoError //@substitute: naming static PyObject *__Pyx_GetBuiltinName(PyObject *name) { PyObject* result = __Pyx_PyObject_GetAttrStrNoError($builtins_cname, name); if (unlikely(!result) && !PyErr_Occurred()) { PyErr_Format(PyExc_NameError, #if PY_MAJOR_VERSION >= 3 "name '%U' is not defined", name); #else "name '%.200s' is not defined", PyString_AS_STRING(name)); #endif } return result; } /////////////// GetNameInClass.proto /////////////// #define __Pyx_GetNameInClass(var, nmspace, name) (var) = __Pyx__GetNameInClass(nmspace, name) static PyObject *__Pyx__GetNameInClass(PyObject *nmspace, PyObject *name); /*proto*/ /////////////// GetNameInClass /////////////// //@requires: GetModuleGlobalName static PyObject *__Pyx__GetNameInClass(PyObject *nmspace, PyObject *name) { PyObject *result; PyObject *dict; assert(PyType_Check(nmspace)); #if CYTHON_USE_TYPE_SLOTS dict = ((PyTypeObject*)nmspace)->tp_dict; Py_XINCREF(dict); #else dict = PyObject_GetAttr(nmspace, PYIDENT("__dict__")); #endif if (likely(dict)) { result = PyObject_GetItem(dict, name); Py_DECREF(dict); if (result) { return result; } } PyErr_Clear(); __Pyx_GetModuleGlobalNameUncached(result, name); return result; } /////////////// SetNameInClass.proto /////////////// #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && PY_VERSION_HEX < 0x030d0000 // Identifier names are always interned and have a pre-calculated hash value. #define __Pyx_SetNameInClass(ns, name, value) \ (likely(PyDict_CheckExact(ns)) ? _PyDict_SetItem_KnownHash(ns, name, value, ((PyASCIIObject *) name)->hash) : PyObject_SetItem(ns, name, value)) #elif CYTHON_COMPILING_IN_CPYTHON #define __Pyx_SetNameInClass(ns, name, value) \ (likely(PyDict_CheckExact(ns)) ? PyDict_SetItem(ns, name, value) : PyObject_SetItem(ns, name, value)) #else #define __Pyx_SetNameInClass(ns, name, value) PyObject_SetItem(ns, name, value) #endif /////////////// SetNewInClass.proto /////////////// static int __Pyx_SetNewInClass(PyObject *ns, PyObject *name, PyObject *value); /////////////// SetNewInClass /////////////// //@requires: SetNameInClass // Special-case setting __new__: if it's a Cython function, wrap it in a // staticmethod. This is similar to what Python does for a Python function // called __new__. static int __Pyx_SetNewInClass(PyObject *ns, PyObject *name, PyObject *value) { #ifdef __Pyx_CyFunction_USED int ret; if (__Pyx_CyFunction_Check(value)) { PyObject *staticnew = PyStaticMethod_New(value); if (unlikely(!staticnew)) return -1; ret = __Pyx_SetNameInClass(ns, name, staticnew); Py_DECREF(staticnew); return ret; } #endif return __Pyx_SetNameInClass(ns, name, value); } /////////////// GetModuleGlobalName.proto /////////////// //@requires: PyDictVersioning //@substitute: naming #if CYTHON_USE_DICT_VERSIONS #define __Pyx_GetModuleGlobalName(var, name) do { \ static PY_UINT64_T __pyx_dict_version = 0; \ static PyObject *__pyx_dict_cached_value = NULL; \ (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION($moddict_cname))) ? \ (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) : \ __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value); \ } while(0) #define __Pyx_GetModuleGlobalNameUncached(var, name) do { \ PY_UINT64_T __pyx_dict_version; \ PyObject *__pyx_dict_cached_value; \ (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value); \ } while(0) static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); /*proto*/ #else #define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) #define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); /*proto*/ #endif /////////////// GetModuleGlobalName /////////////// //@requires: GetBuiltinName //@substitute: naming #if CYTHON_USE_DICT_VERSIONS static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) #else static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) #endif { PyObject *result; // FIXME: clean up the macro guard order here: limited API first, then borrowed refs, then cpython #if !CYTHON_AVOID_BORROWED_REFS #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && PY_VERSION_HEX < 0x030d0000 // Identifier names are always interned and have a pre-calculated hash value. result = _PyDict_GetItem_KnownHash($moddict_cname, name, ((PyASCIIObject *) name)->hash); __PYX_UPDATE_DICT_CACHE($moddict_cname, result, *dict_cached_value, *dict_version) if (likely(result)) { return __Pyx_NewRef(result); } else if (unlikely(PyErr_Occurred())) { return NULL; } #elif CYTHON_COMPILING_IN_LIMITED_API if (unlikely(!$module_cname)) { return NULL; } result = PyObject_GetAttr($module_cname, name); if (likely(result)) { return result; } #else result = PyDict_GetItem($moddict_cname, name); __PYX_UPDATE_DICT_CACHE($moddict_cname, result, *dict_cached_value, *dict_version) if (likely(result)) { return __Pyx_NewRef(result); } #endif #else result = PyObject_GetItem($moddict_cname, name); __PYX_UPDATE_DICT_CACHE($moddict_cname, result, *dict_cached_value, *dict_version) if (likely(result)) { return __Pyx_NewRef(result); } PyErr_Clear(); #endif return __Pyx_GetBuiltinName(name); } //////////////////// GetAttr.proto //////////////////// static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *, PyObject *); /*proto*/ //////////////////// GetAttr //////////////////// //@requires: PyObjectGetAttrStr static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *o, PyObject *n) { #if CYTHON_USE_TYPE_SLOTS #if PY_MAJOR_VERSION >= 3 if (likely(PyUnicode_Check(n))) #else if (likely(PyString_Check(n))) #endif return __Pyx_PyObject_GetAttrStr(o, n); #endif return PyObject_GetAttr(o, n); } /////////////// PyObjectLookupSpecial.proto /////////////// #if CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS #define __Pyx_PyObject_LookupSpecialNoError(obj, attr_name) __Pyx__PyObject_LookupSpecial(obj, attr_name, 0) #define __Pyx_PyObject_LookupSpecial(obj, attr_name) __Pyx__PyObject_LookupSpecial(obj, attr_name, 1) static CYTHON_INLINE PyObject* __Pyx__PyObject_LookupSpecial(PyObject* obj, PyObject* attr_name, int with_error); /*proto*/ #else #define __Pyx_PyObject_LookupSpecialNoError(o,n) __Pyx_PyObject_GetAttrStrNoError(o,n) #define __Pyx_PyObject_LookupSpecial(o,n) __Pyx_PyObject_GetAttrStr(o,n) #endif /////////////// PyObjectLookupSpecial /////////////// //@requires: PyObjectGetAttrStr //@requires: PyObjectGetAttrStrNoError #if CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PyObject* __Pyx__PyObject_LookupSpecial(PyObject* obj, PyObject* attr_name, int with_error) { PyObject *res; PyTypeObject *tp = Py_TYPE(obj); #if PY_MAJOR_VERSION < 3 if (unlikely(PyInstance_Check(obj))) return with_error ? __Pyx_PyObject_GetAttrStr(obj, attr_name) : __Pyx_PyObject_GetAttrStrNoError(obj, attr_name); #endif // adapted from CPython's special_lookup() in ceval.c res = _PyType_Lookup(tp, attr_name); if (likely(res)) { descrgetfunc f = Py_TYPE(res)->tp_descr_get; if (!f) { Py_INCREF(res); } else { res = f(res, obj, (PyObject *)tp); } } else if (with_error) { PyErr_SetObject(PyExc_AttributeError, attr_name); } return res; } #endif /////////////// PyObject_GenericGetAttrNoDict.proto /////////////// // Setting "tp_getattro" to anything but "PyObject_GenericGetAttr" disables fast method calls in Py3.7. #if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name); #else // No-args macro to allow function pointer assignment. #define __Pyx_PyObject_GenericGetAttrNoDict PyObject_GenericGetAttr #endif /////////////// PyObject_GenericGetAttrNoDict /////////////// #if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 static PyObject *__Pyx_RaiseGenericGetAttributeError(PyTypeObject *tp, PyObject *attr_name) { __Pyx_TypeName type_name = __Pyx_PyType_GetName(tp); PyErr_Format(PyExc_AttributeError, #if PY_MAJOR_VERSION >= 3 "'" __Pyx_FMT_TYPENAME "' object has no attribute '%U'", type_name, attr_name); #else "'" __Pyx_FMT_TYPENAME "' object has no attribute '%.400s'", type_name, PyString_AS_STRING(attr_name)); #endif __Pyx_DECREF_TypeName(type_name); return NULL; } static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name) { // Copied and adapted from _PyObject_GenericGetAttrWithDict() in CPython 3.6/3.7. // To be used in the "tp_getattro" slot of extension types that have no instance dict and cannot be subclassed. PyObject *descr; PyTypeObject *tp = Py_TYPE(obj); if (unlikely(!PyString_Check(attr_name))) { return PyObject_GenericGetAttr(obj, attr_name); } assert(!tp->tp_dictoffset); descr = _PyType_Lookup(tp, attr_name); if (unlikely(!descr)) { return __Pyx_RaiseGenericGetAttributeError(tp, attr_name); } Py_INCREF(descr); #if PY_MAJOR_VERSION < 3 if (likely(PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS))) #endif { descrgetfunc f = Py_TYPE(descr)->tp_descr_get; // Optimise for the non-descriptor case because it is faster. if (unlikely(f)) { PyObject *res = f(descr, obj, (PyObject *)tp); Py_DECREF(descr); return res; } } return descr; } #endif /////////////// PyObject_GenericGetAttr.proto /////////////// // Setting "tp_getattro" to anything but "PyObject_GenericGetAttr" disables fast method calls in Py3.7. #if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name); #else // No-args macro to allow function pointer assignment. #define __Pyx_PyObject_GenericGetAttr PyObject_GenericGetAttr #endif /////////////// PyObject_GenericGetAttr /////////////// //@requires: PyObject_GenericGetAttrNoDict #if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name) { if (unlikely(Py_TYPE(obj)->tp_dictoffset)) { return PyObject_GenericGetAttr(obj, attr_name); } return __Pyx_PyObject_GenericGetAttrNoDict(obj, attr_name); } #endif /////////////// PyObjectGetAttrStrNoError.proto /////////////// static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name);/*proto*/ /////////////// PyObjectGetAttrStrNoError /////////////// //@requires: PyObjectGetAttrStr //@requires: Exceptions.c::PyThreadStateGet //@requires: Exceptions.c::PyErrFetchRestore //@requires: Exceptions.c::PyErrExceptionMatches #if __PYX_LIMITED_VERSION_HEX < 0x030d00A1 static void __Pyx_PyObject_GetAttrStr_ClearAttributeError(void) { __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign if (likely(__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) __Pyx_PyErr_Clear(); } #endif static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name) { PyObject *result; #if __PYX_LIMITED_VERSION_HEX >= 0x030d00A1 (void) PyObject_GetOptionalAttr(obj, attr_name, &result); return result; #else #if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_TYPE_SLOTS && PY_VERSION_HEX >= 0x030700B1 // _PyObject_GenericGetAttrWithDict() in CPython 3.7+ can avoid raising the AttributeError. // See https://bugs.python.org/issue32544 PyTypeObject* tp = Py_TYPE(obj); if (likely(tp->tp_getattro == PyObject_GenericGetAttr)) { return _PyObject_GenericGetAttrWithDict(obj, attr_name, NULL, 1); } #endif result = __Pyx_PyObject_GetAttrStr(obj, attr_name); if (unlikely(!result)) { __Pyx_PyObject_GetAttrStr_ClearAttributeError(); } return result; #endif } /////////////// PyObjectGetAttrStr.proto /////////////// #if CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name);/*proto*/ #else #define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) #endif /////////////// PyObjectGetAttrStr /////////////// #if CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { PyTypeObject* tp = Py_TYPE(obj); if (likely(tp->tp_getattro)) return tp->tp_getattro(obj, attr_name); #if PY_MAJOR_VERSION < 3 if (likely(tp->tp_getattr)) return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); #endif return PyObject_GetAttr(obj, attr_name); } #endif /////////////// PyObjectSetAttrStr.proto /////////////// #if CYTHON_USE_TYPE_SLOTS #define __Pyx_PyObject_DelAttrStr(o,n) __Pyx_PyObject_SetAttrStr(o, n, NULL) static CYTHON_INLINE int __Pyx_PyObject_SetAttrStr(PyObject* obj, PyObject* attr_name, PyObject* value);/*proto*/ #else #define __Pyx_PyObject_DelAttrStr(o,n) PyObject_DelAttr(o,n) #define __Pyx_PyObject_SetAttrStr(o,n,v) PyObject_SetAttr(o,n,v) #endif /////////////// PyObjectSetAttrStr /////////////// #if CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE int __Pyx_PyObject_SetAttrStr(PyObject* obj, PyObject* attr_name, PyObject* value) { PyTypeObject* tp = Py_TYPE(obj); if (likely(tp->tp_setattro)) return tp->tp_setattro(obj, attr_name, value); #if PY_MAJOR_VERSION < 3 if (likely(tp->tp_setattr)) return tp->tp_setattr(obj, PyString_AS_STRING(attr_name), value); #endif return PyObject_SetAttr(obj, attr_name, value); } #endif /////////////// PyObjectGetMethod.proto /////////////// static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method);/*proto*/ /////////////// PyObjectGetMethod /////////////// //@requires: PyObjectGetAttrStr static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) { PyObject *attr; #if CYTHON_UNPACK_METHODS && CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_PYTYPE_LOOKUP __Pyx_TypeName type_name; // Copied from _PyObject_GetMethod() in CPython 3.7 PyTypeObject *tp = Py_TYPE(obj); PyObject *descr; descrgetfunc f = NULL; PyObject **dictptr, *dict; int meth_found = 0; assert (*method == NULL); if (unlikely(tp->tp_getattro != PyObject_GenericGetAttr)) { attr = __Pyx_PyObject_GetAttrStr(obj, name); goto try_unpack; } if (unlikely(tp->tp_dict == NULL) && unlikely(PyType_Ready(tp) < 0)) { return 0; } descr = _PyType_Lookup(tp, name); if (likely(descr != NULL)) { Py_INCREF(descr); #if defined(Py_TPFLAGS_METHOD_DESCRIPTOR) && Py_TPFLAGS_METHOD_DESCRIPTOR if (__Pyx_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)) #elif PY_MAJOR_VERSION >= 3 // Repeating the condition below accommodates for MSVC's inability to test macros inside of macro expansions. #ifdef __Pyx_CyFunction_USED if (likely(PyFunction_Check(descr) || __Pyx_IS_TYPE(descr, &PyMethodDescr_Type) || __Pyx_CyFunction_Check(descr))) #else if (likely(PyFunction_Check(descr) || __Pyx_IS_TYPE(descr, &PyMethodDescr_Type))) #endif #else // "PyMethodDescr_Type" is not part of the C-API in Py2. #ifdef __Pyx_CyFunction_USED if (likely(PyFunction_Check(descr) || __Pyx_CyFunction_Check(descr))) #else if (likely(PyFunction_Check(descr))) #endif #endif { meth_found = 1; } else { f = Py_TYPE(descr)->tp_descr_get; if (f != NULL && PyDescr_IsData(descr)) { attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); Py_DECREF(descr); goto try_unpack; } } } dictptr = _PyObject_GetDictPtr(obj); if (dictptr != NULL && (dict = *dictptr) != NULL) { Py_INCREF(dict); attr = __Pyx_PyDict_GetItemStr(dict, name); if (attr != NULL) { Py_INCREF(attr); Py_DECREF(dict); Py_XDECREF(descr); goto try_unpack; } Py_DECREF(dict); } if (meth_found) { *method = descr; return 1; } if (f != NULL) { attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); Py_DECREF(descr); goto try_unpack; } if (likely(descr != NULL)) { *method = descr; return 0; } type_name = __Pyx_PyType_GetName(tp); PyErr_Format(PyExc_AttributeError, #if PY_MAJOR_VERSION >= 3 "'" __Pyx_FMT_TYPENAME "' object has no attribute '%U'", type_name, name); #else "'" __Pyx_FMT_TYPENAME "' object has no attribute '%.400s'", type_name, PyString_AS_STRING(name)); #endif __Pyx_DECREF_TypeName(type_name); return 0; // Generic fallback implementation using normal attribute lookup. #else attr = __Pyx_PyObject_GetAttrStr(obj, name); goto try_unpack; #endif try_unpack: #if CYTHON_UNPACK_METHODS // Even if we failed to avoid creating a bound method object, it's still worth unpacking it now, if possible. if (likely(attr) && PyMethod_Check(attr) && likely(PyMethod_GET_SELF(attr) == obj)) { PyObject *function = PyMethod_GET_FUNCTION(attr); Py_INCREF(function); Py_DECREF(attr); *method = function; return 1; } #endif *method = attr; return 0; } /////////////// UnpackUnboundCMethod.proto /////////////// typedef struct { PyObject *type; PyObject **method_name; // "func" is set on first access (direct C function pointer) PyCFunction func; // "method" is set on first access (fallback) PyObject *method; int flag; } __Pyx_CachedCFunction; /////////////// UnpackUnboundCMethod /////////////// //@requires: PyObjectGetAttrStr static PyObject *__Pyx_SelflessCall(PyObject *method, PyObject *args, PyObject *kwargs) { // NOTE: possible optimization - use vectorcall PyObject *result; PyObject *selfless_args = PyTuple_GetSlice(args, 1, PyTuple_Size(args)); if (unlikely(!selfless_args)) return NULL; result = PyObject_Call(method, selfless_args, kwargs); Py_DECREF(selfless_args); return result; } static PyMethodDef __Pyx_UnboundCMethod_Def = { /* .ml_name = */ "CythonUnboundCMethod", /* .ml_meth = */ __PYX_REINTERPRET_FUNCION(PyCFunction, __Pyx_SelflessCall), /* .ml_flags = */ METH_VARARGS | METH_KEYWORDS, /* .ml_doc = */ NULL }; static int __Pyx_TryUnpackUnboundCMethod(__Pyx_CachedCFunction* target) { PyObject *method; method = __Pyx_PyObject_GetAttrStr(target->type, *target->method_name); if (unlikely(!method)) return -1; target->method = method; // FIXME: use functionality from CythonFunction.c/ClassMethod #if CYTHON_COMPILING_IN_CPYTHON #if PY_MAJOR_VERSION >= 3 if (likely(__Pyx_TypeCheck(method, &PyMethodDescr_Type))) #else // method descriptor type isn't exported in Py2.x, cannot easily check the type there. // Therefore, reverse the check to the most likely alternative // (which is returned for class methods) if (likely(!__Pyx_CyOrPyCFunction_Check(method))) #endif { PyMethodDescrObject *descr = (PyMethodDescrObject*) method; target->func = descr->d_method->ml_meth; target->flag = descr->d_method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_STACKLESS); } else #endif // bound classmethods need special treatment #if CYTHON_COMPILING_IN_PYPY // In PyPy, functions are regular methods, so just do the self check. #else if (PyCFunction_Check(method)) #endif { PyObject *self; int self_found; #if CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_PYPY self = PyObject_GetAttrString(method, "__self__"); if (!self) { PyErr_Clear(); } #else self = PyCFunction_GET_SELF(method); #endif self_found = (self && self != Py_None); #if CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_PYPY Py_XDECREF(self); #endif if (self_found) { PyObject *unbound_method = PyCFunction_New(&__Pyx_UnboundCMethod_Def, method); if (unlikely(!unbound_method)) return -1; // New PyCFunction will own method reference, thus decref __Pyx_PyObject_GetAttrStr Py_DECREF(method); target->method = unbound_method; } } return 0; } /////////////// CallUnboundCMethod0.proto /////////////// //@substitute: naming static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self); /*proto*/ #if CYTHON_COMPILING_IN_CPYTHON // FASTCALL methods receive "&empty_tuple" as simple "PyObject[0]*" #define __Pyx_CallUnboundCMethod0(cfunc, self) \ (likely((cfunc)->func) ? \ (likely((cfunc)->flag == METH_NOARGS) ? (*((cfunc)->func))(self, NULL) : \ (PY_VERSION_HEX >= 0x030600B1 && likely((cfunc)->flag == METH_FASTCALL) ? \ (PY_VERSION_HEX >= 0x030700A0 ? \ (*(__Pyx_PyCFunctionFast)(void*)(PyCFunction)(cfunc)->func)(self, &$empty_tuple, 0) : \ (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)(cfunc)->func)(self, &$empty_tuple, 0, NULL)) : \ (PY_VERSION_HEX >= 0x030700A0 && (cfunc)->flag == (METH_FASTCALL | METH_KEYWORDS) ? \ (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)(cfunc)->func)(self, &$empty_tuple, 0, NULL) : \ (likely((cfunc)->flag == (METH_VARARGS | METH_KEYWORDS)) ? ((*(PyCFunctionWithKeywords)(void*)(PyCFunction)(cfunc)->func)(self, $empty_tuple, NULL)) : \ ((cfunc)->flag == METH_VARARGS ? (*((cfunc)->func))(self, $empty_tuple) : \ __Pyx__CallUnboundCMethod0(cfunc, self)))))) : \ __Pyx__CallUnboundCMethod0(cfunc, self)) #else #define __Pyx_CallUnboundCMethod0(cfunc, self) __Pyx__CallUnboundCMethod0(cfunc, self) #endif /////////////// CallUnboundCMethod0 /////////////// //@requires: UnpackUnboundCMethod //@requires: PyObjectCall static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self) { PyObject *args, *result = NULL; if (unlikely(!cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL; #if CYTHON_ASSUME_SAFE_MACROS args = PyTuple_New(1); if (unlikely(!args)) goto bad; Py_INCREF(self); PyTuple_SET_ITEM(args, 0, self); #else args = PyTuple_Pack(1, self); if (unlikely(!args)) goto bad; #endif result = __Pyx_PyObject_Call(cfunc->method, args, NULL); Py_DECREF(args); bad: return result; } /////////////// CallUnboundCMethod1.proto /////////////// static PyObject* __Pyx__CallUnboundCMethod1(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg);/*proto*/ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_CallUnboundCMethod1(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg);/*proto*/ #else #define __Pyx_CallUnboundCMethod1(cfunc, self, arg) __Pyx__CallUnboundCMethod1(cfunc, self, arg) #endif /////////////// CallUnboundCMethod1 /////////////// //@requires: UnpackUnboundCMethod //@requires: PyObjectCall #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_CallUnboundCMethod1(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg) { if (likely(cfunc->func)) { int flag = cfunc->flag; // Not using #ifdefs for PY_VERSION_HEX to avoid C compiler warnings about unused functions. if (flag == METH_O) { return (*(cfunc->func))(self, arg); } else if ((PY_VERSION_HEX >= 0x030600B1) && flag == METH_FASTCALL) { #if PY_VERSION_HEX >= 0x030700A0 return (*(__Pyx_PyCFunctionFast)(void*)(PyCFunction)cfunc->func)(self, &arg, 1); #else return (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)cfunc->func)(self, &arg, 1, NULL); #endif } else if ((PY_VERSION_HEX >= 0x030700A0) && flag == (METH_FASTCALL | METH_KEYWORDS)) { return (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)cfunc->func)(self, &arg, 1, NULL); } } return __Pyx__CallUnboundCMethod1(cfunc, self, arg); } #endif static PyObject* __Pyx__CallUnboundCMethod1(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg){ PyObject *args, *result = NULL; if (unlikely(!cfunc->func && !cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL; #if CYTHON_COMPILING_IN_CPYTHON if (cfunc->func && (cfunc->flag & METH_VARARGS)) { args = PyTuple_New(1); if (unlikely(!args)) goto bad; Py_INCREF(arg); PyTuple_SET_ITEM(args, 0, arg); if (cfunc->flag & METH_KEYWORDS) result = (*(PyCFunctionWithKeywords)(void*)(PyCFunction)cfunc->func)(self, args, NULL); else result = (*cfunc->func)(self, args); } else { args = PyTuple_New(2); if (unlikely(!args)) goto bad; Py_INCREF(self); PyTuple_SET_ITEM(args, 0, self); Py_INCREF(arg); PyTuple_SET_ITEM(args, 1, arg); result = __Pyx_PyObject_Call(cfunc->method, args, NULL); } #else args = PyTuple_Pack(2, self, arg); if (unlikely(!args)) goto bad; result = __Pyx_PyObject_Call(cfunc->method, args, NULL); #endif bad: Py_XDECREF(args); return result; } /////////////// CallUnboundCMethod2.proto /////////////// static PyObject* __Pyx__CallUnboundCMethod2(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg1, PyObject* arg2); /*proto*/ #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030600B1 static CYTHON_INLINE PyObject *__Pyx_CallUnboundCMethod2(__Pyx_CachedCFunction *cfunc, PyObject *self, PyObject *arg1, PyObject *arg2); /*proto*/ #else #define __Pyx_CallUnboundCMethod2(cfunc, self, arg1, arg2) __Pyx__CallUnboundCMethod2(cfunc, self, arg1, arg2) #endif /////////////// CallUnboundCMethod2 /////////////// //@requires: UnpackUnboundCMethod //@requires: PyObjectCall #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030600B1 static CYTHON_INLINE PyObject *__Pyx_CallUnboundCMethod2(__Pyx_CachedCFunction *cfunc, PyObject *self, PyObject *arg1, PyObject *arg2) { if (likely(cfunc->func)) { PyObject *args[2] = {arg1, arg2}; if (cfunc->flag == METH_FASTCALL) { #if PY_VERSION_HEX >= 0x030700A0 return (*(__Pyx_PyCFunctionFast)(void*)(PyCFunction)cfunc->func)(self, args, 2); #else return (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)cfunc->func)(self, args, 2, NULL); #endif } #if PY_VERSION_HEX >= 0x030700A0 if (cfunc->flag == (METH_FASTCALL | METH_KEYWORDS)) return (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)cfunc->func)(self, args, 2, NULL); #endif } return __Pyx__CallUnboundCMethod2(cfunc, self, arg1, arg2); } #endif static PyObject* __Pyx__CallUnboundCMethod2(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg1, PyObject* arg2){ PyObject *args, *result = NULL; if (unlikely(!cfunc->func && !cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL; #if CYTHON_COMPILING_IN_CPYTHON if (cfunc->func && (cfunc->flag & METH_VARARGS)) { args = PyTuple_New(2); if (unlikely(!args)) goto bad; Py_INCREF(arg1); PyTuple_SET_ITEM(args, 0, arg1); Py_INCREF(arg2); PyTuple_SET_ITEM(args, 1, arg2); if (cfunc->flag & METH_KEYWORDS) result = (*(PyCFunctionWithKeywords)(void*)(PyCFunction)cfunc->func)(self, args, NULL); else result = (*cfunc->func)(self, args); } else { args = PyTuple_New(3); if (unlikely(!args)) goto bad; Py_INCREF(self); PyTuple_SET_ITEM(args, 0, self); Py_INCREF(arg1); PyTuple_SET_ITEM(args, 1, arg1); Py_INCREF(arg2); PyTuple_SET_ITEM(args, 2, arg2); result = __Pyx_PyObject_Call(cfunc->method, args, NULL); } #else args = PyTuple_Pack(3, self, arg1, arg2); if (unlikely(!args)) goto bad; result = __Pyx_PyObject_Call(cfunc->method, args, NULL); #endif bad: Py_XDECREF(args); return result; } /////////////// PyObjectFastCall.proto /////////////// #define __Pyx_PyObject_FastCall(func, args, nargs) __Pyx_PyObject_FastCallDict(func, args, (size_t)(nargs), NULL) static CYTHON_INLINE PyObject* __Pyx_PyObject_FastCallDict(PyObject *func, PyObject **args, size_t nargs, PyObject *kwargs); /*proto*/ /////////////// PyObjectFastCall /////////////// //@requires: PyObjectCall //@requires: PyFunctionFastCall //@requires: PyObjectCallMethO //@substitute: naming #if PY_VERSION_HEX < 0x03090000 || CYTHON_COMPILING_IN_LIMITED_API static PyObject* __Pyx_PyObject_FastCall_fallback(PyObject *func, PyObject **args, size_t nargs, PyObject *kwargs) { PyObject *argstuple; PyObject *result = 0; size_t i; argstuple = PyTuple_New((Py_ssize_t)nargs); if (unlikely(!argstuple)) return NULL; for (i = 0; i < nargs; i++) { Py_INCREF(args[i]); if (__Pyx_PyTuple_SET_ITEM(argstuple, (Py_ssize_t)i, args[i]) < 0) goto bad; } result = __Pyx_PyObject_Call(func, argstuple, kwargs); bad: Py_DECREF(argstuple); return result; } #endif static CYTHON_INLINE PyObject* __Pyx_PyObject_FastCallDict(PyObject *func, PyObject **args, size_t _nargs, PyObject *kwargs) { // Special fast paths for 0 and 1 arguments // NOTE: in many cases, this is called with a constant value for nargs // which is known at compile-time. So the branches below will typically // be optimized away. Py_ssize_t nargs = __Pyx_PyVectorcall_NARGS(_nargs); #if CYTHON_COMPILING_IN_CPYTHON if (nargs == 0 && kwargs == NULL) { if (__Pyx_CyOrPyCFunction_Check(func) && likely( __Pyx_CyOrPyCFunction_GET_FLAGS(func) & METH_NOARGS)) return __Pyx_PyObject_CallMethO(func, NULL); } else if (nargs == 1 && kwargs == NULL) { if (__Pyx_CyOrPyCFunction_Check(func) && likely( __Pyx_CyOrPyCFunction_GET_FLAGS(func) & METH_O)) return __Pyx_PyObject_CallMethO(func, args[0]); } #endif #if PY_VERSION_HEX < 0x030800B1 #if CYTHON_FAST_PYCCALL if (PyCFunction_Check(func)) { if (kwargs) { return _PyCFunction_FastCallDict(func, args, nargs, kwargs); } else { return _PyCFunction_FastCallKeywords(func, args, nargs, NULL); } } #if PY_VERSION_HEX >= 0x030700A1 if (!kwargs && __Pyx_IS_TYPE(func, &PyMethodDescr_Type)) { return _PyMethodDescr_FastCallKeywords(func, args, nargs, NULL); } #endif #endif #if CYTHON_FAST_PYCALL if (PyFunction_Check(func)) { return __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs); } #endif #endif if (kwargs == NULL) { #if CYTHON_VECTORCALL #if PY_VERSION_HEX < 0x03090000 vectorcallfunc f = _PyVectorcall_Function(func); #else vectorcallfunc f = PyVectorcall_Function(func); #endif if (f) { return f(func, args, (size_t)nargs, NULL); } #elif defined(__Pyx_CyFunction_USED) && CYTHON_BACKPORT_VECTORCALL // exclude fused functions for now if (__Pyx_CyFunction_CheckExact(func)) { __pyx_vectorcallfunc f = __Pyx_CyFunction_func_vectorcall(func); if (f) return f(func, args, (size_t)nargs, NULL); } #endif } if (nargs == 0) { return __Pyx_PyObject_Call(func, $empty_tuple, kwargs); } #if PY_VERSION_HEX >= 0x03090000 && !CYTHON_COMPILING_IN_LIMITED_API return PyObject_VectorcallDict(func, args, (size_t)nargs, kwargs); #else return __Pyx_PyObject_FastCall_fallback(func, args, (size_t)nargs, kwargs); #endif } /////////////// PyObjectCallMethod0.proto /////////////// static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name); /*proto*/ /////////////// PyObjectCallMethod0 /////////////// //@requires: PyObjectGetMethod //@requires: PyObjectCallOneArg //@requires: PyObjectCallNoArg static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name) { PyObject *method = NULL, *result = NULL; int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method); if (likely(is_method)) { result = __Pyx_PyObject_CallOneArg(method, obj); Py_DECREF(method); return result; } if (unlikely(!method)) goto bad; result = __Pyx_PyObject_CallNoArg(method); Py_DECREF(method); bad: return result; } /////////////// PyObjectCallMethod1.proto /////////////// static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg); /*proto*/ /////////////// PyObjectCallMethod1 /////////////// //@requires: PyObjectGetMethod //@requires: PyObjectCallOneArg //@requires: PyObjectCall2Args #if !(CYTHON_VECTORCALL && __PYX_LIMITED_VERSION_HEX >= 0x030C00A2) static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg) { // Separate function to avoid excessive inlining. PyObject *result = __Pyx_PyObject_CallOneArg(method, arg); Py_DECREF(method); return result; } #endif static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg) { #if CYTHON_VECTORCALL && __PYX_LIMITED_VERSION_HEX >= 0x030C00A2 PyObject *args[2] = {obj, arg}; // avoid unused functions (void) __Pyx_PyObject_GetMethod; (void) __Pyx_PyObject_CallOneArg; (void) __Pyx_PyObject_Call2Args; return PyObject_VectorcallMethod(method_name, args, 2 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); #else PyObject *method = NULL, *result; int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method); if (likely(is_method)) { result = __Pyx_PyObject_Call2Args(method, obj, arg); Py_DECREF(method); return result; } if (unlikely(!method)) return NULL; return __Pyx__PyObject_CallMethod1(method, arg); #endif } /////////////// tp_new.proto /////////////// #define __Pyx_tp_new(type_obj, args) __Pyx_tp_new_kwargs(type_obj, args, NULL) static CYTHON_INLINE PyObject* __Pyx_tp_new_kwargs(PyObject* type_obj, PyObject* args, PyObject* kwargs) { return (PyObject*) (((PyTypeObject*)type_obj)->tp_new((PyTypeObject*)type_obj, args, kwargs)); } /////////////// PyObjectCall.proto /////////////// #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); /*proto*/ #else #define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) #endif /////////////// PyObjectCall /////////////// #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *result; ternaryfunc call = Py_TYPE(func)->tp_call; if (unlikely(!call)) return PyObject_Call(func, arg, kw); #if PY_MAJOR_VERSION < 3 if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) return NULL; #else if (unlikely(Py_EnterRecursiveCall(" while calling a Python object"))) return NULL; #endif result = (*call)(func, arg, kw); Py_LeaveRecursiveCall(); if (unlikely(!result) && unlikely(!PyErr_Occurred())) { PyErr_SetString( PyExc_SystemError, "NULL result without error in PyObject_Call"); } return result; } #endif /////////////// PyObjectCallMethO.proto /////////////// #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); /*proto*/ #endif /////////////// PyObjectCallMethO /////////////// #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { PyObject *self, *result; PyCFunction cfunc; cfunc = __Pyx_CyOrPyCFunction_GET_FUNCTION(func); self = __Pyx_CyOrPyCFunction_GET_SELF(func); #if PY_MAJOR_VERSION < 3 if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) return NULL; #else if (unlikely(Py_EnterRecursiveCall(" while calling a Python object"))) return NULL; #endif result = cfunc(self, arg); Py_LeaveRecursiveCall(); if (unlikely(!result) && unlikely(!PyErr_Occurred())) { PyErr_SetString( PyExc_SystemError, "NULL result without error in PyObject_Call"); } return result; } #endif /////////////// PyFunctionFastCall.proto /////////////// #if CYTHON_FAST_PYCALL #if !CYTHON_VECTORCALL #define __Pyx_PyFunction_FastCall(func, args, nargs) \ __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); #endif // Backport from Python 3 // Assert a build-time dependency, as an expression. // Your compile will fail if the condition isn't true, or can't be evaluated // by the compiler. This can be used in an expression: its value is 0. // Example: // #define foo_to_char(foo) \ // ((char *)(foo) \ // + Py_BUILD_ASSERT_EXPR(offsetof(struct foo, string) == 0)) // // Written by Rusty Russell, public domain, https://ccodearchive.net/ #define __Pyx_BUILD_ASSERT_EXPR(cond) \ (sizeof(char [1 - 2*!(cond)]) - 1) #ifndef Py_MEMBER_SIZE // Get the size of a structure member in bytes #define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) #endif #if !CYTHON_VECTORCALL #if PY_VERSION_HEX >= 0x03080000 #include "frameobject.h" #if PY_VERSION_HEX >= 0x030b00a6 && !CYTHON_COMPILING_IN_LIMITED_API #ifndef Py_BUILD_CORE #define Py_BUILD_CORE 1 #endif #include "internal/pycore_frame.h" #endif #define __Pxy_PyFrame_Initialize_Offsets() #define __Pyx_PyFrame_GetLocalsplus(frame) ((frame)->f_localsplus) #else // Initialised by module init code. static size_t __pyx_pyframe_localsplus_offset = 0; #include "frameobject.h" // This is the long runtime version of // #define __Pyx_PyFrame_GetLocalsplus(frame) ((frame)->f_localsplus) // offsetof(PyFrameObject, f_localsplus) differs between regular C-Python and Stackless Python < 3.8. // Therefore the offset is computed at run time from PyFrame_type.tp_basicsize. That is feasible, // because f_localsplus is the last field of PyFrameObject (checked by Py_BUILD_ASSERT_EXPR below). #define __Pxy_PyFrame_Initialize_Offsets() \ ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)), \ (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) #define __Pyx_PyFrame_GetLocalsplus(frame) \ (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) #endif #endif /* !CYTHON_VECTORCALL */ #endif /* CYTHON_FAST_PYCALL */ /////////////// PyFunctionFastCall /////////////// // copied from CPython 3.6 ceval.c #if CYTHON_FAST_PYCALL && !CYTHON_VECTORCALL static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, PyObject *globals) { PyFrameObject *f; PyThreadState *tstate = __Pyx_PyThreadState_Current; PyObject **fastlocals; Py_ssize_t i; PyObject *result; assert(globals != NULL); /* XXX Perhaps we should create a specialized PyFrame_New() that doesn't take locals, but does take builtins without sanity checking them. */ assert(tstate != NULL); f = PyFrame_New(tstate, co, globals, NULL); if (f == NULL) { return NULL; } fastlocals = __Pyx_PyFrame_GetLocalsplus(f); for (i = 0; i < na; i++) { Py_INCREF(*args); fastlocals[i] = *args++; } result = PyEval_EvalFrameEx(f,0); ++tstate->recursion_depth; Py_DECREF(f); --tstate->recursion_depth; return result; } static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); PyObject *globals = PyFunction_GET_GLOBALS(func); PyObject *argdefs = PyFunction_GET_DEFAULTS(func); PyObject *closure; #if PY_MAJOR_VERSION >= 3 PyObject *kwdefs; //#if PY_VERSION_HEX >= 0x03050000 //PyObject *name, *qualname; //#endif #endif PyObject *kwtuple, **k; PyObject **d; Py_ssize_t nd; Py_ssize_t nk; PyObject *result; assert(kwargs == NULL || PyDict_Check(kwargs)); nk = kwargs ? PyDict_Size(kwargs) : 0; #if PY_MAJOR_VERSION < 3 if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) { return NULL; } #else if (unlikely(Py_EnterRecursiveCall(" while calling a Python object"))) { return NULL; } #endif if ( #if PY_MAJOR_VERSION >= 3 co->co_kwonlyargcount == 0 && #endif likely(kwargs == NULL || nk == 0) && co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { /* Fast paths */ if (argdefs == NULL && co->co_argcount == nargs) { result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); goto done; } else if (nargs == 0 && argdefs != NULL && co->co_argcount == Py_SIZE(argdefs)) { /* function called with no arguments, but all parameters have a default value: use default values as arguments .*/ args = &PyTuple_GET_ITEM(argdefs, 0); result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); goto done; } } if (kwargs != NULL) { Py_ssize_t pos, i; kwtuple = PyTuple_New(2 * nk); if (kwtuple == NULL) { result = NULL; goto done; } k = &PyTuple_GET_ITEM(kwtuple, 0); pos = i = 0; while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { Py_INCREF(k[i]); Py_INCREF(k[i+1]); i += 2; } nk = i / 2; } else { kwtuple = NULL; k = NULL; } closure = PyFunction_GET_CLOSURE(func); #if PY_MAJOR_VERSION >= 3 kwdefs = PyFunction_GET_KW_DEFAULTS(func); //#if PY_VERSION_HEX >= 0x03050000 //name = ((PyFunctionObject *)func) -> func_name; //qualname = ((PyFunctionObject *)func) -> func_qualname; //#endif #endif if (argdefs != NULL) { d = &PyTuple_GET_ITEM(argdefs, 0); nd = Py_SIZE(argdefs); } else { d = NULL; nd = 0; } //#if PY_VERSION_HEX >= 0x03050000 //return _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL, // args, nargs, // NULL, 0, // d, nd, kwdefs, // closure, name, qualname); //#elif PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3 result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, args, (int)nargs, k, (int)nk, d, (int)nd, kwdefs, closure); #else result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, args, (int)nargs, k, (int)nk, d, (int)nd, closure); #endif Py_XDECREF(kwtuple); done: Py_LeaveRecursiveCall(); return result; } #endif /* CYTHON_FAST_PYCALL && !CYTHON_VECTORCALL */ /////////////// PyObjectCall2Args.proto /////////////// static CYTHON_INLINE PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2); /*proto*/ /////////////// PyObjectCall2Args /////////////// //@requires: PyObjectFastCall static CYTHON_INLINE PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2) { PyObject *args[3] = {NULL, arg1, arg2}; return __Pyx_PyObject_FastCall(function, args+1, 2 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET); } /////////////// PyObjectCallOneArg.proto /////////////// static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); /*proto*/ /////////////// PyObjectCallOneArg /////////////// //@requires: PyObjectFastCall static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { PyObject *args[2] = {NULL, arg}; return __Pyx_PyObject_FastCall(func, args+1, 1 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET); } /////////////// PyObjectCallNoArg.proto /////////////// static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func); /*proto*/ /////////////// PyObjectCallNoArg /////////////// //@requires: PyObjectFastCall static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) { PyObject *arg[2] = {NULL, NULL}; return __Pyx_PyObject_FastCall(func, arg + 1, 0 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET); } /////////////// PyVectorcallFastCallDict.proto /////////////// #if CYTHON_METH_FASTCALL static CYTHON_INLINE PyObject *__Pyx_PyVectorcall_FastCallDict(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw); #endif /////////////// PyVectorcallFastCallDict /////////////// #if CYTHON_METH_FASTCALL // Slow path when kw is non-empty static PyObject *__Pyx_PyVectorcall_FastCallDict_kw(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw) { // Code based on _PyObject_FastCallDict() and _PyStack_UnpackDict() from CPython PyObject *res = NULL; PyObject *kwnames; PyObject **newargs; PyObject **kwvalues; Py_ssize_t i, pos; size_t j; PyObject *key, *value; unsigned long keys_are_strings; Py_ssize_t nkw = PyDict_GET_SIZE(kw); // Copy positional arguments newargs = (PyObject **)PyMem_Malloc((nargs + (size_t)nkw) * sizeof(args[0])); if (unlikely(newargs == NULL)) { PyErr_NoMemory(); return NULL; } for (j = 0; j < nargs; j++) newargs[j] = args[j]; // Copy keyword arguments kwnames = PyTuple_New(nkw); if (unlikely(kwnames == NULL)) { PyMem_Free(newargs); return NULL; } kwvalues = newargs + nargs; pos = i = 0; keys_are_strings = Py_TPFLAGS_UNICODE_SUBCLASS; while (PyDict_Next(kw, &pos, &key, &value)) { keys_are_strings &= Py_TYPE(key)->tp_flags; Py_INCREF(key); Py_INCREF(value); PyTuple_SET_ITEM(kwnames, i, key); kwvalues[i] = value; i++; } if (unlikely(!keys_are_strings)) { PyErr_SetString(PyExc_TypeError, "keywords must be strings"); goto cleanup; } // The actual call res = vc(func, newargs, nargs, kwnames); cleanup: Py_DECREF(kwnames); for (i = 0; i < nkw; i++) Py_DECREF(kwvalues[i]); PyMem_Free(newargs); return res; } static CYTHON_INLINE PyObject *__Pyx_PyVectorcall_FastCallDict(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw) { if (likely(kw == NULL) || PyDict_GET_SIZE(kw) == 0) { return vc(func, args, nargs, NULL); } return __Pyx_PyVectorcall_FastCallDict_kw(func, vc, args, nargs, kw); } #endif /////////////// MatrixMultiply.proto /////////////// #if PY_VERSION_HEX >= 0x03050000 #define __Pyx_PyNumber_MatrixMultiply(x,y) PyNumber_MatrixMultiply(x,y) #define __Pyx_PyNumber_InPlaceMatrixMultiply(x,y) PyNumber_InPlaceMatrixMultiply(x,y) #else #define __Pyx_PyNumber_MatrixMultiply(x,y) __Pyx__PyNumber_MatrixMultiply(x, y, "@") static PyObject* __Pyx__PyNumber_MatrixMultiply(PyObject* x, PyObject* y, const char* op_name); static PyObject* __Pyx_PyNumber_InPlaceMatrixMultiply(PyObject* x, PyObject* y); #endif /////////////// MatrixMultiply /////////////// //@requires: PyObjectGetAttrStrNoError //@requires: PyObjectCallOneArg //@requires: PyObjectCall2Args #if PY_VERSION_HEX < 0x03050000 static PyObject* __Pyx_PyObject_CallMatrixMethod(PyObject* method, PyObject* arg) { // NOTE: eats the method reference PyObject *result = NULL; #if CYTHON_UNPACK_METHODS if (likely(PyMethod_Check(method))) { PyObject *self = PyMethod_GET_SELF(method); if (likely(self)) { PyObject *function = PyMethod_GET_FUNCTION(method); result = __Pyx_PyObject_Call2Args(function, self, arg); goto done; } } #endif result = __Pyx_PyObject_CallOneArg(method, arg); done: Py_DECREF(method); return result; } #define __Pyx_TryMatrixMethod(x, y, py_method_name) { \ PyObject *func = __Pyx_PyObject_GetAttrStrNoError(x, py_method_name); \ if (func) { \ PyObject *result = __Pyx_PyObject_CallMatrixMethod(func, y); \ if (result != Py_NotImplemented) \ return result; \ Py_DECREF(result); \ } else if (unlikely(PyErr_Occurred())) { \ return NULL; \ } \ } static PyObject* __Pyx__PyNumber_MatrixMultiply(PyObject* x, PyObject* y, const char* op_name) { __Pyx_TypeName x_type_name; __Pyx_TypeName y_type_name; int right_is_subtype = PyObject_IsSubclass((PyObject*)Py_TYPE(y), (PyObject*)Py_TYPE(x)); if (unlikely(right_is_subtype == -1)) return NULL; if (right_is_subtype) { // to allow subtypes to override parent behaviour, try reversed operation first // see note at https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types __Pyx_TryMatrixMethod(y, x, PYIDENT("__rmatmul__")) } __Pyx_TryMatrixMethod(x, y, PYIDENT("__matmul__")) if (!right_is_subtype) { __Pyx_TryMatrixMethod(y, x, PYIDENT("__rmatmul__")) } x_type_name = __Pyx_PyType_GetName(Py_TYPE(x)); y_type_name = __Pyx_PyType_GetName(Py_TYPE(y)); PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %.2s: '" __Pyx_FMT_TYPENAME "' and '" __Pyx_FMT_TYPENAME "'", op_name, x_type_name, y_type_name); __Pyx_DECREF_TypeName(x_type_name); __Pyx_DECREF_TypeName(y_type_name); return NULL; } static PyObject* __Pyx_PyNumber_InPlaceMatrixMultiply(PyObject* x, PyObject* y) { __Pyx_TryMatrixMethod(x, y, PYIDENT("__imatmul__")) return __Pyx__PyNumber_MatrixMultiply(x, y, "@="); } #undef __Pyx_TryMatrixMethod #endif /////////////// PyDictVersioning.proto /////////////// #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS #define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) #define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) #define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) \ (version_var) = __PYX_GET_DICT_VERSION(dict); \ (cache_var) = (value); #define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) { \ static PY_UINT64_T __pyx_dict_version = 0; \ static PyObject *__pyx_dict_cached_value = NULL; \ if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) { \ (VAR) = __pyx_dict_cached_value; \ } else { \ (VAR) = __pyx_dict_cached_value = (LOOKUP); \ __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT); \ } \ } static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); /*proto*/ static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); /*proto*/ static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); /*proto*/ #else #define __PYX_GET_DICT_VERSION(dict) (0) #define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) #define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); #endif /////////////// PyDictVersioning /////////////// #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { PyObject *dict = Py_TYPE(obj)->tp_dict; return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; } static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { PyObject **dictptr = NULL; Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; if (offset) { #if CYTHON_COMPILING_IN_CPYTHON dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); #else dictptr = _PyObject_GetDictPtr(obj); #endif } return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; } static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { PyObject *dict = Py_TYPE(obj)->tp_dict; if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) return 0; return obj_dict_version == __Pyx_get_object_dict_version(obj); } #endif /////////////// PyMethodNew.proto /////////////// #if CYTHON_COMPILING_IN_LIMITED_API static PyObject *__Pyx_PyMethod_New(PyObject *func, PyObject *self, PyObject *typ) { PyObject *typesModule=NULL, *methodType=NULL, *result=NULL; CYTHON_UNUSED_VAR(typ); if (!self) return __Pyx_NewRef(func); typesModule = PyImport_ImportModule("types"); if (!typesModule) return NULL; methodType = PyObject_GetAttrString(typesModule, "MethodType"); Py_DECREF(typesModule); if (!methodType) return NULL; result = PyObject_CallFunctionObjArgs(methodType, func, self, NULL); Py_DECREF(methodType); return result; } #elif PY_MAJOR_VERSION >= 3 // This should be an actual function (not a macro), such that we can put it // directly in a tp_descr_get slot. static PyObject *__Pyx_PyMethod_New(PyObject *func, PyObject *self, PyObject *typ) { CYTHON_UNUSED_VAR(typ); if (!self) return __Pyx_NewRef(func); return PyMethod_New(func, self); } #else #define __Pyx_PyMethod_New PyMethod_New #endif ///////////// PyMethodNew2Arg.proto ///////////// // Another wrapping of PyMethod_New that matches the Python3 signature #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyMethod_New2Arg PyMethod_New #else #define __Pyx_PyMethod_New2Arg(func, self) PyMethod_New(func, self, (PyObject*)Py_TYPE(self)) #endif /////////////// UnicodeConcatInPlace.proto //////////////// # if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3 // __Pyx_PyUnicode_ConcatInPlace may modify the first argument 'left' // However, unlike `PyUnicode_Append` it will never NULL it. // It behaves like a regular function - returns a new reference and NULL on error #if CYTHON_REFNANNY #define __Pyx_PyUnicode_ConcatInPlace(left, right) __Pyx_PyUnicode_ConcatInPlaceImpl(&left, right, __pyx_refnanny) #else #define __Pyx_PyUnicode_ConcatInPlace(left, right) __Pyx_PyUnicode_ConcatInPlaceImpl(&left, right) #endif // __Pyx_PyUnicode_ConcatInPlace is slightly odd because it has the potential to modify the input // argument (but only in cases where no user should notice). Therefore, it needs to keep Cython's // refnanny informed. static CYTHON_INLINE PyObject *__Pyx_PyUnicode_ConcatInPlaceImpl(PyObject **p_left, PyObject *right #if CYTHON_REFNANNY , void* __pyx_refnanny #endif ); /* proto */ #else #define __Pyx_PyUnicode_ConcatInPlace __Pyx_PyUnicode_Concat #endif #define __Pyx_PyUnicode_ConcatInPlaceSafe(left, right) ((unlikely((left) == Py_None) || unlikely((right) == Py_None)) ? \ PyNumber_InPlaceAdd(left, right) : __Pyx_PyUnicode_ConcatInPlace(left, right)) /////////////// UnicodeConcatInPlace //////////////// //@substitute: naming # if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3 // copied directly from unicode_object.c "unicode_modifiable // removing _PyUnicode_HASH since it's a macro we don't have // - this is OK because trying PyUnicode_Resize on a non-modifyable // object will still work, it just won't happen in place static int __Pyx_unicode_modifiable(PyObject *unicode) { if (Py_REFCNT(unicode) != 1) return 0; if (!PyUnicode_CheckExact(unicode)) return 0; if (PyUnicode_CHECK_INTERNED(unicode)) return 0; return 1; } static CYTHON_INLINE PyObject *__Pyx_PyUnicode_ConcatInPlaceImpl(PyObject **p_left, PyObject *right #if CYTHON_REFNANNY , void* __pyx_refnanny #endif ) { // heavily based on PyUnicode_Append PyObject *left = *p_left; Py_ssize_t left_len, right_len, new_len; if (unlikely(__Pyx_PyUnicode_READY(left) == -1)) return NULL; if (unlikely(__Pyx_PyUnicode_READY(right) == -1)) return NULL; // Shortcuts left_len = PyUnicode_GET_LENGTH(left); if (left_len == 0) { Py_INCREF(right); return right; } right_len = PyUnicode_GET_LENGTH(right); if (right_len == 0) { Py_INCREF(left); return left; } if (unlikely(left_len > PY_SSIZE_T_MAX - right_len)) { PyErr_SetString(PyExc_OverflowError, "strings are too large to concat"); return NULL; } new_len = left_len + right_len; if (__Pyx_unicode_modifiable(left) && PyUnicode_CheckExact(right) && PyUnicode_KIND(right) <= PyUnicode_KIND(left) // Don't resize for ascii += latin1. Convert ascii to latin1 requires // to change the structure size, but characters are stored just after // the structure, and so it requires to move all characters which is // not so different than duplicating the string. && !(PyUnicode_IS_ASCII(left) && !PyUnicode_IS_ASCII(right))) { int ret; // GIVEREF/GOTREF since we expect *p_left to change (although it won't change on failures). __Pyx_GIVEREF(*p_left); ret = PyUnicode_Resize(p_left, new_len); __Pyx_GOTREF(*p_left); if (unlikely(ret != 0)) return NULL; // copy 'right' into the newly allocated area of 'left' #if PY_VERSION_HEX >= 0x030d0000 if (unlikely(PyUnicode_CopyCharacters(*p_left, left_len, right, 0, right_len) < 0)) return NULL; #else _PyUnicode_FastCopyCharacters(*p_left, left_len, right, 0, right_len); #endif __Pyx_INCREF(*p_left); __Pyx_GIVEREF(*p_left); return *p_left; } else { return __Pyx_PyUnicode_Concat(left, right); } } #endif ////////////// StrConcatInPlace.proto /////////////////////// //@requires: UnicodeConcatInPlace #if PY_MAJOR_VERSION >= 3 // allow access to the more efficient versions where we know str_type is unicode #define __Pyx_PyStr_Concat __Pyx_PyUnicode_Concat #define __Pyx_PyStr_ConcatInPlace __Pyx_PyUnicode_ConcatInPlace #else #define __Pyx_PyStr_Concat PyNumber_Add #define __Pyx_PyStr_ConcatInPlace PyNumber_InPlaceAdd #endif #define __Pyx_PyStr_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ? \ PyNumber_Add(a, b) : __Pyx_PyStr_Concat(a, b)) #define __Pyx_PyStr_ConcatInPlaceSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ? \ PyNumber_InPlaceAdd(a, b) : __Pyx_PyStr_ConcatInPlace(a, b)) /////////////// PySequenceMultiply.proto /////////////// #define __Pyx_PySequence_Multiply_Left(mul, seq) __Pyx_PySequence_Multiply(seq, mul) static CYTHON_INLINE PyObject* __Pyx_PySequence_Multiply(PyObject *seq, Py_ssize_t mul); /////////////// PySequenceMultiply /////////////// static PyObject* __Pyx_PySequence_Multiply_Generic(PyObject *seq, Py_ssize_t mul) { PyObject *result, *pymul = PyInt_FromSsize_t(mul); if (unlikely(!pymul)) return NULL; result = PyNumber_Multiply(seq, pymul); Py_DECREF(pymul); return result; } static CYTHON_INLINE PyObject* __Pyx_PySequence_Multiply(PyObject *seq, Py_ssize_t mul) { #if CYTHON_USE_TYPE_SLOTS PyTypeObject *type = Py_TYPE(seq); if (likely(type->tp_as_sequence && type->tp_as_sequence->sq_repeat)) { return type->tp_as_sequence->sq_repeat(seq, mul); } else #endif { return __Pyx_PySequence_Multiply_Generic(seq, mul); } } /////////////// FormatTypeName.proto /////////////// #if CYTHON_COMPILING_IN_LIMITED_API typedef PyObject *__Pyx_TypeName; #define __Pyx_FMT_TYPENAME "%U" static __Pyx_TypeName __Pyx_PyType_GetName(PyTypeObject* tp); /*proto*/ #define __Pyx_DECREF_TypeName(obj) Py_XDECREF(obj) #else typedef const char *__Pyx_TypeName; #define __Pyx_FMT_TYPENAME "%.200s" #define __Pyx_PyType_GetName(tp) ((tp)->tp_name) #define __Pyx_DECREF_TypeName(obj) #endif /////////////// FormatTypeName /////////////// #if CYTHON_COMPILING_IN_LIMITED_API static __Pyx_TypeName __Pyx_PyType_GetName(PyTypeObject* tp) { PyObject *name = __Pyx_PyObject_GetAttrStr((PyObject *)tp, PYIDENT("__name__")); if (unlikely(name == NULL) || unlikely(!PyUnicode_Check(name))) { PyErr_Clear(); Py_XDECREF(name); name = __Pyx_NewRef(PYIDENT("?")); } return name; } #endif /////////////// RaiseUnexpectedTypeError.proto /////////////// static int __Pyx_RaiseUnexpectedTypeError(const char *expected, PyObject *obj); /*proto*/ /////////////// RaiseUnexpectedTypeError /////////////// static int __Pyx_RaiseUnexpectedTypeError(const char *expected, PyObject *obj) { __Pyx_TypeName obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj)); PyErr_Format(PyExc_TypeError, "Expected %s, got " __Pyx_FMT_TYPENAME, expected, obj_type_name); __Pyx_DECREF_TypeName(obj_type_name); return 0; } /////////////// RaiseUnboundLocalError.proto /////////////// static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname);/*proto*/ /////////////// RaiseUnboundLocalError /////////////// static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname) { PyErr_Format(PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", varname); } /////////////// RaiseClosureNameError.proto /////////////// static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname);/*proto*/ /////////////// RaiseClosureNameError /////////////// static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname) { PyErr_Format(PyExc_NameError, "free variable '%s' referenced before assignment in enclosing scope", varname); } /////////////// RaiseUnboundMemoryviewSliceNogil.proto /////////////// static void __Pyx_RaiseUnboundMemoryviewSliceNogil(const char *varname);/*proto*/ /////////////// RaiseUnboundMemoryviewSliceNogil /////////////// //@requires: RaiseUnboundLocalError // Don't inline the function, it should really never be called in production static void __Pyx_RaiseUnboundMemoryviewSliceNogil(const char *varname) { #ifdef WITH_THREAD PyGILState_STATE gilstate = PyGILState_Ensure(); #endif __Pyx_RaiseUnboundLocalError(varname); #ifdef WITH_THREAD PyGILState_Release(gilstate); #endif } //////////////// RaiseCppGlobalNameError.proto /////////////////////// static CYTHON_INLINE void __Pyx_RaiseCppGlobalNameError(const char *varname); /*proto*/ /////////////// RaiseCppGlobalNameError ////////////////////////////// static CYTHON_INLINE void __Pyx_RaiseCppGlobalNameError(const char *varname) { PyErr_Format(PyExc_NameError, "C++ global '%s' is not initialized", varname); } //////////////// RaiseCppAttributeError.proto /////////////////////// static CYTHON_INLINE void __Pyx_RaiseCppAttributeError(const char *varname); /*proto*/ /////////////// RaiseCppAttributeError ////////////////////////////// static CYTHON_INLINE void __Pyx_RaiseCppAttributeError(const char *varname) { PyErr_Format(PyExc_AttributeError, "C++ attribute '%s' is not initialized", varname); } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/Optimize.c0000644000175100001770000016714500000000000020465 0ustar00runnerdocker00000000000000/* * Optional optimisations of built-in functions and methods. * * Required replacements of builtins are in Builtins.c. * * General object operations and protocols are in ObjectHandling.c. */ /////////////// append.proto /////////////// static CYTHON_INLINE int __Pyx_PyObject_Append(PyObject* L, PyObject* x); /*proto*/ /////////////// append /////////////// //@requires: ListAppend //@requires: ObjectHandling.c::PyObjectCallMethod1 static CYTHON_INLINE int __Pyx_PyObject_Append(PyObject* L, PyObject* x) { if (likely(PyList_CheckExact(L))) { if (unlikely(__Pyx_PyList_Append(L, x) < 0)) return -1; } else { PyObject* retval = __Pyx_PyObject_CallMethod1(L, PYIDENT("append"), x); if (unlikely(!retval)) return -1; Py_DECREF(retval); } return 0; } /////////////// ListAppend.proto /////////////// #if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS static CYTHON_INLINE int __Pyx_PyList_Append(PyObject* list, PyObject* x) { PyListObject* L = (PyListObject*) list; Py_ssize_t len = Py_SIZE(list); if (likely(L->allocated > len) & likely(len > (L->allocated >> 1))) { Py_INCREF(x); #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030d0000 // In Py3.13a1, PyList_SET_ITEM() checks that the end index is lower than the current size. // However, extending the size *before* setting the value would not be correct, // so we cannot call PyList_SET_ITEM(). L->ob_item[len] = x; #else PyList_SET_ITEM(list, len, x); #endif __Pyx_SET_SIZE(list, len + 1); return 0; } return PyList_Append(list, x); } #else #define __Pyx_PyList_Append(L,x) PyList_Append(L,x) #endif /////////////// ListCompAppend.proto /////////////// #if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS static CYTHON_INLINE int __Pyx_ListComp_Append(PyObject* list, PyObject* x) { PyListObject* L = (PyListObject*) list; Py_ssize_t len = Py_SIZE(list); if (likely(L->allocated > len)) { Py_INCREF(x); #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030d0000 // In Py3.13a1, PyList_SET_ITEM() checks that the end index is lower than the current size. // However, extending the size *before* setting the value would not be correct, // so we cannot call PyList_SET_ITEM(). L->ob_item[len] = x; #else PyList_SET_ITEM(list, len, x); #endif __Pyx_SET_SIZE(list, len + 1); return 0; } return PyList_Append(list, x); } #else #define __Pyx_ListComp_Append(L,x) PyList_Append(L,x) #endif //////////////////// ListExtend.proto //////////////////// static CYTHON_INLINE int __Pyx_PyList_Extend(PyObject* L, PyObject* v) { #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030d0000 PyObject* none = _PyList_Extend((PyListObject*)L, v); if (unlikely(!none)) return -1; Py_DECREF(none); return 0; #else return PyList_SetSlice(L, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, v); #endif } /////////////// pop.proto /////////////// static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L); /*proto*/ #if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L); /*proto*/ #define __Pyx_PyObject_Pop(L) (likely(PyList_CheckExact(L)) ? \ __Pyx_PyList_Pop(L) : __Pyx__PyObject_Pop(L)) #else #define __Pyx_PyList_Pop(L) __Pyx__PyObject_Pop(L) #define __Pyx_PyObject_Pop(L) __Pyx__PyObject_Pop(L) #endif /////////////// pop /////////////// //@requires: ObjectHandling.c::PyObjectCallMethod0 static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L) { if (__Pyx_IS_TYPE(L, &PySet_Type)) { return PySet_Pop(L); } return __Pyx_PyObject_CallMethod0(L, PYIDENT("pop")); } #if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L) { /* Check that both the size is positive and no reallocation shrinking needs to be done. */ if (likely(PyList_GET_SIZE(L) > (((PyListObject*)L)->allocated >> 1))) { __Pyx_SET_SIZE(L, Py_SIZE(L) - 1); return PyList_GET_ITEM(L, PyList_GET_SIZE(L)); } return CALL_UNBOUND_METHOD(PyList_Type, "pop", L); } #endif /////////////// pop_index.proto /////////////// static PyObject* __Pyx__PyObject_PopNewIndex(PyObject* L, PyObject* py_ix); /*proto*/ static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix); /*proto*/ #if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS static PyObject* __Pyx__PyList_PopIndex(PyObject* L, PyObject* py_ix, Py_ssize_t ix); /*proto*/ #define __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) ( \ (likely(PyList_CheckExact(L) && __Pyx_fits_Py_ssize_t(ix, type, is_signed))) ? \ __Pyx__PyList_PopIndex(L, py_ix, ix) : ( \ (unlikely((py_ix) == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) : \ __Pyx__PyObject_PopIndex(L, py_ix))) #define __Pyx_PyList_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) ( \ __Pyx_fits_Py_ssize_t(ix, type, is_signed) ? \ __Pyx__PyList_PopIndex(L, py_ix, ix) : ( \ (unlikely((py_ix) == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) : \ __Pyx__PyObject_PopIndex(L, py_ix))) #else #define __Pyx_PyList_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) \ __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) #define __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) ( \ (unlikely((py_ix) == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) : \ __Pyx__PyObject_PopIndex(L, py_ix)) #endif /////////////// pop_index /////////////// //@requires: ObjectHandling.c::PyObjectCallMethod1 static PyObject* __Pyx__PyObject_PopNewIndex(PyObject* L, PyObject* py_ix) { PyObject *r; if (unlikely(!py_ix)) return NULL; r = __Pyx__PyObject_PopIndex(L, py_ix); Py_DECREF(py_ix); return r; } static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix) { return __Pyx_PyObject_CallMethod1(L, PYIDENT("pop"), py_ix); } #if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS static PyObject* __Pyx__PyList_PopIndex(PyObject* L, PyObject* py_ix, Py_ssize_t ix) { Py_ssize_t size = PyList_GET_SIZE(L); if (likely(size > (((PyListObject*)L)->allocated >> 1))) { Py_ssize_t cix = ix; if (cix < 0) { cix += size; } if (likely(__Pyx_is_valid_index(cix, size))) { PyObject* v = PyList_GET_ITEM(L, cix); __Pyx_SET_SIZE(L, Py_SIZE(L) - 1); size -= 1; memmove(&PyList_GET_ITEM(L, cix), &PyList_GET_ITEM(L, cix+1), (size_t)(size-cix)*sizeof(PyObject*)); return v; } } if (py_ix == Py_None) { return __Pyx__PyObject_PopNewIndex(L, PyInt_FromSsize_t(ix)); } else { return __Pyx__PyObject_PopIndex(L, py_ix); } } #endif /////////////// dict_getitem_default.proto /////////////// static PyObject* __Pyx_PyDict_GetItemDefault(PyObject* d, PyObject* key, PyObject* default_value); /*proto*/ /////////////// dict_getitem_default /////////////// static PyObject* __Pyx_PyDict_GetItemDefault(PyObject* d, PyObject* key, PyObject* default_value) { PyObject* value; #if PY_MAJOR_VERSION >= 3 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07020000) value = PyDict_GetItemWithError(d, key); if (unlikely(!value)) { if (unlikely(PyErr_Occurred())) return NULL; value = default_value; } Py_INCREF(value); // avoid C compiler warning about unused utility functions if ((1)); #else if (PyString_CheckExact(key) || PyUnicode_CheckExact(key) || PyInt_CheckExact(key)) { /* these presumably have safe hash functions */ value = PyDict_GetItem(d, key); if (unlikely(!value)) { value = default_value; } Py_INCREF(value); } #endif else { if (default_value == Py_None) value = CALL_UNBOUND_METHOD(PyDict_Type, "get", d, key); else value = CALL_UNBOUND_METHOD(PyDict_Type, "get", d, key, default_value); } return value; } /////////////// dict_setdefault.proto /////////////// static CYTHON_INLINE PyObject *__Pyx_PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *default_value, int is_safe_type); /*proto*/ /////////////// dict_setdefault /////////////// static CYTHON_INLINE PyObject *__Pyx_PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *default_value, int is_safe_type) { PyObject* value; CYTHON_MAYBE_UNUSED_VAR(is_safe_type); #if PY_VERSION_HEX >= 0x030400A0 // we keep the method call at the end to avoid "unused" C compiler warnings if ((1)) { value = PyDict_SetDefault(d, key, default_value); if (unlikely(!value)) return NULL; Py_INCREF(value); #else if (is_safe_type == 1 || (is_safe_type == -1 && /* the following builtins presumably have repeatably safe and fast hash functions */ #if PY_MAJOR_VERSION >= 3 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07020000) (PyUnicode_CheckExact(key) || PyString_CheckExact(key) || PyLong_CheckExact(key)))) { value = PyDict_GetItemWithError(d, key); if (unlikely(!value)) { if (unlikely(PyErr_Occurred())) return NULL; if (unlikely(PyDict_SetItem(d, key, default_value) == -1)) return NULL; value = default_value; } Py_INCREF(value); #else (PyString_CheckExact(key) || PyUnicode_CheckExact(key) || PyInt_CheckExact(key) || PyLong_CheckExact(key)))) { value = PyDict_GetItem(d, key); if (unlikely(!value)) { if (unlikely(PyDict_SetItem(d, key, default_value) == -1)) return NULL; value = default_value; } Py_INCREF(value); #endif #endif } else { value = CALL_UNBOUND_METHOD(PyDict_Type, "setdefault", d, key, default_value); } return value; } /////////////// py_dict_clear.proto /////////////// #define __Pyx_PyDict_Clear(d) (PyDict_Clear(d), 0) /////////////// py_dict_pop.proto /////////////// static CYTHON_INLINE PyObject *__Pyx_PyDict_Pop(PyObject *d, PyObject *key, PyObject *default_value); /*proto*/ /////////////// py_dict_pop /////////////// static CYTHON_INLINE PyObject *__Pyx_PyDict_Pop(PyObject *d, PyObject *key, PyObject *default_value) { #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX > 0x030600B3 & PY_VERSION_HEX < 0x030d0000 if ((1)) { return _PyDict_Pop(d, key, default_value); } else // avoid "function unused" warnings #endif if (default_value) { return CALL_UNBOUND_METHOD(PyDict_Type, "pop", d, key, default_value); } else { return CALL_UNBOUND_METHOD(PyDict_Type, "pop", d, key); } } /////////////// dict_iter.proto /////////////// static CYTHON_INLINE PyObject* __Pyx_dict_iterator(PyObject* dict, int is_dict, PyObject* method_name, Py_ssize_t* p_orig_length, int* p_is_dict); static CYTHON_INLINE int __Pyx_dict_iter_next(PyObject* dict_or_iter, Py_ssize_t orig_length, Py_ssize_t* ppos, PyObject** pkey, PyObject** pvalue, PyObject** pitem, int is_dict); /////////////// dict_iter /////////////// //@requires: ObjectHandling.c::UnpackTuple2 //@requires: ObjectHandling.c::IterFinish //@requires: ObjectHandling.c::PyObjectCallMethod0 #if CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 #include #endif static CYTHON_INLINE PyObject* __Pyx_dict_iterator(PyObject* iterable, int is_dict, PyObject* method_name, Py_ssize_t* p_orig_length, int* p_source_is_dict) { is_dict = is_dict || likely(PyDict_CheckExact(iterable)); *p_source_is_dict = is_dict; if (is_dict) { #if !CYTHON_COMPILING_IN_PYPY *p_orig_length = PyDict_Size(iterable); Py_INCREF(iterable); return iterable; #elif PY_MAJOR_VERSION >= 3 // On PyPy3, we need to translate manually a few method names. // This logic is not needed on CPython thanks to the fast case above. static PyObject *py_items = NULL, *py_keys = NULL, *py_values = NULL; PyObject **pp = NULL; if (method_name) { const char *name = PyUnicode_AsUTF8(method_name); if (strcmp(name, "iteritems") == 0) pp = &py_items; else if (strcmp(name, "iterkeys") == 0) pp = &py_keys; else if (strcmp(name, "itervalues") == 0) pp = &py_values; if (pp) { if (!*pp) { *pp = PyUnicode_FromString(name + 4); if (!*pp) return NULL; } method_name = *pp; } } #endif } *p_orig_length = 0; if (method_name) { PyObject* iter; iterable = __Pyx_PyObject_CallMethod0(iterable, method_name); if (!iterable) return NULL; #if !CYTHON_COMPILING_IN_PYPY if (PyTuple_CheckExact(iterable) || PyList_CheckExact(iterable)) return iterable; #endif iter = PyObject_GetIter(iterable); Py_DECREF(iterable); return iter; } return PyObject_GetIter(iterable); } static CYTHON_INLINE int __Pyx_dict_iter_next( PyObject* iter_obj, CYTHON_NCP_UNUSED Py_ssize_t orig_length, CYTHON_NCP_UNUSED Py_ssize_t* ppos, PyObject** pkey, PyObject** pvalue, PyObject** pitem, int source_is_dict) { PyObject* next_item; #if !CYTHON_COMPILING_IN_PYPY if (source_is_dict) { PyObject *key, *value; if (unlikely(orig_length != PyDict_Size(iter_obj))) { PyErr_SetString(PyExc_RuntimeError, "dictionary changed size during iteration"); return -1; } if (unlikely(!PyDict_Next(iter_obj, ppos, &key, &value))) { return 0; } if (pitem) { PyObject* tuple = PyTuple_New(2); if (unlikely(!tuple)) { return -1; } Py_INCREF(key); Py_INCREF(value); PyTuple_SET_ITEM(tuple, 0, key); PyTuple_SET_ITEM(tuple, 1, value); *pitem = tuple; } else { if (pkey) { Py_INCREF(key); *pkey = key; } if (pvalue) { Py_INCREF(value); *pvalue = value; } } return 1; } else if (PyTuple_CheckExact(iter_obj)) { Py_ssize_t pos = *ppos; if (unlikely(pos >= PyTuple_GET_SIZE(iter_obj))) return 0; *ppos = pos + 1; next_item = PyTuple_GET_ITEM(iter_obj, pos); Py_INCREF(next_item); } else if (PyList_CheckExact(iter_obj)) { Py_ssize_t pos = *ppos; if (unlikely(pos >= PyList_GET_SIZE(iter_obj))) return 0; *ppos = pos + 1; next_item = PyList_GET_ITEM(iter_obj, pos); Py_INCREF(next_item); } else #endif { next_item = PyIter_Next(iter_obj); if (unlikely(!next_item)) { return __Pyx_IterFinish(); } } if (pitem) { *pitem = next_item; } else if (pkey && pvalue) { if (__Pyx_unpack_tuple2(next_item, pkey, pvalue, source_is_dict, source_is_dict, 1)) return -1; } else if (pkey) { *pkey = next_item; } else { *pvalue = next_item; } return 1; } /////////////// set_iter.proto /////////////// static CYTHON_INLINE PyObject* __Pyx_set_iterator(PyObject* iterable, int is_set, Py_ssize_t* p_orig_length, int* p_source_is_set); /*proto*/ static CYTHON_INLINE int __Pyx_set_iter_next( PyObject* iter_obj, Py_ssize_t orig_length, Py_ssize_t* ppos, PyObject **value, int source_is_set); /*proto*/ /////////////// set_iter /////////////// //@requires: ObjectHandling.c::IterFinish static CYTHON_INLINE PyObject* __Pyx_set_iterator(PyObject* iterable, int is_set, Py_ssize_t* p_orig_length, int* p_source_is_set) { #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030d0000 is_set = is_set || likely(PySet_CheckExact(iterable) || PyFrozenSet_CheckExact(iterable)); *p_source_is_set = is_set; if (likely(is_set)) { *p_orig_length = PySet_Size(iterable); Py_INCREF(iterable); return iterable; } #else CYTHON_UNUSED_VAR(is_set); *p_source_is_set = 0; #endif *p_orig_length = 0; return PyObject_GetIter(iterable); } static CYTHON_INLINE int __Pyx_set_iter_next( PyObject* iter_obj, Py_ssize_t orig_length, Py_ssize_t* ppos, PyObject **value, int source_is_set) { if (!CYTHON_COMPILING_IN_CPYTHON || PY_VERSION_HEX >= 0x030d0000 || unlikely(!source_is_set)) { *value = PyIter_Next(iter_obj); if (unlikely(!*value)) { return __Pyx_IterFinish(); } CYTHON_UNUSED_VAR(orig_length); CYTHON_UNUSED_VAR(ppos); return 1; } #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030d0000 if (unlikely(PySet_GET_SIZE(iter_obj) != orig_length)) { PyErr_SetString( PyExc_RuntimeError, "set changed size during iteration"); return -1; } { Py_hash_t hash; int ret = _PySet_NextEntry(iter_obj, ppos, value, &hash); // CPython does not raise errors here, only if !isinstance(iter_obj, set/frozenset) assert (ret != -1); if (likely(ret)) { Py_INCREF(*value); return 1; } } #endif return 0; } /////////////// py_set_discard_unhashable /////////////// //@requires: Builtins.c::pyfrozenset_new static int __Pyx_PySet_DiscardUnhashable(PyObject *set, PyObject *key) { PyObject *tmpkey; int rv; if (likely(!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))) return -1; PyErr_Clear(); tmpkey = __Pyx_PyFrozenSet_New(key); if (tmpkey == NULL) return -1; rv = PySet_Discard(set, tmpkey); Py_DECREF(tmpkey); return rv; } /////////////// py_set_discard.proto /////////////// static CYTHON_INLINE int __Pyx_PySet_Discard(PyObject *set, PyObject *key); /*proto*/ /////////////// py_set_discard /////////////// //@requires: py_set_discard_unhashable static CYTHON_INLINE int __Pyx_PySet_Discard(PyObject *set, PyObject *key) { int found = PySet_Discard(set, key); // Convert *key* to frozenset if necessary if (unlikely(found < 0)) { found = __Pyx_PySet_DiscardUnhashable(set, key); } // note: returns -1 on error, 0 (not found) or 1 (found) otherwise => error check for -1 or < 0 works return found; } /////////////// py_set_remove.proto /////////////// static CYTHON_INLINE int __Pyx_PySet_Remove(PyObject *set, PyObject *key); /*proto*/ /////////////// py_set_remove /////////////// //@requires: py_set_discard_unhashable static int __Pyx_PySet_RemoveNotFound(PyObject *set, PyObject *key, int found) { // Convert *key* to frozenset if necessary if (unlikely(found < 0)) { found = __Pyx_PySet_DiscardUnhashable(set, key); } if (likely(found == 0)) { // Not found PyObject *tup; tup = PyTuple_Pack(1, key); if (!tup) return -1; PyErr_SetObject(PyExc_KeyError, tup); Py_DECREF(tup); return -1; } // note: returns -1 on error, 0 (not found) or 1 (found) otherwise => error check for -1 or < 0 works return found; } static CYTHON_INLINE int __Pyx_PySet_Remove(PyObject *set, PyObject *key) { int found = PySet_Discard(set, key); if (unlikely(found != 1)) { // note: returns -1 on error, 0 (not found) or 1 (found) otherwise => error check for -1 or < 0 works return __Pyx_PySet_RemoveNotFound(set, key, found); } return 0; } /////////////// unicode_iter.proto /////////////// static CYTHON_INLINE int __Pyx_init_unicode_iteration( PyObject* ustring, Py_ssize_t *length, void** data, int *kind); /* proto */ /////////////// unicode_iter /////////////// static CYTHON_INLINE int __Pyx_init_unicode_iteration( PyObject* ustring, Py_ssize_t *length, void** data, int *kind) { #if CYTHON_COMPILING_IN_LIMITED_API // In the limited API we just point data to the unicode object *kind = 0; *length = PyUnicode_GetLength(ustring); *data = (void*)ustring; #elif CYTHON_PEP393_ENABLED if (unlikely(__Pyx_PyUnicode_READY(ustring) < 0)) return -1; *kind = PyUnicode_KIND(ustring); *length = PyUnicode_GET_LENGTH(ustring); *data = PyUnicode_DATA(ustring); #else *kind = 0; *length = PyUnicode_GET_SIZE(ustring); *data = (void*)PyUnicode_AS_UNICODE(ustring); #endif return 0; } /////////////// pyobject_as_double.proto /////////////// static double __Pyx__PyObject_AsDouble(PyObject* obj); /* proto */ #if CYTHON_COMPILING_IN_PYPY #define __Pyx_PyObject_AsDouble(obj) \ (likely(PyFloat_CheckExact(obj)) ? PyFloat_AS_DOUBLE(obj) : \ likely(PyInt_CheckExact(obj)) ? \ PyFloat_AsDouble(obj) : __Pyx__PyObject_AsDouble(obj)) #else #define __Pyx_PyObject_AsDouble(obj) \ ((likely(PyFloat_CheckExact(obj))) ? PyFloat_AS_DOUBLE(obj) : \ likely(PyLong_CheckExact(obj)) ? \ PyLong_AsDouble(obj) : __Pyx__PyObject_AsDouble(obj)) #endif /////////////// pyobject_as_double /////////////// //@requires: pybytes_as_double //@requires: pyunicode_as_double //@requires: ObjectHandling.c::PyObjectCallOneArg static double __Pyx__PyObject_AsDouble(PyObject* obj) { if (PyUnicode_CheckExact(obj)) { return __Pyx_PyUnicode_AsDouble(obj); } else if (PyBytes_CheckExact(obj)) { return __Pyx_PyBytes_AsDouble(obj); } else if (PyByteArray_CheckExact(obj)) { return __Pyx_PyByteArray_AsDouble(obj); } else { PyObject* float_value; #if !CYTHON_USE_TYPE_SLOTS float_value = PyNumber_Float(obj); if ((0)) goto bad; // avoid "unused" warnings (void)__Pyx_PyObject_CallOneArg; #else PyNumberMethods *nb = Py_TYPE(obj)->tp_as_number; if (likely(nb) && likely(nb->nb_float)) { float_value = nb->nb_float(obj); if (likely(float_value) && unlikely(!PyFloat_Check(float_value))) { __Pyx_TypeName float_value_type_name = __Pyx_PyType_GetName(Py_TYPE(float_value)); PyErr_Format(PyExc_TypeError, "__float__ returned non-float (type " __Pyx_FMT_TYPENAME ")", float_value_type_name); __Pyx_DECREF_TypeName(float_value_type_name); Py_DECREF(float_value); goto bad; } } else { float_value = __Pyx_PyObject_CallOneArg((PyObject*)&PyFloat_Type, obj); } #endif if (likely(float_value)) { double value = PyFloat_AS_DOUBLE(float_value); Py_DECREF(float_value); return value; } } bad: return (double)-1; } /////////////// pystring_as_double.proto /////////////// //@requires: pyunicode_as_double //@requires: pybytes_as_double static CYTHON_INLINE double __Pyx_PyString_AsDouble(PyObject *obj) { #if PY_MAJOR_VERSION >= 3 (void)__Pyx_PyBytes_AsDouble; return __Pyx_PyUnicode_AsDouble(obj); #else (void)__Pyx_PyUnicode_AsDouble; return __Pyx_PyBytes_AsDouble(obj); #endif } /////////////// pyunicode_as_double.proto /////////////// static CYTHON_INLINE double __Pyx_PyUnicode_AsDouble(PyObject *obj);/*proto*/ /////////////// pyunicode_as_double.proto /////////////// //@requires: pybytes_as_double #if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY && CYTHON_ASSUME_SAFE_MACROS static const char* __Pyx__PyUnicode_AsDouble_Copy(const void* data, const int kind, char* buffer, Py_ssize_t start, Py_ssize_t end) { int last_was_punctuation; Py_ssize_t i; // number must not start with punctuation last_was_punctuation = 1; for (i=start; i <= end; i++) { Py_UCS4 chr = PyUnicode_READ(kind, data, i); int is_punctuation = (chr == '_') | (chr == '.'); *buffer = (char)chr; // reject sequences of '_' and '.' buffer += (chr != '_'); if (unlikely(chr > 127)) goto parse_failure; if (unlikely(last_was_punctuation & is_punctuation)) goto parse_failure; last_was_punctuation = is_punctuation; } if (unlikely(last_was_punctuation)) goto parse_failure; *buffer = '\0'; return buffer; parse_failure: return NULL; } static double __Pyx__PyUnicode_AsDouble_inf_nan(const void* data, int kind, Py_ssize_t start, Py_ssize_t length) { int matches = 1; Py_UCS4 chr; Py_UCS4 sign = PyUnicode_READ(kind, data, start); int is_signed = (sign == '-') | (sign == '+'); start += is_signed; length -= is_signed; switch (PyUnicode_READ(kind, data, start)) { #ifdef Py_NAN case 'n': case 'N': if (unlikely(length != 3)) goto parse_failure; chr = PyUnicode_READ(kind, data, start+1); matches &= (chr == 'a') | (chr == 'A'); chr = PyUnicode_READ(kind, data, start+2); matches &= (chr == 'n') | (chr == 'N'); if (unlikely(!matches)) goto parse_failure; return (sign == '-') ? -Py_NAN : Py_NAN; #endif case 'i': case 'I': if (unlikely(length < 3)) goto parse_failure; chr = PyUnicode_READ(kind, data, start+1); matches &= (chr == 'n') | (chr == 'N'); chr = PyUnicode_READ(kind, data, start+2); matches &= (chr == 'f') | (chr == 'F'); if (likely(length == 3 && matches)) return (sign == '-') ? -Py_HUGE_VAL : Py_HUGE_VAL; if (unlikely(length != 8)) goto parse_failure; chr = PyUnicode_READ(kind, data, start+3); matches &= (chr == 'i') | (chr == 'I'); chr = PyUnicode_READ(kind, data, start+4); matches &= (chr == 'n') | (chr == 'N'); chr = PyUnicode_READ(kind, data, start+5); matches &= (chr == 'i') | (chr == 'I'); chr = PyUnicode_READ(kind, data, start+6); matches &= (chr == 't') | (chr == 'T'); chr = PyUnicode_READ(kind, data, start+7); matches &= (chr == 'y') | (chr == 'Y'); if (unlikely(!matches)) goto parse_failure; return (sign == '-') ? -Py_HUGE_VAL : Py_HUGE_VAL; case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': break; default: goto parse_failure; } return 0.0; parse_failure: return -1.0; } static double __Pyx_PyUnicode_AsDouble_WithSpaces(PyObject *obj) { double value; const char *last; char *end; Py_ssize_t start, length = PyUnicode_GET_LENGTH(obj); const int kind = PyUnicode_KIND(obj); const void* data = PyUnicode_DATA(obj); // strip spaces at start and end start = 0; while (Py_UNICODE_ISSPACE(PyUnicode_READ(kind, data, start))) start++; while (start < length - 1 && Py_UNICODE_ISSPACE(PyUnicode_READ(kind, data, length - 1))) length--; length -= start; if (unlikely(length <= 0)) goto fallback; // parse NaN / inf value = __Pyx__PyUnicode_AsDouble_inf_nan(data, kind, start, length); if (unlikely(value == -1.0)) goto fallback; if (value != 0.0) return value; if (length < 40) { char number[40]; last = __Pyx__PyUnicode_AsDouble_Copy(data, kind, number, start, start + length); if (unlikely(!last)) goto fallback; value = PyOS_string_to_double(number, &end, NULL); } else { char *number = (char*) PyMem_Malloc((length + 1) * sizeof(char)); if (unlikely(!number)) goto fallback; last = __Pyx__PyUnicode_AsDouble_Copy(data, kind, number, start, start + length); if (unlikely(!last)) { PyMem_Free(number); goto fallback; } value = PyOS_string_to_double(number, &end, NULL); PyMem_Free(number); } if (likely(end == last) || (value == (double)-1 && PyErr_Occurred())) { return value; } fallback: return __Pyx_SlowPyString_AsDouble(obj); } #endif static CYTHON_INLINE double __Pyx_PyUnicode_AsDouble(PyObject *obj) { // Currently not optimised for Py2.7. #if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY && CYTHON_ASSUME_SAFE_MACROS if (unlikely(__Pyx_PyUnicode_READY(obj) == -1)) return (double)-1; if (likely(PyUnicode_IS_ASCII(obj))) { const char *s; Py_ssize_t length; s = PyUnicode_AsUTF8AndSize(obj, &length); return __Pyx__PyBytes_AsDouble(obj, s, length); } return __Pyx_PyUnicode_AsDouble_WithSpaces(obj); #else return __Pyx_SlowPyString_AsDouble(obj); #endif } /////////////// pybytes_as_double.proto /////////////// static double __Pyx_SlowPyString_AsDouble(PyObject *obj);/*proto*/ static double __Pyx__PyBytes_AsDouble(PyObject *obj, const char* start, Py_ssize_t length);/*proto*/ static CYTHON_INLINE double __Pyx_PyBytes_AsDouble(PyObject *obj) { char* as_c_string; Py_ssize_t size; #if CYTHON_ASSUME_SAFE_MACROS as_c_string = PyBytes_AS_STRING(obj); size = PyBytes_GET_SIZE(obj); #else if (PyBytes_AsStringAndSize(obj, &as_c_string, &size) < 0) { return (double)-1; } #endif return __Pyx__PyBytes_AsDouble(obj, as_c_string, size); } static CYTHON_INLINE double __Pyx_PyByteArray_AsDouble(PyObject *obj) { char* as_c_string; Py_ssize_t size; #if CYTHON_ASSUME_SAFE_MACROS as_c_string = PyByteArray_AS_STRING(obj); size = PyByteArray_GET_SIZE(obj); #else as_c_string = PyByteArray_AsString(obj); if (as_c_string == NULL) { return (double)-1; } size = PyByteArray_Size(obj); #endif return __Pyx__PyBytes_AsDouble(obj, as_c_string, size); } /////////////// pybytes_as_double /////////////// static double __Pyx_SlowPyString_AsDouble(PyObject *obj) { PyObject *float_value; #if PY_MAJOR_VERSION >= 3 float_value = PyFloat_FromString(obj); #else float_value = PyFloat_FromString(obj, 0); #endif if (likely(float_value)) { #if CYTHON_ASSUME_SAFE_MACROS double value = PyFloat_AS_DOUBLE(float_value); #else double value = PyFloat_AsDouble(float_value); #endif Py_DECREF(float_value); return value; } return (double)-1; } static const char* __Pyx__PyBytes_AsDouble_Copy(const char* start, char* buffer, Py_ssize_t length) { // number must not start with punctuation int last_was_punctuation = 1; Py_ssize_t i; for (i=0; i < length; i++) { char chr = start[i]; int is_punctuation = (chr == '_') | (chr == '.') | (chr == 'e') | (chr == 'E'); *buffer = chr; buffer += (chr != '_'); // reject sequences of '_' and '.' if (unlikely(last_was_punctuation & is_punctuation)) goto parse_failure; last_was_punctuation = is_punctuation; } if (unlikely(last_was_punctuation)) goto parse_failure; *buffer = '\0'; return buffer; parse_failure: return NULL; } static double __Pyx__PyBytes_AsDouble_inf_nan(const char* start, Py_ssize_t length) { int matches = 1; char sign = start[0]; int is_signed = (sign == '+') | (sign == '-'); start += is_signed; length -= is_signed; switch (start[0]) { #ifdef Py_NAN case 'n': case 'N': if (unlikely(length != 3)) goto parse_failure; matches &= (start[1] == 'a' || start[1] == 'A'); matches &= (start[2] == 'n' || start[2] == 'N'); if (unlikely(!matches)) goto parse_failure; return (sign == '-') ? -Py_NAN : Py_NAN; #endif case 'i': case 'I': if (unlikely(length < 3)) goto parse_failure; matches &= (start[1] == 'n' || start[1] == 'N'); matches &= (start[2] == 'f' || start[2] == 'F'); if (likely(length == 3 && matches)) return (sign == '-') ? -Py_HUGE_VAL : Py_HUGE_VAL; if (unlikely(length != 8)) goto parse_failure; matches &= (start[3] == 'i' || start[3] == 'I'); matches &= (start[4] == 'n' || start[4] == 'N'); matches &= (start[5] == 'i' || start[5] == 'I'); matches &= (start[6] == 't' || start[6] == 'T'); matches &= (start[7] == 'y' || start[7] == 'Y'); if (unlikely(!matches)) goto parse_failure; return (sign == '-') ? -Py_HUGE_VAL : Py_HUGE_VAL; case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': break; default: goto parse_failure; } return 0.0; parse_failure: return -1.0; } static CYTHON_INLINE int __Pyx__PyBytes_AsDouble_IsSpace(char ch) { // see Py_ISSPACE() in CPython // https://github.com/python/cpython/blob/master/Python/pyctype.c return (ch == 0x20) | !((ch < 0x9) | (ch > 0xd)); } CYTHON_UNUSED static double __Pyx__PyBytes_AsDouble(PyObject *obj, const char* start, Py_ssize_t length) { double value; Py_ssize_t i, digits; const char *last = start + length; char *end; // strip spaces at start and end while (__Pyx__PyBytes_AsDouble_IsSpace(*start)) start++; while (start < last - 1 && __Pyx__PyBytes_AsDouble_IsSpace(last[-1])) last--; length = last - start; if (unlikely(length <= 0)) goto fallback; // parse NaN / inf value = __Pyx__PyBytes_AsDouble_inf_nan(start, length); if (unlikely(value == -1.0)) goto fallback; if (value != 0.0) return value; // look for underscores digits = 0; for (i=0; i < length; digits += start[i++] != '_'); if (likely(digits == length)) { value = PyOS_string_to_double(start, &end, NULL); } else if (digits < 40) { char number[40]; last = __Pyx__PyBytes_AsDouble_Copy(start, number, length); if (unlikely(!last)) goto fallback; value = PyOS_string_to_double(number, &end, NULL); } else { char *number = (char*) PyMem_Malloc((digits + 1) * sizeof(char)); if (unlikely(!number)) goto fallback; last = __Pyx__PyBytes_AsDouble_Copy(start, number, length); if (unlikely(!last)) { PyMem_Free(number); goto fallback; } value = PyOS_string_to_double(number, &end, NULL); PyMem_Free(number); } if (likely(end == last) || (value == (double)-1 && PyErr_Occurred())) { return value; } fallback: return __Pyx_SlowPyString_AsDouble(obj); } /////////////// PyNumberPow2.proto /////////////// #define __Pyx_PyNumber_InPlacePowerOf2(a, b, c) __Pyx__PyNumber_PowerOf2(a, b, c, 1) #define __Pyx_PyNumber_PowerOf2(a, b, c) __Pyx__PyNumber_PowerOf2(a, b, c, 0) static PyObject* __Pyx__PyNumber_PowerOf2(PyObject *two, PyObject *exp, PyObject *none, int inplace); /*proto*/ /////////////// PyNumberPow2 /////////////// static PyObject* __Pyx__PyNumber_PowerOf2(PyObject *two, PyObject *exp, PyObject *none, int inplace) { // in CPython, 1<= 0)) { if ((size_t)shiftby <= sizeof(long) * 8 - 2) { long value = 1L << shiftby; return PyInt_FromLong(value); #ifdef HAVE_LONG_LONG } else if ((size_t)shiftby <= sizeof(unsigned PY_LONG_LONG) * 8 - 1) { unsigned PY_LONG_LONG value = ((unsigned PY_LONG_LONG)1) << shiftby; return PyLong_FromUnsignedLongLong(value); #endif } else { PyObject *result, *one = PyInt_FromLong(1L); if (unlikely(!one)) return NULL; result = PyNumber_Lshift(one, exp); Py_DECREF(one); return result; } } else if (shiftby == -1 && PyErr_Occurred()) { PyErr_Clear(); } fallback: #endif return (inplace ? PyNumber_InPlacePower : PyNumber_Power)(two, exp, none); } /////////////// PyIntCompare.proto /////////////// {{py: c_ret_type = 'PyObject*' if ret_type.is_pyobject else 'int'}} static CYTHON_INLINE {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(PyObject *op1, PyObject *op2, long intval, long inplace); /*proto*/ /////////////// PyIntCompare /////////////// {{py: pyval, ival = ('op2', 'b') if order == 'CObj' else ('op1', 'a') }} {{py: c_ret_type = 'PyObject*' if ret_type.is_pyobject else 'int'}} {{py: return_true = 'Py_RETURN_TRUE' if ret_type.is_pyobject else 'return 1'}} {{py: return_false = 'Py_RETURN_FALSE' if ret_type.is_pyobject else 'return 0'}} {{py: slot_name = op.lower() }} {{py: c_op = {'Eq': '==', 'Ne': '!='}[op] }} {{py: return_compare = ( (lambda a,b,c_op, return_true=return_true, return_false=return_false: "if ({a} {c_op} {b}) {return_true}; else {return_false};".format( a=a, b=b, c_op=c_op, return_true=return_true, return_false=return_false)) if ret_type.is_pyobject else (lambda a,b,c_op: "return ({a} {c_op} {b});".format(a=a, b=b, c_op=c_op)) ) }} static CYTHON_INLINE {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(PyObject *op1, PyObject *op2, long intval, long inplace) { CYTHON_MAYBE_UNUSED_VAR(intval); CYTHON_UNUSED_VAR(inplace); if (op1 == op2) { {{return_true if op == 'Eq' else return_false}}; } #if PY_MAJOR_VERSION < 3 if (likely(PyInt_CheckExact({{pyval}}))) { const long {{'a' if order == 'CObj' else 'b'}} = intval; long {{ival}} = PyInt_AS_LONG({{pyval}}); {{return_compare('a', 'b', c_op)}} } #endif #if CYTHON_USE_PYLONG_INTERNALS if (likely(PyLong_CheckExact({{pyval}}))) { int unequal; unsigned long uintval; Py_ssize_t size = __Pyx_PyLong_DigitCount({{pyval}}); const digit* digits = __Pyx_PyLong_Digits({{pyval}}); if (intval == 0) { {{return_compare('__Pyx_PyLong_IsZero(%s)' % pyval, '1', c_op)}} } else if (intval < 0) { if (__Pyx_PyLong_IsNonNeg({{pyval}})) {{return_false if op == 'Eq' else return_true}}; // both are negative => can use absolute values now. intval = -intval; } else { // > 0 => Py_SIZE(pyval) > 0 if (__Pyx_PyLong_IsNeg({{pyval}})) {{return_false if op == 'Eq' else return_true}}; } // After checking that the sign is the same (and excluding 0), now compare the absolute values. // When inlining, the C compiler should select exactly one line from this unrolled loop. uintval = (unsigned long) intval; {{for _size in range(4, 0, -1)}} #if PyLong_SHIFT * {{_size}} < SIZEOF_LONG*8 if (uintval >> (PyLong_SHIFT * {{_size}})) { // The C integer value is between (PyLong_BASE ** _size) and MIN(PyLong_BASE ** _size, LONG_MAX). unequal = (size != {{_size+1}}) || (digits[0] != (uintval & (unsigned long) PyLong_MASK)) {{for _i in range(1, _size+1)}} | (digits[{{_i}}] != ((uintval >> ({{_i}} * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)){{endfor}}; } else #endif {{endfor}} unequal = (size != 1) || (((unsigned long) digits[0]) != (uintval & (unsigned long) PyLong_MASK)); {{return_compare('unequal', '0', c_op)}} } #endif if (PyFloat_CheckExact({{pyval}})) { const long {{'a' if order == 'CObj' else 'b'}} = intval; #if CYTHON_COMPILING_IN_LIMITED_API double {{ival}} = __pyx_PyFloat_AsDouble({{pyval}}); #else double {{ival}} = PyFloat_AS_DOUBLE({{pyval}}); #endif {{return_compare('(double)a', '(double)b', c_op)}} } return {{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}( PyObject_RichCompare(op1, op2, Py_{{op.upper()}})); } /////////////// PyIntBinop.proto /////////////// {{py: c_ret_type = 'PyObject*' if ret_type.is_pyobject else 'int'}} #if !CYTHON_COMPILING_IN_PYPY static {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check); /*proto*/ #else #define __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(op1, op2, intval, inplace, zerodivision_check) \ {{if op in ('Eq', 'Ne')}}{{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}(PyObject_RichCompare(op1, op2, Py_{{op.upper()}})) {{else}}(inplace ? PyNumber_InPlace{{op}}(op1, op2) : PyNumber_{{op}}(op1, op2)) {{endif}} #endif /////////////// PyIntBinop /////////////// #if !CYTHON_COMPILING_IN_PYPY {{py: from Cython.Utility import pylong_join }} {{py: pyval, ival = ('op2', 'b') if order == 'CObj' else ('op1', 'a') }} {{py: c_ret_type = 'PyObject*' if ret_type.is_pyobject else 'int'}} {{py: return_true = 'Py_RETURN_TRUE' if ret_type.is_pyobject else 'return 1'}} {{py: return_false = 'Py_RETURN_FALSE' if ret_type.is_pyobject else 'return 0'}} {{py: slot_name = {'TrueDivide': 'true_divide', 'FloorDivide': 'floor_divide'}.get(op, op.lower()) }} {{py: cfunc_name = '__Pyx_PyInt_%s%s%s' % ('' if ret_type.is_pyobject else 'Bool', op, order)}} {{py: c_op = { 'Add': '+', 'Subtract': '-', 'Multiply': '*', 'Remainder': '%', 'TrueDivide': '/', 'FloorDivide': '/', 'Or': '|', 'Xor': '^', 'And': '&', 'Rshift': '>>', 'Lshift': '<<', 'Eq': '==', 'Ne': '!=', }[op] }} {{py: def zerodiv_check(operand, optype='integer', _is_mod=op == 'Remainder', _needs_check=(order == 'CObj' and c_op in '%/')): return ((( 'if (unlikely(zerodivision_check && ((%s) == 0))) {' ' PyErr_SetString(PyExc_ZeroDivisionError, "%s division%s by zero");' ' return NULL;' '}') % (operand, optype, ' or modulo' if _is_mod else '') ) if _needs_check else '') }} static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check) { CYTHON_MAYBE_UNUSED_VAR(intval); CYTHON_MAYBE_UNUSED_VAR(inplace); CYTHON_UNUSED_VAR(zerodivision_check); {{if op in ('Eq', 'Ne')}} if (op1 == op2) { {{return_true if op == 'Eq' else return_false}}; } {{endif}} #if PY_MAJOR_VERSION < 3 if (likely(PyInt_CheckExact({{pyval}}))) { const long {{'a' if order == 'CObj' else 'b'}} = intval; {{if c_op in '+-%' or op == 'FloorDivide'}} long x; {{endif}} long {{ival}} = PyInt_AS_LONG({{pyval}}); {{zerodiv_check('b')}} {{if op in ('Eq', 'Ne')}} if (a {{c_op}} b) { {{return_true}}; } else { {{return_false}}; } {{elif c_op in '+-'}} // adapted from intobject.c in Py2.7: // casts in the line below avoid undefined behaviour on overflow x = (long)((unsigned long)a {{c_op}} (unsigned long)b); if (likely((x^a) >= 0 || (x^{{ '~' if op == 'Subtract' else '' }}b) >= 0)) return PyInt_FromLong(x); return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2); {{elif c_op == '%'}} // see CMath.c :: ModInt utility code x = a % b; x += ((x != 0) & ((x ^ b) < 0)) * b; return PyInt_FromLong(x); {{elif op == 'TrueDivide'}} if (8 * sizeof(long) <= 53 || likely(labs({{ival}}) <= ((PY_LONG_LONG)1 << 53))) { return PyFloat_FromDouble((double)a / (double)b); } // let Python do the rounding return PyInt_Type.tp_as_number->nb_{{slot_name}}(op1, op2); {{elif op == 'FloorDivide'}} // INT_MIN / -1 is the only case that overflows if (unlikely(b == -1 && ((unsigned long)a) == 0-(unsigned long)a)) return PyInt_Type.tp_as_number->nb_{{slot_name}}(op1, op2); else { long q, r; // see CMath.c :: DivInt utility code q = a / b; r = a - q*b; q -= ((r != 0) & ((r ^ b) < 0)); x = q; } return PyInt_FromLong(x); {{elif op == 'Lshift'}} if (likely(b < (long) (sizeof(long)*8) && a == (a << b) >> b) || !a) { return PyInt_FromLong(a {{c_op}} b); } {{elif c_op == '*'}} #ifdef HAVE_LONG_LONG if (sizeof(PY_LONG_LONG) > sizeof(long)) { PY_LONG_LONG result = (PY_LONG_LONG)a {{c_op}} (PY_LONG_LONG)b; return (result >= LONG_MIN && result <= LONG_MAX) ? PyInt_FromLong((long)result) : PyLong_FromLongLong(result); } #endif #if CYTHON_USE_TYPE_SLOTS return PyInt_Type.tp_as_number->nb_{{slot_name}}(op1, op2); #else return PyNumber_{{op}}(op1, op2); #endif {{else}} // other operations are safe, no overflow return PyInt_FromLong(a {{c_op}} b); {{endif}} } #endif #if CYTHON_USE_PYLONG_INTERNALS if (likely(PyLong_CheckExact({{pyval}}))) { const long {{'a' if order == 'CObj' else 'b'}} = intval; long {{ival}}{{if op not in ('Eq', 'Ne')}}, x{{endif}}; {{if op not in ('Eq', 'Ne', 'TrueDivide')}} #ifdef HAVE_LONG_LONG const PY_LONG_LONG ll{{'a' if order == 'CObj' else 'b'}} = intval; PY_LONG_LONG ll{{ival}}, llx; #endif {{endif}} {{if c_op == '&'}} // special case for &-ing arbitrarily large numbers with known single digit operands if ((intval & PyLong_MASK) == intval) { // Calling PyLong_CompactValue() requires the PyLong value to be compact, we only need the last digit. long last_digit = (long) __Pyx_PyLong_Digits({{pyval}})[0]; long result = intval & (likely(__Pyx_PyLong_IsPos({{pyval}})) ? last_digit : (PyLong_MASK - last_digit + 1)); return PyLong_FromLong(result); } {{endif}} // special cases for 0: + - * % / // | ^ & >> << if (unlikely(__Pyx_PyLong_IsZero({{pyval}}))) { {{if order == 'CObj' and c_op in '%/'}} // division by zero! {{zerodiv_check('0')}} {{elif order == 'CObj' and c_op in '+-|^>><<'}} // x == x+0 == x-0 == x|0 == x^0 == x>>0 == x<<0 return __Pyx_NewRef(op1); {{elif order == 'CObj' and c_op in '*&'}} // 0 == x*0 == x&0 return __Pyx_NewRef(op2); {{elif order == 'ObjC' and c_op in '+|^'}} // x == 0+x == 0|x == 0^x return __Pyx_NewRef(op2); {{elif order == 'ObjC' and c_op == '-'}} // -x == 0-x return PyLong_FromLong(-intval); {{elif order == 'ObjC' and (c_op in '*%&>><<' or op == 'FloorDivide')}} // 0 == 0*x == 0%x == 0&x == 0>>x == 0< {{_size}} * PyLong_SHIFT{{if c_op == '*'}}+30{{endif}}{{if op == 'TrueDivide'}} && {{_size-1}} * PyLong_SHIFT < 53{{endif}}) { {{ival}} = {{'-' if _case < 0 else ''}}(long) {{pylong_join(_size, 'digits')}}; break; {{if op not in ('Eq', 'Ne', 'TrueDivide')}} #ifdef HAVE_LONG_LONG } else if (8 * sizeof(PY_LONG_LONG) - 1 > {{_size}} * PyLong_SHIFT{{if c_op == '*'}}+30{{endif}}) { ll{{ival}} = {{'-' if _case < 0 else ''}}(PY_LONG_LONG) {{pylong_join(_size, 'digits', 'unsigned PY_LONG_LONG')}}; goto long_long; #endif {{endif}} } // if size doesn't fit into a long or PY_LONG_LONG anymore, fall through to default CYTHON_FALLTHROUGH; {{endfor}} {{endfor}} {{if op in ('Eq', 'Ne')}} #if PyLong_SHIFT < 30 && PyLong_SHIFT != 15 // unusual setup - your fault default: return {{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}( PyLong_Type.tp_richcompare({{'op1, op2' if order == 'ObjC' else 'op2, op1'}}, Py_{{op.upper()}})); #else // too large for the long values we allow => definitely not equal default: {{return_false if op == 'Eq' else return_true}}; #endif {{else}} default: return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2); {{endif}} } } {{if op in ('Eq', 'Ne')}} if (a {{c_op}} b) { {{return_true}}; } else { {{return_false}}; } {{else}} {{if c_op == '*'}} CYTHON_UNUSED_VAR(a); CYTHON_UNUSED_VAR(b); #ifdef HAVE_LONG_LONG ll{{ival}} = {{ival}}; goto long_long; #else return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2); #endif {{elif c_op == '%'}} // see CMath.c :: ModInt utility code x = a % b; x += ((x != 0) & ((x ^ b) < 0)) * b; {{elif op == 'TrueDivide'}} if ((8 * sizeof(long) <= 53 || likely(labs({{ival}}) <= ((PY_LONG_LONG)1 << 53))) || __Pyx_PyLong_DigitCount({{pyval}}) <= 52 / PyLong_SHIFT) { return PyFloat_FromDouble((double)a / (double)b); } return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2); {{elif op == 'FloorDivide'}} { long q, r; // see CMath.c :: DivInt utility code q = a / b; r = a - q*b; q -= ((r != 0) & ((r ^ b) < 0)); x = q; } {{else}} x = a {{c_op}} b; {{if op == 'Lshift'}} #ifdef HAVE_LONG_LONG if (unlikely(!(b < (long) (sizeof(long)*8) && a == x >> b)) && a) { ll{{ival}} = {{ival}}; goto long_long; } #else if (likely(b < (long) (sizeof(long)*8) && a == x >> b) || !a) /* execute return statement below */ #endif {{endif}} {{endif}} return PyLong_FromLong(x); {{if op != 'TrueDivide'}} #ifdef HAVE_LONG_LONG long_long: {{if c_op == '%'}} // see CMath.c :: ModInt utility code llx = lla % llb; llx += ((llx != 0) & ((llx ^ llb) < 0)) * llb; {{elif op == 'FloorDivide'}} { PY_LONG_LONG q, r; // see CMath.c :: DivInt utility code q = lla / llb; r = lla - q*llb; q -= ((r != 0) & ((r ^ llb) < 0)); llx = q; } {{else}} llx = lla {{c_op}} llb; {{if op == 'Lshift'}} if (likely(lla == llx >> llb)) /* then execute 'return' below */ {{endif}} {{endif}} return PyLong_FromLongLong(llx); #endif {{endif}}{{# if op != 'TrueDivide' #}} {{endif}}{{# if op in ('Eq', 'Ne') #}} } #endif {{if c_op in '+-*' or op in ('TrueDivide', 'Eq', 'Ne')}} if (PyFloat_CheckExact({{pyval}})) { const long {{'a' if order == 'CObj' else 'b'}} = intval; #if CYTHON_COMPILING_IN_LIMITED_API double {{ival}} = __pyx_PyFloat_AsDouble({{pyval}}); #else double {{ival}} = PyFloat_AS_DOUBLE({{pyval}}); #endif {{if op in ('Eq', 'Ne')}} if ((double)a {{c_op}} (double)b) { {{return_true}}; } else { {{return_false}}; } {{else}} double result; {{zerodiv_check('b', 'float')}} // copied from floatobject.c in Py3.5: PyFPE_START_PROTECT("{{op.lower() if not op.endswith('Divide') else 'divide'}}", return NULL) result = ((double)a) {{c_op}} (double)b; PyFPE_END_PROTECT(result) return PyFloat_FromDouble(result); {{endif}} } {{endif}} {{if op in ('Eq', 'Ne')}} return {{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}( PyObject_RichCompare(op1, op2, Py_{{op.upper()}})); {{else}} return (inplace ? PyNumber_InPlace{{op}} : PyNumber_{{op}})(op1, op2); {{endif}} } #endif /////////////// PyFloatBinop.proto /////////////// {{py: c_ret_type = 'PyObject*' if ret_type.is_pyobject else 'int'}} #if !CYTHON_COMPILING_IN_PYPY static {{c_ret_type}} __Pyx_PyFloat_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(PyObject *op1, PyObject *op2, double floatval, int inplace, int zerodivision_check); /*proto*/ #else #define __Pyx_PyFloat_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(op1, op2, floatval, inplace, zerodivision_check) \ {{if op in ('Eq', 'Ne')}}{{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}(PyObject_RichCompare(op1, op2, Py_{{op.upper()}})) {{elif op == 'Divide'}}((inplace ? __Pyx_PyNumber_InPlaceDivide(op1, op2) : __Pyx_PyNumber_Divide(op1, op2))) {{else}}(inplace ? PyNumber_InPlace{{op}}(op1, op2) : PyNumber_{{op}}(op1, op2)) {{endif}} #endif /////////////// PyFloatBinop /////////////// #if !CYTHON_COMPILING_IN_PYPY {{py: from Cython.Utility import pylong_join }} {{py: c_ret_type = 'PyObject*' if ret_type.is_pyobject else 'int'}} {{py: return_true = 'Py_RETURN_TRUE' if ret_type.is_pyobject else 'return 1'}} {{py: return_false = 'Py_RETURN_FALSE' if ret_type.is_pyobject else 'return 0'}} {{py: pyval, fval = ('op2', 'b') if order == 'CObj' else ('op1', 'a') }} {{py: cfunc_name = '__Pyx_PyFloat_%s%s%s' % ('' if ret_type.is_pyobject else 'Bool', op, order) }} {{py: c_op = { 'Add': '+', 'Subtract': '-', 'TrueDivide': '/', 'Divide': '/', 'Remainder': '%', 'Eq': '==', 'Ne': '!=', }[op] }} {{py: def zerodiv_check(operand, _is_mod=op == 'Remainder', _needs_check=(order == 'CObj' and c_op in '%/')): return ((( 'if (unlikely(zerodivision_check && ((%s) == 0.0))) {' ' PyErr_SetString(PyExc_ZeroDivisionError, "float division%s by zero");' ' return NULL;' '}') % (operand, ' or modulo' if _is_mod else '') ) if _needs_check else '') }} static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, double floatval, int inplace, int zerodivision_check) { const double {{'a' if order == 'CObj' else 'b'}} = floatval; double {{fval}}{{if op not in ('Eq', 'Ne')}}, result{{endif}}; CYTHON_UNUSED_VAR(inplace); CYTHON_UNUSED_VAR(zerodivision_check); {{if op in ('Eq', 'Ne')}} if (op1 == op2) { {{return_true if op == 'Eq' else return_false}}; } {{endif}} if (likely(PyFloat_CheckExact({{pyval}}))) { #if CYTHON_COMPILING_IN_LIMITED_API {{fval}} = __pyx_PyFloat_AsDouble({{pyval}}); #else {{fval}} = PyFloat_AS_DOUBLE({{pyval}}); #endif {{zerodiv_check(fval)}} } else #if PY_MAJOR_VERSION < 3 if (likely(PyInt_CheckExact({{pyval}}))) { {{fval}} = (double) PyInt_AS_LONG({{pyval}}); {{zerodiv_check(fval)}} } else #endif if (likely(PyLong_CheckExact({{pyval}}))) { #if CYTHON_USE_PYLONG_INTERNALS if (__Pyx_PyLong_IsZero({{pyval}})) { {{fval}} = 0.0; {{zerodiv_check(fval)}} } else if (__Pyx_PyLong_IsCompact({{pyval}})) { {{fval}} = (double) __Pyx_PyLong_CompactValue({{pyval}}); } else { const digit* digits = __Pyx_PyLong_Digits({{pyval}}); const Py_ssize_t size = __Pyx_PyLong_SignedDigitCount({{pyval}}); switch (size) { {{for _size in (2, 3, 4)}} case -{{_size}}: case {{_size}}: if (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT && ((8 * sizeof(unsigned long) < 53) || ({{_size-1}} * PyLong_SHIFT < 53))) { {{fval}} = (double) {{pylong_join(_size, 'digits')}}; // let CPython do its own float rounding from 2**53 on (max. consecutive integer in double float) if ((8 * sizeof(unsigned long) < 53) || ({{_size}} * PyLong_SHIFT < 53) || ({{fval}} < (double) ((PY_LONG_LONG)1 << 53))) { if (size == {{-_size}}) {{fval}} = -{{fval}}; break; } } // Fall through if size doesn't fit safely into a double anymore. // It may not be obvious that this is a safe fall-through given the "fval < 2**53" // check above. However, the number of digits that CPython uses for a given PyLong // value is minimal, and together with the "(size-1) * SHIFT < 53" check above, // this should make it safe. CYTHON_FALLTHROUGH; {{endfor}} default: #endif {{if op in ('Eq', 'Ne')}} return {{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}( PyFloat_Type.tp_richcompare({{'op1, op2' if order == 'CObj' else 'op2, op1'}}, Py_{{op.upper()}})); {{else}} {{fval}} = PyLong_AsDouble({{pyval}}); if (unlikely({{fval}} == -1.0 && PyErr_Occurred())) return NULL; {{if zerodiv_check(fval)}} #if !CYTHON_USE_PYLONG_INTERNALS {{zerodiv_check(fval)}} #endif {{endif}} {{endif}} #if CYTHON_USE_PYLONG_INTERNALS } } #endif } else { {{if op in ('Eq', 'Ne')}} return {{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}( PyObject_RichCompare(op1, op2, Py_{{op.upper()}})); {{elif op == 'Divide'}} return (inplace ? __Pyx_PyNumber_InPlaceDivide(op1, op2) : __Pyx_PyNumber_Divide(op1, op2)); {{else}} return (inplace ? PyNumber_InPlace{{op}} : PyNumber_{{op}})(op1, op2); {{endif}} } {{if op in ('Eq', 'Ne')}} if (a {{c_op}} b) { {{return_true}}; } else { {{return_false}}; } {{else}} // copied from floatobject.c in Py3.5: PyFPE_START_PROTECT("{{op.lower() if not op.endswith('Divide') else 'divide'}}", return NULL) {{if c_op == '%'}} result = fmod(a, b); if (result) result += ((result < 0) ^ (b < 0)) * b; else result = copysign(0.0, b); {{else}} result = a {{c_op}} b; {{endif}} PyFPE_END_PROTECT(result) return PyFloat_FromDouble(result); {{endif}} } #endif ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/Overflow.c0000644000175100001770000003700200000000000020454 0ustar00runnerdocker00000000000000/* These functions provide integer arithmetic with integer checking. They do not actually raise an exception when an overflow is detected, but rather set a bit in the overflow parameter. (This parameter may be re-used across several arithmetic operations, so should be or-ed rather than assigned to.) The implementation is divided into two parts, the signed and unsigned basecases, which is where the magic happens, and a generic template matching a specific type to an implementation based on its (c-compile-time) size and signedness. When possible, branching is avoided, and preference is given to speed over accuracy (a low rate of falsely "detected" overflows are acceptable, undetected overflows are not). TODO: Hook up checking. TODO: Conditionally support 128-bit with intmax_t? */ /////////////// Common.proto /////////////// static int __Pyx_check_twos_complement(void) { if ((-1) != (~0)) { PyErr_SetString(PyExc_RuntimeError, "Two's complement required for overflow checks."); return 1; } else if ((sizeof(short) == sizeof(int))) { PyErr_SetString(PyExc_RuntimeError, "sizeof(short) < sizeof(int) required for overflow checks."); return 1; } else { return 0; } } #define __PYX_SIGN_BIT(type) ((((unsigned type) 1) << (sizeof(type) * 8 - 1))) #define __PYX_HALF_MAX(type) ((((type) 1) << (sizeof(type) * 8 - 2))) #define __PYX_MIN(type) ((__PYX_IS_UNSIGNED(type) ? (type) 0 : 0 - __PYX_HALF_MAX(type) - __PYX_HALF_MAX(type))) #define __PYX_MAX(type) ((~__PYX_MIN(type))) #define __Pyx_add_no_overflow(a, b, overflow) ((a) + (b)) #define __Pyx_add_const_no_overflow(a, b, overflow) ((a) + (b)) #define __Pyx_sub_no_overflow(a, b, overflow) ((a) - (b)) #define __Pyx_sub_const_no_overflow(a, b, overflow) ((a) - (b)) #define __Pyx_mul_no_overflow(a, b, overflow) ((a) * (b)) #define __Pyx_mul_const_no_overflow(a, b, overflow) ((a) * (b)) #define __Pyx_div_no_overflow(a, b, overflow) ((a) / (b)) #define __Pyx_div_const_no_overflow(a, b, overflow) ((a) / (b)) #if defined(__has_builtin) # if __has_builtin(__builtin_add_overflow) && !defined(__ibmxl__) # define __PYX_HAVE_BUILTIN_OVERFLOW # endif #elif defined(__GNUC__) && (__GNUC__ >= 5) && (!defined(__INTEL_COMPILER) || (__INTEL_COMPILER >= 1800)) # define __PYX_HAVE_BUILTIN_OVERFLOW #endif #if defined(__GNUC__) # define __Pyx_is_constant(x) (__builtin_constant_p(x)) #elif defined(__has_builtin) # if __has_builtin(__builtin_constant_p) # define __Pyx_is_constant(x) (__builtin_constant_p(x)) # endif #else # define __Pyx_is_constant(x) (0) #endif /////////////// Common.init /////////////// if (likely(__Pyx_check_twos_complement() == 0)); else // error propagation code is appended automatically /////////////// BaseCaseUnsigned.proto /////////////// {{if UINT == "long long"}}#ifdef HAVE_LONG_LONG{{endif}} static CYTHON_INLINE {{UINT}} __Pyx_add_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow); static CYTHON_INLINE {{UINT}} __Pyx_sub_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow); static CYTHON_INLINE {{UINT}} __Pyx_mul_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow); static CYTHON_INLINE {{UINT}} __Pyx_div_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow); // Use these when b is known at compile time. #define __Pyx_add_const_{{NAME}}_checking_overflow __Pyx_add_{{NAME}}_checking_overflow #define __Pyx_sub_const_{{NAME}}_checking_overflow __Pyx_sub_{{NAME}}_checking_overflow #if defined(__PYX_HAVE_BUILTIN_OVERFLOW) #define __Pyx_mul_const_{{NAME}}_checking_overflow __Pyx_mul_{{NAME}}_checking_overflow #else static CYTHON_INLINE {{UINT}} __Pyx_mul_const_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} constant, int *overflow); #endif #define __Pyx_div_const_{{NAME}}_checking_overflow __Pyx_div_{{NAME}}_checking_overflow {{if UINT == "long long"}}#endif{{endif}} /////////////// BaseCaseUnsigned /////////////// {{if UINT == "long long"}}#ifdef HAVE_LONG_LONG{{endif}} #if defined(__PYX_HAVE_BUILTIN_OVERFLOW) static CYTHON_INLINE {{UINT}} __Pyx_add_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) { {{UINT}} result; *overflow |= __builtin_add_overflow(a, b, &result); return result; } static CYTHON_INLINE {{UINT}} __Pyx_sub_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) { {{UINT}} result; *overflow |= __builtin_sub_overflow(a, b, &result); return result; } static CYTHON_INLINE {{UINT}} __Pyx_mul_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) { {{UINT}} result; *overflow |= __builtin_mul_overflow(a, b, &result); return result; } #else static CYTHON_INLINE {{UINT}} __Pyx_add_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) { {{UINT}} r = a + b; *overflow |= r < a; return r; } static CYTHON_INLINE {{UINT}} __Pyx_sub_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) { {{UINT}} r = a - b; *overflow |= r > a; return r; } static CYTHON_INLINE {{UINT}} __Pyx_mul_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) { // if we have a constant, use the constant version if (__Pyx_is_constant(b)) { return __Pyx_mul_const_{{NAME}}_checking_overflow(a, b, overflow); } else if (__Pyx_is_constant(a)) { return __Pyx_mul_const_{{NAME}}_checking_overflow(b, a, overflow); } else if ((sizeof({{UINT}}) < sizeof(unsigned long))) { unsigned long big_r = ((unsigned long) a) * ((unsigned long) b); {{UINT}} r = ({{UINT}}) big_r; *overflow |= big_r != r; return r; #ifdef HAVE_LONG_LONG } else if ((sizeof({{UINT}}) < sizeof(unsigned PY_LONG_LONG))) { unsigned PY_LONG_LONG big_r = ((unsigned PY_LONG_LONG) a) * ((unsigned PY_LONG_LONG) b); {{UINT}} r = ({{UINT}}) big_r; *overflow |= big_r != r; return r; #endif } else { return __Pyx_mul_const_{{NAME}}_checking_overflow(a, b, overflow); } } static CYTHON_INLINE {{UINT}} __Pyx_mul_const_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) { // note that deliberately the overflow check is written such that it divides by b; this // function is used when b is a constant thus the compiler should be able to eliminate the // (very slow on most CPUs!) division operation {{UINT}} prod; if (__Pyx_is_constant(a) && !__Pyx_is_constant(b)) { // if a is a compile-time constant and b isn't, swap them {{UINT}} temp = b; b = a; a = temp; } prod = a * b; if (b != 0) *overflow |= a > (__PYX_MAX({{UINT}}) / b); return prod; } #endif // __PYX_HAVE_BUILTIN_OVERFLOW static CYTHON_INLINE {{UINT}} __Pyx_div_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) { if (b == 0) { *overflow |= 1; return 0; } return a / b; } {{if UINT == "long long"}}#endif{{endif}} /////////////// BaseCaseSigned.proto /////////////// {{if INT == "long long"}}#ifdef HAVE_LONG_LONG{{endif}} static CYTHON_INLINE {{INT}} __Pyx_add_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow); static CYTHON_INLINE {{INT}} __Pyx_sub_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow); static CYTHON_INLINE {{INT}} __Pyx_mul_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow); static CYTHON_INLINE {{INT}} __Pyx_div_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow); // Use when b is known at compile time. #define __Pyx_add_const_{{NAME}}_checking_overflow __Pyx_add_{{NAME}}_checking_overflow #define __Pyx_sub_const_{{NAME}}_checking_overflow __Pyx_sub_{{NAME}}_checking_overflow #if defined(__PYX_HAVE_BUILTIN_OVERFLOW) #define __Pyx_mul_const_{{NAME}}_checking_overflow __Pyx_mul_{{NAME}}_checking_overflow #else static CYTHON_INLINE {{INT}} __Pyx_mul_const_{{NAME}}_checking_overflow({{INT}} a, {{INT}} constant, int *overflow); #endif #define __Pyx_div_const_{{NAME}}_checking_overflow __Pyx_div_{{NAME}}_checking_overflow {{if INT == "long long"}}#endif{{endif}} /////////////// BaseCaseSigned /////////////// {{if INT == "long long"}}#ifdef HAVE_LONG_LONG{{endif}} #if defined(__PYX_HAVE_BUILTIN_OVERFLOW) static CYTHON_INLINE {{INT}} __Pyx_add_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) { {{INT}} result; *overflow |= __builtin_add_overflow(a, b, &result); return result; } static CYTHON_INLINE {{INT}} __Pyx_sub_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) { {{INT}} result; *overflow |= __builtin_sub_overflow(a, b, &result); return result; } static CYTHON_INLINE {{INT}} __Pyx_mul_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) { {{INT}} result; *overflow |= __builtin_mul_overflow(a, b, &result); return result; } #else static CYTHON_INLINE {{INT}} __Pyx_add_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) { if ((sizeof({{INT}}) < sizeof(long))) { long big_r = ((long) a) + ((long) b); {{INT}} r = ({{INT}}) big_r; *overflow |= big_r != r; return r; #ifdef HAVE_LONG_LONG } else if ((sizeof({{INT}}) < sizeof(PY_LONG_LONG))) { PY_LONG_LONG big_r = ((PY_LONG_LONG) a) + ((PY_LONG_LONG) b); {{INT}} r = ({{INT}}) big_r; *overflow |= big_r != r; return r; #endif } else { // Signed overflow undefined, but unsigned overflow is well defined. Casting is // implementation-defined, but we assume two's complement (see __Pyx_check_twos_complement // above), and arithmetic in two's-complement is the same as unsigned arithmetic. unsigned {{INT}} r = (unsigned {{INT}}) a + (unsigned {{INT}}) b; // Overflow happened if the operands have the same sign, but the result // has opposite sign. *overflow |= (((unsigned {{INT}})a ^ r) & ((unsigned {{INT}})b ^ r)) >> (8 * sizeof({{INT}}) - 1); return ({{INT}}) r; } } static CYTHON_INLINE {{INT}} __Pyx_sub_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) { // Compilers don't handle widening as well in the subtraction case, so don't bother unsigned {{INT}} r = (unsigned {{INT}}) a - (unsigned {{INT}}) b; // Overflow happened if the operands differing signs, and the result // has opposite sign to a. *overflow |= (((unsigned {{INT}})a ^ (unsigned {{INT}})b) & ((unsigned {{INT}})a ^ r)) >> (8 * sizeof({{INT}}) - 1); return ({{INT}}) r; } static CYTHON_INLINE {{INT}} __Pyx_mul_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) { // if we have a constant, use the constant version if (__Pyx_is_constant(b)) { return __Pyx_mul_const_{{NAME}}_checking_overflow(a, b, overflow); } else if (__Pyx_is_constant(a)) { return __Pyx_mul_const_{{NAME}}_checking_overflow(b, a, overflow); } else if ((sizeof({{INT}}) < sizeof(long))) { long big_r = ((long) a) * ((long) b); {{INT}} r = ({{INT}}) big_r; *overflow |= big_r != r; return ({{INT}}) r; #ifdef HAVE_LONG_LONG } else if ((sizeof({{INT}}) < sizeof(PY_LONG_LONG))) { PY_LONG_LONG big_r = ((PY_LONG_LONG) a) * ((PY_LONG_LONG) b); {{INT}} r = ({{INT}}) big_r; *overflow |= big_r != r; return ({{INT}}) r; #endif } else { return __Pyx_mul_const_{{NAME}}_checking_overflow(a, b, overflow); } } static CYTHON_INLINE {{INT}} __Pyx_mul_const_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) { // note that deliberately all these comparisons are written such that they divide by b; this // function is used when b is a constant thus the compiler should be able to eliminate the // (very slow on most CPUs!) division operations if (__Pyx_is_constant(a) && !__Pyx_is_constant(b)) { // if a is a compile-time constant and b isn't, swap them {{INT}} temp = b; b = a; a = temp; } if (b > 1) { *overflow |= a > __PYX_MAX({{INT}}) / b; *overflow |= a < __PYX_MIN({{INT}}) / b; } else if (b == -1) { *overflow |= a == __PYX_MIN({{INT}}); } else if (b < -1) { *overflow |= a > __PYX_MIN({{INT}}) / b; *overflow |= a < __PYX_MAX({{INT}}) / b; } return ({{INT}}) (((unsigned {{INT}})a) * ((unsigned {{INT}}) b)); } #endif // defined(__PYX_HAVE_BUILTIN_OVERFLOW) static CYTHON_INLINE {{INT}} __Pyx_div_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) { if (b == 0) { *overflow |= 1; return 0; } *overflow |= a == __PYX_MIN({{INT}}) && b == -1; return ({{INT}}) ((unsigned {{INT}}) a / (unsigned {{INT}}) b); } {{if INT == "long long"}}#endif{{endif}} /////////////// SizeCheck.init /////////////// if (likely(__Pyx_check_sane_{{NAME}}() == 0)); else // error propagation code is appended automatically /////////////// SizeCheck.proto /////////////// static int __Pyx_check_sane_{{NAME}}(void) { if (((sizeof({{TYPE}}) <= sizeof(int)) || #ifdef HAVE_LONG_LONG (sizeof({{TYPE}}) == sizeof(PY_LONG_LONG)) || #endif (sizeof({{TYPE}}) == sizeof(long)))) { return 0; } else { PyErr_Format(PyExc_RuntimeError, \ "Bad size for int type %.{{max(60, len(TYPE))}}s: %d", "{{TYPE}}", (int) sizeof({{TYPE}})); return 1; } } /////////////// Binop.proto /////////////// static CYTHON_INLINE {{TYPE}} __Pyx_{{BINOP}}_{{NAME}}_checking_overflow({{TYPE}} a, {{TYPE}} b, int *overflow); /////////////// Binop /////////////// static CYTHON_INLINE {{TYPE}} __Pyx_{{BINOP}}_{{NAME}}_checking_overflow({{TYPE}} a, {{TYPE}} b, int *overflow) { if ((sizeof({{TYPE}}) < sizeof(int))) { return __Pyx_{{BINOP}}_no_overflow(a, b, overflow); } else if (__PYX_IS_UNSIGNED({{TYPE}})) { if ((sizeof({{TYPE}}) == sizeof(unsigned int))) { return ({{TYPE}}) __Pyx_{{BINOP}}_unsigned_int_checking_overflow(a, b, overflow); } else if ((sizeof({{TYPE}}) == sizeof(unsigned long))) { return ({{TYPE}}) __Pyx_{{BINOP}}_unsigned_long_checking_overflow(a, b, overflow); #ifdef HAVE_LONG_LONG } else if ((sizeof({{TYPE}}) == sizeof(unsigned PY_LONG_LONG))) { return ({{TYPE}}) __Pyx_{{BINOP}}_unsigned_long_long_checking_overflow(a, b, overflow); #endif } else { abort(); return 0; /* handled elsewhere */ } } else { if ((sizeof({{TYPE}}) == sizeof(int))) { return ({{TYPE}}) __Pyx_{{BINOP}}_int_checking_overflow(a, b, overflow); } else if ((sizeof({{TYPE}}) == sizeof(long))) { return ({{TYPE}}) __Pyx_{{BINOP}}_long_checking_overflow(a, b, overflow); #ifdef HAVE_LONG_LONG } else if ((sizeof({{TYPE}}) == sizeof(PY_LONG_LONG))) { return ({{TYPE}}) __Pyx_{{BINOP}}_long_long_checking_overflow(a, b, overflow); #endif } else { abort(); return 0; /* handled elsewhere */ } } } /////////////// LeftShift.proto /////////////// static CYTHON_INLINE {{TYPE}} __Pyx_lshift_{{NAME}}_checking_overflow({{TYPE}} a, {{TYPE}} b, int *overflow) { int overflow_check = #if {{SIGNED}} (a < 0) || (b < 0) || #endif // the following must be a _logical_ OR as the RHS is undefined if the LHS is true (b >= ({{TYPE}}) (8 * sizeof({{TYPE}}))) || (a > (__PYX_MAX({{TYPE}}) >> b)); if (overflow_check) { *overflow |= 1; return 0; } else { return a << b; } } #define __Pyx_lshift_const_{{NAME}}_checking_overflow __Pyx_lshift_{{NAME}}_checking_overflow /////////////// UnaryNegOverflows.proto /////////////// // from intobject.c #define __Pyx_UNARY_NEG_WOULD_OVERFLOW(x) \ (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x))) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/Printing.c0000644000175100001770000001175700000000000020454 0ustar00runnerdocker00000000000000////////////////////// Print.proto ////////////////////// //@substitute: naming static int __Pyx_Print(PyObject*, PyObject *, int); /*proto*/ #if CYTHON_COMPILING_IN_PYPY || PY_MAJOR_VERSION >= 3 static PyObject* $print_function = 0; static PyObject* $print_function_kwargs = 0; #endif ////////////////////// Print.cleanup ////////////////////// //@substitute: naming #if CYTHON_COMPILING_IN_PYPY || PY_MAJOR_VERSION >= 3 Py_CLEAR($print_function); Py_CLEAR($print_function_kwargs); #endif ////////////////////// Print ////////////////////// //@substitute: naming #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION < 3 static PyObject *__Pyx_GetStdout(void) { PyObject *f = PySys_GetObject((char *)"stdout"); if (!f) { PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout"); } return f; } static int __Pyx_Print(PyObject* f, PyObject *arg_tuple, int newline) { int i; if (!f) { if (!(f = __Pyx_GetStdout())) return -1; } Py_INCREF(f); for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) { PyObject* v; if (PyFile_SoftSpace(f, 1)) { if (PyFile_WriteString(" ", f) < 0) goto error; } v = PyTuple_GET_ITEM(arg_tuple, i); if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0) goto error; if (PyString_Check(v)) { char *s = PyString_AsString(v); Py_ssize_t len = PyString_Size(v); if (len > 0) { // append soft-space if necessary (not using isspace() due to C/C++ problem on MacOS-X) switch (s[len-1]) { case ' ': break; case '\f': case '\r': case '\n': case '\t': case '\v': PyFile_SoftSpace(f, 0); break; default: break; } } } } if (newline) { if (PyFile_WriteString("\n", f) < 0) goto error; PyFile_SoftSpace(f, 0); } Py_DECREF(f); return 0; error: Py_DECREF(f); return -1; } #else /* Python 3 has a print function */ static int __Pyx_Print(PyObject* stream, PyObject *arg_tuple, int newline) { PyObject* kwargs = 0; PyObject* result = 0; PyObject* end_string; if (unlikely(!$print_function)) { $print_function = PyObject_GetAttr($builtins_cname, PYIDENT("print")); if (!$print_function) return -1; } if (stream) { kwargs = PyDict_New(); if (unlikely(!kwargs)) return -1; if (unlikely(PyDict_SetItem(kwargs, PYIDENT("file"), stream) < 0)) goto bad; if (!newline) { end_string = PyUnicode_FromStringAndSize(" ", 1); if (unlikely(!end_string)) goto bad; if (PyDict_SetItem(kwargs, PYIDENT("end"), end_string) < 0) { Py_DECREF(end_string); goto bad; } Py_DECREF(end_string); } } else if (!newline) { if (unlikely(!$print_function_kwargs)) { $print_function_kwargs = PyDict_New(); if (unlikely(!$print_function_kwargs)) return -1; end_string = PyUnicode_FromStringAndSize(" ", 1); if (unlikely(!end_string)) return -1; if (PyDict_SetItem($print_function_kwargs, PYIDENT("end"), end_string) < 0) { Py_DECREF(end_string); return -1; } Py_DECREF(end_string); } kwargs = $print_function_kwargs; } result = PyObject_Call($print_function, arg_tuple, kwargs); if (unlikely(kwargs) && (kwargs != $print_function_kwargs)) Py_DECREF(kwargs); if (!result) return -1; Py_DECREF(result); return 0; bad: if (kwargs != $print_function_kwargs) Py_XDECREF(kwargs); return -1; } #endif ////////////////////// PrintOne.proto ////////////////////// //@requires: Print static int __Pyx_PrintOne(PyObject* stream, PyObject *o); /*proto*/ ////////////////////// PrintOne ////////////////////// #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION < 3 static int __Pyx_PrintOne(PyObject* f, PyObject *o) { if (!f) { if (!(f = __Pyx_GetStdout())) return -1; } Py_INCREF(f); if (PyFile_SoftSpace(f, 0)) { if (PyFile_WriteString(" ", f) < 0) goto error; } if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0) goto error; if (PyFile_WriteString("\n", f) < 0) goto error; Py_DECREF(f); return 0; error: Py_DECREF(f); return -1; /* the line below is just to avoid C compiler * warnings about unused functions */ return __Pyx_Print(f, NULL, 0); } #else /* Python 3 has a print function */ static int __Pyx_PrintOne(PyObject* stream, PyObject *o) { int res; PyObject* arg_tuple = PyTuple_Pack(1, o); if (unlikely(!arg_tuple)) return -1; res = __Pyx_Print(stream, arg_tuple, 1); Py_DECREF(arg_tuple); return res; } #endif ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/Profile.c0000644000175100001770000004342200000000000020254 0ustar00runnerdocker00000000000000/////////////// Profile.proto /////////////// //@requires: Exceptions.c::PyErrFetchRestore //@substitute: naming // Note that cPython ignores PyTrace_EXCEPTION, // but maybe some other profilers don't. #ifndef CYTHON_PROFILE #if CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_PYPY #define CYTHON_PROFILE 0 #else #define CYTHON_PROFILE 1 #endif #endif #ifndef CYTHON_TRACE_NOGIL #define CYTHON_TRACE_NOGIL 0 #else #if CYTHON_TRACE_NOGIL && !defined(CYTHON_TRACE) #define CYTHON_TRACE 1 #endif #endif #ifndef CYTHON_TRACE #define CYTHON_TRACE 0 #endif #if CYTHON_TRACE #undef CYTHON_PROFILE_REUSE_FRAME #endif #ifndef CYTHON_PROFILE_REUSE_FRAME #define CYTHON_PROFILE_REUSE_FRAME 0 #endif #if CYTHON_PROFILE || CYTHON_TRACE #include "compile.h" #include "frameobject.h" #include "traceback.h" #if PY_VERSION_HEX >= 0x030b00a6 #ifndef Py_BUILD_CORE #define Py_BUILD_CORE 1 #endif #include "internal/pycore_frame.h" #endif #if CYTHON_PROFILE_REUSE_FRAME #define CYTHON_FRAME_MODIFIER static #define CYTHON_FRAME_DEL(frame) #else #define CYTHON_FRAME_MODIFIER #define CYTHON_FRAME_DEL(frame) Py_CLEAR(frame) #endif #define __Pyx_TraceDeclarations \ static PyCodeObject *$frame_code_cname = NULL; \ CYTHON_FRAME_MODIFIER PyFrameObject *$frame_cname = NULL; \ int __Pyx_use_tracing = 0; #define __Pyx_TraceFrameInit(codeobj) \ if (codeobj) $frame_code_cname = (PyCodeObject*) codeobj; #if PY_VERSION_HEX >= 0x030b00a2 #if PY_VERSION_HEX >= 0x030C00b1 #define __Pyx_IsTracing(tstate, check_tracing, check_funcs) \ ((!(check_tracing) || !(tstate)->tracing) && \ (!(check_funcs) || (tstate)->c_profilefunc || (CYTHON_TRACE && (tstate)->c_tracefunc))) #else #define __Pyx_IsTracing(tstate, check_tracing, check_funcs) \ (unlikely((tstate)->cframe->use_tracing) && \ (!(check_tracing) || !(tstate)->tracing) && \ (!(check_funcs) || (tstate)->c_profilefunc || (CYTHON_TRACE && (tstate)->c_tracefunc))) #endif #define __Pyx_EnterTracing(tstate) PyThreadState_EnterTracing(tstate) #define __Pyx_LeaveTracing(tstate) PyThreadState_LeaveTracing(tstate) #elif PY_VERSION_HEX >= 0x030a00b1 #define __Pyx_IsTracing(tstate, check_tracing, check_funcs) \ (unlikely((tstate)->cframe->use_tracing) && \ (!(check_tracing) || !(tstate)->tracing) && \ (!(check_funcs) || (tstate)->c_profilefunc || (CYTHON_TRACE && (tstate)->c_tracefunc))) #define __Pyx_EnterTracing(tstate) \ do { tstate->tracing++; tstate->cframe->use_tracing = 0; } while (0) #define __Pyx_LeaveTracing(tstate) \ do { \ tstate->tracing--; \ tstate->cframe->use_tracing = ((CYTHON_TRACE && tstate->c_tracefunc != NULL) \ || tstate->c_profilefunc != NULL); \ } while (0) #else #define __Pyx_IsTracing(tstate, check_tracing, check_funcs) \ (unlikely((tstate)->use_tracing) && \ (!(check_tracing) || !(tstate)->tracing) && \ (!(check_funcs) || (tstate)->c_profilefunc || (CYTHON_TRACE && (tstate)->c_tracefunc))) #define __Pyx_EnterTracing(tstate) \ do { tstate->tracing++; tstate->use_tracing = 0; } while (0) #define __Pyx_LeaveTracing(tstate) \ do { \ tstate->tracing--; \ tstate->use_tracing = ((CYTHON_TRACE && tstate->c_tracefunc != NULL) \ || tstate->c_profilefunc != NULL); \ } while (0) #endif #ifdef WITH_THREAD #define __Pyx_TraceCall(funcname, srcfile, firstlineno, nogil, goto_error) \ if (nogil) { \ if (CYTHON_TRACE_NOGIL) { \ PyThreadState *tstate; \ PyGILState_STATE state = PyGILState_Ensure(); \ tstate = __Pyx_PyThreadState_Current; \ if (__Pyx_IsTracing(tstate, 1, 1)) { \ __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&$frame_code_cname, &$frame_cname, tstate, funcname, srcfile, firstlineno); \ } \ PyGILState_Release(state); \ if (unlikely(__Pyx_use_tracing < 0)) goto_error; \ } \ } else { \ PyThreadState* tstate = PyThreadState_GET(); \ if (__Pyx_IsTracing(tstate, 1, 1)) { \ __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&$frame_code_cname, &$frame_cname, tstate, funcname, srcfile, firstlineno); \ if (unlikely(__Pyx_use_tracing < 0)) goto_error; \ } \ } #else #define __Pyx_TraceCall(funcname, srcfile, firstlineno, nogil, goto_error) \ { PyThreadState* tstate = PyThreadState_GET(); \ if (__Pyx_IsTracing(tstate, 1, 1)) { \ __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&$frame_code_cname, &$frame_cname, tstate, funcname, srcfile, firstlineno); \ if (unlikely(__Pyx_use_tracing < 0)) goto_error; \ } \ } #endif #define __Pyx_TraceException() \ if (likely(!__Pyx_use_tracing)); else { \ PyThreadState* tstate = __Pyx_PyThreadState_Current; \ if (__Pyx_IsTracing(tstate, 0, 1)) { \ __Pyx_EnterTracing(tstate); \ PyObject *exc_info = __Pyx_GetExceptionTuple(tstate); \ if (exc_info) { \ if (CYTHON_TRACE && tstate->c_tracefunc) \ tstate->c_tracefunc( \ tstate->c_traceobj, $frame_cname, PyTrace_EXCEPTION, exc_info); \ tstate->c_profilefunc( \ tstate->c_profileobj, $frame_cname, PyTrace_EXCEPTION, exc_info); \ Py_DECREF(exc_info); \ } \ __Pyx_LeaveTracing(tstate); \ } \ } static void __Pyx_call_return_trace_func(PyThreadState *tstate, PyFrameObject *frame, PyObject *result) { PyObject *type, *value, *traceback; __Pyx_ErrFetchInState(tstate, &type, &value, &traceback); __Pyx_EnterTracing(tstate); if (CYTHON_TRACE && tstate->c_tracefunc) tstate->c_tracefunc(tstate->c_traceobj, frame, PyTrace_RETURN, result); if (tstate->c_profilefunc) tstate->c_profilefunc(tstate->c_profileobj, frame, PyTrace_RETURN, result); CYTHON_FRAME_DEL(frame); __Pyx_LeaveTracing(tstate); __Pyx_ErrRestoreInState(tstate, type, value, traceback); } #ifdef WITH_THREAD #define __Pyx_TraceReturn(result, nogil) \ if (likely(!__Pyx_use_tracing)); else { \ if (nogil) { \ if (CYTHON_TRACE_NOGIL) { \ PyThreadState *tstate; \ PyGILState_STATE state = PyGILState_Ensure(); \ tstate = __Pyx_PyThreadState_Current; \ if (__Pyx_IsTracing(tstate, 0, 0)) { \ __Pyx_call_return_trace_func(tstate, $frame_cname, (PyObject*)result); \ } \ PyGILState_Release(state); \ } \ } else { \ PyThreadState* tstate = __Pyx_PyThreadState_Current; \ if (__Pyx_IsTracing(tstate, 0, 0)) { \ __Pyx_call_return_trace_func(tstate, $frame_cname, (PyObject*)result); \ } \ } \ } #else #define __Pyx_TraceReturn(result, nogil) \ if (likely(!__Pyx_use_tracing)); else { \ PyThreadState* tstate = __Pyx_PyThreadState_Current; \ if (__Pyx_IsTracing(tstate, 0, 0)) { \ __Pyx_call_return_trace_func(tstate, $frame_cname, (PyObject*)result); \ } \ } #endif static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno); /*proto*/ static int __Pyx_TraceSetupAndCall(PyCodeObject** code, PyFrameObject** frame, PyThreadState* tstate, const char *funcname, const char *srcfile, int firstlineno); /*proto*/ #else #define __Pyx_TraceDeclarations #define __Pyx_TraceFrameInit(codeobj) // mark error label as used to avoid compiler warnings #define __Pyx_TraceCall(funcname, srcfile, firstlineno, nogil, goto_error) if ((1)); else goto_error; #define __Pyx_TraceException() #define __Pyx_TraceReturn(result, nogil) #endif /* CYTHON_PROFILE */ #if CYTHON_TRACE // see call_trace_protected() in CPython's ceval.c static int __Pyx_call_line_trace_func(PyThreadState *tstate, PyFrameObject *frame, int lineno) { int ret; PyObject *type, *value, *traceback; __Pyx_ErrFetchInState(tstate, &type, &value, &traceback); __Pyx_PyFrame_SetLineNumber(frame, lineno); __Pyx_EnterTracing(tstate); ret = tstate->c_tracefunc(tstate->c_traceobj, frame, PyTrace_LINE, NULL); __Pyx_LeaveTracing(tstate); if (likely(!ret)) { __Pyx_ErrRestoreInState(tstate, type, value, traceback); } else { Py_XDECREF(type); Py_XDECREF(value); Py_XDECREF(traceback); } return ret; } #ifdef WITH_THREAD #define __Pyx_TraceLine(lineno, nogil, goto_error) \ if (likely(!__Pyx_use_tracing)); else { \ if (nogil) { \ if (CYTHON_TRACE_NOGIL) { \ int ret = 0; \ PyThreadState *tstate; \ PyGILState_STATE state = __Pyx_PyGILState_Ensure(); \ tstate = __Pyx_PyThreadState_Current; \ if (__Pyx_IsTracing(tstate, 0, 0) && tstate->c_tracefunc && $frame_cname->f_trace) { \ ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \ } \ __Pyx_PyGILState_Release(state); \ if (unlikely(ret)) goto_error; \ } \ } else { \ PyThreadState* tstate = __Pyx_PyThreadState_Current; \ if (__Pyx_IsTracing(tstate, 0, 0) && tstate->c_tracefunc && $frame_cname->f_trace) { \ int ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \ if (unlikely(ret)) goto_error; \ } \ } \ } #else #define __Pyx_TraceLine(lineno, nogil, goto_error) \ if (likely(!__Pyx_use_tracing)); else { \ PyThreadState* tstate = __Pyx_PyThreadState_Current; \ if (__Pyx_IsTracing(tstate, 0, 0) && tstate->c_tracefunc && $frame_cname->f_trace) { \ int ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \ if (unlikely(ret)) goto_error; \ } \ } #endif #else // mark error label as used to avoid compiler warnings #define __Pyx_TraceLine(lineno, nogil, goto_error) if ((1)); else goto_error; #endif /////////////// Profile /////////////// //@substitute: naming #if CYTHON_PROFILE static int __Pyx_TraceSetupAndCall(PyCodeObject** code, PyFrameObject** frame, PyThreadState* tstate, const char *funcname, const char *srcfile, int firstlineno) { PyObject *type, *value, *traceback; int retval; if (*frame == NULL || !CYTHON_PROFILE_REUSE_FRAME) { if (*code == NULL) { *code = __Pyx_createFrameCodeObject(funcname, srcfile, firstlineno); if (*code == NULL) return 0; } *frame = PyFrame_New( tstate, /*PyThreadState *tstate*/ *code, /*PyCodeObject *code*/ $moddict_cname, /*PyObject *globals*/ 0 /*PyObject *locals*/ ); if (*frame == NULL) return 0; if (CYTHON_TRACE && (*frame)->f_trace == NULL) { // this enables "f_lineno" lookup, at least in CPython ... Py_INCREF(Py_None); (*frame)->f_trace = Py_None; } #if PY_VERSION_HEX < 0x030400B1 } else { (*frame)->f_tstate = tstate; #endif } __Pyx_PyFrame_SetLineNumber(*frame, firstlineno); retval = 1; __Pyx_EnterTracing(tstate); __Pyx_ErrFetchInState(tstate, &type, &value, &traceback); #if CYTHON_TRACE if (tstate->c_tracefunc) retval = tstate->c_tracefunc(tstate->c_traceobj, *frame, PyTrace_CALL, NULL) == 0; if (retval && tstate->c_profilefunc) #endif retval = tstate->c_profilefunc(tstate->c_profileobj, *frame, PyTrace_CALL, NULL) == 0; __Pyx_LeaveTracing(tstate); if (retval) { __Pyx_ErrRestoreInState(tstate, type, value, traceback); return __Pyx_IsTracing(tstate, 0, 0) && retval; } else { Py_XDECREF(type); Py_XDECREF(value); Py_XDECREF(traceback); return -1; } } static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno) { PyCodeObject *py_code = 0; #if PY_MAJOR_VERSION >= 3 py_code = PyCode_NewEmpty(srcfile, funcname, firstlineno); // make CPython use a fresh dict for "f_locals" at need (see GH #1836) if (likely(py_code)) { py_code->co_flags |= CO_OPTIMIZED | CO_NEWLOCALS; } #else PyObject *py_srcfile = 0; PyObject *py_funcname = 0; py_funcname = PyString_FromString(funcname); if (unlikely(!py_funcname)) goto bad; py_srcfile = PyString_FromString(srcfile); if (unlikely(!py_srcfile)) goto bad; py_code = PyCode_New( 0, /*int argcount,*/ 0, /*int nlocals,*/ 0, /*int stacksize,*/ // make CPython use a fresh dict for "f_locals" at need (see GH #1836) CO_OPTIMIZED | CO_NEWLOCALS, /*int flags,*/ $empty_bytes, /*PyObject *code,*/ $empty_tuple, /*PyObject *consts,*/ $empty_tuple, /*PyObject *names,*/ $empty_tuple, /*PyObject *varnames,*/ $empty_tuple, /*PyObject *freevars,*/ $empty_tuple, /*PyObject *cellvars,*/ py_srcfile, /*PyObject *filename,*/ py_funcname, /*PyObject *name,*/ firstlineno, /*int firstlineno,*/ $empty_bytes /*PyObject *lnotab*/ ); bad: Py_XDECREF(py_srcfile); Py_XDECREF(py_funcname); #endif return py_code; } #endif /* CYTHON_PROFILE */ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/StringTools.c0000644000175100001770000012751000000000000021144 0ustar00runnerdocker00000000000000 //////////////////// IncludeStringH.proto //////////////////// #include //////////////////// IncludeCppStringH.proto //////////////////// #include //////////////////// ssize_pyunicode_strlen.proto //////////////////// static CYTHON_INLINE Py_ssize_t __Pyx_Py_UNICODE_ssize_strlen(const Py_UNICODE *u);/*proto*/ //////////////////// ssize_pyunicode_strlen //////////////////// static CYTHON_INLINE Py_ssize_t __Pyx_Py_UNICODE_ssize_strlen(const Py_UNICODE *u) { size_t len = __Pyx_Py_UNICODE_strlen(u); if (unlikely(len > PY_SSIZE_T_MAX)) { PyErr_SetString(PyExc_OverflowError, "Py_UNICODE string is too long"); return -1; } return (Py_ssize_t) len; } //////////////////// InitStrings.proto //////////////////// static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/ //////////////////// InitStrings //////////////////// #if PY_MAJOR_VERSION >= 3 static int __Pyx_InitString(__Pyx_StringTabEntry t, PyObject **str) { if (t.is_unicode | t.is_str) { if (t.intern) { *str = PyUnicode_InternFromString(t.s); } else if (t.encoding) { *str = PyUnicode_Decode(t.s, t.n - 1, t.encoding, NULL); } else { *str = PyUnicode_FromStringAndSize(t.s, t.n - 1); } } else { *str = PyBytes_FromStringAndSize(t.s, t.n - 1); } if (!*str) return -1; // initialise cached hash value if (PyObject_Hash(*str) == -1) return -1; return 0; } #endif static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { while (t->p) { #if PY_MAJOR_VERSION >= 3 /* Python 3+ has unicode identifiers */ __Pyx_InitString(*t, t->p); #else if (t->is_unicode) { *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); } else if (t->intern) { *t->p = PyString_InternFromString(t->s); } else { *t->p = PyString_FromStringAndSize(t->s, t->n - 1); } if (!*t->p) return -1; // initialise cached hash value if (PyObject_Hash(*t->p) == -1) return -1; #endif ++t; } return 0; } //////////////////// BytesContains.proto //////////////////// static CYTHON_INLINE int __Pyx_BytesContains(PyObject* bytes, char character); /*proto*/ //////////////////// BytesContains //////////////////// //@requires: IncludeStringH static CYTHON_INLINE int __Pyx_BytesContains(PyObject* bytes, char character) { const Py_ssize_t length = PyBytes_GET_SIZE(bytes); char* char_start = PyBytes_AS_STRING(bytes); return memchr(char_start, (unsigned char)character, (size_t)length) != NULL; } //////////////////// PyUCS4InUnicode.proto //////////////////// static CYTHON_INLINE int __Pyx_UnicodeContainsUCS4(PyObject* unicode, Py_UCS4 character); /*proto*/ //////////////////// PyUCS4InUnicode //////////////////// #if PY_VERSION_HEX < 0x03090000 || (defined(PyUnicode_WCHAR_KIND) && defined(PyUnicode_AS_UNICODE)) #if PY_VERSION_HEX < 0x03090000 #define __Pyx_PyUnicode_AS_UNICODE(op) PyUnicode_AS_UNICODE(op) #define __Pyx_PyUnicode_GET_SIZE(op) PyUnicode_GET_SIZE(op) #else // Avoid calling deprecated C-API functions in Py3.9+ that PEP-623 schedules for removal in Py3.12. // https://www.python.org/dev/peps/pep-0623/ #define __Pyx_PyUnicode_AS_UNICODE(op) (((PyASCIIObject *)(op))->wstr) #define __Pyx_PyUnicode_GET_SIZE(op) ((PyCompactUnicodeObject *)(op))->wstr_length #endif #if !defined(Py_UNICODE_SIZE) || Py_UNICODE_SIZE == 2 static int __Pyx_PyUnicodeBufferContainsUCS4_SP(Py_UNICODE* buffer, Py_ssize_t length, Py_UCS4 character) { /* handle surrogate pairs for Py_UNICODE buffers in 16bit Unicode builds */ Py_UNICODE high_val, low_val; Py_UNICODE* pos; high_val = (Py_UNICODE) (0xD800 | (((character - 0x10000) >> 10) & ((1<<10)-1))); low_val = (Py_UNICODE) (0xDC00 | ( (character - 0x10000) & ((1<<10)-1))); for (pos=buffer; pos < buffer+length-1; pos++) { if (unlikely((high_val == pos[0]) & (low_val == pos[1]))) return 1; } return 0; } #endif static int __Pyx_PyUnicodeBufferContainsUCS4_BMP(Py_UNICODE* buffer, Py_ssize_t length, Py_UCS4 character) { Py_UNICODE uchar; Py_UNICODE* pos; uchar = (Py_UNICODE) character; for (pos=buffer; pos < buffer+length; pos++) { if (unlikely(uchar == pos[0])) return 1; } return 0; } #endif static CYTHON_INLINE int __Pyx_UnicodeContainsUCS4(PyObject* unicode, Py_UCS4 character) { #if CYTHON_PEP393_ENABLED const int kind = PyUnicode_KIND(unicode); #ifdef PyUnicode_WCHAR_KIND if (likely(kind != PyUnicode_WCHAR_KIND)) #endif { Py_ssize_t i; const void* udata = PyUnicode_DATA(unicode); const Py_ssize_t length = PyUnicode_GET_LENGTH(unicode); for (i=0; i < length; i++) { if (unlikely(character == PyUnicode_READ(kind, udata, i))) return 1; } return 0; } #elif PY_VERSION_HEX >= 0x03090000 #error Cannot use "UChar in Unicode" in Python 3.9 without PEP-393 unicode strings. #elif !defined(PyUnicode_AS_UNICODE) #error Cannot use "UChar in Unicode" in Python < 3.9 without Py_UNICODE support. #endif #if PY_VERSION_HEX < 0x03090000 || (defined(PyUnicode_WCHAR_KIND) && defined(PyUnicode_AS_UNICODE)) #if !defined(Py_UNICODE_SIZE) || Py_UNICODE_SIZE == 2 if ((sizeof(Py_UNICODE) == 2) && unlikely(character > 65535)) { return __Pyx_PyUnicodeBufferContainsUCS4_SP( __Pyx_PyUnicode_AS_UNICODE(unicode), __Pyx_PyUnicode_GET_SIZE(unicode), character); } else #endif { return __Pyx_PyUnicodeBufferContainsUCS4_BMP( __Pyx_PyUnicode_AS_UNICODE(unicode), __Pyx_PyUnicode_GET_SIZE(unicode), character); } #endif } //////////////////// PyUnicodeContains.proto //////////////////// static CYTHON_INLINE int __Pyx_PyUnicode_ContainsTF(PyObject* substring, PyObject* text, int eq) { int result = PyUnicode_Contains(text, substring); return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); } //////////////////// CStringEquals.proto //////////////////// static CYTHON_INLINE int __Pyx_StrEq(const char *, const char *); /*proto*/ //////////////////// CStringEquals //////////////////// static CYTHON_INLINE int __Pyx_StrEq(const char *s1, const char *s2) { while (*s1 != '\0' && *s1 == *s2) { s1++; s2++; } return *s1 == *s2; } //////////////////// StrEquals.proto //////////////////// //@requires: BytesEquals //@requires: UnicodeEquals #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyString_Equals __Pyx_PyUnicode_Equals #else #define __Pyx_PyString_Equals __Pyx_PyBytes_Equals #endif //////////////////// UnicodeEquals.proto //////////////////// static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals); /*proto*/ //////////////////// UnicodeEquals //////////////////// //@requires: BytesEquals static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals) { #if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API return PyObject_RichCompareBool(s1, s2, equals); #else #if PY_MAJOR_VERSION < 3 PyObject* owned_ref = NULL; #endif int s1_is_unicode, s2_is_unicode; if (s1 == s2) { /* as done by PyObject_RichCompareBool(); also catches the (interned) empty string */ goto return_eq; } s1_is_unicode = PyUnicode_CheckExact(s1); s2_is_unicode = PyUnicode_CheckExact(s2); #if PY_MAJOR_VERSION < 3 if ((s1_is_unicode & (!s2_is_unicode)) && PyString_CheckExact(s2)) { owned_ref = PyUnicode_FromObject(s2); if (unlikely(!owned_ref)) return -1; s2 = owned_ref; s2_is_unicode = 1; } else if ((s2_is_unicode & (!s1_is_unicode)) && PyString_CheckExact(s1)) { owned_ref = PyUnicode_FromObject(s1); if (unlikely(!owned_ref)) return -1; s1 = owned_ref; s1_is_unicode = 1; } else if (((!s2_is_unicode) & (!s1_is_unicode))) { return __Pyx_PyBytes_Equals(s1, s2, equals); } #endif if (s1_is_unicode & s2_is_unicode) { Py_ssize_t length; int kind; void *data1, *data2; if (unlikely(__Pyx_PyUnicode_READY(s1) < 0) || unlikely(__Pyx_PyUnicode_READY(s2) < 0)) return -1; length = __Pyx_PyUnicode_GET_LENGTH(s1); if (length != __Pyx_PyUnicode_GET_LENGTH(s2)) { goto return_ne; } #if CYTHON_USE_UNICODE_INTERNALS { Py_hash_t hash1, hash2; #if CYTHON_PEP393_ENABLED hash1 = ((PyASCIIObject*)s1)->hash; hash2 = ((PyASCIIObject*)s2)->hash; #else hash1 = ((PyUnicodeObject*)s1)->hash; hash2 = ((PyUnicodeObject*)s2)->hash; #endif if (hash1 != hash2 && hash1 != -1 && hash2 != -1) { goto return_ne; } } #endif // len(s1) == len(s2) >= 1 (empty string is interned, and "s1 is not s2") kind = __Pyx_PyUnicode_KIND(s1); if (kind != __Pyx_PyUnicode_KIND(s2)) { goto return_ne; } data1 = __Pyx_PyUnicode_DATA(s1); data2 = __Pyx_PyUnicode_DATA(s2); if (__Pyx_PyUnicode_READ(kind, data1, 0) != __Pyx_PyUnicode_READ(kind, data2, 0)) { goto return_ne; } else if (length == 1) { goto return_eq; } else { int result = memcmp(data1, data2, (size_t)(length * kind)); #if PY_MAJOR_VERSION < 3 Py_XDECREF(owned_ref); #endif return (equals == Py_EQ) ? (result == 0) : (result != 0); } } else if ((s1 == Py_None) & s2_is_unicode) { goto return_ne; } else if ((s2 == Py_None) & s1_is_unicode) { goto return_ne; } else { int result; PyObject* py_result = PyObject_RichCompare(s1, s2, equals); #if PY_MAJOR_VERSION < 3 Py_XDECREF(owned_ref); #endif if (!py_result) return -1; result = __Pyx_PyObject_IsTrue(py_result); Py_DECREF(py_result); return result; } return_eq: #if PY_MAJOR_VERSION < 3 Py_XDECREF(owned_ref); #endif return (equals == Py_EQ); return_ne: #if PY_MAJOR_VERSION < 3 Py_XDECREF(owned_ref); #endif return (equals == Py_NE); #endif } //////////////////// BytesEquals.proto //////////////////// static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals); /*proto*/ //////////////////// BytesEquals //////////////////// //@requires: IncludeStringH static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals) { #if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API return PyObject_RichCompareBool(s1, s2, equals); #else if (s1 == s2) { /* as done by PyObject_RichCompareBool(); also catches the (interned) empty string */ return (equals == Py_EQ); } else if (PyBytes_CheckExact(s1) & PyBytes_CheckExact(s2)) { const char *ps1, *ps2; Py_ssize_t length = PyBytes_GET_SIZE(s1); if (length != PyBytes_GET_SIZE(s2)) return (equals == Py_NE); // len(s1) == len(s2) >= 1 (empty string is interned, and "s1 is not s2") ps1 = PyBytes_AS_STRING(s1); ps2 = PyBytes_AS_STRING(s2); if (ps1[0] != ps2[0]) { return (equals == Py_NE); } else if (length == 1) { return (equals == Py_EQ); } else { int result; #if CYTHON_USE_UNICODE_INTERNALS && (PY_VERSION_HEX < 0x030B0000) Py_hash_t hash1, hash2; hash1 = ((PyBytesObject*)s1)->ob_shash; hash2 = ((PyBytesObject*)s2)->ob_shash; if (hash1 != hash2 && hash1 != -1 && hash2 != -1) { return (equals == Py_NE); } #endif result = memcmp(ps1, ps2, (size_t)length); return (equals == Py_EQ) ? (result == 0) : (result != 0); } } else if ((s1 == Py_None) & PyBytes_CheckExact(s2)) { return (equals == Py_NE); } else if ((s2 == Py_None) & PyBytes_CheckExact(s1)) { return (equals == Py_NE); } else { int result; PyObject* py_result = PyObject_RichCompare(s1, s2, equals); if (!py_result) return -1; result = __Pyx_PyObject_IsTrue(py_result); Py_DECREF(py_result); return result; } #endif } //////////////////// GetItemIntByteArray.proto //////////////////// #define __Pyx_GetItemInt_ByteArray(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \ (__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \ __Pyx_GetItemInt_ByteArray_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) : \ (PyErr_SetString(PyExc_IndexError, "bytearray index out of range"), -1)) static CYTHON_INLINE int __Pyx_GetItemInt_ByteArray_Fast(PyObject* string, Py_ssize_t i, int wraparound, int boundscheck); //////////////////// GetItemIntByteArray //////////////////// static CYTHON_INLINE int __Pyx_GetItemInt_ByteArray_Fast(PyObject* string, Py_ssize_t i, int wraparound, int boundscheck) { Py_ssize_t length; if (wraparound | boundscheck) { length = PyByteArray_GET_SIZE(string); if (wraparound & unlikely(i < 0)) i += length; if ((!boundscheck) || likely(__Pyx_is_valid_index(i, length))) { return (unsigned char) (PyByteArray_AS_STRING(string)[i]); } else { PyErr_SetString(PyExc_IndexError, "bytearray index out of range"); return -1; } } else { return (unsigned char) (PyByteArray_AS_STRING(string)[i]); } } //////////////////// SetItemIntByteArray.proto //////////////////// #define __Pyx_SetItemInt_ByteArray(o, i, v, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \ (__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \ __Pyx_SetItemInt_ByteArray_Fast(o, (Py_ssize_t)i, v, wraparound, boundscheck) : \ (PyErr_SetString(PyExc_IndexError, "bytearray index out of range"), -1)) static CYTHON_INLINE int __Pyx_SetItemInt_ByteArray_Fast(PyObject* string, Py_ssize_t i, unsigned char v, int wraparound, int boundscheck); //////////////////// SetItemIntByteArray //////////////////// static CYTHON_INLINE int __Pyx_SetItemInt_ByteArray_Fast(PyObject* string, Py_ssize_t i, unsigned char v, int wraparound, int boundscheck) { Py_ssize_t length; if (wraparound | boundscheck) { length = PyByteArray_GET_SIZE(string); if (wraparound & unlikely(i < 0)) i += length; if ((!boundscheck) || likely(__Pyx_is_valid_index(i, length))) { PyByteArray_AS_STRING(string)[i] = (char) v; return 0; } else { PyErr_SetString(PyExc_IndexError, "bytearray index out of range"); return -1; } } else { PyByteArray_AS_STRING(string)[i] = (char) v; return 0; } } //////////////////// GetItemIntUnicode.proto //////////////////// #define __Pyx_GetItemInt_Unicode(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \ (__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \ __Pyx_GetItemInt_Unicode_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) : \ (PyErr_SetString(PyExc_IndexError, "string index out of range"), (Py_UCS4)-1)) static CYTHON_INLINE Py_UCS4 __Pyx_GetItemInt_Unicode_Fast(PyObject* ustring, Py_ssize_t i, int wraparound, int boundscheck); //////////////////// GetItemIntUnicode //////////////////// static CYTHON_INLINE Py_UCS4 __Pyx_GetItemInt_Unicode_Fast(PyObject* ustring, Py_ssize_t i, int wraparound, int boundscheck) { Py_ssize_t length; if (unlikely(__Pyx_PyUnicode_READY(ustring) < 0)) return (Py_UCS4)-1; if (wraparound | boundscheck) { length = __Pyx_PyUnicode_GET_LENGTH(ustring); if (wraparound & unlikely(i < 0)) i += length; if ((!boundscheck) || likely(__Pyx_is_valid_index(i, length))) { return __Pyx_PyUnicode_READ_CHAR(ustring, i); } else { PyErr_SetString(PyExc_IndexError, "string index out of range"); return (Py_UCS4)-1; } } else { return __Pyx_PyUnicode_READ_CHAR(ustring, i); } } /////////////// decode_c_string_utf16.proto /////////////// static CYTHON_INLINE PyObject *__Pyx_PyUnicode_DecodeUTF16(const char *s, Py_ssize_t size, const char *errors) { int byteorder = 0; return PyUnicode_DecodeUTF16(s, size, errors, &byteorder); } static CYTHON_INLINE PyObject *__Pyx_PyUnicode_DecodeUTF16LE(const char *s, Py_ssize_t size, const char *errors) { int byteorder = -1; return PyUnicode_DecodeUTF16(s, size, errors, &byteorder); } static CYTHON_INLINE PyObject *__Pyx_PyUnicode_DecodeUTF16BE(const char *s, Py_ssize_t size, const char *errors) { int byteorder = 1; return PyUnicode_DecodeUTF16(s, size, errors, &byteorder); } /////////////// decode_cpp_string.proto /////////////// //@requires: IncludeCppStringH //@requires: decode_c_bytes static CYTHON_INLINE PyObject* __Pyx_decode_cpp_string( std::string cppstring, Py_ssize_t start, Py_ssize_t stop, const char* encoding, const char* errors, PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)) { return __Pyx_decode_c_bytes( cppstring.data(), cppstring.size(), start, stop, encoding, errors, decode_func); } /////////////// decode_c_string.proto /////////////// static CYTHON_INLINE PyObject* __Pyx_decode_c_string( const char* cstring, Py_ssize_t start, Py_ssize_t stop, const char* encoding, const char* errors, PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)); /////////////// decode_c_string /////////////// //@requires: IncludeStringH //@requires: decode_c_string_utf16 //@substitute: naming /* duplicate code to avoid calling strlen() if start >= 0 and stop >= 0 */ static CYTHON_INLINE PyObject* __Pyx_decode_c_string( const char* cstring, Py_ssize_t start, Py_ssize_t stop, const char* encoding, const char* errors, PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)) { Py_ssize_t length; if (unlikely((start < 0) | (stop < 0))) { size_t slen = strlen(cstring); if (unlikely(slen > (size_t) PY_SSIZE_T_MAX)) { PyErr_SetString(PyExc_OverflowError, "c-string too long to convert to Python"); return NULL; } length = (Py_ssize_t) slen; if (start < 0) { start += length; if (start < 0) start = 0; } if (stop < 0) stop += length; } if (unlikely(stop <= start)) return __Pyx_NewRef($empty_unicode); length = stop - start; cstring += start; if (decode_func) { return decode_func(cstring, length, errors); } else { return PyUnicode_Decode(cstring, length, encoding, errors); } } /////////////// decode_c_bytes.proto /////////////// static CYTHON_INLINE PyObject* __Pyx_decode_c_bytes( const char* cstring, Py_ssize_t length, Py_ssize_t start, Py_ssize_t stop, const char* encoding, const char* errors, PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)); /////////////// decode_c_bytes /////////////// //@requires: decode_c_string_utf16 //@substitute: naming static CYTHON_INLINE PyObject* __Pyx_decode_c_bytes( const char* cstring, Py_ssize_t length, Py_ssize_t start, Py_ssize_t stop, const char* encoding, const char* errors, PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)) { if (unlikely((start < 0) | (stop < 0))) { if (start < 0) { start += length; if (start < 0) start = 0; } if (stop < 0) stop += length; } if (stop > length) stop = length; if (unlikely(stop <= start)) return __Pyx_NewRef($empty_unicode); length = stop - start; cstring += start; if (decode_func) { return decode_func(cstring, length, errors); } else { return PyUnicode_Decode(cstring, length, encoding, errors); } } /////////////// decode_bytes.proto /////////////// //@requires: decode_c_bytes static CYTHON_INLINE PyObject* __Pyx_decode_bytes( PyObject* string, Py_ssize_t start, Py_ssize_t stop, const char* encoding, const char* errors, PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)) { char* as_c_string; Py_ssize_t size; #if CYTHON_ASSUME_SAFE_MACROS as_c_string = PyBytes_AS_STRING(string); size = PyBytes_GET_SIZE(string); #else if (PyBytes_AsStringAndSize(string, &as_c_string, &size) < 0) { return NULL; } #endif return __Pyx_decode_c_bytes( as_c_string, size, start, stop, encoding, errors, decode_func); } /////////////// decode_bytearray.proto /////////////// //@requires: decode_c_bytes static CYTHON_INLINE PyObject* __Pyx_decode_bytearray( PyObject* string, Py_ssize_t start, Py_ssize_t stop, const char* encoding, const char* errors, PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)) { char* as_c_string; Py_ssize_t size; #if CYTHON_ASSUME_SAFE_MACROS as_c_string = PyByteArray_AS_STRING(string); size = PyByteArray_GET_SIZE(string); #else if (!(as_c_string = PyByteArray_AsString(string))) return NULL; if ((size = PyByteArray_Size(string)) < 0) return NULL; #endif return __Pyx_decode_c_bytes( as_c_string, size, start, stop, encoding, errors, decode_func); } /////////////// PyUnicode_Substring.proto /////////////// static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Substring( PyObject* text, Py_ssize_t start, Py_ssize_t stop); /////////////// PyUnicode_Substring /////////////// //@substitute: naming static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Substring( PyObject* text, Py_ssize_t start, Py_ssize_t stop) { Py_ssize_t length; if (unlikely(__Pyx_PyUnicode_READY(text) == -1)) return NULL; length = __Pyx_PyUnicode_GET_LENGTH(text); if (start < 0) { start += length; if (start < 0) start = 0; } if (stop < 0) stop += length; else if (stop > length) stop = length; if (stop <= start) return __Pyx_NewRef($empty_unicode); if (start == 0 && stop == length) return __Pyx_NewRef(text); #if CYTHON_PEP393_ENABLED return PyUnicode_FromKindAndData(PyUnicode_KIND(text), PyUnicode_1BYTE_DATA(text) + start*PyUnicode_KIND(text), stop-start); #else return PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(text)+start, stop-start); #endif } /////////////// py_unicode_istitle.proto /////////////// // Py_UNICODE_ISTITLE() doesn't match unicode.istitle() as the latter // additionally allows character that comply with Py_UNICODE_ISUPPER() #if PY_VERSION_HEX < 0x030200A2 static CYTHON_INLINE int __Pyx_Py_UNICODE_ISTITLE(Py_UNICODE uchar) #else static CYTHON_INLINE int __Pyx_Py_UNICODE_ISTITLE(Py_UCS4 uchar) #endif { return Py_UNICODE_ISTITLE(uchar) || Py_UNICODE_ISUPPER(uchar); } /////////////// unicode_tailmatch.proto /////////////// static int __Pyx_PyUnicode_Tailmatch( PyObject* s, PyObject* substr, Py_ssize_t start, Py_ssize_t end, int direction); /*proto*/ /////////////// unicode_tailmatch /////////////// // Python's unicode.startswith() and unicode.endswith() support a // tuple of prefixes/suffixes, whereas it's much more common to // test for a single unicode string. static int __Pyx_PyUnicode_TailmatchTuple(PyObject* s, PyObject* substrings, Py_ssize_t start, Py_ssize_t end, int direction) { Py_ssize_t i, count = PyTuple_GET_SIZE(substrings); for (i = 0; i < count; i++) { Py_ssize_t result; #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS result = PyUnicode_Tailmatch(s, PyTuple_GET_ITEM(substrings, i), start, end, direction); #else PyObject* sub = PySequence_ITEM(substrings, i); if (unlikely(!sub)) return -1; result = PyUnicode_Tailmatch(s, sub, start, end, direction); Py_DECREF(sub); #endif if (result) { return (int) result; } } return 0; } static int __Pyx_PyUnicode_Tailmatch(PyObject* s, PyObject* substr, Py_ssize_t start, Py_ssize_t end, int direction) { if (unlikely(PyTuple_Check(substr))) { return __Pyx_PyUnicode_TailmatchTuple(s, substr, start, end, direction); } return (int) PyUnicode_Tailmatch(s, substr, start, end, direction); } /////////////// bytes_tailmatch.proto /////////////// static int __Pyx_PyBytes_SingleTailmatch(PyObject* self, PyObject* arg, Py_ssize_t start, Py_ssize_t end, int direction); /*proto*/ static int __Pyx_PyBytes_Tailmatch(PyObject* self, PyObject* substr, Py_ssize_t start, Py_ssize_t end, int direction); /*proto*/ /////////////// bytes_tailmatch /////////////// static int __Pyx_PyBytes_SingleTailmatch(PyObject* self, PyObject* arg, Py_ssize_t start, Py_ssize_t end, int direction) { const char* self_ptr = PyBytes_AS_STRING(self); Py_ssize_t self_len = PyBytes_GET_SIZE(self); const char* sub_ptr; Py_ssize_t sub_len; int retval; Py_buffer view; view.obj = NULL; if ( PyBytes_Check(arg) ) { sub_ptr = PyBytes_AS_STRING(arg); sub_len = PyBytes_GET_SIZE(arg); } #if PY_MAJOR_VERSION < 3 // Python 2.x allows mixing unicode and str else if ( PyUnicode_Check(arg) ) { return (int) PyUnicode_Tailmatch(self, arg, start, end, direction); } #endif else { if (unlikely(PyObject_GetBuffer(self, &view, PyBUF_SIMPLE) == -1)) return -1; sub_ptr = (const char*) view.buf; sub_len = view.len; } if (end > self_len) end = self_len; else if (end < 0) end += self_len; if (end < 0) end = 0; if (start < 0) start += self_len; if (start < 0) start = 0; if (direction > 0) { /* endswith */ if (end-sub_len > start) start = end - sub_len; } if (start + sub_len <= end) retval = !memcmp(self_ptr+start, sub_ptr, (size_t)sub_len); else retval = 0; if (view.obj) PyBuffer_Release(&view); return retval; } static int __Pyx_PyBytes_TailmatchTuple(PyObject* self, PyObject* substrings, Py_ssize_t start, Py_ssize_t end, int direction) { Py_ssize_t i, count = PyTuple_GET_SIZE(substrings); for (i = 0; i < count; i++) { int result; #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS result = __Pyx_PyBytes_SingleTailmatch(self, PyTuple_GET_ITEM(substrings, i), start, end, direction); #else PyObject* sub = PySequence_ITEM(substrings, i); if (unlikely(!sub)) return -1; result = __Pyx_PyBytes_SingleTailmatch(self, sub, start, end, direction); Py_DECREF(sub); #endif if (result) { return result; } } return 0; } static int __Pyx_PyBytes_Tailmatch(PyObject* self, PyObject* substr, Py_ssize_t start, Py_ssize_t end, int direction) { if (unlikely(PyTuple_Check(substr))) { return __Pyx_PyBytes_TailmatchTuple(self, substr, start, end, direction); } return __Pyx_PyBytes_SingleTailmatch(self, substr, start, end, direction); } /////////////// str_tailmatch.proto /////////////// static CYTHON_INLINE int __Pyx_PyStr_Tailmatch(PyObject* self, PyObject* arg, Py_ssize_t start, Py_ssize_t end, int direction); /*proto*/ /////////////// str_tailmatch /////////////// //@requires: bytes_tailmatch //@requires: unicode_tailmatch static CYTHON_INLINE int __Pyx_PyStr_Tailmatch(PyObject* self, PyObject* arg, Py_ssize_t start, Py_ssize_t end, int direction) { // We do not use a C compiler macro here to avoid "unused function" // warnings for the *_Tailmatch() function that is not being used in // the specific CPython version. The C compiler will generate the same // code anyway, and will usually just remove the unused function. if (PY_MAJOR_VERSION < 3) return __Pyx_PyBytes_Tailmatch(self, arg, start, end, direction); else return __Pyx_PyUnicode_Tailmatch(self, arg, start, end, direction); } /////////////// bytes_index.proto /////////////// static CYTHON_INLINE char __Pyx_PyBytes_GetItemInt(PyObject* bytes, Py_ssize_t index, int check_bounds); /*proto*/ /////////////// bytes_index /////////////// static CYTHON_INLINE char __Pyx_PyBytes_GetItemInt(PyObject* bytes, Py_ssize_t index, int check_bounds) { if (index < 0) index += PyBytes_GET_SIZE(bytes); if (check_bounds) { Py_ssize_t size = PyBytes_GET_SIZE(bytes); if (unlikely(!__Pyx_is_valid_index(index, size))) { PyErr_SetString(PyExc_IndexError, "string index out of range"); return (char) -1; } } return PyBytes_AS_STRING(bytes)[index]; } //////////////////// StringJoin.proto //////////////////// #if PY_MAJOR_VERSION < 3 #define __Pyx_PyString_Join __Pyx_PyBytes_Join #define __Pyx_PyBaseString_Join(s, v) (PyUnicode_CheckExact(s) ? PyUnicode_Join(s, v) : __Pyx_PyBytes_Join(s, v)) #else #define __Pyx_PyString_Join PyUnicode_Join #define __Pyx_PyBaseString_Join PyUnicode_Join #endif static CYTHON_INLINE PyObject* __Pyx_PyBytes_Join(PyObject* sep, PyObject* values); /*proto*/ //////////////////// StringJoin //////////////////// //@requires: ObjectHandling.c::PyObjectCallMethod1 static CYTHON_INLINE PyObject* __Pyx_PyBytes_Join(PyObject* sep, PyObject* values) { // avoid unused function (void) __Pyx_PyObject_CallMethod1; #if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION < 3 return _PyString_Join(sep, values); #elif CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030d0000 return _PyBytes_Join(sep, values); #else return __Pyx_PyObject_CallMethod1(sep, PYIDENT("join"), values); #endif } /////////////// JoinPyUnicode.proto /////////////// static PyObject* __Pyx_PyUnicode_Join(PyObject* value_tuple, Py_ssize_t value_count, Py_ssize_t result_ulength, Py_UCS4 max_char); /////////////// JoinPyUnicode /////////////// //@requires: IncludeStringH //@substitute: naming static PyObject* __Pyx_PyUnicode_Join(PyObject* value_tuple, Py_ssize_t value_count, Py_ssize_t result_ulength, Py_UCS4 max_char) { #if CYTHON_USE_UNICODE_INTERNALS && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS PyObject *result_uval; int result_ukind, kind_shift; Py_ssize_t i, char_pos; void *result_udata; CYTHON_MAYBE_UNUSED_VAR(max_char); #if CYTHON_PEP393_ENABLED // Py 3.3+ (post PEP-393) result_uval = PyUnicode_New(result_ulength, max_char); if (unlikely(!result_uval)) return NULL; result_ukind = (max_char <= 255) ? PyUnicode_1BYTE_KIND : (max_char <= 65535) ? PyUnicode_2BYTE_KIND : PyUnicode_4BYTE_KIND; kind_shift = (result_ukind == PyUnicode_4BYTE_KIND) ? 2 : result_ukind - 1; result_udata = PyUnicode_DATA(result_uval); #else // Py 2.x/3.2 (pre PEP-393) result_uval = PyUnicode_FromUnicode(NULL, result_ulength); if (unlikely(!result_uval)) return NULL; result_ukind = sizeof(Py_UNICODE); kind_shift = (result_ukind == 4) ? 2 : result_ukind - 1; result_udata = PyUnicode_AS_UNICODE(result_uval); #endif assert(kind_shift == 2 || kind_shift == 1 || kind_shift == 0); char_pos = 0; for (i=0; i < value_count; i++) { int ukind; Py_ssize_t ulength; void *udata; PyObject *uval = PyTuple_GET_ITEM(value_tuple, i); if (unlikely(__Pyx_PyUnicode_READY(uval))) goto bad; ulength = __Pyx_PyUnicode_GET_LENGTH(uval); if (unlikely(!ulength)) continue; if (unlikely((PY_SSIZE_T_MAX >> kind_shift) - ulength < char_pos)) goto overflow; ukind = __Pyx_PyUnicode_KIND(uval); udata = __Pyx_PyUnicode_DATA(uval); if (!CYTHON_PEP393_ENABLED || ukind == result_ukind) { memcpy((char *)result_udata + (char_pos << kind_shift), udata, (size_t) (ulength << kind_shift)); } else { #if PY_VERSION_HEX >= 0x030d0000 if (unlikely(PyUnicode_CopyCharacters(result_uval, char_pos, uval, 0, ulength) < 0)) goto bad; #elif CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030300F0 || defined(_PyUnicode_FastCopyCharacters) _PyUnicode_FastCopyCharacters(result_uval, char_pos, uval, 0, ulength); #else Py_ssize_t j; for (j=0; j < ulength; j++) { Py_UCS4 uchar = __Pyx_PyUnicode_READ(ukind, udata, j); __Pyx_PyUnicode_WRITE(result_ukind, result_udata, char_pos+j, uchar); } #endif } char_pos += ulength; } return result_uval; overflow: PyErr_SetString(PyExc_OverflowError, "join() result is too long for a Python string"); bad: Py_DECREF(result_uval); return NULL; #else // non-CPython fallback CYTHON_UNUSED_VAR(max_char); CYTHON_UNUSED_VAR(result_ulength); CYTHON_UNUSED_VAR(value_count); return PyUnicode_Join($empty_unicode, value_tuple); #endif } /////////////// BuildPyUnicode.proto /////////////// static PyObject* __Pyx_PyUnicode_BuildFromAscii(Py_ssize_t ulength, char* chars, int clength, int prepend_sign, char padding_char); /////////////// BuildPyUnicode /////////////// // Create a PyUnicode object from an ASCII char*, e.g. a formatted number. static PyObject* __Pyx_PyUnicode_BuildFromAscii(Py_ssize_t ulength, char* chars, int clength, int prepend_sign, char padding_char) { PyObject *uval; Py_ssize_t uoffset = ulength - clength; #if CYTHON_USE_UNICODE_INTERNALS Py_ssize_t i; #if CYTHON_PEP393_ENABLED // Py 3.3+ (post PEP-393) void *udata; uval = PyUnicode_New(ulength, 127); if (unlikely(!uval)) return NULL; udata = PyUnicode_DATA(uval); #else // Py 2.x/3.2 (pre PEP-393) Py_UNICODE *udata; uval = PyUnicode_FromUnicode(NULL, ulength); if (unlikely(!uval)) return NULL; udata = PyUnicode_AS_UNICODE(uval); #endif if (uoffset > 0) { i = 0; if (prepend_sign) { __Pyx_PyUnicode_WRITE(PyUnicode_1BYTE_KIND, udata, 0, '-'); i++; } for (; i < uoffset; i++) { __Pyx_PyUnicode_WRITE(PyUnicode_1BYTE_KIND, udata, i, padding_char); } } for (i=0; i < clength; i++) { __Pyx_PyUnicode_WRITE(PyUnicode_1BYTE_KIND, udata, uoffset+i, chars[i]); } #else // non-CPython { PyObject *sign = NULL, *padding = NULL; uval = NULL; if (uoffset > 0) { prepend_sign = !!prepend_sign; if (uoffset > prepend_sign) { padding = PyUnicode_FromOrdinal(padding_char); if (likely(padding) && uoffset > prepend_sign + 1) { PyObject *tmp; PyObject *repeat = PyInt_FromSsize_t(uoffset - prepend_sign); if (unlikely(!repeat)) goto done_or_error; tmp = PyNumber_Multiply(padding, repeat); Py_DECREF(repeat); Py_DECREF(padding); padding = tmp; } if (unlikely(!padding)) goto done_or_error; } if (prepend_sign) { sign = PyUnicode_FromOrdinal('-'); if (unlikely(!sign)) goto done_or_error; } } uval = PyUnicode_DecodeASCII(chars, clength, NULL); if (likely(uval) && padding) { PyObject *tmp = PyNumber_Add(padding, uval); Py_DECREF(uval); uval = tmp; } if (likely(uval) && sign) { PyObject *tmp = PyNumber_Add(sign, uval); Py_DECREF(uval); uval = tmp; } done_or_error: Py_XDECREF(padding); Py_XDECREF(sign); } #endif return uval; } //////////////////// ByteArrayAppendObject.proto //////////////////// static CYTHON_INLINE int __Pyx_PyByteArray_AppendObject(PyObject* bytearray, PyObject* value); //////////////////// ByteArrayAppendObject //////////////////// //@requires: ByteArrayAppend static CYTHON_INLINE int __Pyx_PyByteArray_AppendObject(PyObject* bytearray, PyObject* value) { Py_ssize_t ival; #if PY_MAJOR_VERSION < 3 if (unlikely(PyString_Check(value))) { if (unlikely(PyString_GET_SIZE(value) != 1)) { PyErr_SetString(PyExc_ValueError, "string must be of size 1"); return -1; } ival = (unsigned char) (PyString_AS_STRING(value)[0]); } else #endif #if CYTHON_USE_PYLONG_INTERNALS if (likely(PyLong_CheckExact(value)) && likely(__Pyx_PyLong_IsCompact(value))) { if (__Pyx_PyLong_IsZero(value)) { ival = 0; } else { ival = __Pyx_PyLong_CompactValue(value); if (unlikely(ival > 255)) goto bad_range; } } else #endif { // CPython calls PyNumber_Index() internally ival = __Pyx_PyIndex_AsSsize_t(value); if (unlikely(!__Pyx_is_valid_index(ival, 256))) { if (ival == -1 && PyErr_Occurred()) return -1; goto bad_range; } } return __Pyx_PyByteArray_Append(bytearray, ival); bad_range: PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); return -1; } //////////////////// ByteArrayAppend.proto //////////////////// static CYTHON_INLINE int __Pyx_PyByteArray_Append(PyObject* bytearray, int value); //////////////////// ByteArrayAppend //////////////////// //@requires: ObjectHandling.c::PyObjectCallMethod1 static CYTHON_INLINE int __Pyx_PyByteArray_Append(PyObject* bytearray, int value) { PyObject *pyval, *retval; #if CYTHON_COMPILING_IN_CPYTHON if (likely(__Pyx_is_valid_index(value, 256))) { Py_ssize_t n = Py_SIZE(bytearray); if (likely(n != PY_SSIZE_T_MAX)) { if (unlikely(PyByteArray_Resize(bytearray, n + 1) < 0)) return -1; PyByteArray_AS_STRING(bytearray)[n] = value; return 0; } } else { PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); return -1; } #endif pyval = PyInt_FromLong(value); if (unlikely(!pyval)) return -1; retval = __Pyx_PyObject_CallMethod1(bytearray, PYIDENT("append"), pyval); Py_DECREF(pyval); if (unlikely(!retval)) return -1; Py_DECREF(retval); return 0; } //////////////////// PyObjectFormat.proto //////////////////// #if CYTHON_USE_UNICODE_WRITER static PyObject* __Pyx_PyObject_Format(PyObject* s, PyObject* f); #else #define __Pyx_PyObject_Format(s, f) PyObject_Format(s, f) #endif //////////////////// PyObjectFormat //////////////////// #if CYTHON_USE_UNICODE_WRITER static PyObject* __Pyx_PyObject_Format(PyObject* obj, PyObject* format_spec) { int ret; _PyUnicodeWriter writer; if (likely(PyFloat_CheckExact(obj))) { // copied from CPython 3.5 "float__format__()" in floatobject.c #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x03040000 _PyUnicodeWriter_Init(&writer, 0); #else _PyUnicodeWriter_Init(&writer); #endif ret = _PyFloat_FormatAdvancedWriter( &writer, obj, format_spec, 0, PyUnicode_GET_LENGTH(format_spec)); } else if (likely(PyLong_CheckExact(obj))) { // copied from CPython 3.5 "long__format__()" in longobject.c #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x03040000 _PyUnicodeWriter_Init(&writer, 0); #else _PyUnicodeWriter_Init(&writer); #endif ret = _PyLong_FormatAdvancedWriter( &writer, obj, format_spec, 0, PyUnicode_GET_LENGTH(format_spec)); } else { return PyObject_Format(obj, format_spec); } if (unlikely(ret == -1)) { _PyUnicodeWriter_Dealloc(&writer); return NULL; } return _PyUnicodeWriter_Finish(&writer); } #endif //////////////////// PyObjectFormatSimple.proto //////////////////// #if CYTHON_COMPILING_IN_PYPY #define __Pyx_PyObject_FormatSimple(s, f) ( \ likely(PyUnicode_CheckExact(s)) ? (Py_INCREF(s), s) : \ PyObject_Format(s, f)) #elif PY_MAJOR_VERSION < 3 // str is common in Py2, but formatting must return a Unicode string #define __Pyx_PyObject_FormatSimple(s, f) ( \ likely(PyUnicode_CheckExact(s)) ? (Py_INCREF(s), s) : \ likely(PyString_CheckExact(s)) ? PyUnicode_FromEncodedObject(s, NULL, "strict") : \ PyObject_Format(s, f)) #elif CYTHON_USE_TYPE_SLOTS // Py3 nicely returns unicode strings from str() and repr(), which makes this quite efficient for builtin types. // In Py3.8+, tp_str() delegates to tp_repr(), so we call tp_repr() directly here. #define __Pyx_PyObject_FormatSimple(s, f) ( \ likely(PyUnicode_CheckExact(s)) ? (Py_INCREF(s), s) : \ likely(PyLong_CheckExact(s)) ? PyLong_Type.tp_repr(s) : \ likely(PyFloat_CheckExact(s)) ? PyFloat_Type.tp_repr(s) : \ PyObject_Format(s, f)) #else #define __Pyx_PyObject_FormatSimple(s, f) ( \ likely(PyUnicode_CheckExact(s)) ? (Py_INCREF(s), s) : \ PyObject_Format(s, f)) #endif //////////////////// PyObjectFormatAndDecref.proto //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyObject_FormatSimpleAndDecref(PyObject* s, PyObject* f); static CYTHON_INLINE PyObject* __Pyx_PyObject_FormatAndDecref(PyObject* s, PyObject* f); //////////////////// PyObjectFormatAndDecref //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyObject_FormatSimpleAndDecref(PyObject* s, PyObject* f) { if (unlikely(!s)) return NULL; if (likely(PyUnicode_CheckExact(s))) return s; #if PY_MAJOR_VERSION < 3 // str is common in Py2, but formatting must return a Unicode string if (likely(PyString_CheckExact(s))) { PyObject *result = PyUnicode_FromEncodedObject(s, NULL, "strict"); Py_DECREF(s); return result; } #endif return __Pyx_PyObject_FormatAndDecref(s, f); } static CYTHON_INLINE PyObject* __Pyx_PyObject_FormatAndDecref(PyObject* s, PyObject* f) { PyObject *result; if (unlikely(!s)) return NULL; result = PyObject_Format(s, f); Py_DECREF(s); return result; } //////////////////// PyUnicode_Unicode.proto //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Unicode(PyObject *obj);/*proto*/ //////////////////// PyUnicode_Unicode //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Unicode(PyObject *obj) { if (unlikely(obj == Py_None)) obj = PYUNICODE("None"); return __Pyx_NewRef(obj); } //////////////////// PyObject_Unicode.proto //////////////////// #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyObject_Unicode(obj) \ (likely(PyUnicode_CheckExact(obj)) ? __Pyx_NewRef(obj) : PyObject_Str(obj)) #else #define __Pyx_PyObject_Unicode(obj) \ (likely(PyUnicode_CheckExact(obj)) ? __Pyx_NewRef(obj) : PyObject_Unicode(obj)) #endif //////////////////// PyStr_Str.proto //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyStr_Str(PyObject *obj);/*proto*/ //////////////////// PyStr_Str //////////////////// static CYTHON_INLINE PyObject* __Pyx_PyStr_Str(PyObject *obj) { if (unlikely(obj == Py_None)) obj = PYIDENT("None"); return __Pyx_NewRef(obj); } //////////////////// PyObject_Str.proto //////////////////// #define __Pyx_PyObject_Str(obj) \ (likely(PyString_CheckExact(obj)) ? __Pyx_NewRef(obj) : PyObject_Str(obj)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/TestCyUtilityLoader.pyx0000644000175100001770000000023000000000000023166 0ustar00runnerdocker00000000000000########## TestCyUtilityLoader ########## #@requires: OtherUtility test {{cy_loader}} impl ########## OtherUtility ########## req {{cy_loader}} impl ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/TestCythonScope.pyx0000644000175100001770000000340300000000000022343 0ustar00runnerdocker00000000000000########## TestClass ########## # These utilities are for testing purposes # The "cythonscope" test calls METH_O functions with their (self, arg) signature. # cython: always_allow_keywords=False from __future__ import print_function cdef extern from *: cdef object __pyx_test_dep(object) @cname('__pyx_TestClass') cdef class TestClass(object): cdef public int value def __init__(self, int value): self.value = value def __str__(self): return f'TestClass({self.value})' cdef cdef_method(self, int value): print('Hello from cdef_method', value) cpdef cpdef_method(self, int value): print('Hello from cpdef_method', value) def def_method(self, int value): print('Hello from def_method', value) @cname('cdef_cname') cdef cdef_cname_method(self, int value): print("Hello from cdef_cname_method", value) @cname('cpdef_cname') cpdef cpdef_cname_method(self, int value): print("Hello from cpdef_cname_method", value) @cname('def_cname') def def_cname_method(self, int value): print("Hello from def_cname_method", value) @cname('__pyx_test_call_other_cy_util') cdef test_call(obj): print('test_call') __pyx_test_dep(obj) @cname('__pyx_TestClass_New') cdef _testclass_new(int value): return TestClass(value) ########### TestDep ########## from __future__ import print_function @cname('__pyx_test_dep') cdef test_dep(obj): print('test_dep', obj) ########## TestScope ########## @cname('__pyx_testscope') cdef object _testscope(int value): return f"hello from cython scope, value={value}" ########## View.TestScope ########## @cname('__pyx_view_testscope') cdef object _testscope(int value): return f"hello from cython.view scope, value={value}" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/TestUtilityLoader.c0000644000175100001770000000042700000000000022304 0ustar00runnerdocker00000000000000////////// TestUtilityLoader.proto ////////// test {{loader}} prototype ////////// TestUtilityLoader ////////// //@requires: OtherUtility test {{loader}} impl ////////// OtherUtility.proto ////////// req {{loader}} proto ////////// OtherUtility ////////// req {{loader}} impl ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/TypeConversion.c0000644000175100001770000013766300000000000021656 0ustar00runnerdocker00000000000000/////////////// TypeConversions.proto /////////////// //@requires: StringTools.c::IncludeStringH /* Type Conversion Predeclarations */ #define __Pyx_uchar_cast(c) ((unsigned char)c) #define __Pyx_long_cast(x) ((long)x) #define __Pyx_fits_Py_ssize_t(v, type, is_signed) ( \ (sizeof(type) < sizeof(Py_ssize_t)) || \ (sizeof(type) > sizeof(Py_ssize_t) && \ likely(v < (type)PY_SSIZE_T_MAX || \ v == (type)PY_SSIZE_T_MAX) && \ (!is_signed || likely(v > (type)PY_SSIZE_T_MIN || \ v == (type)PY_SSIZE_T_MIN))) || \ (sizeof(type) == sizeof(Py_ssize_t) && \ (is_signed || likely(v < (type)PY_SSIZE_T_MAX || \ v == (type)PY_SSIZE_T_MAX))) ) static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { // Optimisation from Section 14.2 "Bounds Checking" in // https://www.agner.org/optimize/optimizing_cpp.pdf // See https://bugs.python.org/issue28397 // The cast to unsigned effectively tests for "0 <= i < limit". return (size_t) i < (size_t) limit; } // fast and unsafe abs(Py_ssize_t) that ignores the overflow for (-PY_SSIZE_T_MAX-1) #if defined (__cplusplus) && __cplusplus >= 201103L #include #define __Pyx_sst_abs(value) std::abs(value) #elif SIZEOF_INT >= SIZEOF_SIZE_T #define __Pyx_sst_abs(value) abs(value) #elif SIZEOF_LONG >= SIZEOF_SIZE_T #define __Pyx_sst_abs(value) labs(value) #elif defined (_MSC_VER) // abs() is defined for long, but 64-bits type on MSVC is long long. // Use MS-specific _abs64 instead. #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define __Pyx_sst_abs(value) llabs(value) #elif defined (__GNUC__) // gcc or clang on 64 bit windows. #define __Pyx_sst_abs(value) __builtin_llabs(value) #else #define __Pyx_sst_abs(value) ((value<0) ? -value : value) #endif static CYTHON_INLINE Py_ssize_t __Pyx_ssize_strlen(const char *s); static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); static CYTHON_INLINE PyObject* __Pyx_PyByteArray_FromString(const char*); #define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) #define __Pyx_PyBytes_FromString PyBytes_FromString #define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); #if PY_MAJOR_VERSION < 3 #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize #else #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize #endif #define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) #define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) #define __Pyx_PyObject_AsWritableString(s) ((char*)(__pyx_uintptr_t) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsWritableSString(s) ((signed char*)(__pyx_uintptr_t) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*)(__pyx_uintptr_t) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) #define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) #define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) #define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) #define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) // There used to be a Py_UNICODE_strlen() in CPython 3.x, but it is deprecated since Py3.3. #if CYTHON_COMPILING_IN_LIMITED_API static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const wchar_t *u) { const wchar_t *u_end = u; while (*u_end++) ; return (size_t)(u_end - u - 1); } #else static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { const Py_UNICODE *u_end = u; while (*u_end++) ; return (size_t)(u_end - u - 1); } #endif #define __Pyx_PyUnicode_FromOrdinal(o) PyUnicode_FromOrdinal((int)o) #define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) #define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode #define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode #define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) #define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); #define __Pyx_PySequence_Tuple(obj) \ (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*); #if CYTHON_ASSUME_SAFE_MACROS #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) #else #define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) #endif #define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) #else #define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) #endif // __Pyx_PyNumber_Float is now in its own section since it has dependencies (needed to make // string conversion work the same in all circumstances). #if CYTHON_USE_PYLONG_INTERNALS #if PY_VERSION_HEX >= 0x030C00A7 #ifndef _PyLong_SIGN_MASK #define _PyLong_SIGN_MASK 3 #endif #ifndef _PyLong_NON_SIZE_BITS #define _PyLong_NON_SIZE_BITS 3 #endif #define __Pyx_PyLong_Sign(x) (((PyLongObject*)x)->long_value.lv_tag & _PyLong_SIGN_MASK) #define __Pyx_PyLong_IsNeg(x) ((__Pyx_PyLong_Sign(x) & 2) != 0) #define __Pyx_PyLong_IsNonNeg(x) (!__Pyx_PyLong_IsNeg(x)) #define __Pyx_PyLong_IsZero(x) (__Pyx_PyLong_Sign(x) & 1) #define __Pyx_PyLong_IsPos(x) (__Pyx_PyLong_Sign(x) == 0) #define __Pyx_PyLong_CompactValueUnsigned(x) (__Pyx_PyLong_Digits(x)[0]) #define __Pyx_PyLong_DigitCount(x) ((Py_ssize_t) (((PyLongObject*)x)->long_value.lv_tag >> _PyLong_NON_SIZE_BITS)) #define __Pyx_PyLong_SignedDigitCount(x) \ ((1 - (Py_ssize_t) __Pyx_PyLong_Sign(x)) * __Pyx_PyLong_DigitCount(x)) #if defined(PyUnstable_Long_IsCompact) && defined(PyUnstable_Long_CompactValue) #define __Pyx_PyLong_IsCompact(x) PyUnstable_Long_IsCompact((PyLongObject*) x) #define __Pyx_PyLong_CompactValue(x) PyUnstable_Long_CompactValue((PyLongObject*) x) #else #define __Pyx_PyLong_IsCompact(x) (((PyLongObject*)x)->long_value.lv_tag < (2 << _PyLong_NON_SIZE_BITS)) #define __Pyx_PyLong_CompactValue(x) ((1 - (Py_ssize_t) __Pyx_PyLong_Sign(x)) * (Py_ssize_t) __Pyx_PyLong_Digits(x)[0]) #endif // CPython 3.12 requires C99, which defines 'size_t' (but not 'ssize_t') typedef Py_ssize_t __Pyx_compact_pylong; typedef size_t __Pyx_compact_upylong; #else /* Py < 3.12 */ #define __Pyx_PyLong_IsNeg(x) (Py_SIZE(x) < 0) #define __Pyx_PyLong_IsNonNeg(x) (Py_SIZE(x) >= 0) #define __Pyx_PyLong_IsZero(x) (Py_SIZE(x) == 0) #define __Pyx_PyLong_IsPos(x) (Py_SIZE(x) > 0) #define __Pyx_PyLong_CompactValueUnsigned(x) ((Py_SIZE(x) == 0) ? 0 : __Pyx_PyLong_Digits(x)[0]) #define __Pyx_PyLong_DigitCount(x) __Pyx_sst_abs(Py_SIZE(x)) #define __Pyx_PyLong_SignedDigitCount(x) Py_SIZE(x) #define __Pyx_PyLong_IsCompact(x) (Py_SIZE(x) == 0 || Py_SIZE(x) == 1 || Py_SIZE(x) == -1) #define __Pyx_PyLong_CompactValue(x) \ ((Py_SIZE(x) == 0) ? (sdigit) 0 : ((Py_SIZE(x) < 0) ? -(sdigit)__Pyx_PyLong_Digits(x)[0] : (sdigit)__Pyx_PyLong_Digits(x)[0])) typedef sdigit __Pyx_compact_pylong; typedef digit __Pyx_compact_upylong; #endif #if PY_VERSION_HEX >= 0x030C00A5 #define __Pyx_PyLong_Digits(x) (((PyLongObject*)x)->long_value.ob_digit) #else #define __Pyx_PyLong_Digits(x) (((PyLongObject*)x)->ob_digit) #endif #endif #if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII #include static int __Pyx_sys_getdefaultencoding_not_ascii; static int __Pyx_init_sys_getdefaultencoding_params(void) { PyObject* sys; PyObject* default_encoding = NULL; PyObject* ascii_chars_u = NULL; PyObject* ascii_chars_b = NULL; const char* default_encoding_c; sys = PyImport_ImportModule("sys"); if (!sys) goto bad; default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); Py_DECREF(sys); if (!default_encoding) goto bad; default_encoding_c = PyBytes_AsString(default_encoding); if (!default_encoding_c) goto bad; if (strcmp(default_encoding_c, "ascii") == 0) { __Pyx_sys_getdefaultencoding_not_ascii = 0; } else { char ascii_chars[128]; int c; for (c = 0; c < 128; c++) { ascii_chars[c] = (char) c; } __Pyx_sys_getdefaultencoding_not_ascii = 1; ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); if (!ascii_chars_u) goto bad; ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { PyErr_Format( PyExc_ValueError, "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", default_encoding_c); goto bad; } Py_DECREF(ascii_chars_u); Py_DECREF(ascii_chars_b); } Py_DECREF(default_encoding); return 0; bad: Py_XDECREF(default_encoding); Py_XDECREF(ascii_chars_u); Py_XDECREF(ascii_chars_b); return -1; } #endif #if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) #else #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) // __PYX_DEFAULT_STRING_ENCODING is either a user provided string constant // or we need to look it up here #if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT #include static char* __PYX_DEFAULT_STRING_ENCODING; static int __Pyx_init_sys_getdefaultencoding_params(void) { PyObject* sys; PyObject* default_encoding = NULL; char* default_encoding_c; sys = PyImport_ImportModule("sys"); if (!sys) goto bad; default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); Py_DECREF(sys); if (!default_encoding) goto bad; default_encoding_c = PyBytes_AsString(default_encoding); if (!default_encoding_c) goto bad; __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); Py_DECREF(default_encoding); return 0; bad: Py_XDECREF(default_encoding); return -1; } #endif #endif /////////////// TypeConversions /////////////// /* Type Conversion Functions */ #include static CYTHON_INLINE Py_ssize_t __Pyx_ssize_strlen(const char *s) { size_t len = strlen(s); if (unlikely(len > (size_t) PY_SSIZE_T_MAX)) { PyErr_SetString(PyExc_OverflowError, "byte string is too long"); return -1; } return (Py_ssize_t) len; } static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { Py_ssize_t len = __Pyx_ssize_strlen(c_str); if (unlikely(len < 0)) return NULL; return __Pyx_PyUnicode_FromStringAndSize(c_str, len); } static CYTHON_INLINE PyObject* __Pyx_PyByteArray_FromString(const char* c_str) { Py_ssize_t len = __Pyx_ssize_strlen(c_str); if (unlikely(len < 0)) return NULL; return PyByteArray_FromStringAndSize(c_str, len); } // Py3.7 returns a "const char*" for unicode strings static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { Py_ssize_t ignore; return __Pyx_PyObject_AsStringAndSize(o, &ignore); } #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT #if !CYTHON_PEP393_ENABLED static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { char* defenc_c; // borrowed reference, cached internally in 'o' by CPython PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); if (!defenc) return NULL; defenc_c = PyBytes_AS_STRING(defenc); #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII { char* end = defenc_c + PyBytes_GET_SIZE(defenc); char* c; for (c = defenc_c; c < end; c++) { if ((unsigned char) (*c) >= 128) { // raise the error PyUnicode_AsASCIIString(o); return NULL; } } } #endif /*__PYX_DEFAULT_STRING_ENCODING_IS_ASCII*/ *length = PyBytes_GET_SIZE(defenc); return defenc_c; } #else /* CYTHON_PEP393_ENABLED: */ static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII if (likely(PyUnicode_IS_ASCII(o))) { // cached for the lifetime of the object *length = PyUnicode_GET_LENGTH(o); return PyUnicode_AsUTF8(o); } else { // raise the error PyUnicode_AsASCIIString(o); return NULL; } #else /* __PYX_DEFAULT_STRING_ENCODING_IS_ASCII */ return PyUnicode_AsUTF8AndSize(o, length); #endif /* __PYX_DEFAULT_STRING_ENCODING_IS_ASCII */ } #endif /* CYTHON_PEP393_ENABLED */ #endif // Py3.7 returns a "const char*" for unicode strings static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT if ( #if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII __Pyx_sys_getdefaultencoding_not_ascii && #endif PyUnicode_Check(o)) { return __Pyx_PyUnicode_AsStringAndSize(o, length); } else #endif /* __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT */ #if (!CYTHON_COMPILING_IN_PYPY && !CYTHON_COMPILING_IN_LIMITED_API) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) if (PyByteArray_Check(o)) { *length = PyByteArray_GET_SIZE(o); return PyByteArray_AS_STRING(o); } else #endif { char* result; int r = PyBytes_AsStringAndSize(o, &result, length); if (unlikely(r < 0)) { return NULL; } else { return result; } } } /* Note: __Pyx_PyObject_IsTrue is written to minimize branching. */ static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { int is_true = x == Py_True; if (is_true | (x == Py_False) | (x == Py_None)) return is_true; else return PyObject_IsTrue(x); } static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { int retval; if (unlikely(!x)) return -1; retval = __Pyx_PyObject_IsTrue(x); Py_DECREF(x); return retval; } static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { __Pyx_TypeName result_type_name = __Pyx_PyType_GetName(Py_TYPE(result)); #if PY_MAJOR_VERSION >= 3 if (PyLong_Check(result)) { // CPython issue #17576: warn if 'result' not of exact type int. if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, "__int__ returned non-int (type " __Pyx_FMT_TYPENAME "). " "The ability to return an instance of a strict subclass of int is deprecated, " "and may be removed in a future version of Python.", result_type_name)) { __Pyx_DECREF_TypeName(result_type_name); Py_DECREF(result); return NULL; } __Pyx_DECREF_TypeName(result_type_name); return result; } #endif PyErr_Format(PyExc_TypeError, "__%.4s__ returned non-%.4s (type " __Pyx_FMT_TYPENAME ")", type_name, type_name, result_type_name); __Pyx_DECREF_TypeName(result_type_name); Py_DECREF(result); return NULL; } static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { #if CYTHON_USE_TYPE_SLOTS PyNumberMethods *m; #endif const char *name = NULL; PyObject *res = NULL; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x) || PyLong_Check(x))) #else if (likely(PyLong_Check(x))) #endif return __Pyx_NewRef(x); #if CYTHON_USE_TYPE_SLOTS m = Py_TYPE(x)->tp_as_number; #if PY_MAJOR_VERSION < 3 if (m && m->nb_int) { name = "int"; res = m->nb_int(x); } else if (m && m->nb_long) { name = "long"; res = m->nb_long(x); } #else if (likely(m && m->nb_int)) { name = "int"; res = m->nb_int(x); } #endif #else if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { res = PyNumber_Int(x); } #endif if (likely(res)) { #if PY_MAJOR_VERSION < 3 if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { #else if (unlikely(!PyLong_CheckExact(res))) { #endif return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); } } else if (!PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "an integer is required"); } return res; } {{py: from Cython.Utility import pylong_join }} static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { Py_ssize_t ival; PyObject *x; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_CheckExact(b))) { if (sizeof(Py_ssize_t) >= sizeof(long)) return PyInt_AS_LONG(b); else return PyInt_AsSsize_t(b); } #endif if (likely(PyLong_CheckExact(b))) { #if CYTHON_USE_PYLONG_INTERNALS // handle most common case first to avoid indirect branch and optimise branch prediction if (likely(__Pyx_PyLong_IsCompact(b))) { return __Pyx_PyLong_CompactValue(b); } else { const digit* digits = __Pyx_PyLong_Digits(b); const Py_ssize_t size = __Pyx_PyLong_SignedDigitCount(b); switch (size) { {{for _size in (2, 3, 4)}} {{for _case in (_size, -_size)}} case {{_case}}: if (8 * sizeof(Py_ssize_t) > {{_size}} * PyLong_SHIFT) { return {{'-' if _case < 0 else ''}}(Py_ssize_t) {{pylong_join(_size, 'digits', 'size_t')}}; } break; {{endfor}} {{endfor}} } } #endif return PyLong_AsSsize_t(b); } x = PyNumber_Index(b); if (!x) return -1; ival = PyInt_AsSsize_t(x); Py_DECREF(x); return ival; } static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject* o) { if (sizeof(Py_hash_t) == sizeof(Py_ssize_t)) { return (Py_hash_t) __Pyx_PyIndex_AsSsize_t(o); #if PY_MAJOR_VERSION < 3 } else if (likely(PyInt_CheckExact(o))) { return PyInt_AS_LONG(o); #endif } else { Py_ssize_t ival; PyObject *x; x = PyNumber_Index(o); if (!x) return -1; ival = PyInt_AsLong(x); Py_DECREF(x); return ival; } } static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); } static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { return PyInt_FromSize_t(ival); } /////////////// pynumber_float.proto /////////////// static CYTHON_INLINE PyObject* __Pyx__PyNumber_Float(PyObject* obj); /* proto */ #define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : __Pyx__PyNumber_Float(x)) /////////////// pynumber_float /////////////// //@requires: Optimize.c::pybytes_as_double //@requires: Optimize.c::pyunicode_as_double static CYTHON_INLINE PyObject* __Pyx__PyNumber_Float(PyObject* obj) { // 'obj is PyFloat' is handled in the calling macro double val; if (PyLong_CheckExact(obj)) { #if CYTHON_USE_PYLONG_INTERNALS if (likely(__Pyx_PyLong_IsCompact(obj))) { val = (double) __Pyx_PyLong_CompactValue(obj); goto no_error; } #endif val = PyLong_AsDouble(obj); } else if (PyUnicode_CheckExact(obj)) { val = __Pyx_PyUnicode_AsDouble(obj); } else if (PyBytes_CheckExact(obj)) { val = __Pyx_PyBytes_AsDouble(obj); } else if (PyByteArray_CheckExact(obj)) { val = __Pyx_PyByteArray_AsDouble(obj); } else { return PyNumber_Float(obj); } if (unlikely(val == -1 && PyErr_Occurred())) { return NULL; } #if CYTHON_USE_PYLONG_INTERNALS no_error: #endif return PyFloat_FromDouble(val); } /////////////// GCCDiagnostics.proto /////////////// // GCC diagnostic pragmas were introduced in GCC 4.6 // Used to silence conversion warnings that are ok but cannot be avoided. #if !defined(__INTEL_COMPILER) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) #define __Pyx_HAS_GCC_DIAGNOSTIC #endif /////////////// ToPyCTupleUtility.proto /////////////// static PyObject* {{funcname}}({{struct_type_decl}}); /////////////// ToPyCTupleUtility /////////////// static PyObject* {{funcname}}({{struct_type_decl}} value) { PyObject* item = NULL; PyObject* result = PyTuple_New({{size}}); if (!result) goto bad; {{for ix, component in enumerate(components):}} {{py:attr = "value.f%s" % ix}} item = {{component.to_py_function}}({{attr}}); if (!item) goto bad; PyTuple_SET_ITEM(result, {{ix}}, item); {{endfor}} return result; bad: Py_XDECREF(item); Py_XDECREF(result); return NULL; } /////////////// FromPyCTupleUtility.proto /////////////// static CYTHON_INLINE {{struct_type_decl}} {{funcname}}(PyObject *); /////////////// FromPyCTupleUtility /////////////// #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS static void __Pyx_tuple_{{funcname}}(PyObject * o, {{struct_type_decl}} *result) { {{for ix, component in enumerate(components):}} {{py:attr = "result->f%s" % ix}} {{attr}} = {{component.from_py_function}}(PyTuple_GET_ITEM(o, {{ix}})); if ({{component.error_condition(attr)}}) goto bad; {{endfor}} return; bad: return; } static void __Pyx_list_{{funcname}}(PyObject * o, {{struct_type_decl}} *result) { {{for ix, component in enumerate(components):}} {{py:attr = "result->f%s" % ix}} {{attr}} = {{component.from_py_function}}(PyList_GET_ITEM(o, {{ix}})); if ({{component.error_condition(attr)}}) goto bad; {{endfor}} return; bad: return; } #endif static void __Pyx_seq_{{funcname}}(PyObject * o, {{struct_type_decl}} *result) { if (unlikely(!PySequence_Check(o))) { __Pyx_TypeName o_type_name = __Pyx_PyType_GetName(Py_TYPE(o)); PyErr_Format(PyExc_TypeError, "Expected a sequence of size %zd, got " __Pyx_FMT_TYPENAME, (Py_ssize_t) {{size}}, o_type_name); __Pyx_DECREF_TypeName(o_type_name); goto bad; } else if (unlikely(PySequence_Length(o) != {{size}})) { PyErr_Format(PyExc_TypeError, "Expected a sequence of size %zd, got size %zd", (Py_ssize_t) {{size}}, PySequence_Length(o)); goto bad; } { PyObject *item; {{for ix, component in enumerate(components):}} {{py:attr = "result->f%s" % ix}} item = PySequence_ITEM(o, {{ix}}); if (unlikely(!item)) goto bad; {{attr}} = {{component.from_py_function}}(item); Py_DECREF(item); if ({{component.error_condition(attr)}}) goto bad; {{endfor}} } return; bad: return; } static CYTHON_INLINE {{struct_type_decl}} {{funcname}}(PyObject * o) { {{struct_type_decl}} result; #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS if (likely(PyTuple_Check(o) && PyTuple_GET_SIZE(o) == {{size}})) { __Pyx_tuple_{{funcname}}(o, &result); } else if (likely(PyList_Check(o) && PyList_GET_SIZE(o) == {{size}})) { __Pyx_list_{{funcname}}(o, &result); } else #endif { __Pyx_seq_{{funcname}}(o, &result); } return result; } /////////////// UnicodeAsUCS4.proto /////////////// static CYTHON_INLINE Py_UCS4 __Pyx_PyUnicode_AsPy_UCS4(PyObject*); /////////////// UnicodeAsUCS4 /////////////// static CYTHON_INLINE Py_UCS4 __Pyx_PyUnicode_AsPy_UCS4(PyObject* x) { Py_ssize_t length; #if CYTHON_PEP393_ENABLED length = PyUnicode_GET_LENGTH(x); if (likely(length == 1)) { return PyUnicode_READ_CHAR(x, 0); } #else length = PyUnicode_GET_SIZE(x); if (likely(length == 1)) { return PyUnicode_AS_UNICODE(x)[0]; } #if Py_UNICODE_SIZE == 2 else if (PyUnicode_GET_SIZE(x) == 2) { Py_UCS4 high_val = PyUnicode_AS_UNICODE(x)[0]; if (high_val >= 0xD800 && high_val <= 0xDBFF) { Py_UCS4 low_val = PyUnicode_AS_UNICODE(x)[1]; if (low_val >= 0xDC00 && low_val <= 0xDFFF) { return 0x10000 + (((high_val & ((1<<10)-1)) << 10) | (low_val & ((1<<10)-1))); } } } #endif #endif PyErr_Format(PyExc_ValueError, "only single character unicode strings can be converted to Py_UCS4, " "got length %" CYTHON_FORMAT_SSIZE_T "d", length); return (Py_UCS4)-1; } /////////////// ObjectAsUCS4.proto /////////////// //@requires: UnicodeAsUCS4 #define __Pyx_PyObject_AsPy_UCS4(x) \ (likely(PyUnicode_Check(x)) ? __Pyx_PyUnicode_AsPy_UCS4(x) : __Pyx__PyObject_AsPy_UCS4(x)) static Py_UCS4 __Pyx__PyObject_AsPy_UCS4(PyObject*); /////////////// ObjectAsUCS4 /////////////// static Py_UCS4 __Pyx__PyObject_AsPy_UCS4_raise_error(long ival) { if (ival < 0) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_OverflowError, "cannot convert negative value to Py_UCS4"); } else { PyErr_SetString(PyExc_OverflowError, "value too large to convert to Py_UCS4"); } return (Py_UCS4)-1; } static Py_UCS4 __Pyx__PyObject_AsPy_UCS4(PyObject* x) { long ival; ival = __Pyx_PyInt_As_long(x); if (unlikely(!__Pyx_is_valid_index(ival, 1114111 + 1))) { return __Pyx__PyObject_AsPy_UCS4_raise_error(ival); } return (Py_UCS4)ival; } /////////////// ObjectAsPyUnicode.proto /////////////// static CYTHON_INLINE Py_UNICODE __Pyx_PyObject_AsPy_UNICODE(PyObject*); /////////////// ObjectAsPyUnicode /////////////// static CYTHON_INLINE Py_UNICODE __Pyx_PyObject_AsPy_UNICODE(PyObject* x) { long ival; #if CYTHON_PEP393_ENABLED #if Py_UNICODE_SIZE > 2 const long maxval = 1114111; #else const long maxval = 65535; #endif #else static long maxval = 0; #endif if (PyUnicode_Check(x)) { if (unlikely(__Pyx_PyUnicode_GET_LENGTH(x) != 1)) { PyErr_Format(PyExc_ValueError, "only single character unicode strings can be converted to Py_UNICODE, " "got length %" CYTHON_FORMAT_SSIZE_T "d", __Pyx_PyUnicode_GET_LENGTH(x)); return (Py_UNICODE)-1; } #if CYTHON_PEP393_ENABLED ival = PyUnicode_READ_CHAR(x, 0); #else return PyUnicode_AS_UNICODE(x)[0]; #endif } else { #if !CYTHON_PEP393_ENABLED if (unlikely(!maxval)) maxval = (long)PyUnicode_GetMax(); #endif ival = __Pyx_PyInt_As_long(x); } if (unlikely(!__Pyx_is_valid_index(ival, maxval + 1))) { if (ival < 0) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_OverflowError, "cannot convert negative value to Py_UNICODE"); return (Py_UNICODE)-1; } else { PyErr_SetString(PyExc_OverflowError, "value too large to convert to Py_UNICODE"); } return (Py_UNICODE)-1; } return (Py_UNICODE)ival; } /////////////// CIntToPy.proto /////////////// static CYTHON_INLINE PyObject* {{TO_PY_FUNCTION}}({{TYPE}} value); /////////////// CIntToPy /////////////// //@requires: GCCDiagnostics static CYTHON_INLINE PyObject* {{TO_PY_FUNCTION}}({{TYPE}} value) { #ifdef __Pyx_HAS_GCC_DIAGNOSTIC #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wconversion" #endif const {{TYPE}} neg_one = ({{TYPE}}) -1, const_zero = ({{TYPE}}) 0; #ifdef __Pyx_HAS_GCC_DIAGNOSTIC #pragma GCC diagnostic pop #endif const int is_unsigned = neg_one > const_zero; if (is_unsigned) { if (sizeof({{TYPE}}) < sizeof(long)) { return PyInt_FromLong((long) value); } else if (sizeof({{TYPE}}) <= sizeof(unsigned long)) { return PyLong_FromUnsignedLong((unsigned long) value); #ifdef HAVE_LONG_LONG } else if (sizeof({{TYPE}}) <= sizeof(unsigned PY_LONG_LONG)) { return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); #endif } } else { if (sizeof({{TYPE}}) <= sizeof(long)) { return PyInt_FromLong((long) value); #ifdef HAVE_LONG_LONG } else if (sizeof({{TYPE}}) <= sizeof(PY_LONG_LONG)) { return PyLong_FromLongLong((PY_LONG_LONG) value); #endif } } { int one = 1; int little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&value; #if !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030d0000 return _PyLong_FromByteArray(bytes, sizeof({{TYPE}}), little, !is_unsigned); #else // call int.from_bytes() PyObject *from_bytes, *result = NULL; PyObject *py_bytes = NULL, *arg_tuple = NULL, *kwds = NULL, *order_str = NULL; from_bytes = PyObject_GetAttrString((PyObject*)&PyLong_Type, "from_bytes"); if (!from_bytes) return NULL; py_bytes = PyBytes_FromStringAndSize((char*)bytes, sizeof({{TYPE}})); if (!py_bytes) goto limited_bad; // I'm deliberately not using PYIDENT here because this code path is very unlikely // to ever run so it seems a pessimization mostly. order_str = PyUnicode_FromString(little ? "little" : "big"); if (!order_str) goto limited_bad; arg_tuple = PyTuple_Pack(2, py_bytes, order_str); if (!arg_tuple) goto limited_bad; if (!is_unsigned) { // default is signed=False kwds = PyDict_New(); if (!kwds) goto limited_bad; if (PyDict_SetItemString(kwds, "signed", __Pyx_NewRef(Py_True))) goto limited_bad; } result = PyObject_Call(from_bytes, arg_tuple, kwds); limited_bad: Py_XDECREF(kwds); Py_XDECREF(arg_tuple); Py_XDECREF(order_str); Py_XDECREF(py_bytes); Py_XDECREF(from_bytes); return result; #endif } } /////////////// CIntToDigits /////////////// static const char DIGIT_PAIRS_10[2*10*10+1] = { "00010203040506070809" "10111213141516171819" "20212223242526272829" "30313233343536373839" "40414243444546474849" "50515253545556575859" "60616263646566676869" "70717273747576777879" "80818283848586878889" "90919293949596979899" }; static const char DIGIT_PAIRS_8[2*8*8+1] = { "0001020304050607" "1011121314151617" "2021222324252627" "3031323334353637" "4041424344454647" "5051525354555657" "6061626364656667" "7071727374757677" }; static const char DIGITS_HEX[2*16+1] = { "0123456789abcdef" "0123456789ABCDEF" }; /////////////// CIntToPyUnicode.proto /////////////// static CYTHON_INLINE PyObject* {{TO_PY_FUNCTION}}({{TYPE}} value, Py_ssize_t width, char padding_char, char format_char); /////////////// CIntToPyUnicode /////////////// //@requires: StringTools.c::IncludeStringH //@requires: StringTools.c::BuildPyUnicode //@requires: CIntToDigits //@requires: GCCDiagnostics // NOTE: inlining because most arguments are constant, which collapses lots of code below static CYTHON_INLINE PyObject* {{TO_PY_FUNCTION}}({{TYPE}} value, Py_ssize_t width, char padding_char, char format_char) { // simple and conservative C string allocation on the stack: each byte gives at most 3 digits, plus sign char digits[sizeof({{TYPE}})*3+2]; // 'dpos' points to end of digits array + 1 initially to allow for pre-decrement looping char *dpos, *end = digits + sizeof({{TYPE}})*3+2; const char *hex_digits = DIGITS_HEX; Py_ssize_t length, ulength; int prepend_sign, last_one_off; {{TYPE}} remaining; #ifdef __Pyx_HAS_GCC_DIAGNOSTIC #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wconversion" #endif const {{TYPE}} neg_one = ({{TYPE}}) -1, const_zero = ({{TYPE}}) 0; #ifdef __Pyx_HAS_GCC_DIAGNOSTIC #pragma GCC diagnostic pop #endif const int is_unsigned = neg_one > const_zero; if (format_char == 'X') { hex_digits += 16; format_char = 'x'; } // surprise: even trivial sprintf() calls don't get optimised in gcc (4.8) remaining = value; /* not using abs(value) to avoid overflow problems */ last_one_off = 0; dpos = end; do { int digit_pos; switch (format_char) { case 'o': digit_pos = abs((int)(remaining % (8*8))); remaining = ({{TYPE}}) (remaining / (8*8)); dpos -= 2; memcpy(dpos, DIGIT_PAIRS_8 + digit_pos * 2, 2); /* copy 2 digits at a time, unaligned */ last_one_off = (digit_pos < 8); break; case 'd': digit_pos = abs((int)(remaining % (10*10))); remaining = ({{TYPE}}) (remaining / (10*10)); dpos -= 2; memcpy(dpos, DIGIT_PAIRS_10 + digit_pos * 2, 2); /* copy 2 digits at a time, unaligned */ last_one_off = (digit_pos < 10); break; case 'x': *(--dpos) = hex_digits[abs((int)(remaining % 16))]; remaining = ({{TYPE}}) (remaining / 16); break; default: assert(0); break; } } while (unlikely(remaining != 0)); // Correct dpos by 1 if we read an excess digit. assert(!last_one_off || *dpos == '0'); dpos += last_one_off; length = end - dpos; ulength = length; prepend_sign = 0; if (!is_unsigned && value <= neg_one) { if (padding_char == ' ' || width <= length + 1) { *(--dpos) = '-'; ++length; } else { prepend_sign = 1; } ++ulength; } if (width > ulength) { ulength = width; } // single character unicode strings are cached in CPython => use PyUnicode_FromOrdinal() for them if (ulength == 1) { return PyUnicode_FromOrdinal(*dpos); } return __Pyx_PyUnicode_BuildFromAscii(ulength, dpos, (int) length, prepend_sign, padding_char); } /////////////// CBIntToPyUnicode.proto /////////////// #define {{TO_PY_FUNCTION}}(value) \ ((value) ? __Pyx_NewRef({{TRUE_CONST}}) : __Pyx_NewRef({{FALSE_CONST}})) /////////////// PyIntFromDouble.proto /////////////// #if PY_MAJOR_VERSION < 3 static CYTHON_INLINE PyObject* __Pyx_PyInt_FromDouble(double value); #else #define __Pyx_PyInt_FromDouble(value) PyLong_FromDouble(value) #endif /////////////// PyIntFromDouble /////////////// #if PY_MAJOR_VERSION < 3 static CYTHON_INLINE PyObject* __Pyx_PyInt_FromDouble(double value) { if (value >= (double)LONG_MIN && value <= (double)LONG_MAX) { return PyInt_FromLong((long)value); } return PyLong_FromDouble(value); } #endif /////////////// CIntFromPyVerify /////////////// // see CIntFromPy #define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value) \ __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) #define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value) \ __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) #define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc) \ { \ func_type value = func_value; \ if (sizeof(target_type) < sizeof(func_type)) { \ if (unlikely(value != (func_type) (target_type) value)) { \ func_type zero = 0; \ if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred())) \ return (target_type) -1; \ if (is_unsigned && unlikely(value < zero)) \ goto raise_neg_overflow; \ else \ goto raise_overflow; \ } \ } \ return (target_type) value; \ } /////////////// CIntFromPy.proto /////////////// static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *); /////////////// CIntFromPy /////////////// //@requires: CIntFromPyVerify //@requires: GCCDiagnostics {{py: from Cython.Utility import pylong_join }} static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) { #ifdef __Pyx_HAS_GCC_DIAGNOSTIC #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wconversion" #endif const {{TYPE}} neg_one = ({{TYPE}}) -1, const_zero = ({{TYPE}}) 0; #ifdef __Pyx_HAS_GCC_DIAGNOSTIC #pragma GCC diagnostic pop #endif const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { if ((sizeof({{TYPE}}) < sizeof(long))) { __PYX_VERIFY_RETURN_INT({{TYPE}}, long, PyInt_AS_LONG(x)) } else { long val = PyInt_AS_LONG(x); if (is_unsigned && unlikely(val < 0)) { goto raise_neg_overflow; } return ({{TYPE}}) val; } } else #endif if (likely(PyLong_Check(x))) { if (is_unsigned) { #if CYTHON_USE_PYLONG_INTERNALS if (unlikely(__Pyx_PyLong_IsNeg(x))) { goto raise_neg_overflow; //} else if (__Pyx_PyLong_IsZero(x)) { // return ({{TYPE}}) 0; } else if (__Pyx_PyLong_IsCompact(x)) { __PYX_VERIFY_RETURN_INT({{TYPE}}, __Pyx_compact_upylong, __Pyx_PyLong_CompactValueUnsigned(x)) } else { const digit* digits = __Pyx_PyLong_Digits(x); assert(__Pyx_PyLong_DigitCount(x) > 1); switch (__Pyx_PyLong_DigitCount(x)) { {{for _size in (2, 3, 4)}} case {{_size}}: if ((8 * sizeof({{TYPE}}) > {{_size-1}} * PyLong_SHIFT)) { if ((8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT)) { __PYX_VERIFY_RETURN_INT({{TYPE}}, unsigned long, {{pylong_join(_size, 'digits')}}) } else if ((8 * sizeof({{TYPE}}) >= {{_size}} * PyLong_SHIFT)) { return ({{TYPE}}) {{pylong_join(_size, 'digits', TYPE)}}; } } break; {{endfor}} } } #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A7 if (unlikely(Py_SIZE(x) < 0)) { goto raise_neg_overflow; } #else { // misuse Py_False as a quick way to compare to a '0' int object in PyPy int result = PyObject_RichCompareBool(x, Py_False, Py_LT); if (unlikely(result < 0)) return ({{TYPE}}) -1; if (unlikely(result == 1)) goto raise_neg_overflow; } #endif if ((sizeof({{TYPE}}) <= sizeof(unsigned long))) { __PYX_VERIFY_RETURN_INT_EXC({{TYPE}}, unsigned long, PyLong_AsUnsignedLong(x)) #ifdef HAVE_LONG_LONG } else if ((sizeof({{TYPE}}) <= sizeof(unsigned PY_LONG_LONG))) { __PYX_VERIFY_RETURN_INT_EXC({{TYPE}}, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) #endif } } else { // signed #if CYTHON_USE_PYLONG_INTERNALS if (__Pyx_PyLong_IsCompact(x)) { __PYX_VERIFY_RETURN_INT({{TYPE}}, __Pyx_compact_pylong, __Pyx_PyLong_CompactValue(x)) } else { const digit* digits = __Pyx_PyLong_Digits(x); assert(__Pyx_PyLong_DigitCount(x) > 1); switch (__Pyx_PyLong_SignedDigitCount(x)) { {{for _size in (2, 3, 4)}} {{for _case in (-_size, _size)}} case {{_case}}: if ((8 * sizeof({{TYPE}}){{' - 1' if _case < 0 else ''}} > {{_size-1}} * PyLong_SHIFT)) { if ((8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT)) { __PYX_VERIFY_RETURN_INT({{TYPE}}, {{'long' if _case < 0 else 'unsigned long'}}, {{'-(long) ' if _case < 0 else ''}}{{pylong_join(_size, 'digits')}}) } else if ((8 * sizeof({{TYPE}}) - 1 > {{_size}} * PyLong_SHIFT)) { return ({{TYPE}}) ({{'((%s)-1)*' % TYPE if _case < 0 else ''}}{{pylong_join(_size, 'digits', TYPE)}}); } } break; {{endfor}} {{endfor}} } } #endif if ((sizeof({{TYPE}}) <= sizeof(long))) { __PYX_VERIFY_RETURN_INT_EXC({{TYPE}}, long, PyLong_AsLong(x)) #ifdef HAVE_LONG_LONG } else if ((sizeof({{TYPE}}) <= sizeof(PY_LONG_LONG))) { __PYX_VERIFY_RETURN_INT_EXC({{TYPE}}, PY_LONG_LONG, PyLong_AsLongLong(x)) #endif } } {{if IS_ENUM}} PyErr_SetString(PyExc_RuntimeError, "_PyLong_AsByteArray() not available, cannot convert large enums"); return ({{TYPE}}) -1; {{else}} // large integer type and no access to PyLong internals => allow for a more expensive conversion { {{TYPE}} val; PyObject *v = __Pyx_PyNumber_IntOrLong(x); #if PY_MAJOR_VERSION < 3 if (likely(v) && !PyLong_Check(v)) { PyObject *tmp = v; v = PyNumber_Long(tmp); Py_DECREF(tmp); } #endif if (likely(v)) { int ret = -1; #if PY_VERSION_HEX < 0x030d0000 && !(CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API) || defined(_PyLong_AsByteArray) int one = 1; int is_little = (int)*(unsigned char *)&one; unsigned char *bytes = (unsigned char *)&val; ret = _PyLong_AsByteArray((PyLongObject *)v, bytes, sizeof(val), is_little, !is_unsigned); #else // Inefficient copy of bit chunks through the C-API. Probably still better than a "cannot do this" exception. // This is substantially faster in CPython (>30%) than calling "int.to_bytes()" PyObject *stepval = NULL, *mask = NULL, *shift = NULL; int bits, remaining_bits, is_negative = 0; long idigit; int chunk_size = (sizeof(long) < 8) ? 30 : 62; // use exact PyLong to prevent user defined &&/<= (1L << remaining_bits))) goto raise_overflow; val |= (({{TYPE}}) idigit) << bits; #if CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030B0000 unpacking_done: #endif // handle sign and overflow into sign bit if (!is_unsigned) { // gcc warns about unsigned (val < 0) => test sign bit instead if (unlikely(val & ((({{TYPE}}) 1) << (sizeof({{TYPE}}) * 8 - 1)))) goto raise_overflow; // undo the PyNumber_Invert() above if (is_negative) val = ~val; } ret = 0; done: Py_XDECREF(shift); Py_XDECREF(mask); Py_XDECREF(stepval); #endif Py_DECREF(v); if (likely(!ret)) return val; } return ({{TYPE}}) -1; } {{endif}} } else { {{TYPE}} val; PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); if (!tmp) return ({{TYPE}}) -1; val = {{FROM_PY_FUNCTION}}(tmp); Py_DECREF(tmp); return val; } raise_overflow: PyErr_SetString(PyExc_OverflowError, "value too large to convert to {{TYPE}}"); return ({{TYPE}}) -1; raise_neg_overflow: PyErr_SetString(PyExc_OverflowError, "can't convert negative value to {{TYPE}}"); return ({{TYPE}}) -1; } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/UFuncs.pyx0000644000175100001770000000420300000000000020447 0ustar00runnerdocker00000000000000##################### UFuncDefinition ###################### cdef extern from *: ctypedef int npy_intp struct PyObject PyObject* __Pyx_NewRef(object) {{inline_func_declaration}} # variable names have to come from tempita to avoid duplication @cname("{{func_cname}}") cdef void {{func_cname}}(char **args, const npy_intp *dimensions, const npy_intp* steps, void* data) except * {{"nogil" if will_be_called_without_gil else ""}}: cdef npy_intp i cdef npy_intp n = dimensions[0] {{for idx, tp in enumerate(in_types)}} cdef char* in_{{idx}} = args[{{idx}}] cdef {{tp.empty_declaration_code(pyrex=True)}} cast_in_{{idx}} {{endfor}} {{for idx, tp in enumerate(out_types)}} cdef char* out_{{idx}} = args[{{idx+len(in_types)}}] cdef {{tp.empty_declaration_code(pyrex=True)}} cast_out_{{idx}} {{endfor}} {{for idx in range(len(out_types)+len(in_types))}} cdef npy_intp step_{{idx}} = steps[{{idx}}] {{endfor}} {{"with gil" if (not nogil and will_be_called_without_gil) else "if True"}}: for i in range(n): {{for idx, tp in enumerate(in_types)}} {{if tp.is_pyobject}} cast_in_{{idx}} = (<{{tp.empty_declaration_code(pyrex=True)}}>(in_{{idx}})[0]) {{else}} cast_in_{{idx}} = (<{{tp.empty_declaration_code(pyrex=True)}}*>in_{{idx}})[0] {{endif}} {{endfor}} {{", ".join("cast_out_{}".format(idx) for idx in range(len(out_types)))}} = \ {{inline_func_call}}({{", ".join("cast_in_{}".format(idx) for idx in range(len(in_types)))}}) {{for idx, tp in enumerate(out_types)}} {{if tp.is_pyobject}} (out_{{idx}})[0] = __Pyx_NewRef(cast_out_{{idx}}) {{else}} (<{{tp.empty_declaration_code(pyrex=True)}}*>out_{{idx}})[0] = cast_out_{{idx}} {{endif}} {{endfor}} {{for idx in range(len(in_types))}} in_{{idx}} += step_{{idx}} {{endfor}} {{for idx in range(len(out_types))}} out_{{idx}} += step_{{idx+len(in_types)}} {{endfor}} ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/UFuncs_C.c0000644000175100001770000000275700000000000020327 0ustar00runnerdocker00000000000000///////////////////////// UFuncsInit.proto ///////////////////////// //@proto_block: utility_code_proto_before_types #include #include // account for change in type of arguments to PyUFuncGenericFunction in Numpy 1.19.x // Unfortunately we can only test against Numpy version 1.20.x since it wasn't marked // as an API break. Therefore, I'm "solving" the issue by casting function pointer types // on lower Numpy versions. #if NPY_API_VERSION >= 0x0000000e // Numpy 1.20.x #define __PYX_PYUFUNCGENERICFUNCTION_CAST(x) x #else #define __PYX_PYUFUNCGENERICFUNCTION_CAST(x) (PyUFuncGenericFunction)x #endif /////////////////////// UFuncConsts.proto //////////////////// // getter functions because we can't forward-declare arrays static PyUFuncGenericFunction* {{ufunc_funcs_name}}(void); /* proto */ static char* {{ufunc_types_name}}(void); /* proto */ static void* {{ufunc_data_name}}[] = {NULL}; /* always null */ /////////////////////// UFuncConsts ///////////////////////// static PyUFuncGenericFunction* {{ufunc_funcs_name}}(void) { static PyUFuncGenericFunction arr[] = { {{for loop, cname in looper(func_cnames)}} __PYX_PYUFUNCGENERICFUNCTION_CAST(&{{cname}}){{if not loop.last}},{{endif}} {{endfor}} }; return arr; } static char* {{ufunc_types_name}}(void) { static char arr[] = { {{for loop, tp in looper(type_constants)}} {{tp}}{{if not loop.last}},{{endif}} {{endfor}} }; return arr; } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/__init__.py0000644000175100001770000000220700000000000020615 0ustar00runnerdocker00000000000000 def pylong_join(count, digits_ptr='digits', join_type='unsigned long'): """ Generate an unrolled shift-then-or loop over the first 'count' digits. Assumes that they fit into 'join_type'. (((d[2] << n) | d[1]) << n) | d[0] """ return ('(' * (count * 2) + ' | '.join( "(%s)%s[%d])%s)" % (join_type, digits_ptr, _i, " << PyLong_SHIFT" if _i else '') for _i in range(count-1, -1, -1))) # although it could potentially make use of data independence, # this implementation is a bit slower than the simpler one above def _pylong_join(count, digits_ptr='digits', join_type='unsigned long'): """ Generate an or-ed series of shifts for the first 'count' digits. Assumes that they fit into 'join_type'. (d[2] << 2*n) | (d[1] << 1*n) | d[0] """ def shift(n): # avoid compiler warnings for overly large shifts that will be discarded anyway return " << (%d * PyLong_SHIFT < 8 * sizeof(%s) ? %d * PyLong_SHIFT : 0)" % (n, join_type, n) if n else '' return '(%s)' % ' | '.join( "(((%s)%s[%d])%s)" % (join_type, digits_ptr, i, shift(i)) for i in range(count-1, -1, -1)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utility/arrayarray.h0000644000175100001770000000777100000000000021045 0ustar00runnerdocker00000000000000/////////////// ArrayAPI.proto /////////////// // arrayarray.h // // Artificial C-API for Python's type, // used by array.pxd // // last changes: 2009-05-15 rk // 2012-05-02 andreasvc // (see revision control) // #ifndef _ARRAYARRAY_H #define _ARRAYARRAY_H // These two forward declarations are explicitly handled in the type // declaration code, as including them here is too late for cython-defined // types to use them. // struct arrayobject; // typedef struct arrayobject arrayobject; // All possible arraydescr values are defined in the vector "descriptors" // below. That's defined later because the appropriate get and set // functions aren't visible yet. typedef struct arraydescr { int typecode; int itemsize; PyObject * (*getitem)(struct arrayobject *, Py_ssize_t); int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *); #if PY_MAJOR_VERSION >= 3 char *formats; #endif } arraydescr; struct arrayobject { PyObject_HEAD Py_ssize_t ob_size; union { char *ob_item; float *as_floats; double *as_doubles; int *as_ints; unsigned int *as_uints; unsigned char *as_uchars; signed char *as_schars; char *as_chars; unsigned long *as_ulongs; long *as_longs; #if PY_MAJOR_VERSION >= 3 unsigned long long *as_ulonglongs; long long *as_longlongs; #endif short *as_shorts; unsigned short *as_ushorts; Py_UNICODE *as_pyunicodes; void *as_voidptr; } data; Py_ssize_t allocated; struct arraydescr *ob_descr; PyObject *weakreflist; /* List of weak references */ #if PY_MAJOR_VERSION >= 3 int ob_exports; /* Number of exported buffers */ #endif }; #ifndef NO_NEWARRAY_INLINE // fast creation of a new array static CYTHON_INLINE PyObject * newarrayobject(PyTypeObject *type, Py_ssize_t size, struct arraydescr *descr) { arrayobject *op; size_t nbytes; if (size < 0) { PyErr_BadInternalCall(); return NULL; } nbytes = size * descr->itemsize; // Check for overflow if (nbytes / descr->itemsize != (size_t)size) { return PyErr_NoMemory(); } op = (arrayobject *) type->tp_alloc(type, 0); if (op == NULL) { return NULL; } op->ob_descr = descr; op->allocated = size; op->weakreflist = NULL; __Pyx_SET_SIZE(op, size); if (size <= 0) { op->data.ob_item = NULL; } else { op->data.ob_item = PyMem_NEW(char, nbytes); if (op->data.ob_item == NULL) { Py_DECREF(op); return PyErr_NoMemory(); } } return (PyObject *) op; } #else PyObject* newarrayobject(PyTypeObject *type, Py_ssize_t size, struct arraydescr *descr); #endif /* ifndef NO_NEWARRAY_INLINE */ // fast resize (reallocation to the point) // not designed for filing small increments (but for fast opaque array apps) static CYTHON_INLINE int resize(arrayobject *self, Py_ssize_t n) { void *items = (void*) self->data.ob_item; PyMem_Resize(items, char, (size_t)(n * self->ob_descr->itemsize)); if (items == NULL) { PyErr_NoMemory(); return -1; } self->data.ob_item = (char*) items; __Pyx_SET_SIZE(self, n); self->allocated = n; return 0; } // suitable for small increments; over allocation 50% ; static CYTHON_INLINE int resize_smart(arrayobject *self, Py_ssize_t n) { void *items = (void*) self->data.ob_item; Py_ssize_t newsize; if (n < self->allocated && n*4 > self->allocated) { __Pyx_SET_SIZE(self, n); return 0; } newsize = n + (n / 2) + 1; if (newsize <= n) { /* overflow */ PyErr_NoMemory(); return -1; } PyMem_Resize(items, char, (size_t)(newsize * self->ob_descr->itemsize)); if (items == NULL) { PyErr_NoMemory(); return -1; } self->data.ob_item = (char*) items; __Pyx_SET_SIZE(self, n); self->allocated = newsize; return 0; } #endif /* _ARRAYARRAY_H */ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utils.pxd0000644000175100001770000000010500000000000016651 0ustar00runnerdocker00000000000000 cdef class _TryFinallyGeneratorContextManager: cdef object _gen ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/Utils.py0000644000175100001770000005265700000000000016531 0ustar00runnerdocker00000000000000""" Cython -- Things that don't belong anywhere else in particular """ from __future__ import absolute_import import cython cython.declare( basestring=object, os=object, sys=object, re=object, io=object, codecs=object, glob=object, shutil=object, tempfile=object, cython_version=object, _function_caches=list, _parse_file_version=object, _match_file_encoding=object, ) try: from __builtin__ import basestring except ImportError: basestring = str try: FileNotFoundError except NameError: FileNotFoundError = OSError import os import sys import re import io import codecs import glob import shutil import tempfile from functools import wraps from . import __version__ as cython_version PACKAGE_FILES = ("__init__.py", "__init__.pyc", "__init__.pyx", "__init__.pxd") _build_cache_name = "__{0}_cache".format _CACHE_NAME_PATTERN = re.compile(r"^__(.+)_cache$") modification_time = os.path.getmtime GENERATED_BY_MARKER = "/* Generated by Cython %s */" % cython_version GENERATED_BY_MARKER_BYTES = GENERATED_BY_MARKER.encode('us-ascii') class _TryFinallyGeneratorContextManager(object): """ Fast, bare minimum @contextmanager, only for try-finally, not for exception handling. """ def __init__(self, gen): self._gen = gen def __enter__(self): return next(self._gen) def __exit__(self, exc_type, exc_val, exc_tb): try: next(self._gen) except (StopIteration, GeneratorExit): pass def try_finally_contextmanager(gen_func): @wraps(gen_func) def make_gen(*args, **kwargs): return _TryFinallyGeneratorContextManager(gen_func(*args, **kwargs)) return make_gen _function_caches = [] def clear_function_caches(): for cache in _function_caches: cache.clear() def cached_function(f): cache = {} _function_caches.append(cache) uncomputed = object() @wraps(f) def wrapper(*args): res = cache.get(args, uncomputed) if res is uncomputed: res = cache[args] = f(*args) return res wrapper.uncached = f return wrapper def _find_cache_attributes(obj): """The function iterates over the attributes of the object and, if it finds the name of the cache, it returns it and the corresponding method name. The method may not be present in the object. """ for attr_name in dir(obj): match = _CACHE_NAME_PATTERN.match(attr_name) if match is not None: yield attr_name, match.group(1) def clear_method_caches(obj): """Removes every cache found in the object, if a corresponding method exists for that cache. """ for cache_name, method_name in _find_cache_attributes(obj): if hasattr(obj, method_name): delattr(obj, cache_name) # if there is no corresponding method, then we assume # that this attribute was not created by our cached method def cached_method(f): cache_name = _build_cache_name(f.__name__) def wrapper(self, *args): cache = getattr(self, cache_name, None) if cache is None: cache = {} setattr(self, cache_name, cache) if args in cache: return cache[args] res = cache[args] = f(self, *args) return res return wrapper def replace_suffix(path, newsuf): base, _ = os.path.splitext(path) return base + newsuf def open_new_file(path): if os.path.exists(path): # Make sure to create a new file here so we can # safely hard link the output files. os.unlink(path) # we use the ISO-8859-1 encoding here because we only write pure # ASCII strings or (e.g. for file names) byte encoded strings as # Unicode, so we need a direct mapping from the first 256 Unicode # characters to a byte sequence, which ISO-8859-1 provides # note: can't use io.open() in Py2 as we may be writing str objects return codecs.open(path, "w", encoding="ISO-8859-1") def castrate_file(path, st): # Remove junk contents from an output file after a # failed compilation. # Also sets access and modification times back to # those specified by st (a stat struct). if not is_cython_generated_file(path, allow_failed=True, if_not_found=False): return try: f = open_new_file(path) except EnvironmentError: pass else: f.write( "#error Do not use this file, it is the result of a failed Cython compilation.\n") f.close() if st: os.utime(path, (st.st_atime, st.st_mtime-1)) def is_cython_generated_file(path, allow_failed=False, if_not_found=True): failure_marker = b"#error Do not use this file, it is the result of a failed Cython compilation." file_content = None if os.path.exists(path): try: with open(path, "rb") as f: file_content = f.read(len(failure_marker)) except (OSError, IOError): pass # Probably just doesn't exist any more if file_content is None: # file does not exist (yet) return if_not_found return ( # Cython C file? file_content.startswith(b"/* Generated by Cython ") or # Cython output file after previous failures? (allow_failed and file_content == failure_marker) or # Let's allow overwriting empty files as well. They might have resulted from previous failures. not file_content ) def file_generated_by_this_cython(path): file_content = b'' if os.path.exists(path): try: with open(path, "rb") as f: file_content = f.read(len(GENERATED_BY_MARKER_BYTES)) except (OSError, IOError): pass # Probably just doesn't exist any more return file_content and file_content.startswith(GENERATED_BY_MARKER_BYTES) def file_newer_than(path, time): ftime = modification_time(path) return ftime > time def safe_makedirs(path): try: os.makedirs(path) except OSError: if not os.path.isdir(path): raise def copy_file_to_dir_if_newer(sourcefile, destdir): """ Copy file sourcefile to directory destdir (creating it if needed), preserving metadata. If the destination file exists and is not older than the source file, the copying is skipped. """ destfile = os.path.join(destdir, os.path.basename(sourcefile)) try: desttime = modification_time(destfile) except OSError: # New file does not exist, destdir may or may not exist safe_makedirs(destdir) else: # New file already exists if not file_newer_than(sourcefile, desttime): return shutil.copy2(sourcefile, destfile) @cached_function def find_root_package_dir(file_path): dir = os.path.dirname(file_path) if file_path == dir: return dir elif is_package_dir(dir): return find_root_package_dir(dir) else: return dir @cached_function def check_package_dir(dir_path, package_names): namespace = True for dirname in package_names: dir_path = os.path.join(dir_path, dirname) has_init = contains_init(dir_path) if has_init: namespace = False return dir_path, namespace @cached_function def contains_init(dir_path): for filename in PACKAGE_FILES: path = os.path.join(dir_path, filename) if path_exists(path): return 1 def is_package_dir(dir_path): if contains_init(dir_path): return 1 @cached_function def path_exists(path): # try on the filesystem first if os.path.exists(path): return True # figure out if a PEP 302 loader is around try: loader = __loader__ # XXX the code below assumes a 'zipimport.zipimporter' instance # XXX should be easy to generalize, but too lazy right now to write it archive_path = getattr(loader, 'archive', None) if archive_path: normpath = os.path.normpath(path) if normpath.startswith(archive_path): arcname = normpath[len(archive_path)+1:] try: loader.get_data(arcname) return True except IOError: return False except NameError: pass return False _parse_file_version = re.compile(r".*[.]cython-([0-9]+)[.][^./\\]+$").findall @cached_function def find_versioned_file(directory, filename, suffix, _current_version=int(re.sub(r"^([0-9]+)[.]([0-9]+).*", r"\1\2", cython_version))): """ Search a directory for versioned pxd files, e.g. "lib.cython-30.pxd" for a Cython 3.0+ version. @param directory: the directory to search @param filename: the filename without suffix @param suffix: the filename extension including the dot, e.g. ".pxd" @return: the file path if found, or None """ assert not suffix or suffix[:1] == '.' path_prefix = os.path.join(directory, filename) matching_files = glob.glob(path_prefix + ".cython-*" + suffix) path = path_prefix + suffix if not os.path.exists(path): path = None best_match = (-1, path) # last resort, if we do not have versioned .pxd files for path in matching_files: versions = _parse_file_version(path) if versions: int_version = int(versions[0]) # Let's assume no duplicates. if best_match[0] < int_version <= _current_version: best_match = (int_version, path) return best_match[1] # file name encodings def decode_filename(filename): if isinstance(filename, bytes): try: filename_encoding = sys.getfilesystemencoding() if filename_encoding is None: filename_encoding = sys.getdefaultencoding() filename = filename.decode(filename_encoding) except UnicodeDecodeError: pass return filename # support for source file encoding detection _match_file_encoding = re.compile(br"(\w*coding)[:=]\s*([-\w.]+)").search def detect_opened_file_encoding(f, default='UTF-8'): # PEPs 263 and 3120 # Most of the time the first two lines fall in the first couple of hundred chars, # and this bulk read/split is much faster. lines = () start = b'' while len(lines) < 3: data = f.read(500) start += data lines = start.split(b"\n") if not data: break m = _match_file_encoding(lines[0]) if m and m.group(1) != b'c_string_encoding': return m.group(2).decode('iso8859-1') elif len(lines) > 1: m = _match_file_encoding(lines[1]) if m: return m.group(2).decode('iso8859-1') return default def skip_bom(f): """ Read past a BOM at the beginning of a source file. This could be added to the scanner, but it's *substantially* easier to keep it at this level. """ if f.read(1) != u'\uFEFF': f.seek(0) def open_source_file(source_filename, encoding=None, error_handling=None): stream = None try: if encoding is None: # Most of the time the encoding is not specified, so try hard to open the file only once. f = io.open(source_filename, 'rb') encoding = detect_opened_file_encoding(f) f.seek(0) stream = io.TextIOWrapper(f, encoding=encoding, errors=error_handling) else: stream = io.open(source_filename, encoding=encoding, errors=error_handling) except OSError: if os.path.exists(source_filename): raise # File is there, but something went wrong reading from it. # Allow source files to be in zip files etc. try: loader = __loader__ if source_filename.startswith(loader.archive): stream = open_source_from_loader( loader, source_filename, encoding, error_handling) except (NameError, AttributeError): pass if stream is None: raise FileNotFoundError(source_filename) skip_bom(stream) return stream def open_source_from_loader(loader, source_filename, encoding=None, error_handling=None): nrmpath = os.path.normpath(source_filename) arcname = nrmpath[len(loader.archive)+1:] data = loader.get_data(arcname) return io.TextIOWrapper(io.BytesIO(data), encoding=encoding, errors=error_handling) def str_to_number(value): # note: this expects a string as input that was accepted by the # parser already, with an optional "-" sign in front is_neg = False if value[:1] == '-': is_neg = True value = value[1:] if len(value) < 2: value = int(value, 0) elif value[0] == '0': literal_type = value[1] # 0'o' - 0'b' - 0'x' if literal_type in 'xX': # hex notation ('0x1AF') value = strip_py2_long_suffix(value) value = int(value[2:], 16) elif literal_type in 'oO': # Py3 octal notation ('0o136') value = int(value[2:], 8) elif literal_type in 'bB': # Py3 binary notation ('0b101') value = int(value[2:], 2) else: # Py2 octal notation ('0136') value = int(value, 8) else: value = int(value, 0) return -value if is_neg else value def strip_py2_long_suffix(value_str): """ Python 2 likes to append 'L' to stringified numbers which in then can't process when converting them to numbers. """ if value_str[-1] in 'lL': return value_str[:-1] return value_str def long_literal(value): if isinstance(value, basestring): value = str_to_number(value) return not -2**31 <= value < 2**31 @cached_function def get_cython_cache_dir(): r""" Return the base directory containing Cython's caches. Priority: 1. CYTHON_CACHE_DIR 2. (OS X): ~/Library/Caches/Cython (posix not OS X): XDG_CACHE_HOME/cython if XDG_CACHE_HOME defined 3. ~/.cython """ if 'CYTHON_CACHE_DIR' in os.environ: return os.environ['CYTHON_CACHE_DIR'] parent = None if os.name == 'posix': if sys.platform == 'darwin': parent = os.path.expanduser('~/Library/Caches') else: # this could fallback on ~/.cache parent = os.environ.get('XDG_CACHE_HOME') if parent and os.path.isdir(parent): return os.path.join(parent, 'cython') # last fallback: ~/.cython return os.path.expanduser(os.path.join('~', '.cython')) @try_finally_contextmanager def captured_fd(stream=2, encoding=None): orig_stream = os.dup(stream) # keep copy of original stream try: with tempfile.TemporaryFile(mode="a+b") as temp_file: def read_output(_output=[b'']): if not temp_file.closed: temp_file.seek(0) _output[0] = temp_file.read() return _output[0] os.dup2(temp_file.fileno(), stream) # replace stream by copy of pipe def get_output(): result = read_output() return result.decode(encoding) if encoding else result yield get_output # note: @contextlib.contextmanager requires try-finally here os.dup2(orig_stream, stream) # restore original stream read_output() # keep the output in case it's used after closing the context manager finally: os.close(orig_stream) def get_encoding_candidates(): candidates = [sys.getdefaultencoding()] for stream in (sys.stdout, sys.stdin, sys.__stdout__, sys.__stdin__): encoding = getattr(stream, 'encoding', None) # encoding might be None (e.g. somebody redirects stdout): if encoding is not None and encoding not in candidates: candidates.append(encoding) return candidates def prepare_captured(captured): captured_bytes = captured.strip() if not captured_bytes: return None for encoding in get_encoding_candidates(): try: return captured_bytes.decode(encoding) except UnicodeDecodeError: pass # last resort: print at least the readable ascii parts correctly. return captured_bytes.decode('latin-1') def print_captured(captured, output, header_line=None): captured = prepare_captured(captured) if captured: if header_line: output.write(header_line) output.write(captured) def print_bytes(s, header_text=None, end=b'\n', file=sys.stdout, flush=True): if header_text: file.write(header_text) # note: text! => file.write() instead of out.write() file.flush() try: out = file.buffer # Py3 except AttributeError: out = file # Py2 out.write(s) if end: out.write(end) if flush: out.flush() class OrderedSet(object): def __init__(self, elements=()): self._list = [] self._set = set() self.update(elements) def __iter__(self): return iter(self._list) def update(self, elements): for e in elements: self.add(e) def add(self, e): if e not in self._set: self._list.append(e) self._set.add(e) def __bool__(self): return bool(self._set) __nonzero__ = __bool__ # Class decorator that adds a metaclass and recreates the class with it. # Copied from 'six'. def add_metaclass(metaclass): """Class decorator for creating a class with a metaclass.""" def wrapper(cls): orig_vars = cls.__dict__.copy() slots = orig_vars.get('__slots__') if slots is not None: if isinstance(slots, str): slots = [slots] for slots_var in slots: orig_vars.pop(slots_var) orig_vars.pop('__dict__', None) orig_vars.pop('__weakref__', None) return metaclass(cls.__name__, cls.__bases__, orig_vars) return wrapper def raise_error_if_module_name_forbidden(full_module_name): # it is bad idea to call the pyx-file cython.pyx, so fail early if full_module_name == 'cython' or full_module_name.startswith('cython.'): raise ValueError('cython is a special module, cannot be used as a module name') def build_hex_version(version_string): """ Parse and translate public version identifier like '4.3a1' into the readable hex representation '0x040300A1' (like PY_VERSION_HEX). SEE: https://peps.python.org/pep-0440/#public-version-identifiers """ # Parse '4.12a1' into [4, 12, 0, 0xA01] # And ignore .dev, .pre and .post segments digits = [] release_status = 0xF0 for segment in re.split(r'(\D+)', version_string): if segment in ('a', 'b', 'rc'): release_status = {'a': 0xA0, 'b': 0xB0, 'rc': 0xC0}[segment] digits = (digits + [0, 0])[:3] # 1.2a1 -> 1.2.0a1 elif segment in ('.dev', '.pre', '.post'): break # break since those are the last segments elif segment != '.': digits.append(int(segment)) digits = (digits + [0] * 3)[:4] digits[3] += release_status # Then, build a single hex value, two hex digits per version part. hexversion = 0 for digit in digits: hexversion = (hexversion << 8) + digit return '0x%08X' % hexversion def write_depfile(target, source, dependencies): src_base_dir = os.path.dirname(source) cwd = os.getcwd() if not src_base_dir.endswith(os.sep): src_base_dir += os.sep # paths below the base_dir are relative, otherwise absolute paths = [] for fname in dependencies: if fname.startswith(src_base_dir): try: newpath = os.path.relpath(fname, cwd) except ValueError: # if they are on different Windows drives, absolute is fine newpath = os.path.abspath(fname) else: newpath = os.path.abspath(fname) paths.append(newpath) depline = os.path.relpath(target, cwd) + ": \\\n " depline += " \\\n ".join(paths) + "\n" with open(target+'.dep', 'w') as outfile: outfile.write(depline) def print_version(): print("Cython version %s" % cython_version) # For legacy reasons, we also write the version to stderr. # New tools should expect it in stdout, but existing ones still pipe from stderr, or from both. if sys.stderr.isatty() or sys.stdout == sys.stderr: return if os.fstat(1) == os.fstat(2): # This is somewhat unsafe since sys.stdout/err might not really be linked to streams 1/2. # However, in most *relevant* cases, where Cython is run as an external tool, they are linked. return sys.stderr.write("Cython version %s\n" % cython_version) def normalise_float_repr(float_str): """ Generate a 'normalised', simple digits string representation of a float value to allow string comparisons. Examples: '.123', '123.456', '123.' """ str_value = float_str.lower().lstrip('0') exp = 0 if 'E' in str_value or 'e' in str_value: str_value, exp = str_value.split('E' if 'E' in str_value else 'e', 1) exp = int(exp) if '.' in str_value: num_int_digits = str_value.index('.') str_value = str_value[:num_int_digits] + str_value[num_int_digits + 1:] else: num_int_digits = len(str_value) exp += num_int_digits result = ( str_value[:exp] + '0' * (exp - len(str_value)) + '.' + '0' * -exp + str_value[exp:] ).rstrip('0') return result if result != '.' else '.0' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Cython/__init__.py0000644000175100001770000000054600000000000017156 0ustar00runnerdocker00000000000000from __future__ import absolute_import from .Shadow import __version__ # Void cython.* directives (for case insensitive operating systems). from .Shadow import * def load_ipython_extension(ip): """Load the extension in IPython.""" from .Build.IpythonMagic import CythonMagics # pylint: disable=cyclic-import ip.register_magics(CythonMagics) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.020724 Cython-3.0.8/Demos/0000755000175100001770000000000000000000000014643 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Demos/Makefile0000644000175100001770000000051600000000000016305 0ustar00runnerdocker00000000000000all: python setup.py build_ext --inplace test: all python run_primes.py 20 python run_numeric_demo.py python run_spam.py python integrate_timing.py cd callback; $(MAKE) test cd embed; $(MAKE) test clean: @echo Cleaning Demos @rm -f *.c *.o *.so *~ core @rm -rf build @cd callback; $(MAKE) clean @cd embed; $(MAKE) clean ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Demos/Makefile.nodistutils0000644000175100001770000000060600000000000020665 0ustar00runnerdocker00000000000000PYHOME = $(HOME)/pkg/python/version PYINCLUDE = \ -I$(PYHOME)/include/python2.2 \ -I$(PYHOME)/$(ARCH)/include/python2.2 %.c: %.pyx ../bin/cython $< %.o: %.c gcc -c -fPIC $(PYINCLUDE) $< %.so: %.o gcc -shared $< -lm -o $@ all: primes.so spam.so numeric_demo.so clean: @echo Cleaning Demos @rm -f *.c *.o *.so *~ core core.* @cd callback; $(MAKE) clean @cd embed; $(MAKE) clean ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.020724 Cython-3.0.8/Demos/benchmarks/0000755000175100001770000000000000000000000016760 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Demos/benchmarks/bpnn3.pxd0000644000175100001770000000117600000000000020522 0ustar00runnerdocker00000000000000cimport cython cdef double rand(double a, double b, random=*) @cython.locals(i=Py_ssize_t) cdef list makeMatrix(Py_ssize_t I, Py_ssize_t J, fill=*) cdef class NN: cdef Py_ssize_t ni, nh, no cdef list ai, ah, ao cdef list wi, wo cdef list ci, co @cython.locals(i=Py_ssize_t, j=Py_ssize_t, k=Py_ssize_t) cpdef update(self, list inputs) @cython.locals(i=Py_ssize_t, j=Py_ssize_t, k=Py_ssize_t, change=double) cpdef double backPropagate(self, list targets, double N, M) @cython.locals(i=Py_ssize_t, p=list, error=double) cpdef train(self, list patterns, Py_ssize_t iterations=*, double N=*, M=*) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Demos/benchmarks/bpnn3.py0000644000175100001770000001235500000000000020360 0ustar00runnerdocker00000000000000#!/usr/bin/python # Back-Propagation Neural Networks # # Written in Python. See https://www.python.org/ # # Neil Schemenauer import math import random as random # Local imports import util random.seed(0) # calculate a random number where: a <= rand < b def rand(a, b, random=random.random): return (b-a)*random() + a # Make a matrix (we could use NumPy to speed this up) def makeMatrix(I, J, fill=0.0): m = [] for i in range(I): m.append([fill]*J) return m class NN(object): # print 'class NN' def __init__(self, ni, nh, no): # number of input, hidden, and output nodes self.ni = ni + 1 # +1 for bias node self.nh = nh self.no = no # activations for nodes self.ai = [1.0]*self.ni self.ah = [1.0]*self.nh self.ao = [1.0]*self.no # create weights self.wi = makeMatrix(self.ni, self.nh) self.wo = makeMatrix(self.nh, self.no) # set them to random values for i in range(self.ni): for j in range(self.nh): self.wi[i][j] = rand(-2.0, 2.0) for j in range(self.nh): for k in range(self.no): self.wo[j][k] = rand(-2.0, 2.0) # last change in weights for momentum self.ci = makeMatrix(self.ni, self.nh) self.co = makeMatrix(self.nh, self.no) def update(self, inputs): # print 'update', inputs if len(inputs) != self.ni-1: raise ValueError('wrong number of inputs') # input activations for i in range(self.ni-1): #self.ai[i] = 1.0/(1.0+math.exp(-inputs[i])) self.ai[i] = inputs[i] # hidden activations for j in range(self.nh): sum = 0.0 for i in range(self.ni): sum = sum + self.ai[i] * self.wi[i][j] self.ah[j] = 1.0/(1.0+math.exp(-sum)) # output activations for k in range(self.no): sum = 0.0 for j in range(self.nh): sum = sum + self.ah[j] * self.wo[j][k] self.ao[k] = 1.0/(1.0+math.exp(-sum)) return self.ao[:] def backPropagate(self, targets, N, M): # print N, M if len(targets) != self.no: raise ValueError('wrong number of target values') # calculate error terms for output output_deltas = [0.0] * self.no # print self.no for k in range(self.no): ao = self.ao[k] output_deltas[k] = ao*(1-ao)*(targets[k]-ao) # calculate error terms for hidden hidden_deltas = [0.0] * self.nh for j in range(self.nh): sum = 0.0 for k in range(self.no): sum = sum + output_deltas[k]*self.wo[j][k] hidden_deltas[j] = self.ah[j]*(1-self.ah[j])*sum # update output weights for j in range(self.nh): for k in range(self.no): change = output_deltas[k]*self.ah[j] self.wo[j][k] = self.wo[j][k] + N*change + M*self.co[j][k] self.co[j][k] = change # update input weights for i in range(self.ni): for j in range(self.nh): change = hidden_deltas[j]*self.ai[i] self.wi[i][j] = self.wi[i][j] + N*change + M*self.ci[i][j] self.ci[i][j] = change # calculate error error = 0.0 for k in range(len(targets)): error = error + 0.5*(targets[k]-self.ao[k])**2 return error def test(self, patterns): for p in patterns: print('%s -> %s' % (p[0], self.update(p[0]))) def weights(self): print('Input weights:') for i in range(self.ni): print(self.wi[i]) print('') print('Output weights:') for j in range(self.nh): print(self.wo[j]) def train(self, patterns, iterations=2000, N=0.5, M=0.1): # N: learning rate # M: momentum factor for i in range(iterations): error = 0.0 for p in patterns: inputs = p[0] targets = p[1] self.update(inputs) error = error + self.backPropagate(targets, N, M) #if i % 100 == 0: # print i, 'error %-14f' % error def demo(): # Teach network XOR function pat = [ [[0,0], [0]], [[0,1], [1]], [[1,0], [1]], [[1,1], [0]] ] # create a network with two input, two hidden, and two output nodes n = NN(2, 3, 1) # train it with some patterns n.train(pat, 5000) # test it #n.test(pat) def time(fn, *args): import time, traceback begin = time.time() result = fn(*args) end = time.time() return result, end-begin def test_bpnn(iterations): times = [] for _ in range(iterations): result, t = time(demo) times.append(t) return times main = test_bpnn if __name__ == "__main__": import optparse parser = optparse.OptionParser( usage="%prog [options]", description=("Test the performance of a neural network.")) util.add_standard_options_to(parser) options, args = parser.parse_args() util.run_benchmark(options, options.num_runs, test_bpnn) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Demos/benchmarks/chaos.pxd0000644000175100001770000000150000000000000020566 0ustar00runnerdocker00000000000000 cimport cython cdef extern from "math.h": cpdef double sqrt(double x) @cython.final cdef class GVector: cdef public double x, y, z cpdef double Mag(self) cpdef double dist(self, GVector other) cpdef list GetKnots(list points, long degree) @cython.final cdef class Spline: cdef list knots cdef list points cdef long degree cpdef (long, long) GetDomain(self) cpdef long GetIndex(self, u) @cython.final cdef class Chaosgame: cdef list splines cdef double thickness cdef double minx, miny, maxx, maxy, height, width cdef list num_trafos cdef double num_total cpdef tuple get_random_trafo(self) cpdef GVector transform_point(self, GVector point, trafo=*) cpdef truncate(self, GVector point) cpdef create_image_chaos(self, timer, long w, long h, long n) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Demos/benchmarks/chaos.py0000644000175100001770000002325700000000000020440 0ustar00runnerdocker00000000000000# Copyright (C) 2005 Carl Friedrich Bolz """create chaosgame-like fractals """ from __future__ import division, print_function import cython import time import operator import optparse import random random.seed(1234) from functools import reduce if not cython.compiled: from math import sqrt class GVector(object): def __init__(self, x = 0, y = 0, z = 0): self.x = x self.y = y self.z = z def Mag(self): return sqrt(self.x ** 2 + self.y ** 2 + self.z ** 2) def dist(self, other): return sqrt((self.x - other.x) ** 2 + (self.y - other.y) ** 2 + (self.z - other.z) ** 2) @cython.locals(self="GVector", other="GVector") def __add__(self, other): if not isinstance(other, GVector): raise ValueError("Can't add GVector to " + str(type(other))) v = GVector(self.x + other.x, self.y + other.y, self.z + other.z) return v @cython.locals(self="GVector", other="GVector") def __sub__(self, other): return self + other * -1 @cython.locals(self="GVector", other=cython.double) def __mul__(self, other): v = GVector(self.x * other, self.y * other, self.z * other) return v __rmul__ = __mul__ @cython.locals(other="GVector", l1=cython.double, l2_=cython.double) def linear_combination(self, other, l1, l2=None): l2_ = 1 - l1 if l2 is None else l2 v = GVector(self.x * l1 + other.x * l2_, self.y * l1 + other.y * l2_, self.z * l1 + other.z * l2_) return v def __str__(self): return "<%f, %f, %f>" % (self.x, self.y, self.z) def __repr__(self): return "GVector(%f, %f, %f)" % (self.x, self.y, self.z) def GetKnots(points, degree): knots = [0] * degree + range(1, len(points) - degree) knots += [len(points) - degree] * degree return knots class Spline(object): """Class for representing B-Splines and NURBS of arbitrary degree""" def __init__(self, points, degree = 3, knots = None): """Creates a Spline. points is a list of GVector, degree is the degree of the Spline.""" if knots is None: self.knots = GetKnots(points, degree) else: if len(points) > len(knots) - degree + 1: raise ValueError("too many control points") elif len(points) < len(knots) - degree + 1: raise ValueError("not enough control points") last = knots[0] for cur in knots[1:]: if cur < last: raise ValueError("knots not strictly increasing") last = cur self.knots = knots self.points = points self.degree = degree def GetDomain(self): """Returns the domain of the B-Spline""" return (self.knots[self.degree - 1], self.knots[len(self.knots) - self.degree]) @cython.locals(ik=cython.long, ii=cython.long, I=cython.long, ua=cython.long, ub=cython.long, u=cython.double, dom=(cython.long, cython.long)) def __call__(self, u): """Calculates a point of the B-Spline using de Boors Algorithm""" dom = self.GetDomain() if u < dom[0] or u > dom[1]: raise ValueError("Function value not in domain") if u == dom[0]: return self.points[0] if u == dom[1]: return self.points[-1] I = self.GetIndex(u) d = [self.points[I - self.degree + 1 + ii] for ii in range(self.degree + 1)] U = self.knots for ik in range(1, self.degree + 1): for ii in range(I - self.degree + ik + 1, I + 2): ua = U[ii + self.degree - ik] ub = U[ii - 1] co1 = (ua - u) / (ua - ub) co2 = (u - ub) / (ua - ub) index = ii - I + self.degree - ik - 1 d[index] = d[index].linear_combination(d[index + 1], co1, co2) return d[0] @cython.locals(ii=cython.long, I=cython.long, dom=(cython.long, cython.long)) def GetIndex(self, u): dom = self.GetDomain() for ii in range(self.degree - 1, len(self.knots) - self.degree): if self.knots[ii] <= u < self.knots[ii + 1]: I = ii break else: I = dom[1] - 1 return I def __len__(self): return len(self.points) def __repr__(self): return "Spline(%r, %r, %r)" % (self.points, self.degree, self.knots) class Chaosgame(object): @cython.locals(splines=list, thickness=cython.double, maxlength=cython.double, length=cython.double, curr=GVector, last=GVector, p=GVector, spl=Spline, t=cython.double, i=int) def __init__(self, splines, thickness=0.1): self.splines = splines self.thickness = thickness self.minx = min([p.x for spl in splines for p in spl.points]) self.miny = min([p.y for spl in splines for p in spl.points]) self.maxx = max([p.x for spl in splines for p in spl.points]) self.maxy = max([p.y for spl in splines for p in spl.points]) self.height = self.maxy - self.miny self.width = self.maxx - self.minx self.num_trafos = [] maxlength = thickness * self.width / self.height for spl in splines: length = 0 curr = spl(0) for i in range(1, 1000): last = curr t = 1 / 999 * i curr = spl(t) length += curr.dist(last) self.num_trafos.append(max(1, int(length / maxlength * 1.5))) self.num_total = reduce(operator.add, self.num_trafos, 0) def get_random_trafo(self): r = random.randrange(int(self.num_total) + 1) l = 0 for i in range(len(self.num_trafos)): if l <= r < l + self.num_trafos[i]: return i, random.randrange(self.num_trafos[i]) l += self.num_trafos[i] return len(self.num_trafos) - 1, random.randrange(self.num_trafos[-1]) @cython.locals(neighbour="GVector", basepoint="GVector", derivative="GVector", seg_length=cython.double, start=cython.double, end=cython.double, t=cython.double) def transform_point(self, point, trafo=None): x = (point.x - self.minx) / self.width y = (point.y - self.miny) / self.height if trafo is None: trafo = self.get_random_trafo() start, end = self.splines[trafo[0]].GetDomain() length = end - start seg_length = length / self.num_trafos[trafo[0]] t = start + seg_length * trafo[1] + seg_length * x basepoint = self.splines[trafo[0]](t) if t + 1/50000 > end: neighbour = self.splines[trafo[0]](t - 1/50000) derivative = neighbour - basepoint else: neighbour = self.splines[trafo[0]](t + 1/50000) derivative = basepoint - neighbour if derivative.Mag() != 0: basepoint.x += derivative.y / derivative.Mag() * (y - 0.5) * \ self.thickness basepoint.y += -derivative.x / derivative.Mag() * (y - 0.5) * \ self.thickness else: print("r", end='') self.truncate(basepoint) return basepoint def truncate(self, point): if point.x >= self.maxx: point.x = self.maxx if point.y >= self.maxy: point.y = self.maxy if point.x < self.minx: point.x = self.minx if point.y < self.miny: point.y = self.miny @cython.locals(x=cython.long, y=cython.long) def create_image_chaos(self, timer, w, h, n): im = [[1] * h for i in range(w)] point = GVector((self.maxx + self.minx) / 2, (self.maxy + self.miny) / 2, 0) times = [] for _ in range(n): t1 = timer() for i in range(5000): point = self.transform_point(point) x = int((point.x - self.minx) / self.width * w) y = int((point.y - self.miny) / self.height * h) if x == w: x -= 1 if y == h: y -= 1 im[x][h - y - 1] = 0 t2 = timer() times.append(t2 - t1) return times def main(n, timer=time.time): splines = [ Spline([ GVector(1.597350, 3.304460, 0.000000), GVector(1.575810, 4.123260, 0.000000), GVector(1.313210, 5.288350, 0.000000), GVector(1.618900, 5.329910, 0.000000), GVector(2.889940, 5.502700, 0.000000), GVector(2.373060, 4.381830, 0.000000), GVector(1.662000, 4.360280, 0.000000)], 3, [0, 0, 0, 1, 1, 1, 2, 2, 2]), Spline([ GVector(2.804500, 4.017350, 0.000000), GVector(2.550500, 3.525230, 0.000000), GVector(1.979010, 2.620360, 0.000000), GVector(1.979010, 2.620360, 0.000000)], 3, [0, 0, 0, 1, 1, 1]), Spline([ GVector(2.001670, 4.011320, 0.000000), GVector(2.335040, 3.312830, 0.000000), GVector(2.366800, 3.233460, 0.000000), GVector(2.366800, 3.233460, 0.000000)], 3, [0, 0, 0, 1, 1, 1]) ] c = Chaosgame(splines, 0.25) return c.create_image_chaos(timer, 1000, 1200, n) if __name__ == "__main__": import util parser = optparse.OptionParser( usage="%prog [options]", description="Test the performance of the Chaos benchmark") util.add_standard_options_to(parser) options, args = parser.parse_args() util.run_benchmark(options, options.num_runs, main) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Demos/benchmarks/coroutines.py0000644000175100001770000000311300000000000021522 0ustar00runnerdocker00000000000000#!/usr/bin/python3 # cython: language_level=3 # micro benchmarks for coroutines COUNT = 100000 import cython async def done(n): return n @cython.locals(N=cython.Py_ssize_t) async def count_to(N): count = 0 for i in range(N): count += await done(i) return count async def await_all(*coroutines): count = 0 for coro in coroutines: count += await coro return count @cython.locals(N=cython.Py_ssize_t) def bm_await_nested(N): return await_all( count_to(N), await_all( count_to(N), await_all(*[count_to(COUNT // i) for i in range(1, N+1)]), count_to(N)), count_to(N)) def await_one(coro): a = coro.__await__() try: while True: await_one(next(a)) except StopIteration as exc: result = exc.args[0] if exc.args else None else: result = 0 return result def time(fn, *args): from time import time begin = time() result = await_one(fn(*args)) end = time() return result, end-begin def benchmark(N): times = [] for _ in range(N): result, t = time(bm_await_nested, 1000) times.append(t) assert result == 8221043302, result return times main = benchmark if __name__ == "__main__": import optparse parser = optparse.OptionParser( usage="%prog [options]", description="Micro benchmarks for generators.") import util util.add_standard_options_to(parser) options, args = parser.parse_args() util.run_benchmark(options, options.num_runs, benchmark) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Demos/benchmarks/fstrings.py0000644000175100001770000001750600000000000021202 0ustar00runnerdocker00000000000000# coding=utf-8 # NOTE: requires Python 3.6 or later if not compiled with Cython from time import time import cython @cython.locals(x=int, n=int) def run(): t0 = time() f = 1.0 x = 2 n = 5 i = 12345678 s = 'abc' u = u'üöä' # repeat without fast looping ... f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:3.2}--{n:2}{n:5}oo{i}{s}" f"{n}oo{n*10}{f:5.2}--{n:2}{n:5}oo{i}{u}" f"{n}oo{n*10}{f:2.2}--{n:2}{n:5}oo{i}{s}xx{u}" # repeat without fast looping ... f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:3.2}--{n:2}{n:5}oo{i}{s}" f"{n}oo{n*10}{f:5.2}--{n:2}{n:5}oo{i}{u}" f"{n}oo{n*10}{f:2.2}--{n:2}{n:5}oo{i}{s}xx{u}" # repeat without fast looping ... f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:3.2}--{n:2}{n:5}oo{i}{s}" f"{n}oo{n*10}{f:5.2}--{n:2}{n:5}oo{i}{u}" f"{n}oo{n*10}{f:2.2}--{n:2}{n:5}oo{i}{s}xx{u}" # repeat without fast looping ... f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:3.2}--{n:2}{n:5}oo{i}{s}" f"{n}oo{n*10}{f:5.2}--{n:2}{n:5}oo{i}{u}" f"{n}oo{n*10}{f:2.2}--{n:2}{n:5}oo{i}{s}xx{u}" # repeat without fast looping ... f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:3.2}--{n:2}{n:5}oo{i}{s}" f"{n}oo{n*10}{f:5.2}--{n:2}{n:5}oo{i}{u}" f"{n}oo{n*10}{f:2.2}--{n:2}{n:5}oo{i}{s}xx{u}" # repeat without fast looping ... f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:3.2}--{n:2}{n:5}oo{i}{s}" f"{n}oo{n*10}{f:5.2}--{n:2}{n:5}oo{i}{u}" f"{n}oo{n*10}{f:2.2}--{n:2}{n:5}oo{i}{s}xx{u}" # repeat without fast looping ... f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:3.2}--{n:2}{n:5}oo{i}{s}" f"{n}oo{n*10}{f:5.2}--{n:2}{n:5}oo{i}{u}" f"{n}oo{n*10}{f:2.2}--{n:2}{n:5}oo{i}{s}xx{u}" # repeat without fast looping ... f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:3.2}--{n:2}{n:5}oo{i}{s}" f"{n}oo{n*10}{f:5.2}--{n:2}{n:5}oo{i}{u}" f"{n}oo{n*10}{f:2.2}--{n:2}{n:5}oo{i}{s}xx{u}" # repeat without fast looping ... f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:3.2}--{n:2}{n:5}oo{i}{s}" f"{n}oo{n*10}{f:5.2}--{n:2}{n:5}oo{i}{u}" f"{n}oo{n*10}{f:2.2}--{n:2}{n:5}oo{i}{s}xx{u}" # repeat without fast looping ... f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:3.2}--{n:2}{n:5}oo{i}{s}" f"{n}oo{n*10}{f:5.2}--{n:2}{n:5}oo{i}{u}" f"{n}oo{n*10}{f:2.2}--{n:2}{n:5}oo{i}{s}xx{u}" # repeat without fast looping ... f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:3.2}--{n:2}{n:5}oo{i}{s}" f"{n}oo{n*10}{f:5.2}--{n:2}{n:5}oo{i}{u}" f"{n}oo{n*10}{f:2.2}--{n:2}{n:5}oo{i}{s}xx{u}" # repeat without fast looping ... f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:.2}--{n:2}{n:5}oo{i}" f"{n}oo{n*10}{f:3.2}--{n:2}{n:5}oo{i}{s}" f"{n}oo{n*10}{f:5.2}--{n:2}{n:5}oo{i}{u}" f"{n}oo{n*10}{f:2.2}--{n:2}{n:5}oo{i}{s}xx{u}" tk = time() return tk - t0 def main(n): run() # warmup times = [] for i in range(n): times.append(run()) return times if __name__ == "__main__": import optparse import util parser = optparse.OptionParser( usage="%prog [options]", description="Test the performance of fstring literal formatting") util.add_standard_options_to(parser) options, args = parser.parse_args() util.run_benchmark(options, options.num_runs, main) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Demos/benchmarks/generators.py0000644000175100001770000000404100000000000021502 0ustar00runnerdocker00000000000000#!/usr/bin/python # micro benchmarks for generators COUNT = 10000 import cython @cython.locals(N=cython.Py_ssize_t) def count_to(N): for i in range(N): yield i @cython.locals(i=cython.Py_ssize_t) def round_robin(*_iterators): iterators = list(_iterators) to_drop = [] while iterators: for i, it in enumerate(iterators): try: value = next(it) except StopIteration: to_drop.append(i) else: yield value if to_drop: for i in reversed(to_drop): del iterators[i] del to_drop[:] def yield_from(*iterators): for it in iterators: yield from it def bm_plain(N): return count_to(COUNT * N) def bm_round_robin(N): return round_robin(*[ count_to(COUNT // i) for i in range(1,N+1) ]) def bm_yield_from(N): return yield_from(count_to(N), round_robin(*[ yield_from(count_to(COUNT // i)) for i in range(1,N+1) ]), count_to(N)) def bm_yield_from_nested(N): return yield_from(count_to(N), yield_from(count_to(N), round_robin(*[ yield_from(count_to(COUNT // i)) for i in range(1,N+1) ]), count_to(N)), count_to(N)) def time(fn, *args): from time import time begin = time() result = list(fn(*args)) end = time() return result, end-begin def benchmark(N): times = [] for _ in range(N): result, t = time(bm_yield_from_nested, 10) times.append(t) return times main = benchmark if __name__ == "__main__": import optparse parser = optparse.OptionParser( usage="%prog [options]", description=("Micro benchmarks for generators.")) import util util.add_standard_options_to(parser) options, args = parser.parse_args() util.run_benchmark(options, options.num_runs, benchmark) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Demos/benchmarks/hexiom2.pxd0000644000175100001770000000353300000000000021054 0ustar00runnerdocker00000000000000cimport cython cdef object EMPTY cdef int IMPOSSIBLE, SOLVED, OPEN cdef int ASCENDING, DESCENDING cdef class Dir: cdef public int x, y @cython.final cdef class Done: cdef public int count cdef public list cells cdef Done clone(self) cdef inline int set_done(self, int i, v) except -123 cdef inline bint already_done(self, int i) except -123 cdef inline bint remove(self, int i, v) except -123 cdef inline bint remove_unfixed(self, v) except -123 cdef int next_cell(self, Pos pos, int strategy=*) except -123 cdef int filter_tiles(self, int* tiles) except -123 cdef int next_cell_min_choice(self) except -123 cdef int next_cell_max_choice(self) except -123 cdef int next_cell_highest_value(self) except -123 cdef int next_cell_first(self) except -123 cdef int next_cell_max_neighbors(self, Pos pos) except -123 cdef int next_cell_min_neighbors(self, Pos pos) except -123 @cython.final cdef class Node: cdef public tuple pos cdef public int id cdef public list links @cython.final cdef class Hex: cdef public list nodes_by_id cdef public dict nodes_by_pos cdef public int size cdef public int count cdef int link_nodes(self) except -123 cdef bint contains_pos(self, tuple pos) cdef Node get_by_pos(self, tuple pos) cdef Node get_by_id(self, int id) @cython.final cdef class Pos: cdef public Hex hex cdef public Done done cdef public int[8] tiles cdef Pos clone(self) cdef bint constraint_pass(Pos pos, last_move=*) except -123 cdef list find_moves(Pos pos, int strategy, int order) cdef inline int play_move(Pos pos, tuple move) except -123 cdef print_pos(Pos pos, output) cdef int solved(Pos pos, output, bint verbose=*) except -123 cdef int solve_step(Pos prev, int strategy, order, output, bint first=*) except -123 cdef check_valid(Pos pos) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3367221 Cython-3.0.8/Demos/benchmarks/hexiom2.py0000644000175100001770000004136000000000000020711 0ustar00runnerdocker00000000000000"""Benchmark from Laurent Vaucher. Source: https://github.com/slowfrog/hexiom : hexiom2.py, level36.txt (Main function tweaked by Armin Rigo.) """ from __future__ import division, print_function import time from io import StringIO import cython ################################## class Dir(object): def __init__(self, x, y): self.x = x self.y = y DIRS = [ Dir(1, 0), Dir(-1, 0), Dir(0, 1), Dir(0, -1), Dir(1, 1), Dir(-1, -1) ] EMPTY = 7 ################################## class Done(object): MIN_CHOICE_STRATEGY = 0 MAX_CHOICE_STRATEGY = 1 HIGHEST_VALUE_STRATEGY = 2 FIRST_STRATEGY = 3 MAX_NEIGHBORS_STRATEGY = 4 MIN_NEIGHBORS_STRATEGY = 5 def __init__(self, count, empty=False): self.count = count self.cells = None if empty else [[0, 1, 2, 3, 4, 5, 6, EMPTY] for i in range(count)] def clone(self): ret = Done(self.count, True) ret.cells = [self.cells[i][:] for i in range(self.count)] return ret def __getitem__(self, i): return self.cells[i] def set_done(self, i, v): self.cells[i] = [v] def already_done(self, i): return len(self.cells[i]) == 1 def remove(self, i, v): if v in self.cells[i]: self.cells[i].remove(v) return True else: return False def remove_all(self, v): for i in range(self.count): self.remove(i, v) def remove_unfixed(self, v): changed = False for i in range(self.count): if not self.already_done(i): if self.remove(i, v): changed = True return changed def filter_tiles(self, tiles): for v in range(8): if tiles[v] == 0: self.remove_all(v) @cython.locals(i=cython.int) def next_cell_min_choice(self): minlen = 10 mini = -1 for i in range(self.count): if 1 < len(self.cells[i]) < minlen: minlen = len(self.cells[i]) mini = i return mini @cython.locals(i=cython.int) def next_cell_max_choice(self): maxlen = 1 maxi = -1 for i in range(self.count): if maxlen < len(self.cells[i]): maxlen = len(self.cells[i]) maxi = i return maxi @cython.locals(i=cython.int) def next_cell_highest_value(self): maxval = -1 maxi = -1 for i in range(self.count): if (not self.already_done(i)): maxvali = max([k for k in self.cells[i] if k != EMPTY]) if maxval < maxvali: maxval = maxvali maxi = i return maxi @cython.locals(i=cython.int) def next_cell_first(self): for i in range(self.count): if (not self.already_done(i)): return i return -1 @cython.locals(i=cython.int) def next_cell_max_neighbors(self, pos): maxn = -1 maxi = -1 for i in range(self.count): if not self.already_done(i): cells_around = pos.hex.get_by_id(i).links n = sum([1 if (self.already_done(nid) and (self[nid][0] != EMPTY)) else 0 for nid in cells_around]) if n > maxn: maxn = n maxi = i return maxi @cython.locals(i=cython.int) def next_cell_min_neighbors(self, pos): minn = 7 mini = -1 for i in range(self.count): if not self.already_done(i): cells_around = pos.hex.get_by_id(i).links n = sum([1 if (self.already_done(nid) and (self[nid][0] != EMPTY)) else 0 for nid in cells_around]) if n < minn: minn = n mini = i return mini def next_cell(self, pos, strategy=HIGHEST_VALUE_STRATEGY): if strategy == Done.HIGHEST_VALUE_STRATEGY: return self.next_cell_highest_value() elif strategy == Done.MIN_CHOICE_STRATEGY: return self.next_cell_min_choice() elif strategy == Done.MAX_CHOICE_STRATEGY: return self.next_cell_max_choice() elif strategy == Done.FIRST_STRATEGY: return self.next_cell_first() elif strategy == Done.MAX_NEIGHBORS_STRATEGY: return self.next_cell_max_neighbors(pos) elif strategy == Done.MIN_NEIGHBORS_STRATEGY: return self.next_cell_min_neighbors(pos) else: raise Exception("Wrong strategy: %d" % strategy) ################################## class Node(object): def __init__(self, pos, id, links): self.pos = pos self.id = id self.links = links ################################## class Hex(object): @cython.locals(size=cython.int, id=cython.int, x=cython.int, y=cython.int) def __init__(self, size): self.size = size self.count = 3 * size * (size - 1) + 1 self.nodes_by_id = self.count * [None] self.nodes_by_pos = {} id = 0 for y in range(size): for x in range(size + y): pos = (x, y) node = Node(pos, id, []) self.nodes_by_pos[pos] = node self.nodes_by_id[node.id] = node id += 1 for y in range(1, size): for x in range(y, size * 2 - 1): ry = size + y - 1 pos = (x, ry) node = Node(pos, id, []) self.nodes_by_pos[pos] = node self.nodes_by_id[node.id] = node id += 1 @cython.locals(dir=Dir, x=cython.int, y=cython.int, nx=cython.int, ny=cython.int, node=Node) def link_nodes(self): for node in self.nodes_by_id: (x, y) = node.pos for dir in DIRS: nx = x + dir.x ny = y + dir.y if self.contains_pos((nx, ny)): node.links.append(self.nodes_by_pos[(nx, ny)].id) def contains_pos(self, pos): return pos in self.nodes_by_pos def get_by_pos(self, pos): return self.nodes_by_pos[pos] def get_by_id(self, id): return self.nodes_by_id[id] ################################## class Pos(object): def __init__(self, hex, tiles, done = None): self.hex = hex self.tiles = tiles self.done = Done(hex.count) if done is None else done def clone(self): return Pos(self.hex, self.tiles, self.done.clone()) ################################## @cython.locals(pos=Pos, i=cython.long, v=cython.int, nid=cython.int, num=cython.int, empties=cython.int, filled=cython.int, vmax=cython.int, vmin=cython.int, cell=list, left=cython.int[8]) def constraint_pass(pos, last_move=None): changed = False left = pos.tiles[:] done = pos.done # Remove impossible values from free cells free_cells = (range(done.count) if last_move is None else pos.hex.get_by_id(last_move).links) for i in free_cells: if not done.already_done(i): vmax = 0 vmin = 0 cells_around = pos.hex.get_by_id(i).links for nid in cells_around: if done.already_done(nid): if done[nid][0] != EMPTY: vmin += 1 vmax += 1 else: vmax += 1 for num in range(7): if (num < vmin) or (num > vmax): if done.remove(i, num): changed = True # Computes how many of each value is still free for cell in done.cells: if len(cell) == 1: left[cell[0]] -= 1 for v in range(8): # If there is none, remove the possibility from all tiles if (pos.tiles[v] > 0) and (left[v] == 0): if done.remove_unfixed(v): changed = True else: possible = sum([(1 if v in cell else 0) for cell in done.cells]) # If the number of possible cells for a value is exactly the number of available tiles # put a tile in each cell if pos.tiles[v] == possible: for i in range(done.count): cell = done.cells[i] if (not done.already_done(i)) and (v in cell): done.set_done(i, v) changed = True # Force empty or non-empty around filled cells filled_cells = (range(done.count) if last_move is None else [last_move]) for i in filled_cells: if done.already_done(i): num = done[i][0] empties = 0 filled = 0 unknown = [] cells_around = pos.hex.get_by_id(i).links for nid in cells_around: if done.already_done(nid): if done[nid][0] == EMPTY: empties += 1 else: filled += 1 else: unknown.append(nid) if len(unknown) > 0: if num == filled: for u in unknown: if EMPTY in done[u]: done.set_done(u, EMPTY) changed = True #else: # raise Exception("Houston, we've got a problem") elif num == filled + len(unknown): for u in unknown: if done.remove(u, EMPTY): changed = True return changed ASCENDING = 1 DESCENDING = -1 def find_moves(pos, strategy, order): done = pos.done cell_id = done.next_cell(pos, strategy) if cell_id < 0: return [] if order == ASCENDING: return [(cell_id, v) for v in done[cell_id]] else: # Try higher values first and EMPTY last moves = list(reversed([(cell_id, v) for v in done[cell_id] if v != EMPTY])) if EMPTY in done[cell_id]: moves.append((cell_id, EMPTY)) return moves def play_move(pos, move): (cell_id, i) = move pos.done.set_done(cell_id, i) @cython.locals(x=cython.int, y=cython.int, ry=cython.int, id=cython.int) def print_pos(pos, output): hex = pos.hex done = pos.done size = hex.size for y in range(size): print(u" " * (size - y - 1), end=u"", file=output) for x in range(size + y): pos2 = (x, y) id = hex.get_by_pos(pos2).id if done.already_done(id): c = str(done[id][0]) if done[id][0] != EMPTY else u"." else: c = u"?" print(u"%s " % c, end=u"", file=output) print(end=u"\n", file=output) for y in range(1, size): print(u" " * y, end=u"", file=output) for x in range(y, size * 2 - 1): ry = size + y - 1 pos2 = (x, ry) id = hex.get_by_pos(pos2).id if done.already_done(id): c = str(done[id][0]) if done[id][0] != EMPTY else (u".") else: c = u"?" print(u"%s " % c, end=u"", file=output) print(end=u"\n", file=output) OPEN = 0 SOLVED = 1 IMPOSSIBLE = -1 @cython.locals(i=cython.int, num=cython.int, nid=cython.int, vmin=cython.int, vmax=cython.int, tiles=cython.int[8]) def solved(pos, output, verbose=False): hex = pos.hex tiles = pos.tiles[:] done = pos.done exact = True all_done = True for i in range(hex.count): if len(done[i]) == 0: return IMPOSSIBLE elif done.already_done(i): num = done[i][0] tiles[num] -= 1 if (tiles[num] < 0): return IMPOSSIBLE vmax = 0 vmin = 0 if num != EMPTY: cells_around = hex.get_by_id(i).links for nid in cells_around: if done.already_done(nid): if done[nid][0] != EMPTY: vmin += 1 vmax += 1 else: vmax += 1 if (num < vmin) or (num > vmax): return IMPOSSIBLE if num != vmin: exact = False else: all_done = False if (not all_done) or (not exact): return OPEN print_pos(pos, output) return SOLVED @cython.locals(move=tuple) def solve_step(prev, strategy, order, output, first=False): if first: pos = prev.clone() while constraint_pass(pos): pass else: pos = prev moves = find_moves(pos, strategy, order) if len(moves) == 0: return solved(pos, output) else: for move in moves: #print("Trying (%d, %d)" % (move[0], move[1])) ret = OPEN new_pos = pos.clone() play_move(new_pos, move) #print_pos(new_pos) while constraint_pass(new_pos, move[0]): pass cur_status = solved(new_pos, output) if cur_status != OPEN: ret = cur_status else: ret = solve_step(new_pos, strategy, order, output) if ret == SOLVED: return SOLVED return IMPOSSIBLE @cython.locals(tot=cython.int, tiles=cython.int[8]) def check_valid(pos): hex = pos.hex tiles = pos.tiles done = pos.done # fill missing entries in tiles tot = 0 for i in range(8): if tiles[i] > 0: tot += tiles[i] else: tiles[i] = 0 # check total if tot != hex.count: raise Exception("Invalid input. Expected %d tiles, got %d." % (hex.count, tot)) def solve(pos, strategy, order, output): check_valid(pos) return solve_step(pos, strategy, order, output, first=True) # TODO Write an 'iterator' to go over all x,y positions @cython.locals(x=cython.int, y=cython.int, p=cython.int, tiles=cython.int[8], size=cython.int, inctile=cython.int, linei=cython.int) def read_file(file): lines = [line.strip("\r\n") for line in file.splitlines()] size = int(lines[0]) hex = Hex(size) linei = 1 tiles = 8 * [0] done = Done(hex.count) for y in range(size): line = lines[linei][size - y - 1:] p = 0 for x in range(size + y): tile = line[p:p + 2] p += 2 if tile[1] == ".": inctile = EMPTY else: inctile = int(tile) tiles[inctile] += 1 # Look for locked tiles if tile[0] == "+": print("Adding locked tile: %d at pos %d, %d, id=%d" % (inctile, x, y, hex.get_by_pos((x, y)).id)) done.set_done(hex.get_by_pos((x, y)).id, inctile) linei += 1 for y in range(1, size): ry = size - 1 + y line = lines[linei][y:] p = 0 for x in range(y, size * 2 - 1): tile = line[p:p + 2] p += 2 if tile[1] == ".": inctile = EMPTY else: inctile = int(tile) tiles[inctile] += 1 # Look for locked tiles if tile[0] == "+": print("Adding locked tile: %d at pos %d, %d, id=%d" % (inctile, x, ry, hex.get_by_pos((x, ry)).id)) done.set_done(hex.get_by_pos((x, ry)).id, inctile) linei += 1 hex.link_nodes() done.filter_tiles(tiles) return Pos(hex, tiles, done) def solve_file(file, strategy, order, output): pos = read_file(file) solve(pos, strategy, order, output) def run_level36(): f = """\ 4 2 1 1 2 3 3 3 . . 2 3 3 . 4 . . 2 . 2 4 3 2 2 2 . . . 2 4 3 4 . . 3 2 3 3 """ order = DESCENDING strategy = Done.FIRST_STRATEGY output = StringIO() solve_file(f, strategy, order, output) expected = """\ 3 4 3 2 3 4 4 . 3 2 . . 3 4 3 2 . 1 . 3 . 2 3 3 . 2 . 2 3 . 2 . 2 2 2 . 1 """ if output.getvalue() != expected: raise AssertionError("got a wrong answer:\n%s" % output.getvalue()) def main(n): # only run 1/25th of the requested number of iterations. # with the default n=50 from runner.py, this means twice. l = [] for i in range(n): t0 = time.time() run_level36() time_elapsed = time.time() - t0 l.append(time_elapsed) return l if __name__ == "__main__": import util, optparse parser = optparse.OptionParser( usage="%prog [options]", description="Test the performance of the hexiom2 benchmark") util.add_standard_options_to(parser) options, args = parser.parse_args() util.run_benchmark(options, options.num_runs, main) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/benchmarks/meteor_contest.pxd0000644000175100001770000000045300000000000022531 0ustar00runnerdocker00000000000000cimport cython cdef list rotate(list ido, dict rd=*) cdef list flip(list ido, dict fd=*) cdef list permute(list ido, list r_ido) @cython.locals(n_i_min=long) cpdef solve(long n, long i_min, free, list curr_board, list pieces_left, list solutions, list fps=*, list se_nh=*, bisect=*) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/benchmarks/meteor_contest.py0000644000175100001770000001044200000000000022365 0ustar00runnerdocker00000000000000# The Computer Language Benchmarks Game # http://shootout.alioth.debian.org/ # # contributed by Daniel Nanz, 2008-08-21 import optparse import time from bisect import bisect import util w, h = 5, 10 dir_no = 6 S, E = w * h, 2 SE = S + (E / 2) SW = SE - E W, NW, NE = -E, -SE, -SW def rotate(ido, rd={E: NE, NE: NW, NW: W, W: SW, SW: SE, SE: E}): return [rd[o] for o in ido] def flip(ido, fd={E: E, NE: SE, NW: SW, W: W, SW: NW, SE: NE}): return [fd[o] for o in ido] def permute(ido, r_ido): ps = [ido] for r in range(dir_no - 1): ps.append(rotate(ps[-1])) if ido == r_ido: # C2-symmetry ps = ps[0:dir_no//2] for pp in ps[:]: ps.append(flip(pp)) return ps def convert(ido): '''incremental direction offsets -> "coordinate offsets" ''' out = [0] for o in ido: out.append(out[-1] + o) return list(set(out)) def get_footprints(board, cti, pieces): fps = [[[] for p in range(len(pieces))] for ci in range(len(board))] for c in board: for pi, p in enumerate(pieces): for pp in p: fp = frozenset([cti[c + o] for o in pp if (c + o) in cti]) if len(fp) == 5: fps[min(fp)][pi].append(fp) return fps def get_senh(board, cti): '''-> south-east neighborhood''' se_nh = [] nh = [E, SW, SE] for c in board: se_nh.append(frozenset([cti[c + o] for o in nh if (c + o) in cti])) return se_nh def get_puzzle(w=w, h=h): board = [E*x + S*y + (y % 2) for y in range(h) for x in range(w)] cti = dict((board[i], i) for i in range(len(board))) idos = [[E, E, E, SE], # incremental direction offsets [SE, SW, W, SW], [W, W, SW, SE], [E, E, SW, SE], [NW, W, NW, SE, SW], [E, E, NE, W], [NW, NE, NE, W], [NE, SE, E, NE], [SE, SE, E, SE], [E, NW, NW, NW]] perms = (permute(p, idos[3]) for p in idos) # restrict piece 4 pieces = [[convert(pp) for pp in p] for p in perms] return (board, cti, pieces) def print_board(board, w=w, h=h): for y in range(h): for x in range(w): print(board[x + y * w]) print('') if y % 2 == 0: print('') print() board, cti, pieces = get_puzzle() fps = get_footprints(board, cti, pieces) se_nh = get_senh(board, cti) def solve(n, i_min, free, curr_board, pieces_left, solutions, fps=fps, se_nh=se_nh, bisect=bisect): fp_i_cands = fps[i_min] for p in pieces_left: fp_cands = fp_i_cands[p] for fp in fp_cands: if fp <= free: n_curr_board = curr_board[:] for ci in fp: n_curr_board[ci] = p if len(pieces_left) > 1: n_free = free - fp n_i_min = min(n_free) if len(n_free & se_nh[n_i_min]) > 0: n_pieces_left = pieces_left[:] n_pieces_left.remove(p) solve(n, n_i_min, n_free, n_curr_board, n_pieces_left, solutions) else: s = ''.join(map(str, n_curr_board)) solutions.insert(bisect(solutions, s), s) rs = s[::-1] solutions.insert(bisect(solutions, rs), rs) if len(solutions) >= n: return if len(solutions) >= n: return return SOLVE_ARG = 60 def main(n): times = [] for i in range(n): t0 = time.time() free = frozenset(range(len(board))) curr_board = [-1] * len(board) pieces_left = list(range(len(pieces))) solutions = [] solve(SOLVE_ARG, 0, free, curr_board, pieces_left, solutions) #print len(solutions), 'solutions found\n' #for i in (0, -1): print_board(solutions[i]) tk = time.time() times.append(tk - t0) return times if __name__ == "__main__": parser = optparse.OptionParser( usage="%prog [options]", description="Test the performance of the Float benchmark") util.add_standard_options_to(parser) options, args = parser.parse_args() util.run_benchmark(options, options.num_runs, main) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/benchmarks/nbody.pxd0000644000175100001770000000126700000000000020616 0ustar00runnerdocker00000000000000 cimport cython @cython.locals(x=Py_ssize_t) cdef combinations(list l) @cython.locals(x1=double, x2=double, y1=double, y2=double, z1=double, z2=double, m1=double, m2=double, vx=double, vy=double, vz=double, i=long) cdef advance(double dt, long n, list bodies=*, list pairs=*) @cython.locals(x1=double, x2=double, y1=double, y2=double, z1=double, z2=double, m=double, m1=double, m2=double, vx=double, vy=double, vz=double) cdef report_energy(list bodies=*, list pairs=*, double e=*) @cython.locals(vx=double, vy=double, vz=double, m=double) cdef offset_momentum(tuple ref, list bodies=*, double px=*, double py=*, double pz=*) cpdef test_nbody(long iterations) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/benchmarks/nbody.py0000644000175100001770000001071500000000000020451 0ustar00runnerdocker00000000000000#!/usr/bin/env python """N-body benchmark from the Computer Language Benchmarks Game. This is intended to support Unladen Swallow's perf.py. Accordingly, it has been modified from the Shootout version: - Accept standard Unladen Swallow benchmark options. - Run report_energy()/advance() in a loop. - Reimplement itertools.combinations() to work with older Python versions. """ # Pulled from http://shootout.alioth.debian.org/u64q/benchmark.php?test=nbody&lang=python&id=4 # Contributed by Kevin Carson. # Modified by Tupteq, Fredrik Johansson, and Daniel Nanz. __contact__ = "collinwinter@google.com (Collin Winter)" # Python imports import optparse import sys from time import time # Local imports import util def combinations(l): """Pure-Python implementation of itertools.combinations(l, 2).""" result = [] for x in range(len(l) - 1): ls = l[x+1:] for y in ls: result.append((l[x],y)) return result PI = 3.14159265358979323 SOLAR_MASS = 4 * PI * PI DAYS_PER_YEAR = 365.24 BODIES = { 'sun': ([0.0, 0.0, 0.0], [0.0, 0.0, 0.0], SOLAR_MASS), 'jupiter': ([4.84143144246472090e+00, -1.16032004402742839e+00, -1.03622044471123109e-01], [1.66007664274403694e-03 * DAYS_PER_YEAR, 7.69901118419740425e-03 * DAYS_PER_YEAR, -6.90460016972063023e-05 * DAYS_PER_YEAR], 9.54791938424326609e-04 * SOLAR_MASS), 'saturn': ([8.34336671824457987e+00, 4.12479856412430479e+00, -4.03523417114321381e-01], [-2.76742510726862411e-03 * DAYS_PER_YEAR, 4.99852801234917238e-03 * DAYS_PER_YEAR, 2.30417297573763929e-05 * DAYS_PER_YEAR], 2.85885980666130812e-04 * SOLAR_MASS), 'uranus': ([1.28943695621391310e+01, -1.51111514016986312e+01, -2.23307578892655734e-01], [2.96460137564761618e-03 * DAYS_PER_YEAR, 2.37847173959480950e-03 * DAYS_PER_YEAR, -2.96589568540237556e-05 * DAYS_PER_YEAR], 4.36624404335156298e-05 * SOLAR_MASS), 'neptune': ([1.53796971148509165e+01, -2.59193146099879641e+01, 1.79258772950371181e-01], [2.68067772490389322e-03 * DAYS_PER_YEAR, 1.62824170038242295e-03 * DAYS_PER_YEAR, -9.51592254519715870e-05 * DAYS_PER_YEAR], 5.15138902046611451e-05 * SOLAR_MASS) } SYSTEM = list(BODIES.values()) PAIRS = combinations(SYSTEM) def advance(dt, n, bodies=SYSTEM, pairs=PAIRS): for i in range(n): for (([x1, y1, z1], v1, m1), ([x2, y2, z2], v2, m2)) in pairs: dx = x1 - x2 dy = y1 - y2 dz = z1 - z2 mag = dt * ((dx * dx + dy * dy + dz * dz) ** (-1.5)) b1m = m1 * mag b2m = m2 * mag v1[0] -= dx * b2m v1[1] -= dy * b2m v1[2] -= dz * b2m v2[0] += dx * b1m v2[1] += dy * b1m v2[2] += dz * b1m for (r, [vx, vy, vz], m) in bodies: r[0] += dt * vx r[1] += dt * vy r[2] += dt * vz def report_energy(bodies=SYSTEM, pairs=PAIRS, e=0.0): for (((x1, y1, z1), v1, m1), ((x2, y2, z2), v2, m2)) in pairs: dx = x1 - x2 dy = y1 - y2 dz = z1 - z2 e -= (m1 * m2) / ((dx * dx + dy * dy + dz * dz) ** 0.5) for (r, [vx, vy, vz], m) in bodies: e += m * (vx * vx + vy * vy + vz * vz) / 2. return e def offset_momentum(ref, bodies=SYSTEM, px=0.0, py=0.0, pz=0.0): for (r, [vx, vy, vz], m) in bodies: px -= vx * m py -= vy * m pz -= vz * m (r, v, m) = ref v[0] = px / m v[1] = py / m v[2] = pz / m def test_nbody(iterations): # Warm-up runs. report_energy() advance(0.01, 20000) report_energy() times = [] for _ in range(iterations): t0 = time() report_energy() advance(0.01, 20000) report_energy() t1 = time() times.append(t1 - t0) return times main = test_nbody if __name__ == '__main__': parser = optparse.OptionParser( usage="%prog [options]", description=("Run the n-body benchmark.")) util.add_standard_options_to(parser) options, args = parser.parse_args() offset_momentum(BODIES['sun']) # Set up global state util.run_benchmark(options, options.num_runs, test_nbody) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/benchmarks/nqueens.py0000644000175100001770000000457700000000000021025 0ustar00runnerdocker00000000000000#!/usr/bin/env python """Simple, brute-force N-Queens solver.""" __author__ = "collinwinter@google.com (Collin Winter)" # Python imports import optparse import re import string from time import time # Local imports import util import cython try: from builtins import range as _xrange except ImportError: from __builtin__ import xrange as _xrange # Pure-Python implementation of itertools.permutations(). @cython.locals(n=int, i=int, j=int) def permutations(iterable): """permutations(range(3), 2) --> (0,1) (0,2) (1,0) (1,2) (2,0) (2,1)""" pool = tuple(iterable) n = len(pool) indices = list(range(n)) cycles = list(range(1, n+1))[::-1] yield [ pool[i] for i in indices ] while n: for i in reversed(range(n)): j = cycles[i] - 1 if j == 0: indices[i:] = indices[i+1:] + indices[i:i+1] cycles[i] = n - i else: cycles[i] = j indices[i], indices[-j] = indices[-j], indices[i] yield [ pool[i] for i in indices ] break else: return # From https://code.activestate.com/recipes/576647/ @cython.locals(queen_count=int, i=int, vec=list) def n_queens(queen_count): """N-Queens solver. Args: queen_count: the number of queens to solve for. This is also the board size. Yields: Solutions to the problem. Each yielded value is looks like (3, 8, 2, 1, 4, ..., 6) where each number is the column position for the queen, and the index into the tuple indicates the row. """ cols = list(range(queen_count)) for vec in permutations(cols): if (queen_count == len({ vec[i]+i for i in cols }) == len({ vec[i]-i for i in cols })): yield vec def test_n_queens(iterations): # Warm-up runs. list(n_queens(8)) list(n_queens(8)) times = [] for _ in _xrange(iterations): t0 = time() list(n_queens(8)) t1 = time() times.append(t1 - t0) return times main = test_n_queens if __name__ == "__main__": parser = optparse.OptionParser( usage="%prog [options]", description=("Test the performance of an N-Queens solvers.")) util.add_standard_options_to(parser) options, args = parser.parse_args() util.run_benchmark(options, options.num_runs, test_n_queens) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/benchmarks/richards.pxd0000644000175100001770000000457100000000000021303 0ustar00runnerdocker00000000000000cimport cython @cython.final cdef class Packet: cdef public object link cdef public object ident cdef public object kind cdef public Py_ssize_t datum cdef public list data cpdef append_to(self,lst) cdef class TaskRec: pass @cython.final cdef class DeviceTaskRec(TaskRec): cdef public object pending @cython.final cdef class IdleTaskRec(TaskRec): cdef public long control cdef public Py_ssize_t count @cython.final cdef class HandlerTaskRec(TaskRec): cdef public object work_in # = None cdef public object device_in # = None cpdef workInAdd(self, Packet p) cpdef deviceInAdd(self, Packet p) @cython.final cdef class WorkerTaskRec(TaskRec): cdef public object destination # = I_HANDLERA cdef public Py_ssize_t count cdef class TaskState: cdef public bint packet_pending # = True cdef public bint task_waiting # = False cdef public bint task_holding # = False cpdef packetPending(self) cpdef waiting(self) cpdef running(self) cpdef waitingWithPacket(self) cpdef bint isPacketPending(self) cpdef bint isTaskWaiting(self) cpdef bint isTaskHolding(self) cpdef bint isTaskHoldingOrWaiting(self) cpdef bint isWaitingWithPacket(self) cdef class TaskWorkArea: cdef public list taskTab # = [None] * TASKTABSIZE cdef public object taskList # = None cdef public Py_ssize_t holdCount # = 0 cdef public Py_ssize_t qpktCount # = 0 cdef class Task(TaskState): cdef public Task link # = taskWorkArea.taskList cdef public object ident # = i cdef public object priority # = p cdef public object input # = w cdef public object handle # = r cpdef addPacket(self,Packet p,Task old) cpdef runTask(self) cpdef waitTask(self) cpdef hold(self) cpdef release(self,i) cpdef qpkt(self,Packet pkt) cpdef findtcb(self,id) cdef class DeviceTask(Task): @cython.locals(d=DeviceTaskRec) cpdef fn(self,Packet pkt,DeviceTaskRec r) cdef class HandlerTask(Task): @cython.locals(h=HandlerTaskRec) cpdef fn(self,Packet pkt,HandlerTaskRec r) cdef class IdleTask(Task): @cython.locals(i=IdleTaskRec) cpdef fn(self,Packet pkt,IdleTaskRec r) cdef class WorkTask(Task): @cython.locals(w=WorkerTaskRec) cpdef fn(self,Packet pkt,WorkerTaskRec r) @cython.locals(t=Task) cpdef schedule() cdef class Richards: cpdef run(self, iterations) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/benchmarks/richards.py0000644000175100001770000002433600000000000021141 0ustar00runnerdocker00000000000000# based on a Java version: # Based on original version written in BCPL by Dr Martin Richards # in 1981 at Cambridge University Computer Laboratory, England # and a C++ version derived from a Smalltalk version written by # L Peter Deutsch. # Java version: Copyright (C) 1995 Sun Microsystems, Inc. # Translation from C++, Mario Wolczko # Outer loop added by Alex Jacoby # Task IDs I_IDLE = 1 I_WORK = 2 I_HANDLERA = 3 I_HANDLERB = 4 I_DEVA = 5 I_DEVB = 6 # Packet types K_DEV = 1000 K_WORK = 1001 # Packet BUFSIZE = 4 BUFSIZE_RANGE = range(BUFSIZE) class Packet(object): def __init__(self,l,i,k): self.link = l self.ident = i self.kind = k self.datum = 0 self.data = [0] * BUFSIZE def append_to(self,lst): self.link = None if lst is None: return self else: p = lst next = p.link while next is not None: p = next next = p.link p.link = self return lst # Task Records class TaskRec(object): pass class DeviceTaskRec(TaskRec): def __init__(self): self.pending = None class IdleTaskRec(TaskRec): def __init__(self): self.control = 1 self.count = 10000 class HandlerTaskRec(TaskRec): def __init__(self): self.work_in = None self.device_in = None def workInAdd(self,p): self.work_in = p.append_to(self.work_in) return self.work_in def deviceInAdd(self,p): self.device_in = p.append_to(self.device_in) return self.device_in class WorkerTaskRec(TaskRec): def __init__(self): self.destination = I_HANDLERA self.count = 0 # Task class TaskState(object): def __init__(self): self.packet_pending = True self.task_waiting = False self.task_holding = False def packetPending(self): self.packet_pending = True self.task_waiting = False self.task_holding = False return self def waiting(self): self.packet_pending = False self.task_waiting = True self.task_holding = False return self def running(self): self.packet_pending = False self.task_waiting = False self.task_holding = False return self def waitingWithPacket(self): self.packet_pending = True self.task_waiting = True self.task_holding = False return self def isPacketPending(self): return self.packet_pending def isTaskWaiting(self): return self.task_waiting def isTaskHolding(self): return self.task_holding def isTaskHoldingOrWaiting(self): return self.task_holding or (not self.packet_pending and self.task_waiting) def isWaitingWithPacket(self): return self.packet_pending and self.task_waiting and not self.task_holding tracing = False layout = 0 def trace(a): global layout layout -= 1 if layout <= 0: print() layout = 50 print(a, end='') TASKTABSIZE = 10 class TaskWorkArea(object): def __init__(self): self.taskTab = [None] * TASKTABSIZE self.taskList = None self.holdCount = 0 self.qpktCount = 0 taskWorkArea = TaskWorkArea() class Task(TaskState): def __init__(self,i,p,w,initialState,r): self.link = taskWorkArea.taskList self.ident = i self.priority = p self.input = w self.packet_pending = initialState.isPacketPending() self.task_waiting = initialState.isTaskWaiting() self.task_holding = initialState.isTaskHolding() self.handle = r taskWorkArea.taskList = self taskWorkArea.taskTab[i] = self def fn(self,pkt,r): raise NotImplementedError def addPacket(self,p,old): if self.input is None: self.input = p self.packet_pending = True if self.priority > old.priority: return self else: p.append_to(self.input) return old def runTask(self): if self.isWaitingWithPacket(): msg = self.input self.input = msg.link if self.input is None: self.running() else: self.packetPending() else: msg = None return self.fn(msg,self.handle) def waitTask(self): self.task_waiting = True return self def hold(self): taskWorkArea.holdCount += 1 self.task_holding = True return self.link def release(self,i): t = self.findtcb(i) t.task_holding = False if t.priority > self.priority: return t else: return self def qpkt(self,pkt): t = self.findtcb(pkt.ident) taskWorkArea.qpktCount += 1 pkt.link = None pkt.ident = self.ident return t.addPacket(pkt,self) def findtcb(self,id): t = taskWorkArea.taskTab[id] if t is None: raise Exception("Bad task id %d" % id) return t # DeviceTask class DeviceTask(Task): def __init__(self,i,p,w,s,r): Task.__init__(self,i,p,w,s,r) def fn(self,pkt,r): d = r assert isinstance(d, DeviceTaskRec) if pkt is None: pkt = d.pending if pkt is None: return self.waitTask() else: d.pending = None return self.qpkt(pkt) else: d.pending = pkt if tracing: trace(pkt.datum) return self.hold() class HandlerTask(Task): def __init__(self,i,p,w,s,r): Task.__init__(self,i,p,w,s,r) def fn(self,pkt,r): h = r assert isinstance(h, HandlerTaskRec) if pkt is not None: if pkt.kind == K_WORK: h.workInAdd(pkt) else: h.deviceInAdd(pkt) work = h.work_in if work is None: return self.waitTask() count = work.datum if count >= BUFSIZE: h.work_in = work.link return self.qpkt(work) dev = h.device_in if dev is None: return self.waitTask() h.device_in = dev.link dev.datum = work.data[count] work.datum = count + 1 return self.qpkt(dev) # IdleTask class IdleTask(Task): def __init__(self,i,p,w,s,r): Task.__init__(self,i,0,None,s,r) def fn(self,pkt,r): i = r assert isinstance(i, IdleTaskRec) i.count -= 1 if i.count == 0: return self.hold() elif i.control & 1 == 0: i.control //= 2 return self.release(I_DEVA) else: i.control = i.control//2 ^ 0xd008 return self.release(I_DEVB) # WorkTask A = ord('A') class WorkTask(Task): def __init__(self,i,p,w,s,r): Task.__init__(self,i,p,w,s,r) def fn(self,pkt,r): w = r assert isinstance(w, WorkerTaskRec) if pkt is None: return self.waitTask() if w.destination == I_HANDLERA: dest = I_HANDLERB else: dest = I_HANDLERA w.destination = dest pkt.ident = dest pkt.datum = 0 for i in BUFSIZE_RANGE: # range(BUFSIZE) w.count += 1 if w.count > 26: w.count = 1 pkt.data[i] = A + w.count - 1 return self.qpkt(pkt) import time def schedule(): t = taskWorkArea.taskList while t is not None: pkt = None if tracing: print("tcb =", t.ident) if t.isTaskHoldingOrWaiting(): t = t.link else: if tracing: trace(chr(ord("0")+t.ident)) t = t.runTask() class Richards(object): def run(self, iterations): for i in range(iterations): taskWorkArea.holdCount = 0 taskWorkArea.qpktCount = 0 IdleTask(I_IDLE, 1, 10000, TaskState().running(), IdleTaskRec()) wkq = Packet(None, 0, K_WORK) wkq = Packet(wkq , 0, K_WORK) WorkTask(I_WORK, 1000, wkq, TaskState().waitingWithPacket(), WorkerTaskRec()) wkq = Packet(None, I_DEVA, K_DEV) wkq = Packet(wkq , I_DEVA, K_DEV) wkq = Packet(wkq , I_DEVA, K_DEV) HandlerTask(I_HANDLERA, 2000, wkq, TaskState().waitingWithPacket(), HandlerTaskRec()) wkq = Packet(None, I_DEVB, K_DEV) wkq = Packet(wkq , I_DEVB, K_DEV) wkq = Packet(wkq , I_DEVB, K_DEV) HandlerTask(I_HANDLERB, 3000, wkq, TaskState().waitingWithPacket(), HandlerTaskRec()) wkq = None DeviceTask(I_DEVA, 4000, wkq, TaskState().waiting(), DeviceTaskRec()) DeviceTask(I_DEVB, 5000, wkq, TaskState().waiting(), DeviceTaskRec()) schedule() if taskWorkArea.holdCount == 9297 and taskWorkArea.qpktCount == 23246: pass else: return False return True def entry_point(iterations): r = Richards() startTime = time.time() result = r.run(iterations) endTime = time.time() return result, startTime, endTime def main(iterations = 10, entry_point = entry_point): print("Richards benchmark (Python) starting... [%r]" % entry_point) result, startTime, endTime = entry_point(iterations) if not result: print("Incorrect results!") return -1 print("finished.") total_s = endTime - startTime print("Total time for %d iterations: %.2f secs" % (iterations, total_s)) print("Average time per iteration: %.2f ms" % (total_s*1000/iterations)) return 42 try: import sys if '-nojit' in sys.argv: sys.argv.remove('-nojit') raise ImportError import pypyjit except ImportError: pass else: import types for item in globals().values(): if isinstance(item, types.FunctionType): pypyjit.enable(item.func_code) elif isinstance(item, type): for it in item.__dict__.values(): if isinstance(it, types.FunctionType): pypyjit.enable(it.func_code) if __name__ == '__main__': import sys if len(sys.argv) >= 2: main(iterations = int(sys.argv[1])) else: main() ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/benchmarks/setup.py0000644000175100001770000000051700000000000020475 0ustar00runnerdocker00000000000000from distutils.core import setup from Cython.Build import cythonize directives = { 'optimize.inline_defnode_calls': True } setup( name = 'benchmarks', ext_modules = cythonize("*.py", language_level=3, annotate=True, compiler_directives=directives, exclude=["setup.py"]), ) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/benchmarks/spectralnorm.pxd0000644000175100001770000000064100000000000022207 0ustar00runnerdocker00000000000000 cimport cython cdef inline double eval_A(double i, double j) @cython.locals(i=long) cdef list eval_A_times_u(list u) @cython.locals(i=long) cdef list eval_At_times_u(list u) cdef list eval_AtA_times_u(list u) @cython.locals(j=long, u_j=double, partial_sum=double) cdef double part_A_times_u(double i, list u) @cython.locals(j=long, u_j=double, partial_sum=double) cdef double part_At_times_u(double i, list u) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/benchmarks/spectralnorm.py0000644000175100001770000000311500000000000022043 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*- # The Computer Language Benchmarks Game # http://shootout.alioth.debian.org/ # Contributed by Sebastien Loisel # Fixed by Isaac Gouy # Sped up by Josh Goldfoot # Dirtily sped up by Simon Descarpentries # Concurrency by Jason Stitt from time import time import util import optparse def eval_A(i, j): return 1.0 / ((i + j) * (i + j + 1) / 2 + i + 1) def eval_A_times_u(u): return [ part_A_times_u(i,u) for i in range(len(u)) ] def eval_At_times_u(u): return [ part_At_times_u(i,u) for i in range(len(u)) ] def eval_AtA_times_u(u): return eval_At_times_u(eval_A_times_u(u)) def part_A_times_u(i, u): partial_sum = 0 for j, u_j in enumerate(u): partial_sum += eval_A(i, j) * u_j return partial_sum def part_At_times_u(i, u): partial_sum = 0 for j, u_j in enumerate(u): partial_sum += eval_A(j, i) * u_j return partial_sum DEFAULT_N = 130 def main(n): times = [] for i in range(n): t0 = time() u = [1] * DEFAULT_N for dummy in range(10): v = eval_AtA_times_u(u) u = eval_AtA_times_u(v) vBv = vv = 0 for ue, ve in zip(u, v): vBv += ue * ve vv += ve * ve tk = time() times.append(tk - t0) return times if __name__ == "__main__": parser = optparse.OptionParser( usage="%prog [options]", description="Test the performance of the spectralnorm benchmark") util.add_standard_options_to(parser) options, args = parser.parse_args() util.run_benchmark(options, options.num_runs, main) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/benchmarks/util.py0000644000175100001770000000351400000000000020312 0ustar00runnerdocker00000000000000#!/usr/bin/env python """Utility code for benchmark scripts.""" __author__ = "collinwinter@google.com (Collin Winter)" import math import operator try: reduce except NameError: from functools import reduce def run_benchmark(options, num_runs, bench_func, *args): """Run the given benchmark, print results to stdout. Args: options: optparse.Values instance. num_runs: number of times to run the benchmark bench_func: benchmark function. `num_runs, *args` will be passed to this function. This should return a list of floats (benchmark execution times). """ if options.profile: import cProfile prof = cProfile.Profile() prof.runcall(bench_func, num_runs, *args) prof.print_stats(sort=options.profile_sort) else: data = bench_func(num_runs, *args) if options.take_geo_mean: product = reduce(operator.mul, data, 1) print(math.pow(product, 1.0 / len(data))) else: for x in data: print(x) def add_standard_options_to(parser): """Add a bunch of common command-line flags to an existing OptionParser. This function operates on `parser` in-place. Args: parser: optparse.OptionParser instance. """ parser.add_option("-n", action="store", type="int", default=100, dest="num_runs", help="Number of times to run the test.") parser.add_option("--profile", action="store_true", help="Run the benchmark through cProfile.") parser.add_option("--profile_sort", action="store", type="str", default="time", help="Column to sort cProfile output by.") parser.add_option("--take_geo_mean", action="store_true", help="Return the geo mean, rather than individual data.") ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.024724 Cython-3.0.8/Demos/callback/0000755000175100001770000000000000000000000016377 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/callback/Makefile0000644000175100001770000000024300000000000020036 0ustar00runnerdocker00000000000000all: python Setup.py build_ext --inplace test: all python run_cheese.py clean: @echo Cleaning Demos/callback @rm -f cheese.c *.o *.so *~ core @rm -rf build ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/callback/Makefile.nodistutils0000644000175100001770000000050300000000000022415 0ustar00runnerdocker00000000000000PYHOME = $(HOME)/pkg/python/version PYINCLUDE = \ -I$(PYHOME)/include/python2.2 \ -I$(PYHOME)/$(ARCH)/include/python2.2 %.c: %.pyx ../../bin/cython $< %.o: %.c gcc -c -fPIC $(PYINCLUDE) $< %.so: %.o gcc -shared $< -lm -o $@ all: cheese.so clean: @echo Cleaning Demos/callback @rm -f *.c *.o *.so *~ core core.* ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/callback/README.rst0000644000175100001770000000055000000000000020066 0ustar00runnerdocker00000000000000This example demonstrates how you can wrap a C API that has a callback interface, so that you can pass Python functions to it as callbacks. The files ``cheesefinder.h`` and ``cheesefinder.c`` represent the C library to be wrapped. The file ``cheese.pyx`` is the Cython module which wraps it. The file ``run_cheese.py`` demonstrates how to call the wrapper. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/callback/Setup.py0000644000175100001770000000035200000000000020051 0ustar00runnerdocker00000000000000from distutils.core import setup from distutils.extension import Extension from Cython.Build import cythonize setup( name = 'callback', ext_modules=cythonize([ Extension("cheese", ["cheese.pyx", "cheesefinder.c"]), ]), ) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/callback/cheese.pyx0000644000175100001770000000052100000000000020373 0ustar00runnerdocker00000000000000# # Cython wrapper for the cheesefinder API # cdef extern from "cheesefinder.h": ctypedef void (*cheesefunc)(char *name, void *user_data) void find_cheeses(cheesefunc user_func, void *user_data) def find(f): find_cheeses(callback, f) cdef void callback(char *name, void *f): (f)(name.decode('utf-8')) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/callback/cheesefinder.c0000644000175100001770000000050300000000000021165 0ustar00runnerdocker00000000000000/* * An example of a C API that provides a callback mechanism. */ #include "cheesefinder.h" static char *cheeses[] = { "cheddar", "camembert", "that runny one", 0 }; void find_cheeses(cheesefunc user_func, void *user_data) { char **p = cheeses; while (*p) { user_func(*p, user_data); ++p; } } ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/callback/cheesefinder.h0000644000175100001770000000016300000000000021174 0ustar00runnerdocker00000000000000typedef void (*cheesefunc)(char *name, void *user_data); void find_cheeses(cheesefunc user_func, void *user_data); ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/callback/run_cheese.py0000644000175100001770000000014700000000000021073 0ustar00runnerdocker00000000000000import cheese def report_cheese(name): print("Found cheese: " + name) cheese.find(report_cheese) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.024724 Cython-3.0.8/Demos/embed/0000755000175100001770000000000000000000000015717 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/embed/Makefile0000644000175100001770000000433600000000000017365 0ustar00runnerdocker00000000000000# Makefile for creating our standalone Cython program PYTHON := python PYVERSION := $(shell $(PYTHON) -c "import sys; print(sys.version[:3])") PYPREFIX := $(shell $(PYTHON) -c "import sys; print(sys.prefix)") INCDIR := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_python_inc())") PLATINCDIR := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_python_inc(plat_specific=True))") LIBDIR1 := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBDIR'))") LIBDIR2 := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBPL'))") PYLIB := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBRARY')[3:-2])") CC := $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('CC'))") LINKCC := $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('LINKCC'))") LINKFORSHARED := $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('LINKFORSHARED'))") LIBS := $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('LIBS'))") SYSLIBS := $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('SYSLIBS'))") .PHONY: paths all clean test paths: @echo "PYTHON=$(PYTHON)" @echo "PYVERSION=$(PYVERSION)" @echo "PYPREFIX=$(PYPREFIX)" @echo "INCDIR=$(INCDIR)" @echo "PLATINCDIR=$(PLATINCDIR)" @echo "LIBDIR1=$(LIBDIR1)" @echo "LIBDIR2=$(LIBDIR2)" @echo "PYLIB=$(PYLIB)" @echo "CC=$(CC)" @echo "LINKCC=$(LINKCC)" @echo "LINKFORSHARED=$(LINKFORSHARED)" @echo "LIBS=$(LIBS)" @echo "SYSLIBS=$(SYSLIBS)" embedded: embedded.o $(LINKCC) -o $@ $^ -L$(LIBDIR1) -L$(LIBDIR2) -l$(PYLIB) $(LIBS) $(SYSLIBS) $(LINKFORSHARED) embedded.o: embedded.c $(CC) -c $^ -I$(INCDIR) -I$(PLATINCDIR) CYTHON := ../../cython.py embedded.c: embedded.pyx @$(PYTHON) $(CYTHON) --embed embedded.pyx all: embedded clean: @echo Cleaning Demos/embed @rm -f *~ *.o *.so core core.* *.c embedded test.output test: clean all LD_LIBRARY_PATH=$(LIBDIR1):$$LD_LIBRARY_PATH ./embedded > test.output $(PYTHON) assert_equal.py embedded.output test.output ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/embed/Makefile.msc0000644000175100001770000000175500000000000020150 0ustar00runnerdocker00000000000000# Makefile for Microsoft C Compiler, building a DLL PYVERSION = 2.2 PYHOME = \Python$(PYVERSION:.=) PYINCLUDE = -I$(PYHOME)\include PYLIB = /LIBPATH:$(PYHOME)\libs CFLAGS = $(PYINCLUDE) /Ox /W3 /GX -nologo .SUFFIXES: .exe .dll .obj .c .cpp .pyx .pyx.c: $(PYHOME)\Python.exe ../../cython.py $< all: main.exe clean: del /Q/F *.obj embedded.h embedded.c main.exe embedded.dll embedded.lib embedded.exp # When linking the DLL we must explicitly list all of the exports # There doesn't seem to be an easy way to get DL_EXPORT to have the correct definition # to do the export for us without breaking the importing of symbols from the core # python library. embedded.dll: embedded.obj link /nologo /DLL /INCREMENTAL:NO $(PYLIB) $** /IMPLIB:$*.lib /DEF:<< /OUT:$*.dll EXPORTS initembedded EXPORTS spam << main.exe: main.obj embedded.lib link /nologo $** $(PYLIB) /OUT:main.exe embedded.h: embedded.c main.obj: embedded.h embedded.obj: embedded.c $(CC) /MD $(CFLAGS) -c $** embedded.lib: embedded.dll ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/embed/Makefile.msc.static0000644000175100001770000000076400000000000021435 0ustar00runnerdocker00000000000000# Makefile for Microsoft compiler statically linking PYVERSION = 2.2 PYHOME = \Python$(PYVERSION:.=) PYINCLUDE = -I$(PYHOME)\include PYLIB = /LIBPATH:$(PYHOME)\libs python22.lib CFLAGS = $(PYINCLUDE) /Ox /W3 /GX -nologo .SUFFIXES: .exe .dll .obj .c .cpp .pyx .pyx.c: $(PYHOME)\Python.exe ../../cython.py $< all: main.exe clean: -del /Q/F *.obj embedded.h embedded.c main.exe main.exe: main.obj embedded.obj link /nologo $** $(PYLIB) /OUT:main.exe embedded.h: embedded.c main.obj: embedded.h ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/embed/Makefile.unix0000644000175100001770000000063000000000000020340 0ustar00runnerdocker00000000000000# Makefile for creating our standalone Cython program PYVERSION=2.3 PYPREFIX=/usr INCLUDES=-I$(PYPREFIX)/include/python$(PYVERSION) embedded: embedded.o gcc -o $@ $^ -lpython$(PYVERSION) embedded.o: embedded.c gcc -c $^ $(INCLUDES) embedded.c: embedded.pyx @python ../../cython.py --embed embedded.pyx all: embedded clean: @echo Cleaning Demos/embed @rm -f *~ *.o *.so core core.* *.c embedded ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/embed/README.rst0000644000175100001770000000031300000000000017403 0ustar00runnerdocker00000000000000This example demonstrates how Cython-generated code can be called directly from a main program written in C. The Windows makefiles were contributed by Duncan Booth: Duncan.Booth@SuttonCourtenay.org.uk. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/embed/assert_equal.py0000644000175100001770000000043200000000000020760 0ustar00runnerdocker00000000000000from __future__ import absolute_import, print_function import sys f1 = open(sys.argv[1]) f2 = open(sys.argv[2]) try: if f1.read() != f2.read(): print("Files differ") sys.exit(1) else: print("Files identical") finally: f1.close() f2.close() ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/embed/embedded.output0000644000175100001770000000003300000000000020726 0ustar00runnerdocker00000000000000__main__ Hi, I'm embedded. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/embed/embedded.pyx0000644000175100001770000000021600000000000020211 0ustar00runnerdocker00000000000000# cython: language_level=3 print(__name__) if __name__ == "__main__": print("Hi, I'm embedded.") else: print("I'm being imported.") ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.024724 Cython-3.0.8/Demos/freeze/0000755000175100001770000000000000000000000016123 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/freeze/Makefile0000644000175100001770000000311700000000000017565 0ustar00runnerdocker00000000000000CC = gcc CYTHON = ../../bin/cython CYTHON_FREEZE = ../../bin/cython_freeze PYTHON = python RST2HTML = rst2html PY_LDFLAGS = $(shell $(PYTHON) -c 'from distutils.sysconfig import get_config_var as g; import sys; sys.stdout.write(" ".join([g("LINKFORSHARED"), "-L"+g("LIBPL")]) + "\n")') PY_CPPFLAGS = $(shell $(PYTHON) -c 'from distutils.sysconfig import *; import sys; sys.stdout.write("-I"+get_python_inc() + "\n")') LIBDIR1 := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBDIR'))") LIBDIR2 := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBPL'))") PYLIB := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBRARY')[3:-2])") LIBS := $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('LIBS'))") CFLAGS = -fPIC -fno-strict-aliasing -g -O2 -Wall -Wextra CPPFLAGS = $(PY_CPPFLAGS) LDFLAGS = $(PY_LDFLAGS) LDLIBS = -L$(LIBDIR1) -L$(LIBDIR2) -l$(PYLIB) # Name of executable TARGETS = nCr python # List of Cython source files, with main module first. CYTHON_SOURCE = combinatorics.pyx lcmath.pyx CYTHON_SECONDARY = $(CYTHON_SOURCE:.pyx=.c) $(TARGETS:=.c) all : $(TARGETS) html : README.html $(TARGETS) : % : %.o $(CYTHON_SOURCE:.pyx=.o) nCr.c : $(CYTHON_FREEZE) $(CYTHON_SOURCE:.pyx=) > $@ python.c : $(CYTHON_FREEZE) --pymain $(CYTHON_SOURCE:.pyx=) > $@ %.c : %.pyx $(CYTHON) $(CYTHONFLAGS) $^ %.html : %.txt $(RST2HTML) $^ $@ clean: $(RM) *.o $(CYTHON_SECONDARY) $(TARGETS) README.html .PHONY: clean .SECONDARY: $(CYTHON_SECONDARY) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/freeze/README.rst0000644000175100001770000000704300000000000017616 0ustar00runnerdocker00000000000000NAME ==== **cython_freeze** - create a C file for embedding Cython modules SYNOPSIS ======== :: cython_freeze [-o outfile] [-p] module [...] DESCRIPTION =========== **cython_freeze** generates a C source file to embed a Python interpreter with one or more Cython modules built in. This allows one to create a single executable from Cython code, without having to have separate shared objects for each Cython module. A major advantage of this approach is that it allows debugging with gprof(1), which does not work with shared objects. Unless ``-p`` is given, the first module's ``__name__`` is set to ``"__main__"`` and is imported on startup; if ``-p`` is given, a normal Python interpreter is built, with the given modules built into the binary. Note that this method differs from ``cython --embed``. The ``--embed`` options modifies the resulting C source file to include a ``main()`` function, so it can only be used on a single Cython module. The advantage ``--embed`` is simplicity. This module, on the other hand, can be used with multiple modules, but it requires another C source file to be created. OPTIONS ======= :: -o FILE, --outfile=FILE write output to FILE instead of standard output -p, --pymain do not automatically run the first module as __main__ EXAMPLE ======= In the ``Demos/freeze`` directory, there exist two Cython modules: * ``lcmath.pyx``: A module that interfaces with the -lm library. * ``combinatorics.pyx``: A module that implements n-choose-r using lcmath. Both modules have the Python idiom ``if __name__ == "__main__"``, which only execute if that module is the "main" module. If run as main, lcmath prints the factorial of the argument, while combinatorics prints n-choose-r. The provided Makefile creates an executable, *nCr*, using combinatorics as the "main" module. It basically performs the following (ignoring the compiler flags):: $ cython_freeze combinatorics lcmath > nCr.c $ cython combinatorics.pyx $ cython lcmath.pyx $ gcc -c nCr.c $ gcc -c combinatorics.c $ gcc -c lcmath.c $ gcc nCr.o combinatorics.o lcmath.o -o nCr Because the combinatorics module was listed first, its ``__name__`` is set to ``"__main__"``, while lcmath's is set to ``"lcmath"``. The executable now contains a Python interpreter and both Cython modules. :: $ ./nCr USAGE: ./nCr n r Prints n-choose-r. $ ./nCr 15812351235 12 5.10028093999e+113 You may wish to build a normal Python interpreter, rather than having one module as "main". This may happen if you want to use your module from an interactive shell or from another script, yet you still want it statically linked so you can profile it with gprof. To do this, add the ``--pymain`` flag to ``cython_freeze``. In the Makefile, the *python* executable is built like this. :: $ cython_freeze --pymain combinatorics lcmath -o python.c $ gcc -c python.c $ gcc python.o combinatorics.o lcmath.o -o python Now ``python`` is a normal Python interpreter, but the lcmath and combinatorics modules will be built into the executable. :: $ ./python Python 2.6.2 (release26-maint, Apr 19 2009, 01:58:18) [GCC 4.3.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import lcmath >>> lcmath.factorial(155) 4.7891429014634364e+273 PREREQUISITES ============= Cython 0.11.2 (or newer, assuming the API does not change) SEE ALSO ======== * `Python `_ * `Cython `_ * `freeze.py `_ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/freeze/combinatorics.pyx0000644000175100001770000000073600000000000021527 0ustar00runnerdocker00000000000000# cython: language_level=3 import lcmath def nCr(n, r): """Return the number of ways to choose r elements of a set of n.""" return lcmath.exp( lcmath.lfactorial(n) - lcmath.lfactorial(r) - lcmath.lfactorial(n-r) ) if __name__ == "__main__": import sys if len(sys.argv) != 3: sys.stderr.write("USAGE: %s n r\nPrints n-choose-r.\n" % sys.argv[0]) sys.exit(2) n, r = map(float, sys.argv[1:]) print(nCr(n, r)) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/freeze/lcmath.pyx0000644000175100001770000000113700000000000020137 0ustar00runnerdocker00000000000000# cython: language_level=3 cdef extern from "math.h": double c_lgamma "lgamma" (double) double c_exp "exp" (double) def exp(n): """Return e**n.""" return c_exp(n) def lfactorial(n): """Return an estimate of the log factorial of n.""" return c_lgamma(n+1) def factorial(n): """Return an estimate of the factorial of n.""" return c_exp( c_lgamma(n+1) ) if __name__ == "__main__": import sys if len(sys.argv) != 2: sys.stderr.write("USAGE: %s n\nPrints n!.\n" % sys.argv[0]) sys.exit(2) n, = map(float, sys.argv[1:]) print(factorial(n)) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/integrate0.py0000644000175100001770000000022400000000000017255 0ustar00runnerdocker00000000000000def f(x): return x**2-x def integrate_f(a, b, N): s = 0.0 dx = (b-a)/N for i in range(N): s += f(a+i*dx) return s * dx ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/integrate1.pyx0000644000175100001770000000026100000000000017447 0ustar00runnerdocker00000000000000# cython: language_level=3 def f(x): return x**2-x def integrate_f(a, b, N): s = 0.0 dx = (b-a)/N for i in range(N): s += f(a+i*dx) return s * dx ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/integrate2.pyx0000644000175100001770000000035400000000000017453 0ustar00runnerdocker00000000000000# cython: language_level=3 cdef double f(double x) except? -2: return x**2-x def integrate_f(double a, double b, int N): cdef int i s = 0.0 dx = (b-a)/N for i in range(N): s += f(a+i*dx) return s * dx ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/integrate_timing.py0000644000175100001770000000065300000000000020552 0ustar00runnerdocker00000000000000from __future__ import absolute_import, print_function import timeit import integrate0, integrate1, integrate2 number = 10 py_time = None for m in ('integrate0', 'integrate1', 'integrate2'): print(m) t = min(timeit.repeat("integrate_f(0.0, 10.0, 100000)", "from %s import integrate_f" % m, number=number)) if py_time is None: py_time = t print(" ", t / number, "s") print(" ", py_time / t) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.024724 Cython-3.0.8/Demos/libraries/0000755000175100001770000000000000000000000016617 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/libraries/call_mymath.pyx0000644000175100001770000000013300000000000021650 0ustar00runnerdocker00000000000000cdef extern from "mymath.h": double sinc(double) def call_sinc(x): return sinc(x) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/libraries/mymath.c0000644000175100001770000000011700000000000020261 0ustar00runnerdocker00000000000000#include "math.h" double sinc(double x) { return x == 0 ? 1 : sin(x)/x; } ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/libraries/mymath.h0000644000175100001770000000002500000000000020264 0ustar00runnerdocker00000000000000double sinc(double); ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/libraries/setup.py0000644000175100001770000000165500000000000020340 0ustar00runnerdocker00000000000000from __future__ import absolute_import, print_function import os import sys from distutils.core import setup from distutils.extension import Extension from Cython.Build import cythonize # For demo purposes, we build our own tiny library. try: print("building libmymath.a") assert os.system("gcc -shared -fPIC -c mymath.c -o mymath.o") == 0 assert os.system("ar rcs libmymath.a mymath.o") == 0 except: if not os.path.exists("libmymath.a"): print("Error building external library, please create libmymath.a manually.") sys.exit(1) # Here is how to use the library built above. ext_modules = cythonize([ Extension("call_mymath", sources=["call_mymath.pyx"], include_dirs=[os.getcwd()], # path to .h file(s) library_dirs=[os.getcwd()], # path to .a or .so file(s) libraries=['mymath']) ]) setup( name='Demos', ext_modules=ext_modules, ) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/numpy_demo.pyx0000644000175100001770000000027700000000000017567 0ustar00runnerdocker00000000000000cimport numpy as cnp def sum_of_squares(cnp.ndarray[double, ndim=1] arr): cdef long N = arr.shape[0] cdef double ss = 0 for i in range(N): ss += arr[i]**2 return ss ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/overflow_perf.pyx0000644000175100001770000001041300000000000020263 0ustar00runnerdocker00000000000000# cython: language_level=3 # distutils: extra_compile_args = -O3 cimport cython ctypedef fused INT: int long long unsigned int unsigned long long object ctypedef fused C_INT: int long long unsigned int unsigned long long @cython.overflowcheck(False) def fib(INT n): """ >>> [fib(k) for k in range(10)] [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] """ cdef INT a, b, k a, b = 0, 1 for k in range(n): a, b = b, a + b return int(b) @cython.overflowcheck(True) def fib_overflow(INT n): """ >>> [fib_overflow(k) for k in range(10)] [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] """ cdef INT a, b, k a, b = 0, 1 for k in range(n): a, b = b, a + b return int(b) @cython.overflowcheck(False) def collatz(INT n): """ >>> collatz(1) 0 >>> collatz(5) 5 >>> collatz(10) 6 """ cdef INT k = 0 while n != 1: if n % 2 == 0: n //= 2 else: n = 3*n + 1 k += 1 return int(k) @cython.overflowcheck(True) @cython.overflowcheck.fold(False) def collatz_overflow(INT n): """ >>> collatz_overflow(1) 0 >>> collatz_overflow(5) 5 >>> collatz_overflow(10) 6 """ cdef INT k = 0 while n != 1: if n % 2 == 0: n //= 2 else: n = 3*n + 1 k += 1 return int(k) @cython.overflowcheck(True) @cython.overflowcheck.fold(True) def collatz_overflow_fold(INT n): """ >>> collatz_overflow_fold(1) 0 >>> collatz_overflow_fold(5) 5 >>> collatz_overflow_fold(10) 6 """ cdef INT k = 0 while n != 1: if n % 2 == 0: n //= 2 else: n = 3*n + 1 k += 1 return int(k) @cython.overflowcheck(False) def factorial(INT n): """ >>> factorial(2) 2 >>> factorial(5) 120 """ cdef INT k, res = 1 for k in range(2, n+1): res = res * k return int(res) @cython.overflowcheck(True) def factorial_overflow(INT n): """ >>> factorial_overflow(2) 2 >>> factorial_overflow(5) 120 """ cdef INT k, res = 1 for k in range(2, n+1): res = res * k return int(res) @cython.overflowcheck(False) def most_orthogonal(C_INT[:,::1] vectors): cdef C_INT n = vectors.shape[0] cdef C_INT* a cdef C_INT* b cdef double min_dot = 2 # actual max is 1 for i in range(n): for j in range(i): a = &vectors[i, 0] b = &vectors[j, 0] # A highly nested arithmetic expression... normalized_dot = (1.0 * (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]) / ((a[0]*a[0] + a[1]*a[1] + a[2]*a[2]) * (b[0]*b[0] + b[1]*b[1]+b[2]*b[2]))) if normalized_dot < min_dot: min_dot = normalized_dot min_pair = i, j return vectors[i], vectors[j] @cython.overflowcheck(True) @cython.overflowcheck.fold(False) def most_orthogonal_overflow(C_INT[:,::1] vectors): cdef C_INT n = vectors.shape[0] cdef C_INT* a cdef C_INT* b cdef double min_dot = 2 # actual max is 1 for i in range(n): for j in range(i): a = &vectors[i, 0] b = &vectors[j, 0] # A highly nested arithmetic expression... normalized_dot = ((a[0]*b[0] + a[1]*b[1] + a[2]*b[2]) / (1.0 * (a[0]*a[0] + a[1]*a[1] + a[2]*a[2]) * (b[0]*b[0] + b[1]*b[1]+b[2]*b[2]))) if normalized_dot < min_dot: min_dot = normalized_dot min_pair = i, j return vectors[i], vectors[j] @cython.overflowcheck(True) @cython.overflowcheck.fold(True) def most_orthogonal_overflow_fold(C_INT[:,::1] vectors): cdef C_INT n = vectors.shape[0] cdef C_INT* a cdef C_INT* b cdef double min_dot = 2 # actual max is 1 for i in range(n): for j in range(i): a = &vectors[i, 0] b = &vectors[j, 0] # A highly nested arithmetic expression... normalized_dot = ((a[0]*b[0] + a[1]*b[1] + a[2]*b[2]) / (1.0 * (a[0]*a[0] + a[1]*a[1] + a[2]*a[2]) * (b[0]*b[0] + b[1]*b[1]+b[2]*b[2]))) if normalized_dot < min_dot: min_dot = normalized_dot min_pair = i, j return vectors[i], vectors[j] ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/overflow_perf_run.py0000644000175100001770000000370300000000000020763 0ustar00runnerdocker00000000000000from __future__ import absolute_import, print_function from overflow_perf import * import sys import timeit try: import numpy as np except ImportError: np = None def run_tests(N): global f for func in most_orthogonal, fib, collatz, factorial: print(func.__name__) for type in ['int', 'unsigned int', 'long long', 'unsigned long long', 'object']: if func == most_orthogonal: if type == 'object' or np is None: continue type_map = {'int': 'int32', 'unsigned int': 'uint32', 'long long': 'int64', 'unsigned long long': 'uint64'} shape = N, 3 arg = np.ndarray(shape, dtype=type_map[type]) arg[:] = 1000 * np.random.random(shape) else: arg = N try: print("%s[%s](%s)" % (func.__name__, type, N)) with_overflow = my_timeit(globals()[func.__name__ + "_overflow"][type], arg) no_overflow = my_timeit(func[type], arg) print("\t%0.04e\t%0.04e\t%0.04f" % (no_overflow, with_overflow, with_overflow / no_overflow)) if func.__name__ + "_overflow_fold" in globals(): with_overflow = my_timeit(globals()[func.__name__ + "_overflow_fold"][type], arg) print("\t%0.04e\t%0.04e\t%0.04f (folded)" % ( no_overflow, with_overflow, with_overflow / no_overflow)) except OverflowError: print(" ", "Overflow") def my_timeit(func, N): global f, arg f = func arg = N for exponent in range(10, 30): times = 2 ** exponent res = min(timeit.repeat("f(arg)", setup="from __main__ import f, arg", repeat=5, number=times)) if res > .25: break return res / times params = sys.argv[1:] if not params: params = [129, 9, 97] for arg in params: print() print("N", arg) run_tests(int(arg)) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/primes.pyx0000644000175100001770000000062200000000000016704 0ustar00runnerdocker00000000000000# cython: language_level=3 print("starting") def primes(int kmax): # cdef int n, k, i cdef int p[1000] result = [] if kmax > 1000: kmax = 1000 k = 0 n = 2 while k < kmax: i = 0 while i < k and n % p[i] != 0: i += 1 if i == k: p[k] = n k += 1 result.append(n) n += 1 return result ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/pyprimes.py0000644000175100001770000000034700000000000017071 0ustar00runnerdocker00000000000000def primes(kmax): p = [] k = 0 n = 2 while k < kmax: i = 0 while i < k and n % p[i] != 0: i += 1 if i == k: p.append(n) k += 1 n += 1 return p ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/run_numeric_demo.py0000644000175100001770000000016200000000000020546 0ustar00runnerdocker00000000000000import numpy import numpy_demo a = numpy.array([1.0, 3.5, 8.4, 2.3, 6.6, 4.1], "d") numpy_demo.sum_of_squares(a) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/run_primes.py0000644000175100001770000000026300000000000017401 0ustar00runnerdocker00000000000000from __future__ import absolute_import, print_function import sys from primes import primes if len(sys.argv) >= 2: n = int(sys.argv[1]) else: n = 1000 print(primes(n)) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/run_spam.py0000644000175100001770000000027000000000000017040 0ustar00runnerdocker00000000000000from __future__ import absolute_import, print_function from spam import Spam s = Spam() print("Created:", s) s.set_amount(42) print("Amount =", s.get_amount()) s.describe() s = None ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/setup.py0000644000175100001770000000116000000000000016353 0ustar00runnerdocker00000000000000# Run as: # python setup.py build_ext --inplace import sys sys.path.insert(0, "..") from distutils.core import setup from distutils.extension import Extension from Cython.Build import cythonize ext_modules = cythonize("**/*.pyx", exclude="numpy_*.pyx") # Only compile the following if numpy is installed. try: from numpy import get_include except ImportError: pass else: numpy_demo = [Extension("*", ["numpy_*.pyx"], include_dirs=get_include())] ext_modules.extend(cythonize(numpy_demo)) setup( name = 'Demos', ext_modules = ext_modules, ) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Demos/spam.pyx0000644000175100001770000000066600000000000016355 0ustar00runnerdocker00000000000000# cython: language_level=3 # # Example of an extension type. # cdef class Spam: cdef public int amount def __cinit__(self): self.amount = 0 def __dealloc__(self): print(self.amount, "tons of spam is history.") def get_amount(self): return self.amount def set_amount(self, new_amount): self.amount = new_amount def describe(self): print(self.amount, "tons of spam!") ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/INSTALL.txt0000644000175100001770000000114500000000000015444 0ustar00runnerdocker00000000000000Cython - Installation Instructions ================================== You have several installation options: (1) Use pip to install Cython from PyPI: pip install Cython OR (2) From a source copy, run pip in the top directory as follows: pip install . This will install the Cython package into your Python system. OR (3) If you prefer not to modify your Python installation, arrange for the directory containing this file (INSTALL.txt) to be in your PYTHONPATH. On unix, also put the bin directory on your PATH. See README.txt for pointers to other documentation. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/LICENSE.txt0000644000175100001770000002367600000000000015435 0ustar00runnerdocker00000000000000 Apache License Version 2.0, January 2004 https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/MANIFEST.in0000644000175100001770000000205200000000000015331 0ustar00runnerdocker00000000000000include MANIFEST.in README.rst INSTALL.txt ToDo.txt USAGE.txt CHANGES.rst include COPYING.txt LICENSE.txt Makefile include .gitrev include pylintrc include tox.ini include setup.py include setup.cfg include setupegg.py include bin/* include *requirements*.txt include cython.py cythonize.py cygdb.py recursive-include Cython *.pyx *.pxd *.pyi include Cython/Parser/Grammar Cython/Parser/__init__.py include Doc/* include Demos/*.pyx include Demos/*.py include Demos/callback/* include Demos/benchmarks/* include Demos/embed/* include Demos/freeze/* include Demos/libraries/* include Demos/Makefile* recursive-include Cython/Debugger/Tests *.pyx *.pxd *.c *.h recursive-include Cython/Utility *.pyx *.pxd *.c *.h *.cpp recursive-include Tools * recursive-include tests *.pyx *.pxd *.pxi *.py *.h *.hpp *.BROKEN bugs.txt recursive-include tests *_lib.cpp *.srctree recursive-include docs * include runtests.py include Cython/Debugger/Tests/cfuncs.c include Cython/Debugger/Tests/codefile recursive-include pyximport *.py include pyximport/PKG-INFO pyximport/README ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Makefile0000644000175100001770000000616000000000000015237 0ustar00runnerdocker00000000000000PACKAGENAME=Cython PYTHON?=python TESTOPTS?= REPO = git://github.com/cython/cython.git VERSION?=$(shell sed -ne 's|^__version__\s*=\s*"\([^"]*\)".*|\1|p' Cython/Shadow.py) PARALLEL?=$(shell ${PYTHON} -c 'import sys; print("-j5" if sys.version_info >= (3,5) else "")' || true) MANYLINUX_CFLAGS=-O3 -g0 -mtune=generic -pipe -fPIC MANYLINUX_LDFLAGS= MANYLINUX_IMAGES= \ manylinux2014_x86_64 \ manylinux2014_i686 \ musllinux_1_1_x86_64 \ musllinux_1_1_aarch64 \ manylinux_2_24_x86_64 \ manylinux_2_24_i686 \ manylinux_2_24_aarch64 \ manylinux_2_28_x86_64 \ manylinux_2_28_aarch64 \ # manylinux_2_24_ppc64le \ # manylinux_2_24_s390x all: local local: ${PYTHON} setup.py build_ext --inplace $(PARALLEL) plocal: ${PYTHON} setup.py build_ext --inplace --cython-profile $(PARALLEL) sdist: dist/$(PACKAGENAME)-$(VERSION).tar.gz dist/$(PACKAGENAME)-$(VERSION).tar.gz: $(PYTHON) setup.py sdist pywheel: dist/$(PACKAGENAME)-$(VERSION)-py2.py3-none-any.whl dist/$(PACKAGENAME)-$(VERSION)-py2.py3-none-any.whl: ${PYTHON} setup.py bdist_wheel --no-cython-compile --universal [ -f "$@" ] # check that we generated the expected universal wheel TMPDIR = .repo_tmp .git: .gitrev rm -rf $(TMPDIR) git clone -n $(REPO) $(TMPDIR) cd $(TMPDIR) && git reset -q "$(shell cat .gitrev)" mv $(TMPDIR)/.git . rm -rf $(TMPDIR) git ls-files -d | xargs git checkout -- # Create a git repo from an unpacked source directory. repo: .git clean: @echo Cleaning Source @rm -fr build @rm -f *.py[co] */*.py[co] */*/*.py[co] */*/*/*.py[co] @rm -f *.so */*.so */*/*.so @rm -f *.pyd */*.pyd */*/*.pyd @rm -f *~ */*~ */*/*~ @rm -f core */core @rm -f Cython/*.c @rm -f Cython/Compiler/*.c @rm -f Cython/Plex/*.c @rm -f Cython/Tempita/*.c @rm -f Cython/Runtime/refnanny.c @(cd Demos; $(MAKE) clean) testclean: rm -fr BUILD TEST_TMP test: testclean ${PYTHON} runtests.py -vv ${TESTOPTS} checks: ${PYTHON} runtests.py -vv --no-unit --no-doctest --no-file --no-pyregr --no-examples s5: $(MAKE) -C Doc/s5 slides qemu-user-static: docker run --rm --privileged hypriot/qemu-register wheel_manylinux: sdist $(addprefix wheel_,$(MANYLINUX_IMAGES)) $(addprefix wheel_,$(filter-out %_x86_64, $(filter-out %_i686, $(MANYLINUX_IMAGES)))): qemu-user-static wheel_%: dist/$(PACKAGENAME)-$(VERSION).tar.gz echo "Building wheels for $(PACKAGENAME) $(VERSION)" mkdir -p wheelhouse_$(subst wheel_,,$@) time docker run --rm -t \ -v $(shell pwd):/io \ -e CFLAGS="$(MANYLINUX_CFLAGS)" \ -e LDFLAGS="$(MANYLINUX_LDFLAGS) -fPIC" \ -e WHEELHOUSE=wheelhouse$(subst wheel_musllinux,,$(subst wheel_manylinux,,$@)) \ quay.io/pypa/$(subst wheel_,,$@) \ bash -c '\ rm -fr /opt/python/*pypy* ; \ for cpdir in /opt/python/*27* ; do \ if [ -d "$$cpdir" ]; \ then rm -fr /opt/python/*3[78912]; \ else rm -fr /opt/python/*{27*,3[456]*}; \ fi; break; \ done ; \ ls /opt/python/ ; \ for PYBIN in /opt/python/cp*/bin; do \ $$PYBIN/python -V; \ { $$PYBIN/pip wheel -w /io/$$WHEELHOUSE /io/$< & } ; \ done; wait; \ for whl in /io/$$WHEELHOUSE/$(PACKAGENAME)-$(VERSION)-*-linux_*.whl; do auditwheel repair $$whl -w /io/$$WHEELHOUSE; done' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.2367241 Cython-3.0.8/PKG-INFO0000644000175100001770000000613000000000000014671 0ustar00runnerdocker00000000000000Metadata-Version: 2.1 Name: Cython Version: 3.0.8 Summary: The Cython compiler for writing C extensions in the Python language. Home-page: https://cython.org/ Author: Robert Bradshaw, Stefan Behnel, Dag Seljebotn, Greg Ewing, et al. Author-email: cython-devel@python.org License: Apache-2.0 Project-URL: Documentation, https://cython.readthedocs.io/ Project-URL: Donate, https://cython.readthedocs.io/en/latest/src/donating.html Project-URL: Source Code, https://github.com/cython/cython Project-URL: Bug Tracker, https://github.com/cython/cython/issues Project-URL: User Group, https://groups.google.com/g/cython-users Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Programming Language :: C Classifier: Programming Language :: Cython Classifier: Topic :: Software Development :: Code Generators Classifier: Topic :: Software Development :: Compilers Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* License-File: LICENSE.txt License-File: COPYING.txt The Cython language makes writing C extensions for the Python language as easy as Python itself. Cython is a source code translator based on Pyrex_, but supports more cutting edge functionality and optimizations. The Cython language is a superset of the Python language (almost all Python code is also valid Cython code), but Cython additionally supports optional static typing to natively call C functions, operate with C++ classes and declare fast C types on variables and class attributes. This allows the compiler to generate very efficient C code from Cython code. This makes Cython the ideal language for writing glue code for external C/C++ libraries, and for fast C modules that speed up the execution of Python code. Note that for one-time builds, e.g. for CI/testing, on platforms that are not covered by one of the wheel packages provided on PyPI *and* the pure Python wheel that we provide is not used, it is substantially faster than a full source build to install an uncompiled (slower) version of Cython with:: pip install Cython --install-option="--no-cython-compile" .. _Pyrex: https://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/README.rst0000644000175100001770000001416300000000000015270 0ustar00runnerdocker00000000000000Welcome to Cython! ================== Cython is a Python compiler that makes writing C extensions for Python as easy as Python itself. Cython is based on Pyrex, but supports more cutting edge functionality and optimizations. Cython translates Python code to C/C++ code, but additionally supports calling C functions and declaring C types on variables and class attributes. This allows the compiler to generate very efficient C code from Cython code. This makes Cython the ideal language for wrapping external C libraries, and for fast C modules that speed up the execution of Python code. * Official website: https://cython.org/ * Documentation: https://docs.cython.org/ * Github repository: https://github.com/cython/cython * Wiki: https://github.com/cython/cython/wiki Cython has `about 30 million downloads `_ per month on PyPI. You can **support the Cython project** via `Github Sponsors `_ or `Tidelift `_. Installation: ------------- If you already have a C compiler, just run following command:: pip install Cython otherwise, see `the installation page `_. License: -------- The original Pyrex program was licensed "free of restrictions" (see below). Cython itself is licensed under the permissive **Apache License**. See `LICENSE.txt `_. Contributing: ------------- Want to contribute to the Cython project? Here is some `help to get you started `_. Differences to other Python compilers ------------------------------------- Started as a project in the early 2000s, Cython has outlived `most other attempts `_ at producing static compilers for the Python language. Similar projects that have a relevance today include: * `PyPy `_, a Python implementation with a JIT compiler. * Pros: JIT compilation with runtime optimisations, fully language compliant, good integration with external C/C++ code * Cons: non-CPython runtime, relatively large resource usage of the runtime, limited compatibility with CPython extensions, non-obvious performance results * `Numba `_, a Python extension that features a JIT compiler for a subset of the language, based on the LLVM compiler infrastructure (probably best known for its ``clang`` C compiler). It mostly targets numerical code that uses NumPy. * Pros: JIT compilation with runtime optimisations * Cons: limited language support, relatively large runtime dependency (LLVM), non-obvious performance results * `Pythran `_, a static Python-to-C++ extension compiler for a subset of the language, mostly targeted at numerical computation. Pythran can be (and is probably best) used as an additional `backend for NumPy code `_ in Cython. * `mypyc `_, a static Python-to-C extension compiler, based on the `mypy `_ static Python analyser. Like Cython's `pure Python mode `_, mypyc can make use of PEP-484 type annotations to optimise code for static types. * Pros: good support for language and PEP-484 typing, good type inference, reasonable performance gains * Cons: no support for low-level optimisations and typing, opinionated Python type interpretation, reduced Python compatibility and introspection after compilation * `Nuitka `_, a static Python-to-C extension compiler. * Pros: highly language compliant, reasonable performance gains, support for static application linking (similar to `cython_freeze `_ but with the ability to bundle library dependencies into a self-contained executable) * Cons: no support for low-level optimisations and typing In comparison to the above, Cython provides * fast, efficient and highly compliant support for almost all Python language features, including dynamic features and introspection * full runtime compatibility with all still-in-use and future versions of CPython * "generate once, compile everywhere" C code generation that allows for reproducible performance results and testing * C compile time adaptation to the target platform and Python version * support for other C-API implementations, including PyPy and Pyston * seamless integration with C/C++ code * broad support for manual optimisation and tuning down to the C level * a large user base with thousands of libraries, packages and tools * almost two decades of bug fixing and static code optimisations Get the full source history: ---------------------------- Note that Cython used to ship the full version control repository in its source distribution, but no longer does so due to space constraints. To get the full source history from a downloaded source archive, make sure you have git installed, then step into the base directory of the Cython source distribution and type:: make repo The following is from Pyrex: ------------------------------------------------------ This is a development version of Pyrex, a language for writing Python extension modules. For more info, take a look at: * Doc/About.html for a description of the language * INSTALL.txt for installation instructions * USAGE.txt for usage instructions * Demos for usage examples Comments, suggestions, bug reports, etc. are most welcome! Copyright stuff: Pyrex is free of restrictions. You may use, redistribute, modify and distribute modified versions. The latest version of Pyrex can be found `here `_. | Greg Ewing, Computer Science Dept | University of Canterbury | Christchurch, New Zealand A citizen of NewZealandCorp, a wholly-owned subsidiary of USA Inc. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/ToDo.txt0000644000175100001770000001616300000000000015211 0ustar00runnerdocker00000000000000See http://trac.cython.org/cython_trac and http://wiki.cython.org/enhancements -- The Original Pyrex Todo List -- DONE - Pointer-to-function types. DONE - Nested declarators. DONE - Varargs C func defs and calls. DONE - * and ** args in Python func defs. DONE - Default argument values. DONE - Tracebacks. DONE - Disallow creating char * from Python temporary anywhere (not just on assignment). DONE - Module and function and class doc strings. DONE - Predeclare C functions. DONE - Constant expressions. DONE - Forward C struct declarations. DONE - Prefix & operator. DONE - Get rid of auto string->char coercion and add a c'X' syntax for char literals. DONE - Cascaded assignments (a = b = c). DONE - 'include' statement for including other Pyrex files. DONE - Add command line option for specifying name of generated C file. DONE - Add 'else' clause to try-except. DONE - Allow extension types to be declared "public" so they can be accessed from another Pyrex module or a C file. DONE - Don't try to generate objstruct definition for external extension type declared without suite (treat as though declared with empty suite). DONE - Implement two-argument form of 'assert' statement. Const types. Tuple/list construction: Evaluate & store items one at a time? Varargs argument traversal. Use PyDict_SetItemString to build keyword arg dicts? (Or wait until names are interned.) Intern names. print >>file abs() and anything similar. Semicolon-separated statement lists. Optional semicolons after C declarations. Multiple C declarations on one line? Optimise return without value outside of try-finally. exec statement. from ... import statement. Use iterator protocol for unpacking. Save & restore exception being handled on function entry/exit. In-place operators (+=, etc). Constant declarations. Syntax? DONE - Some way for C functions to signal Python errors? Check for lack of return with value in non-void C functions? Allow 'pass' in struct/union/enum definition. Make C structs callable as constructors. DONE - Provide way of specifying C names. DONE - Public cdefs. When calling user __dealloc__ func, save & restore exception. DONE - Forward declaration of extension types. Complex number parsetuple format? DONE - long long type DONE - long double type? Windows __fooblarg function declaration things. Generate type, var and func declarations in the same order that they appear in the source file. Provide a way of declaring a C function as returning a borrowed Python reference. Provide a way of specifying whether a Python object obtained by casting a pointer should be treated as a new reference or not. Optimize integer for-loops. Make sizeof() take types as well as variables. Allow "unsigned" to be used alone as a type name. Allow duplicate declarations, at least in extern-from. Do something about installing proper version of pyrexc script according to platform in setup.py. DONE - Add "-o filename" command line option to unix/dos versions. Recognise #line directives? Catch floating point exceptions? Check that forward-declared non-external extension types are defined. Generate type test when casting from one Python type to another. Generate a Pyrex include file for public declarations as well as a C one. Syntax for defining indefinite-sized int & float types. Allow ranges of exception values. Support "complex double" and "complex float"? Allow module-level Python variables to be declared extern. Consider: >cdef extern from "foo.h": > int dosomething() except -1 raise MyException Properties for Python types. DONE - Properties for extension types. Find a way to make classmethod and staticmethod work better. DONE - Document workarounds for classmethod and staticmethod. Statically initialised C arrays & structs. Reduce generation of unused vars and unreachable code? Support for acquiring and releasing GIL. Make docstrings of extension type special methods work. Treat result of getting C attribute of extension type as non-ephemeral. Make None a reserved identifier. Teach it about builtin functions that correspond to Python/C API calls. Teach it about common builtin types. Option for generating a main() function? DONE - Allow an extension type to inherit from another type. Do something about external C functions declared as returning const * types? Use PyString_FromStringAndSize for string literals? DONE - C functions as methods of extension types. What to do about __name__ etc. attributes of a module (they are currently assumed to be built-in names). Use PyDict_GetItem etc. on module & builtins dicts for speed. Intern all string literals used as Python strings? [Koshy ] Make extension types weak-referenceable. [Matthias Baas ] Make 'pass' work in the body of an extern-from struct or union. Disallow a filename which results in an illegal identifier when used as a module name. Use ctypedef names. Provide an easy way of exposing a set of enum values as Python names. [John J Lee ] Prevent user from returning a value from special methods that return an error indicator only. Use PyObject_TypeCheck instead of PyObject_IsInstance? Allow * in cimport? [John J Lee ] FAQ: Q. Pyrex says my extension type object has no attribute 'rhubarb', but I know it does. A. Have you declared the type at the point where you're using it? Eliminate lvalue casts! (Illegal in C++, also disallowed by some C compilers) [Matthias Baas ] Make Python class construction work more like it does in Python. Give the right module name to Python classes. Command line switch for full pathnames in backtraces? Use PyString_FromStringAndSize on string literals containing nulls. Peephole optimisation? [Vladislav Bulatov ] Avoid PyArg_ParseTuple call when a function takes no positional args. Omit incref/decref of arguments that are not assigned to? Can a faster way of instantiating extension types be found? Disallow declaring a special method of an extension type with 'cdef' instead of 'def'. Use PySequence_GetItem instead of PyObject_GetItem when index is an integer. If a __getitem__ method is declared with an int index, use the sq_item slot instead of the mp_subscript slot. Provide some way of controlling the argument list passed to an extension type's base __new__ method? [Alain Pointdexter ] Rename __new__ in extension types to __alloc__. Implement a true __new__ for extension types. Way to provide constructors for extension types that are not available to Python and can accept C types directly? Support generators by turning them into extension types? List comprehensions. Variable declarations inside inner code blocks? Initial values when declaring variables? Do something about __stdcall. Support class methods in extension types using METH_CLASS flag. Disallow defaulting types to 'object' in C declarations? C globals with static initialisers. Find a way of providing C-only initialisers for extension types. Metaclasses for extension types? Make extension types use Py_TPFLAGS_HEAPTYPE so their __module__ will get set dynamically? ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.024724 Cython-3.0.8/Tools/0000755000175100001770000000000000000000000014674 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Tools/BUILD.bazel0000644000175100001770000000000100000000000016541 0ustar00runnerdocker00000000000000 ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Tools/cevaltrace.py0000644000175100001770000001153000000000000017357 0ustar00runnerdocker00000000000000#!/usr/bin/env python3 """ Translate the byte code of a Python function into the corresponding sequences of C code in CPython's "ceval.c". """ from __future__ import print_function, absolute_import import re import os.path from dis import get_instructions # requires Python 3.4+ # collapse some really boring byte codes _COLLAPSE = {'NOP', 'LOAD_CONST', 'POP_TOP', 'JUMP_FORWARD'} #_COLLAPSE.clear() _is_start = re.compile(r"\s* switch \s* \( opcode \)", re.VERBOSE).match # Py3: TARGET(XX), Py2: case XX _match_target = re.compile(r"\s* (?: TARGET \s* \( | case \s* ) \s* (\w+) \s* [:)]", re.VERBOSE).match _ignored = re.compile(r"\s* PREDICTED[A-Z_]*\(", re.VERBOSE).match _is_end = re.compile(r"\s* } \s* /\* \s* switch \s* \*/", re.VERBOSE).match _find_pyversion = re.compile(r'\#define \s+ PY_VERSION \s+ "([^"]+)"', re.VERBOSE).findall class ParseError(Exception): def __init__(self, message="Failed to parse ceval.c"): super(ParseError, self).__init__(message) def parse_ceval(file_path): snippets = {} with open(file_path) as f: lines = iter(f) for line in lines: if _is_start(line): break else: raise ParseError() targets = [] code_lines = [] for line in lines: target_match = _match_target(line) if target_match: if code_lines: code = ''.join(code_lines).rstrip() for target in targets: snippets[target] = code del code_lines[:], targets[:] targets.append(target_match.group(1)) elif _ignored(line): pass elif _is_end(line): break else: code_lines.append(line) else: if not snippets: raise ParseError() return snippets def translate(func, ceval_snippets): start_offset = 0 code_obj = getattr(func, '__code__', None) if code_obj and os.path.exists(code_obj.co_filename): start_offset = code_obj.co_firstlineno with open(code_obj.co_filename) as f: code_line_at = { i: line.strip() for i, line in enumerate(f, 1) if line.strip() }.get else: code_line_at = lambda _: None for instr in get_instructions(func): code_line = code_line_at(instr.starts_line) line_no = (instr.starts_line or start_offset) - start_offset yield line_no, code_line, instr, ceval_snippets.get(instr.opname) def main(): import sys import importlib.util if len(sys.argv) < 3: print("Usage: %s path/to/Python/ceval.c script.py ..." % sys.argv[0], file=sys.stderr) return ceval_source_file = sys.argv[1] version_header = os.path.join(os.path.dirname(ceval_source_file), '..', 'Include', 'patchlevel.h') if os.path.exists(version_header): with open(version_header) as f: py_version = _find_pyversion(f.read()) if py_version: py_version = py_version[0] if not sys.version.startswith(py_version + ' '): print("Warning: disassembling with Python %s, but ceval.c has version %s" % ( sys.version.split(None, 1)[0], py_version, ), file=sys.stderr) snippets = parse_ceval(ceval_source_file) for code in _COLLAPSE: if code in snippets: snippets[code] = '' for file_path in sys.argv[2:]: module_name = os.path.basename(file_path) print("/*######## MODULE %s ########*/" % module_name) print('') spec = importlib.util.spec_from_file_location(module_name, file_path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) for func_name, item in sorted(vars(module).items()): if not callable(item): continue print("/* FUNCTION %s */" % func_name) print("static void") # assuming that it highlights in editors print("%s() {" % func_name) last_line = None for line_no, code_line, instr, snippet in translate(item, snippets): if last_line != line_no: if code_line: print('') print('/*# %3d %s */' % (line_no, code_line)) print('') last_line = line_no print(" %s:%s {%s" % ( instr.opname, ' /* %s */' % instr.argrepr if instr.arg is not None else '', ' /* ??? */' if snippet is None else ' /* ... */ }' if snippet == '' else '', )) print(snippet or '') print("} /* FUNCTION %s */" % func_name) if __name__ == '__main__': main() ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Tools/ci-run.sh0000644000175100001770000002021600000000000016426 0ustar00runnerdocker00000000000000#!/usr/bin/bash set -x GCC_VERSION=${GCC_VERSION:=8} # Set up compilers if [[ $TEST_CODE_STYLE == "1" ]]; then echo "Skipping compiler setup: Code style run" elif [[ $OSTYPE == "linux-gnu"* ]]; then echo "Setting up linux compiler" echo "Installing requirements [apt]" sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test" sudo apt update -y -q sudo apt install -y -q gdb python3-dbg gcc-$GCC_VERSION || exit 1 ALTERNATIVE_ARGS="" if [[ $BACKEND == *"cpp"* ]]; then sudo apt install -y -q g++-$GCC_VERSION || exit 1 ALTERNATIVE_ARGS="--slave /usr/bin/g++ g++ /usr/bin/g++-$GCC_VERSION" fi sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-$GCC_VERSION 60 $ALTERNATIVE_ARGS export CC="gcc" if [[ $BACKEND == *"cpp"* ]]; then sudo update-alternatives --set g++ /usr/bin/g++-$GCC_VERSION export CXX="g++" fi elif [[ $OSTYPE == "darwin"* ]]; then echo "Setting up macos compiler" export CC="clang -Wno-deprecated-declarations" export CXX="clang++ -stdlib=libc++ -Wno-deprecated-declarations" if [[ $PYTHON_VERSION == "3."[78]* ]]; then # see https://trac.macports.org/ticket/62757 unset MACOSX_DEPLOYMENT_TARGET fi else echo "Skipping compiler setup: No setup specified for $OSTYPE" fi if [[ $COVERAGE == "1" ]]; then echo "Skip setting up compilation caches" elif [[ $OSTYPE == "msys" ]]; then echo "Set up sccache" echo "TODO: Make a soft symlink to sccache" else echo "Set up ccache" echo "/usr/lib/ccache" >> $GITHUB_PATH # export ccache to path echo "Set up symlinks to ccache" cp ccache /usr/local/bin/ ln -s ccache /usr/local/bin/gcc ln -s ccache /usr/local/bin/g++ ln -s ccache /usr/local/bin/cc ln -s ccache /usr/local/bin/c++ ln -s ccache /usr/local/bin/clang ln -s ccache /usr/local/bin/clang++ fi # Set up miniconda if [[ $STACKLESS == "true" ]]; then echo "Installing stackless python" #conda install --quiet --yes nomkl --file=test-requirements.txt --file=test-requirements-cpython.txt conda config --add channels stackless conda install --quiet --yes stackless || exit 1 fi if [[ $PYTHON_VERSION == "2.7"* ]] && [[ $OSTYPE == "darwin"* ]]; then # make sure we find Python 2.7 before Python 3.x export PATH=/Library/Frameworks/Python.framework/Versions/2.7/bin:$PATH fi PYTHON_SYS_VERSION=$(python -c 'import sys; print(sys.version)') # Log versions in use echo "====================" echo "|VERSIONS INSTALLED|" echo "====================" echo "Python $PYTHON_SYS_VERSION" if [[ $CC ]]; then which ${CC%% *} ${CC%% *} --version fi if [[ $CXX ]]; then which ${CXX%% *} ${CXX%% *} --version fi echo "====================" # Install python requirements echo "Installing requirements [python]" if [[ $PYTHON_VERSION == "2.7"* ]]; then pip install "wheel<0.38" || exit 1 pip install -r test-requirements-27.txt || exit 1 elif [[ $PYTHON_VERSION == "3."[45]* ]]; then python -m pip install "wheel<0.38" || exit 1 python -m pip install -r test-requirements-34.txt || exit 1 elif [[ $PYTHON_VERSION == "3.6"* ]]; then python -m pip install "wheel<0.38" || exit 1 python -m pip install -r test-requirements-36.txt || exit 1 elif [[ $PYTHON_VERSION == "pypy-2.7" ]]; then pip install "wheel<0.38" || exit 1 pip install -r test-requirements-pypy27.txt || exit 1 elif [[ $PYTHON_VERSION == "3.1"[2-9]* ]]; then python -m pip install -U pip wheel setuptools || exit 1 if [[ $PYTHON_VERSION == "3.12"* ]]; then python -m pip install --pre -r test-requirements-312.txt || exit 1 fi else python -m pip install -U pip "setuptools<60" wheel || exit 1 if [[ $PYTHON_VERSION != *"-dev" || $COVERAGE == "1" ]]; then python -m pip install -r test-requirements.txt || exit 1 if [[ $PYTHON_VERSION != "pypy"* && $PYTHON_VERSION != "3."[1]* ]]; then python -m pip install -r test-requirements-cpython.txt || exit 1 fi fi fi if [[ $TEST_CODE_STYLE == "1" ]]; then STYLE_ARGS="--no-unit --no-doctest --no-file --no-pyregr --no-examples" python -m pip install -r doc-requirements.txt || exit 1 else STYLE_ARGS="--no-code-style" # Install more requirements if [[ $PYTHON_VERSION != *"-dev" ]]; then if [[ $BACKEND == *"cpp"* ]]; then echo "WARNING: Currently not installing pythran due to compatibility issues" # python -m pip install pythran==0.9.5 || exit 1 fi if [[ $BACKEND != "cpp" && $PYTHON_VERSION != "pypy"* && $PYTHON_VERSION != "2"* && $PYTHON_VERSION != "3.4"* ]]; then python -m pip install mypy || exit 1 fi fi fi # Run tests echo "==== Running tests ====" ccache -s 2>/dev/null || true export PATH="/usr/lib/ccache:$PATH" # Most modern compilers allow the last conflicting option # to override the previous ones, so '-O0 -O3' == '-O3' # This is true for the latest msvc, gcc and clang if [[ $OSTYPE == "msys" ]]; then # for MSVC cl # /wd disables warnings # 4711 warns that function `x` was selected for automatic inline expansion # 4127 warns that a conditional expression is constant, should be fixed here https://github.com/cython/cython/pull/4317 # (off by default) 5045 warns that the compiler will insert Spectre mitigations for memory load if the /Qspectre switch is specified # (off by default) 4820 warns about the code in Python\3.9.6\x64\include ... CFLAGS="-Od /Z7 /MP /W4 /wd4711 /wd4127 /wd5045 /wd4820" else CFLAGS="-O0 -ggdb -Wall -Wextra -Wcast-qual -Wconversion -Wdeprecated -Wunused-result" fi # Trying to cover debug assertions in the CI without adding # extra jobs. Therefore, odd-numbered minor versions of Python # running C++ jobs get NDEBUG undefined, and even-numbered # versions running C jobs get NDEBUG undefined. ODD_VERSION=$(python3 -c "import sys; print(sys.version_info[1]%2)") if [[ $BACKEND == *"cpp"* && $ODD_VERSION == "1" ]]; then CFLAGS="$CFLAGS -UNDEBUG" elif [[ $ODD_VERSION == "0" ]]; then CFLAGS="$CFLAGS -UNDEBUG" fi if [[ $NO_CYTHON_COMPILE != "1" && $PYTHON_VERSION != "pypy"* ]]; then BUILD_CFLAGS="$CFLAGS -O2" if [[ $CYTHON_COMPILE_ALL == "1" && $OSTYPE != "msys" ]]; then BUILD_CFLAGS="$CFLAGS -O3 -g0 -mtune=generic" # make wheel sizes comparable to standard wheel build fi if [[ $PYTHON_SYS_VERSION == "2"* ]]; then BUILD_CFLAGS="$BUILD_CFLAGS -fno-strict-aliasing" fi SETUP_ARGS="" if [[ $COVERAGE == "1" ]]; then SETUP_ARGS="$SETUP_ARGS --cython-coverage" fi if [[ $CYTHON_COMPILE_ALL == "1" ]]; then SETUP_ARGS="$SETUP_ARGS --cython-compile-all" fi # It looks like parallel build may be causing occasional link failures on Windows # "with exit code 1158". DW isn't completely sure of this, but has disabled it in # the hope it helps SETUP_ARGS="$SETUP_ARGS $(python -c 'import sys; print("-j5" if sys.version_info >= (3,5) and not sys.platform.startswith("win") else "")')" CFLAGS=$BUILD_CFLAGS \ python setup.py build_ext -i $SETUP_ARGS || exit 1 # COVERAGE can be either "" (empty or not set) or "1" (when we set it) # STACKLESS can be either "" (empty or not set) or "true" (when we set it) if [[ $COVERAGE != "1" && $STACKLESS != "true" && $BACKEND != *"cpp"* && $LIMITED_API == "" && $EXTRA_CFLAGS == "" ]]; then python setup.py bdist_wheel || exit 1 ls -l dist/ || true fi echo "Extension modules created during the build:" find Cython -name "*.so" -ls | sort -k11 fi if [[ $TEST_CODE_STYLE == "1" ]]; then make -C docs html || exit 1 elif [[ $PYTHON_VERSION != "pypy"* && $OSTYPE != "msys" ]]; then # Run the debugger tests in python-dbg if available # (but don't fail, because they currently do fail) PYTHON_DBG=$(python -c 'import sys; print("%d.%d" % sys.version_info[:2])') PYTHON_DBG="python$PYTHON_DBG-dbg" if $PYTHON_DBG -V >&2; then CFLAGS=$CFLAGS $PYTHON_DBG \ runtests.py -vv --no-code-style Debugger --backends=$BACKEND fi fi RUNTESTS_ARGS="" if [[ $COVERAGE == "1" ]]; then RUNTESTS_ARGS="$RUNTESTS_ARGS --coverage --coverage-html --cython-only" fi if [[ $TEST_CODE_STYLE != "1" ]]; then RUNTESTS_ARGS="$RUNTESTS_ARGS -j7" fi export CFLAGS="$CFLAGS $EXTRA_CFLAGS" python runtests.py \ -vv $STYLE_ARGS \ -x Debugger \ --backends=$BACKEND \ $LIMITED_API \ $EXCLUDE \ $RUNTESTS_ARGS EXIT_CODE=$? ccache -s -v -v 2>/dev/null || true exit $EXIT_CODE ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Tools/cystdlib.py0000644000175100001770000001260200000000000017064 0ustar00runnerdocker00000000000000""" Highly experimental script that compiles the CPython standard library using Cython. Execute the script either in the CPython 'Lib' directory or pass the option '--current-python' to compile the standard library of the running Python interpreter. Pass '-j N' to get a parallel build with N processes. Usage example:: $ python cystdlib.py --current-python build_ext -i """ import os import sys from distutils.core import setup from Cython.Build import cythonize from Cython.Compiler import Options # improve Python compatibility by allowing some broken code Options.error_on_unknown_names = False Options.error_on_uninitialized = False exclude_patterns = ['**/test/**/*.py', '**/tests/**/*.py', '**/__init__.py'] broken = [ 'idlelib/MultiCall.py', 'email/utils.py', 'multiprocessing/reduction.py', 'multiprocessing/util.py', 'threading.py', # interrupt handling 'lib2to3/fixes/fix_sys_exc.py', 'traceback.py', 'types.py', 'enum.py', 'keyword.py', '_collections_abc.py', 'importlib/_bootstrap', ] default_directives = dict( auto_cpdef=False, # enable when it's safe, see long list of failures below binding=True, set_initial_path='SOURCEFILE') default_directives['optimize.inline_defnode_calls'] = True special_directives = [ (['pkgutil.py', 'decimal.py', 'datetime.py', 'optparse.py', 'sndhdr.py', 'opcode.py', 'ntpath.py', 'urllib/request.py', 'plat-*/TYPES.py', 'plat-*/IN.py', 'tkinter/_fix.py', 'lib2to3/refactor.py', 'webbrowser.py', 'shutil.py', 'multiprocessing/forking.py', 'xml/sax/expatreader.py', 'xmlrpc/client.py', 'pydoc.py', 'xml/etree/ElementTree.py', 'posixpath.py', 'inspect.py', 'ctypes/util.py', 'urllib/parse.py', 'warnings.py', 'tempfile.py', 'trace.py', 'heapq.py', 'pickletools.py', 'multiprocessing/connection.py', 'hashlib.py', 'getopt.py', 'os.py', 'types.py', ], dict(auto_cpdef=False)), ] del special_directives[:] # currently unused def build_extensions(includes='**/*.py', excludes=None, special_directives=special_directives, language_level=sys.version_info[0], parallel=None): if isinstance(includes, str): includes = [includes] excludes = list(excludes or exclude_patterns) + broken all_groups = (special_directives or []) + [(includes, {})] extensions = [] for modules, directives in all_groups: exclude_now = excludes[:] for other_modules, _ in special_directives: if other_modules != modules: exclude_now.extend(other_modules) d = dict(default_directives) d.update(directives) extensions.extend( cythonize( modules, exclude=exclude_now, exclude_failures=True, language_level=language_level, compiler_directives=d, nthreads=parallel, )) return extensions def build(extensions): try: setup(ext_modules=extensions) result = True except: import traceback print('error building extensions %s' % ( [ext.name for ext in extensions],)) traceback.print_exc() result = False return extensions, result def _build(args): sys_args, ext = args sys.argv[1:] = sys_args return build([ext]) def parse_args(): from optparse import OptionParser parser = OptionParser('%prog [options] [LIB_DIR (default: ./Lib)]') parser.add_option( '--current-python', dest='current_python', action='store_true', help='compile the stdlib of the running Python') parser.add_option( '-j', '--jobs', dest='parallel_jobs', metavar='N', type=int, default=1, help='run builds in N parallel jobs (default: 1)') parser.add_option( '-x', '--exclude', dest='excludes', metavar='PATTERN', action="append", help='exclude modules/packages matching PATTERN') options, args = parser.parse_args() if not args: args = ['./Lib'] elif len(args) > 1: parser.error('only one argument expected, got %d' % len(args)) return options, args if __name__ == '__main__': options, args = parse_args() if options.current_python: # assume that the stdlib is where the "os" module lives os.chdir(os.path.dirname(os.__file__)) else: os.chdir(args[0]) pool = None parallel_jobs = options.parallel_jobs if options.parallel_jobs: try: import multiprocessing pool = multiprocessing.Pool(parallel_jobs) print("Building in %d parallel processes" % parallel_jobs) except (ImportError, OSError): print("Not building in parallel") parallel_jobs = 0 extensions = build_extensions( parallel=parallel_jobs, excludes=options.excludes) sys_args = ['build_ext', '-i'] if pool is not None: results = pool.map(_build, [(sys_args, ext) for ext in extensions]) pool.close() pool.join() for ext, result in results: if not result: print("building extension %s failed" % (ext[0].name,)) else: sys.argv[1:] = sys_args build(extensions) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Tools/cython-epydoc.py0000644000175100001770000000263400000000000020040 0ustar00runnerdocker00000000000000#! /usr/bin/env python # -------------------------------------------------------------------- import re from epydoc import docstringparser as dsp CYTHON_SIGNATURE_RE = re.compile( # Class name (for builtin methods) r'^\s*((?P\w+)\.)?' + # The function name r'(?P\w+)' + # The parameters r'\(((?P(?:self|cls|mcs)),?)?(?P.*)\)' + # The return value (optional) r'(\s*(->)\s*(?P\w+(?:\s*\w+)))?' + # The end marker r'\s*(?:\n|$)') parse_signature = dsp.parse_function_signature def parse_function_signature(func_doc, doc_source, docformat, parse_errors): PYTHON_SIGNATURE_RE = dsp._SIGNATURE_RE assert PYTHON_SIGNATURE_RE is not CYTHON_SIGNATURE_RE try: dsp._SIGNATURE_RE = CYTHON_SIGNATURE_RE found = parse_signature(func_doc, doc_source, docformat, parse_errors) dsp._SIGNATURE_RE = PYTHON_SIGNATURE_RE if not found: found = parse_signature(func_doc, doc_source, docformat, parse_errors) return found finally: dsp._SIGNATURE_RE = PYTHON_SIGNATURE_RE dsp.parse_function_signature = parse_function_signature # -------------------------------------------------------------------- from epydoc.cli import cli cli() # -------------------------------------------------------------------- ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Tools/cython-numpy-mode-kate.xml0000644000175100001770000012774100000000000021750 0ustar00runnerdocker00000000000000 as cimport import from as DEF IF ELIF ELSE include class cpdef def cdef ctypedef extern api del global property nogil gil inline readonly public and assert in is by not or sizeof print break continue elif else except finally for if pass raise return try while with __import__ abs all any apply basestring buffer callable chr classmethod cmp coerce compile delattr dir divmod enumerate eval execfile filter getattr hasattr hash hex id input intern isinstance issubclass iter len map max min oct open ord pow range raw_input reduce reload repr reversed round setattr sorted staticmethod sum super type unichr unicode xrange zip unsigned void enum double long short char Py_ssize_t Py_intptr_t Py_buffer bint struct union enum int float object list tuple str dict set frozenset slice bool complex file np numpy numpy cython dtype flatiter broadcast ndarray int8_t int16_t int32_t int64_t uint8_t uint16_t uint32_t uint64_t float32_t float64_t complex64_t complex128_t int_t long_t uint_t ulong_t float_t double_t longdouble_t cfloat_t cdouble_t clongdouble_t complex_t npy_int8 npy_int16 npy_int32 npy_int64 npy_int96 npy_int128 npy_uint8 npy_uint16 npy_uint32 npy_uint64 npy_uint96 npy_uint128 npy_float32 npy_float64 npy_float80 npy_float96 npy_float128 npy_complex64 npy_complex128 npy_complex120 npy_complex192 npy_complex256 npy_cfloat npy_cdouble npy_clongdouble npy_bool npy_byte npy_short npy_int npy_long npy_longlong npy_ubyte npy_ushort npy_uint npy_ulong npy_ulonglong npy_float npy_double npy_longdouble npy_intp DataSource MachAr PackageLoader RankWarning Tester abs absolute add add_docstring add_newdoc alen all allclose alltrue alterdot amax amin angle any append apply_along_axis apply_over_axes arange arccos arccosh arcsin arcsinh arctan arctan2 arctanh argmax argmin argsort argwhere around array array2string array_equal array_equiv array_repr array_split array_str asanyarray asarray asarray_chkfinite ascontiguousarray asfarray asfortranarray asmatrix asscalar atleast_1d atleast_2d atleast_3d average bartlett base_repr bench binary_repr bincount bitwise_and bitwise_not bitwise_or bitwise_xor blackman bmat bool bool8 bool_ broadcast broadcast_arrays byte byte_bounds can_cast cdouble ceil cfloat character chararray choose clip clongdouble clongfloat column_stack common_type compare_chararrays complex complex128 complex192 complex64 complex_ complexfloating compress concatenate conj conjugate convolve copy corrcoef correlate cos cosh cov cross csingle cumprod cumproduct cumsum deg2rad degrees delete deprecate deprecate_with_doc diag diagflat diagonal diff digitize disp divide dot double dsplit dstack dtype ediff1d empty empty_like equal errstate exp exp2 expand_dims expm1 extract eye fabs fastCopyAndTranspose find_common_type finfo fix flatiter flatnonzero flexible fliplr flipud float float32 float64 float96 float_ floating floor floor_divide fmax fmin fmod frexp frombuffer fromfile fromfunction fromiter frompyfunc fromregex fromstring fv generic genfromtxt get_array_wrap get_include get_numarray_include get_numpy_include get_printoptions getbuffer getbufsize geterr geterrcall geterrobj gradient greater greater_equal hamming hanning histogram histogram2d histogramdd hsplit hstack hypot i0 identity imag indices inexact info inner insert int int0 int16 int32 int64 int8 int_ int_asbuffer intc integer interp intersect1d intersect1d_nu intp invert ipmt irr iscomplex iscomplexobj isfinite isfortran isinf isnan isneginf isposinf isreal isrealobj isscalar issctype issubclass_ issubdtype issubsctype iterable ix_ kaiser kron ldexp left_shift less less_equal lexsort linspace load loads loadtxt log log10 log1p log2 logaddexp logaddexp2 logical_and logical_not logical_or logical_xor logspace long longcomplex longdouble longfloat longlong lookfor mafromtxt mat matrix max maximum maximum_sctype may_share_memory mean median memmap meshgrid min minimum mintypecode mirr mod modf msort multiply nan_to_num nanargmax nanargmin nanmax nanmin nansum ndarray ndenumerate ndfromtxt ndim ndindex negative newbuffer nonzero not_equal nper npv number obj2sctype object object0 object_ ones ones_like outer packbits piecewise pkgload place pmt poly poly1d polyadd polyder polydiv polyfit polyint polymul polysub polyval power ppmt prod product ptp put putmask pv rad2deg radians rank rate ravel real real_if_close recarray recfromcsv recfromtxt reciprocal record remainder repeat require reshape resize restoredot right_shift rint roll rollaxis roots rot90 round round_ row_stack safe_eval save savetxt savez sctype2char searchsorted select set_numeric_ops set_printoptions set_string_function setbufsize setdiff1d seterr seterrcall seterrobj setmember1d setxor1d shape short show_config sign signbit signedinteger sin sinc single singlecomplex sinh size sometrue sort sort_complex source split sqrt square squeeze std str str_ string0 string_ subtract sum swapaxes take tan tanh tensordot test tile trace transpose trapz tri tril trim_zeros triu true_divide trunc typename ubyte ufunc uint uint0 uint16 uint32 uint64 uint8 uintc uintp ulonglong unicode unicode0 unicode_ union1d unique unique1d unpackbits unravel_index unsignedinteger unwrap ushort vander var vdot vectorize void void0 vsplit vstack where who zeros zeros_like __future__ __import__ __name__ __cythonbufferdefaults__ __weakref__ None self True False NotImplemented Ellipsis NULL __new__ __init__ __cinit__ __dealloc__ __cmp__ __richcmp__ __str__ __repr__ __hash__ __call__ __iter__ __getattr__ __setattr__ __delattr__ __add__ __sub__ __mul__ __div__ __floordiv__ __truediv__ __mod__ __divmod__ __pow__ __neg__ __pos__ __abs__ __nonzero__ __invert__ __lshift__ __rshift__ __and__ __or__ __xor__ __int__ __long__ __float__ __oct__ __hex__ __index__ __iadd__ __isub__ __imul__ __idiv__ __ifloordiv__ __itruediv__ __imod__ __ipow__ __ilshift__ __irshift__ __iand__ __ior__ __ixor__ __len__ __getitem__ __setitem__ __delitem__ __getslice__ __setslice__ __delslice__ __contains__ __next__ __getreadbuffer__ __getwritebuffer__ __getsegcount__ __getcharbuffer__ __get__ __set__ __delete__ __getbuffer__ __releasebuffer__ ArithmeticError AssertionError AttributeError BaseException DeprecationWarning EnvironmentError EOFError Exception FloatingPointError FutureWarning GeneratorExit IOError ImportError ImportWarning IndexError KeyError KeyboardInterrupt LookupError MemoryError NameError NotImplementedError OSError OverflowError PendingDeprecationWarning ReferenceError RuntimeError RuntimeWarning StandardError StopIteration SyntaxError SyntaxWarning SystemError SystemExit TypeError UnboundLocalError UserWarning UnicodeError UnicodeWarning UnicodeEncodeError UnicodeDecodeError UnicodeTranslateError ValueError Warning WindowsError ZeroDivisionError ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.340722 Cython-3.0.8/Tools/cython.st0000644000175100001770000000115200000000000016547 0ustar00runnerdocker00000000000000/** * Name: pyrex * Description: Pyrex - a Language for Writing Python Extension Modules * Author: Markku Rossi */ state pyrex extends python { /* Additional keywords. (build-re '( NULL as cdef char ctypedef double enum extern float include int long private public short signed sizeof struct union unsigned void )) */ /\b(NULL|as|c(def|har|typedef)|double|e(num|xtern)|float|in(clude|t)\ |long|p(rivate|ublic)|s(hort|i(gned|zeof)|truct)|un(ion|signed)|void)\b/ { keyword_face(true); language_print($0); keyword_face(false); } } /* Local variables: mode: c End: */ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.024724 Cython-3.0.8/Tools/dataclass_test_data/0000755000175100001770000000000000000000000020663 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/Tools/dataclass_test_data/test_dataclasses.py0000644000175100001770000041177700000000000024604 0ustar00runnerdocker00000000000000# Deliberately use "from dataclasses import *". Every name in __all__ # is tested, so they all must be present. This is a way to catch # missing ones. from dataclasses import * import abc import pickle import inspect import builtins import types import weakref import unittest from unittest.mock import Mock from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional, Protocol from typing import get_type_hints from collections import deque, OrderedDict, namedtuple from functools import total_ordering import typing # Needed for the string "typing.ClassVar[int]" to work as an annotation. import dataclasses # Needed for the string "dataclasses.InitVar[int]" to work as an annotation. # Just any custom exception we can catch. class CustomError(Exception): pass class TestCase(unittest.TestCase): def test_no_fields(self): @dataclass class C: pass o = C() self.assertEqual(len(fields(C)), 0) def test_no_fields_but_member_variable(self): @dataclass class C: i = 0 o = C() self.assertEqual(len(fields(C)), 0) def test_one_field_no_default(self): @dataclass class C: x: int o = C(42) self.assertEqual(o.x, 42) def test_field_default_default_factory_error(self): msg = "cannot specify both default and default_factory" with self.assertRaisesRegex(ValueError, msg): @dataclass class C: x: int = field(default=1, default_factory=int) def test_field_repr(self): int_field = field(default=1, init=True, repr=False) int_field.name = "id" repr_output = repr(int_field) expected_output = "Field(name='id',type=None," \ f"default=1,default_factory={MISSING!r}," \ "init=True,repr=False,hash=None," \ "compare=True,metadata=mappingproxy({})," \ f"kw_only={MISSING!r}," \ "_field_type=None)" self.assertEqual(repr_output, expected_output) def test_named_init_params(self): @dataclass class C: x: int o = C(x=32) self.assertEqual(o.x, 32) def test_two_fields_one_default(self): @dataclass class C: x: int y: int = 0 o = C(3) self.assertEqual((o.x, o.y), (3, 0)) # Non-defaults following defaults. with self.assertRaisesRegex(TypeError, "non-default argument 'y' follows " "default argument"): @dataclass class C: x: int = 0 y: int # A derived class adds a non-default field after a default one. with self.assertRaisesRegex(TypeError, "non-default argument 'y' follows " "default argument"): @dataclass class B: x: int = 0 @dataclass class C(B): y: int # Override a base class field and add a default to # a field which didn't use to have a default. with self.assertRaisesRegex(TypeError, "non-default argument 'y' follows " "default argument"): @dataclass class B: x: int y: int @dataclass class C(B): x: int = 0 def test_overwrite_hash(self): # Test that declaring this class isn't an error. It should # use the user-provided __hash__. @dataclass(frozen=True) class C: x: int def __hash__(self): return 301 self.assertEqual(hash(C(100)), 301) # Test that declaring this class isn't an error. It should # use the generated __hash__. @dataclass(frozen=True) class C: x: int def __eq__(self, other): return False self.assertEqual(hash(C(100)), hash((100,))) # But this one should generate an exception, because with # unsafe_hash=True, it's an error to have a __hash__ defined. with self.assertRaisesRegex(TypeError, 'Cannot overwrite attribute __hash__'): @dataclass(unsafe_hash=True) class C: def __hash__(self): pass # Creating this class should not generate an exception, # because even though __hash__ exists before @dataclass is # called, (due to __eq__ being defined), since it's None # that's okay. @dataclass(unsafe_hash=True) class C: x: int def __eq__(self): pass # The generated hash function works as we'd expect. self.assertEqual(hash(C(10)), hash((10,))) # Creating this class should generate an exception, because # __hash__ exists and is not None, which it would be if it # had been auto-generated due to __eq__ being defined. with self.assertRaisesRegex(TypeError, 'Cannot overwrite attribute __hash__'): @dataclass(unsafe_hash=True) class C: x: int def __eq__(self): pass def __hash__(self): pass def test_overwrite_fields_in_derived_class(self): # Note that x from C1 replaces x in Base, but the order remains # the same as defined in Base. @dataclass class Base: x: Any = 15.0 y: int = 0 @dataclass class C1(Base): z: int = 10 x: int = 15 o = Base() self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class..Base(x=15.0, y=0)') o = C1() self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class..C1(x=15, y=0, z=10)') o = C1(x=5) self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class..C1(x=5, y=0, z=10)') def test_field_named_self(self): @dataclass class C: self: str c=C('foo') self.assertEqual(c.self, 'foo') # Make sure the first parameter is not named 'self'. sig = inspect.signature(C.__init__) first = next(iter(sig.parameters)) self.assertNotEqual('self', first) # But we do use 'self' if no field named self. @dataclass class C: selfx: str # Make sure the first parameter is named 'self'. sig = inspect.signature(C.__init__) first = next(iter(sig.parameters)) self.assertEqual('self', first) def test_field_named_object(self): @dataclass class C: object: str c = C('foo') self.assertEqual(c.object, 'foo') def test_field_named_object_frozen(self): @dataclass(frozen=True) class C: object: str c = C('foo') self.assertEqual(c.object, 'foo') def test_field_named_like_builtin(self): # Attribute names can shadow built-in names # since code generation is used. # Ensure that this is not happening. exclusions = {'None', 'True', 'False'} builtins_names = sorted( b for b in builtins.__dict__.keys() if not b.startswith('__') and b not in exclusions ) attributes = [(name, str) for name in builtins_names] C = make_dataclass('C', attributes) c = C(*[name for name in builtins_names]) for name in builtins_names: self.assertEqual(getattr(c, name), name) def test_field_named_like_builtin_frozen(self): # Attribute names can shadow built-in names # since code generation is used. # Ensure that this is not happening # for frozen data classes. exclusions = {'None', 'True', 'False'} builtins_names = sorted( b for b in builtins.__dict__.keys() if not b.startswith('__') and b not in exclusions ) attributes = [(name, str) for name in builtins_names] C = make_dataclass('C', attributes, frozen=True) c = C(*[name for name in builtins_names]) for name in builtins_names: self.assertEqual(getattr(c, name), name) def test_0_field_compare(self): # Ensure that order=False is the default. @dataclass class C0: pass @dataclass(order=False) class C1: pass for cls in [C0, C1]: with self.subTest(cls=cls): self.assertEqual(cls(), cls()) for idx, fn in enumerate([lambda a, b: a < b, lambda a, b: a <= b, lambda a, b: a > b, lambda a, b: a >= b]): with self.subTest(idx=idx): with self.assertRaisesRegex(TypeError, f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"): fn(cls(), cls()) @dataclass(order=True) class C: pass self.assertLessEqual(C(), C()) self.assertGreaterEqual(C(), C()) def test_1_field_compare(self): # Ensure that order=False is the default. @dataclass class C0: x: int @dataclass(order=False) class C1: x: int for cls in [C0, C1]: with self.subTest(cls=cls): self.assertEqual(cls(1), cls(1)) self.assertNotEqual(cls(0), cls(1)) for idx, fn in enumerate([lambda a, b: a < b, lambda a, b: a <= b, lambda a, b: a > b, lambda a, b: a >= b]): with self.subTest(idx=idx): with self.assertRaisesRegex(TypeError, f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"): fn(cls(0), cls(0)) @dataclass(order=True) class C: x: int self.assertLess(C(0), C(1)) self.assertLessEqual(C(0), C(1)) self.assertLessEqual(C(1), C(1)) self.assertGreater(C(1), C(0)) self.assertGreaterEqual(C(1), C(0)) self.assertGreaterEqual(C(1), C(1)) def test_simple_compare(self): # Ensure that order=False is the default. @dataclass class C0: x: int y: int @dataclass(order=False) class C1: x: int y: int for cls in [C0, C1]: with self.subTest(cls=cls): self.assertEqual(cls(0, 0), cls(0, 0)) self.assertEqual(cls(1, 2), cls(1, 2)) self.assertNotEqual(cls(1, 0), cls(0, 0)) self.assertNotEqual(cls(1, 0), cls(1, 1)) for idx, fn in enumerate([lambda a, b: a < b, lambda a, b: a <= b, lambda a, b: a > b, lambda a, b: a >= b]): with self.subTest(idx=idx): with self.assertRaisesRegex(TypeError, f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"): fn(cls(0, 0), cls(0, 0)) @dataclass(order=True) class C: x: int y: int for idx, fn in enumerate([lambda a, b: a == b, lambda a, b: a <= b, lambda a, b: a >= b]): with self.subTest(idx=idx): self.assertTrue(fn(C(0, 0), C(0, 0))) for idx, fn in enumerate([lambda a, b: a < b, lambda a, b: a <= b, lambda a, b: a != b]): with self.subTest(idx=idx): self.assertTrue(fn(C(0, 0), C(0, 1))) self.assertTrue(fn(C(0, 1), C(1, 0))) self.assertTrue(fn(C(1, 0), C(1, 1))) for idx, fn in enumerate([lambda a, b: a > b, lambda a, b: a >= b, lambda a, b: a != b]): with self.subTest(idx=idx): self.assertTrue(fn(C(0, 1), C(0, 0))) self.assertTrue(fn(C(1, 0), C(0, 1))) self.assertTrue(fn(C(1, 1), C(1, 0))) def test_compare_subclasses(self): # Comparisons fail for subclasses, even if no fields # are added. @dataclass class B: i: int @dataclass class C(B): pass for idx, (fn, expected) in enumerate([(lambda a, b: a == b, False), (lambda a, b: a != b, True)]): with self.subTest(idx=idx): self.assertEqual(fn(B(0), C(0)), expected) for idx, fn in enumerate([lambda a, b: a < b, lambda a, b: a <= b, lambda a, b: a > b, lambda a, b: a >= b]): with self.subTest(idx=idx): with self.assertRaisesRegex(TypeError, "not supported between instances of 'B' and 'C'"): fn(B(0), C(0)) def test_eq_order(self): # Test combining eq and order. for (eq, order, result ) in [ (False, False, 'neither'), (False, True, 'exception'), (True, False, 'eq_only'), (True, True, 'both'), ]: with self.subTest(eq=eq, order=order): if result == 'exception': with self.assertRaisesRegex(ValueError, 'eq must be true if order is true'): @dataclass(eq=eq, order=order) class C: pass else: @dataclass(eq=eq, order=order) class C: pass if result == 'neither': self.assertNotIn('__eq__', C.__dict__) self.assertNotIn('__lt__', C.__dict__) self.assertNotIn('__le__', C.__dict__) self.assertNotIn('__gt__', C.__dict__) self.assertNotIn('__ge__', C.__dict__) elif result == 'both': self.assertIn('__eq__', C.__dict__) self.assertIn('__lt__', C.__dict__) self.assertIn('__le__', C.__dict__) self.assertIn('__gt__', C.__dict__) self.assertIn('__ge__', C.__dict__) elif result == 'eq_only': self.assertIn('__eq__', C.__dict__) self.assertNotIn('__lt__', C.__dict__) self.assertNotIn('__le__', C.__dict__) self.assertNotIn('__gt__', C.__dict__) self.assertNotIn('__ge__', C.__dict__) else: assert False, f'unknown result {result!r}' def test_field_no_default(self): @dataclass class C: x: int = field() self.assertEqual(C(5).x, 5) with self.assertRaisesRegex(TypeError, r"__init__\(\) missing 1 required " "positional argument: 'x'"): C() def test_field_default(self): default = object() @dataclass class C: x: object = field(default=default) self.assertIs(C.x, default) c = C(10) self.assertEqual(c.x, 10) # If we delete the instance attribute, we should then see the # class attribute. del c.x self.assertIs(c.x, default) self.assertIs(C().x, default) def test_not_in_repr(self): @dataclass class C: x: int = field(repr=False) with self.assertRaises(TypeError): C() c = C(10) self.assertEqual(repr(c), 'TestCase.test_not_in_repr..C()') @dataclass class C: x: int = field(repr=False) y: int c = C(10, 20) self.assertEqual(repr(c), 'TestCase.test_not_in_repr..C(y=20)') def test_not_in_compare(self): @dataclass class C: x: int = 0 y: int = field(compare=False, default=4) self.assertEqual(C(), C(0, 20)) self.assertEqual(C(1, 10), C(1, 20)) self.assertNotEqual(C(3), C(4, 10)) self.assertNotEqual(C(3, 10), C(4, 10)) def test_no_unhashable_default(self): # See bpo-44674. class Unhashable: __hash__ = None unhashable_re = 'mutable default .* for field a is not allowed' with self.assertRaisesRegex(ValueError, unhashable_re): @dataclass class A: a: dict = {} with self.assertRaisesRegex(ValueError, unhashable_re): @dataclass class A: a: Any = Unhashable() # Make sure that the machinery looking for hashability is using the # class's __hash__, not the instance's __hash__. with self.assertRaisesRegex(ValueError, unhashable_re): unhashable = Unhashable() # This shouldn't make the variable hashable. unhashable.__hash__ = lambda: 0 @dataclass class A: a: Any = unhashable def test_hash_field_rules(self): # Test all 6 cases of: # hash=True/False/None # compare=True/False for (hash_, compare, result ) in [ (True, False, 'field' ), (True, True, 'field' ), (False, False, 'absent'), (False, True, 'absent'), (None, False, 'absent'), (None, True, 'field' ), ]: with self.subTest(hash=hash_, compare=compare): @dataclass(unsafe_hash=True) class C: x: int = field(compare=compare, hash=hash_, default=5) if result == 'field': # __hash__ contains the field. self.assertEqual(hash(C(5)), hash((5,))) elif result == 'absent': # The field is not present in the hash. self.assertEqual(hash(C(5)), hash(())) else: assert False, f'unknown result {result!r}' def test_init_false_no_default(self): # If init=False and no default value, then the field won't be # present in the instance. @dataclass class C: x: int = field(init=False) self.assertNotIn('x', C().__dict__) @dataclass class C: x: int y: int = 0 z: int = field(init=False) t: int = 10 self.assertNotIn('z', C(0).__dict__) self.assertEqual(vars(C(5)), {'t': 10, 'x': 5, 'y': 0}) def test_class_marker(self): @dataclass class C: x: int y: str = field(init=False, default=None) z: str = field(repr=False) the_fields = fields(C) # the_fields is a tuple of 3 items, each value # is in __annotations__. self.assertIsInstance(the_fields, tuple) for f in the_fields: self.assertIs(type(f), Field) self.assertIn(f.name, C.__annotations__) self.assertEqual(len(the_fields), 3) self.assertEqual(the_fields[0].name, 'x') self.assertEqual(the_fields[0].type, int) self.assertFalse(hasattr(C, 'x')) self.assertTrue (the_fields[0].init) self.assertTrue (the_fields[0].repr) self.assertEqual(the_fields[1].name, 'y') self.assertEqual(the_fields[1].type, str) self.assertIsNone(getattr(C, 'y')) self.assertFalse(the_fields[1].init) self.assertTrue (the_fields[1].repr) self.assertEqual(the_fields[2].name, 'z') self.assertEqual(the_fields[2].type, str) self.assertFalse(hasattr(C, 'z')) self.assertTrue (the_fields[2].init) self.assertFalse(the_fields[2].repr) def test_field_order(self): @dataclass class B: a: str = 'B:a' b: str = 'B:b' c: str = 'B:c' @dataclass class C(B): b: str = 'C:b' self.assertEqual([(f.name, f.default) for f in fields(C)], [('a', 'B:a'), ('b', 'C:b'), ('c', 'B:c')]) @dataclass class D(B): c: str = 'D:c' self.assertEqual([(f.name, f.default) for f in fields(D)], [('a', 'B:a'), ('b', 'B:b'), ('c', 'D:c')]) @dataclass class E(D): a: str = 'E:a' d: str = 'E:d' self.assertEqual([(f.name, f.default) for f in fields(E)], [('a', 'E:a'), ('b', 'B:b'), ('c', 'D:c'), ('d', 'E:d')]) def test_class_attrs(self): # We only have a class attribute if a default value is # specified, either directly or via a field with a default. default = object() @dataclass class C: x: int y: int = field(repr=False) z: object = default t: int = field(default=100) self.assertFalse(hasattr(C, 'x')) self.assertFalse(hasattr(C, 'y')) self.assertIs (C.z, default) self.assertEqual(C.t, 100) def test_disallowed_mutable_defaults(self): # For the known types, don't allow mutable default values. for typ, empty, non_empty in [(list, [], [1]), (dict, {}, {0:1}), (set, set(), set([1])), ]: with self.subTest(typ=typ): # Can't use a zero-length value. with self.assertRaisesRegex(ValueError, f'mutable default {typ} for field ' 'x is not allowed'): @dataclass class Point: x: typ = empty # Nor a non-zero-length value with self.assertRaisesRegex(ValueError, f'mutable default {typ} for field ' 'y is not allowed'): @dataclass class Point: y: typ = non_empty # Check subtypes also fail. class Subclass(typ): pass with self.assertRaisesRegex(ValueError, f"mutable default .*Subclass'>" ' for field z is not allowed' ): @dataclass class Point: z: typ = Subclass() # Because this is a ClassVar, it can be mutable. @dataclass class C: z: ClassVar[typ] = typ() # Because this is a ClassVar, it can be mutable. @dataclass class C: x: ClassVar[typ] = Subclass() def test_deliberately_mutable_defaults(self): # If a mutable default isn't in the known list of # (list, dict, set), then it's okay. class Mutable: def __init__(self): self.l = [] @dataclass class C: x: Mutable # These 2 instances will share this value of x. lst = Mutable() o1 = C(lst) o2 = C(lst) self.assertEqual(o1, o2) o1.x.l.extend([1, 2]) self.assertEqual(o1, o2) self.assertEqual(o1.x.l, [1, 2]) self.assertIs(o1.x, o2.x) def test_no_options(self): # Call with dataclass(). @dataclass() class C: x: int self.assertEqual(C(42).x, 42) def test_not_tuple(self): # Make sure we can't be compared to a tuple. @dataclass class Point: x: int y: int self.assertNotEqual(Point(1, 2), (1, 2)) # And that we can't compare to another unrelated dataclass. @dataclass class C: x: int y: int self.assertNotEqual(Point(1, 3), C(1, 3)) def test_not_other_dataclass(self): # Test that some of the problems with namedtuple don't happen # here. @dataclass class Point3D: x: int y: int z: int @dataclass class Date: year: int month: int day: int self.assertNotEqual(Point3D(2017, 6, 3), Date(2017, 6, 3)) self.assertNotEqual(Point3D(1, 2, 3), (1, 2, 3)) # Make sure we can't unpack. with self.assertRaisesRegex(TypeError, 'unpack'): x, y, z = Point3D(4, 5, 6) # Make sure another class with the same field names isn't # equal. @dataclass class Point3Dv1: x: int = 0 y: int = 0 z: int = 0 self.assertNotEqual(Point3D(0, 0, 0), Point3Dv1()) def test_function_annotations(self): # Some dummy class and instance to use as a default. class F: pass f = F() def validate_class(cls): # First, check __annotations__, even though they're not # function annotations. self.assertEqual(cls.__annotations__['i'], int) self.assertEqual(cls.__annotations__['j'], str) self.assertEqual(cls.__annotations__['k'], F) self.assertEqual(cls.__annotations__['l'], float) self.assertEqual(cls.__annotations__['z'], complex) # Verify __init__. signature = inspect.signature(cls.__init__) # Check the return type, should be None. self.assertIs(signature.return_annotation, None) # Check each parameter. params = iter(signature.parameters.values()) param = next(params) # This is testing an internal name, and probably shouldn't be tested. self.assertEqual(param.name, 'self') param = next(params) self.assertEqual(param.name, 'i') self.assertIs (param.annotation, int) self.assertEqual(param.default, inspect.Parameter.empty) self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) param = next(params) self.assertEqual(param.name, 'j') self.assertIs (param.annotation, str) self.assertEqual(param.default, inspect.Parameter.empty) self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) param = next(params) self.assertEqual(param.name, 'k') self.assertIs (param.annotation, F) # Don't test for the default, since it's set to MISSING. self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) param = next(params) self.assertEqual(param.name, 'l') self.assertIs (param.annotation, float) # Don't test for the default, since it's set to MISSING. self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) self.assertRaises(StopIteration, next, params) @dataclass class C: i: int j: str k: F = f l: float=field(default=None) z: complex=field(default=3+4j, init=False) validate_class(C) # Now repeat with __hash__. @dataclass(frozen=True, unsafe_hash=True) class C: i: int j: str k: F = f l: float=field(default=None) z: complex=field(default=3+4j, init=False) validate_class(C) def test_missing_default(self): # Test that MISSING works the same as a default not being # specified. @dataclass class C: x: int=field(default=MISSING) with self.assertRaisesRegex(TypeError, r'__init__\(\) missing 1 required ' 'positional argument'): C() self.assertNotIn('x', C.__dict__) @dataclass class D: x: int with self.assertRaisesRegex(TypeError, r'__init__\(\) missing 1 required ' 'positional argument'): D() self.assertNotIn('x', D.__dict__) def test_missing_default_factory(self): # Test that MISSING works the same as a default factory not # being specified (which is really the same as a default not # being specified, too). @dataclass class C: x: int=field(default_factory=MISSING) with self.assertRaisesRegex(TypeError, r'__init__\(\) missing 1 required ' 'positional argument'): C() self.assertNotIn('x', C.__dict__) @dataclass class D: x: int=field(default=MISSING, default_factory=MISSING) with self.assertRaisesRegex(TypeError, r'__init__\(\) missing 1 required ' 'positional argument'): D() self.assertNotIn('x', D.__dict__) def test_missing_repr(self): self.assertIn('MISSING_TYPE object', repr(MISSING)) def test_dont_include_other_annotations(self): @dataclass class C: i: int def foo(self) -> int: return 4 @property def bar(self) -> int: return 5 self.assertEqual(list(C.__annotations__), ['i']) self.assertEqual(C(10).foo(), 4) self.assertEqual(C(10).bar, 5) self.assertEqual(C(10).i, 10) def test_post_init(self): # Just make sure it gets called @dataclass class C: def __post_init__(self): raise CustomError() with self.assertRaises(CustomError): C() @dataclass class C: i: int = 10 def __post_init__(self): if self.i == 10: raise CustomError() with self.assertRaises(CustomError): C() # post-init gets called, but doesn't raise. This is just # checking that self is used correctly. C(5) # If there's not an __init__, then post-init won't get called. @dataclass(init=False) class C: def __post_init__(self): raise CustomError() # Creating the class won't raise C() @dataclass class C: x: int = 0 def __post_init__(self): self.x *= 2 self.assertEqual(C().x, 0) self.assertEqual(C(2).x, 4) # Make sure that if we're frozen, post-init can't set # attributes. @dataclass(frozen=True) class C: x: int = 0 def __post_init__(self): self.x *= 2 with self.assertRaises(FrozenInstanceError): C() def test_post_init_super(self): # Make sure super() post-init isn't called by default. class B: def __post_init__(self): raise CustomError() @dataclass class C(B): def __post_init__(self): self.x = 5 self.assertEqual(C().x, 5) # Now call super(), and it will raise. @dataclass class C(B): def __post_init__(self): super().__post_init__() with self.assertRaises(CustomError): C() # Make sure post-init is called, even if not defined in our # class. @dataclass class C(B): pass with self.assertRaises(CustomError): C() def test_post_init_staticmethod(self): flag = False @dataclass class C: x: int y: int @staticmethod def __post_init__(): nonlocal flag flag = True self.assertFalse(flag) c = C(3, 4) self.assertEqual((c.x, c.y), (3, 4)) self.assertTrue(flag) def test_post_init_classmethod(self): @dataclass class C: flag = False x: int y: int @classmethod def __post_init__(cls): cls.flag = True self.assertFalse(C.flag) c = C(3, 4) self.assertEqual((c.x, c.y), (3, 4)) self.assertTrue(C.flag) def test_post_init_not_auto_added(self): # See bpo-46757, which had proposed always adding __post_init__. As # Raymond Hettinger pointed out, that would be a breaking change. So, # add a test to make sure that the current behavior doesn't change. @dataclass class A0: pass @dataclass class B0: b_called: bool = False def __post_init__(self): self.b_called = True @dataclass class C0(A0, B0): c_called: bool = False def __post_init__(self): super().__post_init__() self.c_called = True # Since A0 has no __post_init__, and one wasn't automatically added # (because that's the rule: it's never added by @dataclass, it's only # the class author that can add it), then B0.__post_init__ is called. # Verify that. c = C0() self.assertTrue(c.b_called) self.assertTrue(c.c_called) ###################################### # Now, the same thing, except A1 defines __post_init__. @dataclass class A1: def __post_init__(self): pass @dataclass class B1: b_called: bool = False def __post_init__(self): self.b_called = True @dataclass class C1(A1, B1): c_called: bool = False def __post_init__(self): super().__post_init__() self.c_called = True # This time, B1.__post_init__ isn't being called. This mimics what # would happen if A1.__post_init__ had been automatically added, # instead of manually added as we see here. This test isn't really # needed, but I'm including it just to demonstrate the changed # behavior when A1 does define __post_init__. c = C1() self.assertFalse(c.b_called) self.assertTrue(c.c_called) def test_class_var(self): # Make sure ClassVars are ignored in __init__, __repr__, etc. @dataclass class C: x: int y: int = 10 z: ClassVar[int] = 1000 w: ClassVar[int] = 2000 t: ClassVar[int] = 3000 s: ClassVar = 4000 c = C(5) self.assertEqual(repr(c), 'TestCase.test_class_var..C(x=5, y=10)') self.assertEqual(len(fields(C)), 2) # We have 2 fields. self.assertEqual(len(C.__annotations__), 6) # And 4 ClassVars. self.assertEqual(c.z, 1000) self.assertEqual(c.w, 2000) self.assertEqual(c.t, 3000) self.assertEqual(c.s, 4000) C.z += 1 self.assertEqual(c.z, 1001) c = C(20) self.assertEqual((c.x, c.y), (20, 10)) self.assertEqual(c.z, 1001) self.assertEqual(c.w, 2000) self.assertEqual(c.t, 3000) self.assertEqual(c.s, 4000) def test_class_var_no_default(self): # If a ClassVar has no default value, it should not be set on the class. @dataclass class C: x: ClassVar[int] self.assertNotIn('x', C.__dict__) def test_class_var_default_factory(self): # It makes no sense for a ClassVar to have a default factory. When # would it be called? Call it yourself, since it's class-wide. with self.assertRaisesRegex(TypeError, 'cannot have a default factory'): @dataclass class C: x: ClassVar[int] = field(default_factory=int) self.assertNotIn('x', C.__dict__) def test_class_var_with_default(self): # If a ClassVar has a default value, it should be set on the class. @dataclass class C: x: ClassVar[int] = 10 self.assertEqual(C.x, 10) @dataclass class C: x: ClassVar[int] = field(default=10) self.assertEqual(C.x, 10) def test_class_var_frozen(self): # Make sure ClassVars work even if we're frozen. @dataclass(frozen=True) class C: x: int y: int = 10 z: ClassVar[int] = 1000 w: ClassVar[int] = 2000 t: ClassVar[int] = 3000 c = C(5) self.assertEqual(repr(C(5)), 'TestCase.test_class_var_frozen..C(x=5, y=10)') self.assertEqual(len(fields(C)), 2) # We have 2 fields self.assertEqual(len(C.__annotations__), 5) # And 3 ClassVars self.assertEqual(c.z, 1000) self.assertEqual(c.w, 2000) self.assertEqual(c.t, 3000) # We can still modify the ClassVar, it's only instances that are # frozen. C.z += 1 self.assertEqual(c.z, 1001) c = C(20) self.assertEqual((c.x, c.y), (20, 10)) self.assertEqual(c.z, 1001) self.assertEqual(c.w, 2000) self.assertEqual(c.t, 3000) def test_init_var_no_default(self): # If an InitVar has no default value, it should not be set on the class. @dataclass class C: x: InitVar[int] self.assertNotIn('x', C.__dict__) def test_init_var_default_factory(self): # It makes no sense for an InitVar to have a default factory. When # would it be called? Call it yourself, since it's class-wide. with self.assertRaisesRegex(TypeError, 'cannot have a default factory'): @dataclass class C: x: InitVar[int] = field(default_factory=int) self.assertNotIn('x', C.__dict__) def test_init_var_with_default(self): # If an InitVar has a default value, it should be set on the class. @dataclass class C: x: InitVar[int] = 10 self.assertEqual(C.x, 10) @dataclass class C: x: InitVar[int] = field(default=10) self.assertEqual(C.x, 10) def test_init_var(self): @dataclass class C: x: int = None init_param: InitVar[int] = None def __post_init__(self, init_param): if self.x is None: self.x = init_param*2 c = C(init_param=10) self.assertEqual(c.x, 20) def test_init_var_preserve_type(self): self.assertEqual(InitVar[int].type, int) # Make sure the repr is correct. self.assertEqual(repr(InitVar[int]), 'dataclasses.InitVar[int]') self.assertEqual(repr(InitVar[List[int]]), 'dataclasses.InitVar[typing.List[int]]') self.assertEqual(repr(InitVar[list[int]]), 'dataclasses.InitVar[list[int]]') self.assertEqual(repr(InitVar[int|str]), 'dataclasses.InitVar[int | str]') def test_init_var_inheritance(self): # Note that this deliberately tests that a dataclass need not # have a __post_init__ function if it has an InitVar field. # It could just be used in a derived class, as shown here. @dataclass class Base: x: int init_base: InitVar[int] # We can instantiate by passing the InitVar, even though # it's not used. b = Base(0, 10) self.assertEqual(vars(b), {'x': 0}) @dataclass class C(Base): y: int init_derived: InitVar[int] def __post_init__(self, init_base, init_derived): self.x = self.x + init_base self.y = self.y + init_derived c = C(10, 11, 50, 51) self.assertEqual(vars(c), {'x': 21, 'y': 101}) def test_default_factory(self): # Test a factory that returns a new list. @dataclass class C: x: int y: list = field(default_factory=list) c0 = C(3) c1 = C(3) self.assertEqual(c0.x, 3) self.assertEqual(c0.y, []) self.assertEqual(c0, c1) self.assertIsNot(c0.y, c1.y) self.assertEqual(astuple(C(5, [1])), (5, [1])) # Test a factory that returns a shared list. l = [] @dataclass class C: x: int y: list = field(default_factory=lambda: l) c0 = C(3) c1 = C(3) self.assertEqual(c0.x, 3) self.assertEqual(c0.y, []) self.assertEqual(c0, c1) self.assertIs(c0.y, c1.y) self.assertEqual(astuple(C(5, [1])), (5, [1])) # Test various other field flags. # repr @dataclass class C: x: list = field(default_factory=list, repr=False) self.assertEqual(repr(C()), 'TestCase.test_default_factory..C()') self.assertEqual(C().x, []) # hash @dataclass(unsafe_hash=True) class C: x: list = field(default_factory=list, hash=False) self.assertEqual(astuple(C()), ([],)) self.assertEqual(hash(C()), hash(())) # init (see also test_default_factory_with_no_init) @dataclass class C: x: list = field(default_factory=list, init=False) self.assertEqual(astuple(C()), ([],)) # compare @dataclass class C: x: list = field(default_factory=list, compare=False) self.assertEqual(C(), C([1])) def test_default_factory_with_no_init(self): # We need a factory with a side effect. factory = Mock() @dataclass class C: x: list = field(default_factory=factory, init=False) # Make sure the default factory is called for each new instance. C().x self.assertEqual(factory.call_count, 1) C().x self.assertEqual(factory.call_count, 2) def test_default_factory_not_called_if_value_given(self): # We need a factory that we can test if it's been called. factory = Mock() @dataclass class C: x: int = field(default_factory=factory) # Make sure that if a field has a default factory function, # it's not called if a value is specified. C().x self.assertEqual(factory.call_count, 1) self.assertEqual(C(10).x, 10) self.assertEqual(factory.call_count, 1) C().x self.assertEqual(factory.call_count, 2) def test_default_factory_derived(self): # See bpo-32896. @dataclass class Foo: x: dict = field(default_factory=dict) @dataclass class Bar(Foo): y: int = 1 self.assertEqual(Foo().x, {}) self.assertEqual(Bar().x, {}) self.assertEqual(Bar().y, 1) @dataclass class Baz(Foo): pass self.assertEqual(Baz().x, {}) def test_intermediate_non_dataclass(self): # Test that an intermediate class that defines # annotations does not define fields. @dataclass class A: x: int class B(A): y: int @dataclass class C(B): z: int c = C(1, 3) self.assertEqual((c.x, c.z), (1, 3)) # .y was not initialized. with self.assertRaisesRegex(AttributeError, 'object has no attribute'): c.y # And if we again derive a non-dataclass, no fields are added. class D(C): t: int d = D(4, 5) self.assertEqual((d.x, d.z), (4, 5)) def test_classvar_default_factory(self): # It's an error for a ClassVar to have a factory function. with self.assertRaisesRegex(TypeError, 'cannot have a default factory'): @dataclass class C: x: ClassVar[int] = field(default_factory=int) def test_is_dataclass(self): class NotDataClass: pass self.assertFalse(is_dataclass(0)) self.assertFalse(is_dataclass(int)) self.assertFalse(is_dataclass(NotDataClass)) self.assertFalse(is_dataclass(NotDataClass())) @dataclass class C: x: int @dataclass class D: d: C e: int c = C(10) d = D(c, 4) self.assertTrue(is_dataclass(C)) self.assertTrue(is_dataclass(c)) self.assertFalse(is_dataclass(c.x)) self.assertTrue(is_dataclass(d.d)) self.assertFalse(is_dataclass(d.e)) def test_is_dataclass_when_getattr_always_returns(self): # See bpo-37868. class A: def __getattr__(self, key): return 0 self.assertFalse(is_dataclass(A)) a = A() # Also test for an instance attribute. class B: pass b = B() b.__dataclass_fields__ = [] for obj in a, b: with self.subTest(obj=obj): self.assertFalse(is_dataclass(obj)) # Indirect tests for _is_dataclass_instance(). with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): asdict(obj) with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): astuple(obj) with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): replace(obj, x=0) def test_is_dataclass_genericalias(self): @dataclass class A(types.GenericAlias): origin: type args: type self.assertTrue(is_dataclass(A)) a = A(list, int) self.assertTrue(is_dataclass(type(a))) self.assertTrue(is_dataclass(a)) def test_helper_fields_with_class_instance(self): # Check that we can call fields() on either a class or instance, # and get back the same thing. @dataclass class C: x: int y: float self.assertEqual(fields(C), fields(C(0, 0.0))) def test_helper_fields_exception(self): # Check that TypeError is raised if not passed a dataclass or # instance. with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): fields(0) class C: pass with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): fields(C) with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): fields(C()) def test_helper_asdict(self): # Basic tests for asdict(), it should return a new dictionary. @dataclass class C: x: int y: int c = C(1, 2) self.assertEqual(asdict(c), {'x': 1, 'y': 2}) self.assertEqual(asdict(c), asdict(c)) self.assertIsNot(asdict(c), asdict(c)) c.x = 42 self.assertEqual(asdict(c), {'x': 42, 'y': 2}) self.assertIs(type(asdict(c)), dict) def test_helper_asdict_raises_on_classes(self): # asdict() should raise on a class object. @dataclass class C: x: int y: int with self.assertRaisesRegex(TypeError, 'dataclass instance'): asdict(C) with self.assertRaisesRegex(TypeError, 'dataclass instance'): asdict(int) def test_helper_asdict_copy_values(self): @dataclass class C: x: int y: List[int] = field(default_factory=list) initial = [] c = C(1, initial) d = asdict(c) self.assertEqual(d['y'], initial) self.assertIsNot(d['y'], initial) c = C(1) d = asdict(c) d['y'].append(1) self.assertEqual(c.y, []) def test_helper_asdict_nested(self): @dataclass class UserId: token: int group: int @dataclass class User: name: str id: UserId u = User('Joe', UserId(123, 1)) d = asdict(u) self.assertEqual(d, {'name': 'Joe', 'id': {'token': 123, 'group': 1}}) self.assertIsNot(asdict(u), asdict(u)) u.id.group = 2 self.assertEqual(asdict(u), {'name': 'Joe', 'id': {'token': 123, 'group': 2}}) def test_helper_asdict_builtin_containers(self): @dataclass class User: name: str id: int @dataclass class GroupList: id: int users: List[User] @dataclass class GroupTuple: id: int users: Tuple[User, ...] @dataclass class GroupDict: id: int users: Dict[str, User] a = User('Alice', 1) b = User('Bob', 2) gl = GroupList(0, [a, b]) gt = GroupTuple(0, (a, b)) gd = GroupDict(0, {'first': a, 'second': b}) self.assertEqual(asdict(gl), {'id': 0, 'users': [{'name': 'Alice', 'id': 1}, {'name': 'Bob', 'id': 2}]}) self.assertEqual(asdict(gt), {'id': 0, 'users': ({'name': 'Alice', 'id': 1}, {'name': 'Bob', 'id': 2})}) self.assertEqual(asdict(gd), {'id': 0, 'users': {'first': {'name': 'Alice', 'id': 1}, 'second': {'name': 'Bob', 'id': 2}}}) def test_helper_asdict_builtin_object_containers(self): @dataclass class Child: d: object @dataclass class Parent: child: Child self.assertEqual(asdict(Parent(Child([1]))), {'child': {'d': [1]}}) self.assertEqual(asdict(Parent(Child({1: 2}))), {'child': {'d': {1: 2}}}) def test_helper_asdict_factory(self): @dataclass class C: x: int y: int c = C(1, 2) d = asdict(c, dict_factory=OrderedDict) self.assertEqual(d, OrderedDict([('x', 1), ('y', 2)])) self.assertIsNot(d, asdict(c, dict_factory=OrderedDict)) c.x = 42 d = asdict(c, dict_factory=OrderedDict) self.assertEqual(d, OrderedDict([('x', 42), ('y', 2)])) self.assertIs(type(d), OrderedDict) def test_helper_asdict_namedtuple(self): T = namedtuple('T', 'a b c') @dataclass class C: x: str y: T c = C('outer', T(1, C('inner', T(11, 12, 13)), 2)) d = asdict(c) self.assertEqual(d, {'x': 'outer', 'y': T(1, {'x': 'inner', 'y': T(11, 12, 13)}, 2), } ) # Now with a dict_factory. OrderedDict is convenient, but # since it compares to dicts, we also need to have separate # assertIs tests. d = asdict(c, dict_factory=OrderedDict) self.assertEqual(d, {'x': 'outer', 'y': T(1, {'x': 'inner', 'y': T(11, 12, 13)}, 2), } ) # Make sure that the returned dicts are actually OrderedDicts. self.assertIs(type(d), OrderedDict) self.assertIs(type(d['y'][1]), OrderedDict) def test_helper_asdict_namedtuple_key(self): # Ensure that a field that contains a dict which has a # namedtuple as a key works with asdict(). @dataclass class C: f: dict T = namedtuple('T', 'a') c = C({T('an a'): 0}) self.assertEqual(asdict(c), {'f': {T(a='an a'): 0}}) def test_helper_asdict_namedtuple_derived(self): class T(namedtuple('Tbase', 'a')): def my_a(self): return self.a @dataclass class C: f: T t = T(6) c = C(t) d = asdict(c) self.assertEqual(d, {'f': T(a=6)}) # Make sure that t has been copied, not used directly. self.assertIsNot(d['f'], t) self.assertEqual(d['f'].my_a(), 6) def test_helper_astuple(self): # Basic tests for astuple(), it should return a new tuple. @dataclass class C: x: int y: int = 0 c = C(1) self.assertEqual(astuple(c), (1, 0)) self.assertEqual(astuple(c), astuple(c)) self.assertIsNot(astuple(c), astuple(c)) c.y = 42 self.assertEqual(astuple(c), (1, 42)) self.assertIs(type(astuple(c)), tuple) def test_helper_astuple_raises_on_classes(self): # astuple() should raise on a class object. @dataclass class C: x: int y: int with self.assertRaisesRegex(TypeError, 'dataclass instance'): astuple(C) with self.assertRaisesRegex(TypeError, 'dataclass instance'): astuple(int) def test_helper_astuple_copy_values(self): @dataclass class C: x: int y: List[int] = field(default_factory=list) initial = [] c = C(1, initial) t = astuple(c) self.assertEqual(t[1], initial) self.assertIsNot(t[1], initial) c = C(1) t = astuple(c) t[1].append(1) self.assertEqual(c.y, []) def test_helper_astuple_nested(self): @dataclass class UserId: token: int group: int @dataclass class User: name: str id: UserId u = User('Joe', UserId(123, 1)) t = astuple(u) self.assertEqual(t, ('Joe', (123, 1))) self.assertIsNot(astuple(u), astuple(u)) u.id.group = 2 self.assertEqual(astuple(u), ('Joe', (123, 2))) def test_helper_astuple_builtin_containers(self): @dataclass class User: name: str id: int @dataclass class GroupList: id: int users: List[User] @dataclass class GroupTuple: id: int users: Tuple[User, ...] @dataclass class GroupDict: id: int users: Dict[str, User] a = User('Alice', 1) b = User('Bob', 2) gl = GroupList(0, [a, b]) gt = GroupTuple(0, (a, b)) gd = GroupDict(0, {'first': a, 'second': b}) self.assertEqual(astuple(gl), (0, [('Alice', 1), ('Bob', 2)])) self.assertEqual(astuple(gt), (0, (('Alice', 1), ('Bob', 2)))) self.assertEqual(astuple(gd), (0, {'first': ('Alice', 1), 'second': ('Bob', 2)})) def test_helper_astuple_builtin_object_containers(self): @dataclass class Child: d: object @dataclass class Parent: child: Child self.assertEqual(astuple(Parent(Child([1]))), (([1],),)) self.assertEqual(astuple(Parent(Child({1: 2}))), (({1: 2},),)) def test_helper_astuple_factory(self): @dataclass class C: x: int y: int NT = namedtuple('NT', 'x y') def nt(lst): return NT(*lst) c = C(1, 2) t = astuple(c, tuple_factory=nt) self.assertEqual(t, NT(1, 2)) self.assertIsNot(t, astuple(c, tuple_factory=nt)) c.x = 42 t = astuple(c, tuple_factory=nt) self.assertEqual(t, NT(42, 2)) self.assertIs(type(t), NT) def test_helper_astuple_namedtuple(self): T = namedtuple('T', 'a b c') @dataclass class C: x: str y: T c = C('outer', T(1, C('inner', T(11, 12, 13)), 2)) t = astuple(c) self.assertEqual(t, ('outer', T(1, ('inner', (11, 12, 13)), 2))) # Now, using a tuple_factory. list is convenient here. t = astuple(c, tuple_factory=list) self.assertEqual(t, ['outer', T(1, ['inner', T(11, 12, 13)], 2)]) def test_dynamic_class_creation(self): cls_dict = {'__annotations__': {'x': int, 'y': int}, } # Create the class. cls = type('C', (), cls_dict) # Make it a dataclass. cls1 = dataclass(cls) self.assertEqual(cls1, cls) self.assertEqual(asdict(cls(1, 2)), {'x': 1, 'y': 2}) def test_dynamic_class_creation_using_field(self): cls_dict = {'__annotations__': {'x': int, 'y': int}, 'y': field(default=5), } # Create the class. cls = type('C', (), cls_dict) # Make it a dataclass. cls1 = dataclass(cls) self.assertEqual(cls1, cls) self.assertEqual(asdict(cls1(1)), {'x': 1, 'y': 5}) def test_init_in_order(self): @dataclass class C: a: int b: int = field() c: list = field(default_factory=list, init=False) d: list = field(default_factory=list) e: int = field(default=4, init=False) f: int = 4 calls = [] def setattr(self, name, value): calls.append((name, value)) C.__setattr__ = setattr c = C(0, 1) self.assertEqual(('a', 0), calls[0]) self.assertEqual(('b', 1), calls[1]) self.assertEqual(('c', []), calls[2]) self.assertEqual(('d', []), calls[3]) self.assertNotIn(('e', 4), calls) self.assertEqual(('f', 4), calls[4]) def test_items_in_dicts(self): @dataclass class C: a: int b: list = field(default_factory=list, init=False) c: list = field(default_factory=list) d: int = field(default=4, init=False) e: int = 0 c = C(0) # Class dict self.assertNotIn('a', C.__dict__) self.assertNotIn('b', C.__dict__) self.assertNotIn('c', C.__dict__) self.assertIn('d', C.__dict__) self.assertEqual(C.d, 4) self.assertIn('e', C.__dict__) self.assertEqual(C.e, 0) # Instance dict self.assertIn('a', c.__dict__) self.assertEqual(c.a, 0) self.assertIn('b', c.__dict__) self.assertEqual(c.b, []) self.assertIn('c', c.__dict__) self.assertEqual(c.c, []) self.assertNotIn('d', c.__dict__) self.assertIn('e', c.__dict__) self.assertEqual(c.e, 0) def test_alternate_classmethod_constructor(self): # Since __post_init__ can't take params, use a classmethod # alternate constructor. This is mostly an example to show # how to use this technique. @dataclass class C: x: int @classmethod def from_file(cls, filename): # In a real example, create a new instance # and populate 'x' from contents of a file. value_in_file = 20 return cls(value_in_file) self.assertEqual(C.from_file('filename').x, 20) def test_field_metadata_default(self): # Make sure the default metadata is read-only and of # zero length. @dataclass class C: i: int self.assertFalse(fields(C)[0].metadata) self.assertEqual(len(fields(C)[0].metadata), 0) with self.assertRaisesRegex(TypeError, 'does not support item assignment'): fields(C)[0].metadata['test'] = 3 def test_field_metadata_mapping(self): # Make sure only a mapping can be passed as metadata # zero length. with self.assertRaises(TypeError): @dataclass class C: i: int = field(metadata=0) # Make sure an empty dict works. d = {} @dataclass class C: i: int = field(metadata=d) self.assertFalse(fields(C)[0].metadata) self.assertEqual(len(fields(C)[0].metadata), 0) # Update should work (see bpo-35960). d['foo'] = 1 self.assertEqual(len(fields(C)[0].metadata), 1) self.assertEqual(fields(C)[0].metadata['foo'], 1) with self.assertRaisesRegex(TypeError, 'does not support item assignment'): fields(C)[0].metadata['test'] = 3 # Make sure a non-empty dict works. d = {'test': 10, 'bar': '42', 3: 'three'} @dataclass class C: i: int = field(metadata=d) self.assertEqual(len(fields(C)[0].metadata), 3) self.assertEqual(fields(C)[0].metadata['test'], 10) self.assertEqual(fields(C)[0].metadata['bar'], '42') self.assertEqual(fields(C)[0].metadata[3], 'three') # Update should work. d['foo'] = 1 self.assertEqual(len(fields(C)[0].metadata), 4) self.assertEqual(fields(C)[0].metadata['foo'], 1) with self.assertRaises(KeyError): # Non-existent key. fields(C)[0].metadata['baz'] with self.assertRaisesRegex(TypeError, 'does not support item assignment'): fields(C)[0].metadata['test'] = 3 def test_field_metadata_custom_mapping(self): # Try a custom mapping. class SimpleNameSpace: def __init__(self, **kw): self.__dict__.update(kw) def __getitem__(self, item): if item == 'xyzzy': return 'plugh' return getattr(self, item) def __len__(self): return self.__dict__.__len__() @dataclass class C: i: int = field(metadata=SimpleNameSpace(a=10)) self.assertEqual(len(fields(C)[0].metadata), 1) self.assertEqual(fields(C)[0].metadata['a'], 10) with self.assertRaises(AttributeError): fields(C)[0].metadata['b'] # Make sure we're still talking to our custom mapping. self.assertEqual(fields(C)[0].metadata['xyzzy'], 'plugh') def test_generic_dataclasses(self): T = TypeVar('T') @dataclass class LabeledBox(Generic[T]): content: T label: str = '' box = LabeledBox(42) self.assertEqual(box.content, 42) self.assertEqual(box.label, '') # Subscripting the resulting class should work, etc. Alias = List[LabeledBox[int]] def test_generic_extending(self): S = TypeVar('S') T = TypeVar('T') @dataclass class Base(Generic[T, S]): x: T y: S @dataclass class DataDerived(Base[int, T]): new_field: str Alias = DataDerived[str] c = Alias(0, 'test1', 'test2') self.assertEqual(astuple(c), (0, 'test1', 'test2')) class NonDataDerived(Base[int, T]): def new_method(self): return self.y Alias = NonDataDerived[float] c = Alias(10, 1.0) self.assertEqual(c.new_method(), 1.0) def test_generic_dynamic(self): T = TypeVar('T') @dataclass class Parent(Generic[T]): x: T Child = make_dataclass('Child', [('y', T), ('z', Optional[T], None)], bases=(Parent[int], Generic[T]), namespace={'other': 42}) self.assertIs(Child[int](1, 2).z, None) self.assertEqual(Child[int](1, 2, 3).z, 3) self.assertEqual(Child[int](1, 2, 3).other, 42) # Check that type aliases work correctly. Alias = Child[T] self.assertEqual(Alias[int](1, 2).x, 1) # Check MRO resolution. self.assertEqual(Child.__mro__, (Child, Parent, Generic, object)) def test_dataclasses_pickleable(self): global P, Q, R @dataclass class P: x: int y: int = 0 @dataclass class Q: x: int y: int = field(default=0, init=False) @dataclass class R: x: int y: List[int] = field(default_factory=list) q = Q(1) q.y = 2 samples = [P(1), P(1, 2), Q(1), q, R(1), R(1, [2, 3, 4])] for sample in samples: for proto in range(pickle.HIGHEST_PROTOCOL + 1): with self.subTest(sample=sample, proto=proto): new_sample = pickle.loads(pickle.dumps(sample, proto)) self.assertEqual(sample.x, new_sample.x) self.assertEqual(sample.y, new_sample.y) self.assertIsNot(sample, new_sample) new_sample.x = 42 another_new_sample = pickle.loads(pickle.dumps(new_sample, proto)) self.assertEqual(new_sample.x, another_new_sample.x) self.assertEqual(sample.y, another_new_sample.y) def test_dataclasses_qualnames(self): @dataclass(order=True, unsafe_hash=True, frozen=True) class A: x: int y: int self.assertEqual(A.__init__.__name__, "__init__") for function in ( '__eq__', '__lt__', '__le__', '__gt__', '__ge__', '__hash__', '__init__', '__repr__', '__setattr__', '__delattr__', ): self.assertEqual(getattr(A, function).__qualname__, f"TestCase.test_dataclasses_qualnames..A.{function}") with self.assertRaisesRegex(TypeError, r"A\.__init__\(\) missing"): A() class TestFieldNoAnnotation(unittest.TestCase): def test_field_without_annotation(self): with self.assertRaisesRegex(TypeError, "'f' is a field but has no type annotation"): @dataclass class C: f = field() def test_field_without_annotation_but_annotation_in_base(self): @dataclass class B: f: int with self.assertRaisesRegex(TypeError, "'f' is a field but has no type annotation"): # This is still an error: make sure we don't pick up the # type annotation in the base class. @dataclass class C(B): f = field() def test_field_without_annotation_but_annotation_in_base_not_dataclass(self): # Same test, but with the base class not a dataclass. class B: f: int with self.assertRaisesRegex(TypeError, "'f' is a field but has no type annotation"): # This is still an error: make sure we don't pick up the # type annotation in the base class. @dataclass class C(B): f = field() class TestDocString(unittest.TestCase): def assertDocStrEqual(self, a, b): # Because 3.6 and 3.7 differ in how inspect.signature work # (see bpo #32108), for the time being just compare them with # whitespace stripped. self.assertEqual(a.replace(' ', ''), b.replace(' ', '')) def test_existing_docstring_not_overridden(self): @dataclass class C: """Lorem ipsum""" x: int self.assertEqual(C.__doc__, "Lorem ipsum") def test_docstring_no_fields(self): @dataclass class C: pass self.assertDocStrEqual(C.__doc__, "C()") def test_docstring_one_field(self): @dataclass class C: x: int self.assertDocStrEqual(C.__doc__, "C(x:int)") def test_docstring_two_fields(self): @dataclass class C: x: int y: int self.assertDocStrEqual(C.__doc__, "C(x:int, y:int)") def test_docstring_three_fields(self): @dataclass class C: x: int y: int z: str self.assertDocStrEqual(C.__doc__, "C(x:int, y:int, z:str)") def test_docstring_one_field_with_default(self): @dataclass class C: x: int = 3 self.assertDocStrEqual(C.__doc__, "C(x:int=3)") def test_docstring_one_field_with_default_none(self): @dataclass class C: x: Union[int, type(None)] = None self.assertDocStrEqual(C.__doc__, "C(x:Optional[int]=None)") def test_docstring_list_field(self): @dataclass class C: x: List[int] self.assertDocStrEqual(C.__doc__, "C(x:List[int])") def test_docstring_list_field_with_default_factory(self): @dataclass class C: x: List[int] = field(default_factory=list) self.assertDocStrEqual(C.__doc__, "C(x:List[int]=)") def test_docstring_deque_field(self): @dataclass class C: x: deque self.assertDocStrEqual(C.__doc__, "C(x:collections.deque)") def test_docstring_deque_field_with_default_factory(self): @dataclass class C: x: deque = field(default_factory=deque) self.assertDocStrEqual(C.__doc__, "C(x:collections.deque=)") class TestInit(unittest.TestCase): def test_base_has_init(self): class B: def __init__(self): self.z = 100 pass # Make sure that declaring this class doesn't raise an error. # The issue is that we can't override __init__ in our class, # but it should be okay to add __init__ to us if our base has # an __init__. @dataclass class C(B): x: int = 0 c = C(10) self.assertEqual(c.x, 10) self.assertNotIn('z', vars(c)) # Make sure that if we don't add an init, the base __init__ # gets called. @dataclass(init=False) class C(B): x: int = 10 c = C() self.assertEqual(c.x, 10) self.assertEqual(c.z, 100) def test_no_init(self): @dataclass(init=False) class C: i: int = 0 self.assertEqual(C().i, 0) @dataclass(init=False) class C: i: int = 2 def __init__(self): self.i = 3 self.assertEqual(C().i, 3) def test_overwriting_init(self): # If the class has __init__, use it no matter the value of # init=. @dataclass class C: x: int def __init__(self, x): self.x = 2 * x self.assertEqual(C(3).x, 6) @dataclass(init=True) class C: x: int def __init__(self, x): self.x = 2 * x self.assertEqual(C(4).x, 8) @dataclass(init=False) class C: x: int def __init__(self, x): self.x = 2 * x self.assertEqual(C(5).x, 10) def test_inherit_from_protocol(self): # Dataclasses inheriting from protocol should preserve their own `__init__`. # See bpo-45081. class P(Protocol): a: int @dataclass class C(P): a: int self.assertEqual(C(5).a, 5) @dataclass class D(P): def __init__(self, a): self.a = a * 2 self.assertEqual(D(5).a, 10) class TestRepr(unittest.TestCase): def test_repr(self): @dataclass class B: x: int @dataclass class C(B): y: int = 10 o = C(4) self.assertEqual(repr(o), 'TestRepr.test_repr..C(x=4, y=10)') @dataclass class D(C): x: int = 20 self.assertEqual(repr(D()), 'TestRepr.test_repr..D(x=20, y=10)') @dataclass class C: @dataclass class D: i: int @dataclass class E: pass self.assertEqual(repr(C.D(0)), 'TestRepr.test_repr..C.D(i=0)') self.assertEqual(repr(C.E()), 'TestRepr.test_repr..C.E()') def test_no_repr(self): # Test a class with no __repr__ and repr=False. @dataclass(repr=False) class C: x: int self.assertIn(f'{__name__}.TestRepr.test_no_repr..C object at', repr(C(3))) # Test a class with a __repr__ and repr=False. @dataclass(repr=False) class C: x: int def __repr__(self): return 'C-class' self.assertEqual(repr(C(3)), 'C-class') def test_overwriting_repr(self): # If the class has __repr__, use it no matter the value of # repr=. @dataclass class C: x: int def __repr__(self): return 'x' self.assertEqual(repr(C(0)), 'x') @dataclass(repr=True) class C: x: int def __repr__(self): return 'x' self.assertEqual(repr(C(0)), 'x') @dataclass(repr=False) class C: x: int def __repr__(self): return 'x' self.assertEqual(repr(C(0)), 'x') class TestEq(unittest.TestCase): def test_no_eq(self): # Test a class with no __eq__ and eq=False. @dataclass(eq=False) class C: x: int self.assertNotEqual(C(0), C(0)) c = C(3) self.assertEqual(c, c) # Test a class with an __eq__ and eq=False. @dataclass(eq=False) class C: x: int def __eq__(self, other): return other == 10 self.assertEqual(C(3), 10) def test_overwriting_eq(self): # If the class has __eq__, use it no matter the value of # eq=. @dataclass class C: x: int def __eq__(self, other): return other == 3 self.assertEqual(C(1), 3) self.assertNotEqual(C(1), 1) @dataclass(eq=True) class C: x: int def __eq__(self, other): return other == 4 self.assertEqual(C(1), 4) self.assertNotEqual(C(1), 1) @dataclass(eq=False) class C: x: int def __eq__(self, other): return other == 5 self.assertEqual(C(1), 5) self.assertNotEqual(C(1), 1) class TestOrdering(unittest.TestCase): def test_functools_total_ordering(self): # Test that functools.total_ordering works with this class. @total_ordering @dataclass class C: x: int def __lt__(self, other): # Perform the test "backward", just to make # sure this is being called. return self.x >= other self.assertLess(C(0), -1) self.assertLessEqual(C(0), -1) self.assertGreater(C(0), 1) self.assertGreaterEqual(C(0), 1) def test_no_order(self): # Test that no ordering functions are added by default. @dataclass(order=False) class C: x: int # Make sure no order methods are added. self.assertNotIn('__le__', C.__dict__) self.assertNotIn('__lt__', C.__dict__) self.assertNotIn('__ge__', C.__dict__) self.assertNotIn('__gt__', C.__dict__) # Test that __lt__ is still called @dataclass(order=False) class C: x: int def __lt__(self, other): return False # Make sure other methods aren't added. self.assertNotIn('__le__', C.__dict__) self.assertNotIn('__ge__', C.__dict__) self.assertNotIn('__gt__', C.__dict__) def test_overwriting_order(self): with self.assertRaisesRegex(TypeError, 'Cannot overwrite attribute __lt__' '.*using functools.total_ordering'): @dataclass(order=True) class C: x: int def __lt__(self): pass with self.assertRaisesRegex(TypeError, 'Cannot overwrite attribute __le__' '.*using functools.total_ordering'): @dataclass(order=True) class C: x: int def __le__(self): pass with self.assertRaisesRegex(TypeError, 'Cannot overwrite attribute __gt__' '.*using functools.total_ordering'): @dataclass(order=True) class C: x: int def __gt__(self): pass with self.assertRaisesRegex(TypeError, 'Cannot overwrite attribute __ge__' '.*using functools.total_ordering'): @dataclass(order=True) class C: x: int def __ge__(self): pass class TestHash(unittest.TestCase): def test_unsafe_hash(self): @dataclass(unsafe_hash=True) class C: x: int y: str self.assertEqual(hash(C(1, 'foo')), hash((1, 'foo'))) def test_hash_rules(self): def non_bool(value): # Map to something else that's True, but not a bool. if value is None: return None if value: return (3,) return 0 def test(case, unsafe_hash, eq, frozen, with_hash, result): with self.subTest(case=case, unsafe_hash=unsafe_hash, eq=eq, frozen=frozen): if result != 'exception': if with_hash: @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) class C: def __hash__(self): return 0 else: @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) class C: pass # See if the result matches what's expected. if result == 'fn': # __hash__ contains the function we generated. self.assertIn('__hash__', C.__dict__) self.assertIsNotNone(C.__dict__['__hash__']) elif result == '': # __hash__ is not present in our class. if not with_hash: self.assertNotIn('__hash__', C.__dict__) elif result == 'none': # __hash__ is set to None. self.assertIn('__hash__', C.__dict__) self.assertIsNone(C.__dict__['__hash__']) elif result == 'exception': # Creating the class should cause an exception. # This only happens with with_hash==True. assert(with_hash) with self.assertRaisesRegex(TypeError, 'Cannot overwrite attribute __hash__'): @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) class C: def __hash__(self): return 0 else: assert False, f'unknown result {result!r}' # There are 8 cases of: # unsafe_hash=True/False # eq=True/False # frozen=True/False # And for each of these, a different result if # __hash__ is defined or not. for case, (unsafe_hash, eq, frozen, res_no_defined_hash, res_defined_hash) in enumerate([ (False, False, False, '', ''), (False, False, True, '', ''), (False, True, False, 'none', ''), (False, True, True, 'fn', ''), (True, False, False, 'fn', 'exception'), (True, False, True, 'fn', 'exception'), (True, True, False, 'fn', 'exception'), (True, True, True, 'fn', 'exception'), ], 1): test(case, unsafe_hash, eq, frozen, False, res_no_defined_hash) test(case, unsafe_hash, eq, frozen, True, res_defined_hash) # Test non-bool truth values, too. This is just to # make sure the data-driven table in the decorator # handles non-bool values. test(case, non_bool(unsafe_hash), non_bool(eq), non_bool(frozen), False, res_no_defined_hash) test(case, non_bool(unsafe_hash), non_bool(eq), non_bool(frozen), True, res_defined_hash) def test_eq_only(self): # If a class defines __eq__, __hash__ is automatically added # and set to None. This is normal Python behavior, not # related to dataclasses. Make sure we don't interfere with # that (see bpo=32546). @dataclass class C: i: int def __eq__(self, other): return self.i == other.i self.assertEqual(C(1), C(1)) self.assertNotEqual(C(1), C(4)) # And make sure things work in this case if we specify # unsafe_hash=True. @dataclass(unsafe_hash=True) class C: i: int def __eq__(self, other): return self.i == other.i self.assertEqual(C(1), C(1.0)) self.assertEqual(hash(C(1)), hash(C(1.0))) # And check that the classes __eq__ is being used, despite # specifying eq=True. @dataclass(unsafe_hash=True, eq=True) class C: i: int def __eq__(self, other): return self.i == 3 and self.i == other.i self.assertEqual(C(3), C(3)) self.assertNotEqual(C(1), C(1)) self.assertEqual(hash(C(1)), hash(C(1.0))) def test_0_field_hash(self): @dataclass(frozen=True) class C: pass self.assertEqual(hash(C()), hash(())) @dataclass(unsafe_hash=True) class C: pass self.assertEqual(hash(C()), hash(())) def test_1_field_hash(self): @dataclass(frozen=True) class C: x: int self.assertEqual(hash(C(4)), hash((4,))) self.assertEqual(hash(C(42)), hash((42,))) @dataclass(unsafe_hash=True) class C: x: int self.assertEqual(hash(C(4)), hash((4,))) self.assertEqual(hash(C(42)), hash((42,))) def test_hash_no_args(self): # Test dataclasses with no hash= argument. This exists to # make sure that if the @dataclass parameter name is changed # or the non-default hashing behavior changes, the default # hashability keeps working the same way. class Base: def __hash__(self): return 301 # If frozen or eq is None, then use the default value (do not # specify any value in the decorator). for frozen, eq, base, expected in [ (None, None, object, 'unhashable'), (None, None, Base, 'unhashable'), (None, False, object, 'object'), (None, False, Base, 'base'), (None, True, object, 'unhashable'), (None, True, Base, 'unhashable'), (False, None, object, 'unhashable'), (False, None, Base, 'unhashable'), (False, False, object, 'object'), (False, False, Base, 'base'), (False, True, object, 'unhashable'), (False, True, Base, 'unhashable'), (True, None, object, 'tuple'), (True, None, Base, 'tuple'), (True, False, object, 'object'), (True, False, Base, 'base'), (True, True, object, 'tuple'), (True, True, Base, 'tuple'), ]: with self.subTest(frozen=frozen, eq=eq, base=base, expected=expected): # First, create the class. if frozen is None and eq is None: @dataclass class C(base): i: int elif frozen is None: @dataclass(eq=eq) class C(base): i: int elif eq is None: @dataclass(frozen=frozen) class C(base): i: int else: @dataclass(frozen=frozen, eq=eq) class C(base): i: int # Now, make sure it hashes as expected. if expected == 'unhashable': c = C(10) with self.assertRaisesRegex(TypeError, 'unhashable type'): hash(c) elif expected == 'base': self.assertEqual(hash(C(10)), 301) elif expected == 'object': # I'm not sure what test to use here. object's # hash isn't based on id(), so calling hash() # won't tell us much. So, just check the # function used is object's. self.assertIs(C.__hash__, object.__hash__) elif expected == 'tuple': self.assertEqual(hash(C(42)), hash((42,))) else: assert False, f'unknown value for expected={expected!r}' class TestFrozen(unittest.TestCase): def test_frozen(self): @dataclass(frozen=True) class C: i: int c = C(10) self.assertEqual(c.i, 10) with self.assertRaises(FrozenInstanceError): c.i = 5 self.assertEqual(c.i, 10) def test_inherit(self): @dataclass(frozen=True) class C: i: int @dataclass(frozen=True) class D(C): j: int d = D(0, 10) with self.assertRaises(FrozenInstanceError): d.i = 5 with self.assertRaises(FrozenInstanceError): d.j = 6 self.assertEqual(d.i, 0) self.assertEqual(d.j, 10) def test_inherit_nonfrozen_from_empty_frozen(self): @dataclass(frozen=True) class C: pass with self.assertRaisesRegex(TypeError, 'cannot inherit non-frozen dataclass from a frozen one'): @dataclass class D(C): j: int def test_inherit_nonfrozen_from_empty(self): @dataclass class C: pass @dataclass class D(C): j: int d = D(3) self.assertEqual(d.j, 3) self.assertIsInstance(d, C) # Test both ways: with an intermediate normal (non-dataclass) # class and without an intermediate class. def test_inherit_nonfrozen_from_frozen(self): for intermediate_class in [True, False]: with self.subTest(intermediate_class=intermediate_class): @dataclass(frozen=True) class C: i: int if intermediate_class: class I(C): pass else: I = C with self.assertRaisesRegex(TypeError, 'cannot inherit non-frozen dataclass from a frozen one'): @dataclass class D(I): pass def test_inherit_frozen_from_nonfrozen(self): for intermediate_class in [True, False]: with self.subTest(intermediate_class=intermediate_class): @dataclass class C: i: int if intermediate_class: class I(C): pass else: I = C with self.assertRaisesRegex(TypeError, 'cannot inherit frozen dataclass from a non-frozen one'): @dataclass(frozen=True) class D(I): pass def test_inherit_from_normal_class(self): for intermediate_class in [True, False]: with self.subTest(intermediate_class=intermediate_class): class C: pass if intermediate_class: class I(C): pass else: I = C @dataclass(frozen=True) class D(I): i: int d = D(10) with self.assertRaises(FrozenInstanceError): d.i = 5 def test_non_frozen_normal_derived(self): # See bpo-32953. @dataclass(frozen=True) class D: x: int y: int = 10 class S(D): pass s = S(3) self.assertEqual(s.x, 3) self.assertEqual(s.y, 10) s.cached = True # But can't change the frozen attributes. with self.assertRaises(FrozenInstanceError): s.x = 5 with self.assertRaises(FrozenInstanceError): s.y = 5 self.assertEqual(s.x, 3) self.assertEqual(s.y, 10) self.assertEqual(s.cached, True) def test_overwriting_frozen(self): # frozen uses __setattr__ and __delattr__. with self.assertRaisesRegex(TypeError, 'Cannot overwrite attribute __setattr__'): @dataclass(frozen=True) class C: x: int def __setattr__(self): pass with self.assertRaisesRegex(TypeError, 'Cannot overwrite attribute __delattr__'): @dataclass(frozen=True) class C: x: int def __delattr__(self): pass @dataclass(frozen=False) class C: x: int def __setattr__(self, name, value): self.__dict__['x'] = value * 2 self.assertEqual(C(10).x, 20) def test_frozen_hash(self): @dataclass(frozen=True) class C: x: Any # If x is immutable, we can compute the hash. No exception is # raised. hash(C(3)) # If x is mutable, computing the hash is an error. with self.assertRaisesRegex(TypeError, 'unhashable type'): hash(C({})) class TestSlots(unittest.TestCase): def test_simple(self): @dataclass class C: __slots__ = ('x',) x: Any # There was a bug where a variable in a slot was assumed to # also have a default value (of type # types.MemberDescriptorType). with self.assertRaisesRegex(TypeError, r"__init__\(\) missing 1 required positional argument: 'x'"): C() # We can create an instance, and assign to x. c = C(10) self.assertEqual(c.x, 10) c.x = 5 self.assertEqual(c.x, 5) # We can't assign to anything else. with self.assertRaisesRegex(AttributeError, "'C' object has no attribute 'y'"): c.y = 5 def test_derived_added_field(self): # See bpo-33100. @dataclass class Base: __slots__ = ('x',) x: Any @dataclass class Derived(Base): x: int y: int d = Derived(1, 2) self.assertEqual((d.x, d.y), (1, 2)) # We can add a new field to the derived instance. d.z = 10 def test_generated_slots(self): @dataclass(slots=True) class C: x: int y: int c = C(1, 2) self.assertEqual((c.x, c.y), (1, 2)) c.x = 3 c.y = 4 self.assertEqual((c.x, c.y), (3, 4)) with self.assertRaisesRegex(AttributeError, "'C' object has no attribute 'z'"): c.z = 5 def test_add_slots_when_slots_exists(self): with self.assertRaisesRegex(TypeError, '^C already specifies __slots__$'): @dataclass(slots=True) class C: __slots__ = ('x',) x: int def test_generated_slots_value(self): class Root: __slots__ = {'x'} class Root2(Root): __slots__ = {'k': '...', 'j': ''} class Root3(Root2): __slots__ = ['h'] class Root4(Root3): __slots__ = 'aa' @dataclass(slots=True) class Base(Root4): y: int j: str h: str self.assertEqual(Base.__slots__, ('y', )) @dataclass(slots=True) class Derived(Base): aa: float x: str z: int k: str h: str self.assertEqual(Derived.__slots__, ('z', )) @dataclass class AnotherDerived(Base): z: int self.assertNotIn('__slots__', AnotherDerived.__dict__) def test_cant_inherit_from_iterator_slots(self): class Root: __slots__ = iter(['a']) class Root2(Root): __slots__ = ('b', ) with self.assertRaisesRegex( TypeError, "^Slots of 'Root' cannot be determined" ): @dataclass(slots=True) class C(Root2): x: int def test_returns_new_class(self): class A: x: int B = dataclass(A, slots=True) self.assertIsNot(A, B) self.assertFalse(hasattr(A, "__slots__")) self.assertTrue(hasattr(B, "__slots__")) # Can't be local to test_frozen_pickle. @dataclass(frozen=True, slots=True) class FrozenSlotsClass: foo: str bar: int @dataclass(frozen=True) class FrozenWithoutSlotsClass: foo: str bar: int def test_frozen_pickle(self): # bpo-43999 self.assertEqual(self.FrozenSlotsClass.__slots__, ("foo", "bar")) for proto in range(pickle.HIGHEST_PROTOCOL + 1): with self.subTest(proto=proto): obj = self.FrozenSlotsClass("a", 1) p = pickle.loads(pickle.dumps(obj, protocol=proto)) self.assertIsNot(obj, p) self.assertEqual(obj, p) obj = self.FrozenWithoutSlotsClass("a", 1) p = pickle.loads(pickle.dumps(obj, protocol=proto)) self.assertIsNot(obj, p) self.assertEqual(obj, p) def test_slots_with_default_no_init(self): # Originally reported in bpo-44649. @dataclass(slots=True) class A: a: str b: str = field(default='b', init=False) obj = A("a") self.assertEqual(obj.a, 'a') self.assertEqual(obj.b, 'b') def test_slots_with_default_factory_no_init(self): # Originally reported in bpo-44649. @dataclass(slots=True) class A: a: str b: str = field(default_factory=lambda:'b', init=False) obj = A("a") self.assertEqual(obj.a, 'a') self.assertEqual(obj.b, 'b') def test_slots_no_weakref(self): @dataclass(slots=True) class A: # No weakref. pass self.assertNotIn("__weakref__", A.__slots__) a = A() with self.assertRaisesRegex(TypeError, "cannot create weak reference"): weakref.ref(a) def test_slots_weakref(self): @dataclass(slots=True, weakref_slot=True) class A: a: int self.assertIn("__weakref__", A.__slots__) a = A(1) weakref.ref(a) def test_slots_weakref_base_str(self): class Base: __slots__ = '__weakref__' @dataclass(slots=True) class A(Base): a: int # __weakref__ is in the base class, not A. But an A is still weakref-able. self.assertIn("__weakref__", Base.__slots__) self.assertNotIn("__weakref__", A.__slots__) a = A(1) weakref.ref(a) def test_slots_weakref_base_tuple(self): # Same as test_slots_weakref_base, but use a tuple instead of a string # in the base class. class Base: __slots__ = ('__weakref__',) @dataclass(slots=True) class A(Base): a: int # __weakref__ is in the base class, not A. But an A is still # weakref-able. self.assertIn("__weakref__", Base.__slots__) self.assertNotIn("__weakref__", A.__slots__) a = A(1) weakref.ref(a) def test_weakref_slot_without_slot(self): with self.assertRaisesRegex(TypeError, "weakref_slot is True but slots is False"): @dataclass(weakref_slot=True) class A: a: int def test_weakref_slot_make_dataclass(self): A = make_dataclass('A', [('a', int),], slots=True, weakref_slot=True) self.assertIn("__weakref__", A.__slots__) a = A(1) weakref.ref(a) # And make sure if raises if slots=True is not given. with self.assertRaisesRegex(TypeError, "weakref_slot is True but slots is False"): B = make_dataclass('B', [('a', int),], weakref_slot=True) def test_weakref_slot_subclass_weakref_slot(self): @dataclass(slots=True, weakref_slot=True) class Base: field: int # A *can* also specify weakref_slot=True if it wants to (gh-93521) @dataclass(slots=True, weakref_slot=True) class A(Base): ... # __weakref__ is in the base class, not A. But an instance of A # is still weakref-able. self.assertIn("__weakref__", Base.__slots__) self.assertNotIn("__weakref__", A.__slots__) a = A(1) weakref.ref(a) def test_weakref_slot_subclass_no_weakref_slot(self): @dataclass(slots=True, weakref_slot=True) class Base: field: int @dataclass(slots=True) class A(Base): ... # __weakref__ is in the base class, not A. Even though A doesn't # specify weakref_slot, it should still be weakref-able. self.assertIn("__weakref__", Base.__slots__) self.assertNotIn("__weakref__", A.__slots__) a = A(1) weakref.ref(a) def test_weakref_slot_normal_base_weakref_slot(self): class Base: __slots__ = ('__weakref__',) @dataclass(slots=True, weakref_slot=True) class A(Base): field: int # __weakref__ is in the base class, not A. But an instance of # A is still weakref-able. self.assertIn("__weakref__", Base.__slots__) self.assertNotIn("__weakref__", A.__slots__) a = A(1) weakref.ref(a) class TestDescriptors(unittest.TestCase): def test_set_name(self): # See bpo-33141. # Create a descriptor. class D: def __set_name__(self, owner, name): self.name = name + 'x' def __get__(self, instance, owner): if instance is not None: return 1 return self # This is the case of just normal descriptor behavior, no # dataclass code is involved in initializing the descriptor. @dataclass class C: c: int=D() self.assertEqual(C.c.name, 'cx') # Now test with a default value and init=False, which is the # only time this is really meaningful. If not using # init=False, then the descriptor will be overwritten, anyway. @dataclass class C: c: int=field(default=D(), init=False) self.assertEqual(C.c.name, 'cx') self.assertEqual(C().c, 1) def test_non_descriptor(self): # PEP 487 says __set_name__ should work on non-descriptors. # Create a descriptor. class D: def __set_name__(self, owner, name): self.name = name + 'x' @dataclass class C: c: int=field(default=D(), init=False) self.assertEqual(C.c.name, 'cx') def test_lookup_on_instance(self): # See bpo-33175. class D: pass d = D() # Create an attribute on the instance, not type. d.__set_name__ = Mock() # Make sure d.__set_name__ is not called. @dataclass class C: i: int=field(default=d, init=False) self.assertEqual(d.__set_name__.call_count, 0) def test_lookup_on_class(self): # See bpo-33175. class D: pass D.__set_name__ = Mock() # Make sure D.__set_name__ is called. @dataclass class C: i: int=field(default=D(), init=False) self.assertEqual(D.__set_name__.call_count, 1) def test_init_calls_set(self): class D: pass D.__set__ = Mock() @dataclass class C: i: D = D() # Make sure D.__set__ is called. D.__set__.reset_mock() c = C(5) self.assertEqual(D.__set__.call_count, 1) def test_getting_field_calls_get(self): class D: pass D.__set__ = Mock() D.__get__ = Mock() @dataclass class C: i: D = D() c = C(5) # Make sure D.__get__ is called. D.__get__.reset_mock() value = c.i self.assertEqual(D.__get__.call_count, 1) def test_setting_field_calls_set(self): class D: pass D.__set__ = Mock() @dataclass class C: i: D = D() c = C(5) # Make sure D.__set__ is called. D.__set__.reset_mock() c.i = 10 self.assertEqual(D.__set__.call_count, 1) def test_setting_uninitialized_descriptor_field(self): class D: pass D.__set__ = Mock() @dataclass class C: i: D # D.__set__ is not called because there's no D instance to call it on D.__set__.reset_mock() c = C(5) self.assertEqual(D.__set__.call_count, 0) # D.__set__ still isn't called after setting i to an instance of D # because descriptors don't behave like that when stored as instance vars c.i = D() c.i = 5 self.assertEqual(D.__set__.call_count, 0) def test_default_value(self): class D: def __get__(self, instance: Any, owner: object) -> int: if instance is None: return 100 return instance._x def __set__(self, instance: Any, value: int) -> None: instance._x = value @dataclass class C: i: D = D() c = C() self.assertEqual(c.i, 100) c = C(5) self.assertEqual(c.i, 5) def test_no_default_value(self): class D: def __get__(self, instance: Any, owner: object) -> int: if instance is None: raise AttributeError() return instance._x def __set__(self, instance: Any, value: int) -> None: instance._x = value @dataclass class C: i: D = D() with self.assertRaisesRegex(TypeError, 'missing 1 required positional argument'): c = C() class TestStringAnnotations(unittest.TestCase): def test_classvar(self): # Some expressions recognized as ClassVar really aren't. But # if you're using string annotations, it's not an exact # science. # These tests assume that both "import typing" and "from # typing import *" have been run in this file. for typestr in ('ClassVar[int]', 'ClassVar [int]', ' ClassVar [int]', 'ClassVar', ' ClassVar ', 'typing.ClassVar[int]', 'typing.ClassVar[str]', ' typing.ClassVar[str]', 'typing .ClassVar[str]', 'typing. ClassVar[str]', 'typing.ClassVar [str]', 'typing.ClassVar [ str]', # Not syntactically valid, but these will # be treated as ClassVars. 'typing.ClassVar.[int]', 'typing.ClassVar+', ): with self.subTest(typestr=typestr): @dataclass class C: x: typestr # x is a ClassVar, so C() takes no args. C() # And it won't appear in the class's dict because it doesn't # have a default. self.assertNotIn('x', C.__dict__) def test_isnt_classvar(self): for typestr in ('CV', 't.ClassVar', 't.ClassVar[int]', 'typing..ClassVar[int]', 'Classvar', 'Classvar[int]', 'typing.ClassVarx[int]', 'typong.ClassVar[int]', 'dataclasses.ClassVar[int]', 'typingxClassVar[str]', ): with self.subTest(typestr=typestr): @dataclass class C: x: typestr # x is not a ClassVar, so C() takes one arg. self.assertEqual(C(10).x, 10) def test_initvar(self): # These tests assume that both "import dataclasses" and "from # dataclasses import *" have been run in this file. for typestr in ('InitVar[int]', 'InitVar [int]' ' InitVar [int]', 'InitVar', ' InitVar ', 'dataclasses.InitVar[int]', 'dataclasses.InitVar[str]', ' dataclasses.InitVar[str]', 'dataclasses .InitVar[str]', 'dataclasses. InitVar[str]', 'dataclasses.InitVar [str]', 'dataclasses.InitVar [ str]', # Not syntactically valid, but these will # be treated as InitVars. 'dataclasses.InitVar.[int]', 'dataclasses.InitVar+', ): with self.subTest(typestr=typestr): @dataclass class C: x: typestr # x is an InitVar, so doesn't create a member. with self.assertRaisesRegex(AttributeError, "object has no attribute 'x'"): C(1).x def test_isnt_initvar(self): for typestr in ('IV', 'dc.InitVar', 'xdataclasses.xInitVar', 'typing.xInitVar[int]', ): with self.subTest(typestr=typestr): @dataclass class C: x: typestr # x is not an InitVar, so there will be a member x. self.assertEqual(C(10).x, 10) def test_classvar_module_level_import(self): from test import dataclass_module_1 from test import dataclass_module_1_str from test import dataclass_module_2 from test import dataclass_module_2_str for m in (dataclass_module_1, dataclass_module_1_str, dataclass_module_2, dataclass_module_2_str, ): with self.subTest(m=m): # There's a difference in how the ClassVars are # interpreted when using string annotations or # not. See the imported modules for details. if m.USING_STRINGS: c = m.CV(10) else: c = m.CV() self.assertEqual(c.cv0, 20) # There's a difference in how the InitVars are # interpreted when using string annotations or # not. See the imported modules for details. c = m.IV(0, 1, 2, 3, 4) for field_name in ('iv0', 'iv1', 'iv2', 'iv3'): with self.subTest(field_name=field_name): with self.assertRaisesRegex(AttributeError, f"object has no attribute '{field_name}'"): # Since field_name is an InitVar, it's # not an instance field. getattr(c, field_name) if m.USING_STRINGS: # iv4 is interpreted as a normal field. self.assertIn('not_iv4', c.__dict__) self.assertEqual(c.not_iv4, 4) else: # iv4 is interpreted as an InitVar, so it # won't exist on the instance. self.assertNotIn('not_iv4', c.__dict__) def test_text_annotations(self): from test import dataclass_textanno self.assertEqual( get_type_hints(dataclass_textanno.Bar), {'foo': dataclass_textanno.Foo}) self.assertEqual( get_type_hints(dataclass_textanno.Bar.__init__), {'foo': dataclass_textanno.Foo, 'return': type(None)}) class TestMakeDataclass(unittest.TestCase): def test_simple(self): C = make_dataclass('C', [('x', int), ('y', int, field(default=5))], namespace={'add_one': lambda self: self.x + 1}) c = C(10) self.assertEqual((c.x, c.y), (10, 5)) self.assertEqual(c.add_one(), 11) def test_no_mutate_namespace(self): # Make sure a provided namespace isn't mutated. ns = {} C = make_dataclass('C', [('x', int), ('y', int, field(default=5))], namespace=ns) self.assertEqual(ns, {}) def test_base(self): class Base1: pass class Base2: pass C = make_dataclass('C', [('x', int)], bases=(Base1, Base2)) c = C(2) self.assertIsInstance(c, C) self.assertIsInstance(c, Base1) self.assertIsInstance(c, Base2) def test_base_dataclass(self): @dataclass class Base1: x: int class Base2: pass C = make_dataclass('C', [('y', int)], bases=(Base1, Base2)) with self.assertRaisesRegex(TypeError, 'required positional'): c = C(2) c = C(1, 2) self.assertIsInstance(c, C) self.assertIsInstance(c, Base1) self.assertIsInstance(c, Base2) self.assertEqual((c.x, c.y), (1, 2)) def test_init_var(self): def post_init(self, y): self.x *= y C = make_dataclass('C', [('x', int), ('y', InitVar[int]), ], namespace={'__post_init__': post_init}, ) c = C(2, 3) self.assertEqual(vars(c), {'x': 6}) self.assertEqual(len(fields(c)), 1) def test_class_var(self): C = make_dataclass('C', [('x', int), ('y', ClassVar[int], 10), ('z', ClassVar[int], field(default=20)), ]) c = C(1) self.assertEqual(vars(c), {'x': 1}) self.assertEqual(len(fields(c)), 1) self.assertEqual(C.y, 10) self.assertEqual(C.z, 20) def test_other_params(self): C = make_dataclass('C', [('x', int), ('y', ClassVar[int], 10), ('z', ClassVar[int], field(default=20)), ], init=False) # Make sure we have a repr, but no init. self.assertNotIn('__init__', vars(C)) self.assertIn('__repr__', vars(C)) # Make sure random other params don't work. with self.assertRaisesRegex(TypeError, 'unexpected keyword argument'): C = make_dataclass('C', [], xxinit=False) def test_no_types(self): C = make_dataclass('Point', ['x', 'y', 'z']) c = C(1, 2, 3) self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) self.assertEqual(C.__annotations__, {'x': 'typing.Any', 'y': 'typing.Any', 'z': 'typing.Any'}) C = make_dataclass('Point', ['x', ('y', int), 'z']) c = C(1, 2, 3) self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) self.assertEqual(C.__annotations__, {'x': 'typing.Any', 'y': int, 'z': 'typing.Any'}) def test_invalid_type_specification(self): for bad_field in [(), (1, 2, 3, 4), ]: with self.subTest(bad_field=bad_field): with self.assertRaisesRegex(TypeError, r'Invalid field: '): make_dataclass('C', ['a', bad_field]) # And test for things with no len(). for bad_field in [float, lambda x:x, ]: with self.subTest(bad_field=bad_field): with self.assertRaisesRegex(TypeError, r'has no len\(\)'): make_dataclass('C', ['a', bad_field]) def test_duplicate_field_names(self): for field in ['a', 'ab']: with self.subTest(field=field): with self.assertRaisesRegex(TypeError, 'Field name duplicated'): make_dataclass('C', [field, 'a', field]) def test_keyword_field_names(self): for field in ['for', 'async', 'await', 'as']: with self.subTest(field=field): with self.assertRaisesRegex(TypeError, 'must not be keywords'): make_dataclass('C', ['a', field]) with self.assertRaisesRegex(TypeError, 'must not be keywords'): make_dataclass('C', [field]) with self.assertRaisesRegex(TypeError, 'must not be keywords'): make_dataclass('C', [field, 'a']) def test_non_identifier_field_names(self): for field in ['()', 'x,y', '*', '2@3', '', 'little johnny tables']: with self.subTest(field=field): with self.assertRaisesRegex(TypeError, 'must be valid identifiers'): make_dataclass('C', ['a', field]) with self.assertRaisesRegex(TypeError, 'must be valid identifiers'): make_dataclass('C', [field]) with self.assertRaisesRegex(TypeError, 'must be valid identifiers'): make_dataclass('C', [field, 'a']) def test_underscore_field_names(self): # Unlike namedtuple, it's okay if dataclass field names have # an underscore. make_dataclass('C', ['_', '_a', 'a_a', 'a_']) def test_funny_class_names_names(self): # No reason to prevent weird class names, since # types.new_class allows them. for classname in ['()', 'x,y', '*', '2@3', '']: with self.subTest(classname=classname): C = make_dataclass(classname, ['a', 'b']) self.assertEqual(C.__name__, classname) class TestReplace(unittest.TestCase): def test(self): @dataclass(frozen=True) class C: x: int y: int c = C(1, 2) c1 = replace(c, x=3) self.assertEqual(c1.x, 3) self.assertEqual(c1.y, 2) def test_frozen(self): @dataclass(frozen=True) class C: x: int y: int z: int = field(init=False, default=10) t: int = field(init=False, default=100) c = C(1, 2) c1 = replace(c, x=3) self.assertEqual((c.x, c.y, c.z, c.t), (1, 2, 10, 100)) self.assertEqual((c1.x, c1.y, c1.z, c1.t), (3, 2, 10, 100)) with self.assertRaisesRegex(ValueError, 'init=False'): replace(c, x=3, z=20, t=50) with self.assertRaisesRegex(ValueError, 'init=False'): replace(c, z=20) replace(c, x=3, z=20, t=50) # Make sure the result is still frozen. with self.assertRaisesRegex(FrozenInstanceError, "cannot assign to field 'x'"): c1.x = 3 # Make sure we can't replace an attribute that doesn't exist, # if we're also replacing one that does exist. Test this # here, because setting attributes on frozen instances is # handled slightly differently from non-frozen ones. with self.assertRaisesRegex(TypeError, r"__init__\(\) got an unexpected " "keyword argument 'a'"): c1 = replace(c, x=20, a=5) def test_invalid_field_name(self): @dataclass(frozen=True) class C: x: int y: int c = C(1, 2) with self.assertRaisesRegex(TypeError, r"__init__\(\) got an unexpected " "keyword argument 'z'"): c1 = replace(c, z=3) def test_invalid_object(self): @dataclass(frozen=True) class C: x: int y: int with self.assertRaisesRegex(TypeError, 'dataclass instance'): replace(C, x=3) with self.assertRaisesRegex(TypeError, 'dataclass instance'): replace(0, x=3) def test_no_init(self): @dataclass class C: x: int y: int = field(init=False, default=10) c = C(1) c.y = 20 # Make sure y gets the default value. c1 = replace(c, x=5) self.assertEqual((c1.x, c1.y), (5, 10)) # Trying to replace y is an error. with self.assertRaisesRegex(ValueError, 'init=False'): replace(c, x=2, y=30) with self.assertRaisesRegex(ValueError, 'init=False'): replace(c, y=30) def test_classvar(self): @dataclass class C: x: int y: ClassVar[int] = 1000 c = C(1) d = C(2) self.assertIs(c.y, d.y) self.assertEqual(c.y, 1000) # Trying to replace y is an error: can't replace ClassVars. with self.assertRaisesRegex(TypeError, r"__init__\(\) got an " "unexpected keyword argument 'y'"): replace(c, y=30) replace(c, x=5) def test_initvar_is_specified(self): @dataclass class C: x: int y: InitVar[int] def __post_init__(self, y): self.x *= y c = C(1, 10) self.assertEqual(c.x, 10) with self.assertRaisesRegex(ValueError, r"InitVar 'y' must be " "specified with replace()"): replace(c, x=3) c = replace(c, x=3, y=5) self.assertEqual(c.x, 15) def test_initvar_with_default_value(self): @dataclass class C: x: int y: InitVar[int] = None z: InitVar[int] = 42 def __post_init__(self, y, z): if y is not None: self.x += y if z is not None: self.x += z c = C(x=1, y=10, z=1) self.assertEqual(replace(c), C(x=12)) self.assertEqual(replace(c, y=4), C(x=12, y=4, z=42)) self.assertEqual(replace(c, y=4, z=1), C(x=12, y=4, z=1)) def test_recursive_repr(self): @dataclass class C: f: "C" c = C(None) c.f = c self.assertEqual(repr(c), "TestReplace.test_recursive_repr..C(f=...)") def test_recursive_repr_two_attrs(self): @dataclass class C: f: "C" g: "C" c = C(None, None) c.f = c c.g = c self.assertEqual(repr(c), "TestReplace.test_recursive_repr_two_attrs" "..C(f=..., g=...)") def test_recursive_repr_indirection(self): @dataclass class C: f: "D" @dataclass class D: f: "C" c = C(None) d = D(None) c.f = d d.f = c self.assertEqual(repr(c), "TestReplace.test_recursive_repr_indirection" "..C(f=TestReplace.test_recursive_repr_indirection" "..D(f=...))") def test_recursive_repr_indirection_two(self): @dataclass class C: f: "D" @dataclass class D: f: "E" @dataclass class E: f: "C" c = C(None) d = D(None) e = E(None) c.f = d d.f = e e.f = c self.assertEqual(repr(c), "TestReplace.test_recursive_repr_indirection_two" "..C(f=TestReplace.test_recursive_repr_indirection_two" "..D(f=TestReplace.test_recursive_repr_indirection_two" "..E(f=...)))") def test_recursive_repr_misc_attrs(self): @dataclass class C: f: "C" g: int c = C(None, 1) c.f = c self.assertEqual(repr(c), "TestReplace.test_recursive_repr_misc_attrs" "..C(f=..., g=1)") ## def test_initvar(self): ## @dataclass ## class C: ## x: int ## y: InitVar[int] ## c = C(1, 10) ## d = C(2, 20) ## # In our case, replacing an InitVar is a no-op ## self.assertEqual(c, replace(c, y=5)) ## replace(c, x=5) class TestAbstract(unittest.TestCase): def test_abc_implementation(self): class Ordered(abc.ABC): @abc.abstractmethod def __lt__(self, other): pass @abc.abstractmethod def __le__(self, other): pass @dataclass(order=True) class Date(Ordered): year: int month: 'Month' day: 'int' self.assertFalse(inspect.isabstract(Date)) self.assertGreater(Date(2020,12,25), Date(2020,8,31)) def test_maintain_abc(self): class A(abc.ABC): @abc.abstractmethod def foo(self): pass @dataclass class Date(A): year: int month: 'Month' day: 'int' self.assertTrue(inspect.isabstract(Date)) msg = 'class Date without an implementation for abstract method foo' self.assertRaisesRegex(TypeError, msg, Date) class TestMatchArgs(unittest.TestCase): def test_match_args(self): @dataclass class C: a: int self.assertEqual(C(42).__match_args__, ('a',)) def test_explicit_match_args(self): ma = () @dataclass class C: a: int __match_args__ = ma self.assertIs(C(42).__match_args__, ma) def test_bpo_43764(self): @dataclass(repr=False, eq=False, init=False) class X: a: int b: int c: int self.assertEqual(X.__match_args__, ("a", "b", "c")) def test_match_args_argument(self): @dataclass(match_args=False) class X: a: int self.assertNotIn('__match_args__', X.__dict__) @dataclass(match_args=False) class Y: a: int __match_args__ = ('b',) self.assertEqual(Y.__match_args__, ('b',)) @dataclass(match_args=False) class Z(Y): z: int self.assertEqual(Z.__match_args__, ('b',)) # Ensure parent dataclass __match_args__ is seen, if child class # specifies match_args=False. @dataclass class A: a: int z: int @dataclass(match_args=False) class B(A): b: int self.assertEqual(B.__match_args__, ('a', 'z')) def test_make_dataclasses(self): C = make_dataclass('C', [('x', int), ('y', int)]) self.assertEqual(C.__match_args__, ('x', 'y')) C = make_dataclass('C', [('x', int), ('y', int)], match_args=True) self.assertEqual(C.__match_args__, ('x', 'y')) C = make_dataclass('C', [('x', int), ('y', int)], match_args=False) self.assertNotIn('__match__args__', C.__dict__) C = make_dataclass('C', [('x', int), ('y', int)], namespace={'__match_args__': ('z',)}) self.assertEqual(C.__match_args__, ('z',)) class TestKeywordArgs(unittest.TestCase): def test_no_classvar_kwarg(self): msg = 'field a is a ClassVar but specifies kw_only' with self.assertRaisesRegex(TypeError, msg): @dataclass class A: a: ClassVar[int] = field(kw_only=True) with self.assertRaisesRegex(TypeError, msg): @dataclass class A: a: ClassVar[int] = field(kw_only=False) with self.assertRaisesRegex(TypeError, msg): @dataclass(kw_only=True) class A: a: ClassVar[int] = field(kw_only=False) def test_field_marked_as_kwonly(self): ####################### # Using dataclass(kw_only=True) @dataclass(kw_only=True) class A: a: int self.assertTrue(fields(A)[0].kw_only) @dataclass(kw_only=True) class A: a: int = field(kw_only=True) self.assertTrue(fields(A)[0].kw_only) @dataclass(kw_only=True) class A: a: int = field(kw_only=False) self.assertFalse(fields(A)[0].kw_only) ####################### # Using dataclass(kw_only=False) @dataclass(kw_only=False) class A: a: int self.assertFalse(fields(A)[0].kw_only) @dataclass(kw_only=False) class A: a: int = field(kw_only=True) self.assertTrue(fields(A)[0].kw_only) @dataclass(kw_only=False) class A: a: int = field(kw_only=False) self.assertFalse(fields(A)[0].kw_only) ####################### # Not specifying dataclass(kw_only) @dataclass class A: a: int self.assertFalse(fields(A)[0].kw_only) @dataclass class A: a: int = field(kw_only=True) self.assertTrue(fields(A)[0].kw_only) @dataclass class A: a: int = field(kw_only=False) self.assertFalse(fields(A)[0].kw_only) def test_match_args(self): # kw fields don't show up in __match_args__. @dataclass(kw_only=True) class C: a: int self.assertEqual(C(a=42).__match_args__, ()) @dataclass class C: a: int b: int = field(kw_only=True) self.assertEqual(C(42, b=10).__match_args__, ('a',)) def test_KW_ONLY(self): @dataclass class A: a: int _: KW_ONLY b: int c: int A(3, c=5, b=4) msg = "takes 2 positional arguments but 4 were given" with self.assertRaisesRegex(TypeError, msg): A(3, 4, 5) @dataclass(kw_only=True) class B: a: int _: KW_ONLY b: int c: int B(a=3, b=4, c=5) msg = "takes 1 positional argument but 4 were given" with self.assertRaisesRegex(TypeError, msg): B(3, 4, 5) # Explicitly make a field that follows KW_ONLY be non-keyword-only. @dataclass class C: a: int _: KW_ONLY b: int c: int = field(kw_only=False) c = C(1, 2, b=3) self.assertEqual(c.a, 1) self.assertEqual(c.b, 3) self.assertEqual(c.c, 2) c = C(1, b=3, c=2) self.assertEqual(c.a, 1) self.assertEqual(c.b, 3) self.assertEqual(c.c, 2) c = C(1, b=3, c=2) self.assertEqual(c.a, 1) self.assertEqual(c.b, 3) self.assertEqual(c.c, 2) c = C(c=2, b=3, a=1) self.assertEqual(c.a, 1) self.assertEqual(c.b, 3) self.assertEqual(c.c, 2) def test_KW_ONLY_as_string(self): @dataclass class A: a: int _: 'dataclasses.KW_ONLY' b: int c: int A(3, c=5, b=4) msg = "takes 2 positional arguments but 4 were given" with self.assertRaisesRegex(TypeError, msg): A(3, 4, 5) def test_KW_ONLY_twice(self): msg = "'Y' is KW_ONLY, but KW_ONLY has already been specified" with self.assertRaisesRegex(TypeError, msg): @dataclass class A: a: int X: KW_ONLY Y: KW_ONLY b: int c: int with self.assertRaisesRegex(TypeError, msg): @dataclass class A: a: int X: KW_ONLY b: int Y: KW_ONLY c: int with self.assertRaisesRegex(TypeError, msg): @dataclass class A: a: int X: KW_ONLY b: int c: int Y: KW_ONLY # But this usage is okay, since it's not using KW_ONLY. @dataclass class A: a: int _: KW_ONLY b: int c: int = field(kw_only=True) # And if inheriting, it's okay. @dataclass class A: a: int _: KW_ONLY b: int c: int @dataclass class B(A): _: KW_ONLY d: int # Make sure the error is raised in a derived class. with self.assertRaisesRegex(TypeError, msg): @dataclass class A: a: int _: KW_ONLY b: int c: int @dataclass class B(A): X: KW_ONLY d: int Y: KW_ONLY def test_post_init(self): @dataclass class A: a: int _: KW_ONLY b: InitVar[int] c: int d: InitVar[int] def __post_init__(self, b, d): raise CustomError(f'{b=} {d=}') with self.assertRaisesRegex(CustomError, 'b=3 d=4'): A(1, c=2, b=3, d=4) @dataclass class B: a: int _: KW_ONLY b: InitVar[int] c: int d: InitVar[int] def __post_init__(self, b, d): self.a = b self.c = d b = B(1, c=2, b=3, d=4) self.assertEqual(asdict(b), {'a': 3, 'c': 4}) def test_defaults(self): # For kwargs, make sure we can have defaults after non-defaults. @dataclass class A: a: int = 0 _: KW_ONLY b: int c: int = 1 d: int a = A(d=4, b=3) self.assertEqual(a.a, 0) self.assertEqual(a.b, 3) self.assertEqual(a.c, 1) self.assertEqual(a.d, 4) # Make sure we still check for non-kwarg non-defaults not following # defaults. err_regex = "non-default argument 'z' follows default argument" with self.assertRaisesRegex(TypeError, err_regex): @dataclass class A: a: int = 0 z: int _: KW_ONLY b: int c: int = 1 d: int def test_make_dataclass(self): A = make_dataclass("A", ['a'], kw_only=True) self.assertTrue(fields(A)[0].kw_only) B = make_dataclass("B", ['a', ('b', int, field(kw_only=False))], kw_only=True) self.assertTrue(fields(B)[0].kw_only) self.assertFalse(fields(B)[1].kw_only) if __name__ == '__main__': unittest.main() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/Tools/dump_github_issues.py0000644000175100001770000000716600000000000021162 0ustar00runnerdocker00000000000000""" Dump the GitHub issues of the current project to a file (.json.gz). Usage: python3 Tools/dump_github_issues.py """ import configparser import gzip import json import os.path from datetime import datetime from urllib.request import urlopen GIT_CONFIG_FILE = ".git/config" class RateLimitReached(Exception): pass def gen_urls(repo): i = 0 while True: yield f"https://api.github.com/repos/{repo}/issues?state=all&per_page=100&page={i}" i += 1 def read_rate_limit(): with urlopen("https://api.github.com/rate_limit") as p: return json.load(p) def parse_rate_limit(limits): limits = limits['resources']['core'] return limits['limit'], limits['remaining'], datetime.fromtimestamp(limits['reset']) def load_url(url): with urlopen(url) as p: data = json.load(p) if isinstance(data, dict) and 'rate limit' in data.get('message', ''): raise RateLimitReached() assert isinstance(data, list), type(data) return data or None # None indicates empty last page def join_list_data(lists): result = [] for data in lists: if not data: break result.extend(data) return result def output_filename(repo): timestamp = datetime.now() return f"github_issues_{repo.replace('/', '_')}_{timestamp.strftime('%Y%m%d_%H%M%S')}.json.gz" def write_gzjson(file_name, data, indent=2): with gzip.open(file_name, "wt", encoding='utf-8') as gz: json.dump(data, gz, indent=indent) def find_origin_url(git_config=GIT_CONFIG_FILE): assert os.path.exists(git_config) parser = configparser.ConfigParser() parser.read(git_config) return parser.get('remote "origin"', 'url') def parse_repo_name(git_url): if git_url.endswith('.git'): git_url = git_url[:-4] return '/'.join(git_url.split('/')[-2:]) def dump_issues(repo): """Main entry point.""" print(f"Reading issues from repo '{repo}'") urls = gen_urls(repo) try: paged_data = map(load_url, urls) issues = join_list_data(paged_data) except RateLimitReached: limit, remaining, reset_time = parse_rate_limit(read_rate_limit()) print(f"FAILURE: Rate limits ({limit}) reached, remaining: {remaining}, reset at {reset_time}") return filename = output_filename(repo) print(f"Writing {len(issues)} to {filename}") write_gzjson(filename, issues) ### TESTS def test_join_list_data(): assert join_list_data([]) == [] assert join_list_data([[1,2]]) == [1,2] assert join_list_data([[1,2], [3]]) == [1,2,3] assert join_list_data([[0], [1,2], [3]]) == [0,1,2,3] assert join_list_data([[0], [1,2], [[[]],[]]]) == [0,1,2,[[]],[]] def test_output_filename(): filename = output_filename("re/po") import re assert re.match(r"github_issues_re_po_[0-9]{8}_[0-9]{6}\.json", filename) def test_find_origin_url(): assert find_origin_url() def test_parse_repo_name(): assert parse_repo_name("https://github.com/cython/cython") == "cython/cython" assert parse_repo_name("git+ssh://git@github.com/cython/cython.git") == "cython/cython" assert parse_repo_name("git+ssh://git@github.com/fork/cython.git") == "fork/cython" def test_write_gzjson(): import tempfile with tempfile.NamedTemporaryFile() as tmp: write_gzjson(tmp.name, [{}]) # test JSON format with gzip.open(tmp.name) as f: assert json.load(f) == [{}] # test indentation with gzip.open(tmp.name) as f: assert f.read() == b'[\n {}\n]' ### MAIN if __name__ == '__main__': repo_name = parse_repo_name(find_origin_url()) dump_issues(repo_name) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/Tools/gen_tests_for_posix_pxds.py0000644000175100001770000000175600000000000022400 0ustar00runnerdocker00000000000000#!/usr/bin/python3 from pathlib import Path PROJECT_ROOT = Path(__file__) / "../.." POSIX_PXDS_DIR = PROJECT_ROOT / "Cython/Includes/posix" TEST_PATH = PROJECT_ROOT / "tests/compile/posix_pxds.pyx" def main(): data = [ "# tag: posix\n" "# mode: compile\n" "\n" "# This file is generated by `Tools/gen_tests_for_posix_pxds.py`.\n" "\n" "cimport posix\n" ] filenames = sorted(map(lambda path: path.name, POSIX_PXDS_DIR.iterdir())) for name in filenames: if name == "__init__.pxd": continue if name.endswith(".pxd"): name = name[:-4] else: continue s = ( "cimport posix.{name}\n" "from posix cimport {name}\n" "from posix.{name} cimport *\n" ).format(name=name) data.append(s) with open(TEST_PATH, "w", encoding="utf-8", newline="\n") as f: f.write("\n".join(data)) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/Tools/jedityper.py0000644000175100001770000001024600000000000017250 0ustar00runnerdocker00000000000000""" Inject Cython type declarations into a .py file using the Jedi static analysis tool. """ from __future__ import absolute_import from io import open from collections import defaultdict from itertools import chain import jedi from jedi.parser.tree import Module, ImportName from jedi.evaluate.representation import Function, Instance, Class from jedi.evaluate.iterable import ArrayMixin, GeneratorComprehension from Cython.Utils import open_source_file default_type_map = { 'float': 'double', 'int': 'long', } def analyse(source_path=None, code=None): """ Analyse a Python source code file with Jedi. Returns a mapping from (scope-name, (line, column)) pairs to a name-types mapping. """ if not source_path and code is None: raise ValueError("Either 'source_path' or 'code' is required.") scoped_names = {} statement_iter = jedi.names(source=code, path=source_path, all_scopes=True) for statement in statement_iter: parent = statement.parent() scope = parent._definition evaluator = statement._evaluator # skip function/generator definitions, class definitions, and module imports if any(isinstance(statement._definition, t) for t in [Function, Class, ImportName]): continue key = (None if isinstance(scope, Module) else str(parent.name), scope.start_pos) try: names = scoped_names[key] except KeyError: names = scoped_names[key] = defaultdict(set) position = statement.start_pos if statement.name in names else None for name_type in evaluator.find_types(scope, statement.name, position=position ,search_global=True): if isinstance(name_type, Instance): if isinstance(name_type.base, Class): type_name = 'object' else: type_name = name_type.base.obj.__name__ elif isinstance(name_type, ArrayMixin): type_name = name_type.type elif isinstance(name_type, GeneratorComprehension): type_name = None else: try: type_name = type(name_type.obj).__name__ except AttributeError as error: type_name = None if type_name is not None: names[str(statement.name)].add(type_name) return scoped_names def inject_types(source_path, types, type_map=default_type_map, mode='python'): """ Hack type declarations into source code file. @param mode is currently 'python', which means that the generated type declarations use pure Python syntax. """ col_and_types_by_line = dict( # {line: (column, scope_name or None, [(name, type)])} (k[-1][0], (k[-1][1], k[0], [(n, next(iter(t))) for (n, t) in v.items() if len(t) == 1])) for (k, v) in types.items()) lines = [u'import cython\n'] with open_source_file(source_path) as f: for line_no, line in enumerate(f, 1): if line_no in col_and_types_by_line: col, scope, types = col_and_types_by_line[line_no] if types: types = ', '.join("%s='%s'" % (name, type_map.get(type_name, type_name)) for name, type_name in types) if scope is None: type_decl = u'{indent}cython.declare({types})\n' else: type_decl = u'{indent}@cython.locals({types})\n' lines.append(type_decl.format(indent=' '*col, types=types)) lines.append(line) return lines def main(file_paths=None, overwrite=False): """ Main entry point to process a list of .py files and inject type inferred declarations. """ if file_paths is None: import sys file_paths = sys.argv[1:] for source_path in file_paths: types = analyse(source_path) lines = inject_types(source_path, types) target_path = source_path + ('' if overwrite else '_typed.py') with open(target_path, 'w', encoding='utf8') as f: for line in lines: f.write(line) if __name__ == '__main__': main() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/Tools/kate.diff0000644000175100001770000013302600000000000016457 0ustar00runnerdocker00000000000000# HG changeset patch # User Sturla Molden # Date 1256723843 25200 # Node ID 0a6ce52272f641d58c874fa007187778d4c2c81c # Parent db4133d43a7ee34d4f172aced054785acba65a57 Syntax highlighting for Cython and NumPy for KATE and KDevelop. diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Tools/cython-numpy-mode-kate.xml Wed Oct 28 02:57:23 2009 -0700 @@ -0,0 +1,1133 @@ + + + + + + + + + + + + + + + as + + + cimport + import + from + as + + + DEF + IF + ELIF + ELSE + include + + + class + cpdef + def + + + cdef + ctypedef + + + extern + api + del + global + property + nogil + gil + inline + + + readonly + public + + + and + assert + in + is + by + not + or + sizeof + + + + print + + + break + continue + elif + else + except + finally + for + if + pass + raise + return + try + while + with + + + + __import__ + abs + all + any + apply + basestring + buffer + callable + chr + classmethod + cmp + coerce + compile + delattr + dir + divmod + enumerate + eval + execfile + filter + getattr + + hasattr + hash + hex + id + input + intern + isinstance + issubclass + iter + len + + map + max + min + oct + open + ord + pow + + range + raw_input + reduce + reload + repr + reversed + round + setattr + sorted + staticmethod + sum + super + type + unichr + unicode + + xrange + zip + + + + unsigned + void + enum + double + long + short + char + Py_ssize_t + Py_intptr_t + Py_buffer + bint + struct + union + enum + + + + int + float + object + list + tuple + str + dict + set + frozenset + slice + bool + complex + file + + + + np + numpy + + + numpy + + + cython + + + dtype + flatiter + broadcast + ndarray + int8_t + int16_t + int32_t + int64_t + uint8_t + uint16_t + uint32_t + uint64_t + float32_t + float64_t + complex64_t + complex128_t + int_t + long_t + uint_t + ulong_t + float_t + double_t + longdouble_t + cfloat_t + cdouble_t + clongdouble_t + complex_t + npy_int8 + npy_int16 + npy_int32 + npy_int64 + npy_int96 + npy_int128 + npy_uint8 + npy_uint16 + npy_uint32 + npy_uint64 + npy_uint96 + npy_uint128 + npy_float32 + npy_float64 + npy_float80 + npy_float96 + npy_float128 + npy_complex64 + npy_complex128 + npy_complex120 + npy_complex192 + npy_complex256 + npy_cfloat + npy_cdouble + npy_clongdouble + npy_bool + npy_byte + npy_short + npy_int + npy_long + npy_longlong + npy_ubyte + npy_ushort + npy_uint + npy_ulong + npy_ulonglong + npy_float + npy_double + npy_longdouble + npy_intp + + + DataSource + MachAr + PackageLoader + RankWarning + Tester + abs + absolute + add + add_docstring + add_newdoc + alen + all + allclose + alltrue + alterdot + amax + amin + angle + any + append + apply_along_axis + apply_over_axes + arange + arccos + arccosh + arcsin + arcsinh + arctan + arctan2 + arctanh + argmax + argmin + argsort + argwhere + around + array + array2string + array_equal + array_equiv + array_repr + array_split + array_str + asanyarray + asarray + asarray_chkfinite + ascontiguousarray + asfarray + asfortranarray + asmatrix + asscalar + atleast_1d + atleast_2d + atleast_3d + average + bartlett + base_repr + bench + binary_repr + bincount + bitwise_and + bitwise_not + bitwise_or + bitwise_xor + blackman + bmat + bool + bool8 + bool_ + broadcast + broadcast_arrays + byte + byte_bounds + can_cast + cdouble + ceil + cfloat + character + chararray + choose + clip + clongdouble + clongfloat + column_stack + common_type + compare_chararrays + complex + complex128 + complex192 + complex64 + complex_ + complexfloating + compress + concatenate + conj + conjugate + convolve + copy + corrcoef + correlate + cos + cosh + cov + cross + csingle + cumprod + cumproduct + cumsum + deg2rad + degrees + delete + deprecate + deprecate_with_doc + diag + diagflat + diagonal + diff + digitize + disp + divide + dot + double + dsplit + dstack + dtype + ediff1d + empty + empty_like + equal + errstate + exp + exp2 + expand_dims + expm1 + extract + eye + fabs + fastCopyAndTranspose + find_common_type + finfo + fix + flatiter + flatnonzero + flexible + fliplr + flipud + float + float32 + float64 + float96 + float_ + floating + floor + floor_divide + fmax + fmin + fmod + frexp + frombuffer + fromfile + fromfunction + fromiter + frompyfunc + fromregex + fromstring + fv + generic + genfromtxt + get_array_wrap + get_include + get_numarray_include + get_numpy_include + get_printoptions + getbuffer + getbufsize + geterr + geterrcall + geterrobj + gradient + greater + greater_equal + hamming + hanning + histogram + histogram2d + histogramdd + hsplit + hstack + hypot + i0 + identity + imag + indices + inexact + info + inner + insert + int + int0 + int16 + int32 + int64 + int8 + int_ + int_asbuffer + intc + integer + interp + intersect1d + intersect1d_nu + intp + invert + ipmt + irr + iscomplex + iscomplexobj + isfinite + isfortran + isinf + isnan + isneginf + isposinf + isreal + isrealobj + isscalar + issctype + issubclass_ + issubdtype + issubsctype + iterable + ix_ + kaiser + kron + ldexp + left_shift + less + less_equal + lexsort + linspace + load + loads + loadtxt + log + log10 + log1p + log2 + logaddexp + logaddexp2 + logical_and + logical_not + logical_or + logical_xor + logspace + long + longcomplex + longdouble + longfloat + longlong + lookfor + mafromtxt + mat + matrix + max + maximum + maximum_sctype + may_share_memory + mean + median + memmap + meshgrid + min + minimum + mintypecode + mirr + mod + modf + msort + multiply + nan_to_num + nanargmax + nanargmin + nanmax + nanmin + nansum + ndarray + ndenumerate + ndfromtxt + ndim + ndindex + negative + newbuffer + nonzero + not_equal + nper + npv + number + obj2sctype + object + object0 + object_ + ones + ones_like + outer + packbits + piecewise + pkgload + place + pmt + poly + poly1d + polyadd + polyder + polydiv + polyfit + polyint + polymul + polysub + polyval + power + ppmt + prod + product + ptp + put + putmask + pv + rad2deg + radians + rank + rate + ravel + real + real_if_close + recarray + recfromcsv + recfromtxt + reciprocal + record + remainder + repeat + require + reshape + resize + restoredot + right_shift + rint + roll + rollaxis + roots + rot90 + round + round_ + row_stack + safe_eval + save + savetxt + savez + sctype2char + searchsorted + select + set_numeric_ops + set_printoptions + set_string_function + setbufsize + setdiff1d + seterr + seterrcall + seterrobj + setmember1d + setxor1d + shape + short + show_config + sign + signbit + signedinteger + sin + sinc + single + singlecomplex + sinh + size + sometrue + sort + sort_complex + source + split + sqrt + square + squeeze + std + str + str_ + string0 + string_ + subtract + sum + swapaxes + take + tan + tanh + tensordot + test + tile + trace + transpose + trapz + tri + tril + trim_zeros + triu + true_divide + trunc + typename + ubyte + ufunc + uint + uint0 + uint16 + uint32 + uint64 + uint8 + uintc + uintp + ulonglong + unicode + unicode0 + unicode_ + union1d + unique + unique1d + unpackbits + unravel_index + unsignedinteger + unwrap + ushort + vander + var + vdot + vectorize + void + void0 + vsplit + vstack + where + who + zeros + zeros_like + + + __future__ + __import__ + __name__ + __cythonbufferdefaults__ + __weakref__ + None + self + True + False + NotImplemented + Ellipsis + NULL + + + __new__ + __init__ + __cinit__ + __dealloc__ + __cmp__ + __richcmp__ + __str__ + __repr__ + __hash__ + __call__ + __iter__ + __getattr__ + __setattr__ + __delattr__ + __add__ + __sub__ + __mul__ + __div__ + __floordiv__ + __truediv__ + __mod__ + __divmod__ + __pow__ + __neg__ + __pos__ + __abs__ + __nonzero__ + __invert__ + __lshift__ + __rshift__ + __and__ + __or__ + __xor__ + __int__ + __long__ + __float__ + __oct__ + __hex__ + __index__ + __iadd__ + __isub__ + __imul__ + __idiv__ + __ifloordiv__ + __itruediv__ + __imod__ + __ipow__ + __ilshift__ + __irshift__ + __iand__ + __ior__ + __ixor__ + __len__ + __getitem__ + __setitem__ + __delitem__ + __getslice__ + __setslice__ + __delslice__ + __contains__ + __next__ + __getreadbuffer__ + __getwritebuffer__ + __getsegcount__ + __getcharbuffer__ + __get__ + __set__ + __delete__ + __getbuffer__ + __releasebuffer__ + + + ArithmeticError + AssertionError + AttributeError + BaseException + DeprecationWarning + EnvironmentError + EOFError + Exception + FloatingPointError + FutureWarning + GeneratorExit + IOError + ImportError + ImportWarning + IndexError + KeyError + KeyboardInterrupt + LookupError + MemoryError + NameError + NotImplementedError + OSError + OverflowError + PendingDeprecationWarning + ReferenceError + RuntimeError + RuntimeWarning + StandardError + StopIteration + SyntaxError + SyntaxWarning + SystemError + SystemExit + TypeError + UnboundLocalError + UserWarning + UnicodeError + UnicodeWarning + UnicodeEncodeError + UnicodeDecodeError + UnicodeTranslateError + ValueError + Warning + WindowsError + ZeroDivisionError + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/Tools/make_dataclass_tests.py0000644000175100001770000004400700000000000021431 0ustar00runnerdocker00000000000000# Used to generate tests/run/test_dataclasses.pyx but translating the CPython test suite # dataclass file. Initially run using Python 3.10 - this file is not designed to be # backwards compatible since it will be run manually and infrequently. import ast import os.path import sys unavailable_functions = frozenset( { "dataclass_textanno", # part of CPython test module "dataclass_module_1", # part of CPython test module "make_dataclass", # not implemented in Cython dataclasses (probably won't be implemented) } ) skip_tests = frozenset( { # needs Cython compile # ==================== ("TestCase", "test_field_default_default_factory_error"), ("TestCase", "test_two_fields_one_default"), ("TestCase", "test_overwrite_hash"), ("TestCase", "test_eq_order"), ("TestCase", "test_no_unhashable_default"), ("TestCase", "test_disallowed_mutable_defaults"), ("TestCase", "test_classvar_default_factory"), ("TestCase", "test_field_metadata_mapping"), ("TestFieldNoAnnotation", "test_field_without_annotation"), ( "TestFieldNoAnnotation", "test_field_without_annotation_but_annotation_in_base", ), ( "TestFieldNoAnnotation", "test_field_without_annotation_but_annotation_in_base_not_dataclass", ), ("TestOrdering", "test_overwriting_order"), ("TestHash", "test_hash_rules"), ("TestHash", "test_hash_no_args"), ("TestFrozen", "test_inherit_nonfrozen_from_empty_frozen"), ("TestFrozen", "test_inherit_nonfrozen_from_frozen"), ("TestFrozen", "test_inherit_frozen_from_nonfrozen"), ("TestFrozen", "test_overwriting_frozen"), ("TestSlots", "test_add_slots_when_slots_exists"), ("TestSlots", "test_cant_inherit_from_iterator_slots"), ("TestSlots", "test_weakref_slot_without_slot"), ("TestKeywordArgs", "test_no_classvar_kwarg"), ("TestKeywordArgs", "test_KW_ONLY_twice"), ("TestKeywordArgs", "test_defaults"), # uses local variable in class definition ("TestCase", "test_default_factory"), ("TestCase", "test_default_factory_with_no_init"), ("TestCase", "test_field_default"), ("TestCase", "test_function_annotations"), ("TestDescriptors", "test_lookup_on_instance"), ("TestCase", "test_default_factory_not_called_if_value_given"), ("TestCase", "test_class_attrs"), ("TestCase", "test_hash_field_rules"), ("TestStringAnnotations",), # almost all the texts here use local variables # Currently unsupported # ===================== ( "TestOrdering", "test_functools_total_ordering", ), # combination of cython dataclass and total_ordering ("TestCase", "test_missing_default_factory"), # we're MISSING MISSING ("TestCase", "test_missing_default"), # MISSING ("TestCase", "test_missing_repr"), # MISSING ("TestSlots",), # __slots__ isn't understood ("TestMatchArgs",), ("TestKeywordArgs", "test_field_marked_as_kwonly"), ("TestKeywordArgs", "test_match_args"), ("TestKeywordArgs", "test_KW_ONLY"), ("TestKeywordArgs", "test_KW_ONLY_as_string"), ("TestKeywordArgs", "test_post_init"), ( "TestCase", "test_class_var_frozen", ), # __annotations__ not present on cdef classes https://github.com/cython/cython/issues/4519 ("TestCase", "test_dont_include_other_annotations"), # __annotations__ ("TestDocString",), # don't think cython dataclasses currently set __doc__ # either cython.dataclasses.field or cython.dataclasses.dataclass called directly as functions # (will probably never be supported) ("TestCase", "test_field_repr"), ("TestCase", "test_dynamic_class_creation"), ("TestCase", "test_dynamic_class_creation_using_field"), # Requires inheritance from non-cdef class ("TestCase", "test_is_dataclass_genericalias"), ("TestCase", "test_generic_extending"), ("TestCase", "test_generic_dataclasses"), ("TestCase", "test_generic_dynamic"), ("TestInit", "test_inherit_from_protocol"), ("TestAbstract", "test_abc_implementation"), ("TestAbstract", "test_maintain_abc"), # Requires multiple inheritance from extension types ("TestCase", "test_post_init_not_auto_added"), # Refers to nonlocal from enclosing function ( "TestCase", "test_post_init_staticmethod", ), # TODO replicate the gist of the test elsewhere # PEP487 isn't support in Cython ("TestDescriptors", "test_non_descriptor"), ("TestDescriptors", "test_set_name"), ("TestDescriptors", "test_setting_field_calls_set"), ("TestDescriptors", "test_setting_uninitialized_descriptor_field"), # Looks up __dict__, which cdef classes don't typically have ("TestCase", "test_init_false_no_default"), ("TestCase", "test_init_var_inheritance"), # __dict__ again ("TestCase", "test_base_has_init"), ("TestInit", "test_base_has_init"), # needs __dict__ for vars # Requires arbitrary attributes to be writeable ("TestCase", "test_post_init_super"), ('TestCase', 'test_init_in_order'), # Cython being strict about argument types - expected difference ("TestDescriptors", "test_getting_field_calls_get"), ("TestDescriptors", "test_init_calls_set"), ("TestHash", "test_eq_only"), # I think an expected difference with cdef classes - the property will be in the dict ("TestCase", "test_items_in_dicts"), # These tests are probably fine, but the string substitution in this file doesn't get it right ("TestRepr", "test_repr"), ("TestCase", "test_not_in_repr"), ('TestRepr', 'test_no_repr'), # class variable doesn't exist in Cython so uninitialized variable appears differently - for now this is deliberate ('TestInit', 'test_no_init'), # I believe the test works but the ordering functions do appear in the class dict (and default slot wrappers which # just raise NotImplementedError ('TestOrdering', 'test_no_order'), # not possible to add attributes on extension types ("TestCase", "test_post_init_classmethod"), # Cannot redefine the same field in a base dataclass (tested in dataclass_e6) ("TestCase", "test_field_order"), ( "TestCase", "test_overwrite_fields_in_derived_class", ), # Bugs #====== # not specifically a dataclass issue - a C int crashes classvar ("TestCase", "test_class_var"), ( "TestFrozen", ), # raises AttributeError, not FrozenInstanceError (may be hard to fix) ('TestCase', 'test_post_init'), # Works except for AttributeError instead of FrozenInstanceError ("TestReplace", "test_frozen"), # AttributeError not FrozenInstanceError ( "TestCase", "test_dataclasses_qualnames", ), # doesn't define __setattr__ and just relies on Cython to enforce readonly properties ( "TestCase", "test_field_named_self", ), # I think just an error in inspecting the signature ( "TestCase", "test_init_var_default_factory", ), # should be raising a compile error ("TestCase", "test_init_var_no_default"), # should be raising a compile error ("TestCase", "test_init_var_with_default"), # not sure... ("TestReplace", "test_initvar_with_default_value"), # needs investigating # Maybe bugs? # ========== # non-default argument 'z' follows default argument in dataclass __init__ - this message looks right to me! ("TestCase", "test_class_marker"), # cython.dataclasses.field parameter 'metadata' must be a literal value - possibly not something we can support? ("TestCase", "test_field_metadata_custom_mapping"), ( "TestCase", "test_class_var_default_factory", ), # possibly to do with ClassVar being assigned a field ( "TestCase", "test_class_var_with_default", ), # possibly to do with ClassVar being assigned a field ( "TestDescriptors", ), # mostly don't work - I think this may be a limitation of cdef classes but needs investigating } ) version_specific_skips = { # The version numbers are the first version that the test should be run on ("TestCase", "test_init_var_preserve_type"): ( 3, 10, ), # needs language support for | operator on types } class DataclassInDecorators(ast.NodeVisitor): found = False def visit_Name(self, node): if node.id == "dataclass": self.found = True return self.generic_visit(node) def generic_visit(self, node): if self.found: return # skip return super().generic_visit(node) def dataclass_in_decorators(decorator_list): finder = DataclassInDecorators() for dec in decorator_list: finder.visit(dec) if finder.found: return True return False class SubstituteNameString(ast.NodeTransformer): def __init__(self, substitutions): super().__init__() self.substitutions = substitutions def visit_Constant(self, node): # attempt to handle some difference in class names # (note: requires Python>=3.8) if isinstance(node.value, str): if node.value.find("") != -1: import re new_value = new_value2 = re.sub("[\w.]*", "", node.value) for key, value in self.substitutions.items(): new_value2 = re.sub(f"(? Search for include files in named directory (may be repeated) -o --output-file Specify name of generated C file (only one source file allowed if this is used) -p, --embed-positions If specified, the positions in Cython files of each function definition is embedded in its docstring. -z, --pre-import If specified, assume undeclared names in this module. Emulates the behavior of putting "from import *" at the top of the file. Anything else is taken as the name of a Cython source file and compiled to a C source file. Multiple Cython source files can be specified (unless -o is used), in which case each source file is treated as the source of a distinct extension module and compiled separately to produce its own C file. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.028724 Cython-3.0.8/bin/0000755000175100001770000000000000000000000014344 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/bin/cygdb0000755000175100001770000000017300000000000015363 0ustar00runnerdocker00000000000000#!/usr/bin/env python import sys from Cython.Debugger import Cygdb as cygdb if __name__ == '__main__': cygdb.main() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/bin/cython0000755000175100001770000000017200000000000015576 0ustar00runnerdocker00000000000000#!/usr/bin/env python # # Cython -- Main Program, Unix # from Cython.Compiler.Main import main main(command_line = 1) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/bin/cython-generate-lexicon.py0000755000175100001770000001115300000000000021455 0ustar00runnerdocker00000000000000#!/usr/bin/env python3 # # Updates Cython's Lexicon.py with the unicode characters that are accepted as # identifiers. Should be run with the most recent version of Python possible # to ensure that Lexicon is as complete as possible. # # Python3 only (it relies on str.isidentifier which is a Python 3 addition) # # Run with either # --overwrite to update the existing Lexicon.py file # --here to create a copy of Lexicon.py in the current directory import functools import re import os import sys # Make sure we import the right Cython cythonpath, _ = os.path.split(os.path.realpath(__file__)) # bin directory cythonpath, _ = os.path.split(cythonpath) if os.path.exists(os.path.join(cythonpath, "Cython")): sys.path.insert(0, cythonpath) print("Found (and using) local cython directory") # else we aren't in a development directory from Cython.Compiler import Lexicon def main(): arg = '--overwrite' if len(sys.argv) == 2: arg = sys.argv[1] if len(sys.argv) > 2 or arg not in ['--overwrite','--here']: print("""Call the script with either: --overwrite to update the existing Lexicon.py file (default) --here to create an version of Lexicon.py in the current directory """) return generated_code = ( f"# Generated with 'cython-generate-lexicon.py' based on:\n" f"# {sys.implementation.name} {sys.version.splitlines()[0].strip()}\n" "\n" f"{generate_character_sets()}\n" ) print("Reading file", Lexicon.__file__) with open(Lexicon.__file__, 'r') as f: parts = re.split(r"(# (?:BEGIN|END) GENERATED CODE\n?)", f.read()) if len(parts) not in (4,5) or ' GENERATED CODE' not in parts[1] or ' GENERATED CODE' not in parts[3]: print("Warning: generated code section not found - code not inserted") return parts[2] = generated_code output = "".join(parts) if arg == "--here": outfile = "Lexicon.py" else: assert arg == "--overwrite" outfile = Lexicon.__file__ print("Writing to file", outfile) with open(outfile, 'w') as f: f.write(output) # The easiest way to generate an appropriate character set is just to use the str.isidentifier method # An alternative approach for getting character sets is at https://stackoverflow.com/a/49332214/4657412 @functools.lru_cache() def get_start_characters_as_number(): return [ i for i in range(sys.maxunicode) if str.isidentifier(chr(i)) ] def get_continue_characters_as_number(): return [ i for i in range(sys.maxunicode) if str.isidentifier('a'+chr(i)) ] def get_continue_not_start_as_number(): start = get_start_characters_as_number() cont = get_continue_characters_as_number() assert set(start) <= set(cont), \ "We assume that all identifier start characters are also continuation characters." return sorted(set(cont).difference(start)) def to_ranges(char_num_list): # Convert the large lists of character digits to # list of characters # a list pairs of characters representing closed ranges char_num_list = sorted(char_num_list) first_good_val = char_num_list[0] single_chars = [] ranges = [] for n in range(1, len(char_num_list)): if char_num_list[n]-1 != char_num_list[n-1]: # discontinuous if first_good_val == char_num_list[n-1]: single_chars.append(chr(char_num_list[n-1])) else: ranges.append(chr(first_good_val) + chr(char_num_list[n-1])) first_good_val = char_num_list[n] return ''.join(single_chars), ''.join(ranges) def escape_chars(chars): escapes = [] for char in chars: charval = ord(char) escape = f'\\U{charval:08x}' if charval > 65535 else f'\\u{charval:04x}' escapes.append(escape) return ''.join(escapes) def make_split_strings(chars, splitby=113, indent=" "): splitby //= 10 # max length of "\U..." unicode escapes lines = [f'u"{escape_chars(chars[i:i+splitby])}"' for i in range(0, len(chars), splitby)] return indent + f"\n{indent}".join(lines) def generate_character_sets(): declarations = [] for char_type, char_generator in [ ("unicode_start_ch", get_start_characters_as_number), ("unicode_continuation_ch", get_continue_not_start_as_number), ]: for set_type, chars in zip(("any", "range"), to_ranges(char_generator())): declarations.append( f"{char_type}_{set_type} = (\n" f"{make_split_strings(chars)}\n" f")\n" ) return "".join(declarations) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/bin/cython.bat0000644000175100001770000000040000000000000016332 0ustar00runnerdocker00000000000000@REM Start cython from windows commandline as "cython", not "cython.py". @REM This is especially useful for windows power shell, as no extra window @REM is used. @echo OFF python -c "from Cython.Compiler.Main import main; main(command_line = 1)" %* ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/bin/cython_freeze0000755000175100001770000001752400000000000017147 0ustar00runnerdocker00000000000000#!/usr/bin/env python """ Create a C file for embedding one or more Cython source files. Requires Cython 0.11.2 (or perhaps newer). See Demos/freeze/README.rst for more details. """ from __future__ import print_function import optparse from os.path import splitext, basename usage= '%prog [-o outfile] [-p] module [module ...]' description = 'Create a C file for embedding Cython modules.' p = optparse.OptionParser(usage=usage, description=description) p.add_option('-o', '--output', metavar='FILE', help='write output to FILE instead of standard output') p.add_option('-p', '--pymain', action='store_true', default=False, help='automatically run the first module as __main__ (default: false)') options, args = p.parse_args() if len(args) < 1: p.print_help() p.exit(1) if options.output: import sys old_stdout = sys.stdout sys.stdout = open(options.output, 'w') modules = [basename(splitext(x)[0]).replace('.', '_') for x in args] print("""\ #include #include #include #include #ifdef __FreeBSD__ #include #endif #if PY_MAJOR_VERSION < 3 # define MODINIT(name) init ## name #else # define MODINIT(name) PyInit_ ## name #endif """) for name in modules: print("PyMODINIT_FUNC MODINIT(%s) (void);" % name) print(""" static struct _inittab inittab[] = {""") for name in modules: print(' {"%(name)s", MODINIT(%(name)s)},' % {'name' : name}) print(""" {NULL, NULL} }; """, end=' ') if not options.pymain: print("\nextern int __pyx_module_is_main_%s;" % modules[0]) print(""" #if PY_MAJOR_VERSION < 3 int main(int argc, char** argv) { #elif defined(WIN32) || defined(MS_WINDOWS) int wmain(int argc, wchar_t **argv) { #else static int python_main(int argc, wchar_t **argv) { #endif """, end=' ') if not options.pymain: print("""\ PyObject *m = NULL; int r = 0; """, end=' ') print("""\ /* 754 requires that FP exceptions run in "no stop" mode by default, * and until C vendors implement C99's ways to control FP exceptions, * Python requires non-stop mode. Alas, some platforms enable FP * exceptions by default. Here we disable them. */ #ifdef __FreeBSD__ fp_except_t m; m = fpgetmask(); fpsetmask(m & ~FP_X_OFL); #endif if (PyImport_ExtendInittab(inittab)) { fprintf(stderr, "No memory\\n"); exit(1); } """, end=' ') if options.pymain: print("""\ return Py_Main(argc, argv); } """) else: print("""\ Py_SetProgramName(argv[0]); Py_Initialize(); PySys_SetArgv(argc, argv); __pyx_module_is_main_%(main)s = 1; m = PyImport_ImportModule(inittab[0].name); if (!m) { r = 1; PyErr_Print(); /* This exits with the right code if SystemExit. */ #if PY_MAJOR_VERSION < 3 if (Py_FlushLine()) PyErr_Clear(); #endif } Py_XDECREF(m); Py_Finalize(); return r; } """ % {'main' : modules[0]}, end=' ') print(r""" #if PY_MAJOR_VERSION >= 3 && !defined(WIN32) && !defined(MS_WINDOWS) static wchar_t* char2wchar(char* arg) { wchar_t *res; #ifdef HAVE_BROKEN_MBSTOWCS /* Some platforms have a broken implementation of * mbstowcs which does not count the characters that * would result from conversion. Use an upper bound. */ size_t argsize = strlen(arg); #else size_t argsize = mbstowcs(NULL, arg, 0); #endif size_t count; unsigned char *in; wchar_t *out; #ifdef HAVE_MBRTOWC mbstate_t mbs; #endif if (argsize != (size_t)-1) { res = (wchar_t *)malloc((argsize+1)*sizeof(wchar_t)); if (!res) goto oom; count = mbstowcs(res, arg, argsize+1); if (count != (size_t)-1) { wchar_t *tmp; /* Only use the result if it contains no surrogate characters. */ for (tmp = res; *tmp != 0 && (*tmp < 0xd800 || *tmp > 0xdfff); tmp++) ; if (*tmp == 0) return res; } free(res); } /* Conversion failed. Fall back to escaping with surrogateescape. */ #ifdef HAVE_MBRTOWC /* Try conversion with mbrtwoc (C99), and escape non-decodable bytes. */ /* Overallocate; as multi-byte characters are in the argument, the actual output could use less memory. */ argsize = strlen(arg) + 1; res = malloc(argsize*sizeof(wchar_t)); if (!res) goto oom; in = (unsigned char*)arg; out = res; memset(&mbs, 0, sizeof mbs); while (argsize) { size_t converted = mbrtowc(out, (char*)in, argsize, &mbs); if (converted == 0) /* Reached end of string; null char stored. */ break; if (converted == (size_t)-2) { /* Incomplete character. This should never happen, since we provide everything that we have - unless there is a bug in the C library, or I misunderstood how mbrtowc works. */ fprintf(stderr, "unexpected mbrtowc result -2\n"); return NULL; } if (converted == (size_t)-1) { /* Conversion error. Escape as UTF-8b, and start over in the initial shift state. */ *out++ = 0xdc00 + *in++; argsize--; memset(&mbs, 0, sizeof mbs); continue; } if (*out >= 0xd800 && *out <= 0xdfff) { /* Surrogate character. Escape the original byte sequence with surrogateescape. */ argsize -= converted; while (converted--) *out++ = 0xdc00 + *in++; continue; } /* successfully converted some bytes */ in += converted; argsize -= converted; out++; } #else /* Cannot use C locale for escaping; manually escape as if charset is ASCII (i.e. escape all bytes > 128. This will still roundtrip correctly in the locale's charset, which must be an ASCII superset. */ res = malloc((strlen(arg)+1)*sizeof(wchar_t)); if (!res) goto oom; in = (unsigned char*)arg; out = res; while(*in) if(*in < 128) *out++ = *in++; else *out++ = 0xdc00 + *in++; *out = 0; #endif return res; oom: fprintf(stderr, "out of memory\n"); return NULL; } int main(int argc, char **argv) { wchar_t **argv_copy = (wchar_t **)malloc(sizeof(wchar_t*)*argc); /* We need a second copies, as Python might modify the first one. */ wchar_t **argv_copy2 = (wchar_t **)malloc(sizeof(wchar_t*)*argc); int i, res; char *oldloc; if (!argv_copy || !argv_copy2) { fprintf(stderr, "out of memory\n"); return 1; } oldloc = strdup(setlocale(LC_ALL, NULL)); setlocale(LC_ALL, ""); for (i = 0; i < argc; i++) { argv_copy2[i] = argv_copy[i] = char2wchar(argv[i]); if (!argv_copy[i]) return 1; } setlocale(LC_ALL, oldloc); free(oldloc); res = python_main(argc, argv_copy); for (i = 0; i < argc; i++) { free(argv_copy2[i]); } free(argv_copy); free(argv_copy2); return res; } #endif""") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/bin/cythonize0000755000175100001770000000016300000000000016306 0ustar00runnerdocker00000000000000#!/usr/bin/env python # # command line frontend for cythonize() # from Cython.Build.Cythonize import main main() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/bin/cythonrun0000755000175100001770000000054700000000000016331 0ustar00runnerdocker00000000000000#!/usr/bin/env python """ Compile a Python script into an executable that embeds CPython and run it. Requires CPython to be built as a shared library ('libpythonX.Y'). Basic usage: python cythonrun somefile.py [ARGS] """ from Cython.Build.BuildExecutable import build_and_run if __name__ == '__main__': import sys build_and_run(sys.argv[1:]) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/bin/move-declarators.sed0000644000175100001770000000144700000000000020316 0ustar00runnerdocker00000000000000# Moves # # use: sed [-E | -r] -i -f move-declarators.sed [files] # Arrays # cdef int a[5] -> cdef int[5] a s/^([ \t]*)cdef +([_0-9a-zA-Z. ]+) +([_0-9a-zA-Z]+)((\[[0-9]*\])+)$/\1cdef \2\4 \3/ # Pointers # cdef int a, *b -> cdef int a \n cdef int *b s/^([ \t]*)cdef +([_0-9a-zA-Z. ]+)( +[_0-9a-zA-Z]+ +(=[^()]+)?),( *[*]+ *)([^()]+)/\1cdef \2\3\ \1cdef \2\5\6/ s/^([ \t]*)cdef +([_0-9a-zA-Z. ]+)( +[_0-9a-zA-Z]+ +(=[^()]+)?),( *[*]+ *)([^()]+)/\1cdef \2\3\ \1cdef \2\5\6/ s/^([ \t]*)cdef +([_0-9a-zA-Z. ]+)( +[_0-9a-zA-Z]+ +(=[^()]+)?),( *[*]+ *)([^()]+)/\1cdef \2\3\ \1cdef \2\5\6/ s/^([ \t]*)cdef +([_0-9a-zA-Z. ]+)( +[_0-9a-zA-Z]+ +(=[^()]+)?),( *[*]+ *)([^()]+)/\1cdef \2\3\ \1cdef \2\5\6/ s/^([ \t]*)cdef +([_0-9a-zA-Z. ]+)( +[_0-9a-zA-Z]+ +(=[^()]+)?),( *[*]+ *)([^()]+)/\1cdef \2\3\ \1cdef \2\5\6/ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/bin/pcython0000755000175100001770000000611500000000000015761 0ustar00runnerdocker00000000000000#!/usr/bin/env python """ Script to run Cython with a Python command line. Executes Python code by compiling it in Cython and running the compiled code. """ import sys import subprocess def parse_args(args=None): import optparse # tried argparse, but it doesn't stop at the first (interspersed) positional argument parser = optparse.OptionParser(description='Run a Python command line with Cython') parser.disable_interspersed_args() parser.add_option('-c', metavar='CODE', dest='command', help='program passed in as string') parser.add_option('--python', metavar='PYTHON', dest='python', default=sys.executable, help='Python interpreter to use') parser.add_option('-X', metavar='NAME=VALUE', dest='directives', action='append', help='Compiler directives to set during compilation') parser.add_option('-V', '--version', action='store_true', help='print the Python and Cython version numbers and exit') return parser.parse_args(args) def run_python(python, command): subprocess.check_call([python, '-c', command]) def print_versions(python): """Print version numbers of Python and Cython. """ command = ( "import sys, Cython; " "print('Python {}'.format('.'.join(map(str, sys.version_info[:3])))); " "print('[Cython {}]'.format(Cython.__version__))" ) run_python(python, command) def run_cython_command(python, command, args=None): """Compile and run a Python command string. """ command = ( "import sys; " "from Cython.Build.Inline import cython_inline; " "sys.argv[1:] = {args!r}; " "(lambda: cython_inline({code!r}, quiet=True))()" ).format(code=command, args=list(args) if args else []) run_python(python, command) def run_python_stdin(python, file_args=None, directives=None): """Compile and run a Python program from stdin. """ import shutil import tempfile with tempfile.NamedTemporaryFile(suffix='.py') as f: shutil.copyfileobj(sys.stdin, f) f.flush() file_args = [f.name] + list(file_args or ()) run_python_file(python, file_args, directives) def run_python_file(python, file_args, directives=None): """Compile and run a Python program from a file. """ args = [] if directives: for directive in directives: args.extend(('-X', directive)) args.extend(file_args) command = ( "import Cython.Build.BuildExecutable as bex; " "bex.DEBUG = False; " "bex.build_and_run({args!r})" ).format(args=args) run_python(python, command) def main(): options, args = parse_args() python = options.python if options.version: print_versions(python) return if options.command: run_cython_command(python, options.command, args) if args: if args[0] == '-': run_python_stdin(python, args[1:], options.directives) else: run_python_file(python, args, options.directives) if __name__ == '__main__': main() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/cygdb.py0000755000175100001770000000017300000000000015242 0ustar00runnerdocker00000000000000#!/usr/bin/env python import sys from Cython.Debugger import Cygdb as cygdb if __name__ == '__main__': cygdb.main() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/cython.py0000755000175100001770000000101000000000000015445 0ustar00runnerdocker00000000000000#!/usr/bin/env python # # Cython -- Main Program, generic # if __name__ == '__main__': import os import sys # Make sure we import the right Cython cythonpath, _ = os.path.split(os.path.realpath(__file__)) sys.path.insert(0, cythonpath) from Cython.Compiler.Main import main main(command_line = 1) else: # Void cython.* directives. from Cython.Shadow import * ## and bring in the __version__ from Cython import __version__ from Cython import load_ipython_extension ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/cythonize.py0000755000175100001770000000022200000000000016161 0ustar00runnerdocker00000000000000#!/usr/bin/env python # # Cython -- enhanced main program # if __name__ == '__main__': from Cython.Build.Cythonize import main main() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/doc-requirements.txt0000644000175100001770000000011400000000000017617 0ustar00runnerdocker00000000000000sphinx==4.5.0 sphinx-issues==3.0.1 sphinx-tabs==3.4.0 Jinja2==3.0.3 jupyter ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.028724 Cython-3.0.8/docs/0000755000175100001770000000000000000000000014524 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/.hgignore0000644000175100001770000000007700000000000016333 0ustar00runnerdocker00000000000000syntax: glob *.pyc *~ .*.swp syntax: regexp ^build/ ^_build/ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/CONTRIBUTING.rst0000644000175100001770000000306400000000000017170 0ustar00runnerdocker00000000000000Welcome, and thank you for your interest in contributing! ========================================================= If you are looking for a good way to contribute to the Cython project, please * have a look at the `Cython Hacker Guide `_, especially the section on `getting started `_. * look through the `issues that need help `_. * look through the `issues that are a good entry point for beginners `_. * ask on the `core developers mailing list `_ for guidance. Note that some (but not all) "good first issue"s also require an understanding of C and a bit of the CPython C-API – usually those that also have the ``Code Generation`` label. We generally consider a ticket a "good first issue" if it has a limited scope that new contributors will have to learn about, e.g. only needs changes to the parser, the type analysis or the code generation, but does not require changes all across the compiler pipeline. If you have code that you want to contribute, please make sure that it * includes tests in the ``tests/`` directory (see the `Hacker Guide on Testing `_) * comes in form of a pull request We use `github actions `_ for cross-platform testing, including pull requests. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/Makefile0000644000175100001770000001307700000000000016174 0ustar00runnerdocker00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = a4 BUILDDIR = build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean pdf html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* pdf: $(SPHINXBUILD) -b pdf $(ALLSPHINXOPTS) $(BUILDDIR)/pdf @echo @echo "Build finished. The PDF is in $(BUILDDIR)/pdf." html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Cython.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Cython.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/Cython" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Cython" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/README.md0000644000175100001770000000176000000000000016007 0ustar00runnerdocker00000000000000# Welcome to Cython's documentation The current Cython documentation is hosted at [cython.readthedocs.io](https://cython.readthedocs.io/) The main documentation files are located in the `cython/docs/src` folder and the code that is used in those documents is located in the `cython/docs/examples` Before building, you need to install `doc-requirements.txt` (and `make` on Linux). To install `doc-requirements.txt` run in the root folder ```shell pip install -r doc-requirements.txt ``` To build the documentation go into `docs` folder and run ```shell make html ``` You can then see the documentation by opening `cython/docs/build/html/index.html` in a browser. Generally follow the structure of the existing documents. If you are creating a (sub)section add a link for it in the TOC of the page.
Notes 1) Some css work should definitely be done. 2) Use local 'top-of-page' contents rather than the sidebar, imo. 3) Fix cython highlighter for cdef blocks
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/TODO0000644000175100001770000000206200000000000015214 0ustar00runnerdocker00000000000000Background ---------- [brain dump] The "Old Cython Users Guide" is a derivative of the old Pyrex documentation. It underwent substantial editing by Peter Alexandar to become the Reference Guide, which is oriented around bullet points and lists rather than prose. This transition was incomplete. At nearly the same time, Robert, Dag, and Stefan wrote a tutorial as part of the SciPy proceedings. It was felt that the content there was cleaner and more up to date than anything else, and this became the basis for the "Getting Started" and "Tutorials" sections. However, it simply doesn't have as much content as the old documentation used to. Eventually, it seems all of the old users manual could be whittled down into independent tutorial topics. Much discussion of what we'd like to see is at https://www.mail-archive.com/cython-dev@codespeak.net/msg06945.html There is currently a huge amount of redundancy, but no one section has it all. Also, we should go through the wiki enhancement proposal list and make sure to transfer the (done) ones into the user manual. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.028724 Cython-3.0.8/docs/_static/0000755000175100001770000000000000000000000016152 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.028724 Cython-3.0.8/docs/_static/css/0000755000175100001770000000000000000000000016742 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/_static/css/tabs.css0000644000175100001770000000225400000000000020410 0ustar00runnerdocker00000000000000.sphinx-tabs { margin-bottom: 1rem; } [role="tablist"] { border-bottom: 0px solid #a0b3bf; } .sphinx-tabs-tab { position: relative; font-family: 'Helvetica Neue',Arial,Helvetica,sans-serif; color: black; line-height: 24px; margin: 0; font-size: 16px; font-weight: 400; background-color: rgba(255, 255, 255, 0); border-radius: 5px 5px 5px 5px; border: 0; padding: 0.5rem 1.6rem; margin-bottom: 0; } .sphinx-tabs-tab[aria-selected="true"] { border: 2px solid gray; border-bottom: 2px solid gray; margin: -2px; background-color: #efefef; z-index: 999; /* render on top*/ } .sphinx-tabs-tab[aria-selected="false"] { border: 2px solid #dddddd; border-bottom: 2px solid #dddddd; margin: -2px; background-color: white; } .sphinx-tabs-tab:focus { z-index: 1; outline-offset: 1px; } .sphinx-tabs-panel { position: relative; padding: 0rem; border: 0px solid #a0b3bf; margin: 0px 0px 0px 0px; border-radius: 0 0 5px 5px; border-top: 0; background: white; } .sphinx-tabs-panel.code-tab { padding: 0.4rem; } .sphinx-tab img { margin-bottom: 24 px; } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/_static/cython-logo-C.svg0000644000175100001770000002742000000000000021322 0ustar00runnerdocker00000000000000 image/svg+xml ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/_static/cython-logo-light.png0000644000175100001770000001011700000000000022227 0ustar00runnerdocker00000000000000PNG  IHDR@xsBIT|d pHYstEXtSoftwarewww.inkscape.org<IDATx tTY+V+V[a !$leBK&,B,@$%!{B;sgrg2˛dHO˛w߼r}!3( ʄN@-2@*( yAq=˲h#t:@tYOBgvB5{@pL 4j"wc:3_cKhyxsR1O0󫓁cNN998Bsa B'@7kءt; -B` 5  &Cq>@ʂ;zY? krH5J Mܱ0YSm5Etch`GQ|-&*C7@Z$9*4l} !%p':K͉2vA[Ϻ"h{ DN7// Gw,j#>hP\V{El(Œ8ŢĠ2><qOjOj]wëJD"D_B|#׾>$ Zk,dK/yXr]E #~D&}$^svۉǬmfm"1pB0`Xy=ZkH"M0aܢ.دg>'MRx)mƖ;3"1:qO92[]_'JigGC(nR568ZKc}USxT:xviᙩuZ2讏JL@͡j[ZRRB'ҥ$*֐:*Hm(diNbq6 Zt]t ᧁgfI%Q9x6kL$=#6׈u94>`bHi`Ԇ`}5N<;4x̢3qH =l . dQ×dkx#]UmD&iᙺtrBv SdKC1]c2b2TTa'̋ꣴ0a[qi٤ۤ2@nn+@W}M4/ɞXQ} 򛟮<*8*;U}Pyٮڪ)J&݀]v9LdC&EYZmF̼8URH'(LckN#.4:g2HHBAc{@5 2/XNܔ_5@5Uhj4&Koyԭ0?,;$=]Nk!qGiYM "9\ ׵5Gh|kRpE$juO(ф\qL&k5G]gwacҩ=tFBHw}zkApW*xHuӼHWIeS:II8ou;RX8t{X3+י˝)PsFːJ/WH-?pO;djuQOH?grw4k"+xn dQ(ZY uz5xd; |RL7*S?pe[΄ iJ6U;tR2s93Tkury ԏP.Sg~e>\nnE"{" &&` 8z3Y7B.  /⎯vj ߇Ous폳2TD$LCdIĪkO0 xק!DK\[{%tku*D' _IyZUrda@9 eǬNx|9^ 7w,:X#t@Z&3uks23?dPb(S~:!RCyoBy`KВ;U Y%29 Ύ2:>Pp ^ #*_Gl7F`VMŰ@&ET#xjqq+?'R+pdu=2wL8U9Wt@/׎~ [j-T.3:Lˣp5y]':JzbreV(H.U__AS@U:kK%u:F9@.9ՔObS;;bNt'A%7V6IiQkryp"e_",((V'C' h]s?.օ]躔5*VG(oQdQ>Sa6py_*F Z@IU 8ʥwz_bT5>9Ԍ ?mQ4FOQ}k;{zN{㟤Sx0cGf(pe#Ϟw륵>uͥ{dDP@9VђZeuj>oQư>t85*DXϳy.[L,c~(u%dM=}ZHc^$(q/fjbbS  Z=˝$q3V;ۚuLRNc@z-}d=H`'u6QC}2 WmM%ۀMZΐ;1N,&1K/5/eWz Lt,4m칅oV*bk($[Tl@qΣ:.IENDB`././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/_static/cython-logo.svg0000644000175100001770000003767000000000000021152 0ustar00runnerdocker00000000000000 image/svg+xml ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/_static/cythonlogo.png0000644000175100001770000001014100000000000021042 0ustar00runnerdocker00000000000000PNG  IHDR@毾csRGB pHYs  tIME ,c$bKGDIDATxy|9+ HVW6m@@8lB6DK Q*G8rB8B@?O R#BP ZPEfw6ݼdM˛w/<36#4s&N4JޅrbT  P*4~kVTO~EAPD~Zi&+:DGh4Xi04-%HҸ`hZnRghlb.@JC7"hX]hm6HзlpڝAj(zjzBC)P:JǔFo {{ERf;C+w QF, ҠXآC!9E;8`h}*xmΡ l`]4 Jd4@MO@ . }Co_w#'}PLL̐ &dA>M0<_Q JK:ƪd[vԢA];l_闲}Vfz} /J74TM 0F^eu _|0|q=բd6/\$8u7\$$ e8{KJ|YOxSf8`0ŀe79pϱa~W{ (\K*$sv)\<5c ϙ9q2T-0T4݃$,$42?%J1Ud7 p%R6QȀ뉇.Tf} UNvփUcy(p`Sir11¥7L#\r)`7V2k uPGg$ZdެV{ÇD|/E,.W-,%a A `]3 p$) |⛸kl/>xƯy!?P<(q#Gr+,jr}mpjg+ Q G|xh(5> v I׎ pm6+!uϔ5lX#l\_:RQHjqbMPj&HOU\?7 4>[4:b4µ~֒ޓW+56pm Gn;|~Q=,>b}"}B=éަUEINt•W #` reޠAh+!HfeT%wg mSY|_(0|MSp4|ǿΙj4(;ciC{:a6: ]n@dǘD$˓ [rw7#}X##\5pfU iU!Sϐj…FytOhʣL42+KJ d+H2ˣ.۹̄OakS%f,QAQzu.So%E*a1:qK ;RP7g!;Fl 0npjeAk1jVPstПߌJ{]$f@ulQOs Z09#aND:$r4AGԩ2`KI|9cIK'?iw3U:*-er-хM6˸GEn5#%:FekQ)1 GሄpfpQUg'Wt՚LR |Mȅ1[`8gj֌6W\c-γo Z@g2Leo#A:pZM` GxGUʸ@iu\V p_^7dN9hz vf9\bAZ=D &?1~@gGL`KfGN` Gԅ dpK4YqjR:!_%r$|L]*ϗ1?`UG.وHp:pώvUÉK$cՊ6ZрIȹ`)XT{#|;> n 9`%%5NpķCSW9F彴ʤ4v]Q ]nChZKժ@<\ʿ j Qŝ#I7?~\" ;,>=s| lItlbBGrY 5\9iZ#9; LHyxJ`9\]o nP9wpVȻ:VJLa,僦,`őZjr&pNNj"鹺Vػ|j0ugܓn/1`fDr5a8 # Ŷ&Ka\k !T&]2W] V+I636U Lb.< PG5sGj fV+ \˻`4P٘^ak* %N8(1n`AֻD>"&fޖ~ǡ_Z̖r u~A5ݐi-]z ꚙDVVSl޼ zrʕ:iiiP袢YuTz"AdalS3wik4ɞڱcG~EEE}v3//9 u:u?}R歔Fo1SҌ111R@166vVq;ʦfԳ.{؍0.re=> 5OaƁ4[~ECaJ7r8Оgy 4E`96h{N)&wY-6H7@D%]bitylb'g?cmbԳCJ5:S )IENDB`././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/_static/favicon.ico0000644000175100001770000000217600000000000020301 0ustar00runnerdocker00000000000000 h(  ddddddKdddddddddddddddddddddddd ddddddddddddeeejjjkkkfffdddddddddddddddddd dddddddddddd^ eeeddddddddddddddddddddddddddddddoQ?F=;;dddddddddddddddIdddWdddddddddddd]TIA;fddddddddddddx<;s8mcYND<;dddddddddddd`~@ͨw;vph]QF?|ddddddddddddMD}?Oˋ~aVMddddddddddddSHɴD|?u:o5j1e\yddddddddddddoJ-GB{>t9n4tpiddd{dddddddddGAz=t8o4fddd ddd!ddd!dddddddddddddddddd6JNFAʩxddddddddddddAddd dddddddddddddddddd9ddddddddddddddddddddddddddddddddddddddd dddnddddddddddddddddddddddddDdddddddddddd%dddddd/??././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.028724 Cython-3.0.8/docs/_templates/0000755000175100001770000000000000000000000016661 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/_templates/layout.html0000644000175100001770000000255600000000000021074 0ustar00runnerdocker00000000000000{% extends "!layout.html" %} {% block header %} {%- if development %}
{% trans %}This version of the documentation is for the latest and greatest in-development branch of Cython. For the last release version, see {% endtrans %} {% trans %}here{% endtrans %}.
{%- endif %} {% endblock %} {% block relbar1 %} {{ super() }} {% if pagename != "src/donating" %}

🤝 Like the tool? Help making it better! Your donation helps! 🤝

{% endif %} {% endblock %} {% block footer %} {{ super() }} {# ## Removed to avoid tracking our users. #} {% endblock %} ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/conf.py0000644000175100001770000003423000000000000016025 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*- # # Cython documentation build configuration file, created by # sphinx-quickstart on Sun Jun 29 13:36:38 2014. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os, os.path, re import itertools import datetime YEAR = datetime.date.today().strftime('%Y') # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('..')) # -- General configuration ----------------------------------------------------- # Use cython as the default syntax highlighting language, as python is a subset # this does the right thing highlight_language = 'cython' # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ 'sphinx.ext.imgmath', 'sphinx.ext.todo', 'sphinx.ext.intersphinx', 'sphinx.ext.autodoc', 'sphinx_issues', # if this is missing, pip install sphinx-issues 'sphinx_tabs.tabs', # if this is missing, pip install sphinx-tabs ] try: import rst2pdf except ImportError: pass else: extensions.append('rst2pdf.pdfbuilder') # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = 'Cython' authors = 'Stefan Behnel, Robert Bradshaw, Dag Sverre Seljebotn, Greg Ewing, William Stein, Gabriel Gellner, et al.' copyright = '%s, %s' % (YEAR, authors) # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The full version, including alpha/beta/rc tags. release = '0.15' try: _match_version = re.compile(r'^\s*_*version\s*_*\s*=\s*["\']([^"\']+)["\'].*').match with open(os.path.join(os.path.dirname(__file__), '..', 'Cython', 'Shadow.py')) as _f: for line in itertools.islice(_f, 5): # assume version comes early enough _m = _match_version(line) if _m: release = _m.group(1) break else: print("FAILED TO PARSE PROJECT VERSION !") except: pass # The short X.Y version. version = re.sub('^([0-9]+[.][0-9]+).*', '\g<1>', release) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['py*', 'build', 'BUILD', 'TEST_TMP'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # todo todo_include_todos = True # intersphinx for standard :keyword:s (def, for, etc.) intersphinx_mapping = {'python': ('https://docs.python.org/3/', None)} # If true, keep warnings as "system message" paragraphs in the built documents. #keep_warnings = False # The output image format. The default is 'png'. It should be either 'png' or 'svg'. imgmath_image_format = "svg" # For sphinx-issues issues_github_path = "cython/cython" # For sphinx-tabs sphinx_tabs_disable_tab_closing = True # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'default' try: import sphinx if os.path.isdir(os.path.join(os.path.dirname(sphinx.__file__), 'themes', 'nature')): html_theme = 'nature' except (ImportError, AttributeError): pass # use default theme # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. html_logo = "_static/cythonlogo.png" # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. html_favicon = "_static/favicon.ico" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] html_css_files = ['css/tabs.css'] html_context = { # "dev version" warning banner 'development': 'a' in release or 'b' in release, } # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. html_domain_indices = False # If false, no index is generated. html_use_index = False # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'Cythondoc' # -- Options for LaTeX output -------------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). _stdauthor = r'Stefan Behnel, Robert Bradshaw, William Stein\\ Gary Furnish, Dag Seljebotn, Greg Ewing\\ Gabriel Gellner, editor' latex_documents = [ ('src/reference/index', 'reference.tex', 'Cython Reference Guide', _stdauthor, 'manual'), ('src/tutorial/index', 'tutorial.tex', 'Cython Tutorial', _stdauthor, 'manual') ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'cython', u'Cython Documentation', [authors], 1) ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------------ # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'Cython', u'Cython Documentation', authors, 'Cython', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. #texinfo_no_detailmenu = False # -- Options for Epub output --------------------------------------------------- # Bibliographic Dublin Core info. epub_title = u'Cython' epub_author = authors epub_publisher = u'' epub_copyright = copyright # The language of the text. It defaults to the language option # or en if the language is not set. #epub_language = '' # The scheme of the identifier. Typical schemes are ISBN or URL. #epub_scheme = '' # The unique identifier of the text. This can be a ISBN number # or the project homepage. #epub_identifier = '' # A unique identification for the text. #epub_uid = '' # A tuple containing the cover image and cover page html template filenames. #epub_cover = () # A sequence of (type, uri, title) tuples for the guide element of content.opf. #epub_guide = () # HTML files that should be inserted before the pages created by sphinx. # The format is a list of tuples containing the path and title. #epub_pre_files = [] # HTML files that should be inserted after the pages created by sphinx. # The format is a list of tuples containing the path and title. #epub_post_files = [] # A list of files that should not be packed into the epub file. #epub_exclude_files = [] # The depth of the table of contents in toc.ncx. #epub_tocdepth = 3 # Allow duplicate toc entries. #epub_tocdup = True # Fix unsupported image types using the PIL. #epub_fix_images = False # Scale large images. #epub_max_image_width = 0 # If 'no', URL addresses will not be shown. #epub_show_urls = 'inline' # If false, no index is generated. #epub_use_index = True # -- Options for PDF output -------------------------------------------------- # Grouping the document tree into PDF files. List of tuples # (source start file, target name, title, author, options). # # If there is more than one author, separate them with \\. # For example: r'Guido van Rossum\\Fred L. Drake, Jr., editor' # # The options element is a dictionary that lets you override # this config per-document. # For example, # ('index', u'MyProject', u'My Project', u'Author Name', # dict(pdf_compressed = True)) # would mean that specific document would be compressed # regardless of the global pdf_compressed setting. pdf_documents = [ ('index', project, project, authors.replace(', ', '\\\\')), ] # A comma-separated list of custom stylesheets. Example: pdf_stylesheets = ['sphinx','kerning','a4'] # A list of folders to search for stylesheets. Example: pdf_style_path = ['.', '_styles'] # Create a compressed PDF # Use True/False or 1/0 # Example: compressed=True pdf_compressed = True # A colon-separated list of folders to search for fonts. Example: # pdf_font_path = ['/usr/share/fonts', '/usr/share/texmf-dist/fonts/'] # Language to be used for hyphenation support #pdf_language = "en_US" # Mode for literal blocks wider than the frame. Can be # overflow, shrink or truncate pdf_fit_mode = "shrink" # Section level that forces a break page. # For example: 1 means top-level sections start in a new page # 0 means disabled #pdf_break_level = 0 # When a section starts in a new page, force it to be 'even', 'odd', # or just use 'any' #pdf_breakside = 'any' # Insert footnotes where they are defined instead of # at the end. #pdf_inline_footnotes = True # verbosity level. 0 1 or 2 #pdf_verbosity = 0 # If false, no index is generated. pdf_use_index = False # If false, no modindex is generated. pdf_use_modindex = False # If false, no coverpage is generated. #pdf_use_coverpage = True # Name of the cover page template to use #pdf_cover_template = 'sphinxcover.tmpl' # Documents to append as an appendix to all manuals. #pdf_appendices = [] # Enable experimental feature to split table cells. Use it # if you get "DelayedTable too big" errors #pdf_splittables = False # Set the default DPI for images #pdf_default_dpi = 72 # Enable rst2pdf extension modules (default is only vectorpdf) # you need vectorpdf if you want to use sphinx's graphviz support #pdf_extensions = ['vectorpdf'] # Page template name for "regular" pages #pdf_page_template = 'cutePage' # Show Table Of Contents at the beginning? pdf_use_toc = False # How many levels deep should the table of contents be? pdf_toc_depth = 9999 # Add section number to section references pdf_use_numbered_links = False # Background images fitting mode pdf_fit_background_mode = 'scale' ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.028724 Cython-3.0.8/docs/examples/0000755000175100001770000000000000000000000016342 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/Cython Magics.ipynb0000644000175100001770000002357300000000000022047 0ustar00runnerdocker00000000000000{ "metadata": { "name": "Cython Magics", "signature": "sha256:c357b93e9480d6347c6677862bf43750745cef4b30129c5bc53cb879a19d4074" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "Cython Magic Functions" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Loading the extension" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cython has an IPython extension that contains a number of magic functions for working with Cython code. This extension can be loaded using the `%load_ext` magic as follows:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%load_ext cython" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "The %cython_inline magic" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `%%cython_inline` magic uses `Cython.inline` to compile a Cython expression. This allows you to enter and run a function body with Cython code. Use a bare `return` statement to return values. " ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = 10\n", "b = 20" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 2 }, { "cell_type": "code", "collapsed": false, "input": [ "%%cython_inline\n", "return a+b" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 3, "text": [ "30" ] } ], "prompt_number": 3 }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "The %cython_pyximport magic" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `%%cython_pyximport` magic allows you to enter arbitrary Cython code into a cell. That Cython code is written as a `.pyx` file in the current working directory and then imported using `pyximport`. You have the specify the name of the module that the Code will appear in. All symbols from the module are imported automatically by the magic function." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%cython_pyximport foo\n", "def f(x):\n", " return 4.0*x" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 4 }, { "cell_type": "code", "collapsed": false, "input": [ "f(10)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 5, "text": [ "40.0" ] } ], "prompt_number": 5 }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "The %cython magic" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Probably the most important magic is the `%cython` magic. This is similar to the `%%cython_pyximport` magic, but doesn't require you to specify a module name. Instead, the `%%cython` magic uses manages everything using temporary files in the `~/.cython/magic` directory. All of the symbols in the Cython module are imported automatically by the magic.\n", "\n", "Here is a simple example of a Black-Scholes options pricing algorithm written in Cython. Please note that this example might not compile on non-POSIX systems (e.g., Windows) because of a missing `erf` symbol." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%cython\n", "cimport cython\n", "from libc.math cimport exp, sqrt, pow, log, erf\n", "\n", "@cython.cdivision(True)\n", "cdef double std_norm_cdf_cy(double x) nogil:\n", " return 0.5*(1+erf(x/sqrt(2.0)))\n", "\n", "@cython.cdivision(True)\n", "def black_scholes_cy(double s, double k, double t, double v,\n", " double rf, double div, double cp):\n", " \"\"\"Price an option using the Black-Scholes model.\n", " \n", " s : initial stock price\n", " k : strike price\n", " t : expiration time\n", " v : volatility\n", " rf : risk-free rate\n", " div : dividend\n", " cp : +1/-1 for call/put\n", " \"\"\"\n", " cdef double d1, d2, optprice\n", " with nogil:\n", " d1 = (log(s/k)+(rf-div+0.5*pow(v,2))*t)/(v*sqrt(t))\n", " d2 = d1 - v*sqrt(t)\n", " optprice = cp*s*exp(-div*t)*std_norm_cdf_cy(cp*d1) - \\\n", " cp*k*exp(-rf*t)*std_norm_cdf_cy(cp*d2)\n", " return optprice" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 6 }, { "cell_type": "code", "collapsed": false, "input": [ "black_scholes_cy(100.0, 100.0, 1.0, 0.3, 0.03, 0.0, -1)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 7, "text": [ "10.327861752731728" ] } ], "prompt_number": 7 }, { "cell_type": "markdown", "metadata": {}, "source": [ "For comparison, the same code is implemented here in pure python." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from math import exp, sqrt, pow, log, erf\n", "\n", "def std_norm_cdf_py(x):\n", " return 0.5*(1+erf(x/sqrt(2.0)))\n", "\n", "def black_scholes_py(s, k, t, v, rf, div, cp):\n", " \"\"\"Price an option using the Black-Scholes model.\n", " \n", " s : initial stock price\n", " k : strike price\n", " t : expiration time\n", " v : volatility\n", " rf : risk-free rate\n", " div : dividend\n", " cp : +1/-1 for call/put\n", " \"\"\"\n", " d1 = (log(s/k)+(rf-div+0.5*pow(v,2))*t)/(v*sqrt(t))\n", " d2 = d1 - v*sqrt(t)\n", " optprice = cp*s*exp(-div*t)*std_norm_cdf_py(cp*d1) - \\\n", " cp*k*exp(-rf*t)*std_norm_cdf_py(cp*d2)\n", " return optprice" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 8 }, { "cell_type": "code", "collapsed": false, "input": [ "black_scholes_py(100.0, 100.0, 1.0, 0.3, 0.03, 0.0, -1)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 9, "text": [ "10.327861752731728" ] } ], "prompt_number": 9 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Below we see the runtime of the two functions: the Cython version is nearly a factor of 10 faster." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%timeit black_scholes_cy(100.0, 100.0, 1.0, 0.3, 0.03, 0.0, -1)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "1000000 loops, best of 3: 319 ns per loop\n" ] } ], "prompt_number": 10 }, { "cell_type": "code", "collapsed": false, "input": [ "%timeit black_scholes_py(100.0, 100.0, 1.0, 0.3, 0.03, 0.0, -1)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "100000 loops, best of 3: 2.28 \u00b5s per loop\n" ] } ], "prompt_number": 11 }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "External libraries" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cython allows you to specify additional libraries to be linked with your extension, you can do so with the `-l` flag (also spelled `--lib`). Note that this flag can be passed more than once to specify multiple libraries, such as `-lm -llib2 --lib lib3`. Here's a simple example of how to access the system math library:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%cython -lm\n", "from libc.math cimport sin\n", "print 'sin(1)=', sin(1)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "sin(1)= 0.841470984808\n" ] } ], "prompt_number": 12 }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can similarly use the `-I/--include` flag to add include directories to the search path, and `-c/--compile-args` to add extra flags that are passed to Cython via the `extra_compile_args` of the distutils `Extension` class. Please see [the Cython docs on C library usage](https://docs.cython.org/src/tutorial/clibraries.html) for more details on the use of these flags." ] } ], "metadata": {} } ] } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/README.rst0000644000175100001770000000033000000000000020025 0ustar00runnerdocker00000000000000:orphan: This example directory is organized like the ``Cython/docs/src/`` directory, with one directory per ``.rst`` file. All files in this directory are tested in the :file:`runtests.py` with the mode `compile`. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880490.976724 Cython-3.0.8/docs/examples/not_in_docs/0000755000175100001770000000000000000000000020640 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.028724 Cython-3.0.8/docs/examples/not_in_docs/great_circle/0000755000175100001770000000000000000000000023263 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/not_in_docs/great_circle/c1.pyx0000644000175100001770000000043600000000000024333 0ustar00runnerdocker00000000000000import math def great_circle(lon1, lat1, lon2, lat2): radius = 3956 # miles x = math.pi/180.0 a = (90.0 - lat1)*x b = (90.0 - lat2)*x theta = (lon2 - lon1)*x c = math.acos(math.cos(a)*math.cos(b) + math.sin(a)*math.sin(b)*math.cos(theta)) return radius*c ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/not_in_docs/great_circle/c2.pyx0000644000175100001770000000056100000000000024333 0ustar00runnerdocker00000000000000import math def great_circle(double lon1, double lat1, double lon2, double lat2): cdef double radius = 3956 # miles cdef double x = math.pi/180.0 cdef double a, b, theta, c a = (90.0 - lat1)*x b = (90.0 - lat2)*x theta = (lon2 - lon1)*x c = math.acos(math.cos(a)*math.cos(b) + math.sin(a)*math.sin(b)*math.cos(theta)) return radius*c ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/not_in_docs/great_circle/p1.py0000644000175100001770000000043700000000000024161 0ustar00runnerdocker00000000000000import math def great_circle(lon1, lat1, lon2, lat2): radius = 3956 # miles x = math.pi/180.0 a = (90.0 - lat1)*x b = (90.0 - lat2)*x theta = (lon2 - lon1)*x c = math.acos(math.cos(a)*math.cos(b) + math.sin(a)*math.sin(b)*math.cos(theta)) return radius*c ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880490.976724 Cython-3.0.8/docs/examples/quickstart/0000755000175100001770000000000000000000000020534 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.028724 Cython-3.0.8/docs/examples/quickstart/build/0000755000175100001770000000000000000000000021633 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/quickstart/build/hello.pyx0000644000175100001770000000006600000000000023502 0ustar00runnerdocker00000000000000def say_hello_to(name): print("Hello %s!" % name) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/quickstart/build/setup.py0000644000175100001770000000021600000000000023344 0ustar00runnerdocker00000000000000from setuptools import setup from Cython.Build import cythonize setup( name='Hello world app', ext_modules=cythonize("hello.pyx"), ) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.028724 Cython-3.0.8/docs/examples/quickstart/cythonize/0000755000175100001770000000000000000000000022550 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/quickstart/cythonize/cdef_keyword.py0000644000175100001770000000016000000000000025564 0ustar00runnerdocker00000000000000@cython.cfunc @cython.exceptval(-2, check=True) def f(x: cython.double) -> cython.double: return x ** 2 - x ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/quickstart/cythonize/cdef_keyword.pyx0000644000175100001770000000007600000000000025762 0ustar00runnerdocker00000000000000 cdef double f(double x) except? -2: return x ** 2 - x ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/quickstart/cythonize/integrate.py0000644000175100001770000000023700000000000025106 0ustar00runnerdocker00000000000000def f(x): return x ** 2 - x def integrate_f(a, b, N): s = 0 dx = (b - a) / N for i in range(N): s += f(a + i * dx) return s * dx ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/quickstart/cythonize/integrate_cy.py0000644000175100001770000000042500000000000025600 0ustar00runnerdocker00000000000000def f(x: cython.double): return x ** 2 - x def integrate_f(a: cython.double, b: cython.double, N: cython.int): i: cython.int s: cython.double dx: cython.double s = 0 dx = (b - a) / N for i in range(N): s += f(a + i * dx) return s * dx ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/quickstart/cythonize/integrate_cy.pyx0000644000175100001770000000035400000000000025771 0ustar00runnerdocker00000000000000def f(double x): return x ** 2 - x def integrate_f(double a, double b, int N): cdef int i cdef double s cdef double dx s = 0 dx = (b - a) / N for i in range(N): s += f(a + i * dx) return s * dx ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880490.980724 Cython-3.0.8/docs/examples/tutorial/0000755000175100001770000000000000000000000020205 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.028724 Cython-3.0.8/docs/examples/tutorial/array/0000755000175100001770000000000000000000000021323 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/array/clone.py0000644000175100001770000000043400000000000022776 0ustar00runnerdocker00000000000000from cython.cimports.cpython import array import array int_array_template = cython.declare(array.array, array.array('i', [])) cython.declare(newarray=array.array) # create an array with 3 elements with same type as template newarray = array.clone(int_array_template, 3, zero=False) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/array/clone.pyx0000644000175100001770000000036600000000000023172 0ustar00runnerdocker00000000000000from cpython cimport array import array cdef array.array int_array_template = array.array('i', []) cdef array.array newarray # create an array with 3 elements with same type as template newarray = array.clone(int_array_template, 3, zero=False) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/array/overhead.py0000644000175100001770000000074000000000000023473 0ustar00runnerdocker00000000000000from cython.cimports.cpython import array import array a = cython.declare(array.array, array.array('i', [1, 2, 3])) ca = cython.declare(cython.int[:], a) @cython.cfunc def overhead(a: cython.object) -> cython.int: ca: cython.int[:] = a return ca[0] @cython.cfunc def no_overhead(ca: cython.int[:]) -> cython.int: return ca[0] print(overhead(a)) # new memory view will be constructed, overhead print(no_overhead(ca)) # ca is already a memory view, so no overhead ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/array/overhead.pyx0000644000175100001770000000056300000000000023666 0ustar00runnerdocker00000000000000from cpython cimport array import array cdef array.array a = array.array('i', [1, 2, 3]) cdef int[:] ca = a cdef int overhead(object a): cdef int[:] ca = a return ca[0] cdef int no_overhead(int[:] ca): return ca[0] print(overhead(a)) # new memory view will be constructed, overhead print(no_overhead(ca)) # ca is already a memory view, so no overhead ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/array/resize.py0000644000175100001770000000047400000000000023203 0ustar00runnerdocker00000000000000from cython.cimports.cpython import array import array a = cython.declare(array.array, array.array('i', [1, 2, 3])) b = cython.declare(array.array, array.array('i', [4, 5, 6])) # extend a with b, resize as needed array.extend(a, b) # resize a, leaving just original three elements array.resize(a, len(a) - len(b)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/array/resize.pyx0000644000175100001770000000042500000000000023367 0ustar00runnerdocker00000000000000from cpython cimport array import array cdef array.array a = array.array('i', [1, 2, 3]) cdef array.array b = array.array('i', [4, 5, 6]) # extend a with b, resize as needed array.extend(a, b) # resize a, leaving just original three elements array.resize(a, len(a) - len(b)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/array/safe_usage.py0000644000175100001770000000025000000000000023774 0ustar00runnerdocker00000000000000from cython.cimports.cpython import array import array a = cython.declare(array.array, array.array('i', [1, 2, 3])) ca = cython.declare(cython.int[:], a) print(ca[0]) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/array/safe_usage.pyx0000644000175100001770000000017200000000000024167 0ustar00runnerdocker00000000000000from cpython cimport array import array cdef array.array a = array.array('i', [1, 2, 3]) cdef int[:] ca = a print(ca[0]) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/array/unsafe_usage.py0000644000175100001770000000043600000000000024345 0ustar00runnerdocker00000000000000from cython.cimports.cpython import array import array a = cython.declare(array.array, array.array('i', [1, 2, 3])) # access underlying pointer: print(a.data.as_ints[0]) from cython.cimports.libc.string import memset memset(a.data.as_voidptr, 0, len(a) * cython.sizeof(cython.int)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/array/unsafe_usage.pyx0000644000175100001770000000034600000000000024535 0ustar00runnerdocker00000000000000from cpython cimport array import array cdef array.array a = array.array('i', [1, 2, 3]) # access underlying pointer: print(a.data.as_ints[0]) from libc.string cimport memset memset(a.data.as_voidptr, 0, len(a) * sizeof(int)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.0327241 Cython-3.0.8/docs/examples/tutorial/cdef_classes/0000755000175100001770000000000000000000000022623 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cdef_classes/integrate.py0000644000175100001770000000061500000000000025161 0ustar00runnerdocker00000000000000from cython.cimports.sin_of_square import Function, SinOfSquareFunction def integrate(f: Function, a: float, b: float, N: cython.int): i: cython.int if f is None: raise ValueError("f cannot be None") s: float = 0 dx: float = (b - a) / N for i in range(N): s += f.evaluate(a + i * dx) return s * dx print(integrate(SinOfSquareFunction(), 0, 1, 10000)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cdef_classes/integrate.pyx0000644000175100001770000000057100000000000025352 0ustar00runnerdocker00000000000000from sin_of_square cimport Function, SinOfSquareFunction def integrate(Function f, double a, double b, int N): cdef int i cdef double s, dx if f is None: raise ValueError("f cannot be None") s = 0 dx = (b - a) / N for i in range(N): s += f.evaluate(a + i * dx) return s * dx print(integrate(SinOfSquareFunction(), 0, 1, 10000)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cdef_classes/math_function.py0000644000175100001770000000031200000000000026027 0ustar00runnerdocker00000000000000class MathFunction(object): def __init__(self, name, operator): self.name = name self.operator = operator def __call__(self, *operands): return self.operator(*operands) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cdef_classes/math_function_2.py0000644000175100001770000000015500000000000026255 0ustar00runnerdocker00000000000000@cython.cclass class Function: @cython.ccall def evaluate(self, x: float) -> float: return 0 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cdef_classes/math_function_2.pyx0000644000175100001770000000013500000000000026443 0ustar00runnerdocker00000000000000 cdef class Function: cpdef double evaluate(self, double x) except *: return 0 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cdef_classes/nonecheck.py0000644000175100001770000000071200000000000025132 0ustar00runnerdocker00000000000000# cython: nonecheck=True # ^^^ Turns on nonecheck globally import cython @cython.cclass class MyClass: pass # Turn off nonecheck locally for the function @cython.nonecheck(False) def func(): obj: MyClass = None try: # Turn nonecheck on again for a block with cython.nonecheck(True): print(obj.myfunc()) # Raises exception except AttributeError: pass print(obj.myfunc()) # Hope for a crash! ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cdef_classes/nonecheck.pyx0000644000175100001770000000070500000000000025324 0ustar00runnerdocker00000000000000# cython: nonecheck=True # ^^^ Turns on nonecheck globally import cython cdef class MyClass: pass # Turn off nonecheck locally for the function @cython.nonecheck(False) def func(): cdef MyClass obj = None try: # Turn nonecheck on again for a block with cython.nonecheck(True): print(obj.myfunc()) # Raises exception except AttributeError: pass print(obj.myfunc()) # Hope for a crash! ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cdef_classes/sin_of_square.pxd0000644000175100001770000000025300000000000026175 0ustar00runnerdocker00000000000000cdef class Function: cpdef double evaluate(self, double x) except * cdef class SinOfSquareFunction(Function): cpdef double evaluate(self, double x) except * ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cdef_classes/sin_of_square.py0000644000175100001770000000044500000000000026035 0ustar00runnerdocker00000000000000from cython.cimports.libc.math import sin @cython.cclass class Function: @cython.ccall def evaluate(self, x: float) -> float: return 0 @cython.cclass class SinOfSquareFunction(Function): @cython.ccall def evaluate(self, x: float) -> float: return sin(x ** 2) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cdef_classes/sin_of_square.pyx0000644000175100001770000000036400000000000026225 0ustar00runnerdocker00000000000000from libc.math cimport sin cdef class Function: cpdef double evaluate(self, double x) except *: return 0 cdef class SinOfSquareFunction(Function): cpdef double evaluate(self, double x) except *: return sin(x ** 2) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cdef_classes/wave_function.py0000644000175100001770000000105000000000000026040 0ustar00runnerdocker00000000000000from cython.cimports.sin_of_square import Function @cython.cclass class WaveFunction(Function): # Not available in Python-space: offset: float # Available in Python-space: freq = cython.declare(cython.double, visibility='public') # Available in Python-space, but only for reading: scale = cython.declare(cython.double, visibility='readonly') # Available in Python-space: @property def period(self): return 1.0 / self.freq @period.setter def period(self, value): self.freq = 1.0 / value ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cdef_classes/wave_function.pyx0000644000175100001770000000072100000000000026234 0ustar00runnerdocker00000000000000from sin_of_square cimport Function cdef class WaveFunction(Function): # Not available in Python-space: cdef double offset # Available in Python-space: cdef public double freq # Available in Python-space, but only for reading: cdef readonly double scale # Available in Python-space: @property def period(self): return 1.0 / self.freq @period.setter def period(self, value): self.freq = 1.0 / value ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.0327241 Cython-3.0.8/docs/examples/tutorial/clibraries/0000755000175100001770000000000000000000000022324 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880490.980724 Cython-3.0.8/docs/examples/tutorial/clibraries/c-algorithms/0000755000175100001770000000000000000000000024715 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.0327241 Cython-3.0.8/docs/examples/tutorial/clibraries/c-algorithms/src/0000755000175100001770000000000000000000000025504 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/clibraries/c-algorithms/src/queue.h0000644000175100001770000000070200000000000027000 0ustar00runnerdocker00000000000000/* queue.h */ typedef struct _Queue Queue; typedef void *QueueValue; Queue *queue_new(void); void queue_free(Queue *queue); int queue_push_head(Queue *queue, QueueValue data); QueueValue queue_pop_head(Queue *queue); QueueValue queue_peek_head(Queue *queue); int queue_push_tail(Queue *queue, QueueValue data); QueueValue queue_pop_tail(Queue *queue); QueueValue queue_peek_tail(Queue *queue); int queue_is_empty(Queue *queue); ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/clibraries/cqueue.pxd0000644000175100001770000000101000000000000024320 0ustar00runnerdocker00000000000000cdef extern from "c-algorithms/src/queue.h": ctypedef struct Queue: pass ctypedef void* QueueValue Queue* queue_new() void queue_free(Queue* queue) int queue_push_head(Queue* queue, QueueValue data) QueueValue queue_pop_head(Queue* queue) QueueValue queue_peek_head(Queue* queue) int queue_push_tail(Queue* queue, QueueValue data) QueueValue queue_pop_tail(Queue* queue) QueueValue queue_peek_tail(Queue* queue) bint queue_is_empty(Queue* queue) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/clibraries/queue.py0000644000175100001770000000026000000000000024020 0ustar00runnerdocker00000000000000from cython.cimports import cqueue @cython.cclass class Queue: _c_queue: cython.pointer(cqueue.Queue) def __cinit__(self): self._c_queue = cqueue.queue_new() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/clibraries/queue.pyx0000644000175100001770000000021000000000000024203 0ustar00runnerdocker00000000000000cimport cqueue cdef class Queue: cdef cqueue.Queue* _c_queue def __cinit__(self): self._c_queue = cqueue.queue_new() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/clibraries/queue2.py0000644000175100001770000000041200000000000024101 0ustar00runnerdocker00000000000000from cython.cimports import cqueue @cython.cclass class Queue: _c_queue = cython.declare(cython.pointer(cqueue.Queue)) def __cinit__(self): self._c_queue = cqueue.queue_new() if self._c_queue is cython.NULL: raise MemoryError() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/clibraries/queue2.pyx0000644000175100001770000000031200000000000024270 0ustar00runnerdocker00000000000000cimport cqueue cdef class Queue: cdef cqueue.Queue* _c_queue def __cinit__(self): self._c_queue = cqueue.queue_new() if self._c_queue is NULL: raise MemoryError() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/clibraries/queue3.py0000644000175100001770000000437700000000000024120 0ustar00runnerdocker00000000000000from cython.cimports import cqueue from cython import cast @cython.cclass class Queue: """A queue class for C integer values. >>> q = Queue() >>> q.append(5) >>> q.peek() 5 >>> q.pop() 5 """ _c_queue = cython.declare(cython.pointer(cqueue.Queue)) def __cinit__(self): self._c_queue = cqueue.queue_new() if self._c_queue is cython.NULL: raise MemoryError() def __dealloc__(self): if self._c_queue is not cython.NULL: cqueue.queue_free(self._c_queue) @cython.ccall def append(self, value: cython.int): if not cqueue.queue_push_tail(self._c_queue, cast(cython.p_void, cast(cython.Py_ssize_t, value))): raise MemoryError() # The `cpdef` feature is obviously not available for the original "extend()" # method, as the method signature is incompatible with Python argument # types (Python does not have pointers). However, we can rename # the C-ish "extend()" method to e.g. "extend_ints()", and write # a new "extend()" method that provides a suitable Python interface by # accepting an arbitrary Python iterable. @cython.ccall def extend(self, values): for value in values: self.append(value) @cython.cfunc def extend_ints(self, values: cython.p_int, count: cython.size_t): value: cython.int for value in values[:count]: # Slicing pointer to limit the iteration boundaries. self.append(value) @cython.ccall @cython.exceptval(-1, check=True) def peek(self) -> cython.int: value: cython.int = cast(cython.Py_ssize_t, cqueue.queue_peek_head(self._c_queue)) if value == 0: # this may mean that the queue is empty, # or that it happens to contain a 0 value if cqueue.queue_is_empty(self._c_queue): raise IndexError("Queue is empty") return value @cython.ccall @cython.exceptval(-1, check=True) def pop(self) -> cython.int: if cqueue.queue_is_empty(self._c_queue): raise IndexError("Queue is empty") return cast(cython.Py_ssize_t, cqueue.queue_pop_head(self._c_queue)) def __bool__(self): return not cqueue.queue_is_empty(self._c_queue) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/clibraries/queue3.pyx0000644000175100001770000000372300000000000024302 0ustar00runnerdocker00000000000000cimport cqueue cdef class Queue: """A queue class for C integer values. >>> q = Queue() >>> q.append(5) >>> q.peek() 5 >>> q.pop() 5 """ cdef cqueue.Queue* _c_queue def __cinit__(self): self._c_queue = cqueue.queue_new() if self._c_queue is NULL: raise MemoryError() def __dealloc__(self): if self._c_queue is not NULL: cqueue.queue_free(self._c_queue) cpdef append(self, int value): if not cqueue.queue_push_tail(self._c_queue, value): raise MemoryError() # The `cpdef` feature is obviously not available for the original "extend()" # method, as the method signature is incompatible with Python argument # types (Python does not have pointers). However, we can rename # the C-ish "extend()" method to e.g. "extend_ints()", and write # a new "extend()" method that provides a suitable Python interface by # accepting an arbitrary Python iterable. cpdef extend(self, values): for value in values: self.append(value) cdef extend_ints(self, int* values, size_t count): cdef int value for value in values[:count]: # Slicing pointer to limit the iteration boundaries. self.append(value) cpdef int peek(self) except? -1: cdef int value = cqueue.queue_peek_head(self._c_queue) if value == 0: # this may mean that the queue is empty, # or that it happens to contain a 0 value if cqueue.queue_is_empty(self._c_queue): raise IndexError("Queue is empty") return value cpdef int pop(self) except? -1: if cqueue.queue_is_empty(self._c_queue): raise IndexError("Queue is empty") return cqueue.queue_pop_head(self._c_queue) def __bool__(self): return not cqueue.queue_is_empty(self._c_queue) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/clibraries/test_queue.py0000644000175100001770000000102000000000000025052 0ustar00runnerdocker00000000000000from __future__ import print_function import time import queue Q = queue.Queue() Q.append(10) Q.append(20) print(Q.peek()) print(Q.pop()) print(Q.pop()) try: print(Q.pop()) except IndexError as e: print("Error message:", e) # Prints "Queue is empty" i = 10000 values = range(i) start_time = time.time() Q.extend(values) end_time = time.time() - start_time print("Adding {} items took {:1.3f} msecs.".format(i, 1000 * end_time)) for i in range(41): Q.pop() Q.pop() print("The answer is:") print(Q.pop()) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.0327241 Cython-3.0.8/docs/examples/tutorial/cython_tutorial/0000755000175100001770000000000000000000000023434 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cython_tutorial/fib.pyx0000644000175100001770000000030100000000000024730 0ustar00runnerdocker00000000000000from __future__ import print_function def fib(n): """Print the Fibonacci series up to n.""" a, b = 0, 1 while b < n: print(b, end=' ') a, b = b, a + b print() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cython_tutorial/primes.py0000644000175100001770000000134600000000000025311 0ustar00runnerdocker00000000000000def primes(nb_primes: cython.int): i: cython.int p: cython.int[1000] if nb_primes > 1000: nb_primes = 1000 if not cython.compiled: # Only if regular Python is running p = [0] * 1000 # Make p work almost like a C array len_p: cython.int = 0 # The current number of elements in p. n: cython.int = 2 while len_p < nb_primes: # Is n prime? for i in p[:len_p]: if n % i == 0: break # If no break occurred in the loop, we have a prime. else: p[len_p] = n len_p += 1 n += 1 # Let's copy the result into a Python list: result_as_list = [prime for prime in p[:len_p]] return result_as_list ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cython_tutorial/primes.pyx0000644000175100001770000000111200000000000025470 0ustar00runnerdocker00000000000000def primes(int nb_primes): cdef int n, i, len_p cdef int[1000] p if nb_primes > 1000: nb_primes = 1000 len_p = 0 # The current number of elements in p. n = 2 while len_p < nb_primes: # Is n prime? for i in p[:len_p]: if n % i == 0: break # If no break occurred in the loop, we have a prime. else: p[len_p] = n len_p += 1 n += 1 # Let's copy the result into a Python list: result_as_list = [prime for prime in p[:len_p]] return result_as_list ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cython_tutorial/primes_cpp.py0000644000175100001770000000124400000000000026150 0ustar00runnerdocker00000000000000# distutils: language=c++ import cython from cython.cimports.libcpp.vector import vector def primes(nb_primes: cython.uint): i: cython.int p: vector[cython.int] p.reserve(nb_primes) # allocate memory for 'nb_primes' elements. n: cython.int = 2 while p.size() < nb_primes: # size() for vectors is similar to len() for i in p: if n % i == 0: break else: p.push_back(n) # push_back is similar to append() n += 1 # If possible, C values and C++ objects are automatically # converted to Python objects at need. return p # so here, the vector will be copied into a Python list. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3447223 Cython-3.0.8/docs/examples/tutorial/cython_tutorial/primes_cpp.pyx0000644000175100001770000000117100000000000026337 0ustar00runnerdocker00000000000000# distutils: language=c++ from libcpp.vector cimport vector def primes(unsigned int nb_primes): cdef int n, i cdef vector[int] p p.reserve(nb_primes) # allocate memory for 'nb_primes' elements. n = 2 while p.size() < nb_primes: # size() for vectors is similar to len() for i in p: if n % i == 0: break else: p.push_back(n) # push_back is similar to append() n += 1 # If possible, C values and C++ objects are automatically # converted to Python objects at need. return p # so here, the vector will be copied into a Python list. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/cython_tutorial/primes_python.py0000644000175100001770000000042300000000000026705 0ustar00runnerdocker00000000000000def primes(nb_primes): p = [] n = 2 while len(p) < nb_primes: # Is n prime? for i in p: if n % i == 0: break # If no break occurred in the loop else: p.append(n) n += 1 return p ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.0327241 Cython-3.0.8/docs/examples/tutorial/embedding/0000755000175100001770000000000000000000000022123 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/embedding/embedded.pyx0000644000175100001770000000043200000000000024415 0ustar00runnerdocker00000000000000# embedded.pyx # The following two lines are for test purposes only, please ignore them. # distutils: sources = embedded_main.c # tag: py3only # tag: no-cpp TEXT_TO_SAY = 'Hello from Python!' cdef public int say_hello_from_python() except -1: print(TEXT_TO_SAY) return 0 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/embedding/embedded_main.c0000644000175100001770000000323600000000000025030 0ustar00runnerdocker00000000000000/* embedded_main.c */ /* This include file is automatically generated by Cython for 'public' functions. */ #include "embedded.h" #ifdef __cplusplus extern "C" { #endif int main(int argc, char *argv[]) { PyObject *pmodule; wchar_t *program; program = Py_DecodeLocale(argv[0], NULL); if (program == NULL) { fprintf(stderr, "Fatal error: cannot decode argv[0], got %d arguments\n", argc); exit(1); } /* Add a built-in module, before Py_Initialize */ if (PyImport_AppendInittab("embedded", PyInit_embedded) == -1) { fprintf(stderr, "Error: could not extend in-built modules table\n"); exit(1); } /* Pass argv[0] to the Python interpreter */ Py_SetProgramName(program); /* Initialize the Python interpreter. Required. If this step fails, it will be a fatal error. */ Py_Initialize(); /* Optionally import the module; alternatively, import can be deferred until the embedded script imports it. */ pmodule = PyImport_ImportModule("embedded"); if (!pmodule) { PyErr_Print(); fprintf(stderr, "Error: could not import module 'embedded'\n"); goto exit_with_error; } /* Now call into your module code. */ if (say_hello_from_python() < 0) { PyErr_Print(); fprintf(stderr, "Error in Python code, exception was printed.\n"); goto exit_with_error; } /* ... */ /* Clean up after using CPython. */ PyMem_RawFree(program); Py_Finalize(); return 0; /* Clean up in the error cases above. */ exit_with_error: PyMem_RawFree(program); Py_Finalize(); return 1; } #ifdef __cplusplus } #endif ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.036724 Cython-3.0.8/docs/examples/tutorial/external/0000755000175100001770000000000000000000000022027 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/external/atoi.py0000644000175100001770000000034300000000000023335 0ustar00runnerdocker00000000000000from cython.cimports.libc.stdlib import atoi @cython.cfunc def parse_charptr_to_py_int(s: cython.p_char): assert s is not cython.NULL, "byte string value is NULL" return atoi(s) # note: atoi() has no error detection! ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/external/atoi.pyx0000644000175100001770000000027000000000000023524 0ustar00runnerdocker00000000000000from libc.stdlib cimport atoi cdef parse_charptr_to_py_int(char* s): assert s is not NULL, "byte string value is NULL" return atoi(s) # note: atoi() has no error detection! ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/external/cpdef_sin.pyx0000644000175100001770000000012200000000000024516 0ustar00runnerdocker00000000000000""" >>> sin(0) 0.0 """ cdef extern from "math.h": cpdef double sin(double x) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/external/keyword_args.pyx0000644000175100001770000000013000000000000025263 0ustar00runnerdocker00000000000000cdef extern from "string.h": char* strstr(const char *haystack, const char *needle) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/external/keyword_args_call.py0000644000175100001770000000031400000000000026072 0ustar00runnerdocker00000000000000from cython.cimports.strstr import strstr def main(): data: cython.p_char = "hfvcakdfagbcffvschvxcdfgccbcfhvgcsnfxjh" pos = strstr(needle='akd', haystack=data) print(pos is not cython.NULL) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/external/keyword_args_call.pyx0000644000175100001770000000034200000000000026263 0ustar00runnerdocker00000000000000cdef extern from "string.h": char* strstr(const char *haystack, const char *needle) cdef char* data = "hfvcakdfagbcffvschvxcdfgccbcfhvgcsnfxjh" cdef char* pos = strstr(needle='akd', haystack=data) print(pos is not NULL) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/external/libc_sin.py0000644000175100001770000000017100000000000024162 0ustar00runnerdocker00000000000000from cython.cimports.libc.math import sin @cython.cfunc def f(x: cython.double) -> cython.double: return sin(x * x) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/external/libc_sin.pyx0000644000175100001770000000011400000000000024347 0ustar00runnerdocker00000000000000from libc.math cimport sin cdef double f(double x): return sin(x * x) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/external/py_version_hex.py0000644000175100001770000000020000000000000025432 0ustar00runnerdocker00000000000000from cython.cimports.cpython.version import PY_VERSION_HEX # Python version >= 3.2 final ? print(PY_VERSION_HEX >= 0x030200F0) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/external/py_version_hex.pyx0000644000175100001770000000016100000000000025630 0ustar00runnerdocker00000000000000from cpython.version cimport PY_VERSION_HEX # Python version >= 3.2 final ? print(PY_VERSION_HEX >= 0x030200F0) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/external/setup.py0000644000175100001770000000043300000000000023541 0ustar00runnerdocker00000000000000from setuptools import Extension, setup from Cython.Build import cythonize ext_modules = [ Extension("demo", sources=["demo.pyx"], libraries=["m"] # Unix-like specific ) ] setup(name="Demos", ext_modules=cythonize(ext_modules)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/external/strstr.pxd0000644000175100001770000000013000000000000024077 0ustar00runnerdocker00000000000000cdef extern from "string.h": char* strstr(const char *haystack, const char *needle) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.036724 Cython-3.0.8/docs/examples/tutorial/memory_allocation/0000755000175100001770000000000000000000000023722 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/memory_allocation/malloc.py0000644000175100001770000000153000000000000025542 0ustar00runnerdocker00000000000000import random from cython.cimports.libc.stdlib import malloc, free def random_noise(number: cython.int = 1): i: cython.int # allocate number * sizeof(double) bytes of memory my_array: cython.p_double = cython.cast(cython.p_double, malloc( number * cython.sizeof(cython.double))) if not my_array: raise MemoryError() try: ran = random.normalvariate for i in range(number): my_array[i] = ran(0, 1) # ... let's just assume we do some more heavy C calculations here to make up # for the work that it takes to pack the C double values into Python float # objects below, right after throwing away the existing objects above. return [x for x in my_array[:number]] finally: # return the previously allocated memory to the system free(my_array) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/memory_allocation/malloc.pyx0000644000175100001770000000142700000000000025737 0ustar00runnerdocker00000000000000import random from libc.stdlib cimport malloc, free def random_noise(int number=1): cdef int i # allocate number * sizeof(double) bytes of memory cdef double *my_array = malloc( number * sizeof(double)) if not my_array: raise MemoryError() try: ran = random.normalvariate for i in range(number): my_array[i] = ran(0, 1) # ... let's just assume we do some more heavy C calculations here to make up # for the work that it takes to pack the C double values into Python float # objects below, right after throwing away the existing objects above. return [x for x in my_array[:number]] finally: # return the previously allocated memory to the system free(my_array) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/memory_allocation/some_memory.py0000644000175100001770000000210700000000000026627 0ustar00runnerdocker00000000000000from cython.cimports.cpython.mem import PyMem_Malloc, PyMem_Realloc, PyMem_Free @cython.cclass class SomeMemory: data: cython.p_double def __cinit__(self, number: cython.size_t): # allocate some memory (uninitialised, may contain arbitrary data) self.data = cython.cast(cython.p_double, PyMem_Malloc( number * cython.sizeof(cython.double))) if not self.data: raise MemoryError() def resize(self, new_number: cython.size_t): # Allocates new_number * sizeof(double) bytes, # preserving the current content and making a best-effort to # reuse the original data location. mem = cython.cast(cython.p_double, PyMem_Realloc( self.data, new_number * cython.sizeof(cython.double))) if not mem: raise MemoryError() # Only overwrite the pointer if the memory was really reallocated. # On error (mem is NULL), the originally memory has not been freed. self.data = mem def __dealloc__(self): PyMem_Free(self.data) # no-op if self.data is NULL ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/memory_allocation/some_memory.pyx0000644000175100001770000000172700000000000027026 0ustar00runnerdocker00000000000000from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free cdef class SomeMemory: cdef double* data def __cinit__(self, size_t number): # allocate some memory (uninitialised, may contain arbitrary data) self.data = PyMem_Malloc( number * sizeof(double)) if not self.data: raise MemoryError() def resize(self, size_t new_number): # Allocates new_number * sizeof(double) bytes, # preserving the current content and making a best-effort to # reuse the original data location. mem = PyMem_Realloc( self.data, new_number * sizeof(double)) if not mem: raise MemoryError() # Only overwrite the pointer if the memory was really reallocated. # On error (mem is NULL), the originally memory has not been freed. self.data = mem def __dealloc__(self): PyMem_Free(self.data) # no-op if self.data is NULL ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.036724 Cython-3.0.8/docs/examples/tutorial/numpy/0000755000175100001770000000000000000000000021355 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/numpy/convolve2.pyx0000644000175100001770000000730700000000000024043 0ustar00runnerdocker00000000000000# tag: numpy # You can ignore the previous line. # It's for internal testing of the cython documentation. import numpy as np # "cimport" is used to import special compile-time information # about the numpy module (this is stored in a file numpy.pxd which is # distributed with Numpy). # Here we've used the name "cnp" to make it easier to understand what # comes from the cimported module and what comes from the imported module, # however you can use the same name for both if you wish. cimport numpy as cnp # It's necessary to call "import_array" if you use any part of the # numpy PyArray_* API. From Cython 3, accessing attributes like # ".shape" on a typed Numpy array use this API. Therefore we recommend # always calling "import_array" whenever you "cimport numpy" cnp.import_array() # We now need to fix a datatype for our arrays. I've used the variable # DTYPE for this, which is assigned to the usual NumPy runtime # type info object. DTYPE = np.int64 # "ctypedef" assigns a corresponding compile-time type to DTYPE_t. For # every type in the numpy module there's a corresponding compile-time # type with a _t-suffix. ctypedef cnp.int64_t DTYPE_t # "def" can type its arguments but not have a return type. The type of the # arguments for a "def" function is checked at run-time when entering the # function. # # The arrays f, g and h is typed as "np.ndarray" instances. The only effect # this has is to a) insert checks that the function arguments really are # NumPy arrays, and b) make some attribute access like f.shape[0] much # more efficient. (In this example this doesn't matter though.) def naive_convolve(cnp.ndarray f, cnp.ndarray g): if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1: raise ValueError("Only odd dimensions on filter supported") assert f.dtype == DTYPE and g.dtype == DTYPE # The "cdef" keyword is also used within functions to type variables. It # can only be used at the top indentation level (there are non-trivial # problems with allowing them in other places, though we'd love to see # good and thought out proposals for it). # # For the indices, the "int" type is used. This corresponds to a C int, # other C types (like "unsigned int") could have been used instead. # Purists could use "Py_ssize_t" which is the proper Python type for # array indices. cdef int vmax = f.shape[0] cdef int wmax = f.shape[1] cdef int smax = g.shape[0] cdef int tmax = g.shape[1] cdef int smid = smax // 2 cdef int tmid = tmax // 2 cdef int xmax = vmax + 2 * smid cdef int ymax = wmax + 2 * tmid cdef cnp.ndarray h = np.zeros([xmax, ymax], dtype=DTYPE) cdef int x, y, s, t, v, w # It is very important to type ALL your variables. You do not get any # warnings if not, only much slower code (they are implicitly typed as # Python objects). cdef int s_from, s_to, t_from, t_to # For the value variable, we want to use the same data type as is # stored in the array, so we use "DTYPE_t" as defined above. # NB! An important side-effect of this is that if "value" overflows its # datatype size, it will simply wrap around like in C, rather than raise # an error like in Python. cdef DTYPE_t value for x in range(xmax): for y in range(ymax): s_from = max(smid - x, -smid) s_to = min((xmax - x) - smid, smid + 1) t_from = max(tmid - y, -tmid) t_to = min((ymax - y) - tmid, tmid + 1) value = 0 for s in range(s_from, s_to): for t in range(t_from, t_to): v = x - smid + s w = y - tmid + t value += g[smid - s, tmid - t] * f[v, w] h[x, y] = value return h ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/numpy/convolve_py.py0000644000175100001770000000301700000000000024273 0ustar00runnerdocker00000000000000import numpy as np def naive_convolve(f, g): # f is an image and is indexed by (v, w) # g is a filter kernel and is indexed by (s, t), # it needs odd dimensions # h is the output image and is indexed by (x, y), # it is not cropped if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1: raise ValueError("Only odd dimensions on filter supported") # smid and tmid are number of pixels between the center pixel # and the edge, ie for a 5x5 filter they will be 2. # # The output size is calculated by adding smid, tmid to each # side of the dimensions of the input image. vmax = f.shape[0] wmax = f.shape[1] smax = g.shape[0] tmax = g.shape[1] smid = smax // 2 tmid = tmax // 2 xmax = vmax + 2 * smid ymax = wmax + 2 * tmid # Allocate result image. h = np.zeros([xmax, ymax], dtype=f.dtype) # Do convolution for x in range(xmax): for y in range(ymax): # Calculate pixel value for h at (x,y). Sum one component # for each pixel (s, t) of the filter g. s_from = max(smid - x, -smid) s_to = min((xmax - x) - smid, smid + 1) t_from = max(tmid - y, -tmid) t_to = min((ymax - y) - tmid, tmid + 1) value = 0 for s in range(s_from, s_to): for t in range(t_from, t_to): v = x - smid + s w = y - tmid + t value += g[smid - s, tmid - t] * f[v, w] h[x, y] = value return h ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.036724 Cython-3.0.8/docs/examples/tutorial/parallelization/0000755000175100001770000000000000000000000023377 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/parallelization/manual_work.py0000644000175100001770000000103400000000000026266 0ustar00runnerdocker00000000000000# tag: openmp from cython.parallel import parallel from cython.cimports.openmp import omp_get_thread_num import cython @cython.cfunc @cython.nogil def long_running_task1() -> cython.void: pass @cython.cfunc @cython.nogil def long_running_task2() -> cython.void: pass def do_two_tasks(): thread_num: cython.int with cython.nogil, parallel(num_threads=2): thread_num = omp_get_thread_num() if thread_num == 0: long_running_task1() elif thread_num == 1: long_running_task2() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/parallelization/manual_work.pyx0000644000175100001770000000067600000000000026471 0ustar00runnerdocker00000000000000# tag: openmp from cython.parallel cimport parallel from openmp cimport omp_get_thread_num cdef void long_running_task1() nogil: pass cdef void long_running_task2() nogil: pass def do_two_tasks(): cdef int thread_num with nogil, parallel(num_threads=2): thread_num = omp_get_thread_num() if thread_num == 0: long_running_task1() elif thread_num == 1: long_running_task2() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/parallelization/median.py0000644000175100001770000000236200000000000025211 0ustar00runnerdocker00000000000000# distutils: language = c++ from cython.parallel import parallel, prange from cython.cimports.libc.stdlib import malloc, free from cython.cimports.libcpp.algorithm import nth_element import cython from cython.operator import dereference import numpy as np @cython.boundscheck(False) @cython.wraparound(False) def median_along_axis0(x: cython.double[:,:]): out: cython.double[::1] = np.empty(x.shape[1]) i: cython.Py_ssize_t j: cython.Py_ssize_t scratch: cython.pointer(cython.double) median_it: cython.pointer(cython.double) with cython.nogil, parallel(): # allocate scratch space per loop scratch = cython.cast( cython.pointer(cython.double), malloc(cython.sizeof(cython.double)*x.shape[0])) try: for i in prange(x.shape[1]): # copy row into scratch space for j in range(x.shape[0]): scratch[j] = x[j, i] median_it = scratch + x.shape[0]//2 nth_element(scratch, median_it, scratch + x.shape[0]) # for the sake of a simple example, don't handle even lengths... out[i] = dereference(median_it) finally: free(scratch) return np.asarray(out) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/parallelization/median.pyx0000644000175100001770000000214600000000000025401 0ustar00runnerdocker00000000000000# distutils: language = c++ from cython.parallel cimport parallel, prange from libcpp.vector cimport vector from libcpp.algorithm cimport nth_element cimport cython from cython.operator cimport dereference import numpy as np @cython.boundscheck(False) @cython.wraparound(False) def median_along_axis0(const double[:,:] x): cdef double[::1] out = np.empty(x.shape[1]) cdef Py_ssize_t i, j cdef vector[double] *scratch cdef vector[double].iterator median_it with nogil, parallel(): # allocate scratch space per loop scratch = new vector[double](x.shape[0]) try: for i in prange(x.shape[1]): # copy row into scratch space for j in range(x.shape[0]): dereference(scratch)[j] = x[j, i] median_it = scratch.begin() + scratch.size()//2 nth_element(scratch.begin(), median_it, scratch.end()) # for the sake of a simple example, don't handle even lengths... out[i] = dereference(median_it) finally: del scratch return np.asarray(out) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/parallelization/norm.py0000644000175100001770000000051000000000000024720 0ustar00runnerdocker00000000000000from cython.parallel import prange import cython from cython.cimports.libc.math import sqrt @cython.boundscheck(False) @cython.wraparound(False) def l2norm(x: cython.double[:]): total: cython.double = 0 i: cython.Py_ssize_t for i in prange(x.shape[0], nogil=True): total += x[i]*x[i] return sqrt(total) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/parallelization/norm.pyx0000644000175100001770000000045500000000000025120 0ustar00runnerdocker00000000000000from cython.parallel cimport prange cimport cython from libc.math cimport sqrt @cython.boundscheck(False) @cython.wraparound(False) def l2norm(double[:] x): cdef double total = 0 cdef Py_ssize_t i for i in prange(x.shape[0], nogil=True): total += x[i]*x[i] return sqrt(total) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/parallelization/normalize.py0000644000175100001770000000071600000000000025755 0ustar00runnerdocker00000000000000from cython.parallel import parallel, prange import cython from cython.cimports.libc.math import sqrt @cython.boundscheck(False) @cython.wraparound(False) def normalize(x: cython.double[:]): i: cython.Py_ssize_t total: cython.double = 0 norm: cython.double with cython.nogil, parallel(): for i in prange(x.shape[0]): total += x[i]*x[i] norm = sqrt(total) for i in prange(x.shape[0]): x[i] /= norm ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/parallelization/normalize.pyx0000644000175100001770000000065200000000000026144 0ustar00runnerdocker00000000000000from cython.parallel cimport parallel, prange cimport cython from libc.math cimport sqrt @cython.boundscheck(False) @cython.wraparound(False) def normalize(double[:] x): cdef Py_ssize_t i cdef double total = 0 cdef double norm with nogil, parallel(): for i in prange(x.shape[0]): total += x[i]*x[i] norm = sqrt(total) for i in prange(x.shape[0]): x[i] /= norm ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/parallelization/parallel_sin.py0000644000175100001770000000073300000000000026421 0ustar00runnerdocker00000000000000from cython.parallel import prange import cython from cython.cimports.libc.math import sin import numpy as np @cython.boundscheck(False) @cython.wraparound(False) def do_sine(input: cython.double[:,:]): output : cython.double[:,:] = np.empty_like(input) i : cython.Py_ssize_t j : cython.Py_ssize_t for i in prange(input.shape[0], nogil=True): for j in range(input.shape[1]): output[i, j] = sin(input[i, j]) return np.asarray(output) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/parallelization/parallel_sin.pyx0000644000175100001770000000065000000000000026607 0ustar00runnerdocker00000000000000from cython.parallel cimport prange cimport cython from libc.math cimport sin import numpy as np @cython.boundscheck(False) @cython.wraparound(False) def do_sine(double[:,:] input): cdef double[:,:] output = np.empty_like(input) cdef Py_ssize_t i, j for i in prange(input.shape[0], nogil=True): for j in range(input.shape[1]): output[i, j] = sin(input[i, j]) return np.asarray(output) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/parallelization/setup.py0000644000175100001770000000104400000000000025110 0ustar00runnerdocker00000000000000from setuptools import Extension, setup from Cython.Build import cythonize import sys if sys.platform.startswith("win"): openmp_arg = '/openmp' else: openmp_arg = '-fopenmp' ext_modules = [ Extension( "*", ["*.pyx"], extra_compile_args=[openmp_arg], extra_link_args=[openmp_arg], ), Extension( "*", ["*.pyx"], extra_compile_args=[openmp_arg], extra_link_args=[openmp_arg], ) ] setup( name='parallel-tutorial', ext_modules=cythonize(ext_modules), ) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.036724 Cython-3.0.8/docs/examples/tutorial/profiling_tutorial/0000755000175100001770000000000000000000000024121 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/profiling_tutorial/calc_pi.py0000644000175100001770000000025500000000000026067 0ustar00runnerdocker00000000000000def recip_square(i): return 1. / i ** 2 def approx_pi(n=10000000): val = 0. for k in range(1, n + 1): val += recip_square(k) return (6 * val) ** .5 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/profiling_tutorial/calc_pi_2.py0000644000175100001770000000042300000000000026305 0ustar00runnerdocker00000000000000# cython: profile=True import cython def recip_square(i: cython.longlong): return 1. / i ** 2 def approx_pi(n: cython.int = 10000000): val: cython.double = 0. k: cython.int for k in range(1, n + 1): val += recip_square(k) return (6 * val) ** .5 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/profiling_tutorial/calc_pi_2.pyx0000644000175100001770000000035000000000000026474 0ustar00runnerdocker00000000000000# cython: profile=True def recip_square(int i): return 1. / i ** 2 def approx_pi(int n=10000000): cdef double val = 0. cdef int k for k in range(1, n + 1): val += recip_square(k) return (6 * val) ** .5 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/profiling_tutorial/calc_pi_3.py0000644000175100001770000000053200000000000026307 0ustar00runnerdocker00000000000000# cython: profile=True import cython @cython.cfunc @cython.inline @cython.exceptval(-1.0) def recip_square(i: cython.longlong) -> cython.double: return 1. / (i * i) def approx_pi(n: cython.int = 10000000): val: cython.double = 0. k: cython.int for k in range(1, n + 1): val += recip_square(k) return (6 * val) ** .5 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/profiling_tutorial/calc_pi_3.pyx0000644000175100001770000000041500000000000026477 0ustar00runnerdocker00000000000000# cython: profile=True cdef inline double recip_square(long long i) except -1.0: return 1. / (i * i) def approx_pi(int n=10000000): cdef double val = 0. cdef int k for k in range(1, n + 1): val += recip_square(k) return (6 * val) ** .5 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/profiling_tutorial/calc_pi_4.py0000644000175100001770000000055200000000000026312 0ustar00runnerdocker00000000000000# cython: profile=True import cython @cython.profile(False) @cython.cfunc @cython.inline @cython.exceptval(-1.0) def recip_square(i: cython.longlong) -> float: return 1. / (i * i) def approx_pi(n: cython.int = 10000000): val: cython.double = 0. k: cython.int for k in range(1, n + 1): val += recip_square(k) return (6 * val) ** .5 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/profiling_tutorial/calc_pi_4.pyx0000644000175100001770000000046400000000000026504 0ustar00runnerdocker00000000000000# cython: profile=True cimport cython @cython.profile(False) cdef inline double recip_square(long long i) except -1.0: return 1. / (i * i) def approx_pi(int n=10000000): cdef double val = 0. cdef int k for k in range(1, n + 1): val += recip_square(k) return (6 * val) ** .5 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/profiling_tutorial/often_called.py0000644000175100001770000000011700000000000027111 0ustar00runnerdocker00000000000000import cython @cython.profile(False) def my_often_called_function(): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/profiling_tutorial/often_called.pyx0000644000175100001770000000012000000000000027273 0ustar00runnerdocker00000000000000cimport cython @cython.profile(False) def my_often_called_function(): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/profiling_tutorial/profile.py0000644000175100001770000000030700000000000026133 0ustar00runnerdocker00000000000000import pstats, cProfile import calc_pi cProfile.runctx("calc_pi.approx_pi()", globals(), locals(), "Profile.prof") s = pstats.Stats("Profile.prof") s.strip_dirs().sort_stats("time").print_stats() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/profiling_tutorial/profile_2.py0000644000175100001770000000035500000000000026357 0ustar00runnerdocker00000000000000import pstats, cProfile import pyximport pyximport.install() import calc_pi cProfile.runctx("calc_pi.approx_pi()", globals(), locals(), "Profile.prof") s = pstats.Stats("Profile.prof") s.strip_dirs().sort_stats("time").print_stats() ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.040724 Cython-3.0.8/docs/examples/tutorial/pure/0000755000175100001770000000000000000000000021160 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/A.pxd0000644000175100001770000000021700000000000022055 0ustar00runnerdocker00000000000000cpdef int myfunction(int x, int y=*) cdef double _helper(double a) cdef class A: cdef public int a, b cpdef foo(self, double x) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/A.py0000644000175100001770000000034100000000000021710 0ustar00runnerdocker00000000000000def myfunction(x, y=2): a = x - y return a + x * y def _helper(a): return a + 1 class A: def __init__(self, b=0): self.a = 3 self.b = b def foo(self, x): print(x + _helper(1.0)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/A_equivalent.pyx0000644000175100001770000000044500000000000024342 0ustar00runnerdocker00000000000000cpdef int myfunction(int x, int y=2): a = x - y return a + x * y cdef double _helper(double a): return a + 1 cdef class A: cdef public int a, b def __init__(self, b=0): self.a = 3 self.b = b cpdef foo(self, double x): print(x + _helper(1.0)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/annotations.py0000644000175100001770000000016100000000000024065 0ustar00runnerdocker00000000000000import cython def func(foo: dict, bar: cython.int) -> tuple: foo["hello world"] = 3 + bar return foo, 5 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/c_arrays.py0000644000175100001770000000054500000000000023341 0ustar00runnerdocker00000000000000import cython @cython.locals(counts=cython.int[10], digit=cython.int) def count_digits(digits): """ >>> digits = '01112222333334445667788899' >>> count_digits(map(int, digits)) [1, 3, 4, 5, 3, 1, 2, 2, 3, 2] """ counts = [0] * 10 for digit in digits: assert 0 <= digit <= 9 counts[digit] += 1 return counts ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/cclass.py0000644000175100001770000000061600000000000023005 0ustar00runnerdocker00000000000000import cython @cython.cclass class A: cython.declare(a=cython.int, b=cython.int) c = cython.declare(cython.int, visibility='public') d = cython.declare(cython.int) # private by default. e = cython.declare(cython.int, visibility='readonly') def __init__(self, a, b, c, d=5, e=3): self.a = a self.b = b self.c = c self.d = d self.e = e ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/compiled_switch.py0000644000175100001770000000016700000000000024713 0ustar00runnerdocker00000000000000import cython if cython.compiled: print("Yep, I'm compiled.") else: print("Just a lowly interpreted script.") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/cython_declare.py0000644000175100001770000000021600000000000024514 0ustar00runnerdocker00000000000000import cython x = cython.declare(cython.int) # cdef int x y = cython.declare(cython.double, 0.57721) # cdef double y = 0.57721 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/cython_declare2.py0000644000175100001770000000013200000000000024573 0ustar00runnerdocker00000000000000import cython cython.declare(x=cython.int, y=cython.double) # cdef int x; cdef double y ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/disabled_annotations.py0000644000175100001770000000157200000000000025723 0ustar00runnerdocker00000000000000import cython @cython.annotation_typing(False) def function_without_typing(a: int, b: int) -> int: """Cython is ignoring annotations in this function""" c: int = a + b return c * a @cython.annotation_typing(False) @cython.cclass class NotAnnotatedClass: """Cython is ignoring annotatons in this class except annotated_method""" d: dict def __init__(self, dictionary: dict): self.d = dictionary @cython.annotation_typing(True) def annotated_method(self, key: str, a: cython.int, b: cython.int): prefixed_key: str = 'prefix_' + key self.d[prefixed_key] = a + b def annotated_function(a: cython.int, b: cython.int): s: cython.int = a + b with cython.annotation_typing(False): # Cython is ignoring annotations within this code block c: list = [] c.append(a) c.append(b) c.append(s) return c ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/dostuff.pxd0000644000175100001770000000012700000000000023347 0ustar00runnerdocker00000000000000import cython @cython.locals(t=cython.int, i=cython.int) cpdef int dostuff(int n) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/dostuff.py0000644000175100001770000000011500000000000023201 0ustar00runnerdocker00000000000000def dostuff(n): t = 0 for i in range(n): t += i return t ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/exceptval.py0000644000175100001770000000023100000000000023521 0ustar00runnerdocker00000000000000import cython @cython.exceptval(-1) def func(x: cython.int) -> cython.int: if x < 0: raise ValueError("need integer >= 0") return x + 1 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/locals.py0000644000175100001770000000017400000000000023011 0ustar00runnerdocker00000000000000import cython @cython.locals(a=cython.long, b=cython.long, n=cython.longlong) def foo(a, b, x, y): n = a * b # ... ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/mymodule.pxd0000644000175100001770000000021400000000000023525 0ustar00runnerdocker00000000000000# mymodule.pxd # declare a C function as "cpdef" to export it to the module cdef extern from "math.h": cpdef double sin(double x) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/mymodule.py0000644000175100001770000000034100000000000023363 0ustar00runnerdocker00000000000000# mymodule.py import cython # override with Python import if not in compiled code if not cython.compiled: from math import sin # calls sin() from math.h when compiled with Cython and math.sin() in Python print(sin(0)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/pep_526.py0000644000175100001770000000114400000000000022712 0ustar00runnerdocker00000000000000import cython def func(): # Cython types are evaluated as for cdef declarations x: cython.int # cdef int x y: cython.double = 0.57721 # cdef double y = 0.57721 z: cython.float = 0.57721 # cdef float z = 0.57721 # Python types shadow Cython types for compatibility reasons a: float = 0.54321 # cdef double a = 0.54321 b: int = 5 # cdef object b = 5 c: long = 6 # cdef object c = 6 pass @cython.cclass class A: a: cython.int b: cython.int def __init__(self, b=0): self.a = 3 self.b = b ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pure/py_cimport.py0000644000175100001770000000012700000000000023717 0ustar00runnerdocker00000000000000 from cython.cimports.libc import math def use_libc_math(): return math.ceil(5.5) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.040724 Cython-3.0.8/docs/examples/tutorial/pxd_files/0000755000175100001770000000000000000000000022162 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pxd_files/cmath.pxd0000644000175100001770000000007200000000000023772 0ustar00runnerdocker00000000000000cdef extern from "math.h": cpdef double sin(double x) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pxd_files/inline.pxd0000644000175100001770000000010400000000000024150 0ustar00runnerdocker00000000000000cdef inline int int_min(int a, int b): return b if b < a else a ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pxd_files/integrate.py0000644000175100001770000000004600000000000024516 0ustar00runnerdocker00000000000000from cython.cimports.cmath import sin ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/pxd_files/integrate.pyx0000644000175100001770000000002700000000000024705 0ustar00runnerdocker00000000000000from cmath cimport sin ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.040724 Cython-3.0.8/docs/examples/tutorial/string/0000755000175100001770000000000000000000000021513 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/api_func.pyx0000644000175100001770000000012400000000000024036 0ustar00runnerdocker00000000000000from to_unicode cimport _text def api_func(s): text_input = _text(s) # ... ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/arg_memview.pyx0000644000175100001770000000021000000000000024550 0ustar00runnerdocker00000000000000def process_byte_data(unsigned char[:] data): length = data.shape[0] first_byte = data[0] slice_view = data[1:-1] # ... ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/auto_conversion_1.pyx0000644000175100001770000000034200000000000025711 0ustar00runnerdocker00000000000000# cython: c_string_type=unicode, c_string_encoding=utf8 cdef char* c_string = 'abcdefg' # implicit decoding: cdef object py_unicode_object = c_string # explicit conversion to Python bytes: py_bytes_object = c_string ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/auto_conversion_2.pyx0000644000175100001770000000051100000000000025710 0ustar00runnerdocker00000000000000# cython: c_string_type=str, c_string_encoding=ascii cdef char* c_string = 'abcdefg' # implicit decoding in Py3, bytes conversion in Py2: cdef object py_str_object = c_string # explicit conversion to Python bytes: py_bytes_object = c_string # explicit conversion to Python unicode: py_bytes_object = c_string ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/auto_conversion_3.pyx0000644000175100001770000000023000000000000025707 0ustar00runnerdocker00000000000000# cython: c_string_type=unicode, c_string_encoding=ascii def func(): ustring = u'abc' cdef char* s = ustring return s[0] # returns u'a' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/c_func.pxd0000644000175100001770000000015100000000000023462 0ustar00runnerdocker00000000000000cdef char* c_call_returning_a_c_string() cdef void get_a_c_string(char** c_string, Py_ssize_t *length) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/c_func.pyx0000644000175100001770000000115600000000000023515 0ustar00runnerdocker00000000000000from libc.stdlib cimport malloc from libc.string cimport strcpy, strlen cdef char* hello_world = 'hello world' cdef size_t n = strlen(hello_world) cdef char* c_call_returning_a_c_string(): cdef char* c_string = malloc((n + 1) * sizeof(char)) if not c_string: return NULL # malloc failed strcpy(c_string, hello_world) return c_string cdef void get_a_c_string(char** c_string_ptr, Py_ssize_t *length): c_string_ptr[0] = malloc((n + 1) * sizeof(char)) if not c_string_ptr[0]: return # malloc failed strcpy(c_string_ptr[0], hello_world) length[0] = n ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/const.pyx0000644000175100001770000000026400000000000023405 0ustar00runnerdocker00000000000000cdef extern from "someheader.h": ctypedef const char specialChar int process_string(const char* s) const unsigned char* look_up_cached_string(const unsigned char* key) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/cpp_string.pyx0000644000175100001770000000034300000000000024425 0ustar00runnerdocker00000000000000# distutils: language = c++ from libcpp.string cimport string def get_bytes(): py_bytes_object = b'hello world' cdef string s = py_bytes_object s.append('abc') py_bytes_object = s return py_bytes_object ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/decode.pyx0000644000175100001770000000032600000000000023501 0ustar00runnerdocker00000000000000from c_func cimport get_a_c_string cdef char* c_string = NULL cdef Py_ssize_t length = 0 # get pointer and length from a C function get_a_c_string(&c_string, &length) ustring = c_string[:length].decode('UTF-8') ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/decode_cpp_string.pyx0000644000175100001770000000034200000000000025727 0ustar00runnerdocker00000000000000# distutils: language = c++ from libcpp.string cimport string def get_ustrings(): cdef string s = string(b'abcdefg') ustring1 = s.decode('UTF-8') ustring2 = s[2:-2].decode('UTF-8') return ustring1, ustring2 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/for_bytes.pyx0000644000175100001770000000021600000000000024250 0ustar00runnerdocker00000000000000cdef bytes bytes_string = b"hello to A bytes' world" cdef char c for c in bytes_string: if c == 'A': print("Found the letter A") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/for_char.pyx0000644000175100001770000000021600000000000024037 0ustar00runnerdocker00000000000000cdef char* c_string = "Hello to A C-string's world" cdef char c for c in c_string[:11]: if c == 'A': print("Found the letter A") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/for_unicode.pyx0000644000175100001770000000024000000000000024545 0ustar00runnerdocker00000000000000cdef unicode ustring = u'Hello world' # NOTE: no typing required for 'uchar' ! for uchar in ustring: if uchar == u'A': print("Found the letter A") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/if_char_in.pyx0000644000175100001770000000026500000000000024341 0ustar00runnerdocker00000000000000cpdef void is_in(Py_UCS4 uchar_val): if uchar_val in u'abcABCxY': print("The character is in the string.") else: print("The character is not in the string") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/naive_decode.pyx0000644000175100001770000000022200000000000024656 0ustar00runnerdocker00000000000000from c_func cimport c_call_returning_a_c_string cdef char* some_c_string = c_call_returning_a_c_string() ustring = some_c_string.decode('UTF-8') ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/return_memview.pyx0000644000175100001770000000041700000000000025327 0ustar00runnerdocker00000000000000def process_byte_data(unsigned char[:] data): # ... process the data, here, dummy processing. cdef bint return_all = (data[0] == 108) if return_all: return bytes(data) else: # example for returning a slice return bytes(data[5:7]) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/slicing_c_string.pyx0000644000175100001770000000053500000000000025600 0ustar00runnerdocker00000000000000from libc.stdlib cimport free from c_func cimport get_a_c_string def main(): cdef char* c_string = NULL cdef Py_ssize_t length = 0 # get pointer and length from a C function get_a_c_string(&c_string, &length) try: py_bytes_string = c_string[:length] # Performs a copy of the data finally: free(c_string) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/someheader.h0000644000175100001770000000021400000000000023775 0ustar00runnerdocker00000000000000typedef const char specialChar; int process_string(const char* s); const unsigned char* look_up_cached_string(const unsigned char* key); ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/to_char.pyx0000644000175100001770000000043300000000000023674 0ustar00runnerdocker00000000000000# define a global name for whatever char type is used in the module ctypedef unsigned char char_type cdef char_type[:] _chars(s): if isinstance(s, unicode): # encode to the specific encoding used inside of the module s = (s).encode('utf8') return s ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/to_unicode.pxd0000644000175100001770000000002700000000000024357 0ustar00runnerdocker00000000000000cdef unicode _text(s) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/to_unicode.pyx0000644000175100001770000000136500000000000024412 0ustar00runnerdocker00000000000000# to_unicode.pyx from cpython.version cimport PY_MAJOR_VERSION cdef unicode _text(s): if type(s) is unicode: # Fast path for most common case(s). return s elif PY_MAJOR_VERSION < 3 and isinstance(s, bytes): # Only accept byte strings as text input in Python 2.x, not in Py3. return (s).decode('ascii') elif isinstance(s, unicode): # We know from the fast path above that 's' can only be a subtype here. # An evil cast to might still work in some(!) cases, # depending on what the further processing does. To be safe, # we can always create a copy instead. return unicode(s) else: raise TypeError("Could not convert to unicode.") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/try_finally.pyx0000644000175100001770000000032200000000000024606 0ustar00runnerdocker00000000000000from libc.stdlib cimport free from c_func cimport c_call_returning_a_c_string cdef bytes py_string cdef char* c_string = c_call_returning_a_c_string() try: py_string = c_string finally: free(c_string) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/tutorial/string/utf_eight.pyx0000644000175100001770000000060500000000000024234 0ustar00runnerdocker00000000000000from libc.stdlib cimport free cdef unicode tounicode(char* s): return s.decode('UTF-8', 'strict') cdef unicode tounicode_with_length( char* s, size_t length): return s[:length].decode('UTF-8', 'strict') cdef unicode tounicode_with_length_and_free( char* s, size_t length): try: return s[:length].decode('UTF-8', 'strict') finally: free(s)././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880490.980724 Cython-3.0.8/docs/examples/userguide/0000755000175100001770000000000000000000000020336 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.044724 Cython-3.0.8/docs/examples/userguide/buffer/0000755000175100001770000000000000000000000021607 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/buffer/matrix.py0000644000175100001770000000054300000000000023467 0ustar00runnerdocker00000000000000# distutils: language = c++ from cython.cimports.libcpp.vector import vector @cython.cclass class Matrix: ncols: cython.uint v: vector[cython.float] def __cinit__(self, ncols: cython.uint): self.ncols = ncols def add_row(self): """Adds a row, initially zero-filled.""" self.v.resize(self.v.size() + self.ncols) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/buffer/matrix.pyx0000644000175100001770000000050500000000000023655 0ustar00runnerdocker00000000000000# distutils: language = c++ from libcpp.vector cimport vector cdef class Matrix: cdef unsigned ncols cdef vector[float] v def __cinit__(self, unsigned ncols): self.ncols = ncols def add_row(self): """Adds a row, initially zero-filled.""" self.v.resize(self.v.size() + self.ncols) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/buffer/matrix_with_buffer.py0000644000175100001770000000344100000000000026053 0ustar00runnerdocker00000000000000# distutils: language = c++ from cython.cimports.cpython import Py_buffer from cython.cimports.libcpp.vector import vector @cython.cclass class Matrix: ncols: cython.Py_ssize_t shape: cython.Py_ssize_t[2] strides: cython.Py_ssize_t[2] v: vector[cython.float] def __cinit__(self, ncols: cython.Py_ssize_t): self.ncols = ncols def add_row(self): """Adds a row, initially zero-filled.""" self.v.resize(self.v.size() + self.ncols) def __getbuffer__(self, buffer: cython.pointer(Py_buffer), flags: cython.int): itemsize: cython.Py_ssize_t = cython.sizeof(self.v[0]) self.shape[0] = self.v.size() // self.ncols self.shape[1] = self.ncols # Stride 1 is the distance, in bytes, between two items in a row; # this is the distance between two adjacent items in the vector. # Stride 0 is the distance between the first elements of adjacent rows. self.strides[1] = cython.cast(cython.Py_ssize_t, ( cython.cast(cython.p_char, cython.address(self.v[1])) - cython.cast(cython.p_char, cython.address(self.v[0])) ) ) self.strides[0] = self.ncols * self.strides[1] buffer.buf = cython.cast(cython.p_char, cython.address(self.v[0])) buffer.format = 'f' # float buffer.internal = cython.NULL # see References buffer.itemsize = itemsize buffer.len = self.v.size() * itemsize # product(shape) * itemsize buffer.ndim = 2 buffer.obj = self buffer.readonly = 0 buffer.shape = self.shape buffer.strides = self.strides buffer.suboffsets = cython.NULL # for pointer arrays only def __releasebuffer__(self, buffer: cython.pointer(Py_buffer)): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/buffer/matrix_with_buffer.pyx0000644000175100001770000000307400000000000026245 0ustar00runnerdocker00000000000000# distutils: language = c++ from cpython cimport Py_buffer from libcpp.vector cimport vector cdef class Matrix: cdef Py_ssize_t ncols cdef Py_ssize_t[2] shape cdef Py_ssize_t[2] strides cdef vector[float] v def __cinit__(self, Py_ssize_t ncols): self.ncols = ncols def add_row(self): """Adds a row, initially zero-filled.""" self.v.resize(self.v.size() + self.ncols) def __getbuffer__(self, Py_buffer *buffer, int flags): cdef Py_ssize_t itemsize = sizeof(self.v[0]) self.shape[0] = self.v.size() // self.ncols self.shape[1] = self.ncols # Stride 1 is the distance, in bytes, between two items in a row; # this is the distance between two adjacent items in the vector. # Stride 0 is the distance between the first elements of adjacent rows. self.strides[1] = ( &(self.v[1]) - &(self.v[0])) self.strides[0] = self.ncols * self.strides[1] buffer.buf = &(self.v[0]) buffer.format = 'f' # float buffer.internal = NULL # see References buffer.itemsize = itemsize buffer.len = self.v.size() * itemsize # product(shape) * itemsize buffer.ndim = 2 buffer.obj = self buffer.readonly = 0 buffer.shape = self.shape buffer.strides = self.strides buffer.suboffsets = NULL # for pointer arrays only def __releasebuffer__(self, Py_buffer *buffer): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/buffer/view_count.py0000644000175100001770000000137400000000000024350 0ustar00runnerdocker00000000000000# distutils: language = c++ from cython.cimports.cpython import Py_buffer from cython.cimports.libcpp.vector import vector @cython.cclass class Matrix: view_count: cython.int ncols: cython.Py_ssize_t v: vector[cython.float] # ... def __cinit__(self, ncols: cython.Py_ssize_t): self.ncols = ncols self.view_count = 0 def add_row(self): if self.view_count > 0: raise ValueError("can't add row while being viewed") self.v.resize(self.v.size() + self.ncols) def __getbuffer__(self, buffer: cython.pointer(Py_buffer), flags: cython.int): # ... as before self.view_count += 1 def __releasebuffer__(self, buffer: cython.pointer(Py_buffer)): self.view_count -= 1 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/buffer/view_count.pyx0000644000175100001770000000123400000000000024533 0ustar00runnerdocker00000000000000# distutils: language = c++ from cpython cimport Py_buffer from libcpp.vector cimport vector cdef class Matrix: cdef int view_count cdef Py_ssize_t ncols cdef vector[float] v # ... def __cinit__(self, Py_ssize_t ncols): self.ncols = ncols self.view_count = 0 def add_row(self): if self.view_count > 0: raise ValueError("can't add row while being viewed") self.v.resize(self.v.size() + self.ncols) def __getbuffer__(self, Py_buffer *buffer, int flags): # ... as before self.view_count += 1 def __releasebuffer__(self, Py_buffer *buffer): self.view_count -= 1 ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.044724 Cython-3.0.8/docs/examples/userguide/early_binding_for_speed/0000755000175100001770000000000000000000000025172 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/early_binding_for_speed/rectangle.py0000644000175100001770000000100400000000000027503 0ustar00runnerdocker00000000000000@cython.cclass class Rectangle: x0: cython.int y0: cython.int x1: cython.int y1: cython.int def __init__(self, x0: cython.int, y0: cython.int, x1: cython.int, y1: cython.int): self.x0 = x0 self.y0 = y0 self.x1 = x1 self.y1 = y1 def area(self): area = (self.x1 - self.x0) * (self.y1 - self.y0) if area < 0: area = -area return area def rectArea(x0, y0, x1, y1): rect = Rectangle(x0, y0, x1, y1) return rect.area() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/early_binding_for_speed/rectangle.pyx0000644000175100001770000000067200000000000027705 0ustar00runnerdocker00000000000000 cdef class Rectangle: cdef int x0, y0 cdef int x1, y1 def __init__(self, int x0, int y0, int x1, int y1): self.x0 = x0 self.y0 = y0 self.x1 = x1 self.y1 = y1 def area(self): area = (self.x1 - self.x0) * (self.y1 - self.y0) if area < 0: area = -area return area def rectArea(x0, y0, x1, y1): rect = Rectangle(x0, y0, x1, y1) return rect.area() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/early_binding_for_speed/rectangle_cdef.py0000644000175100001770000000115600000000000030474 0ustar00runnerdocker00000000000000@cython.cclass class Rectangle: x0: cython.int y0: cython.int x1: cython.int y1: cython.int def __init__(self, x0: cython.int, y0: cython.int, x1: cython.int, y1: cython.int): self.x0 = x0 self.y0 = y0 self.x1 = x1 self.y1 = y1 @cython.cfunc def _area(self) -> cython.int: area: cython.int = (self.x1 - self.x0) * (self.y1 - self.y0) if area < 0: area = -area return area def area(self): return self._area() def rectArea(x0, y0, x1, y1): rect: Rectangle = Rectangle(x0, y0, x1, y1) return rect._area() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/early_binding_for_speed/rectangle_cdef.pyx0000644000175100001770000000101300000000000030654 0ustar00runnerdocker00000000000000 cdef class Rectangle: cdef int x0, y0 cdef int x1, y1 def __init__(self, int x0, int y0, int x1, int y1): self.x0 = x0 self.y0 = y0 self.x1 = x1 self.y1 = y1 cdef int _area(self): cdef int area = (self.x1 - self.x0) * (self.y1 - self.y0) if area < 0: area = -area return area def area(self): return self._area() def rectArea(x0, y0, x1, y1): cdef Rectangle rect = Rectangle(x0, y0, x1, y1) return rect._area() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/early_binding_for_speed/rectangle_cpdef.py0000644000175100001770000000107200000000000030651 0ustar00runnerdocker00000000000000@cython.cclass class Rectangle: x0: cython.int y0: cython.int x1: cython.int y1: cython.int def __init__(self, x0: cython.int, y0: cython.int, x1: cython.int, y1: cython.int): self.x0 = x0 self.y0 = y0 self.x1 = x1 self.y1 = y1 @cython.ccall def area(self)-> cython.int: area: cython.int = (self.x1 - self.x0) * (self.y1 - self.y0) if area < 0: area = -area return area def rectArea(x0, y0, x1, y1): rect: Rectangle = Rectangle(x0, y0, x1, y1) return rect.area() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/early_binding_for_speed/rectangle_cpdef.pyx0000644000175100001770000000073100000000000031042 0ustar00runnerdocker00000000000000 cdef class Rectangle: cdef int x0, y0 cdef int x1, y1 def __init__(self, int x0, int y0, int x1, int y1): self.x0 = x0 self.y0 = y0 self.x1 = x1 self.y1 = y1 cpdef int area(self): cdef int area = (self.x1 - self.x0) * (self.y1 - self.y0) if area < 0: area = -area return area def rectArea(x0, y0, x1, y1): cdef Rectangle rect = Rectangle(x0, y0, x1, y1) return rect.area() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.0487242 Cython-3.0.8/docs/examples/userguide/extension_types/0000755000175100001770000000000000000000000023576 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/extension_types/c_property.pyx0000644000175100001770000000075600000000000026536 0ustar00runnerdocker00000000000000cdef extern from "complexobject.h": struct Py_complex: double real double imag ctypedef class __builtin__.complex [object PyComplexObject]: cdef Py_complex cval @property cdef inline double real(self): return self.cval.real @property cdef inline double imag(self): return self.cval.imag def cprint(complex c): print(f"{c.real :.4f}{c.imag :+.4f}j") # uses C calls to the above property methods. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/extension_types/cheesy.py0000644000175100001770000000107500000000000025433 0ustar00runnerdocker00000000000000import cython @cython.cclass class CheeseShop: cheeses: object def __cinit__(self): self.cheeses = [] @property def cheese(self): return "We don't have: %s" % self.cheeses @cheese.setter def cheese(self, value): self.cheeses.append(value) @cheese.deleter def cheese(self): del self.cheeses[:] # Test input from cheesy import CheeseShop shop = CheeseShop() print(shop.cheese) shop.cheese = "camembert" print(shop.cheese) shop.cheese = "cheddar" print(shop.cheese) del shop.cheese print(shop.cheese) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/extension_types/cheesy.pyx0000644000175100001770000000105400000000000025620 0ustar00runnerdocker00000000000000 cdef class CheeseShop: cdef object cheeses def __cinit__(self): self.cheeses = [] @property def cheese(self): return "We don't have: %s" % self.cheeses @cheese.setter def cheese(self, value): self.cheeses.append(value) @cheese.deleter def cheese(self): del self.cheeses[:] # Test input from cheesy import CheeseShop shop = CheeseShop() print(shop.cheese) shop.cheese = "camembert" print(shop.cheese) shop.cheese = "cheddar" print(shop.cheese) del shop.cheese print(shop.cheese) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/extension_types/dataclass.py0000644000175100001770000000101400000000000026103 0ustar00runnerdocker00000000000000import cython try: import typing import dataclasses except ImportError: pass # The modules don't actually have to exists for Cython to use them as annotations @dataclasses.dataclass @cython.cclass class MyDataclass: # fields can be declared using annotations a: cython.int = 0 b: double = dataclasses.field(default_factory = lambda: 10, repr=False) c: str = 'hello' # typing.InitVar and typing.ClassVar also work d: dataclasses.InitVar[double] = 5 e: typing.ClassVar[list] = [] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/extension_types/dataclass.pyx0000644000175100001770000000116500000000000026302 0ustar00runnerdocker00000000000000cimport cython try: import typing import dataclasses except ImportError: pass # The modules don't actually have to exists for Cython to use them as annotations @dataclasses.dataclass cdef class MyDataclass: # fields can be declared using annotations a: cython.int = 0 b: double = dataclasses.field(default_factory = lambda: 10, repr=False) # fields can also be declared using `cdef`: cdef str c c = "hello" # assignment of default value on a separate line # typing.InitVar and typing.ClassVar also work d: dataclasses.InitVar[cython.double] = 5 e: typing.ClassVar[list] = [] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/extension_types/dict_animal.py0000644000175100001770000000033100000000000026411 0ustar00runnerdocker00000000000000@cython.cclass class Animal: number_of_legs: cython.int __dict__: dict def __cinit__(self, number_of_legs: cython.int): self.number_of_legs = number_of_legs dog = Animal(4) dog.has_tail = True ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/extension_types/dict_animal.pyx0000644000175100001770000000031100000000000026577 0ustar00runnerdocker00000000000000 cdef class Animal: cdef int number_of_legs cdef dict __dict__ def __init__(self, int number_of_legs): self.number_of_legs = number_of_legs dog = Animal(4) dog.has_tail = True ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/extension_types/extendable_animal.py0000644000175100001770000000044500000000000027607 0ustar00runnerdocker00000000000000@cython.cclass class Animal: number_of_legs: cython.int def __cinit__(self, number_of_legs: cython.int): self.number_of_legs = number_of_legs class ExtendableAnimal(Animal): # Note that we use class, not cdef class pass dog = ExtendableAnimal(4) dog.has_tail = True ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/extension_types/extendable_animal.pyx0000644000175100001770000000042100000000000027771 0ustar00runnerdocker00000000000000 cdef class Animal: cdef int number_of_legs def __init__(self, int number_of_legs): self.number_of_legs = number_of_legs class ExtendableAnimal(Animal): # Note that we use class, not cdef class pass dog = ExtendableAnimal(4) dog.has_tail = True ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/extension_types/my_module.pxd0000644000175100001770000000006300000000000026304 0ustar00runnerdocker00000000000000cdef class Shrubbery: cdef int width, height ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/extension_types/my_module.pyx0000644000175100001770000000037700000000000026341 0ustar00runnerdocker00000000000000from __future__ import print_function cdef class Shrubbery: def __init__(self, w, h): self.width = w self.height = h def describe(self): print("This shrubbery is", self.width, "by", self.height, "cubits.") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3487222 Cython-3.0.8/docs/examples/userguide/extension_types/owned_pointer.py0000644000175100001770000000057200000000000027030 0ustar00runnerdocker00000000000000import cython from cython.cimports.libc.stdlib import free @cython.cclass class OwnedPointer: ptr: cython.pointer(cython.void) def __dealloc__(self): if self.ptr is not cython.NULL: free(self.ptr) @staticmethod @cython.cfunc def create(ptr: cython.pointer(cython.void)): p = OwnedPointer() p.ptr = ptr return p ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/owned_pointer.pyx0000644000175100001770000000042600000000000027216 0ustar00runnerdocker00000000000000 from libc.stdlib cimport free cdef class OwnedPointer: cdef void* ptr def __dealloc__(self): if self.ptr is not NULL: free(self.ptr) @staticmethod cdef create(void* ptr): p = OwnedPointer() p.ptr = ptr return p ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/penguin.py0000644000175100001770000000044400000000000025617 0ustar00runnerdocker00000000000000import cython @cython.cclass class Penguin: food: object def __cinit__(self, food): self.food = food def __init__(self, food): print("eating!") normal_penguin = Penguin('fish') fast_penguin = Penguin.__new__(Penguin, 'wheat') # note: not calling __init__() ! ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/penguin.pyx0000644000175100001770000000042300000000000026004 0ustar00runnerdocker00000000000000 cdef class Penguin: cdef object food def __cinit__(self, food): self.food = food def __init__(self, food): print("eating!") normal_penguin = Penguin('fish') fast_penguin = Penguin.__new__(Penguin, 'wheat') # note: not calling __init__() ! ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/penguin2.py0000644000175100001770000000036700000000000025705 0ustar00runnerdocker00000000000000import cython @cython.freelist(8) @cython.cclass class Penguin: food: object def __cinit__(self, food): self.food = food penguin = Penguin('fish 1') penguin = None penguin = Penguin('fish 2') # does not need to allocate memory! ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/penguin2.pyx0000644000175100001770000000036300000000000026071 0ustar00runnerdocker00000000000000cimport cython @cython.freelist(8) cdef class Penguin: cdef object food def __cinit__(self, food): self.food = food penguin = Penguin('fish 1') penguin = None penguin = Penguin('fish 2') # does not need to allocate memory! ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/pets.py0000644000175100001770000000062100000000000025122 0ustar00runnerdocker00000000000000import cython @cython.cclass class Parrot: @cython.cfunc def describe(self) -> cython.void: print("This parrot is resting.") @cython.cclass class Norwegian(Parrot): @cython.cfunc def describe(self) -> cython.void: Parrot.describe(self) print("Lovely plumage!") cython.declare(p1=Parrot, p2=Parrot) p1 = Parrot() p2 = Norwegian() print("p2:") p2.describe() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/pets.pyx0000644000175100001770000000045500000000000025317 0ustar00runnerdocker00000000000000 cdef class Parrot: cdef void describe(self): print("This parrot is resting.") cdef class Norwegian(Parrot): cdef void describe(self): Parrot.describe(self) print("Lovely plumage!") cdef Parrot p1, p2 p1 = Parrot() p2 = Norwegian() print("p2:") p2.describe() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/python_access.py0000644000175100001770000000035000000000000027010 0ustar00runnerdocker00000000000000import cython @cython.cclass class Shrubbery: width = cython.declare(cython.int, visibility='public') height = cython.declare(cython.int, visibility='public') depth = cython.declare(cython.float, visibility='readonly') ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/python_access.pyx0000644000175100001770000000013300000000000027177 0ustar00runnerdocker00000000000000 cdef class Shrubbery: cdef public int width, height cdef readonly float depth ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/shrubbery.py0000644000175100001770000000041700000000000026157 0ustar00runnerdocker00000000000000@cython.cclass class Shrubbery: width: cython.int height: cython.int def __init__(self, w, h): self.width = w self.height = h def describe(self): print("This shrubbery is", self.width, "by", self.height, "cubits.") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/shrubbery.pyx0000644000175100001770000000044500000000000026350 0ustar00runnerdocker00000000000000from __future__ import print_function cdef class Shrubbery: cdef int width cdef int height def __init__(self, w, h): self.width = w self.height = h def describe(self): print("This shrubbery is", self.width, "by", self.height, "cubits.") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/shrubbery_2.py0000644000175100001770000000035700000000000026403 0ustar00runnerdocker00000000000000import cython from cython.cimports.my_module import Shrubbery @cython.cfunc def another_shrubbery(sh1: Shrubbery) -> Shrubbery: sh2: Shrubbery sh2 = Shrubbery() sh2.width = sh1.width sh2.height = sh1.height return sh2 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/shrubbery_2.pyx0000644000175100001770000000031000000000000026560 0ustar00runnerdocker00000000000000 from my_module cimport Shrubbery cdef Shrubbery another_shrubbery(Shrubbery sh1): cdef Shrubbery sh2 sh2 = Shrubbery() sh2.width = sh1.width sh2.height = sh1.height return sh2 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/widen_shrubbery.py0000644000175100001770000000024400000000000027343 0ustar00runnerdocker00000000000000import cython from cython.cimports.my_module import Shrubbery @cython.cfunc def widen_shrubbery(sh: Shrubbery, extra_width): sh.width = sh.width + extra_width ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/widen_shrubbery.pyx0000644000175100001770000000017400000000000027535 0ustar00runnerdocker00000000000000 from my_module cimport Shrubbery cdef widen_shrubbery(Shrubbery sh, extra_width): sh.width = sh.width + extra_width ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/wrapper_class.py0000644000175100001770000000416000000000000027016 0ustar00runnerdocker00000000000000import cython from cython.cimports.libc.stdlib import malloc, free # Example C struct my_c_struct = cython.struct( a = cython.int, b = cython.int, ) @cython.cclass class WrapperClass: """A wrapper class for a C/C++ data structure""" _ptr: cython.pointer(my_c_struct) ptr_owner: cython.bint def __cinit__(self): self.ptr_owner = False def __dealloc__(self): # De-allocate if not null and flag is set if self._ptr is not cython.NULL and self.ptr_owner is True: free(self._ptr) self._ptr = cython.NULL def __init__(self): # Prevent accidental instantiation from normal Python code # since we cannot pass a struct pointer into a Python constructor. raise TypeError("This class cannot be instantiated directly.") # Extension class properties @property def a(self): return self._ptr.a if self._ptr is not cython.NULL else None @property def b(self): return self._ptr.b if self._ptr is not cython.NULL else None @staticmethod @cython.cfunc def from_ptr(_ptr: cython.pointer(my_c_struct), owner: cython.bint=False) -> WrapperClass: """Factory function to create WrapperClass objects from given my_c_struct pointer. Setting ``owner`` flag to ``True`` causes the extension type to ``free`` the structure pointed to by ``_ptr`` when the wrapper object is deallocated.""" # Fast call to __new__() that bypasses the __init__() constructor. wrapper: WrapperClass = WrapperClass.__new__(WrapperClass) wrapper._ptr = _ptr wrapper.ptr_owner = owner return wrapper @staticmethod @cython.cfunc def new_struct() -> WrapperClass: """Factory function to create WrapperClass objects with newly allocated my_c_struct""" _ptr: cython.pointer(my_c_struct) = cython.cast( cython.pointer(my_c_struct), malloc(cython.sizeof(my_c_struct))) if _ptr is cython.NULL: raise MemoryError _ptr.a = 0 _ptr.b = 0 return WrapperClass.from_ptr(_ptr, owner=True) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/extension_types/wrapper_class.pyx0000644000175100001770000000361600000000000027213 0ustar00runnerdocker00000000000000 from libc.stdlib cimport malloc, free # Example C struct ctypedef struct my_c_struct: int a int b cdef class WrapperClass: """A wrapper class for a C/C++ data structure""" cdef my_c_struct *_ptr cdef bint ptr_owner def __cinit__(self): self.ptr_owner = False def __dealloc__(self): # De-allocate if not null and flag is set if self._ptr is not NULL and self.ptr_owner is True: free(self._ptr) self._ptr = NULL def __init__(self): # Prevent accidental instantiation from normal Python code # since we cannot pass a struct pointer into a Python constructor. raise TypeError("This class cannot be instantiated directly.") # Extension class properties @property def a(self): return self._ptr.a if self._ptr is not NULL else None @property def b(self): return self._ptr.b if self._ptr is not NULL else None @staticmethod cdef WrapperClass from_ptr(my_c_struct *_ptr, bint owner=False): """Factory function to create WrapperClass objects from given my_c_struct pointer. Setting ``owner`` flag to ``True`` causes the extension type to ``free`` the structure pointed to by ``_ptr`` when the wrapper object is deallocated.""" # Fast call to __new__() that bypasses the __init__() constructor. cdef WrapperClass wrapper = WrapperClass.__new__(WrapperClass) wrapper._ptr = _ptr wrapper.ptr_owner = owner return wrapper @staticmethod cdef WrapperClass new_struct(): """Factory function to create WrapperClass objects with newly allocated my_c_struct""" cdef my_c_struct *_ptr = malloc(sizeof(my_c_struct)) if _ptr is NULL: raise MemoryError _ptr.a = 0 _ptr.b = 0 return WrapperClass.from_ptr(_ptr, owner=True) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.0487242 Cython-3.0.8/docs/examples/userguide/external_C_code/0000755000175100001770000000000000000000000023414 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/external_C_code/delorean.pyx0000644000175100001770000000031000000000000025741 0ustar00runnerdocker00000000000000# delorean.pyx cdef public struct Vehicle: int speed float power cdef api void activate(Vehicle *v) except *: if v.speed >= 88 and v.power >= 1.21: print("Time travel achieved") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/external_C_code/marty.c0000644000175100001770000000045500000000000024720 0ustar00runnerdocker00000000000000# marty.c #include "delorean_api.h" Vehicle car; int main(int argc, char *argv[]) { Py_Initialize(); import_delorean(); car.speed = atoi(argv[1]); car.power = atof(argv[2]); activate(&car); /* Error handling left out - call PyErr_Occurred() to test for Python exceptions. */ Py_Finalize(); } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/external_C_code/platform_adaptation.pyx0000644000175100001770000000065100000000000030210 0ustar00runnerdocker00000000000000cdef extern from *: """ #if defined(_WIN32) || defined(MS_WINDOWS) || defined(_MSC_VER) #include "stdlib.h" #define myapp_sleep(m) _sleep(m) #else #include #define myapp_sleep(m) ((void) usleep((m) * 1000)) #endif """ # using "myapp_" prefix in the C code to prevent C naming conflicts void msleep "myapp_sleep"(int milliseconds) nogil msleep(milliseconds=1) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/external_C_code/struct_field_adaptation.h0000644000175100001770000000033200000000000030456 0ustar00runnerdocker00000000000000typedef struct { int field1; int field2; int newly_added_field; } StructType; static StructType global_struct; static StructType *get_struct_ptr() { return &global_struct; } #define C_LIB_VERSION 20 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/external_C_code/struct_field_adaptation.pyx0000644000175100001770000000214400000000000031052 0ustar00runnerdocker00000000000000cdef extern from "struct_field_adaptation.h": """ #define HAS_NEWLY_ADDED_FIELD (C_LIB_VERSION >= 20) #if HAS_NEWLY_ADDED_FIELD #define _mylib_get_newly_added_field(a_struct_ptr) ((a_struct_ptr)->newly_added_field) #define _mylib_set_newly_added_field(a_struct_ptr, value) ((a_struct_ptr)->newly_added_field) = (value) #else #define _mylib_get_newly_added_field(a_struct_ptr) (0) #define _mylib_set_newly_added_field(a_struct_ptr, value) ((void) (value)) #endif """ # Normal declarations provided by the C header file: ctypedef struct StructType: int field1 int field2 StructType *get_struct_ptr() # Special declarations conditionally provided above: bint HAS_NEWLY_ADDED_FIELD int get_newly_added_field "_mylib_get_newly_added_field" (StructType *struct_ptr) void set_newly_added_field "_mylib_set_newly_added_field" (StructType *struct_ptr, int value) cdef StructType *some_struct_ptr = get_struct_ptr() print(some_struct_ptr.field1) if HAS_NEWLY_ADDED_FIELD: print(get_newly_added_field(some_struct_ptr)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/external_C_code/verbatim_c_code.pyx0000644000175100001770000000040300000000000027260 0ustar00runnerdocker00000000000000cdef extern from *: """ /* This is C code which will be put * in the .c file output by Cython */ static long square(long x) {return x * x;} #define assign(x, y) ((x) = (y)) """ long square(long x) void assign(long& x, long y) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.0487242 Cython-3.0.8/docs/examples/userguide/fusedtypes/0000755000175100001770000000000000000000000022531 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/fusedtypes/char_or_float.py0000644000175100001770000000047700000000000025715 0ustar00runnerdocker00000000000000from __future__ import print_function char_or_float = cython.fused_type(cython.char, cython.float) @cython.ccall def plus_one(var: char_or_float) -> char_or_float: return var + 1 def show_me(): a: cython.char = 127 b: cython.float = 127 print('char', plus_one(a)) print('float', plus_one(b)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/fusedtypes/char_or_float.pyx0000644000175100001770000000044300000000000026076 0ustar00runnerdocker00000000000000from __future__ import print_function ctypedef fused char_or_float: char float cpdef char_or_float plus_one(char_or_float var): return var + 1 def show_me(): cdef: char a = 127 float b = 127 print('char', plus_one(a)) print('float', plus_one(b)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/fusedtypes/conditional_gil.py0000644000175100001770000000064100000000000026242 0ustar00runnerdocker00000000000000import cython double_or_object = cython.fused_type(cython.double, object) def increment(x: double_or_object): with cython.nogil(double_or_object is not object): # Same code handles both cython.double (GIL is released) # and python object (GIL is not released). x = x + 1 return x increment(5.0) # GIL is released during increment increment(5) # GIL is acquired during increment ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/fusedtypes/conditional_gil.pyx0000644000175100001770000000062500000000000026434 0ustar00runnerdocker00000000000000cimport cython ctypedef fused double_or_object: double object def increment(double_or_object x): with nogil(double_or_object is not object): # Same code handles both cython.double (GIL is released) # and python object (GIL is not released). x = x + 1 return x increment(5.0) # GIL is released during increment increment(5) # GIL is acquired during increment ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/fusedtypes/indexing.py0000644000175100001770000000132700000000000024713 0ustar00runnerdocker00000000000000import cython fused_type1 = cython.fused_type(cython.double, cython.float) fused_type2 = cython.fused_type(cython.double, cython.float) @cython.cfunc def cfunc(arg1: fused_type1, arg2: fused_type1): print("cfunc called:", cython.typeof(arg1), arg1, cython.typeof(arg2), arg2) @cython.ccall def cpfunc(a: fused_type1, b: fused_type2): print("cpfunc called:", cython.typeof(a), a, cython.typeof(b), b) def func(a: fused_type1, b: fused_type2): print("func called:", cython.typeof(a), a, cython.typeof(b), b) # called from Cython space cfunc[cython.double](5.0, 1.0) cpfunc[cython.float, cython.double](1.0, 2.0) # Indexing def functions in Cython code requires string names func["float", "double"](1.0, 2.0) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/fusedtypes/indexing.pyx0000644000175100001770000000121100000000000025073 0ustar00runnerdocker00000000000000cimport cython ctypedef fused fused_type1: double float ctypedef fused fused_type2: double float cdef cfunc(fused_type1 arg1, fused_type1 arg2): print("cfunc called:", cython.typeof(arg1), arg1, cython.typeof(arg2), arg2) cpdef cpfunc(fused_type1 a, fused_type2 b): print("cpfunc called:", cython.typeof(a), a, cython.typeof(b), b) def func(fused_type1 a, fused_type2 b): print("func called:", cython.typeof(a), a, cython.typeof(b), b) # called from Cython space cfunc[double](5.0, 1.0) cpfunc[float, double](1.0, 2.0) # Indexing def function in Cython code requires string names func["float", "double"](1.0, 2.0) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/fusedtypes/pointer.py0000644000175100001770000000037600000000000024571 0ustar00runnerdocker00000000000000my_fused_type = cython.fused_type(cython.int, cython.float) @cython.cfunc def func(a: cython.pointer(my_fused_type)): print(a[0]) def main(): a: cython.int = 3 b: cython.float = 5.0 func(cython.address(a)) func(cython.address(b)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/fusedtypes/pointer.pyx0000644000175100001770000000022700000000000024754 0ustar00runnerdocker00000000000000ctypedef fused my_fused_type: int double cdef func(my_fused_type *a): print(a[0]) cdef int b = 3 cdef double c = 3.0 func(&b) func(&c) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/fusedtypes/type_checking.py0000644000175100001770000000140500000000000025717 0ustar00runnerdocker00000000000000bunch_of_types = cython.fused_type(bytes, cython.int, cython.float) string_t = cython.fused_type(cython.p_char, bytes, unicode) @cython.cfunc def myfunc(i: cython.integral, s: bunch_of_types) -> cython.integral: # Only one of these branches will be compiled for each specialization! if cython.integral is int: print('i is an int') elif cython.integral is long: print('i is a long') else: print('i is a short') if bunch_of_types in string_t: print("s is a string!") return i * 2 myfunc(cython.cast(cython.int, 5), b'm') # will print "i is an int" and "s is a string" myfunc(cython.cast(cython.long, 5), 3) # will print "i is a long" myfunc(cython.cast(cython.short, 5), 3) # will print "i is a short" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/fusedtypes/type_checking.pyx0000644000175100001770000000127000000000000026107 0ustar00runnerdocker00000000000000cimport cython ctypedef fused bunch_of_types: bytes int float ctypedef fused string_t: cython.p_char bytes unicode cdef cython.integral myfunc(cython.integral i, bunch_of_types s): # Only one of these branches will be compiled for each specialization! if cython.integral is int: print('i is int') elif cython.integral is long: print('i is long') else: print('i is short') if bunch_of_types in string_t: print("s is a string!") return i * 2 myfunc( 5, b'm') # will print "i is an int" and "s is a string" myfunc( 5, 3) # will print "i is a long" myfunc( 5, 3) # will print "i is a short" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.0527241 Cython-3.0.8/docs/examples/userguide/language_basics/0000755000175100001770000000000000000000000023445 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/casting_python.pxd0000644000175100001770000000007000000000000027210 0ustar00runnerdocker00000000000000cdef extern from *: ctypedef Py_ssize_t Py_intptr_t ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/casting_python.py0000644000175100001770000000153200000000000027051 0ustar00runnerdocker00000000000000from cython.cimports.cpython.ref import PyObject def main(): python_string = "foo" # Note that the variables below are automatically inferred # as the correct pointer type that is assigned to them. # They do not need to be typed explicitly. ptr = cython.cast(cython.p_void, python_string) adress_in_c = cython.cast(Py_intptr_t, ptr) address_from_void = adress_in_c # address_from_void is a python int ptr2 = cython.cast(cython.pointer(PyObject), python_string) address_in_c2 = cython.cast(Py_intptr_t, ptr2) address_from_PyObject = address_in_c2 # address_from_PyObject is a python int assert address_from_void == address_from_PyObject == id(python_string) print(cython.cast(object, ptr)) # Prints "foo" print(cython.cast(object, ptr2)) # prints "foo" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/casting_python.pyx0000644000175100001770000000117300000000000027242 0ustar00runnerdocker00000000000000from cpython.ref cimport PyObject cdef extern from *: ctypedef Py_ssize_t Py_intptr_t python_string = "foo" cdef void* ptr = python_string cdef Py_intptr_t adress_in_c = ptr address_from_void = adress_in_c # address_from_void is a python int cdef PyObject* ptr2 = python_string cdef Py_intptr_t address_in_c2 = ptr2 address_from_PyObject = address_in_c2 # address_from_PyObject is a python int assert address_from_void == address_from_PyObject == id(python_string) print(ptr) # Prints "foo" print(ptr2) # prints "foo" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/cdef_block.pyx0000644000175100001770000000026700000000000026267 0ustar00runnerdocker00000000000000from __future__ import print_function cdef: struct Spam: int tons int i float a Spam *p void f(Spam *s) except *: print(s.tons, "Tons of spam") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/compile_time.pyx0000644000175100001770000000032100000000000026651 0ustar00runnerdocker00000000000000from __future__ import print_function DEF FavouriteFood = u"spam" DEF ArraySize = 42 DEF OtherArraySize = 2 * ArraySize + 17 cdef int[ArraySize] a1 cdef int[OtherArraySize] a2 print("I like", FavouriteFood) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/enum.pyx0000644000175100001770000000025200000000000025152 0ustar00runnerdocker00000000000000cdef enum CheeseType: cheddar, edam, camembert cdef enum CheeseState: hard = 1 soft = 2 runny = 3 print(CheeseType.cheddar) print(CheeseState.hard) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/function_pointer.pyx0000644000175100001770000000016000000000000027571 0ustar00runnerdocker00000000000000cdef int(*ptr_add)(int, int) cdef int add(int a, int b): return a + b ptr_add = add print(ptr_add(1, 3)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/function_pointer_struct.pyx0000644000175100001770000000021000000000000031171 0ustar00runnerdocker00000000000000cdef struct Bar: int sum(int a, int b) cdef int add(int a, int b): return a + b cdef Bar bar = Bar(add) print(bar.sum(1, 2)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/kwargs_1.pyx0000644000175100001770000000020500000000000025722 0ustar00runnerdocker00000000000000def f(a, b, *args, c, d = 42, e, **kwds): ... # We cannot call f with less verbosity than this. foo = f(4, "bar", c=68, e=1.0) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/kwargs_2.pyx0000644000175100001770000000017400000000000025730 0ustar00runnerdocker00000000000000def g(a, b, *, c, d): ... # We cannot call g with less verbosity than this. foo = g(4.0, "something", c=68, d="other") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/open_file.py0000644000175100001770000000127500000000000025764 0ustar00runnerdocker00000000000000from cython.cimports.libc.stdio import FILE, fopen from cython.cimports.libc.stdlib import malloc, free from cython.cimports.cpython.exc import PyErr_SetFromErrnoWithFilenameObject def open_file(): p = fopen("spam.txt", "r") # The type of "p" is "FILE*", as returned by fopen(). if p is cython.NULL: PyErr_SetFromErrnoWithFilenameObject(OSError, "spam.txt") ... def allocating_memory(number=10): # Note that the type of the variable "my_array" is automatically inferred from the assignment. my_array = cython.cast(p_double, malloc(number * cython.sizeof(double))) if not my_array: # same as 'is NULL' above raise MemoryError() ... free(my_array) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/open_file.pyx0000644000175100001770000000077000000000000026153 0ustar00runnerdocker00000000000000from libc.stdio cimport FILE, fopen from libc.stdlib cimport malloc, free from cpython.exc cimport PyErr_SetFromErrnoWithFilenameObject def open_file(): cdef FILE* p p = fopen("spam.txt", "r") if p is NULL: PyErr_SetFromErrnoWithFilenameObject(OSError, "spam.txt") ... def allocating_memory(number=10): cdef double *my_array = malloc(number * sizeof(double)) if not my_array: # same as 'is NULL' above raise MemoryError() ... free(my_array) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/optional_subclassing.pxd0000644000175100001770000000020700000000000030403 0ustar00runnerdocker00000000000000cdef class A: cdef foo(self) cdef class B(A): cdef foo(self, x=*) cdef class C(B): cpdef foo(self, x=*, int k=*) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/optional_subclassing.py0000644000175100001770000000051200000000000030237 0ustar00runnerdocker00000000000000from __future__ import print_function @cython.cclass class A: @cython.cfunc def foo(self): print("A") @cython.cclass class B(A): @cython.cfunc def foo(self, x=None): print("B", x) @cython.cclass class C(B): @cython.ccall def foo(self, x=True, k:cython.int = 3): print("C", x, k) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/optional_subclassing.pyx0000644000175100001770000000036700000000000030437 0ustar00runnerdocker00000000000000from __future__ import print_function cdef class A: cdef foo(self): print("A") cdef class B(A): cdef foo(self, x=None): print("B", x) cdef class C(B): cpdef foo(self, x=True, int k=3): print("C", x, k) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/override.py0000644000175100001770000000043300000000000025636 0ustar00runnerdocker00000000000000from __future__ import print_function @cython.cclass class A: @cython.cfunc def foo(self): print("A") @cython.cclass class B(A): @cython.ccall def foo(self): print("B") class C(B): # NOTE: no cclass decorator def foo(self): print("C") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/override.pyx0000644000175100001770000000034500000000000026030 0ustar00runnerdocker00000000000000from __future__ import print_function cdef class A: cdef foo(self): print("A") cdef class B(A): cpdef foo(self): print("B") class C(B): # NOTE: not cdef class def foo(self): print("C") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/parameter_refcount.py0000644000175100001770000000132400000000000027704 0ustar00runnerdocker00000000000000from __future__ import print_function from cython.cimports.cpython.ref import PyObject import sys python_dict = {"abc": 123} python_dict_refcount = sys.getrefcount(python_dict) @cython.cfunc def owned_reference(obj: object): refcount = sys.getrefcount(python_dict) print('Inside owned_reference: {refcount}'.format(refcount=refcount)) @cython.cfunc def borrowed_reference(obj: cython.pointer(PyObject)): refcount = obj.ob_refcnt print('Inside borrowed_reference: {refcount}'.format(refcount=refcount)) def main(): print('Initial refcount: {refcount}'.format(refcount=python_dict_refcount)) owned_reference(python_dict) borrowed_reference(cython.cast(cython.pointer(PyObject), python_dict)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/parameter_refcount.pyx0000644000175100001770000000115300000000000030074 0ustar00runnerdocker00000000000000from __future__ import print_function from cpython.ref cimport PyObject import sys python_dict = {"abc": 123} python_dict_refcount = sys.getrefcount(python_dict) cdef owned_reference(object obj): refcount = sys.getrefcount(python_dict) print('Inside owned_reference: {refcount}'.format(refcount=refcount)) cdef borrowed_reference(PyObject * obj): refcount = obj.ob_refcnt print('Inside borrowed_reference: {refcount}'.format(refcount=refcount)) print('Initial refcount: {refcount}'.format(refcount=python_dict_refcount)) owned_reference(python_dict) borrowed_reference(python_dict) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/struct.py0000644000175100001770000000022500000000000025342 0ustar00runnerdocker00000000000000Grail = cython.struct( age=cython.int, volume=cython.float) def main(): grail: Grail = Grail(5, 3.0) print(grail.age, grail.volume) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/struct.pyx0000644000175100001770000000020500000000000025530 0ustar00runnerdocker00000000000000cdef struct Grail: int age float volume def main(): cdef Grail grail = Grail(5, 3.0) print(grail.age, grail.volume) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/union.py0000644000175100001770000000033300000000000025146 0ustar00runnerdocker00000000000000Food = cython.union( spam=cython.p_char, eggs=cython.p_float) def main(): arr: cython.p_float = [1.0, 2.0] spam: Food = Food(spam='b') eggs: Food = Food(eggs=arr) print(spam.spam, eggs.eggs[0]) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/language_basics/union.pyx0000644000175100001770000000031100000000000025332 0ustar00runnerdocker00000000000000cdef union Food: char *spam float *eggs def main(): cdef float *arr = [1.0, 2.0] cdef Food spam = Food(spam='b') cdef Food eggs = Food(eggs=arr) print(spam.spam, eggs.eggs[0]) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.0527241 Cython-3.0.8/docs/examples/userguide/memoryviews/0000755000175100001770000000000000000000000022724 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/C_func_file.c0000644000175100001770000000025400000000000025265 0ustar00runnerdocker00000000000000#include "C_func_file.h" void multiply_by_10_in_C(double arr[], unsigned int n) { unsigned int i; for (i = 0; i < n; i++) { arr[i] *= 10; } } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/C_func_file.h0000644000175100001770000000016300000000000025271 0ustar00runnerdocker00000000000000#ifndef C_FUNC_FILE_H #define C_FUNC_FILE_H void multiply_by_10_in_C(double arr[], unsigned int n); #endif ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/add_one.py0000644000175100001770000000051700000000000024672 0ustar00runnerdocker00000000000000import numpy as np def add_one(buf: cython.int[:,:]): for x in range(buf.shape[0]): for y in range(buf.shape[1]): buf[x, y] += 1 # exporting_object must be a Python object # implementing the buffer interface, e.g. a numpy array. exporting_object = np.zeros((10, 20), dtype=np.intc) add_one(exporting_object) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/add_one.pyx0000644000175100001770000000050700000000000025061 0ustar00runnerdocker00000000000000import numpy as np def add_one(int[:,:] buf): for x in range(buf.shape[0]): for y in range(buf.shape[1]): buf[x, y] += 1 # exporting_object must be a Python object # implementing the buffer interface, e.g. a numpy array. exporting_object = np.zeros((10, 20), dtype=np.intc) add_one(exporting_object) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/copy.py0000644000175100001770000000052000000000000024245 0ustar00runnerdocker00000000000000import numpy as np def main(): to_view: cython.int[:, :, :] = np.empty((20, 15, 30), dtype=np.intc) from_view: cython.int[:, :, :] = np.ones((20, 15, 30), dtype=np.intc) # copy the elements in from_view to to_view to_view[...] = from_view # or to_view[:] = from_view # or to_view[:, :, :] = from_view ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/copy.pyx0000644000175100001770000000043700000000000024444 0ustar00runnerdocker00000000000000import numpy as np cdef int[:, :, :] to_view, from_view to_view = np.empty((20, 15, 30), dtype=np.intc) from_view = np.ones((20, 15, 30), dtype=np.intc) # copy the elements in from_view to to_view to_view[...] = from_view # or to_view[:] = from_view # or to_view[:, :, :] = from_view ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/cpython_array.py0000644000175100001770000000035200000000000026160 0ustar00runnerdocker00000000000000def sum_array(view: cython.int[:]): """ >>> from array import array >>> sum_array( array('i', [1,2,3]) ) 6 """ total: cython.int = 0 for i in range(view.shape[0]): total += view[i] return total ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/cpython_array.pyx0000644000175100001770000000033700000000000026353 0ustar00runnerdocker00000000000000def sum_array(int[:] view): """ >>> from array import array >>> sum_array( array('i', [1,2,3]) ) 6 """ cdef int total = 0 for i in range(view.shape[0]): total += view[i] return total ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/custom_dtype.pyx0000644000175100001770000000076700000000000026217 0ustar00runnerdocker00000000000000import numpy as np CUSTOM_DTYPE = np.dtype([ ('x', np.uint8), ('y', np.float32), ]) a = np.zeros(100, dtype=CUSTOM_DTYPE) cdef packed struct custom_dtype_struct: # The struct needs to be packed since by default numpy dtypes aren't # aligned unsigned char x float y def sum(custom_dtype_struct [:] a): cdef: unsigned char sum_x = 0 float sum_y = 0. for i in range(a.shape[0]): sum_x += a[i].x sum_y += a[i].y return sum_x, sum_y ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/cython_array.py0000644000175100001770000000046600000000000026006 0ustar00runnerdocker00000000000000# tag: numpy import numpy from cython.cimports.numpy import int32_t def main(): a: int32_t[:] = numpy.arange(10, dtype=numpy.int32) a = a[::2] print(a) print(numpy.asarray(a)) print(a.base) # this prints: # # [0 2 4 6 8] # [0 1 2 3 4 5 6 7 8 9] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/cython_array.pyx0000644000175100001770000000041200000000000026165 0ustar00runnerdocker00000000000000# tag: numpy import numpy cimport numpy as cnp cdef cnp.int32_t[:] a = numpy.arange(10, dtype=numpy.int32) a = a[::2] print(a) print(numpy.asarray(a)) print(a.base) # this prints: # # [0 2 4 6 8] # [0 1 2 3 4 5 6 7 8 9] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/memory_layout.py0000644000175100001770000000070500000000000026205 0ustar00runnerdocker00000000000000from cython.cimports.cython import view def main(): # direct access in both dimensions, strided in the first dimension, contiguous in the last a: cython.int[:, ::view.contiguous] # contiguous list of pointers to contiguous lists of ints b: cython.int[::view.indirect_contiguous, ::1] # direct or indirect in the first dimension, direct in the second dimension # strided in both dimensions c: cython.int[::view.generic, :] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/memory_layout.pyx0000644000175100001770000000065500000000000026401 0ustar00runnerdocker00000000000000from cython cimport view def main(): # direct access in both dimensions, strided in the first dimension, contiguous in the last cdef int[:, ::view.contiguous] a # contiguous list of pointers to contiguous lists of ints cdef int[::view.indirect_contiguous, ::1] b # direct or indirect in the first dimension, direct in the second dimension # strided in both dimensions cdef int[::view.generic, :] c ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/memory_layout_2.py0000644000175100001770000000062700000000000026431 0ustar00runnerdocker00000000000000# mode: error from cython.cimports.cython import view def main(): # VALID a: cython.int[::view.indirect, ::1, :] b: cython.int[::view.indirect, :, ::1] c: cython.int[::view.indirect_contiguous, ::1, :] # INVALID d: cython.int[::view.contiguous, ::view.indirect, :] e: cython.int[::1, ::view.indirect, :] _ERRORS = u""" 12:17: Only dimension 2 may be contiguous and direct """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/memory_layout_2.pyx0000644000175100001770000000067700000000000026626 0ustar00runnerdocker00000000000000# mode: error from cython cimport view def main(): # VALID cdef int[::view.indirect, ::1, :] a cdef int[::view.indirect, :, ::1] b cdef int[::view.indirect_contiguous, ::1, :] c # INVALID cdef int[::view.contiguous, ::view.indirect, :] d cdef int[::1, ::view.indirect, :] e _ERRORS = u""" 11:12: Only dimension 2 may be contiguous and direct 12:12: Indirect dimension may not follow Fortran contiguous dimension """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/memview_to_c.pxd0000644000175100001770000000033300000000000026115 0ustar00runnerdocker00000000000000cdef extern from "C_func_file.c": # The C file is include directly so that it doesn't need to be compiled separately. pass cdef extern from "C_func_file.h": void multiply_by_10_in_C(double *, unsigned int) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/memview_to_c.py0000644000175100001770000000104600000000000025754 0ustar00runnerdocker00000000000000import numpy as np def multiply_by_10(arr): # 'arr' is a one-dimensional numpy array if not arr.flags['C_CONTIGUOUS']: arr = np.ascontiguousarray(arr) # Makes a contiguous copy of the numpy array. arr_memview: cython.double[::1] = arr multiply_by_10_in_C(cython.address(arr_memview[0]), arr_memview.shape[0]) return arr a = np.ones(5, dtype=np.double) print(multiply_by_10(a)) b = np.ones(10, dtype=np.double) b = b[::2] # b is not contiguous. print(multiply_by_10(b)) # but our function still works as expected. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/memview_to_c.pyx0000644000175100001770000000134200000000000026143 0ustar00runnerdocker00000000000000cdef extern from "C_func_file.c": # C is include here so that it doesn't need to be compiled externally pass cdef extern from "C_func_file.h": void multiply_by_10_in_C(double *, unsigned int) import numpy as np def multiply_by_10(arr): # 'arr' is a one-dimensional numpy array if not arr.flags['C_CONTIGUOUS']: arr = np.ascontiguousarray(arr) # Makes a contiguous copy of the numpy array. cdef double[::1] arr_memview = arr multiply_by_10_in_C(&arr_memview[0], arr_memview.shape[0]) return arr a = np.ones(5, dtype=np.double) print(multiply_by_10(a)) b = np.ones(10, dtype=np.double) b = b[::2] # b is not contiguous. print(multiply_by_10(b)) # but our function still works as expected. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/not_none.py0000644000175100001770000000056300000000000025121 0ustar00runnerdocker00000000000000import numpy as np import typing def process_buffer(input_view: cython.int[:,:], output_view: typing.Optional[cython.int[:,:]] = None): if output_view is None: # Creating a default view, e.g. output_view = np.empty_like(input_view) # process 'input_view' into 'output_view' return output_view process_buffer(None, None) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/not_none.pyx0000644000175100001770000000051400000000000025305 0ustar00runnerdocker00000000000000import numpy as np def process_buffer(int[:,:] input_view not None, int[:,:] output_view=None): if output_view is None: # Creating a default view, e.g. output_view = np.empty_like(input_view) # process 'input_view' into 'output_view' return output_view process_buffer(None, None) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/np_flag_const.pyx0000644000175100001770000000023300000000000026300 0ustar00runnerdocker00000000000000import numpy as np cdef const double[:] myslice # const item type => read-only view a = np.linspace(0, 10, num=50) a.setflags(write=False) myslice = a ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/old_sum3d.pyx0000644000175100001770000000044500000000000025362 0ustar00runnerdocker00000000000000cpdef int old_sum3d(object[int, ndim=3, mode='strided'] arr): cdef int I, J, K, total = 0 I = arr.shape[0] J = arr.shape[1] K = arr.shape[2] for i in range(I): for j in range(J): for k in range(K): total += arr[i, j, k] return total ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/quickstart.py0000644000175100001770000000375000000000000025475 0ustar00runnerdocker00000000000000from cython.cimports.cython.view import array as cvarray import numpy as np # Memoryview on a NumPy array narr = np.arange(27, dtype=np.dtype("i")).reshape((3, 3, 3)) narr_view = cython.declare(cython.int[:, :, :], narr) # Memoryview on a C array carr = cython.declare(cython.int[3][3][3]) carr_view = cython.declare(cython.int[:, :, :], carr) # Memoryview on a Cython array cyarr = cvarray(shape=(3, 3, 3), itemsize=cython.sizeof(cython.int), format="i") cyarr_view = cython.declare(cython.int[:, :, :], cyarr) # Show the sum of all the arrays before altering it print("NumPy sum of the NumPy array before assignments: %s" % narr.sum()) # We can copy the values from one memoryview into another using a single # statement, by either indexing with ... or (NumPy-style) with a colon. carr_view[...] = narr_view cyarr_view[:] = narr_view # NumPy-style syntax for assigning a single value to all elements. narr_view[:, :, :] = 3 # Just to distinguish the arrays carr_view[0, 0, 0] = 100 cyarr_view[0, 0, 0] = 1000 # Assigning into the memoryview on the NumPy array alters the latter print("NumPy sum of NumPy array after assignments: %s" % narr.sum()) # A function using a memoryview does not usually need the GIL @cython.nogil @cython.ccall def sum3d(arr: cython.int[:, :, :]) -> cython.int: i: cython.size_t j: cython.size_t k: cython.size_t I: cython.size_t J: cython.size_t K: cython.size_t total: cython.int = 0 I = arr.shape[0] J = arr.shape[1] K = arr.shape[2] for i in range(I): for j in range(J): for k in range(K): total += arr[i, j, k] return total # A function accepting a memoryview knows how to use a NumPy array, # a C array, a Cython array... print("Memoryview sum of NumPy array is %s" % sum3d(narr)) print("Memoryview sum of C array is %s" % sum3d(carr)) print("Memoryview sum of Cython array is %s" % sum3d(cyarr)) # ... and of course, a memoryview. print("Memoryview sum of C memoryview is %s" % sum3d(carr_view)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/quickstart.pyx0000644000175100001770000000340200000000000025657 0ustar00runnerdocker00000000000000from cython.view cimport array as cvarray import numpy as np # Memoryview on a NumPy array narr = np.arange(27, dtype=np.dtype("i")).reshape((3, 3, 3)) cdef int [:, :, :] narr_view = narr # Memoryview on a C array cdef int[3][3][3] carr cdef int [:, :, :] carr_view = carr # Memoryview on a Cython array cyarr = cvarray(shape=(3, 3, 3), itemsize=sizeof(int), format="i") cdef int [:, :, :] cyarr_view = cyarr # Show the sum of all the arrays before altering it print("NumPy sum of the NumPy array before assignments: %s" % narr.sum()) # We can copy the values from one memoryview into another using a single # statement, by either indexing with ... or (NumPy-style) with a colon. carr_view[...] = narr_view cyarr_view[:] = narr_view # NumPy-style syntax for assigning a single value to all elements. narr_view[:, :, :] = 3 # Just to distinguish the arrays carr_view[0, 0, 0] = 100 cyarr_view[0, 0, 0] = 1000 # Assigning into the memoryview on the NumPy array alters the latter print("NumPy sum of NumPy array after assignments: %s" % narr.sum()) # A function using a memoryview does not usually need the GIL cpdef int sum3d(int[:, :, :] arr) nogil: cdef size_t i, j, k, I, J, K cdef int total = 0 I = arr.shape[0] J = arr.shape[1] K = arr.shape[2] for i in range(I): for j in range(J): for k in range(K): total += arr[i, j, k] return total # A function accepting a memoryview knows how to use a NumPy array, # a C array, a Cython array... print("Memoryview sum of NumPy array is %s" % sum3d(narr)) print("Memoryview sum of C array is %s" % sum3d(carr)) print("Memoryview sum of Cython array is %s" % sum3d(cyarr)) # ... and of course, a memoryview. print("Memoryview sum of C memoryview is %s" % sum3d(carr_view)) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/slicing.py0000644000175100001770000000040700000000000024727 0ustar00runnerdocker00000000000000import numpy as np def main(): exporting_object = np.arange(0, 15 * 10 * 20, dtype=np.intc).reshape((15, 10, 20)) my_view: cython.int[:, :, :] = exporting_object # These are all equivalent my_view[10] my_view[10, :, :] my_view[10, ...] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/slicing.pyx0000644000175100001770000000034100000000000025114 0ustar00runnerdocker00000000000000import numpy as np exporting_object = np.arange(0, 15 * 10 * 20, dtype=np.intc).reshape((15, 10, 20)) cdef int[:, :, :] my_view = exporting_object # These are all equivalent my_view[10] my_view[10, :, :] my_view[10, ...] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/transpose.py0000644000175100001770000000026200000000000025314 0ustar00runnerdocker00000000000000import numpy as np def main(): array = np.arange(20, dtype=np.intc).reshape((2, 10)) c_contig: cython.int[:, ::1] = array f_contig: cython.int[::1, :] = c_contig.T ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/transpose.pyx0000644000175100001770000000022500000000000025503 0ustar00runnerdocker00000000000000import numpy as np array = np.arange(20, dtype=np.intc).reshape((2, 10)) cdef int[:, ::1] c_contig = array cdef int[::1, :] f_contig = c_contig.T ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/memoryviews/view_string.pyx0000644000175100001770000000041600000000000026027 0ustar00runnerdocker00000000000000cdef bint is_y_in(const unsigned char[:] string_view): cdef int i for i in range(string_view.shape[0]): if string_view[i] == b'y': return True return False print(is_y_in(b'hello world')) # False print(is_y_in(b'hello Cython')) # True ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.0527241 Cython-3.0.8/docs/examples/userguide/numpy_tutorial/0000755000175100001770000000000000000000000023431 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/numpy_tutorial/compute_fused_types.pyx0000644000175100001770000000177700000000000030275 0ustar00runnerdocker00000000000000# cython: infer_types=True import numpy as np cimport cython ctypedef fused my_type: int double long long cdef my_type clip(my_type a, my_type min_value, my_type max_value): return min(max(a, min_value), max_value) @cython.boundscheck(False) @cython.wraparound(False) def compute(my_type[:, ::1] array_1, my_type[:, ::1] array_2, my_type a, my_type b, my_type c): x_max = array_1.shape[0] y_max = array_1.shape[1] assert tuple(array_1.shape) == tuple(array_2.shape) if my_type is int: dtype = np.intc elif my_type is double: dtype = np.double elif my_type is cython.longlong: dtype = np.longlong result = np.zeros((x_max, y_max), dtype=dtype) cdef my_type[:, ::1] result_view = result cdef my_type tmp cdef Py_ssize_t x, y for x in range(x_max): for y in range(y_max): tmp = clip(array_1[x, y], 2, 10) tmp = tmp * a + array_2[x, y] * b result_view[x, y] = tmp + c return result ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/numpy_tutorial/compute_infer_types.pyx0000644000175100001770000000140300000000000030254 0ustar00runnerdocker00000000000000# cython: infer_types=True import numpy as np cimport cython DTYPE = np.intc cdef int clip(int a, int min_value, int max_value): return min(max(a, min_value), max_value) @cython.boundscheck(False) @cython.wraparound(False) def compute(int[:, ::1] array_1, int[:, ::1] array_2, int a, int b, int c): x_max = array_1.shape[0] y_max = array_1.shape[1] assert tuple(array_1.shape) == tuple(array_2.shape) result = np.zeros((x_max, y_max), dtype=DTYPE) cdef int[:, ::1] result_view = result cdef int tmp cdef Py_ssize_t x, y for x in range(x_max): for y in range(y_max): tmp = clip(array_1[x, y], 2, 10) tmp = tmp * a + array_2[x, y] * b result_view[x, y] = tmp + c return result ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/numpy_tutorial/compute_memview.pyx0000644000175100001770000000163100000000000027401 0ustar00runnerdocker00000000000000import numpy as np DTYPE = np.intc cdef int clip(int a, int min_value, int max_value): return min(max(a, min_value), max_value) def compute(int[:, :] array_1, int[:, :] array_2, int a, int b, int c): cdef Py_ssize_t x_max = array_1.shape[0] cdef Py_ssize_t y_max = array_1.shape[1] # array_1.shape is now a C array, no it's not possible # to compare it simply by using == without a for-loop. # To be able to compare it to array_2.shape easily, # we convert them both to Python tuples. assert tuple(array_1.shape) == tuple(array_2.shape) result = np.zeros((x_max, y_max), dtype=DTYPE) cdef int[:, :] result_view = result cdef int tmp cdef Py_ssize_t x, y for x in range(x_max): for y in range(y_max): tmp = clip(array_1[x, y], 2, 10) tmp = tmp * a + array_2[x, y] * b result_view[x, y] = tmp + c return result ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/numpy_tutorial/compute_prange.pyx0000644000175100001770000000247000000000000027206 0ustar00runnerdocker00000000000000# tag: openmp # You can ignore the previous line. # It's for internal testing of the cython documentation. # distutils: extra_compile_args=-fopenmp # distutils: extra_link_args=-fopenmp import numpy as np cimport cython from cython.parallel import prange ctypedef fused my_type: int double long long # We declare our plain c function nogil cdef my_type clip(my_type a, my_type min_value, my_type max_value) nogil: return min(max(a, min_value), max_value) @cython.boundscheck(False) @cython.wraparound(False) def compute(my_type[:, ::1] array_1, my_type[:, ::1] array_2, my_type a, my_type b, my_type c): cdef Py_ssize_t x_max = array_1.shape[0] cdef Py_ssize_t y_max = array_1.shape[1] assert tuple(array_1.shape) == tuple(array_2.shape) if my_type is int: dtype = np.intc elif my_type is double: dtype = np.double elif my_type is cython.longlong: dtype = np.longlong result = np.zeros((x_max, y_max), dtype=dtype) cdef my_type[:, ::1] result_view = result cdef my_type tmp cdef Py_ssize_t x, y # We use prange here. for x in prange(x_max, nogil=True): for y in range(y_max): tmp = clip(array_1[x, y], 2, 10) tmp = tmp * a + array_2[x, y] * b result_view[x, y] = tmp + c return result ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/numpy_tutorial/compute_py.py0000644000175100001770000000121400000000000026165 0ustar00runnerdocker00000000000000import numpy as np def clip(a, min_value, max_value): return min(max(a, min_value), max_value) def compute(array_1, array_2, a, b, c): """ This function must implement the formula np.clip(array_1, 2, 10) * a + array_2 * b + c array_1 and array_2 are 2D. """ x_max = array_1.shape[0] y_max = array_1.shape[1] assert array_1.shape == array_2.shape result = np.zeros((x_max, y_max), dtype=array_1.dtype) for x in range(x_max): for y in range(y_max): tmp = clip(array_1[x, y], 2, 10) tmp = tmp * a + array_2[x, y] * b result[x, y] = tmp + c return result ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/numpy_tutorial/compute_typed.pyx0000644000175100001770000000344100000000000027056 0ustar00runnerdocker00000000000000import numpy as np # We now need to fix a datatype for our arrays. I've used the variable # DTYPE for this, which is assigned to the usual NumPy runtime # type info object. DTYPE = np.intc # cdef means here that this function is a plain C function (so faster). # To get all the benefits, we type the arguments and the return value. cdef int clip(int a, int min_value, int max_value): return min(max(a, min_value), max_value) def compute(array_1, array_2, int a, int b, int c): # The "cdef" keyword is also used within functions to type variables. It # can only be used at the top indentation level (there are non-trivial # problems with allowing them in other places, though we'd love to see # good and thought out proposals for it). cdef Py_ssize_t x_max = array_1.shape[0] cdef Py_ssize_t y_max = array_1.shape[1] assert array_1.shape == array_2.shape assert array_1.dtype == DTYPE assert array_2.dtype == DTYPE result = np.zeros((x_max, y_max), dtype=DTYPE) # It is very important to type ALL your variables. You do not get any # warnings if not, only much slower code (they are implicitly typed as # Python objects). # For the "tmp" variable, we want to use the same data type as is # stored in the array, so we use int because it correspond to np.intc. # NB! An important side-effect of this is that if "tmp" overflows its # datatype size, it will simply wrap around like in C, rather than raise # an error like in Python. cdef int tmp # Py_ssize_t is the proper C type for Python array indices. cdef Py_ssize_t x, y for x in range(x_max): for y in range(y_max): tmp = clip(array_1[x, y], 2, 10) tmp = tmp * a + array_2[x, y] * b result[x, y] = tmp + c return result ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/numpy_tutorial/numpy_and_cython.ipynb0000644000175100001770000005313200000000000030056 0ustar00runnerdocker00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Cython for NumPy users" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To follow the tutorial, see https://cython.readthedocs.io/en/latest/src/userguide/numpy_tutorial.html" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "scrolled": true }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING: Disabling color, you really want to install colorlog.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "0.29a0\n" ] } ], "source": [ "from __future__ import print_function\n", "%load_ext cython\n", "import Cython\n", "print(Cython.__version__)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "array_1 = np.random.uniform(0, 1000, size=(3000, 2000)).astype(np.intc)\n", "array_2 = np.random.uniform(0, 1000, size=(3000, 2000)).astype(np.intc)\n", "a = 4\n", "b = 3\n", "c = 9" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### The first Cython program" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Numpy version" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "def compute_np(array_1, array_2, a, b, c):\n", " return np.clip(array_1, 2, 10) * a + array_2 * b + c" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "103 ms ± 2.68 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" ] } ], "source": [ "timeit_result = %timeit -o compute_np(array_1, array_2, a, b, c)\n", "np_time = timeit_result.average" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "np_result = compute_np(array_1, array_2, a, b, c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Pure Python version" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "def clip(a, min_value, max_value):\n", " return min(max(a, min_value), max_value)\n", "\n", "\n", "def compute(array_1, array_2, a, b, c):\n", " \"\"\"\n", " This function must implement the formula\n", " np.clip(array_1, 2, 10) * a + array_2 * b + c\n", "\n", " array_1 and array_2 are 2D.\n", " \"\"\"\n", " x_max = array_1.shape[0]\n", " y_max = array_1.shape[1]\n", " \n", " assert array_1.shape == array_2.shape\n", "\n", " result = np.zeros((x_max, y_max), dtype=array_1.dtype)\n", "\n", " for x in range(x_max):\n", " for y in range(y_max):\n", "\n", " tmp = clip(array_1[x, y], 2, 10)\n", " tmp = tmp * a + array_2[x, y] * b\n", " result[x, y] = tmp + c\n", "\n", " return result" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "assert np.all(compute(array_1, array_2, a, b, c) == np_result)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1min 10s ± 844 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" ] } ], "source": [ "timeit_result = %timeit -o compute(array_1, array_2, a, b, c)\n", "py_time = timeit_result.average" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### We make a function to be able to easily compare timings with the NumPy version and the pure Python version." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "def compare_time(current, reference, name):\n", " ratio = reference/current\n", " if ratio > 1:\n", " word = \"faster\"\n", " else:\n", " ratio = 1 / ratio \n", " word = \"slower\"\n", " \n", " print(\"We are\", \"{0:.1f}\".format(ratio), \"times\", word, \"than the\", name, \"version.\")\n", "\n", "def print_report(compute_function):\n", " assert np.all(compute_function(array_1, array_2, a, b, c) == np_result)\n", " timeit_result = %timeit -o compute_function(array_1, array_2, a, b, c)\n", " run_time = timeit_result.average\n", " compare_time(run_time, py_time, \"pure Python\")\n", " compare_time(run_time, np_time, \"NumPy\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Pure Python version compiled with Cython:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "%%cython -a\n", "import numpy as np\n", "\n", "\n", "def clip(a, min_value, max_value):\n", " return min(max(a, min_value), max_value)\n", "\n", "\n", "def compute(array_1, array_2, a, b, c):\n", " \"\"\"\n", " This function must implement the formula\n", " np.clip(array_1, 2, 10) * a + array_2 * b + c\n", "\n", " array_1 and array_2 are 2D.\n", " \"\"\"\n", " x_max = array_1.shape[0]\n", " y_max = array_1.shape[1]\n", " \n", " assert array_1.shape == array_2.shape\n", "\n", " result = np.zeros((x_max, y_max), dtype=array_1.dtype)\n", "\n", " for x in range(x_max):\n", " for y in range(y_max):\n", "\n", " tmp = clip(array_1[x, y], 2, 10)\n", " tmp = tmp * a + array_2[x, y] * b\n", " result[x, y] = tmp + c\n", "\n", " return result" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "56.5 s ± 587 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n", "We are 1.2 times faster than the pure Python version.\n", "We are 546.0 times slower than the NumPy version.\n" ] } ], "source": [ "print_report(compute)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Adding types:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "%%cython -a\n", "import numpy as np\n", "\n", "# We now need to fix a datatype for our arrays. I've used the variable\n", "# DTYPE for this, which is assigned to the usual NumPy runtime\n", "# type info object.\n", "DTYPE = np.intc\n", "\n", "# cdef means here that this function is a plain C function (so faster).\n", "# To get all the benefits, we type the arguments and the return value as int.\n", "cdef int clip(int a, int min_value, int max_value):\n", " return min(max(a, min_value), max_value)\n", "\n", "\n", "def compute(array_1, array_2, int a, int b, int c):\n", " \n", " # The \"cdef\" keyword is also used within functions to type variables. It\n", " # can only be used at the top indentation level (there are non-trivial\n", " # problems with allowing them in other places, though we'd love to see\n", " # good and thought out proposals for it).\n", " cdef Py_ssize_t x_max = array_1.shape[0]\n", " cdef Py_ssize_t y_max = array_1.shape[1]\n", " \n", " assert array_1.shape == array_2.shape\n", " assert array_1.dtype == DTYPE\n", " assert array_2.dtype == DTYPE\n", "\n", " result = np.zeros((x_max, y_max), dtype=DTYPE)\n", " \n", " # It is very important to type ALL your variables. You do not get any\n", " # warnings if not, only much slower code (they are implicitly typed as\n", " # Python objects).\n", " # For the \"tmp\" variable, we want to use the same data type as is\n", " # stored in the array, so we use int because it correspond to np.intc.\n", " # NB! An important side-effect of this is that if \"tmp\" overflows its\n", " # datatype size, it will simply wrap around like in C, rather than raise\n", " # an error like in Python.\n", "\n", " cdef int tmp\n", " cdef Py_ssize_t x, y\n", "\n", " for x in range(x_max):\n", " for y in range(y_max):\n", "\n", " tmp = clip(array_1[x, y], 2, 10)\n", " tmp = tmp * a + array_2[x, y] * b\n", " result[x, y] = tmp + c\n", "\n", " return result" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "26.5 s ± 422 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n", "We are 2.7 times faster than the pure Python version.\n", "We are 256.2 times slower than the NumPy version.\n" ] } ], "source": [ "print_report(compute)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Efficient indexing with memoryviews:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "%%cython -a\n", "import numpy as np\n", "\n", "DTYPE = np.intc\n", "\n", "\n", "cdef int clip(int a, int min_value, int max_value):\n", " return min(max(a, min_value), max_value)\n", "\n", "\n", "def compute(int[:, :] array_1, int[:, :] array_2, int a, int b, int c):\n", " \n", " cdef Py_ssize_t x_max = array_1.shape[0]\n", " cdef Py_ssize_t y_max = array_1.shape[1]\n", " \n", " assert tuple(array_1.shape) == tuple(array_2.shape)\n", "\n", " result = np.zeros((x_max, y_max), dtype=DTYPE)\n", " cdef int[:, :] result_view = result\n", "\n", " cdef int tmp\n", " cdef Py_ssize_t x, y\n", "\n", " for x in range(x_max):\n", " for y in range(y_max):\n", "\n", " tmp = clip(array_1[x, y], 2, 10)\n", " tmp = tmp * a + array_2[x, y] * b\n", " result_view[x, y] = tmp + c\n", "\n", " return result" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "22.9 ms ± 197 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n", "We are 3081.0 times faster than the pure Python version.\n", "We are 4.5 times faster than the NumPy version.\n" ] } ], "source": [ "print_report(compute)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Tuning indexing further:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "%%cython -a\n", "import numpy as np\n", "cimport cython\n", "\n", "DTYPE = np.intc\n", "\n", "\n", "cdef int clip(int a, int min_value, int max_value):\n", " return min(max(a, min_value), max_value)\n", "\n", "@cython.boundscheck(False)\n", "@cython.wraparound(False)\n", "def compute(int[:, :] array_1, int[:, :] array_2, int a, int b, int c):\n", " \n", " cdef Py_ssize_t x_max = array_1.shape[0]\n", " cdef Py_ssize_t y_max = array_1.shape[1]\n", " \n", " assert tuple(array_1.shape) == tuple(array_2.shape)\n", "\n", " result = np.zeros((x_max, y_max), dtype=DTYPE)\n", " cdef int[:, :] result_view = result\n", "\n", " cdef int tmp\n", " cdef Py_ssize_t x, y\n", "\n", " for x in range(x_max):\n", " for y in range(y_max):\n", "\n", " tmp = clip(array_1[x, y], 2, 10)\n", " tmp = tmp * a + array_2[x, y] * b\n", " result_view[x, y] = tmp + c\n", "\n", " return result" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "16.8 ms ± 25.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n", "We are 4200.7 times faster than the pure Python version.\n", "We are 6.2 times faster than the NumPy version.\n" ] } ], "source": [ "print_report(compute)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Declaring the NumPy arrays as contiguous." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "%%cython\n", "import numpy as np\n", "cimport cython\n", "\n", "DTYPE = np.intc\n", "\n", "\n", "cdef int clip(int a, int min_value, int max_value):\n", " return min(max(a, min_value), max_value)\n", "\n", "\n", "@cython.boundscheck(False)\n", "@cython.wraparound(False)\n", "def compute(int[:, ::1] array_1, int[:, ::1] array_2, int a, int b, int c):\n", " \n", " cdef Py_ssize_t x_max = array_1.shape[0]\n", " cdef Py_ssize_t y_max = array_1.shape[1]\n", " \n", " assert tuple(array_1.shape) == tuple(array_2.shape)\n", "\n", " result = np.zeros((x_max, y_max), dtype=DTYPE)\n", " cdef int[:, ::1] result_view = result\n", "\n", " cdef int tmp\n", " cdef Py_ssize_t x, y\n", "\n", " for x in range(x_max):\n", " for y in range(y_max):\n", "\n", " tmp = clip(array_1[x, y], 2, 10)\n", " tmp = tmp * a + array_2[x, y] * b\n", " result_view[x, y] = tmp + c\n", "\n", " return result" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "11.1 ms ± 30.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n", "We are 6350.9 times faster than the pure Python version.\n", "We are 9.3 times faster than the NumPy version.\n" ] } ], "source": [ "print_report(compute)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Making the function cleaner" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%cython -a\n", "# cython: infer_types=True\n", "import numpy as np\n", "cimport cython\n", "\n", "DTYPE = np.intc\n", "\n", "\n", "cdef int clip(int a, int min_value, int max_value):\n", " return min(max(a, min_value), max_value)\n", "\n", "\n", "@cython.boundscheck(False)\n", "@cython.wraparound(False)\n", "def compute(int[:, ::1] array_1, int[:, ::1] array_2, int a, int b, int c):\n", " \n", " x_max = array_1.shape[0]\n", " y_max = array_1.shape[1]\n", " \n", " assert tuple(array_1.shape) == tuple(array_2.shape)\n", "\n", " result = np.zeros((x_max, y_max), dtype=DTYPE)\n", " cdef int[:, ::1] result_view = result\n", "\n", " cdef int tmp\n", " cdef Py_ssize_t x, y\n", "\n", " for x in range(x_max):\n", " for y in range(y_max):\n", "\n", " tmp = clip(array_1[x, y], 2, 10)\n", " tmp = tmp * a + array_2[x, y] * b\n", " result_view[x, y] = tmp + c\n", "\n", " return result" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "11.5 ms ± 261 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n", "We are 6131.2 times faster than the pure Python version.\n", "We are 9.0 times faster than the NumPy version.\n" ] } ], "source": [ "print_report(compute)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### More generic code:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "scrolled": true }, "outputs": [], "source": [ "%%cython\n", "# cython: infer_types=True\n", "import numpy as np\n", "cimport cython\n", "\n", "ctypedef fused my_type:\n", " int\n", " double\n", " long long\n", "\n", "\n", "cdef my_type clip(my_type a, my_type min_value, my_type max_value):\n", " return min(max(a, min_value), max_value)\n", "\n", "\n", "@cython.boundscheck(False)\n", "@cython.wraparound(False)\n", "def compute(my_type[:, ::1] array_1, my_type[:, ::1] array_2, my_type a, my_type b, my_type c):\n", " \n", " x_max = array_1.shape[0]\n", " y_max = array_1.shape[1]\n", " \n", " assert tuple(array_1.shape) == tuple(array_2.shape)\n", " \n", " if my_type is int:\n", " dtype = np.intc\n", " elif my_type is double:\n", " dtype = np.double\n", " elif my_type is cython.longlong:\n", " dtype = np.double\n", " \n", " result = np.zeros((x_max, y_max), dtype=dtype)\n", " cdef my_type[:, ::1] result_view = result\n", "\n", " cdef my_type tmp\n", " cdef Py_ssize_t x, y\n", "\n", " for x in range(x_max):\n", " for y in range(y_max):\n", "\n", " tmp = clip(array_1[x, y], 2, 10)\n", " tmp = tmp * a + array_2[x, y] * b\n", " result_view[x, y] = tmp + c\n", "\n", " return result" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [], "source": [ "arr_1_float = array_1.astype(np.float64)\n", "arr_2_float = array_2.astype(np.float64)\n", "\n", "float_cython_result = compute(arr_1_float, arr_2_float, a, b, c)\n", "float_numpy_result = compute_np(arr_1_float, arr_2_float, a, b, c)\n", "\n", "assert np.all(float_cython_result == float_numpy_result)" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "11.5 ms ± 258 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n", "We are 6153.1 times faster than the pure Python version.\n", "We are 9.0 times faster than the NumPy version.\n" ] } ], "source": [ "print_report(compute)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Using multiple threads" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "scrolled": true }, "outputs": [], "source": [ "%%cython --force\n", "# distutils: extra_compile_args=-fopenmp\n", "# distutils: extra_link_args=-fopenmp\n", "import numpy as np\n", "cimport cython\n", "from cython.parallel import prange\n", "\n", "ctypedef fused my_type:\n", " int\n", " double\n", " long long\n", "\n", "\n", "# We declare our plain c function nogil\n", "cdef my_type clip(my_type a, my_type min_value, my_type max_value) nogil:\n", " return min(max(a, min_value), max_value)\n", "\n", "\n", "@cython.boundscheck(False)\n", "@cython.wraparound(False)\n", "def compute(my_type[:, ::1] array_1, my_type[:, ::1] array_2, my_type a, my_type b, my_type c):\n", " \n", " cdef Py_ssize_t x_max = array_1.shape[0]\n", " cdef Py_ssize_t y_max = array_1.shape[1]\n", " \n", " assert tuple(array_1.shape) == tuple(array_2.shape)\n", " \n", " if my_type is int:\n", " dtype = np.intc\n", " elif my_type is double:\n", " dtype = np.double\n", " elif my_type is cython.longlong:\n", " dtype = np.longlong\n", " \n", " result = np.zeros((x_max, y_max), dtype=dtype)\n", " cdef my_type[:, ::1] result_view = result\n", "\n", " cdef my_type tmp\n", " cdef Py_ssize_t x, y\n", "\n", " # We use prange here.\n", " for x in prange(x_max, nogil=True):\n", " for y in range(y_max):\n", "\n", " tmp = clip(array_1[x, y], 2, 10)\n", " tmp = tmp * a + array_2[x, y] * b\n", " result_view[x, y] = tmp + c\n", "\n", " return result" ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "9.33 ms ± 412 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n", "We are 7559.0 times faster than the pure Python version.\n", "We are 11.1 times faster than the NumPy version.\n" ] } ], "source": [ "print_report(compute)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.6" } }, "nbformat": 4, "nbformat_minor": 2 } ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.056724 Cython-3.0.8/docs/examples/userguide/numpy_ufuncs/0000755000175100001770000000000000000000000023071 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/numpy_ufuncs/ufunc.py0000644000175100001770000000031000000000000024555 0ustar00runnerdocker00000000000000# tag: numpy import cython @cython.ufunc @cython.cfunc def add_one(x: cython.double) -> cython.double: # of course, this simple operation can already by done efficiently in Numpy! return x+1 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/numpy_ufuncs/ufunc.pyx0000644000175100001770000000025300000000000024753 0ustar00runnerdocker00000000000000# tag: numpy cimport cython @cython.ufunc cdef double add_one(double x): # of course, this simple operation can already by done efficiently in Numpy! return x+1 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/numpy_ufuncs/ufunc_ctuple.py0000644000175100001770000000022100000000000026132 0ustar00runnerdocker00000000000000# tag: numpy import cython @cython.ufunc @cython.cfunc def add_one_add_two(x: cython.int) -> tuple[cython.int, cython.int]: return x+1, x+2 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/numpy_ufuncs/ufunc_ctuple.pyx0000644000175100001770000000015000000000000026323 0ustar00runnerdocker00000000000000# tag: numpy cimport cython @cython.ufunc cdef (int, int) add_one_add_two(int x): return x+1, x+2 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/numpy_ufuncs/ufunc_fused.py0000644000175100001770000000020100000000000025742 0ustar00runnerdocker00000000000000# tag: numpy import cython @cython.ufunc @cython.cfunc def generic_add_one(x: cython.numeric) -> cython.numeric: return x+1 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/numpy_ufuncs/ufunc_fused.pyx0000644000175100001770000000016200000000000026140 0ustar00runnerdocker00000000000000# tag: numpy cimport cython @cython.ufunc cdef cython.numeric generic_add_one(cython.numeric x): return x+1 ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.056724 Cython-3.0.8/docs/examples/userguide/parallelism/0000755000175100001770000000000000000000000022643 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/parallelism/breaking_loop.py0000644000175100001770000000052700000000000026034 0ustar00runnerdocker00000000000000from cython.parallel import prange @cython.exceptval(-1) @cython.cfunc def func(n: cython.Py_ssize_t) -> cython.int: i: cython.Py_ssize_t for i in prange(n, nogil=True): if i == 8: with cython.gil: raise Exception() elif i == 4: break elif i == 2: return i ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/parallelism/breaking_loop.pyx0000644000175100001770000000044400000000000026222 0ustar00runnerdocker00000000000000from cython.parallel import prange cdef int func(Py_ssize_t n) except -1: cdef Py_ssize_t i for i in prange(n, nogil=True): if i == 8: with gil: raise Exception() elif i == 4: break elif i == 2: return i ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/parallelism/cimport_openmp.py0000644000175100001770000000041300000000000026246 0ustar00runnerdocker00000000000000# tag: openmp from cython.parallel import parallel from cython.cimports.openmp import omp_set_dynamic, omp_get_num_threads num_threads = cython.declare(cython.int) omp_set_dynamic(1) with cython.nogil, parallel(): num_threads = omp_get_num_threads() # ... ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/parallelism/cimport_openmp.pyx0000644000175100001770000000030600000000000026437 0ustar00runnerdocker00000000000000# tag: openmp from cython.parallel cimport parallel cimport openmp cdef int num_threads openmp.omp_set_dynamic(1) with nogil, parallel(): num_threads = openmp.omp_get_num_threads() # ... ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/parallelism/memoryview_sum.py0000644000175100001770000000027400000000000026307 0ustar00runnerdocker00000000000000from cython.parallel import prange def func(x: cython.double[:], alpha: cython.double): i: cython.Py_ssize_t for i in prange(x.shape[0], nogil=True): x[i] = alpha * x[i] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/parallelism/memoryview_sum.pyx0000644000175100001770000000025100000000000026472 0ustar00runnerdocker00000000000000from cython.parallel import prange def func(double[:] x, double alpha): cdef Py_ssize_t i for i in prange(x.shape[0], nogil=True): x[i] = alpha * x[i] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/parallelism/parallel.py0000644000175100001770000000153700000000000025017 0ustar00runnerdocker00000000000000from cython.parallel import parallel, prange from cython.cimports.libc.stdlib import abort, malloc, free @cython.nogil @cython.cfunc def func(buf: cython.p_int) -> cython.void: pass # ... idx = cython.declare(cython.Py_ssize_t) i = cython.declare(cython.Py_ssize_t) j = cython.declare(cython.Py_ssize_t) n = cython.declare(cython.Py_ssize_t, 100) local_buf = cython.declare(p_int) size = cython.declare(cython.size_t, 10) with cython.nogil, parallel(): local_buf: cython.p_int = cython.cast(cython.p_int, malloc(cython.sizeof(cython.int) * size)) if local_buf is cython.NULL: abort() # populate our local buffer in a sequential loop for i in range(size): local_buf[i] = i * 2 # share the work using the thread-local buffer(s) for j in prange(n, schedule='guided'): func(local_buf) free(local_buf) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/parallelism/parallel.pyx0000644000175100001770000000112400000000000025177 0ustar00runnerdocker00000000000000from cython.parallel import parallel, prange from libc.stdlib cimport abort, malloc, free cdef void func(int *buf) nogil: pass # ... cdef Py_ssize_t idx, i, j, n = 100 cdef int * local_buf cdef size_t size = 10 with nogil, parallel(): local_buf = malloc(sizeof(int) * size) if local_buf is NULL: abort() # populate our local buffer in a sequential loop for i in range(size): local_buf[i] = i * 2 # share the work using the thread-local buffer(s) for j in prange(n, schedule='guided'): func(local_buf) free(local_buf) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/parallelism/setup_py.py0000644000175100001770000000047400000000000025072 0ustar00runnerdocker00000000000000from setuptools import Extension, setup from Cython.Build import cythonize ext_modules = [ Extension( "hello", ["hello.py"], extra_compile_args=['-fopenmp'], extra_link_args=['-fopenmp'], ) ] setup( name='hello-parallel-world', ext_modules=cythonize(ext_modules), ) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/parallelism/setup_pyx.py0000644000175100001770000000047500000000000025263 0ustar00runnerdocker00000000000000from setuptools import Extension, setup from Cython.Build import cythonize ext_modules = [ Extension( "hello", ["hello.pyx"], extra_compile_args=['-fopenmp'], extra_link_args=['-fopenmp'], ) ] setup( name='hello-parallel-world', ext_modules=cythonize(ext_modules), ) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/parallelism/simple_sum.py0000644000175100001770000000030400000000000025367 0ustar00runnerdocker00000000000000from cython.parallel import prange i = cython.declare(cython.int) n = cython.declare(cython.int, 30) sum = cython.declare(cython.int, 0) for i in prange(n, nogil=True): sum += i print(sum) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/parallelism/simple_sum.pyx0000644000175100001770000000021200000000000025555 0ustar00runnerdocker00000000000000from cython.parallel import prange cdef int i cdef int n = 30 cdef int sum = 0 for i in prange(n, nogil=True): sum += i print(sum) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.056724 Cython-3.0.8/docs/examples/userguide/sharing_declarations/0000755000175100001770000000000000000000000024521 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/sharing_declarations/c_lunch.pxd0000644000175100001770000000007300000000000026651 0ustar00runnerdocker00000000000000cdef extern from "lunch.h": void eject_tomato(float) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/sharing_declarations/dishes.pxd0000644000175100001770000000016700000000000026521 0ustar00runnerdocker00000000000000cdef enum otherstuff: sausage, eggs, lettuce cdef struct spamdish: int oz_of_spam otherstuff filler ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/sharing_declarations/landscaping.py0000644000175100001770000000030100000000000027350 0ustar00runnerdocker00000000000000from cython.cimports.shrubbing import Shrubbery import shrubbing def main(): sh: Shrubbery sh = shrubbing.standard_shrubbery() print("Shrubbery size is", sh.width, 'x', sh.length) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/sharing_declarations/landscaping.pyx0000644000175100001770000000026100000000000027545 0ustar00runnerdocker00000000000000cimport shrubbing import shrubbing def main(): cdef shrubbing.Shrubbery sh sh = shrubbing.standard_shrubbery() print("Shrubbery size is", sh.width, 'x', sh.length) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3527222 Cython-3.0.8/docs/examples/userguide/sharing_declarations/lunch.h0000644000175100001770000000004100000000000025776 0ustar00runnerdocker00000000000000void eject_tomato(float speed); ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/sharing_declarations/lunch.py0000644000175100001770000000022300000000000026201 0ustar00runnerdocker00000000000000import cython from cython.cimports.c_lunch import eject_tomato as c_eject_tomato def eject_tomato(speed: cython.float): c_eject_tomato(speed) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/sharing_declarations/lunch.pyx0000644000175100001770000000012200000000000026367 0ustar00runnerdocker00000000000000 cimport c_lunch def eject_tomato(float speed): c_lunch.eject_tomato(speed) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/sharing_declarations/restaurant.py0000644000175100001770000000046100000000000027264 0ustar00runnerdocker00000000000000import cython from cython.cimports.dishes import spamdish, sausage @cython.cfunc def prepare(d: cython.pointer(spamdish)) -> cython.void: d.oz_of_spam = 42 d.filler = sausage def serve(): d: spamdish prepare(cython.address(d)) print(f'{d.oz_of_spam} oz spam, filler no. {d.filler}') ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/sharing_declarations/restaurant.pyx0000644000175100001770000000036100000000000027453 0ustar00runnerdocker00000000000000 cimport dishes from dishes cimport spamdish cdef void prepare(spamdish *d): d.oz_of_spam = 42 d.filler = dishes.sausage def serve(): cdef spamdish d prepare(&d) print(f'{d.oz_of_spam} oz spam, filler no. {d.filler}') ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/sharing_declarations/setup_py.py0000644000175100001770000000020200000000000026735 0ustar00runnerdocker00000000000000from setuptools import setup from Cython.Build import cythonize setup(ext_modules=cythonize(["landscaping.py", "shrubbing.py"])) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/sharing_declarations/setup_pyx.py0000644000175100001770000000020400000000000027127 0ustar00runnerdocker00000000000000from setuptools import setup from Cython.Build import cythonize setup(ext_modules=cythonize(["landscaping.pyx", "shrubbing.pyx"])) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/sharing_declarations/shrubbing.pxd0000644000175100001770000000010000000000000027210 0ustar00runnerdocker00000000000000cdef class Shrubbery: cdef int width cdef int length ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/sharing_declarations/shrubbing.py0000644000175100001770000000031300000000000027053 0ustar00runnerdocker00000000000000import cython @cython.cclass class Shrubbery: def __cinit__(self, w: cython.int, l: cython.int): self.width = w self.length = l def standard_shrubbery(): return Shrubbery(3, 7) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/sharing_declarations/shrubbing.pyx0000644000175100001770000000024500000000000027247 0ustar00runnerdocker00000000000000 cdef class Shrubbery: def __init__(self, int w, int l): self.width = w self.length = l def standard_shrubbery(): return Shrubbery(3, 7) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/sharing_declarations/spammery.py0000644000175100001770000000033300000000000026727 0ustar00runnerdocker00000000000000import cython from cython.cimports.volume import cube def menu(description, size): print(description, ":", cube(size), "cubic metres of spam") menu("Entree", 1) menu("Main course", 3) menu("Dessert", 2) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/sharing_declarations/spammery.pyx0000644000175100001770000000030000000000000027111 0ustar00runnerdocker00000000000000 from volume cimport cube def menu(description, size): print(description, ":", cube(size), "cubic metres of spam") menu("Entree", 1) menu("Main course", 3) menu("Dessert", 2) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/sharing_declarations/volume.pxd0000644000175100001770000000003100000000000026537 0ustar00runnerdocker00000000000000cdef float cube(float x) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/sharing_declarations/volume.py0000644000175100001770000000004200000000000026376 0ustar00runnerdocker00000000000000def cube(x): return x * x * x ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/sharing_declarations/volume.pyx0000644000175100001770000000005700000000000026574 0ustar00runnerdocker00000000000000cdef float cube(float x): return x * x * x ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.056724 Cython-3.0.8/docs/examples/userguide/special_methods/0000755000175100001770000000000000000000000023501 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/special_methods/total_ordering.py0000644000175100001770000000056600000000000027076 0ustar00runnerdocker00000000000000import functools import cython @functools.total_ordering @cython.cclass class ExtGe: x: cython.int def __ge__(self, other): if not isinstance(other, ExtGe): return NotImplemented return self.x >= cython.cast(ExtGe, other).x def __eq__(self, other): return isinstance(other, ExtGe) and self.x == cython.cast(ExtGe, other).x ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/special_methods/total_ordering.pyx0000644000175100001770000000050700000000000027261 0ustar00runnerdocker00000000000000import functools @functools.total_ordering cdef class ExtGe: cdef int x def __ge__(self, other): if not isinstance(other, ExtGe): return NotImplemented return self.x >= (other).x def __eq__(self, other): return isinstance(other, ExtGe) and self.x == (other).x ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.060724 Cython-3.0.8/docs/examples/userguide/wrapping_CPlusPlus/0000755000175100001770000000000000000000000024137 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/wrapping_CPlusPlus/Rectangle.cpp0000644000175100001770000000140100000000000026543 0ustar00runnerdocker00000000000000#include #include "Rectangle.h" namespace shapes { // Default constructor Rectangle::Rectangle () {} // Overloaded constructor Rectangle::Rectangle (int x0, int y0, int x1, int y1) { this->x0 = x0; this->y0 = y0; this->x1 = x1; this->y1 = y1; } // Destructor Rectangle::~Rectangle () {} // Return the area of the rectangle int Rectangle::getArea () { return (this->x1 - this->x0) * (this->y1 - this->y0); } // Get the size of the rectangle. // Put the size in the pointer args void Rectangle::getSize (int *width, int *height) { (*width) = x1 - x0; (*height) = y1 - y0; } // Move the rectangle by dx dy void Rectangle::move (int dx, int dy) { this->x0 += dx; this->y0 += dy; this->x1 += dx; this->y1 += dy; } } ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/wrapping_CPlusPlus/Rectangle.h0000644000175100001770000000044700000000000026221 0ustar00runnerdocker00000000000000#ifndef RECTANGLE_H #define RECTANGLE_H namespace shapes { class Rectangle { public: int x0, y0, x1, y1; Rectangle(); Rectangle(int x0, int y0, int x1, int y1); ~Rectangle(); int getArea(); void getSize(int* width, int* height); void move(int dx, int dy); }; } #endif ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/wrapping_CPlusPlus/Rectangle.pxd0000644000175100001770000000055500000000000026565 0ustar00runnerdocker00000000000000cdef extern from "Rectangle.cpp": pass # Declare the class with cdef cdef extern from "Rectangle.h" namespace "shapes": cdef cppclass Rectangle: Rectangle() except + Rectangle(int, int, int, int) except + int x0, y0, x1, y1 int getArea() void getSize(int* width, int* height) void move(int, int) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/wrapping_CPlusPlus/cython_usage.pyx0000644000175100001770000000053500000000000027374 0ustar00runnerdocker00000000000000# distutils: language = c++ from Rectangle cimport Rectangle def main(): rec_ptr = new Rectangle(1, 2, 3, 4) # Instantiate a Rectangle object on the heap try: rec_area = rec_ptr.getArea() finally: del rec_ptr # delete heap allocated object cdef Rectangle rec_stack # Instantiate a Rectangle object on the stack ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/wrapping_CPlusPlus/function_templates.pyx0000644000175100001770000000026700000000000030611 0ustar00runnerdocker00000000000000# distutils: language = c++ cdef extern from "" namespace "std": T max[T](T a, T b) print(max[long](3, 4)) print(max(1.5, 2.5)) # simple template argument deduction ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/wrapping_CPlusPlus/iterate.pyx0000644000175100001770000000033600000000000026340 0ustar00runnerdocker00000000000000# distutils: language = c++ from libcpp.vector cimport vector def main(): cdef vector[int] v = [4, 6, 5, 10, 3] cdef int value for value in v: print(value) return [x*x for x in v if x % 2 == 0] ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/wrapping_CPlusPlus/nested_class.pyx0000644000175100001770000000075600000000000027360 0ustar00runnerdocker00000000000000# distutils: language = c++ cdef extern from "" namespace "std": cdef cppclass vector[T]: cppclass iterator: T operator*() iterator operator++() bint operator==(iterator) bint operator!=(iterator) vector() void push_back(T&) T& operator[](int) T& at(int) iterator begin() iterator end() cdef vector[int].iterator iter #iter is declared as being of type vector::iterator ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/wrapping_CPlusPlus/python_to_cpp.pyx0000644000175100001770000000113200000000000027563 0ustar00runnerdocker00000000000000# distutils: language = c++ from libcpp.string cimport string from libcpp.vector cimport vector py_bytes_object = b'The knights who say ni' py_unicode_object = u'Those who hear them seldom live to tell the tale.' cdef string s = py_bytes_object print(s) # b'The knights who say ni' cdef string cpp_string = py_unicode_object.encode('utf-8') print(cpp_string) # b'Those who hear them seldom live to tell the tale.' cdef vector[int] vect = range(1, 10, 2) print(vect) # [1, 3, 5, 7, 9] cdef vector[string] cpp_strings = b'It is a good shrubbery'.split() print(cpp_strings[1]) # b'is' ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/wrapping_CPlusPlus/rect.pyx0000644000175100001770000000122400000000000025635 0ustar00runnerdocker00000000000000# distutils: language = c++ from Rectangle cimport Rectangle # Create a Cython extension type which holds a C++ instance # as an attribute and create a bunch of forwarding methods # Python extension type. cdef class PyRectangle: cdef Rectangle c_rect # Hold a C++ instance which we're wrapping def __init__(self, int x0, int y0, int x1, int y1): self.c_rect = Rectangle(x0, y0, x1, y1) def get_area(self): return self.c_rect.getArea() def get_size(self): cdef int width, height self.c_rect.getSize(&width, &height) return width, height def move(self, dx, dy): self.c_rect.move(dx, dy) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/wrapping_CPlusPlus/rect_ptr.pyx0000644000175100001770000000071100000000000026522 0ustar00runnerdocker00000000000000# distutils: language = c++ from Rectangle cimport Rectangle cdef class PyRectangle: cdef Rectangle*c_rect # hold a pointer to the C++ instance which we're wrapping def __cinit__(self): self.c_rect = new Rectangle() def __init__(self, int x0, int y0, int x1, int y1): self.c_rect.x0 = x0 self.c_rect.y0 = y0 self.c_rect.x1 = x1 self.c_rect.y1 = y1 def __dealloc__(self): del self.c_rect ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/wrapping_CPlusPlus/rect_with_attributes.pyx0000644000175100001770000000206400000000000031141 0ustar00runnerdocker00000000000000# distutils: language = c++ from Rectangle cimport Rectangle cdef class PyRectangle: cdef Rectangle c_rect def __init__(self, int x0, int y0, int x1, int y1): self.c_rect = Rectangle(x0, y0, x1, y1) def get_area(self): return self.c_rect.getArea() def get_size(self): cdef int width, height self.c_rect.getSize(&width, &height) return width, height def move(self, dx, dy): self.c_rect.move(dx, dy) # Attribute access @property def x0(self): return self.c_rect.x0 @x0.setter def x0(self, x0): self.c_rect.x0 = x0 # Attribute access @property def x1(self): return self.c_rect.x1 @x1.setter def x1(self, x1): self.c_rect.x1 = x1 # Attribute access @property def y0(self): return self.c_rect.y0 @y0.setter def y0(self, y0): self.c_rect.y0 = y0 # Attribute access @property def y1(self): return self.c_rect.y1 @y1.setter def y1(self, y1): self.c_rect.y1 = y1 ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/wrapping_CPlusPlus/setup.py0000644000175100001770000000015300000000000025650 0ustar00runnerdocker00000000000000from setuptools import setup from Cython.Build import cythonize setup(ext_modules=cythonize("rect.pyx")) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/wrapping_CPlusPlus/templates.pyx0000644000175100001770000000131300000000000026675 0ustar00runnerdocker00000000000000# distutils: language = c++ # import dereference and increment operators from cython.operator cimport dereference as deref, preincrement as inc cdef extern from "" namespace "std": cdef cppclass vector[T]: cppclass iterator: T operator*() iterator operator++() bint operator==(iterator) bint operator!=(iterator) vector() void push_back(T&) T& operator[](int) T& at(int) iterator begin() iterator end() cdef vector[int] *v = new vector[int]() cdef int i for i in range(10): v.push_back(i) cdef vector[int].iterator it = v.begin() while it != v.end(): print(deref(it)) inc(it) del v ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/wrapping_CPlusPlus/vector_demo.pyx0000644000175100001770000000032400000000000027206 0ustar00runnerdocker00000000000000# distutils: language = c++ from libcpp.vector cimport vector cdef vector[int] vect cdef int i, x for i in range(10): vect.push_back(i) for i in range(10): print(vect[i]) for x in vect: print(x) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/examples/userguide/wrapping_CPlusPlus/wrapper_vector.pyx0000644000175100001770000000046700000000000027752 0ustar00runnerdocker00000000000000# distutils: language = c++ from libcpp.vector cimport vector cdef class VectorStack: cdef vector[int] v def push(self, x): self.v.push_back(x) def pop(self): if self.v.empty(): raise IndexError() x = self.v.back() self.v.pop_back() return x ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/index.rst0000644000175100001770000000050700000000000016367 0ustar00runnerdocker00000000000000Welcome to Cython's Documentation ================================= Also see the `Cython project homepage `_. .. toctree:: :maxdepth: 2 src/quickstart/index src/tutorial/index src/userguide/index src/userguide/glossary src/reference/index Contributing src/changes ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/make.bat0000644000175100001770000001507500000000000016141 0ustar00runnerdocker00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. xml to make Docutils-native XML files echo. pseudoxml to make pseudoxml-XML files for display purposes echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) %SPHINXBUILD% 2> nul if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.https://sphinx-doc.org/ exit /b 1 ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Sphinx-Gallery.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Sphinx-Gallery.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdf" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf cd %BUILDDIR%/.. echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdfja" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf-ja cd %BUILDDIR%/.. echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) if "%1" == "xml" ( %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml if errorlevel 1 exit /b 1 echo. echo.Build finished. The XML files are in %BUILDDIR%/xml. goto end ) if "%1" == "pseudoxml" ( %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml if errorlevel 1 exit /b 1 echo. echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. goto end ) :end ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.060724 Cython-3.0.8/docs/src/0000755000175100001770000000000000000000000015313 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/changes.rst0000644000175100001770000000003700000000000017455 0ustar00runnerdocker00000000000000.. include:: ../../CHANGES.rst ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/cimport-warning0000644000175100001770000000064500000000000020363 0ustar00runnerdocker00000000000000.. warning:: The code provided above / on this page uses an external native (non-Python) library through a ``cimport`` (``cython.cimports``). Cython compilation enables this, but there is no support for this from plain Python. Trying to run this code from Python (without compilation) will fail when accessing the external library. This is described in more detail in :ref:`calling-c-functions`. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/donating.rst0000644000175100001770000000414600000000000017655 0ustar00runnerdocker00000000000000:orphan: 🌷️ Thank you for your interest in supporting Cython! 🌷️ ========================================================= Managing, maintaining and advancing a project as large as Cython takes **a lot of time and dedication**. **Your support can make a difference** for a great tool that helps you every day! Please consider signing a subscription for continuous project support via * `GitHub Sponsors `_ * `Tidelift `_ * `PayPal `_ or donating via * `PayPal `_ Note that PayPal takes 5 - 15% fees for small non-EUR payments, which is money that *you pay without helping us*. Consider signing up for a GitHub Sponsors subscription instead, which is currently free of additional charges. Also note that we are not accepting donations in crypto currencies. Much of the development for Cython is done in a carbon-neutral way or with compensated and very low emissions. Crypto currencies do not fit into this ambition. Legal Notice for Donations -------------------------- Any donation that you make to the Cython project is voluntary and is not a fee for any services, goods, or advantages. By making a donation to the Cython project, you acknowledge that we have the right to use the money you donate in any lawful way and for any lawful purpose we see fit and we are not obligated to disclose the way and purpose to any party unless required by applicable law. Although Cython is free software, to the best of our knowledge the Cython project does not have any tax exempt status. The Cython project is neither a registered non-profit corporation nor a registered charity in any country. Your donation may or may not be tax-deductible; please consult your tax advisor in this matter. We will not publish or disclose your name and/or e-mail address without your consent, unless required by applicable law. Your donation is non-refundable. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.060724 Cython-3.0.8/docs/src/quickstart/0000755000175100001770000000000000000000000017505 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/quickstart/build.rst0000644000175100001770000001043600000000000021342 0ustar00runnerdocker00000000000000Building Cython code ==================== Cython code must, unlike Python, be compiled. This happens in two stages: - A ``.pyx`` or ``.py`` file is compiled by Cython to a ``.c`` file, containing the code of a Python extension module. - The ``.c`` file is compiled by a C compiler to a ``.so`` file (or ``.pyd`` on Windows) which can be ``import``-ed directly into a Python session. `setuptools `_ takes care of this part. Although Cython can call them for you in certain cases. To understand fully the Cython + setuptools build process, one may want to read more about `distributing Python modules `_. There are several ways to build Cython code: - Write a setuptools ``setup.py``. This is the normal and recommended way. - Run the ``cythonize`` command-line utility. This is a good approach for compiling a single Cython source file directly to an extension. A source file can be built "in place" (so that the extension module is created next to the source file, ready to be imported) with ``cythonize -i filename.pyx``. - Use :ref:`Pyximport`, importing Cython ``.pyx`` files as if they were ``.py`` files (using setuptools to compile and build in the background). This method is easier than writing a ``setup.py``, but is not very flexible. So you'll need to write a ``setup.py`` if, for example, you need certain compilations options. - Run the ``cython`` command-line utility manually to produce the ``.c`` file from the ``.pyx`` file, then manually compiling the ``.c`` file into a shared object library or DLL suitable for import from Python. (These manual steps are mostly for debugging and experimentation.) - Use the [Jupyter]_ notebook or the [Sage]_ notebook, both of which allow Cython code inline. This is the easiest way to get started writing Cython code and running it. Currently, using setuptools is the most common way Cython files are built and distributed. The other methods are described in more detail in the :ref:`compilation` section of the reference manual. Building a Cython module using setuptools ----------------------------------------- Imagine a simple "hello world" script in a file ``hello.pyx``: .. literalinclude:: ../../examples/quickstart/build/hello.pyx The following could be a corresponding ``setup.py`` script: .. literalinclude:: ../../examples/quickstart/build/setup.py To build, run ``python setup.py build_ext --inplace``. Then simply start a Python session and do ``from hello import say_hello_to`` and use the imported function as you see fit. .. _jupyter-notebook: Using the Jupyter notebook -------------------------- Cython can be used conveniently and interactively from a web browser through the Jupyter notebook. To install Jupyter notebook, e.g. into a virtualenv, use pip: .. code-block:: bash (venv)$ pip install jupyter (venv)$ jupyter notebook To enable support for Cython compilation, install Cython as described in :ref:`the installation guide` and load the ``Cython`` extension from within the Jupyter notebook:: %load_ext Cython Then, prefix a cell with the ``%%cython`` marker to compile it .. tabs:: .. group-tab:: Pure Python .. code-block:: python %%cython a: cython.int = 0 for i in range(10): a += i print(a) .. group-tab:: Cython .. code-block:: python %%cython cdef int a = 0 for i in range(10): a += i print(a) You can show Cython's code analysis by passing the ``--annotate`` option:: %%cython --annotate ... .. figure:: jupyter.png For more information about the arguments of the ``%%cython`` magic, see :ref:`Compiling with a Jupyter Notebook `. Using the Sage notebook ----------------------- .. figure:: sage.png For users of the Sage math distribution, the Sage notebook allows transparently editing and compiling Cython code simply by typing ``%cython`` at the top of a cell and evaluate it. Variables and functions defined in a Cython cell imported into the running session. .. [Jupyter] https://jupyter.org/ .. [Sage] W. Stein et al., Sage Mathematics Software, https://www.sagemath.org/ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/quickstart/cython_in_jupyter.ipynb0000644000175100001770000007567600000000000024351 0ustar00runnerdocker00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Installation\n", "\n", "```pip install cython```\n", "\n", "# Using inside Jupyter notebook\n", "\n", "Load th cythonmagic extension." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%load_ext cython" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then, simply use the magic function to start writing cython code." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "45\n" ] } ], "source": [ "%%cython\n", "\n", "cdef int a = 0\n", "for i in range(10):\n", " a += i\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Add `--annotate` or `-a` for showing a code analysis of the compiled code" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "45\n" ] }, { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_6ba45f17d130910db2606828f4326b2d.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.25.2

\n", "

\n", " Yellow lines hint at Python interaction.
\n", " Click on a line that starts with a \"+\" to see the C code that Cython generated for it.\n", "

\n", "
 1: 
\n", "
+2: cdef int a = 0
\n", "
  __pyx_v_46_cython_magic_6ba45f17d130910db2606828f4326b2d_a = 0;\n",
       "
+3: for i in range(10):
\n", "
  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_range, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {\n",
       "    __pyx_t_2 = __pyx_t_1; __Pyx_INCREF(__pyx_t_2); __pyx_t_3 = 0;\n",
       "    __pyx_t_4 = NULL;\n",
       "  } else {\n",
       "    __pyx_t_3 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3, __pyx_L1_error)\n",
       "    __Pyx_GOTREF(__pyx_t_2);\n",
       "    __pyx_t_4 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3, __pyx_L1_error)\n",
       "  }\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  for (;;) {\n",
       "    if (likely(!__pyx_t_4)) {\n",
       "      if (likely(PyList_CheckExact(__pyx_t_2))) {\n",
       "        if (__pyx_t_3 >= PyList_GET_SIZE(__pyx_t_2)) break;\n",
       "        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS\n",
       "        __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_1); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 3, __pyx_L1_error)\n",
       "        #else\n",
       "        __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3, __pyx_L1_error)\n",
       "        __Pyx_GOTREF(__pyx_t_1);\n",
       "        #endif\n",
       "      } else {\n",
       "        if (__pyx_t_3 >= PyTuple_GET_SIZE(__pyx_t_2)) break;\n",
       "        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS\n",
       "        __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_1); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 3, __pyx_L1_error)\n",
       "        #else\n",
       "        __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3, __pyx_L1_error)\n",
       "        __Pyx_GOTREF(__pyx_t_1);\n",
       "        #endif\n",
       "      }\n",
       "    } else {\n",
       "      __pyx_t_1 = __pyx_t_4(__pyx_t_2);\n",
       "      if (unlikely(!__pyx_t_1)) {\n",
       "        PyObject* exc_type = PyErr_Occurred();\n",
       "        if (exc_type) {\n",
       "          if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();\n",
       "          else __PYX_ERR(0, 3, __pyx_L1_error)\n",
       "        }\n",
       "        break;\n",
       "      }\n",
       "      __Pyx_GOTREF(__pyx_t_1);\n",
       "    }\n",
       "    if (PyDict_SetItem(__pyx_d, __pyx_n_s_i, __pyx_t_1) < 0) __PYX_ERR(0, 3, __pyx_L1_error)\n",
       "    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "/* … */\n",
       "  }\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "
+4:     a += i
\n", "
    __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_46_cython_magic_6ba45f17d130910db2606828f4326b2d_a); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "    __Pyx_GOTREF(__pyx_t_1);\n",
       "    __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_i); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "    __Pyx_GOTREF(__pyx_t_5);\n",
       "    __pyx_t_6 = PyNumber_InPlaceAdd(__pyx_t_1, __pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "    __Pyx_GOTREF(__pyx_t_6);\n",
       "    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "    __pyx_t_7 = __Pyx_PyInt_As_int(__pyx_t_6); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;\n",
       "    __pyx_v_46_cython_magic_6ba45f17d130910db2606828f4326b2d_a = __pyx_t_7;\n",
       "
+5: print(a)
\n", "
  __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_46_cython_magic_6ba45f17d130910db2606828f4326b2d_a); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 5, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 5, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_6);\n",
       "  __Pyx_GIVEREF(__pyx_t_2);\n",
       "  PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_2);\n",
       "  __pyx_t_2 = 0;\n",
       "  __pyx_t_2 = __Pyx_PyObject_Call(__pyx_builtin_print, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 5, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython --annotate\n", "\n", "cdef int a = 0\n", "for i in range(10):\n", " a += i\n", "print(a)" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python [conda env:py3]", "language": "python", "name": "conda-env-py3-py" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.2" } }, "nbformat": 4, "nbformat_minor": 1 } ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/quickstart/cythonize.rst0000644000175100001770000001732100000000000022257 0ustar00runnerdocker00000000000000Faster code via static typing ============================= .. include:: ../two-syntax-variants-used Cython is a Python compiler. This means that it can compile normal Python code without changes (with a few obvious exceptions of some as-yet unsupported language features, see :ref:`Cython limitations`). However, for performance critical code, it is often helpful to add static type declarations, as they will allow Cython to step out of the dynamic nature of the Python code and generate simpler and faster C code - sometimes faster by orders of magnitude. It must be noted, however, that type declarations can make the source code more verbose and thus less readable. It is therefore discouraged to use them without good reason, such as where benchmarks prove that they really make the code substantially faster in a performance critical section. Typically a few types in the right spots go a long way. All C types are available for type declarations: integer and floating point types, complex numbers, structs, unions and pointer types. Cython can automatically and correctly convert between the types on assignment. This also includes Python's arbitrary size integer types, where value overflows on conversion to a C type will raise a Python ``OverflowError`` at runtime. (It does not, however, check for overflow when doing arithmetic.) The generated C code will handle the platform dependent sizes of C types correctly and safely in this case. Types are declared via the cdef keyword. Typing Variables ---------------- Consider the following pure Python code: .. literalinclude:: ../../examples/quickstart/cythonize/integrate.py :caption: integrate.py Simply compiling this in Cython merely gives a 35% speedup. This is better than nothing, but adding some static types can make a much larger difference. With additional type declarations, this might look like: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/quickstart/cythonize/integrate_cy.py :caption: integrate_cy.py .. group-tab:: Cython .. literalinclude:: ../../examples/quickstart/cythonize/integrate_cy.pyx :caption: integrate_cy.pyx Since the iterator variable ``i`` is typed with C semantics, the for-loop will be compiled to pure C code. Typing ``a``, ``s`` and ``dx`` is important as they are involved in arithmetic within the for-loop; typing ``b`` and ``N`` makes less of a difference, but in this case it is not much extra work to be consistent and type the entire function. This results in a 4 times speedup over the pure Python version. Typing Functions ---------------- Python function calls can be expensive -- in Cython doubly so because one might need to convert to and from Python objects to do the call. In our example above, the argument is assumed to be a C double both inside ``f()`` and in the call to it, yet a Python ``float`` object must be constructed around the argument in order to pass it. Therefore, Cython provides a way for declaring a C-style function, the Cython specific ``cdef`` statement, as well as the ``@cfunc`` decorator to declare C-style functions in Python syntax. Both approaches are equivalent and produce the same C code: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/quickstart/cythonize/cdef_keyword.py .. group-tab:: Cython .. literalinclude:: ../../examples/quickstart/cythonize/cdef_keyword.pyx Some form of except-modifier should usually be added, otherwise Cython will not be able to propagate exceptions raised in the function (or a function it calls). The ``except? -2`` means that an error will be checked for if ``-2`` is returned (though the ``?`` indicates that ``-2`` may also be used as a valid return value). The same can be expressed using only Python syntax with the decorator ``@exceptval(-2, check=True)``. Alternatively, the slower ``except *`` is always safe. An except clause can be left out if the function returns a Python object or if it is guaranteed that an exception will not be raised within the function call. Again, Cython provides the decorator ``@exceptval(check=True)`` providing the same functionality. A side-effect of ``cdef`` (and the ``@cfunc`` decorator) is that the function is no longer visible from Python-space, as Python wouldn't know how to call it. It is also no longer possible to change :func:`f` at runtime. Using the ``cpdef`` keyword instead of ``cdef``, a Python wrapper is also created, so that the function is available both from Cython (fast, passing typed values directly) and from Python (wrapping values in Python objects). In fact, ``cpdef`` does not just provide a Python wrapper, it also installs logic to allow the method to be overridden by python methods, even when called from within cython. This does add a tiny overhead compared to ``cdef`` methods. Again, Cython provides a ``@ccall`` decorator which provides the same functionality as ``cpdef`` keyword. Speedup: 150 times over pure Python. .. _determining_where_to_add_types: Determining where to add types ------------------------------ Because static typing is often the key to large speed gains, beginners often have a tendency to type everything in sight. This cuts down on both readability and flexibility, and can even slow things down (e.g. by adding unnecessary type checks, conversions, or slow buffer unpacking). On the other hand, it is easy to kill performance by forgetting to type a critical loop variable. Two essential tools to help with this task are profiling and annotation. Profiling should be the first step of any optimization effort, and can tell you where you are spending your time. Cython's annotation can then tell you why your code is taking time. Using the ``-a`` switch to the ``cython`` command line program (or following a link from the Sage notebook) results in an HTML report of Cython code interleaved with the generated C code. Lines are colored according to the level of "typedness" -- white lines translate to pure C, while lines that require the Python C-API are yellow (darker as they translate to more C-API interaction). Lines that translate to C code have a plus (``+``) in front and can be clicked to show the generated code. This report is invaluable when optimizing a function for speed, and for determining when it is possible to :ref:`release the GIL ` (be aware that releasing the GIL is only useful under limited circumstances, see :ref:`cython_and_gil` for more details): in general, a ``nogil`` block may contain only "white" code. .. tabs:: .. group-tab:: Pure Python .. figure:: htmlreport_py.png .. group-tab:: Cython .. figure:: htmlreport_pyx.png Note that Cython deduces the type of local variables based on their assignments (including as loop variable targets) which can also cut down on the need to explicitly specify types everywhere. For example, declaring ``dx`` to be of type double above is unnecessary, as is declaring the type of ``s`` in the last version (where the return type of ``f`` is known to be a C double.) A notable exception, however, is *integer types used in arithmetic expressions*, as Cython is unable to ensure that an overflow would not occur (and so falls back to ``object`` in case Python's bignums are needed). To allow inference of C integer types, set the ``infer_types`` :ref:`directive ` to ``True``. This directive does a work similar to the ``auto`` keyword in C++ for the readers who are familiar with this language feature. It can be of great help to cut down on the need to type everything, but it also can lead to surprises. Especially if one isn't familiar with arithmetic expressions with c types. A quick overview of those can be found `here `_. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/quickstart/demo.pyx0000644000175100001770000000254300000000000021177 0ustar00runnerdocker00000000000000from time import time from math import sin cdef double first_time = 0 def timeit(f, label): global first_time t = time() f(1.0, 2.0, 10**7) cdef double elapsed = time() - t if first_time == 0: first_time = elapsed print label, elapsed, (100*elapsed/first_time), '% or', first_time/elapsed, 'x' # Pure Python py_funcs = {'sin': sin} py_funcs.update(__builtins__.__dict__) exec """ def f(x): return x**2-x def integrate_f(a, b, N): s = 0 dx = (b-a)/N for i in range(N): s += f(a+i*dx) return s * dx """ in py_funcs timeit(py_funcs['integrate_f'], "Python") # Just compiled def f0(x): return x**2-x def integrate_f0(a, b, N): s = 0 dx = (b-a)/N for i in range(N): s += f0(a+i*dx) return s * dx timeit(integrate_f0, "Cython") # Typed vars def f1(double x): return x**2-x def integrate_f1(double a, double b, int N): cdef int i cdef double s, dx s = 0 dx = (b-a)/N for i in range(N): s += f1(a+i*dx) return s * dx timeit(integrate_f1, "Typed vars") # Typed func cdef double f2(double x) except? -2: return x**2-x def integrate_f2(double a, double b, int N): cdef int i cdef double s, dx s = 0 dx = (b-a)/N for i in range(N): s += f2(a+i*dx) return s * dx timeit(integrate_f2, "Typed func") ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/quickstart/htmlreport_py.png0000755000175100001770000005203700000000000023135 0ustar00runnerdocker00000000000000PNG  IHDRAtasRGBgAMA a pHYsodtEXtSoftwareGreenshot^USIDATx^?$əd  ='cd Z4 ]Bh.L;mHw׻48 kH@;w5;7DdD;Yu2|?o B7Ϟ.ʩ}p#\.Я? wmd,IU7 ȉ>,D:gɵz\ 'ikNsT,m4hǖ˾۶94xEelNRHfA0szEW=q^5TQnRZg[Y{d5Δ|>⋫T݅Řb$6ۯԢ s[X,V'j(.r _5R^Z4TgU~iʼn/d`*;EMQH~vbp_nȏPORka#CXhR%.*?-773բaܐM7 SZ!PQ#ɚQ8~ͫ^ke8N/mVJH(hXv57{D-+V9کfՁYG%o8\2AԲb;wd5 3\5lUjnfm컓.T5)j ןT/U2\RNYcbnaYǨ5ֹjF-VGL ?^cZ,SF gLxL<<\oavh{\r}Ԫě)ӂNx;"֯yՋqݴڛP)noV_̥O+[94xN9~rs=ՇdYs_=FmiJne3r?z)g){fmG,[` gBI&,\*}6-wɰD\J[}M2Rs.~|p4{ e0OܖiOeِv|L-4Hk/9v}]cWj9nq@~&oyJKъ!+ 8K^#wFMV,?\ˌT߷7q.]~| w pD !y3| <_OM/:C4)c^ya f8y.6]+Ox'u=7t6Z<Ӧ^5C^3|OEC0^= yu}QPٟt[6ը%;TMGL/9>x2YjMWѧTY`'Ϟq'q;H"O[q$zc7i|'t&Oq9?R?=9^K[: 51;lj6p<nG5<8gOnL:hWN`6ś20,IP-g1_5lVñ?rȑ>`{;ʎFO7KdCQڥ#{ywv] *mv~ZZ62\=| nVP9*(n1ͨFcHORk둳h|+?Anz]T` ۲S[M_?LWbA61HHéZ,ޱ1VYLz84[[s{N8Tcci8g@h㊃cH~ZrWWl;f;K[>x-u5uU^ʉOF@=v^CCƣ줋cZβŴWd32hYE@٢!3OZc?`B;s7Pilt8b`|]8˞q* 4nu?-en[i R?C`6\2CGX2aExb{78gȴih ԙ 8-Q =lP}ȁvT3|Hsu*n0Ɇڶo)<3,*[!v ~bF,S^V@sz%OoZ07}/2OՕ ϦCpNy,q IkWc`Uן&_B1H;L O!+qlՕiM< OXiVVEuً@{yץ)kP ڇ,֘6NjQ#^~Zt}ŏWCOQR1ESFuNpv<6͡gq?qe' MM'Q CPmvXo7Qkkߡ)*ojdGenɜ$fN>tSDZXxf<?:c|,^4nrSCz6zKX;dIJ-Dj9nq}JJuԍƎFF9|iNEUѦOfYܷ9_p 0Ӊ0`w}d8hwpE~/ub2 ?d8!`pC2 ?d8!`pC2 ?d8!g_ kgo=)<}mԫO}oLn7  ӛm2}؉9NT\>OLԳҮqiypKdݦq[\fZ\mzGRj\[?ٓgϭNozJM<{6;~g4MUZ=gO^'}gfd8;;3)M{Y̶!̚'~R͛i7k-p&*HsaˑzoȎ1I> Ʀ}&3 {$ESpf0w'fN΍n,I< Q$/{On[C{Y3ZTʐںgYIrؓge p!zZʦfQ%åfʎ5+<OAy"XrS̭)N0JzkҢb3Le&SQ)Ϋ7aMMpqKoBK`Nz`/e+-[nR4C-*peTm]<ÍOPIrTqi2YfÕjsG"瘈*[>yRܞy@kp0v}\k;8ǰm7kvOÙ$m=3gg8=J ޖug if1Q:4|HYwjY-6J2Q硫jVӓ7 U6醳j7CլR1٘ԥwCZrڻ=_5IiZITnwWA9'sor7lN):hVpcoN^e!:_S!yGM퇯O]}ݥ2Lxfؔ~h4vmw8ģ3\k~eq0q )ݽO9=Ey~Pgs|w8tqKq?`OpM g81*eg7;E%rA͆K.1ظz`B|O5I#qKK m\]=޾OR墏!u%ެ7@ƔrMϘi"qxѹ~OeвwmX:DRK-L=¿?_#ÙKĽ C._^nayLe8;im"ksM5pd F#lgYiV٥`\knOΙwOCuK*d㖷wWygњ1ұfZ4ƃ8,Ndy9CK?Ki)Z.=9eijȂM '`:^'2\e^+t51]Ce8wT?.K0کϒ g(WS6 N.6HS5 $w,3%`W}7q{6muh%g 4McWn0wї~?EC?.]3$An8?'E<$2 ?d8!`f,|m(,p͘[ctӿU-pO,V+X#ead8լ<x/Le{EzMs.W*ofَRV,I\*Apg0 ?d8!`p ?~to~v_oi_[^u6߯?_w}]/%{cЄ SC0Ei_o*_>`;u/X̶$ ]?ùI$ܟ&sf)U}Ͽ}mnͽJfV<~WZpi_5g6ųH3ej2eP ZeǔW*I)VmcˍulY裦Vvn2G*z{З_wzy[i*dZ$:%{mivx.N(Ƃ8[#Kի|e8.>F+:=֚K9?c(>F:)˻l|824;ڑMҨCn,t VfJMV۱y5ۉ²- '>1}8ﻴc2\6g^LgYpqf82ITT>ߐZ;%Tn 4rz $jLЪ֘MFhe(lqqPyu$w/nNJ=^]X#ŗoYȳxQ~wxdv۷upESZNG.Z*4n(-! ŵjc/9^<½S/չa^~.d x45.ɄxYceVpE`S%13dT53\%e,9%/\AR *7q,( ٓ)6=w~2F*JU9FN}|mGdz`+ܖe8=O^ͫz_3\"q &8T8]7k_mGuE?k\=ҳnVΩ׌J<^s[7 wcxy%~{+{nv/jS mg+ɞ﹜Ey%T+;ٻ,|58[QrVzIoNxIn^+3X a'CHǧ afjY/N*^k漦:JV }`AM./W8UYNN]]ҸGN8; An~Z".?O~sۆ!_[wRKEܙCGFyɅUC_ϡ퍽<^n/ʙ >ID<(2\}L\\2 ?d8!go?ܽYN>ŋ?z^iK3\rO ~/ K_'">*+~L ^~ߴ}ȿw"&fb?~{~:,dU2T ~.|/vFMKaNuF!tK*~N!] '~kEpG+/[-Y8򻮒uflqPoOg*. M6j9xCSw׾im޽4!^Pk-֘:̬Ùs[o֪2;%&Dɇof-ye;՟_28i޳k/St3aΟ4h:0@k]n3\=JlXYXV1-p *߾& l@iTFpii/Hr z 2`^I3mlZZ-zKG];4|oo$K?2\;Hxd$C ٱ B6 LlNϫTbC=IlI? 7gVg򱮏^:))*ΦDjݝƻ+d8dw,Mu:Yar5–>QMsXBy5*- ǷM~z8M5? 9#v`:nEXZkUf8NMvHl[4<"6v~Ȩa>/|ύ-4ZnU!?bٿ-[2/ _uN8 'Rg6CEp +MMt٣pC2 ?d8Y_Õ,p&ʾLU}ſYR?eU7CGX.Vj'0pY5iX8eYӟuKof.zXѢiPlYӟ+3fY3i~R<\pYpC2 ?d8!`fC //jfQ3I Li-_n`eK2\so[Icv`kd8'VpY5srQ`=2 \R ,Q}Zp弗 e.eZ̛S52jf8< 2 ?QEQEQ,2EQEQ GQEQ"QEQEfn7QX~wߛ7onT,2r8Xx5uw-n3;AYrxgxc Ów AkW֩K=^=?p(*jBAW[5/&M뼎H&nNݗk|<d{ש=(_*c:1O?G&0kA8qh.5\2AQe8WLb/^si/~p\*.㋸Xըӗ77wy8;~~nnbxz%ԋZu\pxpr^jZ;~7nhnk[b&~۷߻yㇰׂyӗ{BVN_}C2Y-NIʎ)uwg7|(n/^CgV&ryו5OI jNnM1gB;1Qb/x)s)ϥדl~qxIz^x[vxonO)1nk Õdd`Z^C8MOIHVS׆ϻ WΓӡ8Jl)=swAQCor&U\LܪS]r<ݾec7wkX'dN- =^c _vxŪeV;~*5Ժp Kpp?9v1 WJͫW9ǍUdt ی'CbLCW^gNwjx];v +6Pkf82q Kzor*}\W<^zF/ќ gjWc>`MK2_WxS-4riN*4!}7Nfonې?k1uNj);>{aXo`-de^L=3 `pC2 ? 3 4=|-vՎ䥾^n8  x.+26pu3j?PS_z&a3={f6g}{ǝ]P=⠒Tu`3\H/y^:'ӓ9۫U- y_g_6JKY<\W%KFz|9^sæ=̽\z=dSkN_v1$SиsI=3 *702 FL~<0K],7!u8#V xX93Sm}`/D}2\Ҳգ=pz>FPv%h3.':dz-flnp*CЛOLيַow]k# 6=UVX0ג '{-]՚*VWO$t1lNb^CcGZ굓V G7v?郚8ȊZ".?O~sۆ_[wRK42I8pM{1 ?d8!`pC؟}M Yͮ|_eߪ 'sJ蝹+|d}oMRXݢ Ԗg87sd~ʟ,5%$o߼T߽$ ~]5+3po Kne\L֎F+=#^jÙ8< ],mTVz&L7 d=MӸx#u9K$8p26 ?d8!`2ܿQEQEQ,2EQEQ G-wyU(K w{?Uߞ)[|שܰ#o_>7\U 9}2EQu5!+$wVL`gK_;v8yeVw*״ILJC"EQEQZ\pvk+si; J1KnFw񿦥L|{٣@KgstDetvse2*(֬3 F׶LObN*K5wDLPM*sl.C=JB.,c>j'$%QEQԺ5t +۹.P.ĸÔX|Lie:}<_yΊeex/ I8Syz#QEQԚ<ٔpmGĚpydps+i5>/sԐApEQfLHrw-^jdnѱ*)3n뎒O2!'<ԌI8S)ùG GQEQՒ 6"Qf#NyWMd8?u"|Db-r ߾qi_bܜypI )(֫ Z6a9-O|[,((a 0 ϨQEQ^ GQEQ"QEQEpEQEQ "`f[㭿u;E[tz}s<{j>> _t:ugHx \;\7ݼ=s_LpSj t?m`EΩ,_q2[p_8+E_W&N6}ݿ}dW~*_׽[Pp^w ncUp8 ^a(LI\ raxn*yif8Yr,6 6vmـTy(mқ,}{7 ,gw_7X%;|k.`}8߻SD:ЃNm#cj-c\9 iR ٸ:|08L94]/wt>WjaVn˪Pn?zmzxPhmZ0I+nyMpx:3lZ!#á"ͷ|:b3f=d8!`C2 7߾>v/rCߺQb8Go7Ǚdַv!緹 gr/|Ip7sle!odl^jlg8(ewLq)2\6Oֲy8:bR2m ) 4eq)AvK̚S61tgi2d8.a. Y 7bwꌉYaQIhĤҺ㓂۔КM\63\tJy!1:LTR6;I2J6'L).^d8.a索P[L2n*S"D HNSpqiqLEE]0`}abW"uI@%)!l9av1̎N5oW۵>`\=Z(&Oz6ҬW|G;cpv W~,Q븭n,< ?d8!M?Uo5axGfb$MF`Jo68e8;}UfM鞻eNY~h^pebd9l|{w-n"҂ƥuJ5d 7F69>N?8f,Ada$,Tb11+,(IF!1n!V=Qд G(B4)C1ebXQ2]G+{*yB9JvpHT%R =Fi>n1aF;ַy/L.P IB0%3-}<,m8 )# {3g|L@m.åY? =[sgR'Zm?w0>` ?d8!2ebv_V?N88]|}kPmm|c7 kjka|``((m((jE((_((W 3onn酧,Ke=4Nw*מ<ޖ Z? ~]oHx0O_ܖˋ߆(Q2/|}|wOշͫr)8X8g޽x'2܋7c7LZ(c-pZmeyNΔ ҔdԹ"M|08;U`LΙ4L֟ܟɛo{iSp~?A=TEQu%u iW< %W-p k OO!ܔns֌I)ΜN g{&ƹU{QEQԎk åIifSu hl}<%fy8[$Rȣ((j[W{EƲ+kկO3ܩS`&TIޫ=8VqᏎomnU^q./H\q`u?<8(ZMpEQEQƊ GQEQ"QEQEpEQEQ+2EQEQYd8!`pC؛)!ԒIENDB`././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/quickstart/htmlreport_pyx.png0000755000175100001770000004567000000000000023332 0ustar00runnerdocker00000000000000PNG  IHDRAtasRGBgAMA a pHYsodtEXtSoftwareGreenshot^UK/IDATx^=$ٝƐ!C -Czchл1 BbDqa[FPkiiuFbv ڹEkW2p('O01׷5 bm;~D*= sd'l8x -ɍD͈͎Ŏf˫4<DΔav`rm*a](ņV8#s3\ff4I1Pz-eV2r?RÒ-EŜ%2lzrTъïX4\5d~o1tQ<Uf8quTqz4" F't伞"J^6SGi)IPejzbA%9fvq'UpHez~nO :rfOOL iG:KY͊,xzefU(ohw"vN9[F~."G Zu|  1ГF.1ˌH46+ÉONtˣn*`?z}{!?NQ56--0H$Gdp:`%iJwI;%| ^үL҂իO%A}Qf)%X%,8 >ʹ\lK֒MW g({Y9l0jZL8HdS_T^e w8p.ӿ@;u"@{p9noC?Urcy.Μ*8o"A(YeW o 3ǻ38K8Yoq|C, x^7WVt4]ɼsڥ:_y}Gc!EQGC5e'*61Cwlyѓ:YeeKN6uKx7yWt4]yKEiuАq':dJQ;Y~ x 7ڮ\@"hRȧJ}?`rȉމLc ! O'A 9ʞv2 4]nulJ;KÕv,E8-?ᅶ{cM+ij&EPJG?#]0xI"ݥK2)keE/<i&zB^C Tޟd`u/-/k_̼JoҲ=1MLxLgPykcʹ2$|XM*z,x>>~x[5튥-7Y~LKfo5ntYĭb'{ҵ4h(s3[JS{[<\MKuYRaL6ߕ}(NO] }7vAwvRoGxIJ b)KN+(tRygՏ%~l+uM3IaffIyVGNj:V,"dh=ϬLJ(\qPpw$'ef^u2ʐ|fN鉢1jt(é"|S^d?DdneýFT1‰N${&TRr&I6rv{UK!Y=b2](~|<~A-'Aqj'Y.?t+uf~o^6!we_ǡ۹5s7A/7;q+rt796O-hA&5#(l?+*ZhC W21'{Dsٝ,v/<`i8 Հo2śO/3LC~NvoLMO+^hGj֛?n=p l#퟊.6; Oմ*MWyv3c!'ޣizɔle3['ڗcuLL^ oٯ Wfb|c/OM&L/b>PsL<9h ɷ,8,rEk3d{](($s$?7:ƉW?aJڔ⃩=AM@2'3F3ɴ"4Ϩ@ֽ="ܹ"0&^k/u=d8Ch=d8Ch=d8Ch=d8Ch=d8Ch=d8H_=fd=Vzdxze'Ͼ2tfzBpqzzYw!FLprhtz_-Z7gz}nu }x77S?5ͤCnMqv)뻠_TO|_Aؓgg"{U= vK)f|gOZ 껉 NƝR'SsijhIJ&Ĝ'jLYeFQIG4M&04{ޅ{.|M.L&&}riig.uN o,xb+3?Z߈тI). YA[pӉ;$<E(C,d8ɮڬe)pY'bN0B)(xQ3 ˜T,&…td?)y 'I_iTrj" 4*mT݋Y NiKZTOS.^4!Νu 7>@% @Kɢ7i.MT*1LNBI)*|D$b*b4ͨnxpjdg*U?Sp&+qq823\J.0(wxn"r3!Iy̖SdAs!:YzVŌ~z ֍Bla`51l#pY5dP3%ed#RW8%yjӒ'uɔDW69?V撋ײyEح[1<w6c<2#A< ^}I.I?exzvGpMRciņzCe8}߬*ù"92?^*||rNFC'QI7:Bk- ob3/'Fl3 f ge q׎ù3\* tlueqMp6; w=y.o?g8D^$.f^^K L◜^,e0a#R]2h2L3buRƭj?}QHB"ڼ 'ΆV4->g8 ?+>8bfMڋuw2=w١'rgp辋3dPӓϥEζ#DSAMoKlEf2=}S!~Tk2ϩfsO*a^: o8׾~,|bIC혙Kg8dp! 2@{p!gnsϧͬ w oq$E9.dzcT#pF ,pQX+݊ 3!"Rd^+^KM3; wgawZte;,f^q5 Dh=d8Ch=d8pG~3ګ~Η_8YN4{0Ik[`s2\|7(tpk `1Kd8wkT{2-tLsһ`!2\G<N~gӯw?CQ_1S᰻lL;|/WZӾf5\p4sVǬ/nCUdOܞS(@Ѣ[HƸ U.ݜ '+d8m| mI_؎$cZ V7n_VMʜ Oy?pW8 .zS.w(ĤpVɛjL}ܙ<ު؛]S5s [39C@ѫg5$Df%U[Jg^1 M GLJ!SS79~y۪;haUasGI^Ν\]_NRgG3uٴ{'s9S?$uzvIp|uy+*O]_3txg0|fcpѸuppCOWH ME cyb,M6V[oAͲνI b;}xՓ۴q8o_$NPP6);O) ְ& 3a)ʓ; 6h<z'd )oޚ,mFM1=7t!\LH3\0g*| '^^0I~rHH_'^Xk+D-) *bJxōR-!Nppyp8Op&_S W>?Ld{ tv}SCn3~ wVƙI|;2P(f}nS<h k[Dhϑѵ->Ū~y52gN^?`#nZjɂӘKsL^KCǯm%SjLʗF8teÚx=},/f8dfZuc8z r Tr2Ul;3Z*` ζZzI$l7}ZsjD? wA{|$. ~(f~[dg~F$`g;}3ӝ4^D;!2 *nv76>bkhï]T.d R[/!;J*5f [3{f%cx*! p^g5p  w& [jƏb p! 2@{p!áo߼{w?޽wȘ܏?k ~-SL{/Tf/:-¿ ͥHooWS]xqa:#۱{7w=cEw%w+UiC3>?{{+Cj],+L}ѹT>m7"'y}3d=Yᛛk\pZo8oq {7Lf]Rp$ DU2ٻ3FDU;]퍞{4ͮNR拉dZ,L5)qa5!Y+Mt ehījKBrVxtJn=,?krܚX"Y~0վZK5eΈqk.}.vY"eN` 'tN~CI%-pDystm.'O3Z}I?;^2?(&VKk*/DH{JӍގ3p"ʌN@c[&׶w2lϧب{/lޣk_^_~꣛seb18MH3\~lnETƊE"ݬ p [8B-gg2qBMK3Yi]ojv3耢jFSA*GMrl[W+cnt ؛ܼqp<'V2LenpSZ$é(2ܔ]puu gKNY1I6OԅAנKDU+XYi8i{6_J&cۙG+jfOmР8td(;zr5!yE䫓V-oD˳Sy1ZQ)Xc.`p2Vvoo7\[07|psH~nMN3]:Yϫt7qQmYZt^58ɒ:ݓ!5.-E U,_GFQӠb7EFEf>Ly#fl?.IPi̲N}AnH};=e(>??]M|y|q!8pW pШ !quƺ22аXn DŽ 2@{p! 2@{f8ߟ=<*2Hjwq p_xDd[»l?Gu X"/nIX̢q]y.e8`A Ey.<\Ḗ yN57!JeҸFX Dh=d8Ch=d837ù5w^7j G3+É57C}ZۇX؜ >}xd)X obkpY4 sr.re3p@r-.|p\KX̼ /f>i  2@{pp((Zg((+2EQEQT{E((jff'w_lfԻm.6_%m]ogij}NRxMg\=ޡgKwMշEQ"UsS."Z[7]%c\E\ln?񁚹]B3wn!o}Nzwcz?{ۭ[>m3(׬ 7]I?FD6gtz8(.dVlDEpjbVl\xL1YAglPohɉhK3kjm3[E3ͽ4jELۭ ,}!6w2՛hNMnMQdu* PܤEQԜ:fMs6z@j-؝o7l.>ؽk!*UxؾOb]DVJh+:%kKtuU4>c"}^e\S"|48J}PjxGڟZラ^K QsÉ([.T W[2]+ m(?P F2\:NfwaJ7k+j*)uerK2P|L8?/PJx}s#O\@_=N(:U-;~8&=eV`+x lec. m 6W ψSx.q4S?4XSN!(j-dɝs蚩ZK_Wu_8p6fɋ&W^w^ 3c mvm"z*?eq"O'rl%qIQTi䶒)?*W_`ִ g? Y+d߆IONQEͭ9NCtyZϔcp>Ȭf? ץю2p_43P~G%h`LM/wn?ЖngijE%l ~p Vq?f~^v;\ WٿW_}@1rd jxs9d|F^'erpEQG Gݧ}'(q4hWEQu"8YUY+x(S(("QEQEWd8(j `p!gf;_Uޘwno_JUu=wO}cawݙ\p>",tIV+Moqr=yZj)#Ɲ)퉶zܶrw™.ML g~hNM|{ moޚ)ގ0pGT)M?SMw j5NMRz7 ?Og[޼!a.88;2ܾ7\SKO?nRMfknN gRmh{m[g]Q8 o&&J޼57>ptO-5p^d8}gouۻđ2ܾK/'ém.{ˠ&o~/wo87_o]ފ Ŭ½UsM|Jq; Gc\pnC`}ݚ?'3YdtOe8 oZoÙ m`,&d )oޚ,mFM1=7t!\LH3\0gjN䷕!p`+pӑ 7wn8dz?/ʧjtTMꖗm8~G0˧19撙ꯇ_KJ ww3zpD4d 5 kG4~zf2H\t3Ts?z/QH8;3Qvw&Y \K`1Bh=d8Ch=d833.dnnְP7Ԫ:U0uO }77otga/DPwT6jo:~Oy/vչǵ^nK57E-P/w(FuFY%oQ gjofS[x{[&/B&cR! 'ʃ%REӳă57*Uw9}!),nVrgUkKMpF6}E0!,m oz Mp.pÉ` Ǫ(2ihAណÑjy8 ?ǵTe]K .Z~n_ۡ7aNK&Md8Qv_%#pX2@{p! О EQEQ: GQEQ^YuWD(NU33a?~=}4kO׾ 4O^w3/nӉQEG= ]MQEQgYId5qJ>L@L~N,lry%VO'W avHQEQTfe8]2Z/.Ù2ӈ%F_i*//;Tl9)3t:9Znwi GQEQKD!kpbO\NJ׳*Ѩ[.M/K6&1$pd8(Z2\Ȍ_v˅+tl!cܶ&KSZ ǫfsXR&Rp‰(ezϙpSEkV?őq$Mx 76鍒((jZ2É4?n窫kwC~}e I=KmcKUDs0<8 o& ‰Nd8(Zd8^pnqDKO, gی/_Ȉc8R oo; =솂7exl y>]J("Qj>,8E^_|d"EQEQSdMEQEZd8( GQEQ^((ګ " О~w;!=Of7 [|ۏv;s;{>k@OE;䄫3.ȳ\m-TQnpZfYÉ Fd f]wzmwͼ<;T9;3E00Jmo*\M-ݸYKa{'kٮޑo k{VYU[4)䲙ssfN{QU!Morf[uuo.p7w.$7wQӇ踦)u.> UƸtpMA$p{pTpCL^Rk3sb Nŝ$UY(ÙF?~׹6/? JWwa8.jDU!0\HS,:'Nyz!nFE22?vٴ vSprN'e?_Km5Å, ]3nqNZy(^; p4f39>ܻ&#Nu`We3CvOQNC݅qGjYNnc9NM] UuW8z;}RJyjY]q"ե@~-鈺 /32@{p!Jzx8d8ChƟ^uiݫ?iPtטn򗺗&f//q"][]SC9ݫ/#_z>#xp0;2hKL5#r EODc%p8XTpII5lrl-c֯|\k8^K r@GdIQ&B!)t0{Uǂ&Tn[8+;4$KIN҉&3%+>f7`plAXq#MyкjZj"dz|8.Q vl0.0gAbvKO]~)q8Ch=d:3YUxndBqdvĤ->dz W_GvP}G*:ewe 6/2j~/7`ip*D$ ] )AZ9&3)r *G'\2G %(؇]AeL*܌"#6dLJ-a?r((Zg@(l4IC2z(ZNo#+Y $yB>Mr\A/#JM1H1WDnŏnMFN`yk{%r$U!I:1ddk#++\A5S`&bkD[A.Qߏ =kcgRgƏJ-?u?`Ch=d8.Ý/F~;I\]p~n{{KO^_%_^q:Y;I}NDUC3֫ ˾(iN^M:N8?%'.?9g+Jp 3vr)3Ϛ8TKY+|9se坚] F+5i'dCfCYL+/M O$K3DF4O z4#֙v>J>.wr՚mO.L[RzX  ;~VpT?~?ո?'v&x0åiS J_Y}-xSNXO1|(˘.']cvOK_xwFӗCΨ-¬IjFmO:mjQC5Ýxé0яG`~-th\(zRf0aUXG5@M* FNorx,TpY@<yA,S\u2ʎ 0\^+iHR (Cef+VۨWi`ajwM8kdiD@h>a`zc;ge8?l3 Qi.H((Zg((+2EQEQT{E((jff'fM8q߉i^2:MF}!x3p#V>9ӓ_(ڨ wK6{ 7ՋW5Sl LZgn/o wzV~\KQEQ-֬ 4]UdM2lIvՎ$]` Gv^E FD:A 'ƿՅ9PHs{DyáG(3#eϻt1e` Rynf d|oMj~NW_8q8.%REӳd+\( 9d,XzŒvu3*2\pEQy12\B(=4(]Zjk,Ň]ӳ.z\)(ٚF>;yTNV}pvE(Kc:es ?b\~W<|'c}"7'ފ7q)(pT-BQEMW7~T QEQSd8( GQEQ^ d+((jE((jpEQEQ((Nuv}j7?\7rDM_N((jUwIV(#Ziz,\f5^Mo _t#QEQT35+e8ƣtjgOylD]&|x,DU2zwiFDUˑ<5<*nt_[ |{DR>VEQEQע5% plcx{ޙT1+;M|ar뉗?ndɉc,"u͵ϻ_8p\K1NϒyS)(lj A':3x̓7*cEE"ݬ o&/_ ˩wҗxOƸyEQE;>Z~&Sd)ˏm8\} g8uUd8((juåsw-5XZjKf$V] [8`L+^ѵZEQE=xpD4?~3poMN3]:ي}^-姻?ݨ6\Zq:/HBt3_YP $^J8(Z[Ud8((jeE((jpEQEQ(("QEQEW " 2@{p!Lc ,HIENDB`././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/quickstart/index.rst0000644000175100001770000000015400000000000021346 0ustar00runnerdocker00000000000000Getting Started =============== .. toctree:: :maxdepth: 2 overview install build cythonize ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/quickstart/install.rst0000644000175100001770000000617400000000000021715 0ustar00runnerdocker00000000000000.. _install: Installing Cython ================= Many scientific Python distributions, such as Anaconda [Anaconda]_, Enthought Canopy [Canopy]_, and Sage [Sage]_, bundle Cython and no setup is needed. Note however that if your distribution ships a version of Cython which is too old you can still use the instructions below to update Cython. Unlike most Python software, Cython requires a C compiler to be present on the system. The details of getting a C compiler varies according to the system used: - **Linux** The GNU C Compiler (gcc) is usually present, or easily available through the package system. On Ubuntu or Debian, for instance, it is part of the ``build-essential`` package. Next to a C compiler, Cython requires the Python header files. On Ubuntu or Debian, the command ``sudo apt-get install build-essential python3-dev`` will fetch everything you need. - **Mac OS X** To retrieve gcc, one option is to install Apple's XCode, which can be retrieved from the Mac OS X's install DVDs or from https://developer.apple.com/. - **Windows** The CPython project recommends building extension modules (including Cython modules) with the same compiler that Python was built with. This is usually a specific version of Microsoft Visual C/C++ (MSVC) - see https://wiki.python.org/moin/WindowsCompilers. MSVC is the only compiler that Cython is currently tested with on Windows. If you're having difficulty making setuptools detect MSVC then `PyMSVC `_ aims to solve this. A possible alternative is the open source MinGW (a Windows distribution of gcc). See the appendix for instructions for setting up MinGW manually. Enthought Canopy and Python(x,y) bundle MinGW, but some of the configuration steps in the appendix might still be necessary. .. dagss tried other forms of ReST lists and they didn't look nice .. with rst2latex. The simplest way of installing Cython is by using ``pip``:: pip install Cython On platforms that are covered by one of the binary wheel packages provided on PyPI, this will install an accelerated wheel which contains some Cython compiled modules. Other platforms will use pure Python wheels that install quickly but run somewhat slower, which is still well adapted for one-time builds e.g. in CI build servers. For installations on systems where Cython is executed a lot, it is worth checking that the installation uses a binary module, or otherwise to build a binary wheel locally. The newest Cython release can always be downloaded from https://cython.org/. Unpack the tarball or zip file, enter the directory, and then run:: pip install . For one-time installations from a Cython source checkout, it is substantially faster than a full binary build to just install the uncompiled (slower) version of Cython with something like :: pip install . --install-option="--no-cython-compile" or NO_CYTHON_COMPILE=true pip install . .. [Anaconda] https://docs.anaconda.com/anaconda/ .. [Canopy] https://www.enthought.com/product/canopy/ .. [Sage] W. Stein et al., Sage Mathematics Software, https://www.sagemath.org/ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/quickstart/jupyter.png0000644000175100001770000016424600000000000021732 0ustar00runnerdocker00000000000000PNG  IHDRsBITO pHYs+IIDATxXÇ5ѨI431Q^1({E@Eإwq翹'}||)P!B^or!B"BB!hHQ“Ӈ!d(?baB8i(W dlJNNW~Jr$ ZdMX!,ǑNNz?kḿy0^CF36?HN2NI.]2SBy$kf=m\3MN6v&9BUp-ŔX-[&3֭ۊ lYlzsB1 [8pѹ-f?yO]pZ UFm=zQ"К5kƌ{Iq1%I13F.224%+3t D?GZE͆A!!9Ek,;yol>zS _[y[šk] R^L)>~ÆƝ8~ fWlK%:~ cJqNuGNOZ=#n>}o߾6lP4Sbl!B^mh9s׵ۯԙ5m6jcՑ+К*C*[㌿y5Ĥaa2tv}ҸR2}CbWvǿEF Gװ!%%%\1>bŊΝ;_^i-2"!dq4rJHJ4߳ь# gk0óݎn2r} C8ص5;+{-EQR^/_X:fOq%^ڞ8XIO 6 bW:︢1;111yݺu;vܴiqqq iHLLd{#WrJJRrJBR[=C;zQE{PyJC~ZarVzHɓǏivܔs3/_;vѣGqݻhB3k֬`m͚5H_D!WN4i"qu֭e˖;5jК;vׯYf[RTsQ.]0a磢={d$ȑcٲe|޽{ӗr͚5K5mڴhѢ71ggg5eb{:sNXyjWh%G,>qJV2T~_/')f*OJ\z㵘J8,ڋ>CIg}ģ/>J#? L4o# DGG9r=qڄ>|}cƌBsȑ:,\pƌm۶2dD]t}Hp.QM˗cĉ]vE4df֭„I>|ժUΝ;'Idfݺu;wfI]pA٨Qe>D! mۜӿ9ѳC?@]'em2jSTr)?`E~+S8( ʣJp%1T> x*Ձ4g|~_IJ0 hٲݻw'Zjuc;֮]I&ɐ'O⋈ܩS'ÇBDDDt11Z+/!2ԦM4W^ Z~=K\\`k׮پ~:vgBESNwdFϞ=w>D!ZR$YM4~Խ'7iw]lMF:b]em_в.m?uCy4[ W"*C˕+! /p%cLIW͛}oѢ!9?tQ(!(Hs ϟW|D /_i.\!+W# 9;$777،xL[`!f~f whuA,r"CB,Kf[s*ټMgh8u_{j&iFm2b}em 2R,,ϲ#Wn)lǃʽ8wMuͺ>vڙCgΜ6# ]nA̮]Ɗ899:$dH| >Ծ}{Ç#k||]#|1㏘C[F" ȟ?ݺu b; J* CiǏ{Qty)S}ժU`S!dԱanpffݎZk 1zcQ뫎X[eC\+J]6Tr}2ȥư5O)*=+tQ:)"tZ5j:t\=sΦvڅ ҥTn;· 0? j/>4qDrYXQ?H Lr`iTC iӦXOa]PWPZ _ԈF3g)@ΐQFYd!(7|B!4護裏"##BaÆ!!mjHC8#| SL#u{ʕ)RH~bŊ!Y!dq>ѳ =޽-5n>fs-56ν-Gm8b/C2dMjpJho uTU.iPHHH͚51>|„ #GD`@@.گ_ÿ[ޘz}HeV!hK ;de…؎O})={YxsJ;?$_J(5k\^zj?^9kժرc_OXB6rquR!2aBܹ#koo#|IX,QD>Z}F>ŇhW ʕ+ !/Ĥ?=L;~O̐F`Bwm ,db/oўkFV7oF; 9{>?[nUGHZ|nݺ=S+W.K|q޼yꌡ`˗Me[%i~ϵ֛[,9vK {-:0L<<]T^= YJ? d7믑+@T'+hBRxqTqqh5jĉh1c>Yn ߂~g:uBZT=z@d*CRJrN7' W^*Ub@z֍B̰gL=XnGq[Snk9id%y;6_ܸcF)ÔʳJٝB[+͕FSeR,2?TBJmE!>ԱcGxAkY˄M5?$d̙P{{{AT!-[tttTzի=/Bk꣨~CN!3SL8!p J [[[|$ *P:B}0O -1Cu^*VXddd@@@ҥ2m4;;;Ç-pSy~Mqŵ~x͛0|/lꜸv͟?ذa;{-_-ZҥK!Htu3}t Ȅ#~uڶ ם-n=q7'nJ6Ry0\ yrM{dw+m[ 5RnSnVŨoaďx:Ls΅?^֣7[ϣGw.|Ho@.Y!oaJIMuEq&-:⭌b'഑aCjgס6l5koA!qpDž-[vs@ۆԳ&+CS @NXNNN_1O1v[FڶmA,U0zhK+W-ѯ3gή] @, F.\h܇^*C&mb,_y-!8EڮZj@ h(CֈXP!uNlllp*qaQ]ww9Ds!M7GuVBH;_wʁS>jc_GQ bg;;4ܕ'zgL2Ç@Ozn=曔q_':fOPvLwE;vQdZi"k?+(?ZBZh!־P\^"/}Ahhhf*TPF ~?M,X JB^"I))]I]}r_X:ZRyZ k~=I^RWNM}9 E!fo%x#`bcc!C;wvqqQ2Ud5)_~}Ȑ!-2ӧ͛7ٳחuBɢBG(]Re(Pu햊QWܪ<;vRnT#E6!ľ}ֺu[sſoJVkNXӺ!WҊ([(~U6TnQ+7*RBk(__R4={ԩSm@ B!$D!Z}B!!B!6Ї!BB!>D"B}>D!}B!!!ל#GC!B!!BB}B}d'bbb>|E"BC...GaѢECf_vu޽q3n/^mڵ2`ʔ)wԼ;vlڴi2ѣGF}:'Y+VٳZhh v.]Fb(֩͛76ꃻe/Kp [lYpsÆ jɓ&L [E̚F'^~]2cƌgϾ'V!'''9?~[WHHv" К?~]"F#G mر hXz5Ưڢ:>ϟ;wVƐ+CAf:ӧO0$GGGЇ,˗1CCCѭl۶ JXXX!͛7<|в\rbooMPŦC rƍEC'OΌC> W$~~~W^I`h{d ܐ,C!QT#5Y S/^D1aPDUpqqAm^d jI ͪYUVmڴI`No9;;8qI;cycY,Q5QpmB#(@1t(DƱX/uMA&O:e(!d .v\=CGy<{ 1l.>Ņ*b6@3p,vvv..<x/Ňkז/_{ndU Cxyy n GSVOC $h7n-eܹgF0ԯ!hٜ9s60=Y ׍@'saNU./?~^}样0!Ft0!B$eGŮaEZcqC%L > x)>,B 'ڇvB@uP8sbBDoݻwÆ؞?uF mL61,>ESٶm>N4!p~d(V!5k/*̛,=a2}ac&eHr 93ij2^p0p***Z+!%0<НBB&pޡ,PtHU _5C>D hAaEMF31k3C=RnK}h;ze.nVʳ`M:UWz*!5!L>][IC1B8(}K!Ш^.]Cd9[b@qFq8h!؆㋡:>$ Nphh6b\כ|=$$jEl@5 }7V!+WT`2G<@և?^,[o|8L^BlL~lʘ@-~)>v%5Ꙝʒ9[b@@ɂ!âY͇\.4 !j9 ? _r EѝGd(V 6 {'N@p',='e*C!Wؗmg7nTWl v!͛.P!ފ>tiuk1r%YӇ<(N7jN/:Ftr~.Ng]@ʏ&P6gC>Ad6@AvvvF&:Z>ʶ p}:Nޏ Gz… aG}2#W/ˇpqV06cײȜ*1 u1!Ō5}HZ{]1yӛC+5&0ZON\4KO0~D /ыm۶M'OD RY6@tsd2d[2ۇ _f.UCW$kzׯϜ9SE >dd"G9CIT/׮][tJ +'N:gMB&1a\GDD6]BQ\8ƒpYۆrG+,='e6ⱀ8* bm ħW^}9q|]& ފR|x+8YEw„ 8RG6! 8׸"US!ӧB\Cb; t d6@a60|KkUo 7m\ ӧOW?+^?9+݂xLX܆3ŇZo\ 8Le( ^!ɜWh;΁xAa9[bfK>!4!=jk9壛-ZQ:;;I!ۋzs|(NBDe6@~s4Vlyh(zCt8Emx!%`Lݾ};.^˲iWǸ"^,}tS).ydu \d!qQl4+Vn$nnnSNUsenazyyS|E>` CŒ%K8::7Hi5aK!d{G96G+CQZ"ȼe`baCqIè F0;wz}%s!CgϞCvvvV>dVaCC"dΜ93mڴI&9;;gC$>t ߙC{Y9^^}Bt" !Bч!BB!>D"B}>D!}B! WB! >͝B!ȏB!nЇ!B"BB!Ї!BC/h9ԽXa4zJ%C6e|c 5{.6,5'3!Sx%??~N ^7+t,VDz,/fN,C,+"IZ+CiO'CO1r3ZXWqчCW0x2gчC!}>Pbb"/}>Dz-|͛ަYʇMVj:իgz7#)7k֬\ru B5jdQJQ< ߽{0o`!߿e !}(M(m!b5o޼Zj4TXf͚˗:t+2]rEիWNT> cƌiذ!Kt1888)7n_~w"[i0a!H_uE]\\,aO vC07*T(g{nܸ1h 4"$Fԭ[sΡwvvFЇC!s=W6UJ'''H:vq>}xzz }΢E27 Ϝ9sim ҇թSG -@{T5k֠x#?uŋ-[O۱c֧ɨF.;UVnR q2DЮ]0`c/:t0ELL(2xեKYDFv2\ㅰw^aBݻ7jH&}( PTTT շ٠Ξ= ]vZ!VR%F^tkM/d^-[L@O8fK1wwj֬a~Joccs…۷o_t5Twe"|6mZ|+Chm88N؏ɓK.Pjd6yGGǺua}{l׮]G qZH :L!)CS(RJ|tE k׮EUdn><8l0 4L2}`GWNʸ5mڴ +T;=|0 6A>LX b eV!h13$]888]!q12j(߻wիWÍC7feP^=\&6^e-s878s">mҤEjݻk@B!nnnL߬] A\=~h*K, f͚uƍtT5j}+B.]ԪU+]hh,ƌzU4hA_:|HKLT"@t}eo>#LÇe)պK7tЌŋ}={ʕ>dMBFʕ+vɓ'7!SH( H}G'ѣG[ևmܸ1ƀ*U`PTƉeL!t0gh>{,*<!r!:\z€*}zذasܹO>f>*Ae}'Ҁڎk{!> tAk}왥J꣣6lnyyyC0Bëu j,Hoڇ"PΝ;vALHΝ;Ə=8||߅#Jr> #'8Xm v*S7o+݂벧BS2e9Jǧfնʕ+n޼i"__[nZ>ds'W)R\ u2Ç0to<(ENk EUZtիW'ۧOYYć0<I5iF!CP ׮]Ø 9܄ !6.]a `:Cj%ҕ]4F-,?g9r$.?ξ}o#\?q*%}?|rjUY`7ewW&XPP $[:9]\a[N ϟ|HL'CdDo^m]9Ni@cCEYjUt}߾}D6mJY0}($$=xLҲ>F>n֠AKC9;w6xٳдt*'u!n*T0H:|Æe6oa...k׮~~~‡<==j,<HI%+C!11pl ;)*}||t 8nnnp/L6tZxyL8ԩS}H] 5 9A{DCDLCF&-tVV@Z,o2kwhkF|hݺu͙xWDTHV{[C:u>l,%|֭[ф @<$ZGu}-_lYʌ):D/_VtDEE߿iYJd\C'OdCgL8hFA!0!fX P:$B={&|h˖-8^Je}JInݺekk^Sq_؂]%vC.XN.:1ܻwѣG1bIJeBC Q] 2r'堞A1C ň)1#i `q2n8uKC&]{?{)>+fΜyΝ+W`lHGCQz꯮.靱P+%q7>ᅨ0Yʇg?~*K@FnB |z5?\kreL]ONݯfe).N ׯGUyiܽ{2:1l?F.\0݇ OժUɥB z>:$eHz~:jHA>W+I T {0R^,9 D<8j?g@7n܀M8k׮nիW^>\Z;v ƃ PD믿06k uC12|nڇ 2c x('FifvvvM6io-iQV-{{{K)>>A]yE+6V%[hz7FY6BO3,ܹFO->YhV HÌ >QaE_=q%dQ^;2fAlTPP'''s3ܨQA'6i GdɒN:5lCٳ1HU>g\tС;vOz!'D_޽{{j"24x`.4 1}ESru}(+׶,{0_Uw^1+刈\fe0e!}>Dz%}(LчC!чC!}>D"!}>DчC>Dчߘ>DAJ}$&&Ƃ;@jd^WZ[|225Dǧ[8|~S'C-6X܏eY_ 63vgXƇ"""P-R}eb]Ҽ[VoV(yX٬{$!B!!B}B!>D!B"Bym| !BHvW^q͛7r<#B~:d& Ґ#B!$s5)CbZn߾#B!$ C0;w&B5CBL K!Qː Ր#B!$# ܾ}[Ȑ B!䐼M w^DB!zrHݻw ݿ?G!BHvG=9$o  ˑL!QO  2!B^{J!BoeB>|H"BkC !BHvG}L>V&dѣG[9e]\\f!}(8;;Oаdɒ,C2F"BYRJݕ+W.Kч!ЇCEDD\y'OXg!ЇCB!чԁ{ Os]Ll&УGDB (?o2Bǎsߪt |w(Ν;Ciio4h 9w:_D #ڱc񧻻HdϞ=Z~7o^uŋ!41)nZTDaÆ._ޒS ">(!'N+ 0$$lٲ"/{4L? `!$11ԩS۷7ׇLOS12AçM3gN^P)!B>dcc_ɏ|}}E`ӦṀk׮v/1P&O,V%K˗/o>ԢE x!uˏ\]]WBC$ ЦMg̘!?pٳzjժ'%%єǸbccܹs6l(|4!\TlY1& v횾"%B"Yȇݫ;x{{{ɓGwA|о}{j̘1c~'8!4ˇdH+իW/}EJ!>D^1666ٳgqԩ_KڴigۇLO,z իn+VL|ZR%!ЇC bcc=<}>dVfR7nUqqq&MЇ!>D>P qE؀<}t#ځ#cN:U'''˕:Yi*f3Z?m6!BчSNɏVZ%Ksر2|ٲe^?dV2fhw<ȕrR ={>D!!P!_7tm!C/^\F 彪9sBD"+2o=p@SN!41CC.X \Ë-*շCBes:t|^ԯڵbt;)RDl.\8!!t2+MCS ?;wnCW_Ӈ!>Dz]|HHCu?9sXQ?ԫvhKrn޼ٷo_2aŜLOHƌܹs*U2ӧO 3}BC$;} N:366V7ZTTԆ ,YrIח-[vus441߸qcŊ8dߦMPY!>D"B}>D!}B!!!BC!B!ЇCBч!BB!>D"B}>D!}B!!!BC!B!Ї!BCB!!B!!B}B!>D!B"BB!ЇHVg޽s:N"Erhpqq1%Dz֭[Iٳg .ECAo>CB !(M6СCz ,XLGpOOOq_I>0SNڵ+P@%+SRRƌ_A%K.\O9tv(;qիWGf[Nk׮Y܇7o{!8|d&$$$W\Nq:w8F{/_>&&&6죏>֬YxBL! ̝;ߏ1`GINN0a§~ 6@n`Qpj*.˖-~͛7w^X1}(** i6n>>>NNN@xÆ {-DGGrݍ!άYUȓ<^GG>`HE_~ȿ!B"Ckq?C(!#!( @ctҐDҼ_ZrPOe܇+"㱽nݺ… '$$jժm???yI&𰰰7xnd|!ЇHP=*T;vq2,޽c^[n)RI0ߪU>(gΜ6V}ِ^&66`bNI& 0OqLx!@rb |s1R>BC$S|k׮ϟ~)M2,xgTTh֬qTPPPrrp +@boK!CNNNˇB}Xއʗ//cbbϿrJ>d$E|Hu\ru3>}ZF9!̙3ϓ'OjPRĊl- \paeٳ8ɓ'wp|9/B~ٮ]CB"!~~~{.X`DDq2?>r̀vo}#F!ŊƓ'OjԨC:uB``` *bJJJẈ8 .ܸqI=SLzkƌZͧ>}z=.n҇!>DCgÆ +===ExŊ6m0~֭˗ϗ/_7n 1Rcǎ7ߔϱ:u 3k֬`xE7f͚I&#K\BBBOC 2dȇ~oWVM.B}XՇy7WˁB}>:~ԩ|mڴA!>Dz[nD"B}>D! B!!B!!B}B!>D!B"BB!Ї!BCB!!B!!B}B!>D!B"BB!Ї!BCB!!B!!B}B!>D!B"BB!Ї!BCB!!x7NѢEet.../`sw7m4Xǎ ^!VI^B"!P!gg ,Y[Ə>D}ЇC*UJd\r٩eCЇȫCW^ɓxVΉчCЇH!Ն}>D}X҇zνPB ۷oiCm&dcc駟ΝL2FI||3ʖ-'OO>o߾Ϟ=[lL I\egg>߽u떑ɓ'K~ 6lXpp}h2Gr-avQ{gUV Ǜ,Sٳb u)))O[sKC봆:Xb8%}5?p`An U:.Jbd:뭴zd#{ZBegZpoC:ur2sLXV ԻH/hE-C&$#0}WZ_Tz}̙3|~7f8pnի-";vLlR8T~5Mo04ԧu۶m+W]t1ŇL 6m !NNNǥ~oԨu2z}/f }>}ܹso K({{{-D ZʇLIΕ*UʑrhA[*X̙3w}'﹈={t@ ʔ)ӧ G,V<_qqq2qGGG?00愲eğ斆֨QCnC֭[?͓'O\![a/鈯C֭{y@}>=}hȑ"}'Ѝ"0$$lٲ"/4Ba|||Pi/_[oɋxի2r"E~9ZćLI|֭2/􌈈|z}诿ɓ'ɑy{>dkk$Δ[ܹ (X+[P 4:߬Y3ҥKM!SjZ, PtH 5lUɓ'-D"aaaˤ|82o.XBesjڴvjS,DkI9`7o/^3C$.o끁j>D. Rmɒ%2#G^ըQCӦM'˗/N``X}Eٳ{Y>~!:4ܚТE x!uˏ\]]-x\j(YZGvvvˤٹs'ZlE}(z,Z*ϋI,ç:3G.\~WuȠ8ȑuZշudMŤItн,R 11i%JjHyKqo04ԧuʔ)Y5 ʖ-+G$wՂǥ<󋏚5kLQ чy{{ɓGwcĕ)Ouw^^kQkDΝ`ˌ$;q"Q/>{& hb*|̙3ZGdztQ\zuzY\J&DEEɐ:h%:/_>܂ǥP|yQҥӑtL%!+CŋGEkcc#H-zi) y 0`V/_nMȁ?^̝;W+{Z>>4#zv*92|ʕ+ZZd˯L>!_~siYaZćuW^ɕm*UqٳZ;5vd:Jˇuk8!!P| ˓' ȓ4azãwZKc,b!;c6ӸqC>px3du?t Aj\1t1!ݛ#ҡճ#jTa]re:4}ȬlJJJ7nT\\I&<.l޼YӒ%KWtt:?Et钼UZ@tc }> P9F.%!! Ӱ/Ԛȧ .C?pC>zNPppƾЍȯ2|Æ ΝS#3C:z_~z4qD]~}J#}|DZDzm6<.@ՑG=zH_&͍ΏVHn}AltҸSl7) uSGVK}G1Z2~!dcj0)RDޡPgo2/GGauիee"rɳz뭷3nUTyxx~A1G-_ܐ,YR|H=1icc#ԣC;{W+ǥ7|S{TTTZGwN_&͍hZwb}(_ވ{/odRxYʇI`6@?tPYV_P jmt?o׆ 0PD@+o駟}7o^ :h^(|嫯:;?..\Xo_|YSs3iV|>wiMBvAw߹sgTz+Q?9s_f؃.zܹK.z8y۽{w OԝYʕ+ժU*.1Ji]ԯ__kRp˖-i>_‘O6 kݧO>UOYWҰ)H j&GjRǞ={{ 4_ȤY 1nc }>*nݐ vCs_۾}… Ns%,, {2ex =5 8 vx&ӧOy+%%ڵk6lAN:^̙3˖-8n:#|>xرYf9::߿g7o.i4(%KHҰ887nXgBi&#qQ35u_ L#>!>D3Ξ=$e+UH&a}EiҡCCoO !Q(Çe8j\~ ɲ>+&B";wo'MqƉ'ڳg *+А!C5k&e>S)!ЇIٳgz%_|Z?@iV@݃B"$PahѢp%JԮ]{?fd}jܸo]tVZرeHB!Ї!BCB!!B!!B}B!>D!B"BB!Ї!BCB!!B!!B}B!>D!B"Bk;;;[6'N(P@7|ѢE׮]Fbbb9,Kق9$,<,OBчC?֒y)[C[>ٳgTT *$R@?>|C_4t{ɃݻW+f!P! {eʔiԨѩSlقuOIIO[lyĉ۷'NDӧO1d`>AwuuEb@%9rٳ*ThݺV%KofΜgΜ9vX޼y*W\ަlDUB}N>]lVZyk׮v"Ev@ J۶mG]bh/:L__ߜ9sN6 o5Ĕ4!ЇݻwŸ(tqqH(Wb` s/^ü6l)Ȳeʕ+y֭ şP5k`FNv؁ŋc$61eCG$XBC搔 %o1bӧp,C|“ditEˇ/]?~^;wdl#[[[<yh0axoǏ|[hBCʇ̙SR%?ƿO*Ŷw4iҤ &ҭ[7lԩSgʔ)&lD˗/׫}WWZu…b{رr6Koi3Er_-!C&YzuΜ9 /OgϞ?7lؠ[h0###Q iۼy&inBe+rrrRp 1~7+VĐ|߿d]vZ6iD7={|ᇨ[o*):"ƍz}HÇ5Z>d4F%KhC\믿_ґ.>|C_4tWɒ%K`e>-4B!lC{ťp)))[n-TP\\`>L!>|x}hڵ;BDϟUBS6tD!Cċ-*Kk׮Z>d$OΝ;7ZsmڴAn1իy@7ECo߾iӦ@q/4!Ї^a2dJҥ4i? i<3g۷â0$7j(::C&@7`C?ӄ 0ܚC111ŊԩӹsfϞ+W#G| QF|PiDEEtr"UL94bŊÇoڴxÆ ݹsM IozƃCXt˗g̘8/^4J2WWW6+B}>P"& Ń'p#:tP…\zҐ?~X͙3G6Ň͂z˗DK,֭(fVz(#>d4U,mv޼yVC/"E q1 5sRJm{m۶M}h0qPEΝ&֡iVؘBcggWV,KEZ>-O!>D"b=l&Q~)S۷p;w#}Xs,XW^r%kk׮.o޼eʔY`A-!!B}B!>D!B"BB!Ї!BCB!!B!!B}B!>D!B"BB!Ї!BCB!!B!!B}B!>D!B"BB!Ї^y"""B!(1\҇38ϟ?%B0PbegBq0\҇CB}>D"BC!!Bч!}>D!ЇC!B!>DX""ӌ"""<<<===###00P~Qo4nXR#99iӦePXXѣ͓ROKK͛7l۴i#C2^zرC ={1BR9_~dٳg]xrww7 V֏L/aÆ'衪COROX,urܡ_ t 7W]?ydeɓժUcz/+̻>~z Z*..Ɖpww L___NgooW2L{n=Wtz! n[ꡡC]?롰Mk{.'|iXY?2}``w=_&$L㏛8~!WVe2-=$7C|pXԿWo?CǎVFL>5R>gN_QzH.=}?_סC2{h޼yP-̔5jTbb_`nnnFN֭(oÌ;V6Y|O>;wСL5`qXV3Wgj mL둒#^V~:22R2)=[Cݺu޽{۵ksk׮~2rӦM{;u$Gݻw!aVnѣ3gΔqW2Mv1112ܠAo߾VzHYf7oڴjm۶յDF&p[ziqֲehїw^Gڵk6l*zW^III Yu 0gg[ӧ~*{mq榫E] Ǯw޻v풨c^pp Sf:++SF:&$$D6_1t<]VQQ\ɓfb^-Zw_a5eq[|زdqIfXPP / Jc)=d3pzH}a!)e`߾}2Nx;;;;_zU?W~UVVnQիWϗay-fQA}cy2+k!Fvx5EoZ9!˦uǭ}^!44Tn``e`ٲerh2^^^ЪUի.ԕٽPϗYբ.;2eTTD֘zƏ8­行 :_|!/dSN)߿_j֭A nWĉVLW...2CÆ 2d mM>lZwzپK|wMLLx'LJYM:W^ַ{í5yo^ĉ2 I|TR&55zd{;K?w%fbKZ)oYPz#%њk/׭[8­!S^222ǎٛ6m*QAPf]ؼyimذA^ʜeJ:ܹs^6;nl_W/͛?SorwM}YM4o߾!ui=Z3/}MqCRg5276әhL%eL?k h9YF,+=[zzXMi|ς27y,. G-ifC6>zv,2>))_Z=iӦ3g*[QQQ!e)))r1//ϴ~yY){vڕ^`ǿi-Z;eQ=<<Գf=ӰaC"/>f^J"[k_}U͚5(]^=7$uZ)sc3ʴBCC#Og>|Fr1,,zHa5-> Po$Z3\p?޵wyG!q=C?Ѳcݲeˊ+5j4~x+߮>@^ݢ/^~y%-+C2y)G;y裏*/;o/}D%`9n+G>-.7eʔ)2W`y{믿\v<ϟ/ww%%%AE JKK#Nk֬h4>CR6RsuppغuVi"[kj1}gϞ-L׳Dke!WJ$wI&2|U+ +=dqXZ)+lgA<@DkRHSv.wS<3Ev)Avo׿";u6hV^U[KN P^K@ٳ+,o~366VJHU^zL :-q6nX~= `iq3͓ʻCrx%Wq7ȫm倗-χɰaĉ=zrJ *p[ZL#//O׹!uZ)sc3,CkJ~ygyF@y3J^-VŇՌ#[Y`ˆz#%z&eU+~^"St=yJCeNԵk{gm.^X=0az= zwiӦeffW>I*/a-ϽիO>]^oڴ^z֭c#g{YCC)))nnn#G>~'xյYf .#z> z!z!z!z!z!z\xȑ#9P1.**4ȁRPU&ˆur!!z!!z!!z!!z0h͟D_˜m{N=7l0xz4iv%Jԟ顸UGM|Xuz/7q~{;w_ _1ܹCUďg dzxO~2 ?W^>fSTlF3ɻo^=saaa#G>}z!=Da|Lnju´m.;0~S!SI*LvZzh ,PgԩHy+ׯ_ڵԩӧO윜^^i*RdPzhÇYgBBrcƌtO?}~ 5z꡶=H\zmQ䁞_r{h'/)6!$=t1izIJ=Zk\ի׎;"2gϞ#FPf{y/C2ٳ% 9s_&mOݧO;w}IKmeg)[DN!yz}͚5-[ @CwC>>>...#G4<=t/=D@C=D@C=D@C=D@C=D@C=D@C=D@C=D@C=D@Q$!!ܝ=4l0 aeNf 9;8}BfL@P2_ߨQ}ӧ Y38SxFf3w򜙺}tkyr؉=DCQgf\ѹQ=?q}w6mvDڒӿ:Lsy`be-#wexK—/U/\7R9fm22~JJR&3;__cOef.?GV某ЩS'777WW׮]VFhкAwͲُ=Dݕ=tQɋ>S{fm)%a&ȏ27W a)WVRwv] dNr$];T%J~HzHl8X2 ?Q\\5LiWJ͵ER=<-\(%e~|#@Cwe)O6 |yP!'?)8 n:'cl,P%=cgܔ.2"oE$R:9}iYv+yy'z+{}D{o12l|^顕W>o"EP;2S*C:^yG|h,.`0XݡK E0==twٹ-[r/+=R$ڸԟfVn [;̴[jѢ_VVVIIlC[h? Ub,q q|CCk%2Էd~,Q=_hأ +=2G|[Cr12g/A[nC=_&F X '&Ͳur衻2NgTm[RVR>?;`S^[Iqz,qmwkzH>vsEì#((Hiooo=T#B_ɠv=C}MYGw"1^痷J2FХ߷aTz!||6Xj琂eP|F|OM}{^ߪU+www//JK?Ɔ5ꇾ=T5?F!z!!z!!zUv}*L=[C돮ossbm~q7R111O>!""s--?F%+}JKK2dȽCM4Yz:f+}=xͲ<i:S^{7 2UV{z̬#qτJ^RR1dĘPَ-yrgfIwz7Z4eMsva磤X,2=Ǎ:=)+VRRQm<_6eZ ~O&Oς=  t/tW'Yn\FuU?_cOL+rg+pq媐!2\֛63! A)û-ʿ)))yyyf3'Xvvhd*9F)Y#Gkʰ,c$Dv3k?iCq2RuG2ӿXYjV>]fI/sĹ7<=/=tF@<)=$ʹ؆cį'Juֆ'6KzR{HQ~wGk^5N:neDiE%K?~`0ԨQ#66l&c*|>t:]pZ.O.׾i-ٿDB%2{h2#RNeΤ挚V̙єz.驌?v)[֌Z ,PC 4ϟ61y&7WWqg@NJ>EPs{OUz(|IFQ l+6PLFLPE"]άL !܉=Tͫz(=/\=|fTYJ%g |2R ~жoY]lٲ2{H9_p dzL4h@Mܟs<_v7P|Ӿٚz/e%"#e B6C[n=q2{Hn6@NMkwܥ^+%;;;v$//_CdoFKF%6A|5#hk Hym.]<)='< WkFE)2dʵ8Awv E{ʏχ?e}Fp q%E3}llN3 f=[Csvn^=7Tj׮ _ՙTbsrkWԾ2{H}L6gǜ4u$s_/aJVVSNLlSASOm8K_|ig?~|F=!bS&3%ן7rsu֕gk!CSz^źp (WVb/ʓaƌ7rIII<@vONsm`AgβN!!z!!z;C=Tդ 27pz(!!SNnnn]vMMM"##۵kw#w؜/C=Q\\\9ؕҼys[jCΗ)ݖzH:tC z(33W+z?j988Ȕp˖-Fcq);=p'P-JJJdٲeIJѤ_, 9rezwkK$''+njT/C:yxx)M]0z@^oժWTT=#+9ev~-889=Dz=!zC\9OLL̓O>i˔;w pGPZ^ڐ5ClL ;K_U\\ܤIիW2 Z+]vJŹ8I&uޝ+BeP}-,7^OlVqOς= s Ȥ$1;_ܿ:{&d&sĦ?Go 0`Ȑy)!!SNnnn]vMMM56%%>//g,BeÇm0^21?_Y!]lgKZJ}~HzH|J%h(!N7|1FKr{Hf+M.=֭[O8Q/[n5! ڎ;x!TfUm3>4"a,.T=$?rq칢sŅwtGPP 6mC:`0Czy=^e-ng`}p=S;o䔓Zrww򊊊2g}v<]*F%[~m[̬[la<]TF3c [LJJ Pzz=Dz=!zCU"ÇCUŋ1>4ȁR=@C=@C=t;vݢEo *ʶlҡCիP=ԩS%*iӦΦ=sϱr ӧO]vZ5j4rHi&VPۺu˗/Њ+V\ٰa޽{ yt:ݡC=djڵvvvYYY1衪f%ح[76oj 1իW luIegg8|ٕ+W^|={DGG{xxۗ=tիW霜7n_kVY3|l ٕ2^vǏt]t9r䈌Ѯ۵2e6mlݺ}_ׯG2eʕ+WdKd&Zn-yE%QYCV즗,Yc,{Ç?CTG믿zݕ]Pɮ<33hߣuZ/ZH˶.wFf/Le15kֻwoY?=cpp% Q*FV~O?r]yoѣ3gܻw 塼|L/Q"'۵k'k]G:eEEErQ'O6N:oݒM PO+&_v<~~~Z|ڵ 6ͦݴiӀY9smٳGk6c!/lڴI? uW۶m-))tppCLڲn0fo lR7زr(kL"&&F4h~۷{<_[\Y=xnzsɎጌ ȎI?FɵdǏWZ+IIK/e|^^@SNUƟ={Zj7Z5̔=#i7ׯF\) ܴ{eX:x͚52rR_"۴icerԔ.MB-L/HJH _l-J^^!Y*)]sāfooUVիWOT.T欵Z}E:I4ܶ,Ԛ^=qW*!!AFJ(oY|hԕiZ[CϗlY9zRj޼ᆱ JH4x M(G=xnzss^&W^+uEk/[Nyk/mر999r L^*k/{n/Wʁv޼yVFv-N/qh?Lg(7׾}{'dyADIjjQb*pr,֭}CcC7[VN冎=nĉg\\\ddZ<[vYr=Dݡd,OZH,rlѣfF_<-[ɓ'唲۱c=jp(s{H}_biݮ)7gΖ_%TgT˵Z,PoZRRD*iӦ58z8Ԛ ˱$$$GV ~•٪Nͅw}״>=$͛?SsMOO7KФIkáGFF>c_ՖѺZӛІ ׯ/+_6`ٍj=4*}-wZlY9z֘,lru.[Q5bXX-=$P=jժ_~Q.6t4lP=+x9j-f,쳔III},sa=$֪UKڵШ+⵶l7Cr= 6xZ<[vYl=Dݡ+}c^ڤI_|QW>3(;)Y(y7衇6m ?sٳg~qnKyw߽pz_v]H[R.K^kJǔPsyl}z7-{|{{ŋ߿_:O&KOO:j_yAe-D.*ǹ2{HO"4Y2f͚-_-˹vZٳ̟?_zwUү!sܹ[nZfX^O=Dɖ-[VXѨQ۸0ZwPkz/˓c^ueZ֖J/2e܄`)ף`c=}$7l裏*&Z<ųeu6Cj-[4{#DyU$Q9J<՝!{?r,\lY{HgرrzʇT ?uttT?uZvӔ2I~kFfE^*4{y{>塗]P>Bu8Ԛ@Փ<]  )9)_;ozO8qGJ}g֗Yk3֭۠A-}2FjMoCrF]e;C͓X\9zl!Y*Y9u(ɢacZg.lcߙ?}W*?޹s8#ہΝ;*qz=txp==Kv33n Ӷx{~9_p*ٟJ]+_ 0`JL:U)xe]v:u铝9K2\eWlJ ;wȍ5R;$w{HkփjM?o޼Zj-Z(33SiԨQS?J_2aڶX?- ,x[gyu{6\sppCNNecjڴ-ÛoY~իwQ!^ߪU+I k՚^̙3GFJwoKz{VΗYt'_[n<=T/}=&!S6CH5k.[D7|||\\\Fi4y:!z^!!z!!z!!z!!z!!z!!z!!z!!z!!z!!zv]]2\t}͜m>!3A&衪C-[Ȕ~q~GseN6dLܝwsfukr~a'=DGudsEn6zGPَ-yrg۱z{hKN2S-e _Wʿ?rH]挚mMLPf"4?))+I|__@|rI+Ϗ=g6HYBBBN\]]v횚ZO A)ûm7Ne?=tW3G%z$/_OO홵T=*#k"?J \1P^YJuse|>X:i\;tP*s+!!؆cį'n0*PDDDxxxzzzFFF``Gqq2])͛7ך^zHp墬.Pُ=Dݕ= :N>r۷d.T/?8A$dO4ʚ#k‸~߲qC=T=&sSޯtdl{K9tf٭8b~g=xLN~!z%2td䳱*yV^YUCk?RO@efft:{{{^F`b2bBwz/.2tCCf綔znsŗWKh6SfnY=4l0{rozE~~~YYY%%%!Jm٢ybR~T)ĉe@Cwk PߒG|٣a*#/hˀG oMo˜m~~MrSnݺz|h6`m2l7n]G8Q=rګ{twYnIYI%ƒdo>tP?O{io% 豤qܭ!؍c>g uPDp q%E@Cw7emjeP/z)_ K*C~CSx|czvfC CM?i*7]z}Vݽ*.]o׸CP!zz!zz!zVّ#|ox<3nQ?قfe]IHHpvv}qǩK<72Ν;ozZ8J+--mȐ!N7idXa7.@SO}ps\{-S:`0LVZ !܊3ǹs<*E\\{II:fwlcC#g;.޷xɝmۚ?ד&M޽;!jVΗ5]9عCDnbe7v⧬lXIIIʟG|ٔ-Sj7??r`DʛL>Q> ,xxr/d_fNsU__@|rICϏ=e2e(˝s,ǕBȔrUO[odz z?̬$ ~\+צD`F=Cnd釮*ߺzEjϬ}2iId{Ha]'Ob {lWcdi}X-\v=$=?̙31b~LZDk=>{4ӆcJ%(e0d[z裇6,E5K!FGV=stޮy5P;ItCrC+..SEPFXKb=Cefw컟sAti8l Z3j-س@yj50z_:?zZ4ePbeʕerqő<=_^#ekM;)BHIV=W顼yf'G3K$&&C11Czta:2e {(p'P6r!S-[ȯg*1)<#QH5hC۾fvFe!|YX,S2ѠASoz7r-|CMfkV=dd/LTϗ5m0c nݺĉ!6me897Yurz?nE)߷R9ع}D{Py{]vv+8XYTgn# P=ѷZ#w^Q!6Ros2ٜs~iz+YYYNNN99O2OM>..kOg}v=*`MY$Όl_oeff֭[WQy@Ny1b~8És'||^Y(O3fM'%%ɓ!Cv? i B Z=lY C==DCC==DCw?z!CC|n_%$$tյk׮Vdddvnvez"""322=<W m|'6W8'g}9YedRVč/ __gfϏ=2ddleb# 0dϔЩS'777WW׮]^boo3@2{C 6/Swvݟ/.T?%bbQ->?$=$cd>%ƒ_Ot`4N?阈􌌌@bZPFXzC]"^FCS=TsFMӷsP%=cgIem V\Qʖ$E9k,zCCU/]jYe1J>z&"h:233W+UכN5ezCVR/yџM{H̐=4l0{r2˖-3٢E ??ـlb:A N@F{H}֌Z~V=$&O֭'N^ϗJN}ʭ[rmǎψoISǩf߷rrrQVZ{yyEEEг>;~xzCG-oo-Sfff֭[W0zUd1c-S&%%Fs@=t{C!@C=Tku^g^}^>|>|!C!C>z9nN|S ɣ5f#d*q|ᐔnqco3fgּƣ$1OSC{)?9wVY^_o2PiJO.߭(}Z>TcTQ.*TRv7ЛEӽur\G񴜻hBފY,a>de֘ )>yޫч$EY8pЫ,ȟc_POyӥRR^$$D*9!;ά_^dNܚV#.|>$y>Q2w05$Jxs*WerܕٟC| Bl>e#d*K'PEzӯGik'%|#}æ(i˿~}tg}ᾍY# V<+eyx"xŒ?eΗ!G5O=(%!!Y$E5׈޺EY^3ݭ~*K&!)6^o!t:BJ 1 N;l_e>>*/S𡷊[ܮt՘ sC!2Ϙ1iӦvvvAAA2.\P=rrLcZhQ urrZfD:u.++8.++~ۤ$00Ԕ~zyƍײeK33ɓ'K>|N5h?n6<<}ǎɊh5H}\\\6o܀>Dnii٭[ 6$&&.X@GG'$$D:""[?xu444=*_~;w=@ǏǎK q9j,1ѱOy𡍍… {O---*a`\\\m=zTӧlҥˢEurY77f͚{4]veuf̘!VAՋO>ׯ]vQFz2l0>ϟ/\I6 $+VRάY]zzzz|)idddggGY^^yɊK(sss(طo ~!DR&R***h:tɓ'|||wIII:uRҥK/]D,--w^ ŋbcbbHĊ*(( 9rdJJJDDiB"UhE{{!CP'ttt[AIAAVas)\]Xg,ڵ;z(U{ZEfNu&! VҌB׺(}.)PM<Ɔfii)#[j5}G)9PcaӦM4(o~-Ϝ9c``@6_fDyY:ẏVX_ cĉl$VTxx8 ٳg+!8!%vZIH l@lue7ndQQQ]v===;7l@QV֭/^U.y1IȢ IO۶mOu Ǐv{I/U`|/HP(nn.Ϟ=V b:ub?PKKKއĊ ;vBjҤ 5$|M6e&L =_d̊.\Px}ի.C,,\G|ilNAAX3 !>D$!Y'\StgZ|]o.;88zR6_rEf |hL*СCWW˗>}z>$Vԧ~:fSŇtuuiȧҡAǫ̊TOuuݻw IDͧ}hŊB N fFOpj)Fvvު !۶m+əG1JMM֦]:x#H/r2>Dz'}H(rVZH̙S'O>dTݻwW T [+v}H5Ё>|7l@Ne60116mȑ#ePm5k_ˤŽKQ5d- >Ԉ]EӦMC[{C4fȑ;v̞=r2>ta{ҧ^ZWWݝS~w.\XXX(VYOiaaЇLGGG /)5J8I:R͝h]-*{&Nlub>D۷HKKO܇3gv̙3nӦMAX:vѻR㏴isT\4=ٿݻwpزeK.<cccE%2>DCrCZciiIyLLLa\f޼ybEUV@޽ /ɁBlܸ܎J^ٺu+)?~<IC(a-:_g1"rrrT5гgϦNJEM/BBB89/j|}-YqHu[ i[C> I~~>m۶׿:|4|>|!C!CMpou!C>2>kڔyA#>33㊊KƣGq󅺋 _$ĝ;CeeeTrVVL ܯH:LRdd ToUBSSC7oVׅWᵅ/_|*HD;DV \TT*|5KT^Ϛ5HI+(RǧLBUk,UЫ—Je>^֭R9s!||ΝWw.JQ>4m4eEEܹsć^ņi|Csnn҅t?^Yܔ)ҋ7b>t6qvv…:խhQuQ\Nq={*!DvJ8}}G.3SY(6n~JӦ؇{ꥧꚙIUI)pуeڵ+5c ;{[f͌}}} %e|e Æ 8|a9b'L422[payy9"NZh1eʔbJ|)e8w\.]-Z$&u NNN7n)L]C}YNM弽\dPI.1Q*>>}ёswRR]\=T-ЮԔ~Çҗ}p_|%%qRRV_*M %Pv=zݻ{{{kA޽RSS;uVtvvaꎥÓkaaxb%UAvZ۷8qBGGcOKUrtttwwOIIٵkJpp0ۢćo8m,СCi|||x"Zt)YM={foo?zhZ}ٲeJZZ|2u":ԩ\朖wFuʙ3G{iksJH*rnJtugϸ}ll9KJ$'C""8eK={XYbW&]kAtt4–! O8_ISF!HLMMccc)I 2U>!!AOO6oذ+1RgΜ100MfЊ+ݻMLLgΜea|eEu!;.sGٴIzа:B\>r~kH/|97g7f `E=[a۶jRR)~~Ν'Yx"{IðB:{,˰m6>TY5 8>>>88?RŇԧO 0a,ɒ% }H+Wѣ_ȵ/((P-b>|7mڤfU힛|ԩS/moy|Շ(ի\^:E |hŊ|(+K^K~l"# St>]"CbbΟWv=SЕ+WT!;t|rӧC2xojjJ'E }H+VCVUәd[|H_֋2+&&=<d6l011wJMM֦3$&?K;vP]C}$Օޝ;r۱C:glijߞ^O.بseD:E^>$V+r255路ؖ.{tлᄏpB~R jjj{c}պlN}5jp.Sz=<5_16y䉵qӗ/_~Qavcbbp&CŽ{ȑ1gn͜) -}NNm<ޞ9t{Gu!ZQ$a ҇6njC+W4447o@Rr͛[ZZΜ93))Ąٌ5֭[I&Sr*O䰧۴i#tz}H!t9ܜ]!%mrڵڮ[N|"5@=Yòh"777۶m !|1PzzԩS+**pD|>jC>|>|ࠫfDB鏪~7t;wN[[b=U'22… rj]u=Ka[e{ra*4-\9 T|b mg&]:]6n(Ce>O:dI'e0`~=233+yY77f͚_)Y-LB_dJڵ+WŌ3X9zsuuQX+2R[9884mڔ-!!A>?LҥˢEdV/S}SU2eԩ[7o^Ϟ=Rq{kG***֬YC W S5foO-dwaPc9O1'mCѧO#h726O8pUF]k׮׏ZfРA;vh׮&m!snbb{Glo`5|xC9J&{ƳgG}e˖QbZZCR?O?ɔC窣{JJʮ]/; ғJjii9|pδw^ ŋC%Si :ꟘHLisLL UCѣGiݻ.V+2W55P*3ʪ3:8ݖ.]z%* ~(ymleՍ MMML/U[=")AX+xXSL“Kl h,9r$GDDyFІ:•o'ttt?4bըKA玵WZE|HjiȜXQb{S%aZv3BJ }HlPc("6Q3vmbbBg0s-[0:vˡ/ a/7l`jjw@,:N-,,g'NȾC%9s,2oQQQJy^޷oV~~>-ӷFGV>X/u+]]]e)occC;6l5{>$Sc : T)G)&D%CiٳgpIC/U;66iD/UXtz$(|1kv2*-&V_&,݅~|(… ]zg|嗃L>D_WfͨG+WCxJD:{,K߶m|VY5z[Ҙɗi& &ʖ|x"?~ V+} հ)I3fVX N:%_72B_>gΜ1c,XPVSϫćno 4hTA ϖk{Avw}(<Ķ=00pر|z\\Aq3&L _dըKA̿d>$D4[L()Cb"_%| ?4DSaXg!zw֭k֬!%AWgoVVu@W\QҩIޡCWW˗>}z|ׯwpp"G ~'M+GSlooO0X3)_L!4.]_~{襧X(#dT̖k$D4dMUZL()Cb"]C6:=.&M(>?XXX+}?>?:''ɓ'|āvuĤBN:͛PmCTU<8btJjILL$;Ff+P)$,,lȐ!zzzyyy rժUu!UH/;~jla]_(9ń\bѪU+˜9sPGxIEШ߽{wիQ2[YYM4qDCbMTNCTĊۛb>$,!c[;iNE555lgLٻw/RWݝM| .cꑏ9cٳg˷ɻᄏpB*MVR+~]#}ٳg.]Je7Haf;8~2e`ϴK$%kaXvԋ kvw}*v io$R|9UQFnu:̨Y~ZQIնӐ97Ui15>$܃111CǷiӆa֭['sڵko'4RJtssJÞOyhVyFPA̙3蛐̄A}w8ʕ+?7oPV2[A}[N7g+PL!MMMK}li[="٤ZUGrXSLKɶi``@i|G9Ṷ[1hJ~鮃xOj*ZVD4dM[LlM>$,*>gϐWŢEk7o~w?\xM۶m{mJ֒%KrrrMLL/|@Ðndd4uTݯ}uQGG1""5:>|>|!C!C[._eeeq|1>{l:CCƎBzc+|/}C!>j>C!>j>D{D"AZJJJUA>dZ!!ϕ+W >|>|!C!Cz`ʾ)".s~CD`mMH/CDDD׮]ǏO;M!Hg{FŒ]q. Lj<+|s+ 80gΜiӦ_|4o;Э[7 C )gQIѫCSNMII 1 !jټy8ک|ʃeEE*'g}_5mMaۆP?θDP]'PiwꞐ ̔Gs$72ҽ8=n/ ?}e鑒*42!wp PLL [3j*@PTTVQ27HzH_:_4 mvֱ hnG20{ - s?1V[v;MɡIMlBN7IjtCCrJ VDEUfdTffVNTim]YV&nɓXpX~DHkAAA'N !0>:̜9S{ac'<+;{>*~VrYKC$O~Mrʼ~zÇ/MoZ*nBJCYYٰaٳ^ѽ`~'aK)qvb>'sS9ҹ~}ܤ֥>tzWYT(RħwWTT!Hӧh/̚5 >!J(((Ȩ"44ٙ-geewi9rdϞ==z|H;G.DV>t~ʷBzx.%|ٹۻ2;PC^~y_!j_FC1cu&6C{+<&j{Z/sX"]w*~VzZ4n'%A-. PZZ˟j{ +l/!:}u]egjk^6 2حc *{J5b|j<`Ϳn~=>D$Zz_XTy֕_}%]xo|%HMM AU(x\~=66VǽH`W݇$CC aۧ;E8*Q ?y%z旚&KMlp摗2_ Fcc5}JJeΕ[ԿUVٳ p|>C^i@ D|@ |>@ |>jtx@ C5j[wVjz/?!Z[[Mn]e߳wNnݚ֥ 77GHIZ::j>>nPs&ޮ?#yJM/ 0l<>TV`g$>ފOw##ϝ7y'380piý ;BBW@ C!XZ$$Xw޴cGjZTb^bnKKKMāOyΝOԾS~/$dThŋ[ D !|H7[|ٿߊ㸻wy>v5d.UW=)kihIϭhT&q`6_hI/++tX+fU_;*Y%F)WKᄅ6Qwis,seg:_ߨ{!5]܏|wڮlBXgm6̴hoV_[fJ9魮봏j%#ŮPh記iR֕ޥϷVS{Gv~@ CFCyyiӤkPkl2mi roҡ?֐R$BPw>D])s[y^RC n~óO[}?}2§;/[J'圷:cqMf8CeUWqȇș߰T8,<[*ۘuydz[:}֍fu6┙5ޓ(4֮5ч$v`/oOp2U۵R/@Coo!⢝mWRot&ҶRRzDZx?b,-Yrz!Ċ~OJǥ2S>F&$whC%"L,"Juf އ,ip%_?6| [~-5~\U>T\D/ϝyKK$okd2S/d<Rad?϶/9pWCiM/?2mBzZu>_|U魥DZ}`z>wykY_qIqBO:ךnW+;)XȲfSƇM"|B#kFFPggme+{;49b:}5?o}T+bsd#~h'p(|jOR"/4̇~\⑘jjr۷T~n(})_Fan.z @ C!/{.!s떝Z*/;PB9FUT:P#6 i,M1].l|ꐐQѻS߿/ݳNɊWm/@Cogѣ v`A~^貲99](xD EE4(4Ty],4fha]nKÿ,)i;n\6mdjxzed&KnzRy{K&^$4Tt6LEYa{>v/GJɱV[M5Z[.ч[dfmWIqJi@bJv]&\nf/:p`~AA# : k;|c,i!5FB qV+ÊJRΙӼ.Gll.Y)Cmv^ بϽT\Νw.5G;JxQ@ C!aiC:_iL5|i@ !|@ |>@ |>ZE |>@ |>B >!/ }>g8F>.^`v@ |m#GzlB |>ͮ-d/kkЃ߾YQ1McէQ.\Z'O ;֏X/C |mѣm,D >۪o8&{TT LI쬭u|jC'˱pDB |Q֭=tiM!aܿ1JKD2>T\웓3Z&B |':[vq1ffڼXЛׯeMUScbyܔ)Bz-ErِHF‡>z)(NlȖ-r u#UҠz O>eͧM?dmW#o}6@Co]alGJIйc-[zC>~l]>{Pg)}@ |>@ |>B >!h!Co\}lԙ.}@ !H}߇q>u/jNn,T @C6Q7և(m*+igg?\r˥]@Cj8ܹ,rs'DZڽ{DE-^kР>j>yWז2>Vy 5{vJ/t^tgLJ|aH͚|{KJ>ћ\rhA)-iҗgceO~#: O ^}Xihos SΟݻ@ C!ԇ520в1:եp]_vU~>dpfbfZ||鵽lGC׽eBjCcGN]~{Б>~-Їf|rK!Cq=62eOΠJʼn?2\"5\>j,DGFFf]\Le{ѻ^ c>g駴z{4-Yo%e3TO|]xoo+/&CӨڇ&^LWMzxJ(aGG>j,1ddQqv6eYYe~$/OhxHyR2CwT45շoHH6;{DYaT_!ss[l2a}L {o P-C. U3CnI5_|ž!ii˟%CکSc; |>}|Qv$uq_7mXЇ$HBwVhKZ}=>th2),ѯ dmmW#r}ZЮ]ff>jt>tl^"2&M[n>|C2=/>o/' JPC}Z.c%LΞD 񤔔Q;YZ;:o!CÇ?5 |>}!:;ΙM$Mŏ!|>z|ΝKU%c#B >؇C@C;|>|!C!C>J}_;2Cx(,,ܸ3Pjf}N7>x <C!4Jͅ>|>F͛7Ch>[|v/@!=q{U('?NP~~QIENDB`././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/quickstart/overview.rst0000644000175100001770000000611100000000000022104 0ustar00runnerdocker00000000000000Cython - an overview ==================== [Cython]_ is a programming language that makes writing C extensions for the Python language as easy as Python itself. It aims to become a superset of the [Python]_ language which gives it high-level, object-oriented, functional, and dynamic programming. Its main feature on top of these is support for optional static type declarations as part of the language. The source code gets translated into optimized C/C++ code and compiled as Python extension modules. This allows for both very fast program execution and tight integration with external C libraries, while keeping up the high programmer productivity for which the Python language is well known. The primary Python execution environment is commonly referred to as CPython, as it is written in C. Other major implementations use Java (Jython [Jython]_), C# (IronPython [IronPython]_) and Python itself (PyPy [PyPy]_). Written in C, CPython has been conducive to wrapping many external libraries that interface through the C language. It has, however, remained non trivial to write the necessary glue code in C, especially for programmers who are more fluent in a high-level language like Python than in a close-to-the-metal language like C. Originally based on the well-known Pyrex [Pyrex]_, the Cython project has approached this problem by means of a source code compiler that translates Python code to equivalent C code. This code is executed within the CPython runtime environment, but at the speed of compiled C and with the ability to call directly into C libraries. At the same time, it keeps the original interface of the Python source code, which makes it directly usable from Python code. These two-fold characteristics enable Cython's two major use cases: extending the CPython interpreter with fast binary modules, and interfacing Python code with external C libraries. While Cython can compile (most) regular Python code, the generated C code usually gains major (and sometime impressive) speed improvements from optional static type declarations for both Python and C types. These allow Cython to assign C semantics to parts of the code, and to translate them into very efficient C code. Type declarations can therefore be used for two purposes: for moving code sections from dynamic Python semantics into static-and-fast C semantics, but also for directly manipulating types defined in external libraries. Cython thus merges the two worlds into a very broadly applicable programming language. .. [Cython] G. Ewing, R. W. Bradshaw, S. Behnel, D. S. Seljebotn et al., The Cython compiler, https://cython.org/. .. [IronPython] Jim Hugunin et al., https://archive.codeplex.com/?p=IronPython. .. [Jython] J. Huginin, B. Warsaw, F. Bock, et al., Jython: Python for the Java platform, https://www.jython.org. .. [PyPy] The PyPy Group, PyPy: a Python implementation written in Python, https://pypy.org/. .. [Pyrex] G. Ewing, Pyrex: C-Extensions for Python, https://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/ .. [Python] G. van Rossum et al., The Python programming language, https://www.python.org/. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/quickstart/sage.png0000644000175100001770000016142300000000000021141 0ustar00runnerdocker00000000000000PNG  IHDR  sRGB pHYs  tIME  MxJbKGDIDATxX[ǯxzݭ((X!  Hww7ҡR4ܹ[.K(?9sfN̙ߜ=;P( BP(TSl BP(D'Dh4F3h4Fh4r9Fh4\\Fh4F\6rq?G/zaWi"ṃFhts;gG[q9yoB.oЬ\= F舰@s3WFub/[p@s<Ν;G2bR:ڱc1;w&;5w*f߷wD+͛'|` ,\uuF>.?saǏ1c:p(|jij>>P##x;C7=wU+)S&F3xЄ{vmX`٘r I'G2{mL^A\zWfW~}n^@f}qr![ LJ&*+݇$Wx>ڵ p(uXknfBP7ɰئM"A<ey5_;]F0 K(&sgO-\0.>6❵1̓/\~` ~̅eκKoy3jHcnjfYvp, 1|}/^8@\vj;KZݻwgYk ax']@){v=Ϟ9Ip.밡Cϟ;w:YlLہZ׿{NKm(/^Fhtn6oװ wv?\ 3`@mk~9<^lбcǞ={0 t( 󨹒\6mYV]ޚVO lei@\d Y9BWGe0n\+G9GU LNcuiÁAF! ,îӲ|& h4F{ߘNГ$'/YHEYۡ%_dFht#;,ğ`tScCbD?y,o̱! Ky#S/q,6?Bh4Mkcs3~ O4J*4`.H4h4n|cHr4Fh4\Fh4F73.4Fh4$P( BPP( BP(T 痣h4FO4Fh4Fh4F.Gh4Fh4Fh4r9Fh4F.oGF_||-.Mn>p&Ȩ_t㣘ܟP( w_7D]?ח˭  WԜq蝗K=Qqzi;Tzg: ŋ 0ZpJJ>cRܧ ɟާ&'~LOR㌟NOȌdH 1l>ZP( UF֘\gx|[f[:::aa!ŽHHM_u@{aWMlU~ktc`:oP~|bC"""?Wq?|z ؝9' 2S!q "BP(rrTpɻǮz.:?33sѡ c#fzxXpQ~U?nP>4D&A$1ŧZF6S Y-#K?ݵEs OrY*rrv&&%D$ 6 asr B]eee*--m&\>dgQ\•9S:,323o?2[TT8OM֞l<1>ꌼawvAu ]?=wl{ b=hY['mU1.?dNAAAk>>>-GcR\DŽ䤌"zаۻCRaVVAB̓%d6IM1v BW߾}:OKKk>\PY4kqV ^][}uJJóeqq1_{UVV˟?4*((2Uhr뉉\nns[9x.|灢К(%=Kaב"Z':G'ErOn T3UWWWu?~*trrֹsͣPh?%~Lږ/,ZhbRc,DmpeDX M.ݵf||*Ϟ uܩ%QO襤$~}Ėנ4/C>ħ$HKJ'&|Z_heUN"EEEJJ_>k?_;A.G.o"ǣPটM?תYqcaҪYαr2t峎#|-B.oѽ뗧ښen|PMo++%Ä^\ҋKpȾ8'c{ƌwҖ@@ , $lX c|ןx:t z/ LY[ؾ{kmeaܭĔ Ck8$: }.m~~~꫄uuuʋuk\x @yVV˗: xxxhm^m.Ē9'h[Q*5HG@nl\;45~)VT lvBy㪨aÆ13sI||ejX$⫫/^ح[ݻ_|yo&H5gevիT}ʉBb>}!믨ELMM V5!;6RvB9ܒ¢D\^XXhnn.##7ojkk_& 7C9>0 Wx>/ዉw pYГʯC32ӭY֋垝pWxq.''81;222nOiA>&&f/>|WHjC̅Q)xn874i+AELKPOxh@dx|{9:ܡɧ 2.vٚ" }}}UfO('ќr0H}Pe(cbZʇ/cc!`bRQ\T^3^P7ɟٰaZFrÇ3Q.2e 0b^_>uT"ɓ'fJ>}[|5G,֭[VvzDP|8תa 8DªH΁K`~h {}:kDrpK"wppͅv Eذ~EʼnoҤ#Ğ),,ok{~NvpMg{JJUmWe,{IsǏO  `;;Z/>YO rYCٛ.O^OO_L/+x{{EGF@$sk]jNA8p\\?[e*ñ ZHaW\1+3l@E^^?&֌;.)lּ ?~xڵ %"g{G@@@BB|*^̌!L&H5̙3z֭"nݺ?C+W$6"r?~<$M&s5ر#YMINٳ0ygh"544ھ}{ȑ#͡˗/ [XXȜ5vݻN': ;ՈH@sQ(I7:)p߰~-C ;`˫IbNs5rpK555%/̂W^ݨׯvp+466z[\]]I'UUUp#4,_,'j%{]?XeX=M*g y>>wٳ޿ZڄW3ܮSCBB.ilv^\v\XX!SjkӉQ_WyIM4o: М>TNB&ŷ|@pa|FD\(E;;s4̆OH4(T޶Zԏ?<5򄄒‚oE@W~,yUI6G.DKKK+**taq͚5ٵTx"sʲ2Ǽ<0ܹs-ZVXqy".1˗/nO>MD7w߿?uԎ;eEW@# 1[J%%%D<ԫ,g @M6S1{_bbbYdo^l4,9@#GfpG^6;@)''(OC\=r ۗVikWU|}wp(:,-h]\Cm۶0FLHH͜99L-0`Y ٻwofcYv 8:]8T3x`2 t"u mڴ- aGfΐy!kjɺD-<۷/V,ӠP\C"G\>~w@3u/ ݻ!@^-222nnɭ=>|x1Nh)/> vH|dock {NLؕ)>|ث0388x˽1T__ׇV@|d/ ׇ6{9SIX| yQ]R(QP--Mx^,>m=|l{`ianӲRFa!q1szxzy-mo,'˟d4ʉ9pa5WgÃ?汘|+,($<ٹ7׼"9caX'SCU׮]~:s )˝@<󛶼Ν۹sg[jErnݺ={6ҲN._t7rMD.u,"̒mH͚];3dM<*cR\q7vW d 2⒆Ӫ >nts0zlt0}55!~5twz{1 Ty77'~~}TffDV XjjUEvv>o n1c s:^NE吅1\ \KB$?\ޡCrX$_βhօ&8~Pfr˩eJGGgӠP&Qjj*+\qy?gk=/1z?8I},pd_N/'crrr`x0mESao rO<~!!p,]qyޝ!*|< Jq3򐐐.r{7rwAGR8,T<ݝ"j!3Pti5!eO5dvH(VՍ @s;;;'`BAAAeָ8zriTȾf\OʥaguB%]{qD1׵Ll||=}l5hvi?6 #~$J'#8Զ,x``}iz`<9J|Rq`ںOrtWW[o˳ȨoN?"޽[eϞ=!"ׯ j׾}`SwﮬLD 6M6j>r122=zt۶mǏe5hѢNZx1yשdZ]tr욈f]h1\eddwL0ؘ9kv xPw8 c?34'O,{ jZ;<aИZp$ MBa9]6<'|0H#~LMM.%%M(nmz @>p>˗/3p9>\\\w+))aYn&49{yyJߣr_GW@P޹7lh4?|w@[5pwỤT^{KVݐMWYyʴs.=oQAq14Nh>۷o kD|*M ؁ں>!4/C?%~L"\Q*&orի"¿~)PU}gll~9YTUUel5We^B5+} 3==2##(?}Di KO99IHKLdSj~Ζ^ !\S#m!C54/̟B9y?!>ԏ-ͫX8ˉx2Y͛X>a'( B5ϱE͖===]˲2KMP#ʉ?ګ/#ƒ8\?gC-=S s7榷l_{ ͷEb/|beEhhYq5XN8.&&}HHE䬌9 HX a6OJm/P( j*.o-zq98*"dىA A޹5(؈@/?͛gT "7t r36QP1zjLP 0PSxa,?R'zRb ɟާ&'p}LOqO@$;$d?6EBP娦 kYA91dh &^RbokenfblPkxh{2 r,<}=! o/7+>"<(876B B!; ~̇F.Ghtpg:vA"bbcc`mB\lEr'~u捙s]A]'Ϟ9w-i޸\Y@C=8 k=\+C.G7=ݝΜ;;c=]9GvڵOrx$h4H p|yhpc"quGES\ i87"~\~@:rݾsAג5P@IEQ3;.]-Ȕ8kgDNLqyû:c\ S۷oߥ_˗-zk<梳ՑwCm;vػko |'ND.Gf 2@9@6 G;v\zUxh,qCN{yYnfYN\si̲۷mK1 !!vڍ9腼ܽ!C A{- Y$&*uȑ{jxLcGr5ϖoB X# \QMM hg\~э1o.>зED64.ps-oǞ=d?߱c> oپm Sϑh4y:6:l$Abx:occcc4ёq˙ۻp|C?y b1b_<pw.xaޞ.AN4q˭N:1Wx `Mwl' tb(ad锓ȹK[gQL>*B8.&sV,_|Ν;Z\2e2lPN0 =0ÒdQT\Eʎ:۾7zG`D7W77_9-5u3i?w`tu4HR̋D̑Çwֱc5W:۱D78{ݕf \l׭]ݹx5HĻó\׮]DN:̙qhj+!vvYr9TGPe2;ʝ;u֭CK/tbJˉ>: žt}fL |\96 c=@rmڴa;[a`^za(=vvZ`$9)*KOYo2aJPk" |i95h.)mNͧ J JrϴlNq+VA5ob[X`oh %rrߙ 6$(V&x{}m s<=(\456ߝ:u"ƮI#r9͂QȌ ns$m:E8~b\s[N9Inٱ=;w<;}+VUL9fo,Yc~CB rcD>{3գƍe'.ؖ݋`A9u,+.?jj^a ݻ3lٯ__ӧ'- ͫd$ԑrٹc|BaVupb۷Q;ohA.G>y5):KruN0φxrQqodpg &AWGwș *%Gmnޞ./&YNx9W@VC0ι-s+u\6q%e[7U(=x|MeU%m9<'5):77 =8;z޻[Fcqq0xXrvӵ#=wٽ9Lu,wȰ'MбcGfB e~zn@YP:?ݵKܶ2 .]|qr'{w&~L⯅=ŷ2%<4nq\XAsrQE4<4uN\>aS'2\/rXBb79_y$pn]>P 8^zKs~9x;{j.Nv@~- /"Jl@/0rnٕ!2v{KX52nب` șˡ?/Zp>_qEl+sՋre7l,"YAQ˲rDwrrŀoBSY)"G/}|t7v#5ˍɆE-vNVdW`v4g9^ާOo 3@9a+m- ģp_G 6tND=ӂ撹{ [5-PQL7mڸy7޻ Fg.'1Ds r u!RG 4$X,߼lӦ̀KƟ=sR@@\XԹV ؑ>x8p~7o\#3,!.ċPF@Ulaú;ֲ-r2s;PͲ"7ܻ\rItX6l7\~Y7:sBZmtgo\I c$H-Pv>r?$i0/B2aĬ9sf,2ݛ?;w&;S,n%'RϜ9]|(9<een:%/} ra؄]ϛ'L_~ٳfӆ"ǏcB/]3vZgW˗aHx;jgG|@G|ƍ;RO"8\F-ޞ>V4Jr9038_?ZVi{tyGOXxªuKbϪuk/]p)#3-o,͵:9xY/GgH}gȪ˩/9!ܽ#405 5kV $Só8#?fqܻ ^[=}8}.g M.wrY|i#NTEdС@ rfGR OCQRmܖ@4\*ɵVkV,_\>m\\vΝ`fcfm+׮!Bh4"SLTlltldxjkr%Ų{w z/\0_Bb7ry-+VHXrŶ];mY[X5{kj¥Kݳ`2^ρ-߆9;z**ZY[z@|1K.o}ܰ~ǘÿ tۄ9Wxkͼ]hrW,߼e ]}=m]gOmذ`,=񂧻r9F8.+(ڤΑ2 lbZ9|ׯ]޽@۝#@n\M<~앑+C s=Ϝ}޸,'(v. 2I73-bm߽|j[6 {9]pvȐO=la/>z'մ4n6uƬSgN: ht rFF_Y+vD7vGGxzx'B"amB\$oXʖhV8\;c]vԩӲK8LJ\m!_߾u9`]͗BH>!lokhk9?` hhgf.G?#h4r9\F#h4Fh4 Q( BP((+*ʑQ( BPr)r BP(T[r BP( BP( B.G.GP( Bˣ">TOr BP(i<.&BA  BP( BP( B.G.GP( B4r9 BP( Հ\m!P( BP 4S322$%%ǎ;tA 2dذa#jĈk1cl޼9442$$d޼yѣsܸq&LX+"0}+V;v,**9ׯ_/Z 9BF"v5~I&-[r}NoH<䧆0ao3f8|p@pW\v+BP( GHHw׮] 4\IIr\\]]C Ϟ=]v+Vx%`:<<<:wLryrr#irӧy,rqiˁe+/91tK |OMbFo$?pJ}<4j{@ RIPB( VxP( B5 <uGw E(+2._<zvaܸq@ɟ>}`aA֋yzz³իW/_|鿺\/;vlذaP5xӾ?S2%˖W\fo1rhʉ̫ /Dxj}o ?lk?Cl%$b/x5/[e E7~ Wx4;.' utt.w뢩Svu7O8Z({xxxYr9AuBTֵɂ ̐=D,K3"n `@3L7P*)wK r/ =0(^PXT>r9 vuJCC_~JJJ$޽{|ӦM;v(捏ܹsN<\9΃0]YUd8,zFa;.'S6>8\E#0ai .rzz:Y?uܹ֭[={\x}@䬬,쬟ʮ<عs &~~~C }vdddJJJZZs py޽!,,2oI Vrgx /8r ô7._fX8K`D֙)3^PXT>r9 vrYYA W~D\5V:ujժU߾}MLLڵk1:t:tѣGjȑ~jݻw|Z!%᯿@'A \\vcXjg`õ?=.X"ST񯜍ܱ%.wvv>zMֳ:RVv277/))IKKn'VqFHs___PˁϞ=+**JdİK7]wm*ԿSo{2i8ԅjk{sO݌=߽D =_z2ܯzw5T̷,_x;5x>Y0vRh6,WVVXp/KKKSSS9_~-++c(졨(++݆? ӧp95p9 L`Pr\,}!b5u }AY_'DLh!= ٧6\x2ǐoWQK3hx^R֙.d1^ D. zcn\nMunnlؘф\ބT` _kLP@o$ԴNÖVEB}^>ƯRI\+)&&k\jRQQSu}=x |vڍ7N__DXKKkС۷8q+Wg̘LD׳gرcΝ/__.7~1mwINibA&x&^k|>VQ0ɚB\"z(  *8O/< Gܡ C/-U,l]sVlO*}P7]ՂHWɩ'A#W~,>JZ;,*dDZvz$4*ˈ*ظpx}6wUSoxǯ~[ͮԣ Cyf\TA68Y: ϲm9Ԃa?J<bWOK Y>o,l~ ]S!S%d&t q5ᤠfWesvy7oޔs玌l~ boܸqsah,x4sW^?ngb`@ā߉Db?ZjӦ ;. !`L._-;0\ % m9f%+tvdz-Y `#b᷊Sy+-suuNw/9ߥB UXA&B\B( Ȋ@N M0!`jYRR{{e 筂ԣ Cyfr3i߫?]r8#;tۇj7v1tC-7BQ?˟CaC(P,CʰkjI G r%d&M4KqN fp8Rxzr9 m۶ `d]]aÆk׎fR_qE}!E5/Z,YsSF_3\RݎuC2΋\?ց,lyȼs7ARۺwj^c1$<?(oo*_]?z㡛3 wQs{Mt=k^9XV'i.fjLeîՂaK=C 2u4!dW4ORmE*6 3nQDӜzNDda&\]JETp8)h^fwܣQ('rjgftR3o xUNny B7 vM_n;Gܱa-0B@NݲZٯ$QܯǗWY՜G~3fVoxT@Z=@Sgeeabcv#eeesZ,XzI^ghhg> x+/.0$$dԩmڴaH=zhy( BPf#F|ȑ#c2^}}}_ Lor?ֵ"G###+**d 'MJ?"-[cCP( B5G.?s挮gΞ=KĴUZ M gΜ9y/_P)6)++n۶-Uu1ҥK!S%3رcP( BP͔===׮]f///"fرVVV3KUs566mll!3I_0<30SѣP( BP͑˫Ԋ>rHd@jaaϟ?SWYZZ0}\Yp&88xҤIZbwCB%%%P( BP͎Q( BP(rr BP( BP( B.G.GP( BQ( BP(rr BP( BP( B!P( BP( BP( BP( B.GP( BP( BP(r9 BP( B.GP( BQ( BP(r9 BP( \Ψ?]䈉` >[|sxZ6 BPߐMMM{Gi\_,Љ\BP(%ry#Nqy39Kl7 BP< Sˑ/Q( U6,㩑GٍgϞݩS?s޼yo޼aAA+Vy={lӦ jƌ666 IҐgΜo~ԨQ՜ksknԼ`wyƍrgh ugW vg'u i۶-sԩS^^>i$xX͛/H)//<==;vد_?mmmM֭[tu޽_~C<( U'[4 i%&FΝc^{miK2gjkkۺuk@ECpѣRPPPSaÆ10`@ff&\w\NX>KYK.>[nW^ R 45FWWa!!!j8 p,X6QAP(rNl"8::T+Zjΰ?ӧϟ?1aUVV.***..~'L(,,@{B8,ΊP(r9B'6rׯ'"H'Æt CX۱cGNIT&b&9d$ME Ebqʔ)Daaar e;CSVwH3κ<<<"۴iC{3+}V*5"A#`+jmFhlhx`ŊӦMc_6@c//))9pEJwڵ+[n١P,7ؤk!}E;uNِr^/ I<B̈́PȎ҉!bZxy{ymm5d&G:^FyMFTUZ\\L̹^czʃv(T'f}6Zt_}gv*6UUpG^/o!mLuzyMM .VCkkk*RZYE-MMөS'&JiE]ve/ f}6ZyU;ѣ٢A!O??bii4Ȏ@[򻷯dllla?T\-9ہLMM{pٴa]+ڤ!bg:wܷoysve!5/777gŸ={Ƅ\zN[Lcǘ^՚ft҅9%ږr=8p w"jJKP;jN۷Icoo?^| gBƌ4xǨ3}b/D?|pd.p7W^:::IwNV9HLG|߳xVO\pL?fTFFF2}6BLHLLLWszᢢ"ު"ŋ3&L())wL@vIIIիH/WwM╦P;j^\\L,(R7Zw>|cYv MMMTu1&zܸ򊙙vͫWkl XZZ˞'$ܽ-q )Ab$/wcǗV,_ª!yܵZrm/^l螝{211qrrϘٳ}iкvчT ,[ԪV xypp0oŭSnf7o˗h"^!Œ7n˕TDBzq3լ23j\mߕ6I4ͮaT3ܗV.mI>b\4ڎaxoxMx${yQz&< gV=yllKEW.] %9]mI[H:KyDچǎ!g~ɫHlrq)5/;8h+/Nsέ@X(aɨRr"((wt ս{sfgg;ܼk׮&Lo;vH3|C.>C%k׮MJniԩrU=-..^bݱ(YXX3u֍bk(&Ϧ^ 1(wZ7 ,c~bO\\Ulwԩ حf"x9yszE$afpҒϜdܣczDGNNg%Җt겅Vٳǫ>9 KF.iٓz) ʋup_H)ɘuE#C蒊 F {M&s/gizO˨#=8t[ǎٯ2cF{lۺn0˓ mc&f#:h#..A6gf >@}/'FJ"ƍۭ[7g!;+}X^EF@^#ode˖1!~~~x9QSSSv$wêϾovQv.6lآ-ev:Z܏TȿVہǏI'wϟ=NrIyuVc{_ykz,cF_89y"kK:u)~m0U"¯+hCt(&Iz=zIk]&k˖-Vr<99yڵBvʕK.qחsBQD3E]|bOGɮXRJ`6[#5֮X=dcH6i&J\|T>( IHH _|yTTҤ eee?{{9Ѹٔ4DT)]b^o)*==n t ~y?g)=S۷nJ{iUE43(Qy"U^.&718"%`xcCrE,zn /G!rrc ^7-rx9\oU5MyyNa9%5 9}SJ!1w3ِ[RHUG̨닪NxxL~yh{肪4oۘ'yk/^u%Y?h%:r^JTfsV]]h^.ׯ766gAKFFF]v]cFOГz5y4㆘*{ tR -*gC(B&=ki6 /L[˵r1O^\;f÷qBަ9(|?JD^~/ש롉L^}_tܮܹpBGGG'x996l{Z__߫Wx6oۨ(zՕ}:}ڵ7F!ى'dɓlL&[xun6nțu NUU՜9s6@l;vy<ݻwz{9NOOܹ[ot&kԩSBWgݩ}W+])w{9ʊ8qY;MLo???x̙۶mƒ#sL"f ^.2ϞV:<ǭ$63)@nRJ`7(cRnI{;#/,bN?wk&#> Rlx;ZČjY-=?ΧSz~,K{^^M` I>!QvT/8q7|C{c6|ʕ-R:V%K(/i\nnK Hמ>}Z^^gq[=33ޞ9ׯ_LL }T%KOw\G^ TuoS#$|S4[CA f&qpp`鶇N۷/;_qY\ΫQ8V|Ӧ$z0쳰?ͩb]EJqfsssU媪29K\2_NFv_|@<#R7+J9@BOk~j09S7irJo.3!)YIX܄UG/_'f|UMg(v:}𤐉]"ɬ*?bbu?_?ѳ5?#Ycug}y򿾹p3F؏Cc -\JnXqE]Pʚbk͗|7SɦԘRI^' -uyM5ҩo[ܔ% oKCOYz?ĥPl'ܼ'=qCqWPb/ ١~x!+48tOC$JsE^;Z_xУG>[IrnccLo3KR&{>155ϕ1鈉]Td2br~M9((A;tA.团}׽݋ q=gbl}A/vؑ-**Zp.]oڴnd˧MS KɸL-z.;# >yV%@Ӥ?ߴP c 7Go=iIPrrfl###VrQxҥe˖1QƊr*zwe\\{NxKU27n"}$û|S4rbɡڱc/KIIr{{J#G:uȌ߿;_]{5P3OJ+ilVTR`vanªNwo bNN)k?<ԗYEuA!L*ѳ+~q\!LKx.ram;L28װYB˙W( X h=FGJi?e˿t~/{!"c=EQ C]+fIJb.O>}zh9R>o|yZZ;_N:rm}eճfbgI}?^__O"jLU_}ɓ';CT|m{ ͭw޼U+Br:8}47ҥKrʛ3_wYi|OZI SXiK I}FZH/WNQؙNɬbg*M$JicVދO4(h-嵍;.|fzY֬^>BO6lj$rAvF\[6^_nZ" jI+mpS|ݡ+wrJ+jM ^{/bĉ=ݛ>}ZnKc޽{'MK3a„}5VR\_ޭ[7v/k䭷zyEΝ;>w?KK|57iUwjjjN8amm-/xSs/\rbf?Cqc$jkؼ4~d$lmmoݺE)::ˍ)fAˮ ܸ7bu, cQSOnd! xս:f3rJCNIŁKtv̬z̠=/gX;D=ǡ?j\lQ/gcaoi^^WW_2[ 0F|СNogd2RUr_W7ofb׬Yӹsg_ڥ:`^, 4hTȜ~_⍀d~MLL{;v$#gW ) R3;;[1943m0orwy‚^$lʊ.i󋊊d$œ^z%XGis>LH.fz1ۮi}}懿(~S|/Y;IX;{kQfQb/4n=Q6w?}td뿻A bbaâYѿ~dHʫn`6E\Ս}& Y#Gϯ=xYsZf㿈ƥ c~BHZ{O%#; >zR ܫ+!|VhclSXvVn}ǏB/y.iږ?n8~!#ʫli/g֜PccDܓsNBUҞE}S 4, چ*DDDkuؼ}[1K; }}7.9L/O"BHkbu溓'K“@r*ٯo3x/YM[TVs7b ]J+(w^56_rw ;$2{0~^jĠJFWnZn1QwRysf ooq/=^4bx^VK}?}I}}i$Ii0jZFVz\Ȗyr HGan^+^۸ԬBSU),nkߺG{>ԝ/^9C}>-***ə8qŋwussuxy~Kx`, x9x9r4^/h<//^}J^ 4fx9r-a//^/^^x9=oh ]/oi/ш#<<<222t9kז1ctr/SSr: 5733xy+x7nHjvڑ#G2 lǏ9884[ΐ!C^|yyyy||)SlllLLL,YRUU&pႇ+=:66V|^/oK^Jjnjj:bĈ􊊊M6XR\PPPSSsiӦw[?uJ_Η;;;߿P.߿ܸq .db⬬>\VVVZZzA:~^Ƽ|Æ  ڸq#9G.://9uppQQQ1c'Mݱcɓeee֭L1b޽{p:@1i3?~srr,XS7n…I(R. N_:?~̙3tsڒǎKήʢ{OLg3ں Pv^_^i&Uez{{pCo 5kGl-\W^III))){Si3 T*sQQQܐt;;;-zz'MĻ ;v>>{pחϞ=["-ݻ}a *垞˽Z;uTXXMVu޽;L&#%gcSRR\\\"""ɀùdee/444??_.SQ$Ço3 L:NRxž}R %P0e!bڬo^~eKKKf?СCtʮo-/;wyG*0|`eeūZU9vUryϚ5tD///q33377Hdggϟ?ܝx{{sn& L]h71rC?NykWf}rܹsF؈{LLH{n9/Zt)[[[]jUW^x9r}rfP//^/D+[J ҁCT*5777o$?1G/n]: `$ßmlSSK.HRrssW޽{^^^殮kx.\xѣG ⣢Jv3!!AMJR+++NDGGNMMͺu ҹsgcccoooFU>(0>>~ʔ)666&&&NNNK,ټyرc l$WV#99eee%%%aaad~ő1ׯI2TB)C:16Iׯ_OZ|igggj/]4==]&UWW1BLH߿P.߿ܸq .䦙0aBhh$ ѤIWV,}vx;vo<K@@^^x9x9rx9rr//^/^^x9x9rx9rrZҤɩC#WB:phדhHRssy浓PCFFiv...gϞ/YH9h0*hrQ}}}khdgg^t4}`LF9((Bw0~~~fff ⥼wD"T*񱲲ءCFGGDQ… 42zhr8aa **Jv3!!AB W ͛ǎF# 7?w\^2wwZ^@4Dnnn/2]I&%&&jPSSsS.zc err}id''ÇV~ӧO;;;ʼn:*ȍ҃E(ieСCNLEW0aBhhh{ z1b޽ixx8*fHH nWU K$(Ç|#0m޵kt[k\^i&Uez{{qCo~Y{QOO{pj;vL}0U}PcOW \H޽\C/o ##{24,MIIqqq(//' կ_?R|\NE>>^.\˗---H]D]+`7|3))TTTt=z(@Bpf ׀#Gn۶7,{} o4:cv?Nj/ۗXoSInpy#IoFI6TuXXX`K m_4|87 hXXr III=zЁmܸΝ;嵵iiisՖ't"669xb߾} Ϳ:Tŋ9$^n^q绸x{{pq%qRQQpBccckkS&$$˯]F"޳gON: 2dÆ jhR~Wh֬Y-ЩfWG)tĦ ^4 TWWI{U#x9JӓP{xr/Ж[^-D/+bD>^/^/rx9rx9^^x9x9rx9rr/޽CMD"qrrHSGG,T*5777onMRu={d@zdddxy?]\\Ξ=[WWK'OYlf|}} P]]i0Nmz5HlmmCBBTEFFFmQU٦.]2xׄy3|ƍ=zN󊊍Bnn.>//wD"~FJR+++:thtt4#G>Ue)Sؘ899-YJdmNNNk$'8~8H1p߿Oҥ s^z%1ݩZtiݍ,Iժ+$| F؈{LL E .tpp`}s\\j{lD^nbbRSS/ /޽;L&'gcSRR\\\"""KKKùdee/444??_.SQ$Ç/ӧOXXf?f/Rt֬Yvvv<|07611ˋt-22'w666ޱwh?~Zedd٦o//o^L^/^/rx9rn-HV.Dۖ'Oob^ޚ6rYzS^cc6`/9]u]gϞCfFFFzbr@F>{lnȬY6n܈?d^Ǐ988 4{yyyYXXJ$MJR+++:thtt4;5M{z/\J#G]6Tl׮]===p5Q@@]nbs6Ԑ"2stiZEEܐgώ;x9\ݾ}{ڴillrrÇJJJeYttt\~}~~~UUӧD:RdLlii"̘PF~!U'"AhGw^4<}6="{ꕔһwo:577;vPrFNtc`ff?d^{{gϞ冐/fFyyXRRbii|/ʊCYDzb^[[[1m_ z:lذWj2dĉ'O,**wr^/W OJ166Pb&)dQ\^^.W"AXF7뛙9sLkkke̘1Vҁc /7 rE:::d2Uh*/'d/AfՠG AAAs .//߹s,Yǂ}rxyؽgϞ=ٳgK$rz===ח{yy,JQQQ\/'7ڵkƌ(]-{n>}o-tŋ;vү+$nذx9\9ݻwgcddllJJKDDDyy9bxx8w~r*srz/_liimB IIIԤCq?Hpvvx 9rmx"A1$n/^۷/TɦwݹsJMKK3g݌]/G*Κ5tD///H333H."'666ܭ5r;wnԨQqwwa***.\`lllmm=uԄK$WWW* *"o޼٫W/E_ zDh"nb:s]]W\ /̵kHɉ)cN aW4GQ;wܥK~O Mr˗c(/78/gkuX-[Eqq {9h;kǎ8^/^^xy;zkT*5777oΚGuQjS^reԨQVٓ5x rr__TWWyTWԦnB ^/7(/655t钎K INNׯ_}}=U7nѣw^x9\,򲰰077wuuH$MfΝm޼yرJoJ ڵgBBbϟ??ynݺ{ժUx=00PٳgZUYYioocx9򦑜tᲲ02]&kjjFw^4<7;;6++={=^I&*ٳg={3h[lqvvfE[}vM+)))%%wt**6aHKKSZ2wNӧk6dt+ Β^ʲlٲJU\UU@c/^lllx ɼy6:lذWm&&&Jy6ڊ)>887ܹBuu?N^RRˉ@`/ظ"mrt#:n+(u˗ ƹs犋om*[ Q*6/y9<^x9\yyy򠠠9s/Y+XRSS8_noo/LKK'OpC VZB ={T[Egno}ݻwSVVVZZmܹs'7d׮]3fSfN !=SJIc׿U}WIl/^.r2p~,$山ŋK)u6}XyR`ꈘ2gϞ;HR\N|=9Rq~=x@t`oo/^.D///q33377H&g͚h"nb:M~WH"Rx2.]ڽ{wccckkkrtz=(]~ɪJ"z /^n= q۷/הFy\چY'HRssyƀ[^.:M/EmS*iEc MԵ2g.)4Y /yTP V1pg. ;ry9|̙Μrr9@.r\$&&4Nו5_{H鄎;zG=#\D.塡;v쨨%;,I'nzŎzFRqss3L<\OOϽ{~8={v̭>ʼ/^&6cwݻw{g;KڪUsVwG⋁!!!ofYYYܹsРA2˫sӦMr'Oy[hѴiӞ={nٲEaÆ{{{?۷oj՜9skmڴr9o<#\^s$'/IqݺuEEEk֬gQ.\8que^ؾ}O?ի!==_~&Mb="IF1'''..W^qf?]bVŮ_^zgyyyn*K+[.[Q'ȇE9ŋ8Ps{@.\ՉAft@III!gΜ b|DqEάWG}d-=z̙3cCBBBN>$ͷmvz&##C;\ouR f<|VgL&77j-#J@IkM6ʱ~~~!v;A>KHv7Wc32ӓ ߕh4*  V3rۑ]\G4uԞ={h4wd7\ev{2V,UrIޒG\Vp??s)dff:˃KOZ[]ܖdnYzk,X *++y,zˣm/iի!|WZhe1c[O3N'{ܹթ|\^s}ck׮h\ }7TQ_ӧ?V[RR"O ؜nݺI˓ggg/]W.J:ʻ .lӦmc"""T>^rO6.22r׮]S+޾\^VV6eʔvڹHFp2͛_.{=XN0!44300066R*+;vh5P TVV}WYFCY~Iq",,lԨQ9 Q%ύ+W ϙ3Q{՚+..Ny\N.GerrSO=e>#(<<|ɒ% r9@.'r\N.oCBB]f6quv'G!%;;z'44tǎvZ3ˣxB9 #777dwμ}%mː"55U= 6t{/<<ݽm۶w5a59skwޝ;w4UV^^^;w6mW .|gd2D9cbbZlݽ{Dr⬎=zܸqV7o{ @.ot\R)SΜ9%fff.^'n}Ѩg}vٲevGI^_n]nnhɑL+T͎rE,\n+sɓ'CBBdEEE+WlѢe92wWZ%wb8p { @.ot[rHM\.!,DDds!Cϟo9e޼y2D GRr (#:utĉΝ;]UȨ۳Fß{BeǛdիWiwl``թᒼܿ{yK.//dO.={v CCC3m4'3oG.:uߔFcΨ`,6 Fz-sdr9 7\nQ\\|х ѣwޮ;pKffp??s)d{ܮ֭[_tI9xƎow!=[h4f͚VzvQ sU_aÆ-]T9k׮EEE<| ]ȢE' 7\ޣGٳgFcǎ9rd厮8f̘gee o߁\~zIIޫVR^E⸄T={ɔV :\s%w'<<|֬Yz4O%;])Sk= @2$f's'ޤH<6l>bĈɓ'+'Vv ry#w5ɵ=Tlj0 YYYǏuqqqXY\r9 @.'rr9rԺIrryÏrr9 :4>>^˃ϗ!teK.ImժU@@ܹs- 裏n߾]9ۍ] ?z/o9Xt:{޶mݻw;9… yi2n<~xLLL˖-whyqqqV9zqrr-Xb5k/\0qDgyyynھ}Wv+eE~իW Czzz~&Mc>eʔ3gŋ?NEYrv>?[`ʕ-Z<^Ya滫V F͛g;|3gTIHH\nw2<))I9DrvPP3[qaȐ!Ϸ"m!N+rȂ 777SN'NܹU r|ymڴ~~~W[b2ܜy,=\rrr~~+RY/^"]gw޽gϞ% r;1vIV\nwٳg Ӈgڴi5FQ9`0.':^\N.F 5WdR)--u满.rG.\G{}غuK.)/?~\\رcyIr9;f̘Dy=<<~QrjVVrHRRҝYf tRǮ]>W5 ˝999ݺu[lY^^`Ζ+rJQ&Nؿ'NȌWС=z={?P\\l4O>=vؑ#G> ]~WUc8.jgϞ06 ˝&Lk f6mnnnV )))4iR۶m^zcǎ݁\~A ;v 5kVgԊ^^^`Æ 61bʉ@.r9@.|\fr\ r9@.'r\N.y.j !  rr\~Ww\&4N=Gu=zx{jyᅢ zfLo]zZ/n ֮ձ)Pl)H ij$&CB7KJLutaayy&zL&N,9sB;wdխZi;wNVZ^~sޓ'2E g-[u璖rtQWŨQm^o~S ^9VeUٓ5F:< |}5ҶbiIl#V Xwf[AҀ =zHdEiiF˼2Ugx@ʱGWR+ۗFonnW\3R|A.o}{^5 ~ 'Mٿ {ut" MkC7tz)i~6X|lEpLںU/+:*٭˼ނd[(css+ʜ oʍ?WȊVib\{f4ֹ\Nmj˯\1{ϑ#?曄6RIWMRzL^_)oə?DHUp{"y"O<'z-((%HO7޼,)oyo~L YƻU:s.]o_ {a_)ZB.[v|_ Z^ȮM9e^ɞrys̙.rrk U>vyC2ߖ>e^YT"" H9D<=jըQ3^ԷzOmt{m*/ᅱE$oZilѻfitU^~ƻ<4.ݘ]H۶Z %t=q˜aY+w~a7xu7W+\J!\`sϕ׿yvuﯹxЅ ݁Loq=7wmX L~~N!UXWeȊ{*PvyV:s[Km7֘/8̼ғm@}+(<3?{+HUa7<#HVIc>FعVKؿн{AϞTۗFonدnWJ\B.rF- J|lo9#vkYԩsLIk4&zuhV}dD+ܳufFIz}eF6:{b ko̡>} M+#[%k:*VRbjLzeJO4c.7O9]vQQRzbo_ {a_)rGr91=Z#;>gZjmiΝUʣ5Vcpϕj8Щ)e+ȢtQz(dre*"m{DM:P9D>YɆFz>vlI||ym1eѰ\r96_S^c̘- Vt&}|4V;_/>Xvʱ=Wll5N}uhٳ{ҕmdK6RoVNN?xmX$[|Ȑ[ zNerŏ?v-0? $8~a7xu7W3I#H2@._3ݸڵ:k9N}Sѭ[eyy׾]!o!Na32uVrٳ\U!oQ׾'׮PRbs]PaL+cy'z6OXE&uݸb.o ~l{ҕmԣG~0ʒk>vl ׷z._h~7`ͪrWU'oy./m!/ny#Ymr ={ aag9ۗFonدngr,|J]EE syDDH 7\.RRO>YجF*2p.{܊ J3?0Pu]ii׮+o3^^ݰpLS=? @#\uzy7q\y_|j].p~k_ZjuDu7bDIO>-Xmޓl ױ#G^0kV?.n#V:u.+{gfi,귿-Η.:vQ*U[}Kɷ\LZ2A~a7xu7W3|&[[s;u] }iQ /6I@. W7(? \HN?ԍ,YRN\?&j뾣 $n\~/m<"+l_z9^r9h( r9@.'r\N.\r93.@r9p"rr9@.r\d.oҤ "++{VϜ93hР=ٵÇ7+++{~//nݺ]V9VzO /лت#G>CʁZ644h4nǎ kkOnZ:4`'gNwرC*'{GNy, /zzzݻצ;3frȈ#fϞ}[^WUvZ n+55UzŋG:z/oYh YYYÆ ~Go߮{AhѢiӦ={ܲeK$j* `ܹQ;wyeWΝMf9bĜ9skQQQ^;v؝vq]WhVddy؏rQ.o߾~zUޯ_I&U98{lpp|'Q~֭rwŊZxls3'(\x1((vZz_ɇ4 w۶m]ŋ%rWsyRRrș3g}v^OOOp"7""""##^֫WҀ_>$''kn˖-V Ȑ4~]喳VL&3 M6!~~~N;K6|ԬUf:N%?c|.U+iՓj)˔G\^@G XҭޖLn4K]rEE풧NڳgϔF#Ѽ5hz.ol籨U@@@QQrf͚~`^hu+^p%;wN9$33VZe" ؾWrc;]3fLbb >|!-r2[\zU9_V9ާΚ5vZz_M>I[M&}r]v]r '999ݺug0.]jmOOZmII4>((\.yqYYYXo^˥f2stDN8z =<>jrZM`1@3Uմļ{!2Pn;*m syBݺ^ݻ2MmBԤ'_wP{&pG/K'M*jMEE,<Ʃ#7k1b]VWRrm+tr]FWVfz2pGlʪGF1@C)-̼qzwA)4TkYJ <*˨ ܹ<;AJn]h'- Ƨ/Q.2WBn֮=R)YK6jm|l3>?na_ V3{"U^؟Y|?/Y17K6FG!?"6 {F׽ rG&O1*jϷ^]^^!o=Q?LKӖ^wWeb &S_K,U;:J3f9d iUW>!L^`χlڼ9(nݹmyyNʒYFueŊ+WtW|'Iz_yDmV @.MnjN9dĈo%溞˛7pBrm"RںkמUJ&ɸ8YO?lt|JS"rg1Du|ܸG9ԩ®]:۬>\^yI9dǎ}q=mtc/oTɋͷܷwomذ|D.lmYs_ѼxӦ%%"asus-igzkS_ڦ砠2؃'NXF͜y駿>r$BJnw9iI{w_s,M gT޻m }l,n Zz޵;JPn,:~Y~vuyDmV @.M õbFD슌-7 /'g^}nҬ6mea_UqR ɗcrrnvl͏Մn6?g,Sm`],g@I!}vmTnY);cd/h:zDmV @.-vOQV.jտ FK))KKo(Q:5?0*i6oε{Ř1߽~.̼dB%;W==dž6ovAoQAoLuٙSVl;uڲzY'zkX),48Yʱ}wU:w<؀/%*Jo,j˗7JTorɿFK.:?oy 7Q_={.ln?;˕lqVVpj="6W9\^k\ާ Ӗ啠W(tjGc#"v9NOGlrv}ٙzy}ggg3I~~׬9[PosukfʨV>k9Cr۱cyҥˍMnuKrrrMNV*咫Lz=h 3KVXw¢EgF*a לn?CK9]!HJ;`0/^|mۛG;7s-˥v[;mOeނƍz׭/_.nQAݺB+.>"%`絛_~Љ!+x#O?T~d~3'7^4ƙG*k?|{% yqӦկ6zx|!IqC^,GMٖQ_}Y2_H&W ٱrS  e$/w$$X_ Wv/XUB3z.]J5"U%3s?Y#RoXr9@.'r\N.\ryrr\\r9r9@.@.\3s90r9 rr9@.r\ r9@.'r\N.\r9 rr9@.r\ r9@.' 7 ݚr9r9@.@.  rr\\ r9@.'XPw\^oK.r'WԤIr9u.or?gPOH.ݗ˟|IGW^!{VrڹIݺuw}#8 r\n9_yD\n,Ydr{Ȑ!WV{,44tժU}Θ1gԩr\^/_n5CGԩ`=.Q^'N{キ)yh[r9\aÆGy䷿mJJr3ڶm Zliup]@TisBK-N)K(2\>رCrx^^ޟR͚5;rHNNrȩS 땵}Kڱ#͵S<4\n>7sJ),CLrN02^!ӦMSNfZ?C"/:{r %6m^#uz \bwE.ݑ늋@ͩfժkܙEQEQEݾ˛5^xs*+JQEQEQ nG 2EQEQ\NQEQEQ;prc߾ں] ~ar((s{I22dc{)((ꎞsƭ[ƙSG~27M:?_rC|}}ºw)(O>f̹'w.2&/w4o;ƄQ#_iݺulH((?ܻ򭯿ٻ`U"+g++%6((Hٿ}\f^.6c1?!>퐐`L4 5m4gO((~2kނ=5{gKVʂ˧o p<5{Swo}D}{pߡ{{~rc,sI޿owڱïOG~<|d7{wK" _((×yrTW|:3cwJ.7O\\q򘇇v֭wb#|<<#!!;o6ߖ(((|O3¬&l\ʵ/?_fpz;oUͲm(ց:ur%[e+(n͍'EQEQUr'?/F phKSrsx5kZ4ľ5V痿 ])[-z.o۶}yPEQEQ31kޙ=xxY82ygN #jm\jcQ#c3fS}|{pTTTnjRoz>QwnI=((?CI_})7ir񝰙9;'NXݮnʫq~{7^n~~urČ)oN6_Ks6O((_~x7OC\;5Ţ2UB9(("W+|2C9(("{׽2`_) Only the system paths, the directory containing the DLL or PYD file are searched for load-time dependencies. Instead, a new function `os.add_dll_directory() `_ was added to supply additional search paths. But such a runtime update is not applicable in all situations. Unlike MSVC, MinGW has its owned standard libraries such as ``libstdc++-6.dll``, which are not placed in the system path (such as ``C:\Windows\System32``). For a C++ example, you can check the dependencies by MSVC tool ``dumpbin``:: > dumpbin /dependents my_gnu_extension.cp38-win_amd64.pyd ... Dump of file my_gnu_extension.cp38-win_amd64.pyd File Type: DLL Image has the following dependencies: python38.dll KERNEL32.dll msvcrt.dll libgcc_s_seh-1.dll libstdc++-6.dll ... These standard libraries can be embedded via static linking, by adding the following options to the linker:: -static-libgcc -static-libstdc++ -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive In ``setup.py``, a cross platform config can be added through extending ``build_ext`` class:: from setuptools import setup from setuptools.command.build_ext import build_ext link_args = ['-static-libgcc', '-static-libstdc++', '-Wl,-Bstatic,--whole-archive', '-lwinpthread', '-Wl,--no-whole-archive'] ... # Add extensions class Build(build_ext): def build_extensions(self): if self.compiler.compiler_type == 'mingw32': for e in self.extensions: e.extra_link_args = link_args super(Build, self).build_extensions() setup( ... cmdclass={'build_ext': Build}, ... ) .. [WinInst] https://github.com/cython/cython/wiki/CythonExtensionsOnWindows ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/tutorial/array.rst0000644000175100001770000001567100000000000021040 0ustar00runnerdocker00000000000000.. _array-array: ========================== Working with Python arrays ========================== .. include:: ../two-syntax-variants-used Python has a builtin array module supporting dynamic 1-dimensional arrays of primitive types. It is possible to access the underlying C array of a Python array from within Cython. At the same time they are ordinary Python objects which can be stored in lists and serialized between processes when using :obj:`multiprocessing`. Compared to the manual approach with :c:func:`malloc` and :c:func:`free`, this gives the safe and automatic memory management of Python, and compared to a Numpy array there is no need to install a dependency, as the :obj:`array` module is built into both Python and Cython. Safe usage with memory views ---------------------------- .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/array/safe_usage.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/array/safe_usage.pyx NB: the import brings the regular Python array object into the namespace while the cimport adds functions accessible from Cython. A Python array is constructed with a type signature and sequence of initial values. For the possible type signatures, refer to the Python documentation for the `array module `_. Notice that when a Python array is assigned to a variable typed as memory view, there will be a slight overhead to construct the memory view. However, from that point on the variable can be passed to other functions without overhead, so long as it is typed: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/array/overhead.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/array/overhead.pyx Zero-overhead, unsafe access to raw C pointer --------------------------------------------- To avoid any overhead and to be able to pass a C pointer to other functions, it is possible to access the underlying contiguous array as a pointer. There is no type or bounds checking, so be careful to use the right type and signedness. .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/array/unsafe_usage.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/array/unsafe_usage.pyx Note that any length-changing operation on the array object may invalidate the pointer. Cloning, extending arrays ------------------------- To avoid having to use the array constructor from the Python module, it is possible to create a new array with the same type as a template, and preallocate a given number of elements. The array is initialized to zero when requested. .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/array/clone.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/array/clone.pyx An array can also be extended and resized; this avoids repeated memory reallocation which would occur if elements would be appended or removed one by one. .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/array/resize.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/array/resize.pyx API reference ------------- Data fields ~~~~~~~~~~~ :: data.as_voidptr data.as_chars data.as_schars data.as_uchars data.as_shorts data.as_ushorts data.as_ints data.as_uints data.as_longs data.as_ulongs data.as_longlongs # requires Python >=3 data.as_ulonglongs # requires Python >=3 data.as_floats data.as_doubles data.as_pyunicodes Direct access to the underlying contiguous C array, with given type; e.g., ``myarray.data.as_ints``. Functions ~~~~~~~~~ The following functions are available to Cython from the array module .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc @cython.exceptval(-1) def resize(self: array.array, n: cython.Py_ssize_t) -> cython.int .. group-tab:: Cython .. code-block:: cython cdef int resize(array.array self, Py_ssize_t n) except -1 Fast resize / realloc. Not suitable for repeated, small increments; resizes underlying array to exactly the requested amount. ---- .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc @cython.exceptval(-1) def resize_smart(self: array.array, n: cython.Py_ssize_t) -> cython.int .. group-tab:: Cython .. code-block:: cython cdef int resize_smart(array.array self, Py_ssize_t n) except -1 Efficient for small increments; uses growth pattern that delivers amortized linear-time appends. ---- .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc @cython.inline def clone(template: array.array, length: cython.Py_ssize_t, zero: cython.bint) -> array.array .. group-tab:: Cython .. code-block:: cython cdef inline array.array clone(array.array template, Py_ssize_t length, bint zero) Fast creation of a new array, given a template array. Type will be same as ``template``. If zero is ``True``, new array will be initialized with zeroes. ---- .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc @cython.inline def copy(self: array.array) -> array.array .. group-tab:: Cython .. code-block:: cython cdef inline array.array copy(array.array self) Make a copy of an array. ---- .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc @cython.inline @cython.exceptval(-1) def extend_buffer(self: array.array, stuff: cython.p_char, n: cython.Py_ssize_t) -> cython.int .. group-tab:: Cython .. code-block:: cython cdef inline int extend_buffer(array.array self, char* stuff, Py_ssize_t n) except -1 Efficient appending of new data of same type (e.g. of same array type) ``n``: number of elements (not number of bytes!) ---- .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc @cython.inline @cython.exceptval(-1) def extend(self: array.array, other: array.array) -> cython.int .. group-tab:: Cython .. code-block:: cython cdef inline int extend(array.array self, array.array other) except -1 Extend array with data from another array; types must match. ---- .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc @cython.inline def zero(self: array.array) -> cython.void .. group-tab:: Cython .. code-block:: cython cdef inline void zero(array.array self) Set all elements of array to zero. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/tutorial/caveats.rst0000644000175100001770000000163000000000000021336 0ustar00runnerdocker00000000000000Caveats ======= Since Cython mixes C and Python semantics, some things may be a bit surprising or unintuitive. Work always goes on to make Cython more natural for Python users, so this list may change in the future. - Given two typed ``int`` variables ``a`` and ``b``, ``a % b`` has the same sign as the second argument (following Python semantics) rather than having the same sign as the first (as in C). The C behavior can be obtained, at some speed gain, by enabling the cdivision directive (versions prior to Cython 0.12 always followed C semantics). - Care is needed with unsigned types. ``cdef unsigned n = 10; print(range(-n, n))`` will print an empty list, since ``-n`` wraps around to a large positive integer prior to being passed to the ``range`` function. - Python's ``float`` type actually wraps C ``double`` values, and the ``int`` type in Python 2.x wraps C ``long`` values. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/tutorial/cdef_classes.rst0000644000175100001770000001401500000000000022327 0ustar00runnerdocker00000000000000*********************************** Extension types (aka. cdef classes) *********************************** .. include:: ../two-syntax-variants-used To support object-oriented programming, Cython supports writing normal Python classes exactly as in Python: .. literalinclude:: ../../examples/tutorial/cdef_classes/math_function.py Based on what Python calls a "built-in type", however, Cython supports a second kind of class: *extension types*, sometimes referred to as "cdef classes" due to the Cython language keywords used for their declaration. They are somewhat restricted compared to Python classes, but are generally more memory efficient and faster than generic Python classes. The main difference is that they use a C struct to store their fields and methods instead of a Python dict. This allows them to store arbitrary C types in their fields without requiring a Python wrapper for them, and to access fields and methods directly at the C level without passing through a Python dictionary lookup. Normal Python classes can inherit from cdef classes, but not the other way around. Cython requires to know the complete inheritance hierarchy in order to lay out their C structs, and restricts it to single inheritance. Normal Python classes, on the other hand, can inherit from any number of Python classes and extension types, both in Cython code and pure Python code. .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/cdef_classes/math_function_2.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/cdef_classes/math_function_2.pyx The ``cpdef`` command (or ``@cython.ccall`` in Python syntax) makes two versions of the method available; one fast for use from Cython and one slower for use from Python. Now we can add subclasses of the ``Function`` class that implement different math functions in the same ``evaluate()`` method. Then: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/cdef_classes/sin_of_square.py :caption: sin_of_square.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/cdef_classes/sin_of_square.pyx :caption: sin_of_square.pyx This does slightly more than providing a python wrapper for a cdef method: unlike a cdef method, a cpdef method is fully overridable by methods and instance attributes in Python subclasses. This adds a little calling overhead compared to a cdef method. To make the class definitions visible to other modules, and thus allow for efficient C-level usage and inheritance outside of the module that implements them, we define them in a ``.pxd`` file with the same name as the module. Note that we are using Cython syntax here, not Python syntax. .. literalinclude:: ../../examples/tutorial/cdef_classes/sin_of_square.pxd :caption: sin_of_square.pxd With this way to implement different functions as subclasses with fast, Cython callable methods, we can now pass these ``Function`` objects into an algorithm for numeric integration, that evaluates an arbitrary user provided function over a value interval. Using this, we can now change our integration example: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/cdef_classes/integrate.py :caption: integrate.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/cdef_classes/integrate.pyx :caption: integrate.pyx We can even pass in a new ``Function`` defined in Python space, which overrides the Cython implemented method of the base class:: >>> import integrate >>> class MyPolynomial(integrate.Function): ... def evaluate(self, x): ... return 2*x*x + 3*x - 10 ... >>> integrate(MyPolynomial(), 0, 1, 10000) -7.8335833300000077 Since ``evaluate()`` is a Python method here, which requires Python objects as input and output, this is several times slower than the straight C call to the Cython method, but still faster than a plain Python variant. This shows how large the speed-ups can easily be when whole computational loops are moved from Python code into a Cython module. Some notes on our new implementation of ``evaluate``: - The fast method dispatch here only works because ``evaluate`` was declared in ``Function``. Had ``evaluate`` been introduced in ``SinOfSquareFunction``, the code would still work, but Cython would have used the slower Python method dispatch mechanism instead. - In the same way, had the argument ``f`` not been typed, but only been passed as a Python object, the slower Python dispatch would be used. - Since the argument is typed, we need to check whether it is ``None``. In Python, this would have resulted in an ``AttributeError`` when the ``evaluate`` method was looked up, but Cython would instead try to access the (incompatible) internal structure of ``None`` as if it were a ``Function``, leading to a crash or data corruption. There is a *compiler directive* ``nonecheck`` which turns on checks for this, at the cost of decreased speed. Here's how compiler directives are used to dynamically switch on or off ``nonecheck``: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/cdef_classes/nonecheck.py :caption: nonecheck.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/cdef_classes/nonecheck.pyx :caption: nonecheck.pyx Attributes in cdef classes behave differently from attributes in regular classes: - All attributes must be pre-declared at compile-time - Attributes are by default only accessible from Cython (typed access) - Properties can be declared to expose dynamic attributes to Python-space .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/cdef_classes/wave_function.py :caption: wave_function.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/cdef_classes/wave_function.pyx :caption: wave_function.pyx ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/tutorial/clibraries.rst0000644000175100001770000007544400000000000022045 0ustar00runnerdocker00000000000000 .. _using_c_libraries: ****************** Using C libraries ****************** .. include:: ../two-syntax-variants-used Apart from writing fast code, one of the main use cases of Cython is to call external C libraries from Python code. As Cython code compiles down to C code itself, it is actually trivial to call C functions directly in the code. The following gives a complete example for using (and wrapping) an external C library in Cython code, including appropriate error handling and considerations about designing a suitable API for Python and Cython code. Imagine you need an efficient way to store integer values in a FIFO queue. Since memory really matters, and the values are actually coming from C code, you cannot afford to create and store Python ``int`` objects in a list or deque. So you look out for a queue implementation in C. After some web search, you find the C-algorithms library [CAlg]_ and decide to use its double ended queue implementation. To make the handling easier, however, you decide to wrap it in a Python extension type that can encapsulate all memory management. .. [CAlg] Simon Howard, C Algorithms library, https://fragglet.github.io/c-algorithms/ Defining external declarations ============================== You can download CAlg `here `_. The C API of the queue implementation, which is defined in the header file :file:`c-algorithms/src/queue.h`, essentially looks like this: .. literalinclude:: ../../examples/tutorial/clibraries/c-algorithms/src/queue.h :language: C :caption: queue.h To get started, the first step is to redefine the C API in a ``.pxd`` file, say, :file:`cqueue.pxd`: .. literalinclude:: ../../examples/tutorial/clibraries/cqueue.pxd :caption: cqueue.pxd Note how these declarations are almost identical to the header file declarations, so you can often just copy them over. However, you do not need to provide *all* declarations as above, just those that you use in your code or in other declarations, so that Cython gets to see a sufficient and consistent subset of them. Then, consider adapting them somewhat to make them more comfortable to work with in Cython. Specifically, you should take care of choosing good argument names for the C functions, as Cython allows you to pass them as keyword arguments. Changing them later on is a backwards incompatible API modification. Choosing good names right away will make these functions more pleasant to work with from Cython code. One noteworthy difference to the header file that we use above is the declaration of the ``Queue`` struct in the first line. ``Queue`` is in this case used as an *opaque handle*; only the library that is called knows what is really inside. Since no Cython code needs to know the contents of the struct, we do not need to declare its contents, so we simply provide an empty definition (as we do not want to declare the ``_Queue`` type which is referenced in the C header) [#]_. .. [#] There's a subtle difference between ``cdef struct Queue: pass`` and ``ctypedef struct Queue: pass``. The former declares a type which is referenced in C code as ``struct Queue``, while the latter is referenced in C as ``Queue``. This is a C language quirk that Cython is not able to hide. Most modern C libraries use the ``ctypedef`` kind of struct. Another exception is the last line. The integer return value of the ``queue_is_empty()`` function is actually a C boolean value, i.e. the only interesting thing about it is whether it is non-zero or zero, indicating if the queue is empty or not. This is best expressed by Cython's ``bint`` type, which is a normal ``int`` type when used in C but maps to Python's boolean values ``True`` and ``False`` when converted to a Python object. This way of tightening declarations in a ``.pxd`` file can often simplify the code that uses them. It is good practice to define one ``.pxd`` file for each library that you use, and sometimes even for each header file (or functional group) if the API is large. That simplifies their reuse in other projects. Sometimes, you may need to use C functions from the standard C library, or want to call C-API functions from CPython directly. For common needs like this, Cython ships with a set of standard ``.pxd`` files that provide these declarations in a readily usable way that is adapted to their use in Cython. The main packages are ``cpython``, ``libc`` and ``libcpp``. The NumPy library also has a standard ``.pxd`` file ``numpy``, as it is often used in Cython code. See Cython's ``Cython/Includes/`` source package for a complete list of provided ``.pxd`` files. Writing a wrapper class ======================= After declaring our C library's API, we can start to design the Queue class that should wrap the C queue. It will live in a file called :file:`queue.pyx`/:file:`queue.py`. [#]_ .. [#] Note that the name of the ``.pyx``/``.py`` file must be different from the :file:`cqueue.pxd` file with declarations from the C library, as both do not describe the same code. A ``.pxd`` file next to a ``.pyx``/``.py`` file with the same name defines exported declarations for code in the ``.pyx``/``.py`` file. As the :file:`cqueue.pxd` file contains declarations of a regular C library, there must not be a ``.pyx``/``.py`` file with the same name that Cython associates with it. Here is a first start for the Queue class: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/clibraries/queue.py :caption: queue.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/clibraries/queue.pyx :caption: queue.pyx Note that it says ``__cinit__`` rather than ``__init__``. While ``__init__`` is available as well, it is not guaranteed to be run (for instance, one could create a subclass and forget to call the ancestor's constructor). Because not initializing C pointers often leads to hard crashes of the Python interpreter, Cython provides ``__cinit__`` which is *always* called immediately on construction, before CPython even considers calling ``__init__``, and which therefore is the right place to initialise static attributes (``cdef`` fields) of the new instance. However, as ``__cinit__`` is called during object construction, ``self`` is not fully constructed yet, and one must avoid doing anything with ``self`` but assigning to static attributes (``cdef`` fields). Note also that the above method takes no parameters, although subtypes may want to accept some. A no-arguments ``__cinit__()`` method is a special case here that simply does not receive any parameters that were passed to a constructor, so it does not prevent subclasses from adding parameters. If parameters are used in the signature of ``__cinit__()``, they must match those of any declared ``__init__`` method of classes in the class hierarchy that are used to instantiate the type. Memory management ================= Before we continue implementing the other methods, it is important to understand that the above implementation is not safe. In case anything goes wrong in the call to ``queue_new()``, this code will simply swallow the error, so we will likely run into a crash later on. According to the documentation of the ``queue_new()`` function, the only reason why the above can fail is due to insufficient memory. In that case, it will return ``NULL``, whereas it would normally return a pointer to the new queue. The Python way to get out of this is to raise a ``MemoryError`` [#]_. We can thus change the init function as follows: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/clibraries/queue2.py :caption: queue.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/clibraries/queue2.pyx :caption: queue.pyx .. [#] In the specific case of a ``MemoryError``, creating a new exception instance in order to raise it may actually fail because we are running out of memory. Luckily, CPython provides a C-API function ``PyErr_NoMemory()`` that safely raises the right exception for us. Cython automatically substitutes this C-API call whenever you write ``raise MemoryError`` or ``raise MemoryError()``. If you use an older version, you have to cimport the C-API function from the standard package ``cpython.exc`` and call it directly. The next thing to do is to clean up when the Queue instance is no longer used (i.e. all references to it have been deleted). To this end, CPython provides a callback that Cython makes available as a special method ``__dealloc__()``. In our case, all we have to do is to free the C Queue, but only if we succeeded in initialising it in the init method: .. tabs:: .. group-tab:: Pure Python .. code-block:: python def __dealloc__(self): if self._c_queue is not cython.NULL: cqueue.queue_free(self._c_queue) .. group-tab:: Cython .. code-block:: cython def __dealloc__(self): if self._c_queue is not NULL: cqueue.queue_free(self._c_queue) Compiling and linking ===================== At this point, we have a working Cython module that we can test. To compile it, we need to configure a ``setup.py`` script for setuptools. Here is the most basic script for compiling a Cython module .. tabs:: .. group-tab:: Pure Python .. code-block:: python from setuptools import Extension, setup from Cython.Build import cythonize setup( ext_modules = cythonize([Extension("queue", ["queue.py"])]) ) .. group-tab:: Cython .. code-block:: cython from setuptools import Extension, setup from Cython.Build import cythonize setup( ext_modules = cythonize([Extension("queue", ["queue.pyx"])]) ) To build against the external C library, we need to make sure Cython finds the necessary libraries. There are two ways to archive this. First we can tell setuptools where to find the c-source to compile the :file:`queue.c` implementation automatically. Alternatively, we can build and install C-Alg as system library and dynamically link it. The latter is useful if other applications also use C-Alg. Static Linking --------------- To build the c-code automatically we need to include compiler directives in :file:`queue.pyx`/:file:`queue.py` .. tabs:: .. group-tab:: Pure Python .. code-block:: python # distutils: sources = c-algorithms/src/queue.c # distutils: include_dirs = c-algorithms/src/ import cython from cython.cimports import cqueue @cython.cclass class Queue: _c_queue = cython.declare(cython.pointer(cqueue.Queue)) def __cinit__(self): self._c_queue = cqueue.queue_new() if self._c_queue is cython.NULL: raise MemoryError() def __dealloc__(self): if self._c_queue is not cython.NULL: cqueue.queue_free(self._c_queue) .. group-tab:: Cython .. code-block:: cython # distutils: sources = c-algorithms/src/queue.c # distutils: include_dirs = c-algorithms/src/ cimport cqueue cdef class Queue: cdef cqueue.Queue* _c_queue def __cinit__(self): self._c_queue = cqueue.queue_new() if self._c_queue is NULL: raise MemoryError() def __dealloc__(self): if self._c_queue is not NULL: cqueue.queue_free(self._c_queue) The ``sources`` compiler directive gives the path of the C files that setuptools is going to compile and link (statically) into the resulting extension module. In general all relevant header files should be found in ``include_dirs``. Now we can build the project using: .. code-block:: bash $ python setup.py build_ext -i And test whether our build was successful: .. code-block:: bash $ python -c 'import queue; Q = queue.Queue()' Dynamic Linking --------------- Dynamic linking is useful, if the library we are going to wrap is already installed on the system. To perform dynamic linking we first need to build and install c-alg. To build c-algorithms on your system: .. code-block:: bash $ cd c-algorithms $ sh autogen.sh $ ./configure $ make to install CAlg run: .. code-block:: bash $ make install Afterwards the file :file:`/usr/local/lib/libcalg.so` should exist. .. note:: This path applies to Linux systems and may be different on other platforms, so you will need to adapt the rest of the tutorial depending on the path where ``libcalg.so`` or ``libcalg.dll`` is on your system. In this approach we need to tell the setup script to link with an external library. To do so we need to extend the setup script to install change the extension setup from .. tabs:: .. group-tab:: Pure Python .. code-block:: python ext_modules = cythonize([Extension("queue", ["queue.py"])]) .. group-tab:: Cython .. code-block:: cython ext_modules = cythonize([Extension("queue", ["queue.pyx"])]) to .. tabs:: .. group-tab:: Pure Python .. code-block:: python ext_modules = cythonize([ Extension("queue", ["queue.py"], libraries=["calg"]) ]) .. group-tab:: Cython .. code-block:: cython ext_modules = cythonize([ Extension("queue", ["queue.pyx"], libraries=["calg"]) ]) Now we should be able to build the project using: .. code-block:: bash $ python setup.py build_ext -i If the `libcalg` is not installed in a 'normal' location, users can provide the required parameters externally by passing appropriate C compiler flags, such as: .. code-block:: bash CFLAGS="-I/usr/local/otherdir/calg/include" \ LDFLAGS="-L/usr/local/otherdir/calg/lib" \ python setup.py build_ext -i Before we run the module, we also need to make sure that `libcalg` is in the `LD_LIBRARY_PATH` environment variable, e.g. by setting: .. code-block:: bash $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib Once we have compiled the module for the first time, we can now import it and instantiate a new Queue: .. code-block:: bash $ export PYTHONPATH=. $ python -c 'import queue; Q = queue.Queue()' However, this is all our Queue class can do so far, so let's make it more usable. Mapping functionality --------------------- Before implementing the public interface of this class, it is good practice to look at what interfaces Python offers, e.g. in its ``list`` or ``collections.deque`` classes. Since we only need a FIFO queue, it's enough to provide the methods ``append()``, ``peek()`` and ``pop()``, and additionally an ``extend()`` method to add multiple values at once. Also, since we already know that all values will be coming from C, it's best to provide only ``cdef``/``@cfunc`` methods for now, and to give them a straight C interface. In C, it is common for data structures to store data as a ``void*`` to whatever data item type. Since we only want to store ``int`` values, which usually fit into the size of a pointer type, we can avoid additional memory allocations through a trick: we cast our ``int`` values to ``void*`` and vice versa, and store the value directly as the pointer value. Here is a simple implementation for the ``append()`` method: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc def append(self, value: cython.int): cqueue.queue_push_tail(self._c_queue, cython.cast(cython.p_void, value)) .. group-tab:: Cython .. code-block:: cython cdef append(self, int value): cqueue.queue_push_tail(self._c_queue, value) Again, the same error handling considerations as for the ``__cinit__()`` method apply, so that we end up with this implementation instead: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc def append(self, value: cython.int): if not cqueue.queue_push_tail(self._c_queue, cython.cast(cython.p_void, value)): raise MemoryError() .. group-tab:: Cython .. code-block:: cython cdef append(self, int value): if not cqueue.queue_push_tail(self._c_queue, value): raise MemoryError() Adding an ``extend()`` method should now be straight forward: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc def extend(self, values: cython.p_int, count: cython.size_t): """Append all ints to the queue. """ value: cython.int for value in values[:count]: # Slicing pointer to limit the iteration boundaries. self.append(value) .. group-tab:: Cython .. code-block:: cython cdef extend(self, int* values, size_t count): """Append all ints to the queue. """ cdef int value for value in values[:count]: # Slicing pointer to limit the iteration boundaries. self.append(value) This becomes handy when reading values from a C array, for example. So far, we can only add data to the queue. The next step is to write the two methods to get the first element: ``peek()`` and ``pop()``, which provide read-only and destructive read access respectively. To avoid compiler warnings when casting ``void*`` to ``int`` directly, we use an intermediate data type that is big enough to hold a ``void*``. Here, ``Py_ssize_t``: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc def peek(self) -> cython.int: return cython.cast(cython.Py_ssize_t, cqueue.queue_peek_head(self._c_queue)) @cython.cfunc def pop(self) -> cython.int: return cython.cast(cython.Py_ssize_t, cqueue.queue_pop_head(self._c_queue)) .. group-tab:: Cython .. code-block:: cython cdef int peek(self): return cqueue.queue_peek_head(self._c_queue) cdef int pop(self): return cqueue.queue_pop_head(self._c_queue) Normally, in C, we risk losing data when we convert a larger integer type to a smaller integer type without checking the boundaries, and ``Py_ssize_t`` may be a larger type than ``int``. But since we control how values are added to the queue, we already know that all values that are in the queue fit into an ``int``, so the above conversion from ``void*`` to ``Py_ssize_t`` to ``int`` (the return type) is safe by design. Handling errors --------------- Now, what happens when the queue is empty? According to the documentation, the functions return a ``NULL`` pointer, which is typically not a valid value. But since we are simply casting to and from ints, we cannot distinguish anymore if the return value was ``NULL`` because the queue was empty or because the value stored in the queue was ``0``. In Cython code, we want the first case to raise an exception, whereas the second case should simply return ``0``. To deal with this, we need to special case this value, and check if the queue really is empty or not: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc def peek(self) -> cython.int: value: cython.int = cython.cast(cython.Py_ssize_t, cqueue.queue_peek_head(self._c_queue)) if value == 0: # this may mean that the queue is empty, or # that it happens to contain a 0 value if cqueue.queue_is_empty(self._c_queue): raise IndexError("Queue is empty") return value .. group-tab:: Cython .. code-block:: cython cdef int peek(self): cdef int value = cqueue.queue_peek_head(self._c_queue) if value == 0: # this may mean that the queue is empty, or # that it happens to contain a 0 value if cqueue.queue_is_empty(self._c_queue): raise IndexError("Queue is empty") return value Note how we have effectively created a fast path through the method in the hopefully common cases that the return value is not ``0``. Only that specific case needs an additional check if the queue is empty. If the ``peek`` function was a Python function returning a Python object value, CPython would simply return ``NULL`` internally instead of a Python object to indicate an exception, which would immediately be propagated by the surrounding code. The problem is that the return type is ``int`` and any ``int`` value is a valid queue item value, so there is no way to explicitly signal an error to the calling code. The only way calling code can deal with this situation is to call ``PyErr_Occurred()`` when returning from a function to check if an exception was raised, and if so, propagate the exception. This obviously has a performance penalty. Cython therefore uses a dedicated value that it implicitly returns in the case of an exception, so that the surrounding code only needs to check for an exception when receiving this exact value. By default, the value ``-1`` is used as the exception return value. All other return values will be passed through almost without a penalty, thus again creating a fast path for 'normal' values. See :ref:`error_return_values` for more details. Now that the ``peek()`` method is implemented, the ``pop()`` method also needs adaptation. Since it removes a value from the queue, however, it is not enough to test if the queue is empty *after* the removal. Instead, we must test it on entry: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc def pop(self) -> cython.int: if cqueue.queue_is_empty(self._c_queue): raise IndexError("Queue is empty") return cython.cast(cython.Py_ssize_t, cqueue.queue_pop_head(self._c_queue)) .. group-tab:: Cython .. code-block:: cython cdef int pop(self): if cqueue.queue_is_empty(self._c_queue): raise IndexError("Queue is empty") return cqueue.queue_pop_head(self._c_queue) The return value for exception propagation is declared exactly as for ``peek()``. Lastly, we can provide the Queue with an emptiness indicator in the normal Python way by implementing the ``__bool__()`` special method (note that Python 2 calls this method ``__nonzero__``, whereas Cython code can use either name):: def __bool__(self): return not cqueue.queue_is_empty(self._c_queue) Note that this method returns either ``True`` or ``False`` as we declared the return type of the ``queue_is_empty()`` function as ``bint`` in :file:`cqueue.pxd`. Testing the result ------------------ Now that the implementation is complete, you may want to write some tests for it to make sure it works correctly. Especially doctests are very nice for this purpose, as they provide some documentation at the same time. To enable doctests, however, you need a Python API that you can call. C methods are not visible from Python code, and thus not callable from doctests. A quick way to provide a Python API for the class is to change the methods from ``cdef``/``@cfunc`` to ``cpdef``/``@ccall``. This will let Cython generate two entry points, one that is callable from normal Python code using the Python call semantics and Python objects as arguments, and one that is callable from C code with fast C semantics and without requiring intermediate argument conversion from or to Python types. Note that ``cpdef``/``@ccall`` methods ensure that they can be appropriately overridden by Python methods even when they are called from Cython. This adds a tiny overhead compared to ``cdef``/``@cfunc`` methods. Now that we have both a C-interface and a Python interface for our class, we should make sure that both interfaces are consistent. Python users would expect an ``extend()`` method that accepts arbitrary iterables, whereas C users would like to have one that allows passing C arrays and C memory. Both signatures are incompatible. We will solve this issue by considering that in C, the API could also want to support other input types, e.g. arrays of ``long`` or ``char``, which is usually supported with differently named C API functions such as ``extend_ints()``, ``extend_longs()``, ``extend_chars()``, etc. This allows us to free the method name ``extend()`` for the duck typed Python method, which can accept arbitrary iterables. The following listing shows the complete implementation that uses ``cpdef``/``@ccall`` methods where possible: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/clibraries/queue3.py :caption: queue.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/clibraries/queue3.pyx :caption: queue.pyx Now we can test our Queue implementation using a python script, for example here :file:`test_queue.py`: .. literalinclude:: ../../examples/tutorial/clibraries/test_queue.py As a quick test with 10000 numbers on the author's machine indicates, using this Queue from Cython code with C ``int`` values is about five times as fast as using it from Cython code with Python object values, almost eight times faster than using it from Python code in a Python loop, and still more than twice as fast as using Python's highly optimised ``collections.deque`` type from Cython code with Python integers. Callbacks --------- Let's say you want to provide a way for users to pop values from the queue up to a certain user defined event occurs. To this end, you want to allow them to pass a predicate function that determines when to stop, e.g.:: def pop_until(self, predicate): while not predicate(self.peek()): self.pop() Now, let us assume for the sake of argument that the C queue provides such a function that takes a C callback function as predicate. The API could look as follows:: /* C type of a predicate function that takes a queue value and returns * -1 for errors * 0 for reject * 1 for accept */ typedef int (*predicate_func)(void* user_context, QueueValue data); /* Pop values as long as the predicate evaluates to true for them, * returns -1 if the predicate failed with an error and 0 otherwise. */ int queue_pop_head_until(Queue *queue, predicate_func predicate, void* user_context); It is normal for C callback functions to have a generic :c:type:`void*` argument that allows passing any kind of context or state through the C-API into the callback function. We will use this to pass our Python predicate function. First, we have to define a callback function with the expected signature that we can pass into the C-API function: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc @cython.exceptval(check=False) def evaluate_predicate(context: cython.p_void, value: cqueue.QueueValue) -> cython.int: "Callback function that can be passed as predicate_func" try: # recover Python function object from void* argument func = cython.cast(object, context) # call function, convert result into 0/1 for True/False return bool(func(cython.cast(int, value))) except: # catch any Python errors and return error indicator return -1 .. note:: ``@cfunc`` functions in pure python are defined as ``@exceptval(-1, check=True)`` by default. Since ``evaluate_predicate()`` should be passed to function as parameter, we need to turn off exception checking entirely. .. group-tab:: Cython .. code-block:: cython cdef int evaluate_predicate(void* context, cqueue.QueueValue value): "Callback function that can be passed as predicate_func" try: # recover Python function object from void* argument func = context # call function, convert result into 0/1 for True/False return bool(func(value)) except: # catch any Python errors and return error indicator return -1 The main idea is to pass a pointer (a.k.a. borrowed reference) to the function object as the user context argument. We will call the C-API function as follows: .. tabs:: .. group-tab:: Pure Python .. code-block:: python def pop_until(self, python_predicate_function): result = cqueue.queue_pop_head_until( self._c_queue, evaluate_predicate, cython.cast(cython.p_void, python_predicate_function)) if result == -1: raise RuntimeError("an error occurred") .. group-tab:: Cython .. code-block:: cython def pop_until(self, python_predicate_function): result = cqueue.queue_pop_head_until( self._c_queue, evaluate_predicate, python_predicate_function) if result == -1: raise RuntimeError("an error occurred") The usual pattern is to first cast the Python object reference into a :c:type:`void*` to pass it into the C-API function, and then cast it back into a Python object in the C predicate callback function. The cast to :c:type:`void*` creates a borrowed reference. On the cast to ````, Cython increments the reference count of the object and thus converts the borrowed reference back into an owned reference. At the end of the predicate function, the owned reference goes out of scope again and Cython discards it. The error handling in the code above is a bit simplistic. Specifically, any exceptions that the predicate function raises will essentially be discarded and only result in a plain ``RuntimeError()`` being raised after the fact. This can be improved by storing away the exception in an object passed through the context parameter and re-raising it after the C-API function has returned ``-1`` to indicate the error. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/tutorial/cython_tutorial.rst0000644000175100001770000004277600000000000023157 0ustar00runnerdocker00000000000000.. highlight:: cython .. _tutorial: ************** Basic Tutorial ************** .. include:: ../two-syntax-variants-used The Basics of Cython ==================== The fundamental nature of Cython can be summed up as follows: Cython is Python with C data types. Cython is Python: Almost any piece of Python code is also valid Cython code. (There are a few :ref:`cython-limitations`, but this approximation will serve for now.) The Cython compiler will convert it into C code which makes equivalent calls to the Python/C API. But Cython is much more than that, because parameters and variables can be declared to have C data types. Code which manipulates :term:`Python values` and C values can be freely intermixed, with conversions occurring automatically wherever possible. Reference count maintenance and error checking of Python operations is also automatic, and the full power of Python's exception handling facilities, including the try-except and try-finally statements, is available to you -- even in the midst of manipulating C data. Cython Hello World =================== As Cython can accept almost any valid python source file, one of the hardest things in getting started is just figuring out how to compile your extension. So lets start with the canonical python hello world:: print("Hello World") Save this code in a file named :file:`helloworld.pyx`. Now we need to create the :file:`setup.py`, which is like a python Makefile (for more information see :ref:`compilation`). Your :file:`setup.py` should look like:: from setuptools import setup from Cython.Build import cythonize setup( ext_modules = cythonize("helloworld.pyx") ) To use this to build your Cython file use the commandline options: .. code-block:: text $ python setup.py build_ext --inplace Which will leave a file in your local directory called :file:`helloworld.so` in unix or :file:`helloworld.pyd` in Windows. Now to use this file: start the python interpreter and simply import it as if it was a regular python module:: >>> import helloworld Hello World Congratulations! You now know how to build a Cython extension. But so far this example doesn't really give a feeling why one would ever want to use Cython, so lets create a more realistic example. :mod:`pyximport`: Cython Compilation for Developers --------------------------------------------------- If your module doesn't require any extra C libraries or a special build setup, then you can use the pyximport module, originally developed by Paul Prescod, to load .pyx files directly on import, without having to run your :file:`setup.py` file each time you change your code. It is shipped and installed with Cython and can be used like this:: >>> import pyximport; pyximport.install() >>> import helloworld Hello World The :ref:`Pyximport` module also has experimental compilation support for normal Python modules. This allows you to automatically run Cython on every .pyx and .py module that Python imports, including the standard library and installed packages. Cython will still fail to compile a lot of Python modules, in which case the import mechanism will fall back to loading the Python source modules instead. The .py import mechanism is installed like this:: >>> pyximport.install(pyimport=True) Note that it is not recommended to let :ref:`Pyximport` build code on end user side as it hooks into their import system. The best way to cater for end users is to provide pre-built binary packages in the `wheel `_ packaging format. Fibonacci Fun ============== From the official Python tutorial a simple fibonacci function is defined as: .. literalinclude:: ../../examples/tutorial/cython_tutorial/fib.pyx Now following the steps for the Hello World example we first rename the file to have a `.pyx` extension, lets say :file:`fib.pyx`, then we create the :file:`setup.py` file. Using the file created for the Hello World example, all that you need to change is the name of the Cython filename, and the resulting module name, doing this we have:: from setuptools import setup from Cython.Build import cythonize setup( ext_modules=cythonize("fib.pyx"), ) Build the extension with the same command used for the helloworld.pyx: .. code-block:: text $ python setup.py build_ext --inplace And use the new extension with:: >>> import fib >>> fib.fib(2000) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 .. _primes: Primes ======= Here's a small example showing some of what can be done. It's a routine for finding prime numbers. You tell it how many primes you want, and it returns them as a Python list. .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.py :linenos: :caption: primes.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx :linenos: :caption: primes.pyx You'll see that it starts out just like a normal Python function definition, except that the parameter ``nb_primes`` is declared to be of type ``int``. This means that the object passed will be converted to a C integer (or a ``TypeError.`` will be raised if it can't be). Now, let's dig into the core of the function: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.py :lines: 2,3 :dedent: :lineno-start: 2 .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.py :lines: 11,12 :dedent: :lineno-start: 11 Lines 2, 3, 11 and 12 use the variable annotations to define some local C variables. The result is stored in the C array ``p`` during processing, and will be copied into a Python list at the end (line 26). .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx :lines: 2,3 :dedent: :lineno-start: 2 Lines 2 and 3 use the ``cdef`` statement to define some local C variables. The result is stored in the C array ``p`` during processing, and will be copied into a Python list at the end (line 26). .. NOTE:: You cannot create very large arrays in this manner, because they are allocated on the C function call :term:`stack`, which is a rather precious and scarce resource. To request larger arrays, or even arrays with a length only known at runtime, you can learn how to make efficient use of :ref:`C memory allocation `, :ref:`Python arrays ` or :ref:`NumPy arrays ` with Cython. .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx :lines: 5,6 :dedent: :lineno-start: 5 As in C, declaring a static array requires knowing the size at compile time. We make sure the user doesn't set a value above 1000 (or we would have a segmentation fault, just like in C) .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.py :lines: 8,9 :dedent: :lineno-start: 8 When we run this code from Python, we have to initialize the items in the array. This is most easily done by filling it with zeros (as seen on line 8-9). When we compile this with Cython, on the other hand, the array will behave as in C. It is allocated on the function call stack with a fixed length of 1000 items that contain arbitrary data from the last time that memory was used. We will then overwrite those items in our calculation. .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.py :lines: 10-13 :dedent: :lineno-start: 10 .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx :lines: 10-13 :dedent: :lineno-start: 10 Lines 11-13 set up a while loop which will test numbers-candidates to primes until the required number of primes has been found. .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx :lines: 14-17 :dedent: :lineno-start: 14 Lines 15-16, which try to divide a candidate by all the primes found so far, are of particular interest. Because no Python objects are referred to, the loop is translated entirely into C code, and thus runs very fast. You will notice the way we iterate over the ``p`` C array. .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx :lines: 15 :dedent: :lineno-start: 15 The loop gets translated into a fast C loop and works just like iterating over a Python list or NumPy array. If you don't slice the C array with ``[:len_p]``, then Cython will loop over the 1000 elements of the array. .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx :lines: 19-23 :dedent: :lineno-start: 19 If no breaks occurred, it means that we found a prime, and the block of code after the ``else`` line 20 will be executed. We add the prime found to ``p``. If you find having an ``else`` after a for-loop strange, just know that it's a lesser known features of the Python language, and that Cython executes it at C speed for you. If the for-else syntax confuses you, see this excellent `blog post `_. .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx :lines: 25-27 :dedent: :lineno-start: 25 In line 26, before returning the result, we need to copy our C array into a Python list, because Python can't read C arrays. Cython can automatically convert many C types from and to Python types, as described in the documentation on :ref:`type conversion `, so we can use a simple list comprehension here to copy the C ``int`` values into a Python list of Python ``int`` objects, which Cython creates automatically along the way. You could also have iterated manually over the C array and used ``result_as_list.append(prime)``, the result would have been the same. You'll notice we declare a Python list exactly the same way it would be in Python. Because the variable ``result_as_list`` hasn't been explicitly declared with a type, it is assumed to hold a Python object, and from the assignment, Cython also knows that the exact type is a Python list. Finally, at line 27, a normal Python return statement returns the result list. .. tabs:: .. group-tab:: Pure Python Compiling primes.py with the Cython compiler produces an extension module which we can try out in the interactive interpreter as follows: .. group-tab:: Cython Compiling primes.pyx with the Cython compiler produces an extension module which we can try out in the interactive interpreter as follows: .. code-block:: python >>> import primes >>> primes.primes(10) [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] See, it works! And if you're curious about how much work Cython has saved you, take a look at the C code generated for this module. Cython has a way to visualise where interaction with Python objects and Python's C-API is taking place. For this, pass the ``annotate=True`` parameter to ``cythonize()``. It produces a HTML file. Let's see: .. tabs:: .. group-tab:: Pure Python .. figure:: htmlreport_py.png :scale: 90 % .. group-tab:: Cython .. figure:: htmlreport_pyx.png :scale: 90 % If a line is white, it means that the code generated doesn't interact with Python, so will run as fast as normal C code. The darker the yellow, the more Python interaction there is in that line. Those yellow lines will usually operate on Python objects, raise exceptions, or do other kinds of higher-level operations than what can easily be translated into simple and fast C code. The function declaration and return use the Python interpreter so it makes sense for those lines to be yellow. Same for the list comprehension because it involves the creation of a Python object. But the line ``if n % i == 0:``, why? We can examine the generated C code to understand: .. figure:: python_division.png We can see that some checks happen. Because Cython defaults to the Python behavior, the language will perform division checks at runtime, just like Python does. You can deactivate those checks by using the :ref:`compiler directives`. Now let's see if we get a speed increase even if there is a division check. Let's write the same program, but in Python: .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes_python.py :caption: primes_python.py / primes_python_compiled.py It is possible to take a plain (unannotated) ``.py`` file and to compile it with Cython. Let's create a copy of ``primes_python`` and name it ``primes_python_compiled`` to be able to compare it to the (non-compiled) Python module. Then we compile that file with Cython, without changing the code. Now the ``setup.py`` looks like this: .. tabs:: .. group-tab:: Pure Python .. code-block:: python from setuptools import setup from Cython.Build import cythonize setup( ext_modules=cythonize( ['primes.py', # Cython code file with primes() function 'primes_python_compiled.py'], # Python code file with primes() function annotate=True), # enables generation of the html annotation file ) .. group-tab:: Cython .. code-block:: python from setuptools import setup from Cython.Build import cythonize setup( ext_modules=cythonize( ['primes.pyx', # Cython code file with primes() function 'primes_python_compiled.py'], # Python code file with primes() function annotate=True), # enables generation of the html annotation file ) Now we can ensure that those two programs output the same values:: >>> import primes, primes_python, primes_python_compiled >>> primes_python.primes(1000) == primes.primes(1000) True >>> primes_python_compiled.primes(1000) == primes.primes(1000) True It's possible to compare the speed now:: python -m timeit -s "from primes_python import primes" "primes(1000)" 10 loops, best of 3: 23 msec per loop python -m timeit -s "from primes_python_compiled import primes" "primes(1000)" 100 loops, best of 3: 11.9 msec per loop python -m timeit -s "from primes import primes" "primes(1000)" 1000 loops, best of 3: 1.65 msec per loop The cythonize version of ``primes_python`` is 2 times faster than the Python one, without changing a single line of code. The Cython version is 13 times faster than the Python version! What could explain this? Multiple things: * In this program, very little computation happen at each line. So the overhead of the python interpreter is very important. It would be very different if you were to do a lot computation at each line. Using NumPy for example. * Data locality. It's likely that a lot more can fit in CPU cache when using C than when using Python. Because everything in python is an object, and every object is implemented as a dictionary, this is not very cache friendly. Usually the speedups are between 2x to 1000x. It depends on how much you call the Python interpreter. As always, remember to profile before adding types everywhere. Adding types makes your code less readable, so use them with moderation. Primes with C++ =============== With Cython, it is also possible to take advantage of the C++ language, notably, part of the C++ standard library is directly importable from Cython code. Let's see what our code becomes when using `vector `_ from the C++ standard library. .. note:: Vector in C++ is a data structure which implements a list or stack based on a resizeable C array. It is similar to the Python ``array`` type in the ``array`` standard library module. There is a method `reserve` available which will avoid copies if you know in advance how many elements you are going to put in the vector. For more details see `this page from cppreference `_. .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes_cpp.py :linenos: .. include:: ../cimport-warning .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes_cpp.pyx :linenos: The first line is a compiler directive. It tells Cython to compile your code to C++. This will enable the use of C++ language features and the C++ standard library. Note that it isn't possible to compile Cython code to C++ with `pyximport`. You should use a :file:`setup.py` or a notebook to run this example. You can see that the API of a vector is similar to the API of a Python list, and can sometimes be used as a drop-in replacement in Cython. For more details about using C++ with Cython, see :ref:`wrapping-cplusplus`. Language Details ================ For more about the Cython language, see :ref:`language-basics`. To dive right in to using Cython in a numerical computation context, see :ref:`memoryviews`. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/tutorial/data.py0000644000175100001770000000311300000000000020437 0ustar00runnerdocker00000000000000{ 'title': 'Cython Tutorial', 'paper_abstract': ''' Cython is a programming language based on Python with extra syntax to provide static type declarations. This takes advantage of the benefits of Python while allowing one to achieve the speed of C. In this paper we describe the Cython language and show how it can be used both to write optimized code and to interface with external C libraries. ''', 'authors': [ {'first_names': 'Stefan', 'surname': 'Behnel', 'address': '', 'country': 'Germany', 'email_address': 'stefan\_ml@behnel.de', 'institution': ''}, {'first_names': 'Robert W.', 'surname': 'Bradshaw', 'address': '', 'country': 'USA', 'email_address': 'robertwb@math.washington.edu', 'institution': '''University of Washington\\footnote{ Department of Mathematics, University of Washington, Seattle, WA, USA }'''}, {'first_names': 'Dag Sverre', 'surname': 'Seljebotn', 'address': '', 'country': 'Norway', 'email_address': 'dagss@student.matnat.uio.no', # I need three institutions w/ full address... leave it # all here until we get to editing stage 'institution': '''University of Oslo\\footnote{Institute of Theoretical Astrophysics, University of Oslo, P.O. Box 1029 Blindern, N-0315 Oslo, Norway}\\footnote{Department of Mathematics, University of Oslo, P.O. Box 1053 Blindern, N-0316 Oslo, Norway}\\footnote{Centre of Mathematics for Applications, University of Oslo, P.O. Box 1053 Blindern, N-0316 Oslo, Norway}'''} ], } ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/tutorial/embedding.rst0000644000175100001770000001653100000000000021634 0ustar00runnerdocker00000000000000.. highlight:: cython .. _embedding: ********************************************** Embedding Cython modules in C/C++ applications ********************************************** **This is a stub documentation page. PRs very welcome.** Quick links: * `CPython docs `_ * `Cython Wiki `_ * See the ``--embed`` option to the ``cython`` and ``cythonize`` frontends for generating a C main function and the `cython_freeze `_ script for merging multiple extension modules into one library. * `Embedding demo program `_ * See the documentation of the `module init function `_ in CPython and `PEP 489 `_ regarding the module initialisation mechanism in CPython 3.5 and later. Initialising your main module ============================= Most importantly, DO NOT call the module init function instead of importing the module. This is not the right way to initialise an extension module. (It was always wrong but used to work before, but since Python 3.5, it is wrong *and* no longer works.) For details, see the documentation of the `module init function `_ in CPython and `PEP 489 `_ regarding the module initialisation mechanism in CPython 3.5 and later. The `PyImport_AppendInittab() `_ function in CPython allows registering statically (or dynamically) linked extension modules for later imports. An example is given in the documentation of the module init function that is linked above. Embedding example code ====================== The following is a simple example that shows the main steps for embedding a Cython module (``embedded.pyx``) in Python 3.x. First, here is a Cython module that exports a C function to be called by external code. Note that the ``say_hello_from_python()`` function is declared as ``public`` to export it as a linker symbol that can be used by other C files, which in this case is ``embedded_main.c``. .. literalinclude:: ../../examples/tutorial/embedding/embedded.pyx The C ``main()`` function of your program could look like this: .. literalinclude:: ../../examples/tutorial/embedding/embedded_main.c :linenos: :language: c (Adapted from the `CPython documentation `_.) Instead of writing such a ``main()`` function yourself, you can also let Cython generate one into your module's C file with the ``cython --embed`` option. Or use the `cython_freeze `_ script to embed multiple modules. See the `embedding demo program `_ for a complete example setup. Be aware that your application will not contain any external dependencies that you use (including Python standard library modules) and so may not be truly portable. If you want to generate a portable application we recommend using a specialized tool (e.g. `PyInstaller `_ or `cx_freeze `_) to find and bundle these dependencies. Troubleshooting =============== Here's some of the things that can go wrong when embedding Cython code. Not initializing the Python interpreter --------------------------------------- Cython doesn't compile to "pure stand-alone C code". Instead Cython compiles to a bunch of Python C API calls that depend on the Python interpreter. Therefore, in your main function you *must* initialize the Python interpreter with ``Py_Initialize()``. You should do this as early as possible in your ``main()`` function. Very occasionally you may get away without it, for exceptionally simple programs. This is pure luck, and you should not rely on it. There is no "safe subset" of Cython that's designed to run without the interpreter. The consequence of not initializing the Python interpreter is likely to be crashes. You should only initialize the interpreter once - a lot of modules, including most Cython modules and Numpy, don't currently like being imported multiple times. Therefore if you're doing occasional Python/Cython calculations in a larger program what you *don't do* is:: void run_calculation() { Py_Initialize(); // Use Python/Cython code Py_Finalize(); } The chances are you will get mystery unexplained crashes. Not setting the Python path --------------------------- If your module imports anything (and possibly even if it doesn't) then it'll need the Python path set so it knows where to look for modules. Unlikely the standalone interpreter, embedded Python doesn't set this up automatically. ``PySys_SetPath(...)`` is the easiest way of doing this (just after ``Py_Initialize()`` ideally). You could also use ``PySys_GetObject("path")`` and then append to the list that it returns. if you forget to do this you will likely see import errors. Not importing the Cython module ------------------------------- Cython doesn't create standalone C code - it creates C code that's designed to be imported as a Cython module. The "import" function sets up a lot of the basic infrastructure necessary for you code to run. For example, strings are initialized at import time, and built-ins like ``print`` are found and stashed within your Cython module. Therefore, if you decide to skip the initialization and just go straight to running your public functions you will likely experience crashes (even for something as simple as using a string). InitTab ^^^^^^^ The preferred way to set up an extension module so that it's available for import in modern Python (>=3.5) is to use the `inittab mechanism `_ which is detailed in :ref:`elsewhere in the documentation `. This should be done before ``Py_Initialize()``. Forcing single-phase ^^^^^^^^^^^^^^^^^^^^ If for some reason you aren't able to add your module to the inittab before Python is initialized (a common reason is trying to import another Cython module built into a single shared library) then you can disable multi-phase initialization by defining ``CYTHON_PEP489_MULTI_PHASE_INIT=0`` for your C compiler (for gcc this would be ``-DCYTHON_PEP489_MULTI_PHASE_INIT=0`` at the command line). If you do this then you can run the module init function directly (``PyInit_`` on Python 3). *This really isn't the preferred option*. Working with multi-phase ^^^^^^^^^^^^^^^^^^^^^^^^ It is possible to run the multi-phase initialization manually yourself. One of the Cython developers has written a `guide showing how to do this `_. However, he considers it sufficiently hacky that it is only linked here, and not reproduced directly. It is an option though, if you're unable to use the inittab mechanism before initializing the interpreter. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.356722 Cython-3.0.8/docs/src/tutorial/external.rst0000644000175100001770000001271500000000000021540 0ustar00runnerdocker00000000000000Calling C functions ==================== .. include:: ../two-syntax-variants-used This tutorial describes shortly what you need to know in order to call C library functions from Cython code. For a longer and more comprehensive tutorial about using external C libraries, wrapping them and handling errors, see :doc:`clibraries`. For simplicity, let's start with a function from the standard C library. This does not add any dependencies to your code, and it has the additional advantage that Cython already defines many such functions for you. So you can just cimport and use them. For example, let's say you need a low-level way to parse a number from a ``char*`` value. You could use the ``atoi()`` function, as defined by the ``stdlib.h`` header file. This can be done as follows: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/external/atoi.py :caption: atoi.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/external/atoi.pyx :caption: atoi.pyx You can find a complete list of these standard cimport files in Cython's source package `Cython/Includes/ `_. They are stored in ``.pxd`` files, the standard way to provide reusable Cython declarations that can be shared across modules (see :ref:`sharing-declarations`). Cython also has a complete set of declarations for CPython's C-API. For example, to test at C compilation time which CPython version your code is being compiled with, you can do this: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/external/py_version_hex.py :caption: py_version_hex.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/external/py_version_hex.pyx :caption: py_version_hex.pyx .. _libc.math: Cython also provides declarations for the C math library: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/external/libc_sin.py :caption: libc_sin.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/external/libc_sin.pyx :caption: libc_sin.pyx Dynamic linking --------------- The libc math library is special in that it is not linked by default on some Unix-like systems, such as Linux. In addition to cimporting the declarations, you must configure your build system to link against the shared library ``m``. For setuptools, it is enough to add it to the ``libraries`` parameter of the ``Extension()`` setup: .. literalinclude:: ../../examples/tutorial/external/setup.py External declarations --------------------- If you want to access C code for which Cython does not provide a ready to use declaration, you must declare them yourself. For example, the above ``sin()`` function is defined as follows:: cdef extern from "math.h": double sin(double x) This declares the ``sin()`` function in a way that makes it available to Cython code and instructs Cython to generate C code that includes the ``math.h`` header file. The C compiler will see the original declaration in ``math.h`` at compile time, but Cython does not parse "math.h" and requires a separate definition. Just like the ``sin()`` function from the math library, it is possible to declare and call into any C library as long as the module that Cython generates is properly linked against the shared or static library. Note that you can easily export an external C function from your Cython module by declaring it as ``cpdef``. This generates a Python wrapper for it and adds it to the module dict. Here is a Cython module that provides direct access to the C ``sin()`` function for Python code: .. literalinclude:: ../../examples/tutorial/external/cpdef_sin.pyx You get the same result when this declaration appears in the ``.pxd`` file that belongs to the Cython module (i.e. that has the same name, see :ref:`sharing-declarations`). This allows the C declaration to be reused in other Cython modules, while still providing an automatically generated Python wrapper in this specific module. .. note:: External declarations must be placed in a ``.pxd`` file in Pure Python mode. Naming parameters ----------------- Both C and Cython support signature declarations without parameter names like this:: cdef extern from "string.h": char* strstr(const char*, const char*) However, this prevents Cython code from calling it with keyword arguments. It is therefore preferable to write the declaration like this instead: .. literalinclude:: ../../examples/tutorial/external/keyword_args.pyx You can now make it clear which of the two arguments does what in your call, thus avoiding any ambiguities and often making your code more readable: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/external/keyword_args_call.py :caption: keyword_args_call.py .. literalinclude:: ../../examples/tutorial/external/strstr.pxd :caption: strstr.pxd .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/external/keyword_args_call.pyx :caption: keyword_args_call.pyx Note that changing existing parameter names later is a backwards incompatible API modification, just as for Python code. Thus, if you provide your own declarations for external C or C++ functions, it is usually worth the additional bit of effort to choose the names of their arguments well. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/tutorial/htmlreport_py.png0000644000175100001770000022636700000000000022614 0ustar00runnerdocker00000000000000PNG  IHDR~Kv iCCPICC ProfileHT"Л@J$@(!Y\ "ʂ(@VQAŊ"tAu],Pyp}w͙3ϝ9sϹB"I3&60<-fd]Mη-&jJ|A6(D~6/xKr@CKrē|aIININb4z*&"aUd.W 3syɈak_(B322#$F>+;i&5d9Oe>lq:wy2ҥ=AN!3{iAr% ??)ҀHdצ qЏ#DX.cIf|$7[\̾ҴH?EDD8W5OiA31rD&_ O~+DΝ_ bhfs ||gb"/^Py _ APrCe |/F>L l2l,|;SL"LNa*09"l5;$ކM"he"5z_b)M>Z@cO*ɝM":P@ $3G <A`$` XւBP T 8&p5p 􀇠 ` D 2l!BP %@ɐB+uP1TU@P-+t :]4>( a-Y0#p2&Íy/1@P .ByBPq$ U*CՠQ-mT?%h +:桳ЫFmz Chb1.&Y)ĔacNb.bz0CX,5:aTrFnl ;pj8s. q;qqgqݸ!G< "|> ߊ C !',#l&#nD%1эAL%%}ķ$ILO֐IGIIOdeٛO7ϑR(#'%CDSS>*,8 | !M]DͣQSoR_*+O)*)єlB26*RLlW.PޫܮbTRJ?0bp͌cϳfg fmU?{U UOUjjjg5ZV&Ghu3K_TApiix kii.ܫy]sLK[_KS]6CS;UTU{D#)9d3ә Q]M]nn^^^#}>K?ITM@` :CaFFF덚sL(&&Y&5&wL,4ݦ`3J氹|yll٢5{-l\:Keee++8VV߬ӭY?Q ɷiyckf˳cG[ml^`az6Nz']N,:+u'Gc.Zr}6x`ξ9nzn\j~w{\'|lSv*0o|P>>E>ʾF l hqxZhS A𠊠'f3'B8!Bf6;?t~a6a+:i0$RE]c2Zz09?nl  .4^tEYL]]|<p( 7[K$Jyv^=D0T,-y[HGJYKB:5 *CZHځ |FB)(Mt!S;sif\\(rڞ5* φf7БDt =2㒨%Ǘ*--lنey~y,G/-o[b튁իUV.X=ĵiko[[@`M?*J {׻ vvnV/Zl]\Ve#o՟l~*ibSҦ͎lnmcms52KJm_J}Y;RRSUٰKs׆]vwwS_UU\gkjb}/j_/_j/@jjki\IFuHsE}u(8*=ׄ_ :vu]'i'eM)Mͱ]OuOWQ9Z:q69-n{~ .^wqW\ʺtZu'o88xf-[-]sZ=}εy=]w#ǿ~r?\Ӈ+zMow?33pIde)iٰp3gGFn=_|?Չ<>3:ZzƷjo6:}E>9//_M| 711!JS pRo@v zʠSOS^"|HKS"~Wɇ'M0^Vv֑}23T+C~VeXIfMM*iD~ASCIIScreenshotpiTXtXML:com.adobe.xmp 677 638 Screenshot sIDATxoUz~IHT8JщP*B"A@$;N1R8PV­\ N 6Cl~0cȲ֞5k\}ߙ5b0 cU`0 Q`0 F`0z `05 `ԛ.ٳt(ׯ_OC~e˖/_ .P555p֭{Fl?)B[w?~]_Q3xML2lذ3f~W/Q࿓'Of;3ݻp믿NC>ҕ-^xȑ&Mڶmۂ ~+X=s̋jիWw5-wϝ;#Ge֭Ͼ曉vٮe0^!EI,ҥ zCV:uTeݟ>zh"]ӠerR;{j=z|۷oٳ'9qDǏ=# ¬Dkz=f ݀PgIy׮]&} ާׯaÆ yE5!s=l͛7w~8|2~{:tΝ;BH}ݼyӿt9.dÇoWVV"C[2qĐb Nr9Md%SBwr Ezw*$so!3rWR'jooV]~ݕB! Q*Qouu5s8=1Fiظq#믣?"VSa%8p`59o[頹&^Ǎz gm6B* 1A>|^{͙\Hu֥K%Anڅ | L4 2瑛9sfqqKW,=myyyW #F)7n}Ŕ.}1\|Zu(ώIHm`Q;=wQ✷oF&Ç|0Yvmo.\H ǎy{뭷BG҄+%Kz CD.;wE#s"*'J$YQ裏v܌ m/Z>x ?M["WE#׏;M6{yqL 2!׍7c~SB08.JŋO>MI3TTY^>!'F8r ]9s=H4$ԻᆱH.Λ7=h{f]] n˧*1|`bg8uF?VH{WSK@9rd)/ qT|* _Jc'N𳨨H?!Z\| Q>:f̘@An߾~I>g޽SyϞ=F!Sꕓڵkխ#.B/X02dHOIsBإy oҰ `G4.~),]T?UH|_r%J[li @D&Af%SRAWSbqGٶ qyyy 7n\ZK&N_dVIV堾aTSjꗜ\|طwmzRH:1 Aׯ_ٚ 3yҥ%M@t2t+]oneRXQRe{pIIlwl*'iz9fgϖ/S҂TN7E"d i ;`0  4c&Og+qc{= `J@|dr//رDբ?|Lǜ]<>"MJxu#FQ/jǺu9?عοK_2&͛:hll|NnիW7'oӧU:{cmM^E?7lxr…Oo D1S137ܜsL]{:aNuu쯮i~fzy7&?kWNyy:ѪbwN^Ǐs9p D={>|ݻf8n޼Sǎ K*I$.Imno=K-^ /kq׮]S%>|*F)۵kWh7n8t͏?W\۷otR{ "ρ[L{w^pΝQݺu)ZK#?LSӵ9B/ eSVKKu۱ N0~3v\Ϭ9T/Z,)9=cn 4'gxOgN/O\&Io?3x3q._?=n~>ׯ_V_DVյkޭ[7jm.ڿnn.C8 44B 9_599|0l0mĉLb ;N!uժU.2R:R3ѣGKf$( 8&D%^Lյk׊7h$pBF)[om6lk?CzoIȴi0¹sgϞ$N`믿^TTj}/ѣGi;Cʜzb`g뢿L3œ,aDZq4zDVӧ?YQ!ϸDz޽'JhQ_5PZ2#R/E?߿< XH/zWݺuK?K 0ɓ'KKK:L-V@ۿS.]LzB"˼S: 셺2O>ď?g(5k?eee-&H\)V&Y , )"Bh|!z d;w-?fh".Dv5=͚HT;f:e6^꭯9TX{SGYcn17ְc gwU8:4 urdA6rdlb]ԋRS)|.-! ޻w/+[WWlu?]3MI[]\M1$ň;h STk*N4ɏ\eYY^LO2`LSstynܧ۷'vк{2}S#O?Mzo&\nSvl^~$,04oMn+0).4'5o^r@7;wy֧ϹskX4EE]HW¿M+KsV*%RommmIn+Vh #yHݻghVTT${a@|Z&o Nx+e:w+ׁCD K Roi6tճXv- P={綣Ff<ѽ(MzT׾)c MMM& /x&b\{~쑿ź? ߏ-njοNAr8#Ljh]#}ƝeIMMzeL={օܸqCә)|e;tPEsz! LwKB0(ÇSӄM: NݻwQ_e!;l0ߝ沣^M|/̾p¸qƍIwF|-5k\oԗnYݺul}tNGg۷bDž듶y5bd#2U_]])M&,ׄ`*Okt{ Xj#Gb…Aʉ{CPF^Mj޾[EH|I̶Vlkz)b7'>aKVY ?IQ \1v: PRdn[ ›ݻW&!Ck %ljT.C3aF"c jLC"'4LG<͜9S>(iĉmR&`⨙>l|oQ8lݺu$lkrE(fZcL1ܹ@߿%HS֠9Hqgq)>T 'Ƈ~Ej/4kA5Y %a4t#I:߾}ŋEƼH3t-e}B&5#tl_EZ`5nBt)%*J_/ArZL 2 }*\Oٱ[FD\`2NFii=ZXS E `P ;V 7ҽ;xAX!˘DSEDR8^n3S:ELJ!jyP$Ȝ9s6:[DE]/^LxBdNUdj>xh+oTGEh6[7n8T( ɓ'KJF%%%~Aa}K#JCǧt(^@>}:3zhAÆ4oq-7xƢ8Q /z=eFvK^zugؙ3g>W셃$MO֭[:#?W ]8,X@nݺ֗>x)BLY-"> Tϼ]rSKZ ܠ-ZfhN6-+K虈 Ɲ8L)"L2|VFLKð%~VQ5y$ GPzIy>כk kz!dS/n F"LڙS>I]t8>tBynwE6N8ݓ'OJtjV*;`jΚ5+;SV9`@'k #G$4(UjժNtXeR Nׅy]![bIk_ oGX~.#4:= $+(;@-HPrhK@ &2w"͊0PQ2JinnɿgQoVaRr Lz{=UZ$ՄL?]'i1[o)=~xK5UIjd";zKWIjxճ(#-7i`9s|z^b. HݻwO޿e;" T>oɘ^ۑc.rd-}GJ=:'zkpcQFUTT |tlQ/ 7}JGDˤKGJȁv%fϜ93j3FP\HH%.1 XZu*)@˗/wԛaء`Ӂ|' qޏʈEfZWh+9-\իW5;ӣ^%_S-zc 0*dYYYu+Ϟ=BhwDmMiUA:t()\D\CxpΝh!=GR)bۅSoHD^6N"HQ=WJͤ!p.(.cEݹޔՒR\d'pNd/jFlVJ F 5Dehn_Ǣ!ƍ'>$h&^L]WpPv(:oذ!S]zn:L>Lopܹs A d򸪌*޴iR2Ԡs-k׮u)'NPӱGAM2'O%birh#}>|xzY6xDc QghĪ.ͻti1'-Z@L)'N  4i-[(>ZBI1tU%8w\6&&EtZs!T5q(9dHD^Ըru<>2oplݺUðWAl[+3DH0yP,xO>io>ZZZJ7nIg(.5`#H1"-v-UUU-e o>d$jL B}떹0h̓o߾4p`#Ĩ"hz<\ɥ_l A=m}ΘniG:@v(3&zw: n"6o,Cһd ;ݟuc0k#~!2CxiB}o#;[DH!??jѵ[H$}Ƀ=ɕ&*7n-og BXmUN@[1ZZ'S .Tc\͐mxGQ@[..2tl.\+W$~ n"% lG4"@\~igT D+85/?8+°W@w@`>c3̲1&Z1}"ϩZիW/^kE[ODH @I 8^uu5TeeeѦϣڪ s2K9f/]In-.4^xlAe虋 Kw%Mں{=mRy^ `05 `0 Q`0 F`0z `05^j`0m7n\tiS^.Kk׮-V\'UUU%%%VzNvv c0 Q" FA@ksNm8ܹ~I&=zɒ%6lHzv[xޥ{4u!MmP}@R%=([c0~ԫ0ڝ5%wܡSh8fSxޥ{qP>Wz޽ g`yyy{zgr ïzC΀/vJ@dߎ;nH_K.GQp?~ڵkQ>THUU[f^7n:tڧۗW\}K.QLN[)0p-[ GUš]xS+++ۼy3 x-ݳgKL7īb[U4x"۷Ue, ꭨ/m5I)k .@WkKq$2#&Mr=N1cD^O?"ǝmW_6ϬO|1 ._?Dj뭷ڶmD 2}=?Uqԩ$(ؿȩBE*1;&cQ|PشqɄXͰtcڴinSҳgOe C /**uP8 Mga:L[VC R?G5Ι3ED)\zU0QC-aoذA{{Eu̙8lƌh6{u ݆q);zܹsN5K^5h"X!T Q'//ϑhD%ŇUPE)ۮ"իPS;'ю=5O ZNY9Ω]&R 9ydii)"xt#rl0|lڥY:}ڭByqx=`0ԫIgϞu!7nppE:>vSh\Duĉ0aBAAf-[\D[ZMbR× $Fdrh@dRA3\-[sŧ\Zu J;Ak(Լyg2O:cbʔ)X (!ׯ_DCq iC"И[cرE |{ܹcǎhL-))-r9 /\P I0R8xV5/gGro8ƍ"a>pr/>qV+W? ɤt?L  `|S2_<|…4^Eʂc|$M*"hKIsιs|.:ҫեޗH4(Y:'`݊"vl0 N%öm^RhSիW[75 NGYV`5Q'W ֯_OA9 `0 ^`0 F`0 `05 `0 ^`0 F`0 `05 `0 Q`0 F`0 `05 `0 Q`0 F`0 `05 `0 QM|rjҥ'O|NWTT̞=@Ϟwsrn~l]`0:;80'ݻwuKT.]s׽g&s&!jT#рxNsp͸X.xQHd(ra 5IAP |(" oa{}XkhߪŪnW_un//>*<88mR[[۟[qULL3_,:pВ?yIeffJӱ? H,++I\UWW9s&11177W+**PNee%-޸qd{.Y}򗔔 U444H3!C}}=j%c{i^ԤOFE:/O}֪*h|l ԺMMT))*AP!eeXު*mby:+Ku@3l$&6ss;0* TXr_Wgg2('G {Vyh>>Z0?. .Y,W^;;;2|OVR˞ÂS"D`U9rH9z(rAnK{^Docc#W#aLA&)z.m캜Р Ԗ xI:4IL@)C[}bѣ>E[^L8 ,mF4''V*pxR!Ù3gL쁦*#@).駟U4lB/p+R^*+̀իW@x={^RklPK`DI+J7?ޝ;hr{}ᒩG4/[$Cp*vzYYb1z;Bz}ѢŻF9Rދ/ҝT2&&?pƌԦ淁@HR}Qr{%K̂^OOO3_J!b0m2n߾)8LRZZ<()zCژ]_xTJK}!#C{ɓhԤd0@b`#miS)֭M!!,맍ޔ .\ D"pMMM2mll+x_X+fp-Z=+D؎:vڄ~K %Ҿ3L:::$E/͍CUUeX`RppؔyϞ=V98+WRm۶l7mjժ@/7YҔi D0-A%O?ZLù޺NM>] (6ӄ%5ȘΆ6EG7J(iy׮&8>-*zn$&3MsU..JMEJ?dX?iH %ĒbWrqq_3g(?=t 4$kkkMS0RT$ %&&$'@kqVj{V *JThnLzR`i'TWkəZZI7nߚfX?uk׮5uuuu'OxYYh={U̳T ݾ^XX($W`m+tz wFsg+\hWe|nC_Rw8 K⛾,SWSZ0,}%{-??ukn-Eb1zҾfN&qcbX,bX,eX,eX,bX,bX,bX,F/bX,F/bX^bX^b,b1zY,b1zY,bX,bX,eX,bX*F/bX^b]Unꭊ.ng> ˗5IIڿ,bjJDzss+**z/yᙴQӯ?ݗw|fGR  SbX^Ĥ<""-**ݰaChh(W*.m]Pz3i>kd$OܻWne*b1z5CCC???Բt^p=x_b2#zOݶ߯F?N_)iёE Y1<<=7z&!8}Q tMtUGoQlKkKusu@թ뺭J ZffMB\bEꪝ@j>]E&#CDh5MxÂd͂ڽ̛ XMXvTX,LѫT*AӢ>9j= re&Di@yO_[;(KyZЦMbśc68 75i&Lh(M?c;W$?~#蕆]VUk|X,ޒ4m4}Kp555zֲVU FJ{9,~̝C`Dbsc2v3䵩k wa("vn7\ںװsM`Z;6xlnu䕓c >'}|OfWfw][]Dim٣]gڬ ڠ<&8X`geEiII,vݻZK99.Ej+{aX,֋z ziUgEw&Q^Q,:r>p"bȹD`4 4zoS䇚l?FGbeSltWdVfii0i͛mqk5ڈz-,q6N4Iw6tij7bz5k֬q}[[[ L*zw]%лqUT/~ *߶voRv}HWBE!pEU.?m5];q#mwOW(4f" Kn_*xCB4eX@iLL ( Rzkk+Ĵ7nȶ{֯n韄BԜ6 3eg}/|qI_D}~}B/QEϥEXXb9BfE武[iHOuȫɣ;N_: (k-kʕ3RG6$^NܖBQm(V-ZFTtMl6?H,zѫP(̈[l/_7..)`>s΀"QvgLljPdٱḛ^]/yy膡.sh^BQ8Jpn 9;Q:V]ǎi)HHkGG?4RĴaf7hAAmG毨=| ^Za ҒvzK7?? ^U*Uk_>ClZHQT\ݳgj:9/Cji*ӜR5%%fY,링-wfrbf-^bX---}»_Uo Z Ӧi dX,F/bX,F/bX^bX^b,bz%%%8FMMMee%71bX^RiaaAW&EMqq174bX^///P~P+͓&M.++0a;74bX^CCC???_╕b zժU&eBB•+WY,zOβ<355?4׷7X,bvޒ4m4i$ hRhh(6Dzk>,b1zqqqqΝ;WΝ;~ۂ&t;b= qرc IHHgX,g455JcbbZxYJ㓚dnn"݊ `X,U(fff-[Hs\\lsfX,ǿfښh* rX,˿bX,bX,F/bX,F/bX/zM9p8p8p`vJJLƶOGbyIoUT{0ܷU  G\Q`G-sRG'%)c23G[[lnB8a8p`֎#Xka dUX؛"fԩ)~+u>(T4ѠbQ_,,<`&:zS8[[wߘs漎OLP n0\Ҕ&&>ܹ'y9WXƂ8z}\|ڨ._&&eW$ሀћ(P o1\ѯ\}Tƾm`Fϟze|;D\On)-5y: ?Νqq\ gAw?a֯~C_ytF^2Zfaq?5[Uӥ7x?2BlSa <;<-]"1|{pعvm`^EڳggedomlN$%9ڍ7bkDq%OWӧ%%*+2ܼife~c7NY8|ٴ.Z4Xڌh[$%̛7…QS3b7gú1]728#x]; ik`1fLZm}ȌaٯOJ%KYsA'{8  63 p\ßo!VV8 *ĬѨ*qGCŀ7 *L=th$9ukh71'bbqȏZ[3*Uo6C}NtuRXsV*3F{jj FGIwljߦ,-_:8 ߒh}(ALS "Ya6215&תe yhE&DuuFF'E)SNϴ]^V Rk#HMLJ5+ 64 4rPКe˶#ng@nڴԴ(:zQD 5<~-`$CD'ЋE4k/X(FMK* †*ЎNQqqҀ֢>ZA (BS "6hGf@;RcЂ&ƿ SwX|\! |niCPD\.ڐ6DXrHD_i506B-{GPi3"ϻ E;IEE@O_7498yDOW!~(ߔ 7`d#*sŻ}iS*{8)Usb4-V5k,W|{y,Hnw+-DGWVcߚexPTdD8Q$L3 X6NPw-Mug2U>c+gXIYpǏW2uK)A.K gLN0c(/C<|?._G<*jON6NJ7Rs#^_VJvLG=im;^`JYE Pm p^ߡ}͛&:>SFzPBHt㟜z=^ϙQj6)9`7|Rtc,t {*E1K ~o M쒮3[K?F@dŊGoe=!}-^Jts O-z$-0& +k0 ct$\KYČho l L,.fIX@5 t8qpx/8xJǎDw#GF"tJ5NG8pXY^o"?X4yno%4n wK##3+F#psd@ @W_}赲J4r]"]$$bVSRf7,~ڰk0"' 7؅%x{O^*g!4y ç;7 nΜq0gw`l^\CK:1+^O|X̙p{GZս+m_gИȀVøH;A/z;x<{@oJ_vXp!:Dd.,~x w>W7s[;5:{~/cV2#ڠUv@`K--~o ]Hya֭>E @/lnc^ʆ/G`?˳ [1yY]ZO}I%l'N|&~v|֙&<86 4;A7߼τ3c)uw{@bVX ?"Pɭ[ QT'T,P&J}Ş?? wh)@!˗00ƐW{t`4 :)'.>SAfz US1@i8.q!3%(h89e) {5ᛕӖ-ҽ W2A wvڦuYz&#8Smx xF*}ѓI><2]qѱ^c Gf$3g>a})uV&\ ۞>mGqqq 2:z"k}!cG<_c1tnio/C-LJOO0'q38@6A9l y`A0N/16?{vmlҹƸ-:Z;8hq͈瞠 61cpJGɲ{=l]QSNTӧi.G7wn֠yvj;ja)%3s4^ZZ~|g@ѣxDMS8q],="Gׅ]zժ}N**2;Jϻ"+Th-UݒU gOϰ㚚uu '9MW=;8z65 gtZ@q媪14ȫ0))1O#Kv!jңwa1Fa=ozI;3 7;{!{@K!?EkJ*Oߴ+L/6%C1O曷`yOrۃsKa-0|˗q.c,޾MBOs~¢0--_핟8ǵF/g;*jDA8p`r?X,M1zY,bX,B%%%MMM}#33ںT)+++))',}(RiaaA?&[{]SS>G,]3{tttFF,U:vXlbXB iꯋk />ج[}:񩡷-YY,'(n``~z)Dыb\үq...>ӧ߿'6n8M@7774B]#CNN+###enn> uV9sÇ;:{,J:u*֢zx*:44G- :X,ѫT*ӢX;w\t Pjzڵ}lmJJ 966V68q"2ڂ>N V_JUTT4e1Fl_ )E/̙ELJ}|Æ T͛i0a,ZXX,Ymڴ[`޽T7{{{GGGD5.bXGoII Ӣ5#0aY Govv61F߰0WqN"dG[ZZH DĆ666k֬pvaٲe733M޽bDEZGCǓ=]zIPcy{{w[gb덋=2{[[[[YY-E!f=?ѫ=}M} YWiʭ[ZGFFbH-zDnnn\v $$$l`<ҥK)`WLt/^ΘbX]"Oq:@a`Vp!!!Rf"%""bΝjB2Q*`[$FQ2hM6ݽC BU( %m۶ )tFƍF8_2vVgb z===A0&&&5tJUBzEEl+-,,? : *Tgۢ9rIO...^j+Ej. VΟ?tPH-FN={="̚5 W@ZZZ"V9::`;v}m <,, Eprr֙bX}^tpĤ-[*t8$jO.b@O]pAҒcP2`߹sb@6TTcĉH攒@qz䆻n`>b^b,b1zY,b1zY,bX,u;}^ueffZ[[~s/kƑvxUUU? /@R_2 cBfu茌 Y_LEDD{֙T\\Miz||<u׮]t  ӪGJ:uL%55{ `'b=211A7M9HSSӓ lll֭[>] ulقbٲe4&P?~ZZ4ŋ klMII"ytޭ[J ܿ+p X, ^ Ϗ„^33.v [|ʕ ...8vڼG:{,J:u*֢zx*:#U? D4т PxVZu j…2\d޷oű;08jcX^ ZZZ:;; 0ydMD?&L@Bȅ`hmll>m:qDde4< M8T"2MFkhF;88̙3>c@y 6PQ7oQŒ%KPڦMZƘ}4p޽T7{{{GGGD5.]|m%>vN c@q 損> eX/&zKJJЩ? 8ȯdҤIv0aYK?c̅ B }&~@/ihG&$"b>;&w(#mѢEHl4?)#NzQcy{{w[@/X{AWUU!~uGm&TQQl?#b7..Ngoʦ" C@Y"\-}n͛X11$3)E(kP=xq..]JI^1 )ػݱc'sgΜW|Cze:3zY, ^voZ>;0.Rf-ޱܹ×[dĶymqEʠ5m4ww+ܶ 1IPȞWe0^7nƊA8_2vV@o``ſ |󣣣E\=z;w0zY,֋^OOOP!k /Kѫfff iҮ[maaaB/c$D*//9ӧOZ /^`^c*c/|3?{lTXgjtaJV@tzRp04zyXX%ֹk644TTT񨹸6222hƸ\_J^%(z !l_^1IBK,/0Rҭ(_9(3gΜ>}:``KZI .S pfHo?I V'ND"6 7ܭhj2Zv-lݺݻwXAAAҽ] 5Np]wX;sX'IƪPJ>KdU}@zh[^]VvgbJֶ<W$p'&# ďxho+(i>QAEqEeFIdF@qeW/(F'+vUjU-ާZBhg埯 B Lʬ8Ӻ ׵AbN4SSSt ?dMkkkZ3Z(^ R .mmmAbB 33 innkԋFDDĜG8S/`5:X!vuXōRSS?Z---uuuuqqQ,`g`0z `e0 `0 S/`0L `0>666urrA놅 `0Ιz---i'#MnHH9[zbO``0z߅z===Z[[cccAruM{%*g0 ݩϏ0ލuˌ2}`0_pfeem6 x__ߍ7?~\!|OcԼ`0z@O㱃-P%'yr7v `0zݺu+q L ,uuuF1`0E@*i~_Zr޽[ g0 SܨT~z7ͱ΋ &&&^~Tgg'N|rNI cPowwuﷴ-"##ECD__ߢobYⳤB):n}̇Y533[,bKKwYu%deeOQ$a0A駟===a[[[(/^ÇÆ>bٻ**9R,~q ^/z_[uuuz;::>|5S*H׮]޳g|G$o^ :9sf$ hvm۶m&&&~~~^t) `(++3ܖqOefoL55?^p}=T ӓ𰫫SmmmPP E$pn^444ё3#aaa"ӧOVB800ۉ 6mdmm"]((H-[@I\dd$˫pbbu&ڵի,NLLpNN2::J.z^z&`ʿoooOanWX4+++Mn5HB= ~t45%gq ǟ?e˖---A=zTN=LxNZXXȓyfA0Ȗp#HO"rӣ0W"zNEE...eF ۽{7qGH =ԋZ1:.ן@% 6 W8G%BѣGT"xw DBpXܨb`d!Az:ʜչ23f U_0WX!^)7'COVC)OBi!m %''#+?(KKKϣp?ӯ[a)ܷwX|JC Bvvv"P34! V† Pʰ `0FG###m]6nHaZ2Jv\^d9lmmܴ҉q.vtԤ^jUă U?S8%%4&rq%sV'}$^Z755U%M3Gd^cGD\.^xs@zNNN- 'O>}||?0hzz:&;;gtiIyq޽ |1 ^LLLÇS8((HlL +X~ˌ }b ݹsgff&1ׯOMMvڵk|p5G߿ t{{ݻq#~?~5kE644PȈb&99\qF1"ֆRڵk;=(M6ںhzTfLA E)7''EU0]{U =2zbC`0zad_Iprr0Y7+,fl:x ̽4F˗iĶe  / R+pkffV%ޏ5n[jFpwRL^EX%N#Ĝ> A`z7}ѡR3A@ 0" qŀ0$`;;;ܹzqq'?z=+<9B_$ `Y]]xIT~֊A<ɩW%9D x& >} MTD>t%d.)[p0iAuhM3PPoXX:BG;;;H(IqJ䀮@zz:aD Y&B´dTorr0bdS \^{>[O Ta z7l .:ԵpWP/z0n[[[S/j^' P) r/)r4xK۷oVKv´^IR}P©%^r4::ʪ`˗/Ǐaiݰ-gWP% mll4.f|AO666+VA|ϒZ_a]UTT(z@sVV,)tn\/A{+++0 c^///csssPiBB̮,i v9tR}}V[&&& T/vݺu%PQ'+J+W'I/"7Գ6ܫN^|qqf QoCCQoggs Ϟ=C᭭iaٲeWSoݺ%'rȑ#ǎC@H^~M񊂛E .璘oSP111Pu/0R\"'z$ni(Y\(99pyժUbdFက,,,P] 6kzQ,k͚54 ~RvixxX)|6,Z300P\{AEg{zz.Pቶ-NѷC #NȘN]~] Kfaԫ 555r'Z,Q?ԅ̬+ccc͊IYP$|?V~f֦Cc`=3 qQ/#2i\\g;q`0LyFddNHLL`kkˣ ˘ܿ 1 `0 S/`0L `0Ιz~:H`0 cҒvT0ܰa[YY}n 433˾x 3''\(`0 w^??? /]vuu0/fddr`0z ^r(XYY01ѭܻKc<`0 9P/#`ggGnruVbYpڵ ;g՛,T/V-**Oիq"m]]g趈`0 {BCLLL#CCCy`0Ιz=<K*:+4O}}kckAFk\\"2??dʕܹSԴl2md;.Kϝnom۷99Ϟ+6$T+̫kyoS^8s񢑼:}j PfQzgӋFd ޽B]Tn.J2+p=[T]Qߋzsrr"""֍tuuz_GJUsq僗,~q ^/zDǛkĉVҌG3~||hii;cǎ^lp˾>á?y5o\ܺ`ܧO ѦWе55%wl|ܨ6DnT4offJ 'Qֈ CҲndd䧟~O UR &0<<<'H yf@---N+0;]"޽055.((@G W`>-l2AӢoa#OP!ԋBTAAAf^~SIIIAn'^\C({% I)쮘^3.io1^qq@*0+΂aV,zaBdl>(P @V _l}X7 6< "8՟_b"n]P STz4 |*3XjXdӋ(BoiX@%9&ŻwQ=p9''6Lra􍐹M@@lS[ΜAS-%VV"D]#8P yj:'݌ZGׄJH v$R͇Eo]<#m֬tU(x(gzP/hzE/:R;V' )ܗMQX(ꅦ~:X%06<02IeeYΈWU]U󙜘S'3?S?ƆTkjMUsaJptRZlG\a0ݺu+X)x4,p&pFtttD2a4%iL'"EE>V4=eFYvtˋxC#`aaAᲦ&ҬP H@g/jUUƒ7nʄUP/MC/!d+L|&pɬó0d,ظ);1C>BXLw w/ A`IHmkpV1hKQ.FefnX(u 6HQ{g[ЦH"477qPoMH[ԧz0IYIkM &*)Ro-TPje?474Kk$7p?7F/RҐVZiC";-LJ.55S@Ί Fޯ% D>efZ[KF@ ܫD&oew!J*AbZ+ Q4^uZ0!zVܫK\xQwWW$A9uz``#"S4U4EE5g;YN8A{T޽{t%O?{nц.%&#ZYYg=q4|[+wbb999&/3'@ɐ7ozt5|Bϕz>L}5HSULAxǏw,B KCKJ$$nS|$%+?1,XX+!фZ2P#z%0/!IHؤF. *qykdR| ;3VЊ S:P-«$ k! I.EzSr-0"jPFbvE|\>& [_Pބ( pSEEdJŋB<}k3t 5fpk\&>NCk*/4ˬ+ 8݂S/+ BȒ’š>SI;$1uqW_דE8h5uv[h3sl6MϣT-Yt[)uğMҽ~:fao0Y3KmIz̙\BbߗCd^^^EEExx8 4*Eb&@u4vtt Xܜd+reaǏop֭Y\RR W*++iB BoݺOʁh'ボqJxoW]]39!Y@d4nTJxeee Dђuݢ@6mrM?P| !CwDE6zQzzno~e8d`` `K@94LCq?FdbE.B/y^ ji14=yaD&a9_R9B^0]*U!rLEs3 yD&?Id$-_É4%}MʏǓ'-¨rgЈIS+h&7h'Mh_W]dlmmVDH5m]e9㗆!рzxRZTScC3'--%,40;dȂouJ1vIbÚ?> W-Cb.am7e62n[NE@Ȼ8;;;hOooHiQ[[[<#FGYy޽+o-.Ig.cpƮҪ:=6ƻ!WzI"h ×502tj/ƉvD}h"*ĉOtwD ˩<Ø_޻Nڛ% 9cL}22 `0 S/`0 ^`0z `,4 %La$hkkж࠮O~u})ߑԐ$ؘ_RҜ 6095rTqowGCӵcL|Oziccd'''#v&j׻y c&|˹]vm߾}ǎղ l#""DM7HzxxޓlwCQt*kα,v_9ŕ+/ݿzLV֥*p- K91-^iuAZYNH~U_bOQQG҂ $W'rrr``(9B{v*N>wwwϛu޽h={ȷ-_|7tvv{@ͥA'==gdNubccQ۷oq$YԨjińiӇԻm!m L[j=~uR]*%v7EuuwLbSH֝,&&Jfnq/䎨(n/E'T澝w>=SEFe3g~vuuurr rqq\C-("[ZZUTWU)R/s5䓘V"kԋqWնv'bċ= .y%5sBDiF61ؐOBCXغ`(cű4(;xB*P6F =GW5"O8G \%bס< H+:SH+`DVhFSsTro\PxbX}/G'r,22L,9E&S)3Zvo'&'!Iø̩՜z< mHi=)=őkT5TsIwC%9)B>~i,xyj|jKc^'33ݻw ܥBΪ_o>r>Y%,B?bz'Oj1Eebr0Sե1JKCCF׭BQ_7=zB.dO*+*Iӿ~X&!7q7f:1f8c;3`݊-@+ ("B(-"/4yn><<σWNH=uNթsWQ}U9E)&ihd'ׯvaʼnӬ͏=Ϝ ̕3"#q J>zi%J;<\^sB³dEİtne~ fGWTd=KBj&t mxxXO#/SocE530d16V]־+l)-l"+W|}}NJN9нvgXhw^ˆ8pɸqyk׮r7m4o<{J}޽{޺uLuJixbLdlٲ%00*ycEl,I_ yn~MF;IbF/kd چ:C-=/dH<-ܾ3ךcCR,KN&7kUZ8(_wcH&nksѣ,VkO2++!>99eXu+Cdn'B8@BNYEf]{dr5oISR.d}8i:B02 ! ".ʼʶteIEjdvñ̙~ތr4pFE]݄VW'%1 %3[0ԝ,v3j6b7f>$݃P{^ýzާZ뚚yժ׍w܌Ɖ 7%7_cbb޸W-ޡCrNj"QqƽAU oi V =w:}L؞XR6~Ǝ[n%QRR`.)hݻw$ٺu֗5> cu8b!1/ϴo** BԫP( RBP( ^BP(z BPjmnnq;w * B17##{Ȑ!ͳWTT3Fc5qjYP(~옘q9lhѢQF]zfĈ BP(^E7o4jZd 6==TP( 4`///{dPP BP(,vttpjСUUUhx;]{|* BԻpB(ԩSΧ*++ Bx+|}CCCdddzzZ_P(J}^+W|}}NJ˗ûK.=ztmKE\/I Bq`^">|=asjj*^^^:P( !ɖNSP(J gBP(z BPU( BԫP( RBP( ^BP(z BP677?x9ÇhowfY8~;Aܮioll<_qTTӧ""^#nmmY%%GΟ>땢C `.f={%wq[SM? mhhyC⌌ oo!C̛7Ν &ȧƌsot//aÆQ添s_"x>ʕ+9))sh导쌏e!22ӗA{Gϊ'Nl͝reˏɤGz5$߆~Zٖ?;6]?EG ټ$lf-Tw;-!_nWvgh÷"s.\ rc()j/&SM(jpYr2Q7))fݻuR*nXu ,ޱx^r=4CpA~y9۱VʃM\ۉ'&rn)䞂;ƤTZu+.R[2r%JIVWm6G;s99J)IZk0y^ߡcɟ>3]ev}V @ -v#cHKR/)$i=&Tس`bGg繫WCY61q#פg c.ھy|c1"T*OpDeeŋTas 1ܱ@'K+'gvA7oޤ:t-[2=gB6lؒ%Kx-ܿ˘- i?$ %[9 {Rڤ$.?n}DL׭[ZM<ipx)I(5d*z@Pa;?zB(pn; Ec]tׯ5F8%%婵֌0 M7QYeNGz({]|+e>|<܉00Bk$|ȑYfdtXt|t+gq52`&0QR H r-Ḯ1w t$ݍhA3!Gp*~Ϯޏ?)4 NO専 ~PODqN&& {nIz#gfkv2(Hv$@?p C'.eJ>YXvai3\_֥=o'63Ҫ7;?'?>#/8R湨T1Ghý%1M޽^M$XC 3//z.طUgnfmܮ) %+i6{O|Gh ~~~vv.+Qtt01Йz-gcņz޽+WB;k=o[dkܖ ϚkV*=yƬc~:x5s)ꬡQUmThhP/P_ze>{g~ So" nUo]v;"q sM@-^Ces3yVg u8>.2܆6Z_o4b[bǎO6lpP:;3|*w>d -Gڗ5 H܅BJ*O:+\\]݅oЯP={D Q3D*v˦~;<ۍ Sۖ: ϭڻ'v6L\%$ΝCstǏ_DW$OiB*fSigL>Pi{QY XV+́E/?כAikhht;f8@wʕw` SY`)4nNNի c?Kٳ)@֭#5 a 9rر2N4⩾ށzQx7yso7>#7wQwqv3_ۏR/:y3u;uTFӿߍ`Oe Ν;)X֬ (--yXFF^^^aaaPap>2C|%&v IUSSs!XpҤI8 y =ydh!EdBu2.H2D=S$ S!37>yOL?zΜ9XLIȳDDDp=v>}F)˗)O7ͪUqS'й m U?x[Ȁ$Ofn8p@[::VS:@Q:S~Duu]ڝ.81.'tgS6((1/%t:aL9LJ}ÁnzDeeAV#4VsWyD/RURBwlF{3SCtF!SgbP&P 4fwo3ţHbÇ DcjbPl""D`OHj$ 1-姅3YWrCV qL$GHopSoAr Qk+y~B٭"N}6+^7E8QY|||*yԘ)SF.\|4i~:Ihm'2i UȂ#p4O_5mJO>q&Lp~n3\d f$<,wvv,+1FwݼyS7هНIHr5'! -O! efKgYOs̕UAi!ѣ=:nm-]᠋ %},ⱏ z"^qUCLq℄4(.eupHISFɭeKX&{ kP2N7m^Nܼ&}TUUHtP񒯖 ^*pL#.f#A3OǵQdE-ח.zfw瀻gqﷴlOdpCk+e2P/h[{{cOzfF?}7ifW@#Xl+YhLp߄K0S$5WYm#gøW'Q&MB oC* GVAt6(3=i/HNN?~h cǎ-z߱dɒ]=%BxGQhA]~Q(++ J% BxǡԫP( RBP(J BP(z Bx'A/7xZEo(..ʺ6***ů7nx/* ^AC COU= vݱco̙d[e#3gmmma.#G=(z^oooԒlFb>t@( JQSk';?_1vdk׮طrAYYY&sYv%I 5l8$~Ϟ=m_z@w`` Ũf@8'\ [N>Θ1c~fF GFF9cPȑ# :P/T6mrp;z*@dh&kܹ0iM4y@FmcjF½e6l F&\^#xEܧTUUyN2T J-!!!x'/B@Իxb(+WN:miiA*яummX\oI2@/[F =GZQI!`q%DK,3gw!w{W.^+},Wr_ >}"`vNmݺUsNrرqj̙T o OW*++X#'ƍɊ&E , ٳϟ]BS/(w$J$<7pƜsssSL!! YItiO2!118څAjX.?Y}2vzKKKCBB^8aÆ6:P(4i">pqKd1@[H~J̩SӒ k?q? ˎ-C+T!Cc9KBHz_ ~i#>}ߟS3f0}ɓə ,0#==5G*谕@k bpPo[[ ͣӑç{ޡC"|La]d y?73fpg"^ubDw W~eUO"R<37Έ6Lmm/FPlrʀmLLψ#9f sɓ'% $&=f|?[00ZdC'___u I3#|(!WJxNرcCS2e 1{UXj ; K;OJJڶm$M]P 53'CamٲhԨQ Y鿤d׃Â[,^#V5Vha4"?AIsͺd+3?U]Sݿ ?K=Ǚz{=\HªbjhGŲe˨S˵kCǏw ۧEvUUU%*Np| ;666, ˶Qg;DFF.]xYhi-`SW(zoX@7IaxgC *++F7)SŇ]BWA=22Ad}S(]۽ BPg}fık53?wInk733;gC5tرP/\e7o,bיzQƢek\TTd$_:e5uB1\ק^;>LtEЀHOO8V_|pˇ :,lPࢺ"96onjmzj_`?\iiiRo6s/1:U{{) xTP/jce\p%׵i,..YbW 䦮P(.^y3+W|}}QwLwO4'#E%dBhQ.?goz2hRQ F"_v >[JbR0#u ] ^F<K.%`͘1/((Z[[=zD̜9#..Vs;)~~~P7"gz& ߻w]Fhllޠ 100_LVbVer+EEEQ455AF{3&Lz*8rykP( ;/H L$ݙÇ RSS%~@ | ~zS4pNU㿄AM_ ԼyCLjZo;*KnO;agn~JYb=NS'`9rȄNN>-aO)S&O /䮌vK~BW-ы(c7Bg$+V$8-M\J]\ G~Z#0}ݺ\ێmm/Ҳd? ȑqAAݺUBxWsQuu5-]vDYٷs3>ٰ?=xKu޽u^{YCV})&;˒n #~0*+$.^=tTaݾ_N8qSD>~$*3cZ-͛9wڵ O)""PqJrԬ߆ڕ}~Eŭ.QX9BP7n-hV^ |;.j)]PKwFU޺6ϻoS~pŞ=ip! (q̉Ը(AI~|yUOz51Wy"Skk޵!!dsd+(l0(ڵ$$Ask+"^B3d֬Y>p-Ÿm4TݾjNBZn{XMfGg'ހ|9CCy?:r.Gۭr8}Znļ"'!sQyoU,.{V(wzΝ ^zU0, |+++m S="EGq< *zTdHj|23}Vx^ntz)az;w7deܼ,~=fPSC̝ӕ_D lΝV?BPzáG>vrCCCdddzz;hS[x!!33|w;;۞*55H//wpy / 2@]c,9ȩ߯] Mƺ9n߿??>^;;"TCڵK^}ۿtYYkgg/< 8plWt& !KF,0皗=u&3B(dxٚƍ1C!K!Pz !B%B(BwPҫژDWOWNyN%'L?;vc}gz Vv]t)L wM tuuușnnncƌ[nôpcs]/{yL t#//c>R~}cˆ7Ҷm۶cG5suuEE|Z4GGG2B\r޼y111SNU|y2:?a( [m]5fP___!݊oW@DMjժ^>)@M{һ~/ȉ'X !OBzΝk'^|pfwwgη߂~ u␱?)O~ZsuvS?)9ۑI߉{Dƍ 6^]ߵj-?@_4aaau~~>zf/o$Lܓ'O8(0 ޹sGFDD /~'fҫjqѹ!dh46"zMՅ AAAbZ(AJ¹' }3M!4A׶&z7*.. tss2eijj`@So_ WjOsUU]=uꔈ.]'~h'ك[ٳkx3ͶUD\hBHː///755bP1::Z4pPQO|e|z#/<ݱ0s +G#/E )k)s#P9.og I/h/}mwjN{Xr0a^}qoؒk׮Yrê TWYfKZLx4ے^BHoWWWo0^www???6hshttߍ}xCZX|=~ GѣJ/RzU!'?1W~YI/Xy湺ڕ^`kBzV!::)+WΚ7CEcbN7 LZ&Tڳ 2]o@q ߏ?^Сuuu;X_WQTHee>>ߜ:*DGG4_%y_!7~=nj!eF]afB?OqOWGç[/yEH_f_7&oDof >CL\Q魬Lp$7nlFG ڶ[9&UVnW [K&-^11wu-(ܮ^iV'Mo'wѠ.TWǰ,X 'W]P3WR{M̞z NX|brᶸ˷ǿeBF\r޼y111SN?<… ]qㆫy52(j,zy Lj<'.;wK̙3G!K.4i[׿shR2w\#\!ayaśUk"jaĽs8[ފ~==0Eup&.uȫJ)#?M 'Xd6nu鍊rrrrpBHoyQPPLȐ^{c/!k[^} .~U쟭18VH9Gf>!dJ/]dԥW48SDGGG#9!O\}q͋>E^2RRs%n=ENd"8dI _Z\z?B+nA!#Szj̞=[ +W@wqhZ⎎Ȑ^hS'tBדqUX]zͨ7r/TV2 !#YziWSaGDDh4Ȑ]*LX!GZaC✣ڣp]C-F[oմ8^ :N`BFXpZRR2k,x[LL. b# %f*PG{?b ġ+H|e+x#C"~wq|dwдt:B=moؒ6qGHBF644XyWxb5vXL0ۊX81EG ݅^ UZ_Iq־$٩PYW7:7 ~'xލFRDhBH477:dJCEk4{KK:}/]$Pz !B%B(BB!^B!K%B(BѨj{zz,uvv2 !!P+ggHTqEBHoKK 566`0DEE744@zm@!Pz{zhmBB ~bw^h4}B!A.JJJ+VpuuӧO+6/ cі1B!^899K!_\\ ϗ ;Q8L!ҫj=<<䋜a7NϜ9U,us@B!Gޢ"3 <<..rLL t:]DDFaB>:KLL ݶ'Ι3G_!Pzތ1/ q-#r̙Bw(?$ Ν;&PggpB!K!J/!B%BBB!^J/!B%B(0ZVg9igojVS_gaam/\VUU毿47?GS[s~~yCðs5ܨOl +*ȎW)1 mmH5dr\h`6Syx-pIohhdsdd}}}]\\pl^uRΝKə~}7F G=*wԠ)pĞbaBܹi?M 2ߚɷZ;;{p͚]Oӡ2=#<ӞezTBn޽{WZlBBةRzqYFSXX8:s\Q#G࠸_o:g6x{náCPkyH MXcp'e,_};ton8n]j-znpngd#5 mmntڵw''{^ 47ogaaH@?{{Th4fmR+9LK޿]c:i33È5ɾ>޼;&&Mpd@BG\{J olo2,HKDǎ!=?#T9_RxNewpRGKmb"lAb 埔$~wm{geޝ;pA?5IpiiN1J\xYVN$ y-8r0bpfڅ ٸ}{")+VB%ӬVu&2CAsٳH32 }xVKPVكިK;qBz=mUus~:PZ/ }PQކ=D~@^Qzy,!~[$GA76(--8X?x3Q}QXh `?4UQ1. >3<ҫC77Wjxq54bLX$GW@b^\۰A -G8޷vm񶋫9wnxW!x(Is\=mYYF+ 8Ѯ]Ke֮ ω3   qᇀ!\T[g 4 WCiv_FF~OG[@GxN7ݜ4}ph@>7Gqm!p8CHB x 2 藈X0\"?\mVFfr$ cKcH}8BEV`+lU4 {L^YPRrshUp$dQDUMƿFG.L4(ouji h@KgEv`l1=G ZX|p:M~EjR)e`n(1GJMr+7Hi/;Us+*BITB[~A[R!? 㜠A䳱GC>AHUWbO RA*5fD;pU< Bz3f0X[ҫ"""4(^/9BS$<댎_Zwx *dNOpyo8KF?V]oHSR/;{ᩅC4tB!sr Hٶ}nޔ#.#].:ƒ(T4(-5%Hw֢d K}Nm;QL1D=UUpz{%Tq{m^ 4[BO&=kv*īh֎NVh!"D Ȩ}ޖӄwbH@C$'.NE)0Bfi%Nh\6,Kƃx @%5ȊnYY)&Ohːx44xp<&䀘F>,`*" S"r@C_Cs1EwAA& @X71כgnÌ2J xA-_ڭHj\//_gJ<)+ba UL]]'@YB^ޜm̎LU$\>$FE˗_uQ)7]x\1A*BPm 4xM{<ŃG!ݿb6 wč`˧Ĝbc&~Owu!+"1DࠜKR쭊@ ѷ~aZFo&"(xĤX$wwXX;Xt:4Ϸ!qxvJdXH FhߥXҰ,⥕\}?ݲE,ǔKUr)F8ynW nQ;z@Ձ(Nq`8awfCRzHvK˱ӘlRU9Qv''(I99{er@ptq T)5)[f Pu_p uYN}X89(-MDcU*U}N,~1SċqRCՇ&}ֆ5:fcu[lDrϠ30,Z ա=X58sQPⲆ˸S_lj2+LG6Zj, Z&\'*JmTuJwMC;)ojo"&PLſɛ3!\EXVGݽV\9.jb/cPz ! [>ڸQ k `%W` gHK!Pz !B%B(BB!ϝFVcmƺ:ftvgJ J5BCCǪ#eهO… 7o|ҥ~aŊ'N< 5G ݻ[SVVrѢEYYY}7?pMyl4oYत$7‚ٵk<<((HEs&xHLL9#UUU^ Ä $h!cB]]]q/UTT(`ĉڵk> %*QP):u*8H4Fmaz !d$K/yZª՛b\!i…...H☘aX !^y4@FF 6lXdʕ+cme˖ɓ'[=??sƄB%EEE{m B(^B!K!Pz !B%BFFVk}qt:eF|iB'4酂)"J_8Tvuu}fNNN3g|6SXQQ1$766['1!<һrJ7[ZZ h CTTaaacEppY@,XGBȳ%Vw.+>+@mm-LTKe5Maa!sH+W|||N陝-^OII rww6Eff&9r~~~WQQ XK!YoY`C P(#Fь/ZjV\%))IaもKE.V2y DϜ9W_gsK.E)$$D.\Q>襵 #]4K`^BȨ^i?9U%hvqNgUz苭cV>yuqq~b[7nի{TՑ:w&u&VM05u=9 3ɘ3f81cL)c 1CDwD|y<yED >y""AP鬬EkW^kgΜUq!}Ii?de0OvttTښ0~Jedddee%lnn7h޽00ׯ}1S/}^7o$]tpITP/^ҷ~5Igݸql ,..F>2x ce0봮w-,,d ؼ1}]:G oWkJ DՀz-[FCHbˆYZ֋aAY`<$ {gFRRRrr#tmmmqqqŲD1]VV0HKKK,Y2~R5b1*6l\Lnff&y<1cj+$$5h)ggg @p#>^QvCWZҵ^oAA`0O :99v8N6;;XR1]VV  AB3gΜ2e˗/---;Polll]]`0(vE SK,&&&9997"s7n oذ{^s̑.={` E+rssKJJa0 `0 S/`0L `0z `e0 `0 ^`0yTT^]QQQ^^Ίf0 cۛddd'#]@ބ m `zAAAAZ 1nnne`0-))@kk+644+**p}`0>6pmee%ơEÇ]#=j|1 _l"w;xp-P^VK:`#SS{RTʀ Up!HIŸھX^n- ]Lj1Df: ! ']klT3)4BT T> D° N,){CȊ io%FKvH)ҳr4ŃpY{@ iģht^oE1Q ȴ4:\?[;:0!#<٦۷u|h2.N9NoX\CtCZ<#nY+Ax4-1Rz'O"HhQdctxSo7''gذa~ia&5t}F19y0:avWo0|t 4,ྴ4 ~rwZfB걌oLCaq&Q42|* ? Fǐp]ŤDJRVǵeᢁwZ[+.\U79nUՍ(#\a2Rv-*η4Mʭ̯mikC乾/ɑ駳 1p|&3T!KK!eOm$kȺ{qM R@wQRӹ Hh[1^^-/C 0`3 =1:(?{eC4Z8/^Ftvź3T*MZݥCꋁo1E+"#oW3N ".cxp %һ'&>,L!/MXE K?WoWoA ٔ0^Rr<ٖ(DMU= w႔*{'? $JHVr(/OnEy/%Nm!"HGqB$9}_lެ7ِ&yxgMTĚ Na4SoQQx¢]2򳭯wK_hll:Z-;>x ׈-iFVnOJɈ~^#!.;/*#YaN[NE-=Γ"w;1'x.,lmhYeBb؟A6]xzxX2 ONE<*-Ff=f:%|B`qu6?phTsb#>lk7AA?O&ÕzZ[­vÇaREظ)Zd~$d/nEjd#RRp نOLD^l@wńBL UVV4&@_q1"Aw.y _f˗i-(Ç[ NB ]]p܆&7Vhnvh 'Rb~DE,LMŕpgC](&Rr @C3Οb;֩{܃1,޵ :Ű,Q)<5!U@kybՁ4,!h3bZbZ*Fh'GZ}␪-a ?hKh3(x!܊mȧ ڤ<?Ȥ\ꍉy7Dd9 >~\ p@NitLt@ 8!f0V N>lSLO,ҹkpKF[vwІ,YLӦH8s)LUYiGHHTAҎi)V,^ |JFssR"ߔ)L&TPA4Jѽ*|n%T32k%"Wzqi7'{suϣоVNi"UF`zf5#}ʀ4Di}QuuUijeֳP_CEJڰ]b T &]yVV%ߺj-mk,0zO cXO={"1"xlGg'rrpذ_ԨQ-d?i 5ŏ+c_#cJMÇ8ohÉ| ۭnAA۶MgzI9?G=h*CA[h[;{>2IN<~ܼA=MɹlH]rܹމf 0E%.jk۸`Ίر\^][RB50,{u:d`%7;mc85k>g|d-&r~\pqȑG~MBٳGivQy~A6>zt6NI{;p)EMH?<g&g2E$N55\$)wԿ$Hҥn2 aϔ65g?BT ָ@ƊE1TkgAPw2T؄S2q5(RC5clB!R @bvRהOZ/.Xvu?`ƶuh6f&[}Xvo4v:;!Ne (4uޡKo8wauEKr1=3RfG;M c} h\^ؙp% ^ DFNsqUu˵y&դ^K?`}ݵa-- ߽IJDWh(+,õk?NLC+3Xz1(MS /y(z9b1hA#gF#0p36~ҲQ`+t`1 kFw,}n! 13>Vt9 % h#nr+Bo[d v3:v06W꬯\9#^!P/r0Ihd1!Сj C,oc:p5W2[ y_Oe hmԫU Cl=+k9iYc>1h^Ν3aȄ3udSC 'ܸ//_@"^`_\=z/lPDW)P2(5z'N|OkA) WP/n;mb) C^T"p<77s[07,ss]dR[493P m#k+ĐQ. hmA 㡩􊞅féSHIzh'j{*W4Oԫg^;]H55h@;8,2h1.Fz?blz:aŸa b[PA2dÎ]  ۯ^] U ru22Iݞ+Qz#8pYFƷpS7'$&7*jݻ"|ؖ 8DR8Ի ?l\LJE;j #pHvgĈCc+Q'Jŕ+pe$\\M LzQ#鰤8DUVK*t *1k|cluF6@rz[kJKQ#(3`:- )%cN}΋ntƮ)HPh*ZA CA'/D_9g#&2(\u^CC5Z="3]Su3f eG~.)癩)Y+3C6#Z0.ME:pI7Μsz"YYc޸YU04lժq[L!6iXL,-dM3p.Ђ?4>|g&=N!MCzCY05ۖeSP)PL4 >sѰ/ lOF:2Ɋutl̡YLmmEJ(A\on%K_ݾ#f}.vZF#ðg jj@he  rkT9Od ) :JpO^Q- QnOԋa-VtuO]-g#g^;K]HsEԆչ`!]F)@r(&l\WoB4(gh.^Bq< x͛jj =z 45o^jjrZ4{#XBl*OCpfBԻv⯨ 24 5}nlyv4@; FӤk7R굱yK=y?M Q/:vzzYW,"}`5 }~2~ﴖ ݼyS O[4u ,,,CzWf/w67g9_X7=}/]:hggoyG2vۚkaaz˫zKJ36<)W. ut5{vY7|Gnn˕<2J~!'>hAuS{c6oifֻYk,0li|Ystg?b׶_Poxʰ뱔9'$$uωS#?!b#NVο#y sKQT4q ;:.C&Op„1]11[qYN:搏ARnE8!!a{]]y ԋJ93 /DJ0Dջwd+*WhW!Ni@}}JVV \Mќaaaay lhH,\͑$:yr[tER$bffWHsY")\0J&CNDufȵj`b*z\6,,,zj~c֬ϤI•҅a\W~g^!yeSB"6"lD~nC[*(yh2\at \a2WYvv ם'^.#rV4=k WD~Ȟixz}.(>t[xxH(;;/_˴׼yF^^K&IDD+&ׯ_'Uww޷ϓ)E$\]~=cܘHO8Qh999 ^Oէ 0no W]YY},䜕ޝ9s2|MXZzCM4oizz!])sY - ]*A[ ^0,~i6є|2CQz"ȧ473w#ԎDGG{*h Xޅ񕒱Tafd:o Si{p"y5$ނk:Ξգ{E n%굋J%AM7|7<ƍ$ uBTq RS#"6mV IiCwıdS7`( WP/ [2ϝLL uNSzcb]`aa Iù4#$))Ì –UT(pn'/ yOPЩs"?%>`p YK;P@uW@9;ϣآNYhF^G/_a 5M\B(ÉD].o%q (wsR^떖 ")M׺rq1);;sѺp8~h !S0RŠᅭm cٮ(8)M2-0!yɫCgުlJ-e{e|_AeM ~4< OF/QðQb!/+|eoZ#vW`+;i&5d9Oe>lq:wy2ҥ=AN!3{iAr% ??)ҀHdצ qЏ#DX.cIf|$7[\̾ҴH?EDD8W5OiA31rD&_ O~+DΝ_ bhfs ||gb"/^Py _ APrCe |/F>L l2l,|;SL"LNa*09"l5;$ކM"he"5z_b)M>Z@cO*ɝM":P@ $3G <A`$` XւBP T 8&p5p 􀇠 ` D 2l!BP %@ɐB+uP1TU@P-+t :]4>( a-Y0#p2&Íy/1@P .ByBPq$ U*CՠQ-mT?%h +:桳ЫFmz Chb1.&Y)ĔacNb.bz0CX,5:aTrFnl ;pj8s. q;qqgqݸ!G< "|> ߊ C !',#l&#nD%1эAL%%}ķ$ILO֐IGIIOdeٛO7ϑR(#'%CDSS>*,8 | !M]DͣQSoR_*+O)*)єlB26*RLlW.PޫܮbTRJ?0bp͌cϳfg fmU?{U UOUjjjg5ZV&Ghu3K_TApiix kii.ܫy]sLK[_KS]6CS;UTU{D#)9d3ә Q]M]nn^^^#}>K?ITM@` :CaFFF덚sL(&&Y&5&wL,4ݦ`3J氹|yll٢5{-l\:Keee++8VV߬ӭY?Q ɷiyckf˳cG[ml^`az6Nz']N,:+u'Gc.Zr}6x`ξ9nzn\j~w{\'|lSv*0o|P>>E>ʾF l hqxZhS A𠊠'f3'B8!Bf6;?t~a6a+:i0$RE]c2Zz09?nl  .4^tEYL]]|<p( 7[K$Jyv^=D0T,-y[HGJYKB:5 *CZHځ |FB)(Mt!S;sif\\(rڞ5* φf7БDt =2㒨%Ǘ*--lنey~y,G/-o[b튁իUV.X=ĵiko[[@`M?*J {׻ vvnV/Zl]\Ve#o՟l~*ibSҦ͎lnmcms52KJm_J}Y;RRSUٰKs׆]vwwS_UU\gkjb}/j_/_j/@jjki\IFuHsE}u(8*=ׄ_ :vu]'i'eM)Mͱ]OuOWQ9Z:q69-n{~ .^wqW\ʺtZu'o88xf-[-]sZ=}εy=]w#ǿ~r?\Ӈ+zMow?33pIde)iٰp3gGFn=_|?Չ<>3:ZzƷjo6:}E>9//_M| 711!JS pRo@v zʠSOS^"|HKS"~Wɇ'M0^Vv֑}23T+C~VeXIfMM*iD^ASCIIScreenshot!iTXtXML:com.adobe.xmp 644 606 Screenshot 0IDATxoUz~IJTJэPj"t!{#@ P@I(CCpR@b&.1O%L@lC0w΃}g0}dYk|}k `gU`0 Q`0 F`05 `h0 Qca޽K.-((Æ ?|Xe˖-_/1---.]櫫3KΝ;d9TUUQ6778qƗQGl2eʔCΘ1cӦM_~+T$ԩS٧;űgϞ(2_'!C:teee/9rIo߾`~!)..VaϞ=n]vkEˠs}Rw֍g|vJG NDپ}2zzrÇJt$ӧO%Ⱥwqɓٳg uMAvڹs^V߱cVcϞ=ɓ'?~18p f5%za߼ywcƌI@uwm`xbnܸQ?/_0%䧟~rq]nᠺڵkDw$xE߿kqp!W9r}ʕ+О8qbH{FH'i:2F2)n[TTTPׯKhllTHD_Mf.wuZ~=?ݻtPH}}}qXUUE9s&1Nssw}GLQ>:6oLf菈uTXFI iMz:x ^:hIQqF۷3nV cDhkdA[N^@Dt RtoI&9AC7b?x-7ݢҢ>.?X ABBUguo_x1yBs7ވR9F`ذa~x$?k׮ia…p菐~4h)q9]ٗ,Ybh0"b^p؈*Z7n@VHPF"?q'Rh"8СC(6m"`D6l0vX7Ix;c"ΜjAu~x6 d]qa'Og޽r׼QԨGx~Ƅ Tu:FyvN!K bȘ1c\'|B&lN^DYx14%PQIg 5bH#=zԅN Ӊ$wO$ w͛G=T io ;BH 3w>03:KJOZr%$>ȭ#GFIYiIAM§9t:=y$?"YŇeFi1c:w^ħ޽+݅|駄F8D{5j4~('͛7+[ EGZ] _>k Pu=xए,_|c&nAAA^|y"WZaC9U\@#KA I K.OjƱkEEEKKKt: 04\`V,%5\5%dk|X#iiklܹ}i> M"@DrM8js&nnh0qΜ9ے\f_|!\lYk7^9q/Oyʥa$̙3)ر_>}zb^d:u &'?0իW˽x͛$Ը|t+/ FOidGn p\t)0])xN+tTNk UQO&WʦπI IEc%uQ~Iw:zF//\Df֭^|͡WFF9TwZQF~ܻ4wF[{BSS4Bk&tZU'HAK15W]߉GPKeq(NF15m&SRh-OCf"¶md%Crb5 jl}%v,..>y$cX#j|)@UVmٲ壏>R~=ޥ;|VOG 7n\ZM'ND(/YDLL+Ѥ_hrP/Ȱi xNM )5HW\y!W)D)>%СC!-JM̜5kVR C?jM ,i=Vzڂ hSz4^rbݺuIѯIJ\`0Ljloxїw.ES!§NL qôv*1_# >>ɪI8ɀ;xgz-ds"e$L&BU )6hH%_6:ګd- ,$3Z<4}80!ӧOvAվIΆ<ojwjU 9rķ&wmbyQNB'AGFLjA!Nxޮ^4W?-ܓ4}r2t+KWnfSXQERr\?u$M_/6qf49GsssB&i]*' ^ii`0hI;6q~4Wvsػ!a0 N-r6mx `؉Z6]6V/QPVV[i0 Đ`V`0 F`05 `h0 Q`0 F`05 `h0 Q`0 F`0 `0j4 `0 F`0 `0j4 R_?`hF`hF`O65>y:_x=~gHs^qq^aa쯨('ʕ+F(+{s~ުUO?…<|y'UV-])uРA]v}ؼy3u{N 4܀~rJӧC:5_+){ &w~­(ü<`?vw„Mǎ={_uvE2QիWe˖lԞ={޽{ٳgw\o۵k3xرck=|9,]nݨw}ƻw7x#g;^@S;w\6t.jgq@̩إӟ zlǤ`OoĈ0jD-X.:C~۲Sٺuk+훗7|̙3*o hz~nrPX>q"B<ŘC阙sjln;{67o>{8*W[,wkjrCFԋHܿW]cy>>vHh7n9--yǏ<KjtqSc]]޽{9ؘhv\ہ[|xqڤD{N8fE>#\B/^#~|׸rM\ qwN 3޽;i[n>|~ij/^ct "㏁[LxSSGIz.m|Vյkޭ[7jk.@9páa!qDIUﻻ0СCa2^: 'NL9HsŊ.wމ]!oq!(.5#Ϫ*7Ikjj(_:ds6LnžwtRz}~ӓO zQ T7l[α ߳ge\mO{muVٳ~Y85P94J0uTwl!7_YY{?ƦgB~-jH1 lƧ]l5sTVÈ?d!3 gO Lci"][쳼}];O%KbyX `̧V?~~O9-jƍC};v,כ7o|wGj#~߾}KKK.]ȑ#u_~}Tמӧ:t8zhI% 3ɧSoڵ4]p!wN޾};)|n=z7$dڴiDpܹsٳgO'F믿^TTj})ñch;4hP.f~ԨQ4~ȵ㶔ÖRި%7EHuLV8m4cƌb ,Amo<]d̙3Iӑ+FdĦq)ٳ헽KW暮Eƈ6~(`57jSpȐA:O$Ɔ#ةo}6Ӊ%KJ\$(Fx+5OK~3.1kjzJ*ѢE*¦M*3"52Çȋ! qɝ;w hҡ :ujӦMuq̕CUԈFۿ#.WLzBbtS:T ̄Z Yǟ3gP~Κ5دYXXϲtI$R# 57WFVBJ'ZD%/HCp!P .Ц֬YA ]9e>^VӬHȫnuʎm0С#|1KpkRـr 1%s 'O~FHZ9z ׁJ92615TE4Ģ"Pcmm-yt1f̘RÇ;iQ2&bu~t s 1 4iߙʌrBn.KP PL@LFМȼyySٯM|C/OÇ~ΝݻA(*/Bկ2_.5b ZɒH555$VX%*_!wX^^^]]qwUUL@V(tDWHp/`-5^.vLJIKٸo= P޽{熣F桨fDDiHMɔ[mhh0o=5|.ݘ==5>|{*F.xnBb sC.vSPH%"Tؾ}skJCCgF)Νs!ntZJ }٧52tqĹDȂaÆ҅P# a4e˖NB!CuϞ=~| m5:wWrQ}B.]7n߸Q>)5Έ[f r׭3B۶mN`rߐ65b[51&VϏCRV1;\侦'?=O'hb1FvUR>/J Cy5Wtu^lQ! 1TMeSbOżM,YQ ?IQ ,0:<[vjll\z5!)Nqu5SݹU|O"0ъ21sL0'ƷqPXXfz+--uq>(n:by~7СCO3feHvڅpG8p5,ES*HkW.TBR|ʅЇ<$?(+^hdCF&(k&Zk|I*$ \Hėϑ2ucǎŋ,yٓ5<{V=]ȏOZeM\< 7~Swc;祵 nbjRqa?VsL ,Y!0{숻 PPP :812A,ۀY RiӦw+$Ѽ/N줏>;wtѢ(pIx?J߻ !gl;t m*0??:_#j肓'O*6ܶ1bߩ›^ mJlZ|Dب*[k0dP ]$߼3ƍ<Wl[?~-d;wby0IO@`!VGD]]͛7QK |  +CV'fS:1LyڵN?mx޽ [D[\tPc^rWdyG FgRu^ 1KN63 FƟ+`0qxɚ5kjCQQQfߟ Cj4 `h0 Q`0 /ne``xqK(((C.3 [ZZ֬Y[bE{!v:`N͛7ژy`XuӮH 휐x(c{tjƍ2~ lw^QRg1bĬY  l8,G~~>v=+UUUڮ7YO?v |;i4}R*E'#! 6? 0<cyaVvYB8"tI>*gϞ v@ ؔ(++[xȑ#'M$/mB(8XWW=ځ޵oY5ftb {?Wjtv FP\\R) 3 3]:@2eK& VvYB{>zHG G}moÇk'شNj 'Ot*'N 88Q:KNhǏ3Q1=J9jtrUTT5wa;w6ڱcSzzw Fms j›o>]JwʕFZȉ4޽{wh8qTes^@sN<=0J'NAnFB]t.1aK?=A%+?nܥVٷ]|?~_4G8<|ImD{][sҥCEd}}=^ZZzDPCt mV<|pUrIx;@U־@&OΏ?އ 'jRjF>Gu*u4r9"5J|ɒ%9FıK%B:p]Mp!޽5*>Os\{~S񣲒g*0[ZVXAV\T̸K,$q |jgNƎpgو LRm'Skg޼y3d5 _wAu; 2a5fS$Ԩp!?ojd̠)P[T`w l5:C{GI:Qȃ:B6>js̡[T? xb +=52P0=\}Q5j-ct.ҸqPqP'O,)eOzmT* JСKhѣ#tkkq-.xƢ8K #z1e`v3^zugؙ3g6W셃$MOΝ;:>S ]8,X@n۶ VR>x)BLY-"> TϼUTTwI@v+o-#5ӦMIR6z6B&NsRϟ?_Q4T4`ZQ]1 Fnv Cr1%F,e<5&=T?^YbH9UNӳ]1n?pt(/(( 8O0&=5crC n'-O[FevS@-gPUDp֬Y-ܡ4ˎR9FIiPMlm;8I]J`"a$0Li8r;ZRl$)C&\3qb9t;FR\ȥЌD9x|mm;TZV܏ML*DԘa5juOKf(QjG5:ٟ2"9S?D~gs8fiJW*;}ժU.cя 8~εu'W3&WsNT3C1Jۑ%`%{a{,P,qښH?PcHۥ4GD c{E\d'Hf!O݌=KqQZZJ̥Kf((4=RjM/_1'0/`1 i`@/AF1hѢ,)U`Vp N?~|jfԨK^P|Ɏ VVV}ݝsιQEm|lD Bs WsPܵkW |?ysHϑԈvR9M#jTOߕipH;F|\cjI).r&˗5P 9)]xg).r`S(K}7nSo<`1&R^C5KabfDg}qFZN zn:LO?TpyFuSkx\E l»䂓̢x:ނ;'OTsѻNLɓ'RSHFoE491|>}6,V'K55!jlF"ۼKZ Mϐ_{9rO~G&T8i1⽭ƚ&'s„ hiii`Ӌe CSsEa(u*S(mGCU(B*'bBƕ+Oa}ۅc۶mEEE؎Z̙[%B%\\d'e0H͛vD}qӦM7z654zB>GE(k:۵ܸq5,Nߏ QќC)O7W2~xyyIg>}sD R#K|ٲe2#PHW߶9Wb_VKSz*9Qg̸4*|~Jc1:=]20ش[[oMMqٳAvwoBAAբkF&Ry%{]p KT>$}[veB:UN@[ 1Z۾'MS,.TcD鵐0(Ij I:6rُ@ .tDEEENNv^\@pP[H{߂t?pGtS+/]NрuauhtP|j dׯ_|rf/}qv*!q^UUԕ+WݰEkrg/d=Ћ_L.嘽zj\\WK"JՌގ[={q{?CI{wTIE LICFt6C `0j4 `0 F`0 `0j4 `l `xqK.~Jԫw^!]XregM7()))((o:]=+ χ[ƻ vJ$xrEEEuu(|ǎW^͠lk@.HAرcZ?ɓ'7ЮQӉȦ[R_wܡx^ݽ{ٟ|Z!A"wۜQG#7uw/_>tP7 !Dz`ij( $A+vbO<tމ:OCۣy[) w5j.g1pBd.߿{^0={gXBq{veG ;vO>q#&MrN),,ts̘1ѩBR0%q[x}ns536h3>r Cƒ~Iz2O۷oבc|O~!ѣGjM:%9qQ~t*Ǐ<"[lwɓ'p7!%٧M郼={T0Dtr7A\G\HB4Էo_HHySY!q`8LHW =kΜ9( JJ_ɑj rƍrMc+w}ct13f(..FطoSMhP3 .:bУG׸.:E`*SQ'??ߑ\Dj$ŇkUD)[ի4P;;'Ѱ汆Y)+`02ZgԩM6!/ufP}-8bv;w5k@? }mC4UpHGE]vȑDrBQN=3RF)yԴGN)^b92HݻgWהFUUU2/)f:/^!PN87oN EGkr}< ~wڙ&F}xޏ/s2rh:)5d4:s@a4 ޘH:;'3vpΩ1i X)QWΝ;Bnݺ<]ԈiO[j2d|px~+#ԟ?!q qp\6O?$p˖-S#ʄ0؂~PMw1}RpjCuϞ=2j=07(;_yT__Ur\ߗ+t:T]GScH8|'r,?dйQSP{Ƥ@Y3gϞh/b bj>oĉ0aBaafn[iiK_3dȩuSۛJj8D 5ԀU D< 8]q >\>V)T'"UGڱPyAdu?e~N<,D23gHR<W,)okzje:m۶m③"ݹg(&-%Kx⧟~2M6.:ُ?^ #FJXjÇSV]cc#E[ o;KUIk"z&][[Ts2cl2:5?)s[ngϖzC-7nroBAADNa(K.22 -DpnK MC3nG} %sN-I׹s;"xD"x\4pBIpKńɔ¡C*}%<c cD0n8-pa}SgVTT$~ns`xMF79QN+M;/|;8r͉ǬF3R1N}}}ݼy3A f?{lR@=BgS:D^ _;r +?̷^t&u{N^={65ܻb`0%{wyԥK)StP˖-N߿ߙk'[>m0 9F}vDӧy9s9zh?NCCwQUUڵkDpo߾Gt:wɓ'w}f{.gMM ?d"5N811YrETܓʦ&?OF[ZZH%I[ݖkZc^s30שT"};|{8Igb12f$8:+&8=0qYQ1z}#5<|DQQ /y  t7(64Zڵj׮owwU'$NO*A((x2HdZdՈ޺e,srqqÇ7o6c:u+Wt؋z22׮&(5U],Sai $2YF)@'%%iӦ ɓ'F)NHHC -Squww4iRIBŝG=U9;;_N)،MǏ2eqQH7:}! n gF.Q*'NTS]#n3+)qrͮ]Z mNP)-hLC%+D} hLYDCySp҈)|a5[,3)** 3g|}}a"JXzxx`3(( e;~i޽pBv"5?ё2={v{FApGsssǎ+ECR48..8AdVT`?P{6dFʟgmֶQġXލ7rR m"ȔO!ҧMS٣9S~}?u䕧%nV K૝*zuh)fTyxHِ^zU:)j8N*l{bEp};vT9r$bu4iKNNy&m߾(=33_x1 D qBzLRݰA q*1) ӡDc}هf|[feFIH;v mٲ<\jj*0VhB/v988lܸq^ٳg$P 49RަhlɤCr R ZJbEѻ9MU\\_zUeyK˜@ҥτFZBhܶ&oqDyؿ_ I5W=L&Ca6N>5JD,{=b:'S;߿6'OM]Dz-GիWI`'|2n8sRZZJ@HJ=)2GDfA2BEhN)pأp?6HGNyO(ʶ8rϜ>{h O?}³/حG&&c|G3g>'U7o &`XO5k%K\rQ\spp0#=_͠Tp=q^3[CXݷo#_LٳD\cg8Me˖cSLh9sPSA0sLP)]Y['|r3md[+s%Mi]I ӆHqtD#,)Y4ݻ?{Vz;Њ҄#4nX#c;Tu9k4Hdr @/ڃx.(58)h*tEjww k Xz˔}eTqfo_)Ϝ9^Y,VGGHKKj7:)^PP`vMq|fUV mHBpKedhlqKJKKumAIԏ| a7F\MA_ו[jQjuБblh"4ԡhDӚ5/qaeX,FO ,[MU"b1R t3Or *qQb4X,hdX,bX,bX,F#bXFb,b1Y,b4X,hdX,bX,bX,bX,F#bXFb,b1Y,zh48ȁ809pƼlu^jJ?Pzț}R*ELƻ7T~Nd̘cWYmד _q .YYv ޹ӊ]9pQXV6ؘsjͰaotiPHHo̙gH/*j:.>ѣg Ex(gϩﲳt18\͛4FQz8Ыͬ\uЕw1[caxaS|z8~fq3gJyaa0+P0'G!иfoA"K+?ث׀jϐ9;0~PJ߫<(h :<YϲStm&M۷!]mZ<(pu4b67F,-_Iq~~={͢z`L̻))̟JM99~=o0@.w0߉"%N艜 IB7unnѳvϝ{&^wv>7] v͞77sJ 6/4)z̘,Y\<2ܽ٢EO|urrr:3NW'sv7j=Մnedč>H5_*%}#y} [ .ƏvO6 q[! 2̞o~{{˗[ɾ?JJ|=ĝ-~O{qB8q1fۨ ߌ3}[':9ߣ~Vaט1 Pv(] 91ɓݴpwb"1`D@3; ?x0fSAo}È-qJK5Pow1/JId%@*p "iMt1 ZURZYq'qp8|RۗXϜR Gں !f}E%Cl qX*nz"aa_SAy ٳ}Z-`l滏3gD R` ]:o)޽}LD.\xO.%$D̚ '}||zZY daspxأO]7Vv%=PCd_, @%HٸۈT!shho0 ӡ"M5j<=;@xUG#4oq/Fѣei(j&Fxߍ?O̷hHe?tBu=׭?b2ޅ4cn0 4/?P쵷diYvi mln7-ncxAԣ|B9aQ## F>'WD=laka5rsv?j]vr涍 0h$#Ri]w/ž} Q9{Z3 @#BA wR)͂^tO~ [Jj7mzŽ [V6"3\'Lt;yUGcM@ |3fHUƨǮ*iWK//g )g%66 {'6'X1 4~6E#<(yJ[k ñXITȞ*ɭ" ti[i_lܙl~{F4FG7?~h0OCqśeF=2)S-",q!}ҴZzRXW~E[:r&ߋ:>ettTCr}ֈ1F__5&=0WL̻vŸ6=tG3,()>>Jhm]P_?F@ @cp糣1qД? 䱧O/ܤۄ/5^kOhhxHLƼʣGbh n4::9t/T?3Sh{-[8"HJ֯mk%GˁWK4*xPJiiv+!ΝJ {vv_ې@qnkӎHg߽8FyrcAOn} Ƹ7ĉ?Q"MfeolMdg; ~4E  Haݼ[U>a5OF 9 `5r5$sĈ 45*!/x>uj*<*ד'MMp^~ lp豪6uX{+ m7':f[| J5򵐐8zu@pXiKsH6O͢"[ lJKD' M$xu{i5%17BcII;zHCGxˑ8ŋ[jʧCD2HouƘaG۴e1 ̩ic7G\xAPpBD71kk䳬 *Ǐ3hiY6g!}uFDhʞ;7ΧBdɒ ?E~&)&T*oL: G b]T[?pA۴}gB5ojDEW %M-13oEZIJ3f5q'zmق4¥}fdzjѤ$k*(3z:K"q\R^0_YDwo#ٗW9poIw`d׷!AhvP'j|L.ZtÇ,(YZ?!<&ؤ@x-۫ fMVy |^߰*6-dlbVƗ?dfNt&<|K.% 읷AٳI _p䰤<(pUGmˀF ˗1 =_证7 {u86֭yDC{]_8px bX,֫(F#bXFb򪪪4}ҫz3K)(rMƜʌ$kD489g'dXjzذa"!!!"=33S;;;}b3E"s9Rq=jNb/,5U@?mτISX aA.h\xuaaaXX(C-:t(dAA͛Q~e~ŀ^{5V''7 !GcQ7p'q??ڞ_yjed4XNFKKK///[XXQXLXٌҡPz5m41r#k$JM5/ѯr4?ˇA:q O ݎC% +6$mjjt)7_s_C ($^6xϢho}]:5OP|[^lpw7̝+MZO7\L7IB4ƻwqept4c 1<|(%fd1[gؾl4Ryzal7.]2,_{;ɓbjN￧M{{iӦ*3fW\7 ;N-oF?}MwiP}sF0~ټqy9s6"]ڀ:}-b_V=c$^襜HɣisZȀM]S3 C`'?b럾PGB,!\=4fg0taFס;w$R"t^ aԨ֬~c[[ "+Wb yyy%~7hԩG~bC"ܤh% KKK;=C ;v11?UxEƾHhe~m JKc2b8?#4JjOwsIu?"q|0Z--|*=}+Jaҕ x𲑕@96%4EolpψM޽h_@JJY b"kǏ7-UVVqoކ_zUNB?~Grs74=dr:BEmyAkmE55 mAƍWJCpr@~b^ iF1)goood׮]tΝtiMC=[ߌV^쾦;AAZQ0)2'vfTwVP;yzE LRNCMksZ~X[h5T(5}[*hEGjqZb: 0^t6N:zhyp+++䓫ᑽ@zVt;Lbz .2}7Eg@cum5/ӕX#mhK +!tҚ11ilIK5^@Dy7]&2n+OD,\#%L R@cCui}{$F&ꄮ1**J &#Ç͛QhZjuj@# lEhy+IW@FV2RERFX@{3g3E"OƠǛ3g9R$h44g%7s$vQp=kZtHEEŋ9WWWkkwٰaÌ3ϟߴ-[6AǎJLLEəjb.]:sLb/[XXw?'' E#νtͫ5 b7np9?++E޽{/===n޼٦R :th֭_}USDܟ>}wi9ftt44n޼",nhĸ#_diiEq &[ҡAմ#,Rwݎ9hT*6$mmGV\hh~:쑇<|DU:ns̹}ڵka0";wāpׂ. =zٳkjj+55qݲemӦMիWy1iҤ#FlFFHx")SDO8aiɒ%.\3B:u)g͚~V?к.v7QTZZy]gXmF#Faṫ!aID&d$NB!4tszl6 b ^A7 MAP\oSgolNZjժU}Zk>h99R -a@U[M1<<5l$PzzzJQȆ^*OXB%[H#<{u5$2NrB4(ğ>Ҙ6m^G!Fb xi6|' ˳B(ӄfH !P !J#!Bi$B(B Fs 744u95===wLM>xs1>~X^kPKKBi4Ǝc-={btt 6=Ζٽ{7* NPX y@-dS^^>W^+WyBqƍP]~aj!b랉e-[ޤ)4`~ [```\\A w YJ(#_.IN߱owab&Bj8=nhh.&$$;XNN M3bbbVZ~ƢE;Hcvv6QՖ0%%%6mB7Eu͚58Е+W] ekDD6!-.Ġ|eeeAK.]F\[ZZP*lߦ%&&~g~~~&W%3^ڝX93ƂUbWJ/҈I# Iѣdʡ~:6*%hí 4s7pYeO)J `0NHXXYiR ?MK#P1L:x dffhc)KXs+CqD[ 1Е2nݺ% mhkO"n"%[h$i!EGߵm wF'@hor?FX#"ZLgM*H'h!o VhkGGr˟xYYY4ooolv 4pkkkg웲!xQfҸxbuhK%[ prE~GsiMJ# rА,_exQqq1FFXI25*oXF1/_Fhx˗/5BX&a nݪªc}vJQP_ӎظ+ ~z^tAF6T3F777GGN ~C]p7i۷o$msPhT}!:a̩[ps8SVYY9 J#|BxqÆ wB/ u0~x߾}DGGcj#՜9sݡмgybDB cxjv=Btm~q֭*hgQQA.A!dJc@@.==*_P￷4N%suuuzB!J͛':k.~~~Ʃ?4cB4h @#7=zd>>H!dzJ#!Bi$B(BH!Hi$B(BByh/_677r ! ivvvٳGiÆ 6667okT !)ׯArr2T^dƾ>oooGGGV1!![l0|p GDDIԩSNrrr***XB4z/pyy96;999;;,MV=!#lٲO>Dm]|Q  /UO!dyYYYkJ833;ejcmm-W"2ݤqD_ܺu IxݺusΕk UUU*UGGGLLLNNBtƀH]zz:_x? S@k]]BȴƮyڵKssקB<4cB4 @#Mfz=N!dJ#!Bi$B(BH!Hi$B(BȄK[ZZqB!3K-e<<#!2#177m֬Y>>>-9s Bf4ǻZJ/REGGA:B4FaٲeҸw^H$Y!SQQz'2Sq>wAAA2V=!!+Vpmm-TLm?ƆsBf8{l ?Bhp*+RBAҘ9G8>>ϟ111999wB!M-\p(G rQ7oS* @UO!dZI#q___СC9{GSeee!cB4Z.ݻw7'B4B!FB!H!P !J#!Bi4B4R ! n tvvk\xq\קOvuuMl>YU6 ߼yw7ouk2 Nss-o tv,+ç_e瀟~bsCdnnnf1KaSkk딨[[[y\ᤤ111CCCАGXXK.\X>d 1N|Kkk]CCg_ݻ>PgfCw[~JH5e8=Ū+WNHIFDt} ђL;ahN̚f_qqo#o߁+?l Ճ.fkۿ R܌6 Ӿ>Tƀ/db7YX-\"ϟ?߹s{`` Q,׬YdPii֮] ޽{~~~S5551˩6m$۷M\q>P/bcލ~5?$p v֤sxǡSR`vWy*9teBBjM͚}HtL8s\|.±ݻS1:1qITMm oK*|ӑ#uoHIAn8_Ba@Q0g̱Du#&_XwbY[j*?0O(ђA#(<{56dզ(ݿ>.)H7op tnҮ\ӗ>렺&E/(@h 9cſ?)BPh{j0n6g++Q3Q$Kfq1洴?\KC *鰣G'5z(E&*P|C[99o.gT`hV5p{G!= .ٙ}"X4Fv t/// ]qHcPPy|:hkkyf虽ӧOQ3j ___ko$֭$vvvNNN eu4NNLٳG‡6~S`:BBĎ@`"ad(:7cm4Ŕ{+1p~R))agQI_9g"{+ۑS҈CS޻7oJnIKs?Ͱ8N aH#.~ ?(s&|j\Pmxt'LEf`!0GU# (-ʀ{5x/szFP VU6:v<ْFDP;DzYG" JFTKÀFb +k@廇_p_= &*暍7r2fAPpB\$/5&,W٣џ@ . vS};(@~w$&B N$J|6H.4yWҨ˗4@MX|2H#;Ĕ:RUvz/G833SƐ9L>}?q ?havvϞ= -3A s/ 倉/ IQkWr;H&saȕrz`sh3m/LJW[ 4ò0z]o`є±֦"a댟o2ыrB$ Q9YيBv2M`US/ r%S%§D qTc+f:bѿݖD3F"V>tktP6=!sg%@1*Aw@Ҥn7hl/|Hz }tڒ>X+̉f%ƼH.(fXuȻFL-T.]*aMQ6M2f9ذaNs)(X9>5k,$ `Dqq^cf#GkAˌtN1 qO޴jvcKC=p@EpP^0X(>߲ݻ3cd0zq@+Pax9m/)gk^rޣrME?":$3p8aG3¨:tn yoIna< MCѣZiqu@r7 ZpfZп] -MzTF6]@ Ψq| uCV/+e=V5/tÇ)93%1<<1PQho#UܵFMsN;^y#`3^Dw:+/ /i7ݻŚr/\YR"gsPy}A/u ?pF}M=mߥCSԗ.;p@! Z\.u $jѿ Du/j/UswPq#GI#GD*uڃ?{ݏ<*B*)m57{A0#ʱO0.5$CS6.l ђza gty Fw{Cj*(s a3P?6]n9A)+,2pds(@l~*R!f_gqM%jl?F XdqjZ[Qq7o\gMIaj/ gSC#¸ .NP&d 9it>^M eEnEEpe0CNϜAX l6eB’(\D1ꅇH\s- %Hݢh!1lm:H#"CHq~W޽]/iBjpS^o :^Z*u.>EhIڌ?~Woݺe0OɤS]hAb:qBw 2(CCC D;wnLs dFX ~\fGD0x*rk >=0?ܤ`J|`!?j vG@"! fX5II*Vb`L4_D,($ϧn܀]|-ysZ ~JekıcᅲJ-0i-F}qK- QJapk".X36P|:W3fHݘ%>Gnh6Co۟GsFN'5y| ԭ&wT[)辣>,r'W )45Ε{&gy ^m2JƩ. ƉoxxxjѣG oH;m옜q}}{N~ 77u37ch ACPhxn`pTx1ֳCVɓ jtDP0+ow_KGw,d }}6t)rSCg&xHcbbbZZ2UK.9x`^P'sέ2CFF4\\\>M! 6?ӈP'#ՇpSoBB4B!FB!H!PMm!vՏɈGKKD-/L!HcGG溹͚5555v 4XFBvvf'ZBƍ7C >>MMMsQ/#Ϟ=(cpuWBtF+oTzټyrrr*Xq]8IIIpsFW*TWW9LҢ҈!L%ih׀rxyyI`Q+WGs,G'evwww+ǏBTF˗[#Ʀ^' V$''T~ֹsKkkkd1?B!B[4`Ǘ.]*[FիWM d{6qΜ9'766ZI6=oΛT !dI.H舉]|Hܹs%64߾}TTTvMMM~C!SZ7l`|*< .^nݺx…|'''`AZ$$?88ى<ȊW/7*++ !dJJ#)f9Hٳwfee!:4yT!REA&mllӧO'@/_^:?3!LIiX'bsB!dH#!Bi$B(BB4B!FB!H!PngϞM5M}W}ܚ\s;W]m~U}Hxۗ$_C-h5y&Nӳ~BÇrssf͚㣏ooowww8;;߻woV doV,|Nl*GJ* ܵktm9N-KKK㟟2~iܸq;T ]]] ^/^]]̙cn5)!,(\ʕ9+iEbi9ᛂzXQQ:lmmߛ42 4 '''0MOCpsꒌ%Y?q?BÃo6C>n2YD"~mȅZgXZZrJlR뜜:u W$555((#..r$$9qѣGq rXSovŊ{23.=2_fM~~%KKczzzBBʫWf 233Q9/VAbjjjs}'rڵkHzf gdkꄐƁv  |iY 1XZZ'Ld57oM~S%Nm"K3Z#[+ii+I#$#I8" pe4 22rW\$M^_C3222L7]!4 .(3HJ=$aRR͛h"@ "m6 Piiiɒp27uBH2dz ^ ֙3g/bYԁPz(bZzZEGuu^s/f(3/oGV=_3"u|҈ꅽV?ỠVe/\ٳg;܃Cϟ-=QT( 04l޼yeWWEw!dK4W111Ri p.h NNij@{ҥV1Ta kkk'ϊT N&$jÙ nBYp+7bpKxn(-#Bi_K"#\%+טqՐ:+RQ(%%EI#Dlei0i,,ŧB#چZ粲27n48dkꄐ FǸsssa5ԤΈv+:9996A-?>:Fھ4r!L>CC:unHu$m4۫֯_ YNNŋQ x}iDL ee}[JzF3°0y !)6l0CẺ 玀DGGWWWLhSAZ$2&az\/ohh(113昞 N.]BC!?!Upp=]TVV".k b!|С'OS}h UXŀ4B{zz Zsܠg"Olꄐ ƶ6[ `CLF<<< B<Фh**p"Mo/$Ո_(Bė?,75܆GaU*4% g<'c*rܹ퓮ܗJlѢEvP)7D\G%?!'rK -tMN_]jjl-** }/*\=WTSGNN0iTͨAR/~i҅p{_ GAmm*~䘏gX#3r>@@y2gpy8NNH555NNNpRSSKJJXfB4W;!!iM6M2ٳgdoBi$Sf0xfpEsenmm5%P !J#!Bi$B(B4^sφ氙ŪccGFDEMx{^nBȌ\77Yfo}M5АGXXKC ?)B[nb%00WAkW$ӈiipΔ8́򆆁~8$8#]RtkP7 B&4 &WhmmPl&/}~zlj@]{7y׊;+k՚ _P2m=fHrΝӧ*OʦK /^\;gZ˩~w~l8vLeur;}9us\\fq(x/^猒d^">۷LH{55F=O##3)&˗/WclKCdn!!b%}h̴^11^_nK \G]&!78Ucvgub" 9uJ@؁nӖHreΝYZNs#G> ETVo#[C*+oѲR2.cGGIi@p;|8y~J>|Gmhx ru=C_,'r.v jW{Cilۿ?SL XD!q'&?|P#]ʙ;߼r1 L!N=<s\ a4Yq/[‰?'XhV֘yz!=mL|1~/X/wnXMnjBL{OOim-PUU T>oFFggJ5[8o<*^7U!t]yyڭ[O*⧟V] u#{ƲCc-Wot.ʕZ|X~vWWkAL&v<b? Ѧݧs3å_]] <Cppp077(y %A וN[wrg;vEKK!'\]c! T-('G[S?@>5XI Lg26tv llDº&+Vg"d[NŸ:y- U\#^m[}}PzwBA>I;vefFK#QtoooppKyF>P mݒ1F6T$X.ܽ޵? ΦO=$lӡCRh45X?r}²}/!&3.¦h쉿]2]y ͛ѾqBb/yߨ3JLd=^0^롿&iqÆ '777!x&QTR݀@ Z0w-[djAΟ?_v-i[ww7 D5F @|I#z'٩j(.]YY8Vvv6[jK_ ɞnM 6ٮPP+^y0jU 0_Ga:tMYD8%\UdVii\n 5&-Y())Q/SNNN.\@… )p>II(ᦄa,Kkjj V-:͘E L@c[e5d I`#666>{ H3eFFfrF080 K#K#0 Ø vرcK#;vرcȎ;vM4)}} nj{wgsqk;~Mk7eU~/oo瘀<ر3-*Ub{{$R9sxy-XY'l]=&sٻpac &. 5k<+?=j37눈;U;F9iܸyժO%7ĸ;8ի%6mr(->ܶ?ɾ+}W[=ޞ uliI4?bGG\c]׮EBoߎPBر4I]WX"{qq9YBcE.s.Ϛy/3?\q{eː - &cD R}/Zisju66&@I͛<=sEEռZ|Aհ)QV0,lO?N?;[vX HF~~"WMtyil Fb8"^Y?M.l0^|.R᠎:po40#DYclLFز Gw,9X^NftY\Vqeǎр4X聛4R,[rw?xktJrOS &HQ=rՠ˯4I3y(֮}8 _b⬴SB TPf&;2Li|ZxHϜ٥#[vX_kk B JFO?ih" p}00ݽ_%PB_C8@ssNI8c2?o)}ڸ.QkxH&&YشEb5reǎwt4? R#"V(?r@(8|}{R,=Ei:P^%q55q4߄}-ӹk_@X\oٱciHAE:;!DK-vΑ#cڱi=љg*v^8}gyé8YҸqUVI888^Z}:౱j˳U ji$Px,y ,i[r+VHwwKNP(***8_t" Zaa+Uw:_k,kʂs. uikQcKߋ~))"]8q'vԭT iD/3aC/r3 ܤQJ3QVϙ3ҥKO¶pi7"E䏱)r8}}RNƏjG/I i\wj=gI#EC2v3S322Y$T~HW[.Z˿<I2RRSSSU`^lTʤ>gQQ m} kt a#í:<<<-[F!3QmmF:9!H5U?Obe|A{ߕK[_jmgyJ[ZZ`IU*UDDB|ҸlX$ituMωmpEM'^{0.a}Jhkϛob|a4PWWWܽ{$0H(/.2 W$Z چM%0}->rt@?N!֫vJsX]C])<\)n+?v3B%? 0M;;;W@xɲu1'֒.BH`յMThx\mvTP!{$0Cٟۄ⥭ 0G@GGZ6ipptM46Bdln`D7R  ZidaFaaidaFaaidaFFaaa4꾾>𑑑f\aƂQT:::Ι3K ΝUaҘ yxii)}qppޞai$c8q2%>B|ga,E [n˛7o[u+ga)M"GiixStt4߿Y0 X4feeA=Z__Z"0 cAҸ~W^L޾}[تR""" ;0 3ۤ_]] 4, T67+_o~fpxiiCg紞E3:z'Q؈K6bD:嗖6MCbo44pUx6YtiT*szj,Xaѱ1 R o>&'NB;ğ>`fWᙐ3paEb?DPb˩!6=Y2:{ΝBI`o!1>=:210ܖ=[Kg `Qw6u(111׋_t 7o޴swwg!'vdB |ܟRW֖.bzj~67ñ\B %,P;8'ktէܹxuLO\>KgL[F%MWϛ7AAAIqXBQQQaxjWn.={VDECGBM!CC10/D< wTbQ0[zs_]llk&}plfN_KKs ͸tvwtҰ0$ q<حPNr޵?=M42%3;óavmR:i•J0"t]w2qwr رH$ G疔{z:?Z+W( gɓHYY:$dy'',(#8>ZRR`KAIaTʓ##fAt>Qw v$: 1J4>u22܉gp |t:F+'<_Y  [CUL̼ti"oܠ2XC& Vu&&Έ_qQpj ər>"4D~Ψ~Io66@~Ɲ>-ܞƪ:8^ZJY G7l:t5<ϟmI'ƽ{ZYYzzzBD4j323~AB05"b}jq@М,ܨ4&>'~U*e|fj.=(ax[i$-E1ep% mB 2 p( M\姙h%aTYj*'z6tD;{r AuOB+5eىfQp.Ԑ\ VzQ # u.@kt4'7VIяADd "" 8E@bQ"vKJptss#looFGG#isChЏtQ ꡒ0 &j]{`'~OG3y/0MV-kՍbY&…nFhYθx&ih _\G2-$9Ġ;s& U0)dN49NK_/c0.ݹ (tG#Р(w$L2H &9-89:i(lӵdܜ,+>~pu'5s+ 2&S9)?qbsD T^mm8>l#tp=RXTu避V)s`l݉P /: ;0ƪ:ڒAJZд r*6l=aPu{q"SJJشh"/S[k_B :P&)X* 2{5>ynSk9vƵo(IH W'1H;I=elB&@p@ۏX4ό4ܺ"UU-YM?!2Bj%+&1[LH Y}=Wtopt`%CǙ4žh10Y4feNAK݅?߄FHo&/'OSj2]%AHrm{qTAc UUP%4Vj4i2U/ B>kFGi%#O_EϝHe:(u%Ń1TaR'/('Q=.;cc6662""BPX4=ͺ|%tB{O쇋 C9U^Z6{ Or23.]Bb6;v8DtqSdn){z0;գvD痺*];DRhĩX)ņNvM|knǢLl d2{Ľo$WmА5d\pp$d@ =n3/j%YJ\0P 4.33QchMd*'ͽ ҠjQw4,F>?0AUS+5yeLU׭܁> j4Sg2ޡs@Q4 _n wmR҄F맛 4xZBhDU9 &`˯!XNĂ0}ϏFYI*t~˸xQbȏikNNF̓G0eF$n(o77éM n<ݴ  ]8(\ja!UҎ(p9( ;҉M3< 7hD nVndNܓII0;G&5=􈋣,Igw0H} 2uK`p\,3aŅ༸ @"ȊoDO5\P\8.Nhdr& ( C?geJa*![(:a6]ݠ: $2-2i@zC\cn8pd28E)Oy:X餮iNd*'ec%%4u}Ld2SD]\"* 4&7sa<ӌUubU\M 3v@"o66z=‰A'OjdۜN#pEE4AI!6ѡdZcE0p(D'&6'u+9c$Ë7"c dgggc)GqK~0sЉ;9k\.Ԫaq }CiCw."@b( n tE+b'_DŽT?H: GߟFv=Jl2MXE9iQ!% 'B+LЦ,ݴ<jSH.S tth9y:٦qca(Lk6L8'mTtBCƤ}?6/_j*'ʎzZtLDI-( MEE (hk(Sj2C2XU'Pp E,E'"ʿv̤LZU+SշMYh 48.y|Oa:%EufrzSVVm|Vki=2BՄ#iCi3gűM- k?$a+ 3Z <VcMR>Ź(e}gS/FA3cV-5  ]G +Y#J60VjS@V}*)i4&5j"fB{PeJݺ6XGؿJEi89˞gidRَؓ -0o45 3$D>K#K#0 ð42 0 K#0 ð42 0 K#0 <ih4գ088x7P,^n0 bJchh(:PgddЦ>6-s4p0 üx勍ڻwQNHʕ+9MQコo42 üVcKj50a=/E3B01JSo?ࣤ >ɟ|/~?ul8?rhE^.9WQQљ3gFe?0 '} WGa>A(H"j4I0 0%mmm: |}} 7w+V#@_ Iۖg-wv[ &盏>&H!wQ24jq4ֺj4'5kJY(afz1;;{Σ [iax뭷:::#Yv\p.@V}5UhzD=ÞQhj#MB]2]M0I¹QRRUaYHI`2޹sGk[ჃZbԩ4gg=jhadl t4oa" 0 0 0, 0 0 0, 0 0 ð442 0̓JF6#L+OGaa!0iiTTCCC7֑BZ򲱱6ߙFfffTTTRR8PP١(Qj+a555Q:ҸqUV ڻw`~qrYp͛$`2>Gi,--]~Ֆ-[rJ>hO[K҈@|&V^ HdVTGG%K3L|{Ν;^^^!!!/555' ]\O?mذ;H#*۷+ElQ|}}׮]tRwww~,0-h@#J~ȓƀerHIIh"nnn4kdATB)-OXcc#EsEDxP&z?t$_Lc1-B;"M ͥ~dLiQbk~\ -.ǒFD~T2>>;@ &=w=== ۿ?vʂ_BW~x,iw@ 0 8<<ܪe˖_ˮF⢿H՘4& "3FtAVU75i|뭷G$'Fv=j T+k7Gf\݁0 (ap Mŋ IFJP(8ߧUћ‚7oԤѻD1J_m4w;qJf͔FԺr=$(K#0(KVY/((&jgϞEViE\(0 K3}Q࠸fCJ2ƀ]+ 1jdL+EEE`5|* ?3<==mll0͵111dr92 <5 ?&!88gƍa;wnv=|JKKK}tdaid^daidaFaaidaFaaiCTWW@ܿ_̳^2BgYKJ׹P )vyic-[YYY-YdfTX///www7)a]7n(yjOO ޽{o󳷷ohhhjjzw9 30a3'hVV։'aO ~yCx%Rx5K7oM)9B|.XRRꚟOPիW899EGG h4RDܜ___̄z@:::|ztvvs6Fa4#]7uTML9M̌'cΘƌ1!11@ 8DQ|QT%P(A|CDDPPD@-x?/{AWw{JaI)*?,,LDT;qFP#h ?~<aoQ.\hdd4ϋ"3܃zQ4`05 ,JCڦMSeeexemYS!C'O=(F:>޶zj333G(iְWLmu'L WR tmmm),ݸFsfFF.TO۰&ݻGԸh"\*F8%]ẘM:4W!!!L QB\cQQxqرRʒG FJBݕ@ /^LᘘD|%|ҥxl_bМkmj?052C...GjRRRbkD">11qȑ4d'XW{( .,U(.H133܉iiiAԩSPXAAA(YdC蠸d<ߐ=`e<$//O+((`vd0JVDEE`OСCt)m(FƃDiOcp$feeQ\/5Z[[?C)ϟ?f lk(//M[2;2ޣ &=S pT=C/@˯ 1HQRRB;gffB S#cP `<%aʕ+HMM=3"`052 `0 S#`0L `05JRJJJ4?X10[c=0 FשV^^^{7۷ow3f 5j֑@ŏuvv9sٳgY uj\|`;wJ_,**/_6l؜9sX݇KJJJ̚5+55`0]F;owԸk.G;999RAhtϰgP'O> tJ_rWܹs +ԨR1|;;; m@׮]FVWWoܸH랛™ӇmmmN@zz޲iPcѢEG0, 052 FR@JӧKoɁtxx!Cp*99Y燇 ~pn,X.../YdN8d052 FR #pt(,ݸF"U8@vtHj#xNzhG0ypjS#`tZ@{cǎ ELmmO||FwCQZҹFcAAAF%jtqqP2V#)))%%)44N[ cmիW꠱;mڴ &@/Y乬Pmhh@فcccoݺnd0.RcMMlLTTl2((N#.VVV99971U RKvv6zFO{+++Ff͒N[;w`t2]% `0 `jd0 `0 F`0 `jdjd0 S#S#`0ݥFJURR e2 cP}x8e0 Ơz^@@@ssΝ;5_ܺu+(`0kr Av"""4g3 cQ@XX(ڵk"fNNN999Fð2/`0B?8"&==1ZMw OXRRblllcc#]jeeeiiuց׮](tH`0OEEEűc677K솪abbj1bDkk8 oGt`0 ƪ*c5RRRBCC455Łq4ٙ^ʪg0 ƨFPP=SFSSSSe0 ƀe{{;`0L `052 `0 S#`0L `052 Ԩ[_'@jmkQ.d7>|x# />jk{.L),uk#S͛dEs~y>F][K?z1hTŜ?pɂGI;d+a.ؽsOPf3t4ܿ򒔗>TEEuᙳ?z^RB ^9͸#66.+a]٥j={VumjiA1R{}.1J\ʲ՘so7>|'^A,2lR_19?oѮu+~jEPgtAgFW\gO$<.-Ų2Cn):N!w9yx(VQ[f+ITB T (Dn?z `٢"[Ԩn /OX@: &3my׮GG#TW?ܐoяfVƠF###8'NmY72F +%8p#\F'O*:"L&y\g Cl=rDpFPZkd$; Sb+ 7II8aaa|!2affv)/}6BOB! ټLok땕ȴ4WݰsOOhrݺ:XmƸ9t%eH (%j<]Xx>°qH N,~`Y6q! ,%R;z T]H9jE쌚`AGQ]v.@B= igᚃq҂U'hQ=x+Rqʩsh|Sp~p g!qjqXҌ޺eF=xĠiAxcG? Zd /q(,%>ԨqZZ}tttHHYľ孌D +*PeÇH;AfKtB8{Vta(= %eR$OVtၑC Ֆ-zS 9|DuF):{OFœ)5L6^0-"b o4kZj//.uwI6 dAܸՀ1QVR$'' Ճ->1*) 11hh"F6 4ZN[柔D+Kt~ !hW.#o)#9aa8i'\Cb1[v. lٴ;h@UAb 8N6WBW6:1em4+(MwUZ*LW{OS3)0(;\Cyz4%T8֚Lߵն #.' NZ?%wp?&$ J*CzS"W%\(պ ^ Q)h~z_=&Q?Un7bZeZKM0QI jk?ȴ;# a ]IT/c XjT MLLTT5V SwH֔I*V9hh*hc{| 1E ߇*556A t7>*]x,yEm'a ǝ3"3ss޶ O#SH6ob"*p%^`f Abhچ3;QҴ @"^Gq (z ()7'Ԓz2_%VWڅ@d589*]p2&+>hc?4R]1߃HKϜqͧB]&F3 V?fbΟl;=n@QAjѭswx ۖ"k:APgİ-94UǢ.J C*ni ]I%Z%F=wDSaR^d:Ԩ… EiNȉ>1+LᬬeK:|Cv4*OLb=Suχ :>DOn7,޽ұYtk)\wR;B34fKpXgR̟4A_R:a(JC =C"FS`Z &XTp7Mӈe@l$+!x; ݩ.h Et\HFc`DZCM\nKdM4_K ꢰ qB)^(_0B6uliնδ(=x@h8hbY$F[?x hjjBʕ+Z V谣;fe]nك-h]n? g 5pgL-XZk*iP <[508({YL[} ꆅUmf59x~޼ٲÇоB(3Fh6!sGA/a`yA_ԧTzʡ xWWKxzE$Nl5߉F0Q.udpBA99Nf#d!޻ HXQqߴiqoZ[`(;/r,d3yVVqt|ŗ-C$ezIMQ ~0{7 Cq 0(2ꡏxeG88OC1B!R@bv"OX?\nkbk|`ޘ^'}m"rs?_oPZ ZY C za[ܐBE(,VGgH/5*4^^i_r5WXY #\@ 77{H%P66-24PNN$D4  "2;Ԉ+eVV!1t ުHZd}OP#l]ܢxВsIHȢP#i .P#R0~IȢ%%}K̙y11ҬXڦ5!^j>n|R+" qtN;&Oe hԨU Cl;'Ɗ@ĜaD8yB!4޶8=cUi YT.hkv3L~> ]JģHKNZ;Bn,r+l*+X6vcqR.؈IԡSLQ<@j7g'Oa8ѻy{Fw3PL>wjD!B!99N'OYފ< 8DluIuP蝠IE6n@ YGz 2N}&jԥU Ԩ:LwLdNK9k?iȚrA/PԨfD VVUur254OXFFHo]1c F #/B+:x ~7VB{zy< '?bP$ZX8=;ƣ˄YX5FDLimxj,аxH8hJ s#C Ævm9ulic~}n#U'-<^PEE1ysMQ+ PYc(8@G<@xjTh\!ZhATeİʌ(Bޚ9N}_Q&HP ZA CAStz"?wt\זꔃ)|x^A.m ,%]@WMj  Y: @W;ңwH9LkjVVDEM0HnFESMK[ ˋ72Ɗ*&  H0#ZoQȌ(lwL ] >ܱ^MLCBY5S -P}*Z5teii(t ,f6+Pt`豰@ z+RN̸ҵ6/Ń' /K)W[> RVր֡ '-Yx"KHQiP&  ioߤAB&t5O]-*4]CfD]/6Z-JVF@:\ wzhDM%Z3u`5nv9 x{8j]* uA υ ᆗl^yoՍJvYzY40C *h435pjda!j\W<h41.i<h`ҹ )5ٽ-zEr 5QGqK@5[S7P̵>j޼Бwvp`A,,La> 0oLPu)(-k<<:x|E/S)5*)Â+Hڻזm#S㠖yi.zLŋ=lt %2y uii;Q7)D?οXu!ZHXzO 0]koC.TFB wLبw%_udvMsH;\"ZRqFϛgr_Adƌ:.M ĉch <*:z ;vt֖@(C#Gm,8CTwz܂ aEE"6}\X[[.X0 5x#dMvJjjR"?aTw̟?n,[[sdmPoИ$'LK'tsK _ҷ=_q50-6܀pz~wx'N՛u)P#ed bnnWx!E CA|Ax&C'OF5kFjCy\9M Sj)ӿ vWj>fZ|WN,wTЬkWšǯm@K D~ޝ3s8WxSl\Fdj=OJ\F:,?k~D~!ȘQxz}+BC7^˗4!~L@gEbj .Q#D(T׮]Lno/,<|&'GpwTrs=? YF Ք,,,J$F֊ĝ%% ?O.Rzif|i5-wXaQokz55BRjܗ灳vQceS䍰!+[ F0,qgGM%G zϞ # ucȿ_SkDFFz5*h95 ^q7OH tK|Ipڤk̮$,\P=]C :D=aCR̂X_G?xp ??8dPэ( W9tסC[JOOq4Y^#?b[4фVXxw}~.WYXv[""6ܹs%KihH!Zg.p*.&%ДJڅCKˑ`npH X\ zƍ:05ƚT٪teCvd|͗э1Ux{!?u, ]{Bo N\~[ɗ=_G!#OSB^q7Z%V߈HVj$ҿ:^IX1Kz˄ %{2Rii>sHOᛊÇ '_$t(|vTz#3 k%cbmXQM~@]qn46jwz.:³ѐTMcLb4JAFC Z+4pS*pX_,TUU9PeaaaaaajdyrtaU@I?wu&OKMݫi=:b52 `jd0 `0 F`0 `jd0 `0HA(jIENDB`././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/tutorial/index.rst0000644000175100001770000000044000000000000021015 0ustar00runnerdocker00000000000000Tutorials ========= .. toctree:: :maxdepth: 2 cython_tutorial external clibraries cdef_classes pxd_files caveats profiling_tutorial strings memory_allocation embedding pure numpy array parallelization readings related_work appendix ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/tutorial/memory_allocation.rst0000644000175100001770000000673500000000000023440 0ustar00runnerdocker00000000000000.. _memory_allocation: ***************** Memory Allocation ***************** .. include:: ../two-syntax-variants-used Dynamic memory allocation is mostly a non-issue in Python. Everything is an object, and the reference counting system and garbage collector automatically return memory to the system when it is no longer being used. When it comes to more low-level data buffers, Cython has special support for (multi-dimensional) arrays of simple types via NumPy, memory views or Python's stdlib array type. They are full featured, garbage collected and much easier to work with than bare pointers in C, while still retaining the speed and static typing benefits. See :ref:`array-array` and :ref:`memoryviews`. In some situations, however, these objects can still incur an unacceptable amount of overhead, which can then makes a case for doing manual memory management in C. Simple C values and structs (such as a local variable ``cdef double x`` / ``x: cython.double``) are usually :term:`allocated on the stack` and passed by value, but for larger and more complicated objects (e.g. a dynamically-sized list of doubles), the memory must be :term:`manually requested and released`. C provides the functions :c:func:`malloc`, :c:func:`realloc`, and :c:func:`free` for this purpose, which can be imported in cython from ``clibc.stdlib``. Their signatures are: .. code-block:: c void* malloc(size_t size) void* realloc(void* ptr, size_t size) void free(void* ptr) A very simple example of malloc usage is the following: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/memory_allocation/malloc.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/memory_allocation/malloc.pyx Note that the C-API functions for allocating memory on the Python heap are generally preferred over the low-level C functions above as the memory they provide is actually accounted for in Python's internal memory management system. They also have special optimisations for smaller memory blocks, which speeds up their allocation by avoiding costly operating system calls. The C-API functions can be found in the ``cpython.mem`` standard declarations file: .. tabs:: .. group-tab:: Pure Python .. code-block:: python from cython.cimports.cpython.mem import PyMem_Malloc, PyMem_Realloc, PyMem_Free .. group-tab:: Cython .. code-block:: cython from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free Their interface and usage is identical to that of the corresponding low-level C functions. One important thing to remember is that blocks of memory obtained with :c:func:`malloc` or :c:func:`PyMem_Malloc` *must* be manually released with a corresponding call to :c:func:`free` or :c:func:`PyMem_Free` when they are no longer used (and *must* always use the matching type of free function). Otherwise, they won't be reclaimed until the python process exits. This is called a memory leak. If a chunk of memory needs a larger lifetime than can be managed by a ``try..finally`` block, another helpful idiom is to tie its lifetime to a Python object to leverage the Python runtime's memory management, e.g.: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/memory_allocation/some_memory.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/memory_allocation/some_memory.pyx ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/tutorial/numpy.rst0000644000175100001770000001751100000000000021065 0ustar00runnerdocker00000000000000.. _working-numpy: ======================= Working with NumPy ======================= .. NOTE:: Cython 0.16 introduced typed memoryviews as a successor to the NumPy integration described here. They are easier to use than the buffer syntax below, have less overhead, and can be passed around without requiring the GIL. They should be preferred to the syntax presented in this page. See :ref:`Cython for NumPy users `. You can use NumPy from Cython exactly the same as in regular Python, but by doing so you are losing potentially high speedups because Cython has support for fast access to NumPy arrays. Let's see how this works with a simple example. The code below does 2D discrete convolution of an image with a filter (and I'm sure you can do better!, let it serve for demonstration purposes). It is both valid Python and valid Cython code. I'll refer to it as both :file:`convolve_py.py` for the Python version and :file:`convolve1.pyx` for the Cython version -- Cython uses ".pyx" as its file suffix. .. literalinclude:: ../../examples/tutorial/numpy/convolve_py.py This should be compiled to produce :file:`yourmod.so` (for Linux systems, on Windows systems, it will be :file:`yourmod.pyd`). We run a Python session to test both the Python version (imported from ``.py``-file) and the compiled Cython module. .. code-block:: ipythonconsole In [1]: import numpy as np In [2]: import convolve_py In [3]: convolve_py.naive_convolve(np.array([[1, 1, 1]], dtype=np.int64), ... np.array([[1],[2],[1]], dtype=np.int64)) Out [3]: array([[1, 1, 1], [2, 2, 2], [1, 1, 1]]) In [4]: import convolve1 In [4]: convolve1.naive_convolve(np.array([[1, 1, 1]], dtype=np.int64), ... np.array([[1],[2],[1]], dtype=np.int64)) Out [4]: array([[1, 1, 1], [2, 2, 2], [1, 1, 1]]) In [11]: N = 100 In [12]: f = np.arange(N*N, dtype=np.int64).reshape((N,N)) In [13]: g = np.arange(81, dtype=np.int64).reshape((9, 9)) In [19]: %timeit -n2 -r3 convolve_py.naive_convolve(f, g) 2 loops, best of 3: 1.86 s per loop In [20]: %timeit -n2 -r3 convolve1.naive_convolve(f, g) 2 loops, best of 3: 1.41 s per loop There's not such a huge difference yet; because the C code still does exactly what the Python interpreter does (meaning, for instance, that a new object is allocated for each number used). Look at the generated html file and see what is needed for even the simplest statements you get the point quickly. We need to give Cython more information; we need to add types. Adding types ============= To add types we use custom Cython syntax, so we are now breaking Python source compatibility. Consider this code (*read the comments!*) : .. literalinclude:: ../../examples/tutorial/numpy/convolve2.pyx After building this and continuing my (very informal) benchmarks, I get: .. code-block:: ipythonconsole In [21]: import convolve2 In [22]: %timeit -n2 -r3 convolve2.naive_convolve(f, g) 2 loops, best of 3: 828 ms per loop Efficient indexing ==================== There's still a bottleneck killing performance, and that is the array lookups and assignments. The ``[]``-operator still uses full Python operations -- what we would like to do instead is to access the data buffer directly at C speed. What we need to do then is to type the contents of the :obj:`ndarray` objects. We do this with a special "buffer" syntax which must be told the datatype (first argument) and number of dimensions ("ndim" keyword-only argument, if not provided then one-dimensional is assumed). These are the needed changes:: ... def naive_convolve(cnp.ndarray[DTYPE_t, ndim=2] f, cnp.ndarray[DTYPE_t, ndim=2] g): ... cdef cnp.ndarray[DTYPE_t, ndim=2] h = ... Usage: .. code-block:: ipythonconsole In [18]: import convolve3 In [19]: %timeit -n3 -r100 convolve3.naive_convolve(f, g) 3 loops, best of 100: 11.6 ms per loop Note the importance of this change. *Gotcha*: This efficient indexing only affects certain index operations, namely those with exactly ``ndim`` number of typed integer indices. So if ``v`` for instance isn't typed, then the lookup ``f[v, w]`` isn't optimized. On the other hand this means that you can continue using Python objects for sophisticated dynamic slicing etc. just as when the array is not typed. Tuning indexing further ======================== The array lookups are still slowed down by two factors: 1. Bounds checking is performed. 2. Negative indices are checked for and handled correctly. The code above is explicitly coded so that it doesn't use negative indices, and it (hopefully) always access within bounds. We can add a decorator to disable bounds checking:: ... cimport cython @cython.boundscheck(False) # turn off bounds-checking for entire function @cython.wraparound(False) # turn off negative index wrapping for entire function def naive_convolve(cnp.ndarray[DTYPE_t, ndim=2] f, cnp.ndarray[DTYPE_t, ndim=2] g): ... Now bounds checking is not performed (and, as a side-effect, if you ''do'' happen to access out of bounds you will in the best case crash your program and in the worst case corrupt data). It is possible to switch bounds-checking mode in many ways, see :ref:`compiler-directives` for more information. Also, we've disabled the check to wrap negative indices (e.g. g[-1] giving the last value). As with disabling bounds checking, bad things will happen if we try to actually use negative indices with this disabled. The function call overhead now starts to play a role, so we compare the latter two examples with larger N: .. code-block:: ipythonconsole In [11]: %timeit -n3 -r100 convolve4.naive_convolve(f, g) 3 loops, best of 100: 5.97 ms per loop In [12]: N = 1000 In [13]: f = np.arange(N*N, dtype=np.int64).reshape((N,N)) In [14]: g = np.arange(81, dtype=np.int64).reshape((9, 9)) In [17]: %timeit -n1 -r10 convolve3.naive_convolve(f, g) 1 loops, best of 10: 1.16 s per loop In [18]: %timeit -n1 -r10 convolve4.naive_convolve(f, g) 1 loops, best of 10: 597 ms per loop (Also this is a mixed benchmark as the result array is allocated within the function call.) .. Warning:: Speed comes with some cost. Especially it can be dangerous to set typed objects (like ``f``, ``g`` and ``h`` in our sample code) to ``None``. Setting such objects to ``None`` is entirely legal, but all you can do with them is check whether they are None. All other use (attribute lookup or indexing) can potentially segfault or corrupt data (rather than raising exceptions as they would in Python). The actual rules are a bit more complicated but the main message is clear: Do not use typed objects without knowing that they are not set to None. What typing does not do ======================= The main purpose of typing things as :obj:`ndarray` is to allow efficient indexing of single elements, and to speed up access to a small number of attributes such as ``.shape``. Typing does not allow Cython to speed up mathematical operations on the whole array (for example, adding two arrays together). Typing does not allow Cython to speed up calls to Numpy global functions or to methods of the array. More generic code ================== It would be possible to do:: def naive_convolve(object[DTYPE_t, ndim=2] f, ...): i.e. use :obj:`object` rather than :obj:`cnp.ndarray`. Under Python 3.0 this can allow your algorithm to work with any libraries supporting the buffer interface; and support for e.g. the Python Imaging Library may easily be added if someone is interested also under Python 2.x. There is some speed penalty to this though (as one makes more assumptions compile-time if the type is set to :obj:`cnp.ndarray`, specifically it is assumed that the data is stored in pure strided mode and not in indirect mode). ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/tutorial/parallelization.rst0000644000175100001770000002752100000000000023111 0ustar00runnerdocker00000000000000.. _parallel-tutorial: ================================= Writing parallel code with Cython ================================= .. include:: ../two-syntax-variants-used One method of speeding up your Cython code is parallelization: you write code that can be run on multiple cores of your CPU simultaneously. For code that lends itself to parallelization this can produce quite dramatic speed-ups, equal to the number of cores your CPU has (for example a 4× speed-up on a 4-core CPU). This tutorial assumes that you are already familiar with Cython's :ref:`"typed memoryviews"` (since code using memoryviews is often the sort of code that's easy to parallelize with Cython), and also that you're somewhat familiar with the pitfalls of writing parallel code in general (it aims to be a Cython tutorial rather than a complete introduction to parallel programming). Before starting, a few notes: - Not all code can be parallelized - for some code the algorithm simply relies on being executed in order and you should not attempt to parallelize it. A cumulative sum is a good example. - Not all code is worth parallelizing. There's a reasonable amount of overhead in starting a parallel section and so you need to make sure that you're operating on enough data to make this overhead worthwhile. Additionally, make sure that you are doing actual work on the data! Multiple threads simply reading the same data tends not to parallelize too well. If in doubt, time it. - Cython requires the contents of parallel blocks to be ``nogil``. If your algorithm requires access to Python objects then it may not be suitable for parallelization. - Cython's inbuilt parallelization uses the OpenMP constructs ``omp parallel for`` and ``omp parallel``. These are ideal for parallelizing relatively small, self-contained blocks of code (especially loops). However, If you want to use other models of parallelization such as spawning and waiting for tasks, or off-loading some "side work" to a continuously running secondary thread, then you might be better using other methods (such as Python's ``threading`` module). - Actually implementing your parallel Cython code should probably be one of the last steps in your optimization. You should start with some working serial code first. However, it's worth planning for early since it may affect your choice of algorithm. This tutorial does not aim to explore all the options available to customize parallelization. See the :ref:`main parallelism documentation` for details. You should also be aware that a lot of the choices Cython makes about how your code is parallelized are fairly fixed and if you want specific OpenMP behaviour that Cython doesn't provide by default you may be better writing it in C yourself. Compilation =========== OpenMP requires support from your C/C++ compiler. This support is usually enabled through a special command-line argument: on GCC this is ``-fopenmp`` while on MSVC it is ``/openmp``. If your compiler doesn't support OpenMP (or if you forget to pass the argument) then the code will usually still compile but will not run in parallel. The following ``setup.py`` file can be used to compile the examples in this tutorial: .. literalinclude:: ../../examples/tutorial/parallelization/setup.py Element-wise parallel operations ================================ The easiest and most common parallel operation in Cython is to iterate across an array element-wise, performing the same operation on each array element. In the simple example below we calculate the ``sin`` of every element in an array: .. tabs:: .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/parallelization/parallel_sin.pyx .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/parallelization/parallel_sin.py We parallelize the outermost loop. This is usually a good idea since there is some overhead to entering and leaving a parallel block. However, you should also consider the likely size of your arrays. If ``input`` usually had a size of ``(2, 10000000)`` then parallelizing over the dimension of length ``2`` would likely be a worse choice. The body of the loop itself is ``nogil`` - i.e. you cannot perform "Python" operations. This is a fairly strong limitation and if you find that you need to use the GIL then it is likely that Cython's parallelization features are not suitable for you. It is possible to throw exceptions from within the loop, however -- Cython simply regains the GIL and raises an exception, then terminates the loop on all threads. It's necessary to explicitly type the loop variable ``i`` as a C integer. For a non-parallel loop Cython can infer this, but it does not currently infer the loop variable for parallel loops, so not typing ``i`` will lead to compile errors since it will be a Python object and so unusable without the GIL. The C code generated is shown below, for the benefit of experienced users of OpenMP. It is simplified a little for readability here: .. code-block:: C #pragma omp parallel { #pragma omp for firstprivate(i) lastprivate(i) lastprivate(j) for (__pyx_t_8 = 0; __pyx_t_8 < __pyx_t_9; __pyx_t_8++){ i = __pyx_t_8; /* body goes here */ } } Private variables ----------------- One useful point to note from the generated C code above - variables used in the loops like ``i`` and ``j`` are marked as ``firstprivate`` and ``lastprivate``. Within the loop each thread has its own copy of the data, the data is initialized according to its value before the loop, and after the loop the "global" copy is set equal to the last iteration (i.e. as if the loop were run in serial). The basic rules that Cython applies are: - C scalar variables within a ``prange`` block are made ``firstprivate`` and ``lastprivate``, - C scalar variables assigned within a :ref:`parallel block` are ``private`` (which means they can't be used to pass data in and out of the block), - array variables (e.g. memoryviews) are not made private. Instead Cython assumes that you have structured your loop so that each iteration is acting on different data, - Python objects are also not made private, although access to them is controlled via Python's GIL. Cython does not currently provide much opportunity of override these choices. Reductions ========== The second most common parallel operation in Cython is the "reduction" operation. A common example is to accumulate a sum over the whole array, such as in the calculation of a vector norm below: .. tabs:: .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/parallelization/norm.pyx .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/parallelization/norm.py Cython is able to infer reductions for ``+=``, ``*=``, ``-=``, ``&=``, ``|=``, and ``^=``. These only apply to C scalar variables so you cannot easily reduce a 2D memoryview to a 1D memoryview for example. The C code generated is approximately: .. code-block:: C #pragma omp parallel reduction(+:total) { #pragma omp for firstprivate(i) lastprivate(i) for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_3; __pyx_t_2++){ i = __pyx_t_2; total = total + /* some indexing code */; } } .. _parallel-block: ``parallel`` blocks =================== Much less frequently used than ``prange`` is Cython's ``parallel`` operator. ``parallel`` generates a block of code that is run simultaneously on multiple threads at once. Unlike ``prange``, however, work is not automatically divided between threads. Here we present three common uses for the ``parallel`` block: Stringing together prange blocks -------------------------------- There is some overhead in entering and leaving a parallelized section. Therefore, if you have multiple parallel sections with small serial sections in between it can be more efficient to write one large parallel block. Any small serial sections are duplicated, but the overhead is reduced. In the example below we do an in-place normalization of a vector. The first parallel loop calculates the norm, the second parallel loop applies the norm to the vector, and we avoid jumping in and out of serial code in between. .. tabs:: .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/parallelization/normalize.pyx .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/parallelization/normalize.py The C code is approximately: .. code-block:: C #pragma omp parallel private(norm) reduction(+:total) { /* some calculations of array size... */ #pragma omp for firstprivate(i) lastprivate(i) for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_3; __pyx_t_2++){ /* ... */ } norm = sqrt(total); #pragma omp for firstprivate(i) lastprivate(i) for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_3; __pyx_t_2++){ /* ... */ } } Allocating "scratch space" for each thread ------------------------------------------ Suppose that each thread requires a small amount of scratch space to work in. They cannot share scratch space because that would lead to data races. In this case the allocation and deallocation is done in a parallel section (so occurs on a per-thread basis) surrounding a loop which then uses the scratch space. Our example here uses C++ to find the median of each column in a 2D array (just a parallel version of ``numpy.median(x, axis=0)``). We must reorder each column to find the median of it, but don't want to modify the input array. Therefore, we allocate a C++ vector per thread to use as scratch space, and work in that. For efficiency the vector is allocated outside the ``prange`` loop. .. tabs:: .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/parallelization/median.pyx .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/parallelization/median.py .. note:: Pure and classic syntax examples are not quite identical since pure Python syntax does not support C++ "new", so we allocate the scratch space slightly differently In the generated code the ``scratch`` variable is marked as ``private`` in the outer parallel block. A rough outline is: .. code-block:: C++ #pragma omp parallel private(scratch) { scratch = new std::vector ((x.shape[0])) #pragma omp for firstprivate(i) lastprivate(i) lastprivate(j) lastprivate(median_it) for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_10; __pyx_t_9++){ i = __pyx_t_9; /* implementation goes here */ } /* some exception handling detail omitted */ delete scratch; } Performing different tasks on each thread ----------------------------------------- Finally, if you manually specify the number of threads and then identify each thread using ``omp.get_thread_num()`` you can manually split work between threads. This is a fairly rare use-case in Cython, and probably suggests that the ``threading`` module is more suitable for what you're trying to do. However it is an option. .. tabs:: .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/parallelization/manual_work.pyx :lines: 2- .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/parallelization/manual_work.py :lines: 2- The utility of this kind of block is limited by the fact that variables assigned to in the block are ``private`` to each thread, so cannot be accessed in the serial section afterwards. The generated C code for the example above is fairly simple: .. code-block:: C #pragma omp parallel private(thread_num) { thread_num = omp_get_thread_num(); switch (thread_num) { /* ... */ } } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/tutorial/profiling_tutorial.rst0000644000175100001770000003733000000000000023632 0ustar00runnerdocker00000000000000.. highlight:: cython .. _profiling: ********* Profiling ********* .. include:: ../two-syntax-variants-used This part describes the profiling abilities of Cython. If you are familiar with profiling pure Python code, you can only read the first section (:ref:`profiling_basics`). If you are not familiar with Python profiling you should also read the tutorial (:ref:`profiling_tutorial`) which takes you through a complete example step by step. .. _profiling_basics: Cython Profiling Basics ======================= Profiling in Cython is controlled by a compiler directive. It can be set either for an entire file or on a per function basis via a Cython decorator. Enabling profiling for a complete source file --------------------------------------------- Profiling is enabled for a complete source file via a global directive to the Cython compiler at the top of a file:: # cython: profile=True Note that profiling gives a slight overhead to each function call therefore making your program a little slower (or a lot, if you call some small functions very often). Once enabled, your Cython code will behave just like Python code when called from the cProfile module. This means you can just profile your Cython code together with your Python code using the same tools as for Python code alone. Disabling profiling function wise --------------------------------- If your profiling is messed up because of the call overhead to some small functions that you rather do not want to see in your profile - either because you plan to inline them anyway or because you are sure that you can't make them any faster - you can use a special decorator to disable profiling for one function only (regardless of whether it is globally enabled or not): .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/profiling_tutorial/often_called.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/profiling_tutorial/often_called.pyx Enabling line tracing --------------------- To get more detailed trace information (for tools that can make use of it), you can enable line tracing:: # cython: linetrace=True This will also enable profiling support, so the above ``profile=True`` option is not needed. Line tracing is needed for coverage analysis, for example. Note that even if line tracing is enabled via the compiler directive, it is not used by default. As the runtime slowdown can be substantial, it must additionally be compiled in by the C compiler by setting the C macro definition ``CYTHON_TRACE=1``. To include nogil functions in the trace, set ``CYTHON_TRACE_NOGIL=1`` (which implies ``CYTHON_TRACE=1``). C macros can be defined either in the extension definition of the ``setup.py`` script or by setting the respective distutils options in the source file with the following file header comment (if ``cythonize()`` is used for compilation):: # distutils: define_macros=CYTHON_TRACE_NOGIL=1 Enabling coverage analysis -------------------------- Since Cython 0.23, line tracing (see above) also enables support for coverage reporting with the `coverage.py `_ tool. To make the coverage analysis understand Cython modules, you also need to enable Cython's coverage plugin in your ``.coveragerc`` file as follows: .. code-block:: ini [run] plugins = Cython.Coverage With this plugin, your Cython source files should show up normally in the coverage reports. To include the coverage report in the Cython annotated HTML file, you need to first run the coverage.py tool to generate an XML result file. Pass this file into the ``cython`` command as follows: .. code-block:: bash $ cython --annotate-coverage coverage.xml package/mymodule.pyx This will recompile the Cython module and generate one HTML output file next to each Cython source file it processes, containing colour markers for lines that were contained in the coverage report. .. _profiling_tutorial: Profiling Tutorial ================== This will be a complete tutorial, start to finish, of profiling Python code, turning it into Cython code and keep profiling until it is fast enough. As a toy example, we would like to evaluate the summation of the reciprocals of squares up to a certain integer :math:`n` for evaluating :math:`\pi`. The relation we want to use has been proven by Euler in 1735 and is known as the `Basel problem `_. .. math:: \pi^2 = 6 \sum_{k=1}^{\infty} \frac{1}{k^2} = 6 \lim_{k \to \infty} \big( \frac{1}{1^2} + \frac{1}{2^2} + \dots + \frac{1}{k^2} \big) \approx 6 \big( \frac{1}{1^2} + \frac{1}{2^2} + \dots + \frac{1}{n^2} \big) A simple Python code for evaluating the truncated sum looks like this: .. literalinclude:: ../../examples/tutorial/profiling_tutorial/calc_pi.py :caption: calc_pi.py On my box, this needs approximately 4 seconds to run the function with the default n. The higher we choose n, the better will be the approximation for :math:`\pi`. An experienced Python programmer will already see plenty of places to optimize this code. But remember the golden rule of optimization: Never optimize without having profiled. Let me repeat this: **Never** optimize without having profiled your code. Your thoughts about which part of your code takes too much time are wrong. At least, mine are always wrong. So let's write a short script to profile our code: .. literalinclude:: ../../examples/tutorial/profiling_tutorial/profile.py :caption: profile.py Running this on my box gives the following output: .. code-block:: none Sat Nov 7 17:40:54 2009 Profile.prof 10000004 function calls in 6.211 CPU seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 1 3.243 3.243 6.211 6.211 calc_pi.py:4(approx_pi) 10000000 2.526 0.000 2.526 0.000 calc_pi.py:1(recip_square) 1 0.442 0.442 0.442 0.442 {range} 1 0.000 0.000 6.211 6.211 :1() 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} This contains the information that the code runs in 6.2 CPU seconds. Note that the code got slower by 2 seconds because it ran inside the cProfile module. The table contains the real valuable information. You might want to check the Python `profiling documentation `_ for the nitty gritty details. The most important columns here are totime (total time spent in this function **not** counting functions that were called by this function) and cumtime (total time spent in this function **also** counting the functions called by this function). Looking at the tottime column, we see that approximately half the time is spent in ``approx_pi()`` and the other half is spent in ``recip_square()``. Also half a second is spent in range ... of course we should have used xrange for such a big iteration. And in fact, just changing range to xrange makes the code run in 5.8 seconds. We could optimize a lot in the pure Python version, but since we are interested in Cython, let's move forward and bring this module to Cython. We would do this anyway at some time to get the loop run faster. Here is our first Cython version: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/profiling_tutorial/calc_pi_2.py :caption: calc_pi.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/profiling_tutorial/calc_pi_2.pyx :caption: calc_pi.pyx Note the first line: We have to tell Cython that profiling should be enabled. This makes the Cython code slightly slower, but without this we would not get meaningful output from the cProfile module. The rest of the code is mostly unchanged, I only typed some variables which will likely speed things up a bit. We also need to modify our profiling script to import the Cython module directly. Here is the complete version adding the import of the :ref:`Pyximport` module: .. literalinclude:: ../../examples/tutorial/profiling_tutorial/profile_2.py :caption: profile.py We only added two lines, the rest stays completely the same. Alternatively, we could also manually compile our code into an extension; we wouldn't need to change the profile script then at all. The script now outputs the following: .. tabs:: .. group-tab:: Pure Python .. code-block:: none Sat Nov 7 18:02:33 2009 Profile.prof 10000004 function calls in 4.406 CPU seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 1 3.305 3.305 4.406 4.406 calc_pi.py:6(approx_pi) 10000000 1.101 0.000 1.101 0.000 calc_pi.py:3(recip_square) 1 0.000 0.000 4.406 4.406 {calc_pi.approx_pi} 1 0.000 0.000 4.406 4.406 :1() 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} .. group-tab:: Cython .. code-block:: none Sat Nov 7 18:02:33 2009 Profile.prof 10000004 function calls in 4.406 CPU seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 1 3.305 3.305 4.406 4.406 calc_pi.pyx:6(approx_pi) 10000000 1.101 0.000 1.101 0.000 calc_pi.pyx:3(recip_square) 1 0.000 0.000 4.406 4.406 {calc_pi.approx_pi} 1 0.000 0.000 4.406 4.406 :1() 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} We gained 1.8 seconds. Not too shabby. Comparing the output to the previous, we see that the ``recip_square()`` function got faster while the ``approx_pi()`` function has not changed a lot. Let's concentrate on the ``recip_square()`` function a bit more. First, note that this function is not to be called from code outside of our module; so it would be wise to turn it into a cdef to reduce call overhead. We should also get rid of the power operator: it is turned into a ``pow(i, 2)`` function call by Cython, but we could instead just write ``i * i`` which could be faster. The whole function is also a good candidate for inlining. Let's look at the necessary changes for these ideas: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/profiling_tutorial/calc_pi_3.py :caption: calc_pi.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/profiling_tutorial/calc_pi_3.pyx :caption: calc_pi.pyx Note that the ``except``/``@exceptval`` declaration is needed in the signature of ``recip_square()`` in order to propagate division by zero errors. Now running the profile script yields: .. tabs:: .. group-tab:: Pure Python .. code-block:: none Sat Nov 7 18:10:11 2009 Profile.prof 10000004 function calls in 2.622 CPU seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 1 1.782 1.782 2.622 2.622 calc_pi.py:9(approx_pi) 10000000 0.840 0.000 0.840 0.000 calc_pi.py:6(recip_square) 1 0.000 0.000 2.622 2.622 {calc_pi.approx_pi} 1 0.000 0.000 2.622 2.622 :1() 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} .. group-tab:: Cython .. code-block:: none Sat Nov 7 18:10:11 2009 Profile.prof 10000004 function calls in 2.622 CPU seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 1 1.782 1.782 2.622 2.622 calc_pi.pyx:9(approx_pi) 10000000 0.840 0.000 0.840 0.000 calc_pi.pyx:6(recip_square) 1 0.000 0.000 2.622 2.622 {calc_pi.approx_pi} 1 0.000 0.000 2.622 2.622 :1() 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} That bought us another 1.8 seconds. Not the dramatic change we could have expected. And why is ``recip_square()`` still in this table; it is supposed to be inlined, isn't it? The reason for this is that Cython still generates profiling code even if the function call is eliminated. Let's tell it to not profile ``recip_square()`` any more; we couldn't get the function to be much faster anyway: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/profiling_tutorial/calc_pi_4.py :caption: calc_pi.py .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/profiling_tutorial/calc_pi_4.pyx :caption: calc_pi.pyx Running this shows an interesting result: .. tabs:: .. group-tab:: Pure Python .. code-block:: none Sat Nov 7 18:15:02 2009 Profile.prof 4 function calls in 0.089 CPU seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 1 0.089 0.089 0.089 0.089 calc_pi.py:12(approx_pi) 1 0.000 0.000 0.089 0.089 {calc_pi.approx_pi} 1 0.000 0.000 0.089 0.089 :1() 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} .. group-tab:: Cython .. code-block:: none Sat Nov 7 18:15:02 2009 Profile.prof 4 function calls in 0.089 CPU seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 1 0.089 0.089 0.089 0.089 calc_pi.pyx:12(approx_pi) 1 0.000 0.000 0.089 0.089 {calc_pi.approx_pi} 1 0.000 0.000 0.089 0.089 :1() 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} First note the tremendous speed gain: this version only takes 1/50 of the time of our first Cython version. Also note that ``recip_square()`` has vanished from the table like we wanted. But the most peculiar and important change is that ``approx_pi()`` also got much faster. This is a problem with all profiling: calling a function in a profile run adds a certain overhead to the function call. This overhead is **not** added to the time spent in the called function, but to the time spent in the **calling** function. In this example, ``approx_pi()`` didn't need 2.622 seconds in the last run; but it called ``recip_square()`` 10000000 times, each time taking a little to set up profiling for it. This adds up to the massive time loss of around 2.6 seconds. Having disabled profiling for the often called function now reveals realistic timings for ``approx_pi()``; we could continue optimizing it now if needed. This concludes this profiling tutorial. There is still some room for improvement in this code. We could try to replace the power operator in ``approx_pi()`` with a call to sqrt from the C stdlib; but this is not necessarily faster than calling ``pow(x, 0.5)``. Even so, the result we achieved here is quite satisfactory: we came up with a solution that is much faster then our original Python version while retaining functionality and readability. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/tutorial/pure.rst0000644000175100001770000004354400000000000020675 0ustar00runnerdocker00000000000000 .. _pure-mode: Pure Python Mode ================ In some cases, it's desirable to speed up Python code without losing the ability to run it with the Python interpreter. While pure Python scripts can be compiled with Cython, it usually results only in a speed gain of about 20%-50%. To go beyond that, Cython provides language constructs to add static typing and cythonic functionalities to a Python module to make it run much faster when compiled, while still allowing it to be interpreted. This is accomplished via an augmenting ``.pxd`` file, via Python type :ref:`pep484_type_annotations` (following `PEP 484 `_ and `PEP 526 `_), and/or via special functions and decorators available after importing the magic ``cython`` module. All three ways can be combined at need, although projects would commonly decide on a specific way to keep the static type information easy to manage. Although it is not typically recommended over writing straight Cython code in a :file:`.pyx` file, there are legitimate reasons to do this - easier testing and debugging, collaboration with pure Python developers, etc. In pure mode, you are more or less restricted to code that can be expressed (or at least emulated) in Python, plus static type declarations. Anything beyond that can only be done in .pyx files with extended language syntax, because it depends on features of the Cython compiler. .. _augmenting_pxd: Augmenting .pxd --------------- Using an augmenting :file:`.pxd` allows to let the original :file:`.py` file completely untouched. On the other hand, one needs to maintain both the :file:`.pxd` and the :file:`.py` to keep them in sync. While declarations in a :file:`.pyx` file must correspond exactly with those of a :file:`.pxd` file with the same name (and any contradiction results in a compile time error, see :doc:`pxd_files`), the untyped definitions in a :file:`.py` file can be overridden and augmented with static types by the more specific ones present in a :file:`.pxd`. If a :file:`.pxd` file is found with the same name as the :file:`.py` file being compiled, it will be searched for :keyword:`cdef` classes and :keyword:`cdef`/:keyword:`cpdef` functions and methods. The compiler will then convert the corresponding classes/functions/methods in the :file:`.py` file to be of the declared type. Thus if one has a file :file:`A.py`: .. literalinclude:: ../../examples/tutorial/pure/A.py and adds :file:`A.pxd`: .. literalinclude:: ../../examples/tutorial/pure/A.pxd then Cython will compile the :file:`A.py` as if it had been written as follows: .. literalinclude:: ../../examples/tutorial/pure/A_equivalent.pyx Notice how in order to provide the Python wrappers to the definitions in the :file:`.pxd`, that is, to be accessible from Python, * Python visible function signatures must be declared as `cpdef` (with default arguments replaced by a `*` to avoid repetition):: cpdef int myfunction(int x, int y=*) * C function signatures of internal functions can be declared as `cdef`:: cdef double _helper(double a) * `cdef` classes (extension types) are declared as `cdef class`; * `cdef` class attributes must be declared as `cdef public` if read/write Python access is needed, `cdef readonly` for read-only Python access, or plain `cdef` for internal C level attributes; * `cdef` class methods must be declared as `cpdef` for Python visible methods or `cdef` for internal C methods. In the example above, the type of the local variable `a` in `myfunction()` is not fixed and will thus be a :term:`Python object`. To statically type it, one can use Cython's ``@cython.locals`` decorator (see :ref:`magic_attributes`, and :ref:`magic_attributes_pxd`). Normal Python (:keyword:`def`) functions cannot be declared in :file:`.pxd` files. It is therefore currently impossible to override the types of plain Python functions in :file:`.pxd` files, e.g. to override types of their local variables. In most cases, declaring them as `cpdef` will work as expected. .. _magic_attributes: Magic Attributes ---------------- Special decorators are available from the magic ``cython`` module that can be used to add static typing within the Python file, while being ignored by the interpreter. This option adds the ``cython`` module dependency to the original code, but does not require to maintain a supplementary :file:`.pxd` file. Cython provides a fake version of this module as `Cython.Shadow`, which is available as `cython.py` when Cython is installed, but can be copied to be used by other modules when Cython is not installed. "Compiled" switch ^^^^^^^^^^^^^^^^^ * ``compiled`` is a special variable which is set to ``True`` when the compiler runs, and ``False`` in the interpreter. Thus, the code .. literalinclude:: ../../examples/tutorial/pure/compiled_switch.py will behave differently depending on whether or not the code is executed as a compiled extension (:file:`.so`/:file:`.pyd`) module or a plain :file:`.py` file. Static typing ^^^^^^^^^^^^^ * ``cython.declare`` declares a typed variable in the current scope, which can be used in place of the :samp:`cdef type var [= value]` construct. This has two forms, the first as an assignment (useful as it creates a declaration in interpreted mode as well): .. literalinclude:: ../../examples/tutorial/pure/cython_declare.py and the second mode as a simple function call: .. literalinclude:: ../../examples/tutorial/pure/cython_declare2.py It can also be used to define extension type private, readonly and public attributes: .. literalinclude:: ../../examples/tutorial/pure/cclass.py * ``@cython.locals`` is a decorator that is used to specify the types of local variables in the function body (including the arguments): .. literalinclude:: ../../examples/tutorial/pure/locals.py * ``@cython.returns()`` specifies the function's return type. * ``@cython.exceptval(value=None, *, check=False)`` specifies the function's exception return value and exception check semantics as follows:: @exceptval(-1) # cdef int func() except -1: @exceptval(-1, check=False) # cdef int func() except -1: @exceptval(check=True) # cdef int func() except *: @exceptval(-1, check=True) # cdef int func() except? -1: @exceptval(check=False) # no exception checking/propagation If exception propagation is disabled, any Python exceptions that are raised inside of the function will be printed and ignored. C types ^^^^^^^ There are numerous types built into the Cython module. It provides all the standard C types, namely ``char``, ``short``, ``int``, ``long``, ``longlong`` as well as their unsigned versions ``uchar``, ``ushort``, ``uint``, ``ulong``, ``ulonglong``. The special ``bint`` type is used for C boolean values and ``Py_ssize_t`` for (signed) sizes of Python containers. For each type, there are pointer types ``p_int``, ``pp_int``, etc., up to three levels deep in interpreted mode, and infinitely deep in compiled mode. Further pointer types can be constructed with ``cython.pointer(cython.int)``, and arrays as ``cython.int[10]``. A limited attempt is made to emulate these more complex types, but only so much can be done from the Python language. The Python types int, long and bool are interpreted as C ``int``, ``long`` and ``bint`` respectively. Also, the Python builtin types ``list``, ``dict``, ``tuple``, etc. may be used, as well as any user defined types. Typed C-tuples can be declared as a tuple of C types. Extension types and cdef functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * The class decorator ``@cython.cclass`` creates a ``cdef class``. * The function/method decorator ``@cython.cfunc`` creates a :keyword:`cdef` function. * ``@cython.ccall`` creates a :keyword:`cpdef` function, i.e. one that Cython code can call at the C level. * ``@cython.locals`` declares local variables (see above). It can also be used to declare types for arguments, i.e. the local variables that are used in the signature. * ``@cython.inline`` is the equivalent of the C ``inline`` modifier. * ``@cython.final`` terminates the inheritance chain by preventing a type from being used as a base class, or a method from being overridden in subtypes. This enables certain optimisations such as inlined method calls. Here is an example of a :keyword:`cdef` function:: @cython.cfunc @cython.returns(cython.bint) @cython.locals(a=cython.int, b=cython.int) def c_compare(a,b): return a == b Managing the Global Interpreter Lock ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * ``cython.nogil`` can be used as a context manager or as a decorator to replace the :keyword:`nogil` keyword:: with cython.nogil: # code block with the GIL released @cython.nogil @cython.cfunc def func_released_gil() -> cython.int: # function that can be run with the GIL released Note that the two uses differ: the context manager releases the GIL while the decorator marks that a function *can* be run without the GIL. See :ref:`` for more details. * ``cython.gil`` can be used as a context manager to replace the :keyword:`gil` keyword:: with cython.gil: # code block with the GIL acquired .. Note:: Cython currently does not support the ``@cython.with_gil`` decorator. Both directives accept an optional boolean parameter for conditionally releasing or acquiring the GIL. The condition must be constant (at compile time):: with cython.nogil(False): # code block with the GIL not released @cython.nogil(True) @cython.cfunc def func_released_gil() -> cython.int: # function with the GIL released with cython.gil(False): # code block with the GIL not acquired with cython.gil(True): # code block with the GIL acquired A common use case for conditionally acquiring and releasing the GIL are fused types that allow different GIL handling depending on the specific type (see :ref:`gil_conditional`). .. py:module:: cython.cimports cimports ^^^^^^^^ The special ``cython.cimports`` package name gives access to cimports in code that uses Python syntax. Note that this does not mean that C libraries become available to Python code. It only means that you can tell Cython what cimports you want to use, without requiring special syntax. Running such code in plain Python will fail. .. literalinclude:: ../../examples/tutorial/pure/py_cimport.py Since such code must necessarily refer to the non-existing ``cython.cimports`` 'package', the plain cimport form ``cimport cython.cimports...`` is not available. You must use the form ``from cython.cimports...``. Further Cython functions and declarations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * ``address`` is used in place of the ``&`` operator:: cython.declare(x=cython.int, x_ptr=cython.p_int) x_ptr = cython.address(x) * ``sizeof`` emulates the `sizeof` operator. It can take both types and expressions. :: cython.declare(n=cython.longlong) print(cython.sizeof(cython.longlong)) print(cython.sizeof(n)) * ``typeof`` returns a string representation of the argument's type for debugging purposes. It can take expressions. :: cython.declare(n=cython.longlong) print(cython.typeof(n)) * ``struct`` can be used to create struct types.:: MyStruct = cython.struct(x=cython.int, y=cython.int, data=cython.double) a = cython.declare(MyStruct) is equivalent to the code:: cdef struct MyStruct: int x int y double data cdef MyStruct a * ``union`` creates union types with exactly the same syntax as ``struct``. * ``typedef`` defines a type under a given name:: T = cython.typedef(cython.p_int) # ctypedef int* T * ``cast`` will (unsafely) reinterpret an expression type. ``cython.cast(T, t)`` is equivalent to ``t``. The first attribute must be a type, the second is the expression to cast. Specifying the optional keyword argument ``typecheck=True`` has the semantics of ``t``. :: t1 = cython.cast(T, t) t2 = cython.cast(T, t, typecheck=True) * ``fused_type`` creates a new type definition that refers to the multiple types. The following example declares a new type called ``my_fused_type`` which can be either an ``int`` or a ``double``.:: my_fused_type = cython.fused_type(cython.int, cython.float) .. _magic_attributes_pxd: Magic Attributes within the .pxd ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The special `cython` module can also be imported and used within the augmenting :file:`.pxd` file. For example, the following Python file :file:`dostuff.py`: .. literalinclude:: ../../examples/tutorial/pure/dostuff.py can be augmented with the following :file:`.pxd` file :file:`dostuff.pxd`: .. literalinclude:: ../../examples/tutorial/pure/dostuff.pxd The :func:`cython.declare()` function can be used to specify types for global variables in the augmenting :file:`.pxd` file. .. _pep484_type_annotations: PEP-484 type annotations ------------------------ Python `type hints `_ can be used to declare argument types, as shown in the following example: .. literalinclude:: ../../examples/tutorial/pure/annotations.py Note the use of ``cython.int`` rather than ``int`` - Cython does not translate an ``int`` annotation to a C integer by default since the behaviour can be quite different with respect to overflow and division. Annotations on global variables are currently ignored. This is because we expect annotation-typed code to be in majority written for Python, and global type annotations would turn the Python variable into an internal C variable, thus removing it from the module dict. To declare global variables as typed C variables, use ``@cython.declare()``. Annotations can be combined with the ``@cython.exceptval()`` decorator for non-Python return types: .. literalinclude:: ../../examples/tutorial/pure/exceptval.py Note that the default exception handling behaviour when returning C numeric types is to check for ``-1``, and if that was returned, check Python's error indicator for an exception. This means, if no ``@exceptval`` decorator is provided, and the return type is a numeric type, then the default with type annotations is ``@exceptval(-1, check=True)``, in order to make sure that exceptions are correctly and efficiently reported to the caller. Exception propagation can be disabled explicitly with ``@exceptval(check=False)``, in which case any Python exceptions raised inside of the function will be printed and ignored. Since version 0.27, Cython also supports the variable annotations defined in `PEP 526 `_. This allows to declare types of variables in a Python 3.6 compatible way as follows: .. literalinclude:: ../../examples/tutorial/pure/pep_526.py There is currently no way to express the visibility of object attributes. Disabling annotations ^^^^^^^^^^^^^^^^^^^^^ To avoid conflicts with other kinds of annotation usages, Cython's use of annotations to specify types can be disabled with the ``annotation_typing`` :ref:`compiler directive`. From Cython 3 you can use this as a decorator or a with statement, as shown in the following example: .. literalinclude:: ../../examples/tutorial/pure/disabled_annotations.py ``typing`` Module ^^^^^^^^^^^^^^^^^ Support for the full range of annotations described by PEP-484 is not yet complete. Cython 3 currently understands the following features from the ``typing`` module: * ``Optional[tp]``, which is interpreted as ``tp or None``; * typed containers such as ``List[str]``, which is interpreted as ``list``. The hint that the elements are of type ``str`` is currently ignored; * ``Tuple[...]``, which is converted into a Cython C-tuple where possible and a regular Python ``tuple`` otherwise. * ``ClassVar[...]``, which is understood in the context of ``cdef class`` or ``@cython.cclass``. Some of the unsupported features are likely to remain unsupported since these type hints are not relevant for the compilation to efficient C code. In other cases, however, where the generated C code could benefit from these type hints but does not currently, help is welcome to improve the type analysis in Cython. Reference table ^^^^^^^^^^^^^^^ The following reference table documents how type annotations are currently interpreted. Cython 0.29 behaviour is only shown where it differs from Cython 3.0 behaviour. The current limitations will likely be lifted at some point. .. csv-table:: Annotation typing rules :file: annotation_typing_table.csv :header-rows: 1 :class: longtable :widths: 1 1 1 Tips and Tricks --------------- .. _calling-c-functions: Calling C functions ^^^^^^^^^^^^^^^^^^^ Normally, it isn't possible to call C functions in pure Python mode as there is no general way to support it in normal (uncompiled) Python. However, in cases where an equivalent Python function exists, this can be achieved by combining C function coercion with a conditional import as follows: .. literalinclude:: ../../examples/tutorial/pure/mymodule.pxd .. literalinclude:: ../../examples/tutorial/pure/mymodule.py Note that the "sin" function will show up in the module namespace of "mymodule" here (i.e. there will be a ``mymodule.sin()`` function). You can mark it as an internal name according to Python conventions by renaming it to "_sin" in the ``.pxd`` file as follows:: cdef extern from "math.h": cpdef double _sin "sin" (double x) You would then also change the Python import to ``from math import sin as _sin`` to make the names match again. Using C arrays for fixed size lists ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C arrays can automatically coerce to Python lists or tuples. This can be exploited to replace fixed size Python lists in Python code by C arrays when compiled. An example: .. literalinclude:: ../../examples/tutorial/pure/c_arrays.py In normal Python, this will use a Python list to collect the counts, whereas Cython will generate C code that uses a C array of C ints. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/tutorial/pxd_files.rst0000644000175100001770000001022100000000000021661 0ustar00runnerdocker00000000000000.. _pxd_files: ********* pxd files ********* .. include:: ../two-syntax-variants-used In addition to the ``.pyx`` and ``.py`` source files, Cython uses ``.pxd`` files which work like C header files -- they contain Cython declarations (and sometimes code sections) which are only meant for inclusion by Cython modules. A ``.pxd`` file is imported into a ``.pyx`` module by using the ``cimport`` keyword. ``.pxd`` files have many use-cases: 1. They can be used for sharing external C declarations. 2. They can contain functions which are well suited for inlining by the C compiler. Such functions should be marked ``inline``, example: .. literalinclude:: ../../examples/tutorial/pxd_files/inline.pxd :caption: inline.pxd 3. When accompanying an equally named ``.pyx`` / ``.py`` file, they provide a Cython interface to the Cython module so that other Cython modules can communicate with it using a more efficient protocol than the Python one. In our integration example, we might break it up into ``.pxd`` files like this: 1. Add a ``cmath.pxd``: .. literalinclude:: ../../examples/tutorial/pxd_files/cmath.pxd :caption: cmath.pxd Then one would simply do .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/tutorial/pxd_files/integrate.py :caption: integrate.py .. include:: ../cimport-warning .. group-tab:: Cython .. literalinclude:: ../../examples/tutorial/pxd_files/integrate.pyx :caption: integrate.pyx 2. Add a ``integrate.pxd`` so that other modules written in Cython can define fast custom functions to integrate: .. code-block:: cython :caption: integrate.pxd cdef class Function: cpdef evaluate(self, double x) cpdef integrate(Function f, double a, double b, int N) Note that if you have a cdef class with attributes, the attributes must be declared in the class declaration ``.pxd`` file (if you use one), not the ``.pyx`` / ``.py`` file. The compiler will tell you about this. __init__.pxd ============ Cython also supports ``__init__.pxd`` files for declarations in package's namespaces, similar to ``__init__.py`` files in Python. Continuing the integration example, we could package the module as follows: 1. Place the module files in a directory tree as one usually would for Python: .. tabs:: .. group-tab:: Pure Python .. code-block:: text CyIntegration/ ├── __init__.py ├── __init__.pxd ├── integrate.py └── integrate.pxd .. group-tab:: Cython .. code-block:: text CyIntegration/ ├── __init__.pyx ├── __init__.pxd ├── integrate.pyx └── integrate.pxd 2. In ``__init__.pxd``, use ``cimport`` for any declarations that one would want to be available from the package's main namespace: .. tabs:: .. group-tab:: Pure Python .. code-block:: python from cython.cimports.CyIntegration import integrate .. group-tab:: Cython .. code-block:: cython from CyIntegration cimport integrate Other modules would then be able to use ``cimport`` on the package in order to recursively gain faster, Cython access to the entire package and the data declared in its modules: .. tabs:: .. group-tab:: Pure Python .. code-block:: python from cython.cimports import CyIntegration @cython.ccall def do_integration(f: CyIntegration.integrate.Function): return CyIntegration.integrate.integrate(f, 0., 2., 1) .. include:: ../cimport-warning .. group-tab:: Cython .. code-block:: cython cimport CyIntegration cpdef do_integration(CyIntegration.integrate.Function f): return CyIntegration.integrate.integrate(f, 0., 2., 1) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/tutorial/python_division.png0000644000175100001770000022253100000000000023116 0ustar00runnerdocker00000000000000PNG  IHDRk0sRGBgAMA a pHYsodIDATx^XSW{[@٨(޸½GZ붵ZGZ{[7pe!.J! GOnsȌLBY"PefR @D@QA( "hEA (dFF&_,= _*ĩ)i.tI@TרCC4C I\"kfoϯ2vo-L? ZrT:DZtySɢ6%d̈|̍On? Y\伏_,0trV.BŻ-'2jٌF$;,olSV왿ٙ/&_c\ d,Kֲs|JA T3z5n؏ Tv̜FL_iY @Yoˢk07-)酏'I : |F }[LiV᳊aWrjX4wjۦX&slЅn 9hT~^{Y[#B9hT۲~;^#:oj>+hΐ-4#Qя~ۻ7OoyN׸aKY t7Hn۸<"A)lA)"# WH y|V~rs_l}~ɐwWvmR#+M_럇[*rpÁ%lL2B_ܾwvFu5:F杚PCzxXT+n?D*2a֧)T~رMP:\v;qӋO5n =CO%M ~x{wrV[!w?Yڠb>}~>Oh1+?PV#1H:{OYG-Z R/Cciͤr7x~hkf:w[GIu U5G,|VRqnW ϞAh FQy~χ/Od@"_* 0U]DFfY Ioeo_$ZVvƻN'E[òHf,)ާP6|Ffz`Ύpz> a`eNJ-zhtz{e֮KlpΫ-[_o1/<RҳƆ/vdǧdKSnwKLq?\w&|F{L)dokc}g~W2?`?)B3ϩj4~-+y=%_\fO}?0S ~Cf:N͙9=otb%& xͮfEwf}k¢6Ϋ_շMvξF2@<)ҌOi c>Hc-x=ʂ$Z8mO\Aִݣ*mzx+U7x{ia!tjzQ [F̌u?2_tL]MU}Oo<` E'0o7}й+q֤DCB 6 I``ߌO/ִfkqfc*Pq%M}r[jYٷRHՊ{^er=עiz46z\siq:"CksWjғFT@<jךyN1Әzstk˽a\攝9"!W{HMfKR42JɈg7Ӳ}{sjΤ![4h售M/׏_mpK5-~x͘mZ7L)Y²N6tM);#!HW Qi#6`Zߨ,zAL~f_•u B` ņ;;60Næ_g6.>}Sl^u|?>!CUNW"h >g⁉OqhǷwm?)qFi럩fnG7-z-ut(IIaNfddi[=e)IG1Oeg'H6В>Kq "}?,X`Nڧ bEIh6ZWzZ3}\$O`4s4 U]x&,0;VG?A=s/؋O4N7B*y{'SAY)P?6n۩?K"B`Ьz&lAy'4_Ε7UH\lWh`)Rџ"ѽfL [Y_dmFH/2[g2 ȱ㨮yxӯ7][sA=*4OØG-dYV^ot**R #e֘҄{~gA1rOF~ܡ@l/fb^UI|@sw6y̤b?KCsDu -ڃ~zRn-0I1\cӔv\*M4}`F\2 E)Q7 2C:7ROIH׈.]aklQRICS_XK_;u_0IfN#,I&2 |> f҅jXrs_va̋F j8b=# ^v[̐"Kҷ\8J,e1n{ dih'!'0uHJ $ c:+LɒԺu2٨ȏ܀V{)c"dP*$"7?U*5J / j҅ )oH9$@@E]qKy@ؽmbp3 62aZZ"aAm{Fޔfz.U19n#gќ/҈Q9)]b䓛gR'oEB%ɤ~7iH86uNw@6KN6,} Cm=F_ay+c,1&@S"hyc 3PZNLLT:bIChѢviȇҼF*'%*)´ui*Nc+&Ъm+7,Ǔߪ~<՞(²Ks9q|L:>IMZBB)v,*,[lftH G{ג~Z~`ӆجE+0jP϶|2R9hU5#?B2Ӓ٦m¡r8LoאY4LZ!zb6 a^sTLgeTakww4ƝxDPQAr_ =Jӡ0C1NM󦚅-wbaEdɒ6ZfsUadt4Y%8sсԐI&-%g<>Iz{7sM8vh\WQl"M†÷ #,u-ق祻l IfL~\_ǁWLT?3_,=55!_*=*ٞDS 1޽wgg$k4j9<^o;)05UB@=q6"ܻҨl&p?$HAJXP!j_zro|k-?a{|F,ڷw4$ "^qkkfNՃnc3s#n"ywP̥!ȷ}fz]W=¡_m qTdE|ep?Y}^[|:P.͞U_$- mh&?_%?70gV]!B4*ԪQ-}fY1WJq?6Q]M+H,|fmԷ+>lUzjOU-9 )聾Nr'5Ӟ&l@.h - 32o٥!KyP~w^3=mlRaGr/ie7}?z=tk*pSɢ6\~ZisU$A xz ?89>?[ust+$|B=!zÙBPW ڬ$ч`E^>.B@%23|T'" 8ù=mxϒǼ_$Ew_|6oWve&BD|_"& #|y}V]5/Oۿ*GǶȠ VN\TGw7(_| D%*#n ;jv7OC ڕj79#ujߚ3zo[w?}iEQ ToL0[p^_3vf'/-3㉡owɊͽuobδ0>+U.a6B>7~_ޔE͜]z-HފD=_žzavãSUTj/Hˊ5Y?VТRm0a(J:ۏb%vRw,?djLËoN|ОK!EI}6_r4c-8vƵw/I.XIMJB@$tzO^Ģ pw.֤͌S؇*D}<1gI;ǎ\r :ĹQAsvEwNooF\TR3Xe*WŪ&}>ڷCkqKx8Y|@dz7[~o;(&>td+^ݧKNF@ nʙOW:A_e\WMi D_^1~m<|S[fv3a3rޞ e"|/7/NE lmrOv?mj7KA>j۸6ö?ˢ߸hiz UEȁ+}iUj/Y$OaB+n"v| Ck˫/zb*%3M mzik|njQY4-iăEQ;94*'{g_1EZ'W"G__âuwԭU=~5[6!@]6ՔKH¦ܑwӂGSY̓{FQ|{uw[O au]JFf4ڐ/}mï=0e=}z{qu׸#Mv{ sǨ[y=`QV{_y'ZmV3ϳ7 O*>tpy.%-Ey8pYϒ+AiG52^: |盡46 \|ʃl?,|Eթ^_FùGީלSVxj[*MfH(!-Gm}ND2FewLا9qfѵ5W⶟%Ĥae2I `](fX7ZzGA}{än2 W&}I/|B־^5^cAaթTTr}IP"sszt $kR/'POBA5|PF: ~;c)&6F`Ꮳ# >̌lUPP6ɗTg" ʝ_"xyM#"(fnPtn!UE%c5kBN++XU8&K@$A2k(?ml3*d _&::Zc_=6fH#zl!;:QFrHy3JGw7(P|PL(U~YM/зZȩ-gT2q6 ,QZ͝g2ثdjV;|jMf0mfI}y„ w(in?^Olh| < AF䭣cgh53hX+~, *M XӺp ~*s)?dȿ @$&pkfRut-F?۽˝' ?I6?.}擛t hD;/捜}AR P6Ҡ=ӆڶֶI|nmT4ᤢn߹;xΗ&<3Y0ԩYms8!ͿS#ӳcٟG聵qSȄĄHV88|}0 &?:~ >7/"{vߔq3+o og#0r#3*m(堥hiͱW|-_G~d hߌi,!s;&}#j]=UAiMu]ef?,Ltb'V8i=L&sD߆?; ٛ51v0I=RȬ_dLK]X?7+|utӏSGp9b5[]#HMMg޹UjP#hgXNal^XzsFv{{GZ Cٍy=K,کt$016',.+mv6 r6g,u5.VyTEp򑫿/ ͻ/RFKFk^ݰ^hOsfW+DYAC 'D {,,q\jY?ȅF(/A9hl9h+| K4 PD@QA( "hEA (dFF&_,= Pd?9y#!-5g?G--3+]umV.3%*o )ǗJ4K^!RmǺ׺tiS8ٳ ҏ54:۷٩ LFxѓ)U}&.?^}> tLe9sƃHBo\7gT"h^^|]Ԃ6y/r t{? ЏlvsX#=@}ç0"Q_oL&rV{w3ޟdBarag};u3wTի|B)¬WU#*+vpe_'r,Ri賀ӷC~ȢW%@ߤS;b' CY"h4*V6n  }E?Vg쀷7O^?n_fp3@)%7|Vu$=}BW5L hjDm_Lg_@>Jմ 4 jE"EI17M*MHuO_AK;[,~WY 3SW^[ ]gEoz֊[II·V Wۈ6V̖XwᡍE }a8g ԝ׋OkuҷFKcBC1IOf:NJj]'6RmK;{$y秸X|--z۪珣E@o7#zTRԾu/ӱD8лޱtfC ycȕ"Ӿ>O05~XD+=~.t_z ?M>Aܵ{17J#fƕ3Ƙ^kW+~UgDٽ7v&iV]鸼>GOj8S*Rwvy2GNLf3+WC4<TՊSc= %_$hnݷ~INylTBo0?Wt!i| ;hާ&WjL&" 32x}-C-ȾEf\LAUAg^03jNM]o؏DHC*5/5Ӫ1=}֬b*;u}Yz\A7Gw7fGAЇ׻U`zQvãg9olBT- Nz%$E^/gڶTOy挏 :Lqh$R|j6 N*-YD,imޭ-w# YtQ1F!.|h6^qtP3R]\j۷nO=۶ϧPӬGaIۮ-9r=<~©Q$./Ck!5; ~M&w5as[LQf}m,?"M+^x+&SZd<40l2:jPto_.VKG9+r ,AL{yƖIiˌO衫^qȂ;osr/u>t' مſ{/WwA mn,m fDkeJ#euv''e4|~hiM%_Hyxx)!\CUqXmYp,wWeӧ I{|ι㾧a8;=Uz/?jm2UFrvhjܳƵR=EmѤDܘTtj؛+|INͷΰҒNlu!)jg%ѕbݎMTN̎>sWUpeTid̥D߰}ܫw(l=3MyB6[Rwh;N΄JD~f4聏`7|g*.{ ˩Zi*\Jh+go~Y 6jlC.3Ϯxw7yFpOxG oy#mWj,zm1.iEö 4XԵM~03ZVv~~8Je 0mnSN,@*VY#h~NI杲N垚߮O+ci'W{<ӎ[#OL]VgF+vz(T}.x]!A3M;m3-zvNb( D۔S)YL-̗!yT&7ҫR9h &2>ߌ3h/c% ~s ^eփ2> % )u,rTH?R5v1̼<٫r~*^aJhQj.# Ga&ePqRJN)0dʴ,D`[. ԾL;&?Uԩ Id# Mj4mʏilk''*3"-4m\ bq b}Pa\zspwajvzTl o*%AL`NvVFUz+ӋzU4 sߣƎLX+$\i0A,9 #琂}yD5Rcޞ©׏:#c[Rl\s=<~©Q$./aj*ӿ'cz5oDFFLPG~dD 4eMdڢuI&5dU0ٛsC&LJÃ9nGV<_3]wP6NY+Dm2~6Cfd(羆 _CZ}ta6fʑ{D~̱WtqI]e= ͹=ɰlٶ.ͻYa__qO=_`;Iu_R{Al|rjA F-?LbG,E<> }8Fm-E J<_X:Ah02_=hyש]j`Z;2L3(Lv5Ȣ:ۙE󺯟g[df4ȊU-B{5A >;T6+ :A (4 PD@QA( + _(g~|PD@QA( "hEA (gw[ߧC~rIR\]8?,*gOOߥRcLȌLX4DWD+R.nxk""Z:5:._̲ݒX"67)ٟ[~jqθkUjؼse1Eoܤ䨘TE *N˖ĚɄtJt~rG1C=/Iʋ G]}Sо--*.S܏/rЪi׬ۇ5l%YW>IbÒ>IUˋx MiYc+JV{V1{v¿)?rlF 4t 4RDg,􌪨‚~x`/АVo,ݳC=2z8c\4JdJ"Qӎ}M )J}LkցN UJ ՙKTr1P×G]~ %A+EWd{`i}te[Ġ:;?•5{.2ãT\| g5k>~\fE$fkYh{l9R]j0e&̜2:-Lm\ utո.G(Ͻ1%;r =ϥmצ]}Z:|FX{.V؊P;痔R^(}MsTE ͗BCW zc蓛s3Zf\~c٩":Yu4}Ɏ,nn1D alG/xU9aTp&|Vo:nTއ |Duΐ KZeWKԇ/ԃ] u`G ٰZhq38erY_@DZv-Mv<&uo`Ko C}/☢zp[buG-҈vzc69xD2NoK}W:A^tMfluKtD׺!W(GG i`xjꓽRj"n.]sv:_HT>2b}rIfLIxő'jc^ I˦'*{hnf9a=-@ *N 6_95⮽XPI{+dݘhq=" eGZ;LA+Rm-)?PZ'qԫ+ILi0G n"wĕh9 d?9o3s$ٻ &r3݈HSN}nG/tc_{ɋn]zRM~}> [E_̱;?*"0Tw9KpVtUI񕼝2JR* Y+O1/ӘιXtt`Xׂ@v׎MCܺϭ?Ӳ?e]'6(ٓ+VUxɺ.g撱VeI/,eT&ފ;ScyEsBʡ>x?͏lm%c6+8^a/ O~y=O-{dP@K x[Q%l` O-b1r~Vq?]1z6a"/E+n/1΀~~Ɍ:7f#uֳ,I/{k>^Ծ`D fԑ,w%+Y#tEPNAul׷_|Eٴj<7}se:x,D;3KVgxCZFuMҽuKaVQڋK>es?h'2(Bmfgn}l_p "]sI|"_d2vN:*l+'%L5ZGt^:wHs˱ܼ?a L|B'y5+y =kԂ1,u|G%m1`_E~ݯr*d և pNͺ[XB֨=}uھz&}4x-k$q7 ^@EFBE{.uq3IkZtj,MO{P}!V5ڴ'u'*DlʎFֶLE"Z{t1M:?U-NUjO~\lĺ?v*Qw'3t]7׳mt_SOD56Cz2}3)j#7NNN.b儽"L:u:YͻeVC;C[Jho4pR['M {k@-fNqs I5>1ܵi;]Xxmx}Ճ8G>ELZfXX4XEӻxYHUYSdIK*oR7P2S] 7c73c1)h|}Kۢ /J).BFuQռ7ϑMg滬:|n8,mHO\,54]-7'NQé@3ao<T9${?]DF6Iw72Uvn~f7X.\OpP?ń4_y_(֐x"UO[=_.b sCI˦3^}ɒbo-#yvן϶Z(N|1mdi)t3tJjGu%ftrMb>/h^T?[xZ˛WNJ_Hv+nvS!Z?B""o]{>_^oe'IzD~EvA *]ԭk #H_ %O:J -y6yT{93ˍzY^JvK,k T\+>~g"۫Qr.+r+G;l%}͌$/*%&\%nѻpXnhl}m켪Lݟ#ߛmjeJUJ~c>B!DDLMݟ'kjt}nĐ+79!$_4@`b?S׹m$n V JK/uH;p}*č1v3L.Wm{bVxE:P}l1fPԇ g` X=S`i?6ekJH9Qa\&5&wleiXt|0DР"F˾J i]+;>8~Uk<[tfS2O߭FU¯ݏO|Ʀ*$^=%msv*<l<۟>~ǘa Z=mhJO&oSk[+nK~1Ue d)~Fbcpڶ^LV <+wZ (WyZ2`ϋ/ؼB/yqMzFBc}LxP 膯L/@.DРbd>(>bVǘKBw?!ONK_WܚNvN-piVg%657,DS*^~}V0S*U`q ?z u,o,EYF^ҵp5%n5vUܾb e3[79}{*oװhӮ^I(4w,ɴi՜ߍ{yM!' V$O\6cÝbHPyC P?3_Xj@e" >!?zA?]ۤFjbu#=59d?Lr}/''ŃBavih ujU@`}/@Ld\|M& O% fz)t!wNyr'@@gɕW47ڄLj y6Cy$4'e3ujj*Pj4,t $!|;7eqH}y&K$b'FDe3WGe{vV_zG)ApP Ajj%L4\&\K#}Ù]d/"81WǐCT@E Ո}N :n]d`LMSӏI?#n>{|m?OKRqZ崳;d߸AYeJ)* NJ6_ZF6R=Y ȤR]~"!EYqN׿NCGٸ~׬~ -1dןoIBf0PN@HlRp{LCt/Asp|?"PsS3y.뿞Ղ;*'!kF\`8iج9ٷNK76]ԥosğ=N]2Ңpw.,H-םy?P,g)Y튾}9ؒKL(S`b|c.b Q-.̜,7EE~?}Q=m$&yTr^J+FqU!q]!] '%7:Tb%[.9HM;7U]l"_ʥF/I& 7Ԉh!Ӛn\lTo|jm0Ӓi8O?hPue1T-cؼ̠SF̣S{i[SmIji7l]Sn#3Lފ4*x6Fxl̒*gh;;>S n>9 [nR_E\U(oFMkӪݙkJSܚ5 6|F,ɱP\Rj`vC~ThխŲhC .l'w21"B=S^q]lTW4r] g$ܡOn>E(%dͨc}ۢ}Pxl=la |X5x9 %q}̮e3kssC~]zn|`} {g =unΏ!d/J9hP! ]_a226JCpuO؏)f <""ߞi04Jq I 4_5*a}~S`bFJ 4Pz`*]%I 츓Ž_;5-M궈%)gcHɁ2 u7.4%t1yW˹^ˑ.f9çbzj*Pw.ʋW"pVHtR,LxNX"~u Mf('>-1b=aWB% A ;/t; {h >8ۺ[zX>&8@$fɲ hgPdfj_bVKZzxC#n~ "G3Si"KIa{6Q&FNuPfT3oen u=7s;t3S\h,v믲XxJY.E3tо-- 0 P`$z:o^d~U>DH-m ~pe Ѫ"ZM\6*Gkqߴ,U2#iΎ*6|F5wpoZeF9h4 PD@QA( "hEA (;¥QR!@'Iq]vd`#322b]KJ"2 ]BgTJT3oe:jo@ʝD+R6R*K%qw h2K?cADe!3qθk*V-Rʙ9RM8V]8%3K(z%(^2yzV` u=7eGPIϗ_AXP:a2!2{D?)ǗJ9hP%Q1> FfԜ!,}/VB)["ʬٍ>~땈MzaSN-ߵCv k4\<~Hm_ʢ_R,)mw K<)yZmH đfA:E2 p%vVZآ?OeEFjJŪ%;1s{ "+OM48SߐkOgԖ/miSsog,QcL0ndm ~f~R_/՗C'k{t^'\Ɵr"IqdoAh;??;\r kYlؾ^6Nuyec^NUDnIqd)*_=4jܫI.Cw*+k8r]bGޔ{6xl)w3ʪnɈכ{KϿLU5POG6kmI"w22PAHz罷LRk<>9wg͇jL9h\b&_&K AUl}ܸw!=r+uUNH={C;#"n%3SJx9kOrg4/tl$~N!mJx%iϗr A{+>:*7|$6,K?I{!'H-R\_<4_roZm[;O7?Qwj-ӊh)0CNl5ב&FuWVz~hzӤ&VHB|=ڥNZZ[.] @.Xvu^8]yZVs׷I"=%*[Ra5ڲ"͋Y=*pϢzȺkٙbTfM=Tz]=E ha=f1[sV ZqBIZq R?/hHq 7 d8lSBL5lAC*o5UM%'^1K& Zi|X^8+=YCb 'SA]\767_if_J_Tf5܊Zy7G3/:٤0*eU"|;n,mAp4ܖ55RnPy^ZMg$+Gl$0*kml+)Bcm g\Ak|ńJ>#!1jI|ۏK/HSe:f?1޾ƆU:b=7a6Ǵ*>+V,1d@-&.G6@Bklᢚ PeGRV:%Szq`c9hPRE報Kgrҝb2;E= !dޕ=]]/ZjT.M\V}t! e_/~LD8vP[>LmDعrRBNvRعݭd'f)${2rLkz hTAxysͨ3=E$ 6UOTNdoK}1ĻX-mnŸF9q/.Ly:ˇ0GBJh/ A/>>aQAcypHǦ#yT{׊W/L&>SFؒKLwjlr2) Lt=nHM;7Ցcc}3""ɜ",wԠ4eMu,Iyqkox*+f5jL- '*0}=/O4tl9kZ5sG__{zu(Y'0ʪ]59'78grZ0?8u9[3cJ:yCPO6J {=!:Qc~]Qia^{֝\{Tgϒg ;x5*nC$^W=bρ_\v5s^{NL_}V!mlڳiֳoӕժ>׼;==Nߑx\bw2v-2\Ba7nLwy>aI/+T{JSڳ$)/u=eƅ]xj"(}A$$mO>Mq]Nr2޷O^,g:Dwon\suscy397(-J"I|:^{cg4I.Rf$?z_GVufy}Sj7y[1]o#T3ƎMaŝ -o<@c] .%m93"¢\uٕML]ɑ1OqŽ}RVn0g?yIbn9uns䪘]S~̠kO|3Tϲ|bƇ5 m*w)ʲCFO]E{nvKy?"O&%j7;&-{5HWOvO1+mm;PzRI`$|F#6т bf=."}Y׋obU/~KMȗzJ ჅtydIΝ[~#%=ȚL4M`&x.P;jGwR?h٫&j4c ţ>Kz(&""Ά_E>ψ}7.{HL'tzPLAaSZd;J}` L4NͅsaH=dފ4b+M~L=N"pxVdqA٭Qsn$oβʒ{_Kj/dk 'QN>I6?d $|WMq7+)u9Rޒ{ ?OBM7? ۃP׃ &'5 Jz0{/b ßx `b!L߫W;i6`mmv#a*:E%vp3"n a!h>{|m-u*[ng7MQ@sڶ}~98FJD^_qbg_^8ei]~vs̫wçHԴKI[ ްmc}]AfDtzVc2_29fXK GS<HK:}CWOAq؈;>GS c];=$^f&9 jc1^JHR?j iJR\b2h?qvS KKh;}/tgڟao+/P׈}y T-Zk)Դӭ{ԽvWpfmTa5?zMY}Hr;R|߳U8RSQzS3'|k2Y+_ӫJ4ڥL̵;(v cmѽhm¿RW;_0W)zMj3}X~R";cy#g|*eDYwziƗo)&1Y JkRM^nzRпQ=ԩ쳌o}Ou3Wpg2h֩;|";E%ńEӵGżs[ k7Nݠrl%.۽kX73<&^/%>vݬ~V횸3cShS4}L%|~?JW]'= H#Rc[:]}[eՀ?,n9sVja)C}OΆ;Ϝ$%mX>wFroy.FI˜q(}[jyiP]-[}--q$;0cƶ|UE]'%ΩŞG>}q[܌֭X UH"KT4*Med[7~LIR8'(O8+>y"hd'*8Ddj0dAs_rww {X [6 !:;9ko$Za%$>vg//oUs]z:١ O:5 P͵/'I+;oy6PյvM݂$OD2ms؞6m`ݨvg1[Ta2ӕFد\&&-t14QijԪmҡo3ۄ;.UɇR tgXE~V)W}˰7?7邖C]{imfԃq΍ 0&%RުYtVD4Ov͑"5J&Xn019D q΃- V&wpӲu>Kji>t"Kp .ya0krouj۾Ϝk~em[)N㗯4:%FJ֭}4emO7*"AOk嶬t1Ѱ[IJvFNv.<7-ѭsrJTD+~HQvz>~Xg0QX Rq^hj SEfmںϛ|FKʯۈ,Bzбcc#7%!"9|kl5Z-^/w>? )kJ|~2wPWWCMS?zWȺψu<>Iwطq45M9VEp Wݠrw_s/.uos?~+wz nT~Ի&s̈7s#!bVcOĮ{g<`>Mf'vCWZZXhKcy}Y"}:aHϿpI:oqVր^L0ADHyޘAel͏=Mn↩#u:=8u֍d=OҠH +hĝE!Ml2I HB#}cScek-|lݔaCDrk{FД\Xʐ} }?`^=u ?A?n0쉱roS՛^f/0< Bwvqm_Xj4tkz{q;"C*CUFO3$k6S2R@=6[4s!0;IN*Q\ ţdK"G]m|$9+#͆6neZ!w>'yƿ=ʱ@kN-&xػ|}]h첮 Gc#>)ɨA备;ˬZk?s~wo0}'zUNzlS:F`Vǘ}{^m;Z-& Rn7Xr-gک`zXz[A)8O]KhVF1L45_`QSkrT=beڱa eO39e=1.$GO2 pM=YN0Ϫ;u\>`sm}vM|x/ڬ#/" .:u4FWĤ]On翕MPP$^qS+WgԜGe?`:kσ td6|fRgHNcb `jYyEٕ{W)ϘQS'~H#yԻep2FWl +idbڅ9q4Xf{Qq v9`4&{ P܁7 yh o<_$9;91,_a}?<{.wθi't3tV$aZ6KWvVJ-})7^cϥ f&oK[4jf2[r=7/ןE)rcC͠Υjw99;O?rRif+uf~:ߣ^7!^]KjsZLMd )̜F 9VGћTYVt*d⪽R'D½&R/MI#9b?{Vz ˲t?&2|;{I8v)7w}"Bط0A\G'0{#/f w+8>7hHUex>]G/ZWq63 mj)l1e ,6@5~ aa^a&lA!黭$ƨ6[b.x?e:KQ/wxU5cLȮEĻW& ;bW2T} YjW|EŵLQf"fapyc>*2¹q'mu AF6:p? W (4ދҔ5?^z5ټu{}MY$S(Vݠr|/=Gl`1hg;2JpcNm8.JQx{6: nӪe^R ),X_NAgLLlM*f$lPQ!jqPN*wصʼ0GԵNccُĸLR·,l#v9 |õU׌*e&qVJZU#-jB.liP!0|Ofp{o"䆂hOy Tb/?e{ܡu}gF r'&nXI4v39EQП#QJߥ.3Irl#BA A)R0gh;}*v_nԃ{,;AdJDPK6iJ~|=' |>eװr Us=R#kIO ae|ײ2=k|=g֢ꤓ^ٵ?d=s )/ZU{#NP&cȵ*JM9A]~\#ė'^/162/}yVș W>lIGAtվiػ7grC꠶e;ISm?53e7ޜ5aG!-*^תw ^Q"ٵ]ݺФ,E~RSk{iUU'Ƭk/\bZ?MFZ]h;]hgL./(qЗ['vk( ]\;O7 %h669}#&yI!_.&Pu_ޞC7gscfWM4 >/}˕1I]3Ndtْ})HH"BܞqkŬte]Szxr }t3-}ULJ𔿍) ĆW@UD"GpUzU")>l0EM9/$.'WN*M$k?יt\_Nb;|[_wM5~7PQ>KpnddRfJdaM^R"7X4q=̠ KP!VORv9|~oZv ;)81u6 St_T׮d꩜/Xj%G$oaO.K>er͔uL€9yrr۠H1çVwYTXNXكfԜiGnFjW*hBjjGɬeUh-zp8In]b{<(RU$?aGDL<%_O&k4,p; q/YM_}ǣ7iTY4UbOb?pE+t* OzMVیXgjkZ}G'}ש%khf*-5krvQA!r"T;nd*<=u&.Y.ԼDڶ.sƱn"㮾7MilȞ`g*OֹUc~2N5f;~.R :&X3R.g^1$%0Hҫd +}wEF DV)zEA"㠟L*Lkܲf_{ʖ f\" Z &r#iFCsأE)|W z/*&/唴.UY9G;6<&|1O}F↎|(QnXN-SQ9$)nz0\wI.sudէZqfw-:sGީjT&E\u-aM^?}p۪TxuNe`b:N]ŇXՅdx)?pV Mm;WɩR)jvV]Rʍ7RBc԰>b/3A3 &VܮI+*N`lD ˆ: 0̡4-w9-m5Cy1蓕EWȕojH867TO㸮\ u;&ٷs(O>ucwV#>eܶ ۵\fЩrQ>dV^aFì;(kqw+%A1 [f@TJ`=뷔sǴNzQ/r%ϼUǧ󠟃 c]`dY|OOW,iM}[@ɃM)/Y!Mm\1ToCW~ݲ\o&7)F" }/c#a]:034QؽkVi eHǟENRqWiBc&5Q~yצ*wcS^u.Q,ۯFˠ.wyy*2)ՔRrRDpѢΝ PpJOKUrR޴c|*2hWg.wMTN6o{jtr*ɍH>,}fjju7hˑU7gdbnswbHɽXTZqzUMC7Qhnxr/}]u+'jN} Iǖ\R ʲRboyV8+"FG`'ǥ=u'qe\|}$OH5Nŷz/9Nl3#,~?^^gXԄ| 髧{ >X،.) 5cțM"^3G +ڮWqNt“}:_/EJ {W饈GMɞTI6JJ>F?$8ͬ)WeONXZ(]1.HnIR$|f5wgwȁ#~%"@JĿYq2.g Di:H^_rn*BIyr'@@g^WhebpHrlFBPWnxƱ[>VN}/tgFVdl"h>^;7܍LeNͧ ]b\16(< WLxQݸ9.SPހƚò x" 0φm[Y$z$׮mR#̔nDƛA?O!RD_oϽe Z?TzG  8( r&f9kN+f[+iou޽r[VYw T۾2lX3_@:yK )(O6>qqY J~s#.5c TMm$5ʙPۦp4pvezu? $/{TR&Qۗ7[Fƿy鍄S54E‚[z]ڡK_M}oobm5CݠR H_xJHR_ VIOx~ ^A;1Eܮ)@G39R oC$hX׹mUfDP:xc`XTPX8!}Yݓ6+1NyT\Q9DOQ|" RSL@X3"(> g^RIH.u:<.HnP q$W(%iщ>6\ 7Lн9Q]S q4o=uڏm|uq9QNT8+<>/]O}M س7g32xWݷ25o>fm% x=bH,jXjH$|Ȍϓ!—:E2]ڥ>oX*7ݟfE} |HMxȒ<>ǍXoܻJ/1s $l^ 5v,b?=*l-2`^+wü?Zփb EK%,nťTzvY5w =_ǙVB\s4.á2R3&*DQ]IǦôf5oܐ"Fؼse>g)"B}6ݍ#G<}^<.A|?6DŽYHRO>K͌.7~۟Z9a*&C-V6Oۗ\B?fj2#q겐w-ЯKAwM%Ҽ<|u8)G&"/Ld4vݐ>A%2ϟUe"s,UT%?1V;+R@ưAgTAjvqmOW֎~'\}ouM`$<8K}O#YMТfNY&.lQ]>وMnhbL y"ÎHXDug yz0ݻ@F6^Ȟˎ*iUNfyFM]=r2Ld7zccLmܼF׳pmg)Yu`ڮ%7IlXLRK¢ο;rg @VcӺo[3 ϩοqn oګ]fpn-E6yI״Y?|񄺽VMoH?o߹P&-m+la-Ly*_jɌkjw]8s[X^O_0ȥgK;lݔ;47~v ֵ`ZB^璍'@+GMkFT8,zMY E^N`ץZ^0B᳊'r2!v 2sWuzA﯒LS.j5w̮%mZ[qc;==n-,C.fRSvm#(Ehxb\6z :mRfŐMRvW |rg>C 9֮DgYB v:~*)&WCfQ;_mD}aRع`F<.ӮUah7?;*vs9ܼ 'rHY3[yNPKmucv*xٜÿk\ fn|j 'Ɵ)wHB5%!̃3˫ՑUC.|F*Fy 'H&ɕgFMGq4d=^똜og w <*.#waױ)gB&|F8PQwsrÉgrvC6`WJ1$%]^;:VT\7["]9T 7\t 2dZ\0N2w}l<Tʔvj- * Iڥ폸u(1 ܟ!"2T;h[,U @$nvSM' ]ֽTplѽiJ]bBK}Դlf(> -v\Y|PJȚQA4u޼s8Ht=) =yL VONɫZv-֮PWYAC qz?Mtx *x,HA RUMO|V)ײӾ}wؠwW _GƌX2`#h/L vj2a {WCyX*y q~q-bBd:~f%:pK-}Fw?QQA(O͆Z^ {*AdJ^d}Dy^aLzeo#Zmh+Ҩ"Oן~ F(ZvVƴв7F L$iݼ}b\d&?fu[vܧa}C'U$u 0|V PDp? (4 PD@QA( "hEA ':}їde_W?X@1K^ܡe_gT,mT ~@B B}x,qÔڪaT4A^Iq@#322b]Kd_\LE4 YQ@G;gbMaeFB,$:T NK -GN kBrߢ.hJW6i`@rag#Q',I㖂ƎzU!ܻHrFdSak6YGq "Od3LɚNHO~| LيHSɟ Bڭ-H܁dIIw/Rb0j{D><ξy-*i()ǗJPdTɽǮP Rn.YҌ-I$WXA(h)hҗ4>"͏-$yQe TV_]Ҿ+-^6|VS4s[p/>|Fˎ\//ĉ{ƅϊO{w93Z*!;}fcI1sl *Ye'"cPA?3_XjBt I$R%t;UX=f4`YAҀ4aƄ 05?'(f>!$Pg^S@Zy5Z$ XK}}KP!ϩ8@ڵ~WYC{=F}W5LUdDYHb^Q]H>} TagSn\{;lQW؈DFBTT`U I<"JbHzٵK1$ghiMhӞC--"-oO"ߒHC܇r7"քB}DvAjk8;@РmwP,̖HK'qAmM HlR!,&/t4'MI`e#h^`n. ~IH}lFM"3RaS;BPRVr@H \FcB̽1V[yc?DF~,A~v"hˡ¶*8 r/{6^TE$dӻ%BfzOV]N:*|Y%آba[, ; Ku$# p˾fFŽsHQT7z^~zGHc\V|Z74J"RS$KPՔ>}~64NUA"hFvCJE w(,4dO@C5W4+3ms" Z}W(}% a. a'LjY %s(}sOcJ+cDԓɄ4oZKEl{EE$قtA|-=Vk;xlLupQ1\lܑf]ˠOJ'NA۱<< g 9hP-0-% u)l\yNއ@PRT#*.Uؠ%H/}SZh5t0 |CcLa!4Xsn+Z]V̢&) V4{W.lZ7 'J{+y)hScG.ŔtyKۘ 6#Ҁ.řGT}*]O z!H..Ui*FZ1%N ԩ&#\Hsn7/,4*KrRRo*ReFj8ٗdV]IMzNroQ +ĉW%nGnG*\.y-#W*&}#H01WZ¦Lu<>:Tp:iX-&LwM6@YRP,Ld_EE8  !ٕ7e #mrhБ|e{Hv˖S ґĿ>3(*teV_K䥤 PR^$$F+qRQ󡉉$=زJк)_f۰ -LnZVI|n>OˣYla:Pv,xAC~tWRJy*ot~uUҩ{J>@}>[M۷h'.m] d>KRj0_f%]?\U42$ݖKy +)lW٦w2 w7Z`.ږi2dadw}ugܞQ4Ti ˇ~XI|~r*4dL)HSFSi [QL;?'H7OUl 7yQY+:5[ 7Tiwe=WW)S0|钼=}Q>TKSK,Y_W]ɼh'i>$E3*t33+3I'ꍞȥ<Yc/C!Be7M[4mS ?ad0>fx.BwQK=iĕӥxؐTE.R!Зv)O!lI\3>q $9T^D]uPnۺtM[@P\+oڑ~zZH1X[W&pU{å[޿H9uiz6\6Ss1cݔ{Ǧ~XE]6rڤ(ƋRm@ASnLڲ*qG(\u5ێ+*kJJ/]^Z%{\uhMg1/Jjk:,,VRXZ#̧OJw٥OS~^b:|:J7uyqC]-#J 䡫\iDϪbP`ekprA ۗ+7/3MWͷKHؓFtOS_jo]p"FC}J# W}=-Qfse%Nk443 E\FpAS.J $( ;V( J-ߥErrYΙS2sȒ眮uy=Obg*HM*fa>0ϒ HVbJQpӎxS!]7\wIH$,R- Dv.O~o_4(i^иKd%VT] R|Q&ۻ)VZ%>ʶV(vE)dYBbb5Mt/v*\\H .HL;(e,{Rlyj-kH߶eQևo )unb)u8uܡNq{*eʞVLWQӦG:^|>H1mG}C!LjImv/ĢOr,ƻoZ!3D_?Mou0USϋns{e4å yN< g|+zgB2i@]UOWVQ',q"%|&C]WT;e.=_ODoWMWS|aڐG]Ru6_GJʭSA.ۈst@TN߰`(kQDrZc(|V S2,z&EebLZC(Kr xA/;KMu6J'puiKkϽFLz-iEǴ⶛O#迒327K j ?kYc?kvU_l]bgyϚzNg-xZ1\@nLj Gj'%n9cOZK"=@f%K:ݵwnWZZsN-/;D\fY:$ xykd) {/Rnը4l3Zk>,\ںtEϔ.gvU"@Q))ΙvO5ebڿBciEꪫ -&?&*5prSxԜP]*7~J [(JKzȍĭK7Iwm?RxszNj|v2KrӦC覯t:!U@ҿZ3oi[g6 Sm\g]yǃf?&+եK]A^WtJI1_nWմ?IIrK#ܕnL^bN)tMN 7LSNC)_SպdQwKe($հV:M,SUzT_04!]gͻ/SRBhX>=ǷYLa}5!bL[5:m>wF rRh4_Z]RW6WAo.+C½{O|?-ҳo_,n{+4M|>JR5/Õb% M[KNwrApu5>j٬JG9]NI:-ӆRI{$rg[p]OWҟ#ɛr3LD-æi!Z`ZtUUgη945[pK~UṠ5^h\L_O PjTu\&XwM}kʆ/DIWwHg¤(g͕"mKۧb)`̙a>#϶\X:S0?BQDФA#f }uu9)"sV:9sBqE< t>w wwS,޳D/|\9u  ij (yxc rWtjRMRSHzOc%1s;PdɝѡbN֕M,UC4HU壗"{t`RʺU3m[Ҟ8Yk/؇$)}{ͧX.G,ztv=u$5ҥB6XV&? L\:K7J.FjQRD4ɺ!rDty̖>1P)BVvNX䕅*JzUwC8Lhի>\g4yï(J,O4 ׵q^F ]ڿ(VHZ9ޭNLܥØKSN"h7'oY.TBX.ԉW}W\|Y \<>X N>sӡmڈm ׉qqZ3oj-N(*8_VCSU Gՙ ZOi}VL՜oa}=zlde}[=3,dFԹK[gYƮZ+A`KD ~hepXWmHmh3;ՖjKș+ h:άN3DئoG*J'R~mNnMQ$6T[bv$>:L-b.m-i188 ѵRX!V8y A}i}맔VLRvȁKCMK\9_1XW% 'Sq|hG⟟*SOrX_Qd>|.Xi7z!DrG{CA4"gՌςUH7 >ڭ|K+߿ޣ\hB]Z;ӤHj(RYWH6꠩)]+^*sxCڱovMVU#Oy~7DKX6]dzKѹ7M A#J:ΚpGkfWO,] ̴v9R }A*W77%$-RF,DWr4LhiHuAKRx4{J.]/of*Hi8Rگar2cu΄ d"}tuEߑ Ytʼn. շ]0gosw}~K7Ke` @v!:oa! 9h@n!C `4"h=D{Afr3ZȩwXF/>|>٨G뒅v'!Uke9hs߾X̸W$9CZA`7 Mݵfg@?W9h:C17bEj4{9O))߼ϱ=8E_JYJrZASBih! A!C ZA#z +w5rZARؽM VW:AOU{ߏN@qqZ3oj-kMwhu$ޯ) JK GO:r "1ƽS A+2wHAh; +/$jwprP"h=D{A!C `4ޞN#j73d5eχb@ml3[2`NۿN5k7ѿZ3oi-(jCW΄7<PTug< o/TרvR{w >է8"6v2llڍ}\ndCYK{{Xεܵ)9}{]X8-:r8t䄏ѻ+}3yuuW˿Ҫom dKw__qљsxde٥Q,~ORSnkj]ҸbըIP0qqZ3oj-)ĞrnۮJؠȻl~ bL%>yշ%Pf̧T^yW(9C _]|Ȍڍd"e WݱOv596̶wXF/ZΝ-V"f>ׯbICm oslw-"[GKwhՓ7rqv ~Lk{^zb_pdH`ӱ_Z,w/cqF0fФ%^'q;_ n9~'=/YL>Q)zӃ-KPl37vZYQ;\51ϭW¢۹{} CGϺg64Ňj> 4|ZOd2aҦSZs+tk7h[N= %kophd+uDPN}FßbE9u44dA JϾ-7C欺t=*K')tUrT%$}}__t`۽CccV+#_:n&|7噢|L+]1{/;eRm1<\6}*u f@f%V;_Һk}C7nDQ j޲sPal|rg,L[_J䶶~XSWnvk6wBA}~Rvٮ]ϖll8)é6y t_#iهt7iPi>{?іF/~>:ywCf]k0_i7q@?sZm)Ihsf6?|<r3 oI f/;dŜWSbPWfMX}G*ֺ0|Eig%56htW7g|u0]1hz%یk yyMFUkIgG]iUMۺ?|zu\KwOn9~wޖʭ( aBԪ?|Mmؖg tye)ҾiI#WhδoMfoN)z'+KlOWOog-|ժx)Anr7[(]ҷ2츼lm#ylϮLOY:Z7pprSX)%O{zGzұ{C6ƫ&}ay$ߔ3rұ~6<m֪ͬqRso9sR`=E=t1/*\`h>_!'ֵzhk{J^[T>t%ȯ|5|^Y i%l^>j(Ϥ7}6B9tkQ-Dҽ[yA>eҮd̞,vG:s}e ^ϽDUxNf؀|rXm 0K+@K7hf&ʬ= |0ijSf~bn8JՇA=u )"겲;q # g*ۡW?ngϷ٭eOe{v{qaL ɕ{u5Yŵ[刂JζƫتO, Cul8?D ߯@o67Lڎ/l=$z3y~ ]/;{H^rkm~)צ})+]wY[ >WNգ1n_wZix bXr eg8"cHY]'}*kժ 9#zj;xr~`q^S(XU48UTP!9NGo_%z5HfԸ4WֳYX&;ܦeN?' "8UV,n{yLӋVE\?mT* ܝFtfaFr5^)5RXruvbLvbVUKjД\"Cɻdgߩ/oX?恗feb/WvڮeӍ+@ԕ 9f+[zڜ4ivfw|<ݷI`zzڌ5?d櫇^}V4@ڧwB])ڃ*WcG>J];߻)YT헶J'Җ S ~L1WEoW;ZwWGD&X'sk$il_=;ڷtR*iPXGLg\>֫vIYʚڰ]eNrܡr9Pk@H1N*I߸jsK,U~5W& (8WG+o!M,@v<$ KS}`ڥN)&KkQ G'{ۈ3u:gnZ%'>HQ]Am~[6=X3/#w2kSWY|Ce8qPI^e^BDc0 :4~>=ack P^ U@bEXO{W5KՅgEZ׎X:sg??wvYПkVŞj{.廾JL㍸N+-~.9zz2Np?H>w۝TYDsuz$c/ٱ$]3T-~eSϷ {Or0߾R {,Zi$r(~RFt<|uI[ۧ9U sEAmHKCWC:\=㣅X)嫒|E5ICtk/֩/oͽR"~LMQo*}0})-Y=jk pJd}W+Ua%)u1jvTK͵9=gySȨ;#'rfV W;V6R:`fR̯[ԉk{v {4iCڊ063W)z9ym)'9S͋:sFnGsIM1ml#-jاw@k[ )BTARP_0C׺tV‹ftxP|lRa]-Pne˷xdIi~aOʹx`<0uXKѭ=, JQ;C>wxVc|:K=`xc>}u [g,i$l_7d:t ۳vwyxpѶY/Itѱyįq2E_{4Hʤ?xRqFڞ !fˤ=lMcϿxc Lz؜ŊU>ٛ'Z4E~Jo TPguxKJ\'/+Qs:2{e֘WCkKZ/07>C-'_t쩌yVnUоtd%/7W!mOHLP:=[ @߾`=u%ruƚ9kj\}[D;xa۱$_=at)e|AsoT;RHߴUu5b2kzAaͤPex,׷kQ6Wulkˉ8ҽ +YEݻ{kM 5 }42gto˦7e}}ff:ϰWUI|d؆߷ʗAnr'6Õ?[HޑbZ>Z6JogLj`NVL]LX`hwz)2N*f4gN8|gYJU}LˡBa>,A1"L*HWO~:zxj\z) {~q%Y)Fsۡ^Tu6_}M}yfgVՃvhYnmu>Э nrrPzoKf:lgjUMEKG[pdr^8k6IMX)~tUt}D<(C`TtΞ}>&䟗踰dt]p+VAdl,^ف!{H# ђ{= ڞ5:u`I e:y Z {{GW+ |r-٪ռݬˤ\@aQvC<#{OQǭu 4X zԲ9<겵jƐ`FEԐqfKZ9B_Dva.~<"܈idP:s<EQS(2u&SzY*6HJ19BxJ| 2S!_\eٿմ|0dܡfZVw?PUƊ+NjoڤF1Ou *_p?6G2@smܬOe1S*֦ĸ8 js3Z'.[>deK/j(r)%u~~bj/ ^)~v6qaD) <k^>d l~8%.lجGDwpow W2O5{~C<$lY)I>#~|!/l7yUӉ7vZYwNjEjo CXkfŇ|sH&kT9}."HagoR~s)[ۈӋ^PMxl?gs6@6i!8T1Ӂ[z'^ju,;4[\5m̵㾏`$|?}{H)oREQvJwEۜpgq5l?J;)/;>Z0)ekqjWmH/؞_6(ݪ<#Cr۫"KX9eي9$2Vm:x&E^^0O5յyyR9x>`NYP{&I4"hUL+. rZuhYYʬk5'+/,KW3;{=` GX6<Q0}Jg4i,c~W{R{z MڍLuפNڗ];ww*3$ozhnY6\K&gF-[}Zwzד]@z$&{ WWpZڴ雹ޣ}ǵc0Ԭ{~30FHR͟8k dgߩ/_o|CrêL1WEg9h(Ar 4"h=D{A!C {{v:B#Hzr{ߗ8%1..^k-7Z2< n[Go܈HT:%.Q1`g}s!qo#ÐZ7!R_[ry7E\uݯ) J-Uke9hQ=gk[g>yϏ^7g땤{gܺt$9裃wDAJ_g&tA]} {l4kMssޙ~>A+H&F!f*;ܱ#Pe@%A/$"t9j:67'KWߖC3Z0n.vmSЙ/T>.Zon~Oy3Q׵x`YZՇ 56gc9\WA!C),=b"rР%G{굖}ʌ9w>XiʁO4rog;:|&n|><}֝Yng;u䢨3ϿM eјkɫ+>9aR蹥Y.]f~Ӳs#~Qی5ۦKhvN]=̓xV(I>^lv".6a1= {>=r6f7\t0B`z88: (,çڰ~ ~~ZhREb)V Ms+ktwGm$qf>miH7M^v d4VGi?MG4W(kSY(/GEK!ޔUQFROaLi.nFereˇ̸lidg eђ?ua}k{+TL1'6FZZ̫ac2*}KOOXum/{ٌ$YAygQߎElr9]zz!5rMKݿI uH}4 $,t_#~OTTt>k P0vŽ/X/C RVtj9$|ӄR|{`>kl>~?9޼NG%>ԮvO_YNWǵ\X}r+)s`(3zc =bE[gWS8 'CLA[hQ0;&cidSv`/ר 3hRLH@~=vu8lh̥H-aգqh2K{o~2г}ֲf>{?21r~ΔL9~o|ݴ^Aw-@ N "玜e4di\:Rzj7&9ht3r1A4xdHKjڬP<|VI %K<) U݂߿{yAE W}$ިM;IsG^\>r-zLYm~<@ >|tY½rN%g9٠:͓FDORQa֏^fQ hBK䘓K1&so@YaȈJwLXېq*ē{C冭Fc\GyM, MwZ^~ԣVmܙyxOШ@&AC^".+kK?lW?mW)JU|2G1FGGF;<ՅP^k;zpNDАWRQ:\ )ϒj+4oMq{zݔGo8t'E0&}rVޯn/ONoR'}c\oo}F4/"]?uZL" z +WӵxeQA r2P0Z' ] ]yZΡXa!{iNWp1,tx??Uz%%=n|,;=ι'<4t J@$!4"e51g>wc W:]]\], zv&ܖ7_6ZUfY7rsc~ ].t8X@\utPpAC^KSD$s%? 4n[qTAGI:gN. EZ-kg<,3#?kkԙ8O&ch%JhI]0*ŕk+QZRTD4@fAC(|n|B}xK#YbO5x}_͌6,S +V˓o WQ~\6$F?cX):ƌ!Nx@ҨX͌C95B|+,wx.z?2?ڵT.6b3QN_NԸO.FT'F. 7Y^pP:<ȰMA,TԠ3=x/^/ 7_7j;UBnkИEm?E4[~jڣ+X!tȩb:rؼbqOa%~gޓS\[;͋b|i=4sS2(Ww@Ѝ;,^q“{?7kۑk|Y?]4ٽ;{Pi(3vSi>C;+xQ D|ֺl&=V.];Șޯ) `][S-_pTƮZ+8D^q@ox˙ %%݊׿ǖvg+ =j IWONH [}"}P_?,uVpUDUd _\1Yf_9sTE3/{r-z?6gd9hC'>KSr!eG->=!ϭ?ua !cW/e98ُ _rE JC_ AŇ|scK?6؟Y6Ha_͒o4yjtyʷ[uj6/V׮.RNѽډ,0EYFLh$OOeNX+' (!o={xm9f\7wޞoL$y<59 hYg<0u˚0~s} [^kZ=Mbh̡묔W5ꏍ:|:"2"KzzfλT㪞٨v;bHdy7['By1&tlZaYprwV9b؜6!.[>r,۳ϯV_˜ vkex*{$k6|f~a<-xrP"h=D{A!C `4yj3u"ij'6_:uv6§f#}&Nк5A3m[} ^~=ݴ>dE㫣%A0VU@8q-"dF9~5ӾLӁUoT0 .u{e?IC"2UvlRWPT)_qz3b78e|UtEA ]u|vI)Ozi蜷f.Y. Vg<ggA۶ߐ>K9'w^mxnUGNL[zKz)C&KIZkI8g^dm-o5˸ל5)'MAKKK i'KBizuFHgA.yg;tX7%?E؁-$+ҟ{ k-V.T70)z}>,Ao0`4%{unDw_/ͮ{3~Ao4 [3}|2],ا 5Fޯ 7vZYqM_\6ߦ|ƯPlȓ=ݧd4 rֲo3"5k5m\&A0^ooBLB7d8Y⌡&S /:e)ĿAV{^X]f>oZ?ߚ/We)|p˵gz K0fڶ}A.#MKd<.hTY{3fZ>b.[+"tyݟ[1wS>/]m¼CV,ݥô1+?P]wj~3ة;ISuf,vіn٭z`E"BoKUگf|;+ߥe}{p./ܵٽVw] -؍-w^iCgSdYb >thyӫ<;p%=IDAT=* :MtѺfNF(Ǜڎ ,0wxa=%&ػFiD 5t{}I-9d4ϒE2[˽Ӈݭa&)y Ez94g V>k},/,2_Ԯ^:pj=ZѺAf/2ZLA D9vv#"iF̈|UTNAWNJ\{ VN@qqrfXg?j_TE§kY~D?/$7vZY<9hmϲ:38D"Bo?Wӹ pZ|v( KKghү/ h4SEkNw$MH2JS1:mO;˒s֣u 4kݪj}N ^ Wzeܭ^r23G>kfa|UTB!·z[?tQ`iH7O.+?(+ cet35Ԟ r-W)r pq^Z5 <עt~ >SJ|ͽҋkq U?aܓN-l}) P0qqZ3oW'>2(Q(կ#+ KLA_>qs?uao쪵!G\BW졀WNHN$@?G 7<Ԡ)|p˵g&OҺP{'(NA!C `4"h=D{A!C `5aBN5zAtF=Z,; ƮZ+A+8ؘkg'ir cdQ0^>?oꮝ7-=>z1z/A{y+RcyOIy! ,ҽVR/hV#D J+Fc 9h@ `4"h=D C_XiܸcT#D ]]'o.ǽ xr6v/~tv/HךyͰVk!\۵oGF#9~-NiPZRn:2#͖85aBN5z톅G㖿NlMt I:,P.ư.,4 A!C `4"h=D{qqZ3oj)z?f1 Oe֝գ7J$UkeA\f4^?si+?nI@AZn1FMBĵ?-=`l?ga4x_ 7=9:$HwO9^ '&kͼfXQgNF$MY߾.i/Uke9hy'  rHuC&3 }ھ1F.}9M q^C !'b`\lRދg  ݋ S^ `4"h=D{A!.rlJ "hymrëzWb|j˳&[z<)gĸ89 kVt3Θ[[Vs oj#%*Kլ+=ݞ@~D >rB `4"h=D{A!#kͼfX9͞rؤ/M|%70fФ%.Qv#$MY߾n/a‚o`]N^^f{ܿ`Yh%k9wJη0x4j#-I-9d4+qؒۋ]ssޙ~> v|Ձ+ UѺ֕D dѫff,^zS <-i4eH | 3V;K`\Vo 3"B v#D/ߝ䏦to0ȲTL' Zފ|UTBڗ$vmoH;z_va݆,_uĴrw,f*u; _/ 4[K >Y8={g.Feo;zni9YKߴ\etQ<zOP>ԞKBizuFHg#xY/#; l8cI/,jnsϯ^sTh^4a-Yt.At/+=>n&WՃ3 fCZ-yv۵2:s)AM0F`0F}1ռO.E/nj3fI{S>7M ^+-l{~]K1@hI =U)R[ӆ[h/\ 91g!O[t(FG`Y3L/vgbW=IW%_ؙ2ڥy[n)}g`E~w'%˕iާ3=*z?8ؔȻ_Z{4ʖ*TV'=ަRY{7-Or+VROkئRC1M1'6a)Op+Se-4n?@f{N#-.[rdi4W+8v Yp_wTg@uݩśi̔c$MՙR͙/[Tg׮bpNj3Z:ĵ լSG',rTg}!J">2GIy4L3F΋>c)ױ"BsM0= $`yߋ%޷M/zn#J2Aboj ہ;oNY)^z-7>ֳkjnRbIDR3kef.`bRgיOzcttonR¥v;Wa2gX@-O^\*r]`Fbwxa=%`ԻF}:gҷ֗܍oK3`F,VZo-~]{@3ɴg;5}عJf-'i~7bT"B~QDo ٷ|Q7b^ur3d7V_tBѺIL3 U,]arHvUD߱_Kef,w8 Aǃ-^S{l5>E[GBKbMjW/M$(̬"-׮[NUB*r^XAWr{[e2gv9pyM4/}Ƕ(/4X-'ѥH~N"^)NŞS{b,׆F|PAhrm\MOD9vv#z˦)Ól7m^Mi=|A#̽dy9eLN4=F2·m_η~z+%bve}7Bd)Z]Vdwg12>:2.yXG="h|B9¢f+GΝ\XVc:i/Ƥ9em9&_vpy|8;[Q~ŊMڔK!G̑9h9]nLksF۴kf ?}ШNPqqZ3oj.vոSDoefONUA,#cMpc18cD)׵o:s㷂  ZTM4=9hӎYIJݽ: JLj7vZYGZ.[rHp5}A.qLR_HMou|vyj9WF-{'z=ILry[}cӘ ǬψEػ.v'(XA]ǦOVm]rc:(cZ:۱,䠥b2]:svÂKD2fskl A N{+Tzs_n/TLsGY|IC)b/._m.?8%JQo_rTYWS{gVڶO\}6yTXԣ"s9,{*bk;WbPAEAǃ-^S{R㪅kӚgY*L!O(M1&E'\-tЪSזsy(Q|%EE(&ZE˕kmrXA1{6D4Nc&3'OVZ2fCnri1 -lwXV^,vHZn1}}O^|֛ c/ : Ewv՚-#^4^?yD}.ːF>r;Eؠߐgg$Ų,-1/Wō;,VxF>e˖lRS+7 9uOrow J3qWmW}y{rD%˳Şeˇ̸jt \b E/ tɢ$xYc}zs 5L<7~B]SLw˾p'y9_9_LyحID,(&?q"5]w[{Xb.ZP\ϴ!)g9PӘ&]˖+ꩌT苔)_:|m,m~vcVVn%lVg[}Y^/v -W.ko7E};Pa-vrp~9؋ܴ\{v׆YaAƒU ?rC\잞/]9* t؋ÂT3'5&. a'0j,O{lͰ{8P8BɣOZΝҠ9h~ab! -Wj7 WV9KڝWST|׬fڮFk^E~J'}pg|* 8ÏI׃~ީNͮ,9u%9S5}[<3%CLJׅ]h(1fMsz'OW-~^JvQ{?gL籿=|Ν;ӕ|vK]_뒤=1GФSl\_7/թ/Ba qs o' B! w.U*^%߸Ew|hyȵY>1Ggwhrf{eOISaBNQ3A Ov[N-^tlUK#tƴICcf팏~էjkY YTTxAs>VLqQ7F*UF~ z)-BFzwN<7%e}sm@Ps~{JOl ۏqnIm:J{=㚙;?>ctI?6 n=>X08}o鴽[~3i!_Cھm?w#n9;HoF_m;]xLvJKC,_҈p#Rhw>5!aVpHF'^%7m_<[) EnLcEow̆Tg}2|yɤ^EmbmDfu$?EмJWV;Oq>LkS}*31(q!U|Yꕳ^9:gܴX4V#¬i'p@?ru :[ӺrSk L5c+Q8v7/Ͼ4/_ƇԷOiYϹSl7w&V5+3xS])*7N.NOo ,ݍ3G.#jAZ9lc{'wxG8xjKVJr>ڗ)dU{Ij}UXP'ݸJ!|S,YY7,FT^Hӛ?ޥk@//OS0]1Pvg elS~MxrAu)/[i9 uzFLq|׽韁:4uw-޴ {T-RBƧn|l:)8ã7iJ ڶ1kQ'~Бpg+uQ:H:4ܴw%0M1fZ-Qi|*%2&;Z5\Ssrs3l\O4.)Is/lkM2J{Lfڋ>q@h? 6v}s朩nΟ{&]xdSo"O;Tr1NmyD?LVjxvCeQOEk4Zrw"feO}!Qket7,tO뺽| Oi+|f(o B34kRj;RzfU+IŠO736.ɐS֨B aZKs3e4}IBgtu㿯eorAA'bϖ+1&^<:n\%IB-f:fIUդ;7)pmo:g}ؙa5D4nǟfTE}Wp )vt3-W'_]|t뿂ɛuU毫P#C/f.rx7mؠ>H,Բ߷C I'n 2D"PfV:m?>vet}켣ȧu6ʵ6A\,j[omfs\Fkʤӿ/@&_R>m7r_ pA~MZf⒏;x69yoޔg͕~½aZ;~{MIV vvUl]{mqf'\S?/ bBA.~}z"nieXv!C_7Q<ÉqqOqps3hL;vi9xfʩIw6s[vy_-<*3򤶕4 I[ݬ9eR-ǯ맂7-[굕'w&\Lj7=qM T18๶6z};}S}8=2 cN!YI2$fkNC. :l F' -WmfT/dC|Qke E_X5/Ūo[5|vyKg_y{T5|gk> c_string This creates a Python byte string object that holds a copy of the original C string. It can be safely passed around in Python code, and will be garbage collected when the last reference to it goes out of scope. It is important to remember that null bytes in the string act as terminator character, as generally known from C. The above will therefore only work correctly for C strings that do not contain null bytes. Besides not working for null bytes, the above is also very inefficient for long strings, since Cython has to call :c:func:`strlen()` on the C string first to find out the length by counting the bytes up to the terminating null byte. In many cases, the user code will know the length already, e.g. because a C function returned it. In this case, it is much more efficient to tell Cython the exact number of bytes by slicing the C string. Here is an example: .. literalinclude:: ../../examples/tutorial/string/slicing_c_string.pyx Here, no additional byte counting is required and ``length`` bytes from the ``c_string`` will be copied into the Python bytes object, including any null bytes. Keep in mind that the slice indices are assumed to be accurate in this case and no bounds checking is done, so incorrect slice indices will lead to data corruption and crashes. Note that the creation of the Python bytes string can fail with an exception, e.g. due to insufficient memory. If you need to :c:func:`free()` the string after the conversion, you should wrap the assignment in a try-finally construct: .. literalinclude:: ../../examples/tutorial/string/try_finally.pyx To convert the byte string back into a C :c:type:`char*`, use the opposite assignment:: cdef char* other_c_string = py_string # other_c_string is a 0-terminated string. This is a very fast operation after which ``other_c_string`` points to the byte string buffer of the Python string itself. It is tied to the life time of the Python string. When the Python string is garbage collected, the pointer becomes invalid. It is therefore important to keep a reference to the Python string as long as the :c:type:`char*` is in use. Often enough, this only spans the call to a C function that receives the pointer as parameter. Special care must be taken, however, when the C function stores the pointer for later use. Apart from keeping a Python reference to the string object, no manual memory management is required. Starting with Cython 0.20, the :obj:`bytearray` type is supported and coerces in the same way as the :obj:`bytes` type. However, when using it in a C context, special care must be taken not to grow or shrink the object buffer after converting it to a C string pointer. These modifications can change the internal buffer address, which will make the pointer invalid. Accepting strings from Python code ---------------------------------- The other side, receiving input from Python code, may appear simple at first sight, as it only deals with objects. However, getting this right without making the API too narrow or too unsafe may not be entirely obvious. In the case that the API only deals with byte strings, i.e. binary data or encoded text, it is best not to type the input argument as something like :obj:`bytes`, because that would restrict the allowed input to exactly that type and exclude both subtypes and other kinds of byte containers, e.g. :obj:`bytearray` objects or memory views. Depending on how (and where) the data is being processed, it may be a good idea to instead receive a 1-dimensional memory view, e.g. .. literalinclude:: ../../examples/tutorial/string/arg_memview.pyx Cython's memory views are described in more detail in :doc:`../userguide/memoryviews`, but the above example already shows most of the relevant functionality for 1-dimensional byte views. They allow for efficient processing of arrays and accept anything that can unpack itself into a byte buffer, without intermediate copying. The processed content can finally be returned in the memory view itself (or a slice of it), but it is often better to copy the data back into a flat and simple :obj:`bytes` or :obj:`bytearray` object, especially when only a small slice is returned. Since memoryviews do not copy the data, they would otherwise keep the entire original buffer alive. The general idea here is to be liberal with input by accepting any kind of byte buffer, but strict with output by returning a simple, well adapted object. This can simply be done as follows: .. literalinclude:: ../../examples/tutorial/string/return_memview.pyx For read-only buffers, like :obj:`bytes`, the memoryview item type should be declared as ``const`` (see :ref:`readonly_views`). If the byte input is actually encoded text, and the further processing should happen at the Unicode level, then the right thing to do is to decode the input straight away. This is almost only a problem in Python 2.x, where Python code expects that it can pass a byte string (:obj:`str`) with encoded text into a text API. Since this usually happens in more than one place in the module's API, a helper function is almost always the way to go, since it allows for easy adaptation of the input normalisation process later. This kind of input normalisation function will commonly look similar to the following: .. literalinclude:: ../../examples/tutorial/string/to_unicode.pyx And should then be used like this: .. literalinclude:: ../../examples/tutorial/string/api_func.pyx Similarly, if the further processing happens at the byte level, but Unicode string input should be accepted, then the following might work, if you are using memory views: .. literalinclude:: ../../examples/tutorial/string/to_char.pyx In this case, you might want to additionally ensure that byte string input really uses the correct encoding, e.g. if you require pure ASCII input data, you can run over the buffer in a loop and check the highest bit of each byte. This should then also be done in the input normalisation function. Dealing with "const" -------------------- Many C libraries use the ``const`` modifier in their API to declare that they will not modify a string, or to require that users must not modify a string they return, for example: .. literalinclude:: ../../examples/tutorial/string/someheader.h Cython has support for the ``const`` modifier in the language, so you can declare the above functions straight away as follows: .. literalinclude:: ../../examples/tutorial/string/const.pyx Decoding bytes to text ---------------------- The initially presented way of passing and receiving C strings is sufficient if your code only deals with binary data in the strings. When we deal with encoded text, however, it is best practice to decode the C byte strings to Python Unicode strings on reception, and to encode Python Unicode strings to C byte strings on the way out. With a Python byte string object, you would normally just call the ``bytes.decode()`` method to decode it into a Unicode string:: ustring = byte_string.decode('UTF-8') Cython allows you to do the same for a C string, as long as it contains no null bytes: .. literalinclude:: ../../examples/tutorial/string/naive_decode.pyx And, more efficiently, for strings where the length is known: .. literalinclude:: ../../examples/tutorial/string/decode.pyx The same should be used when the string contains null bytes, e.g. when it uses an encoding like UCS-4, where each character is encoded in four bytes most of which tend to be 0. Again, no bounds checking is done if slice indices are provided, so incorrect indices lead to data corruption and crashes. However, using negative indices is possible and will inject a call to :c:func:`strlen()` in order to determine the string length. Obviously, this only works for 0-terminated strings without internal null bytes. Text encoded in UTF-8 or one of the ISO-8859 encodings is usually a good candidate. If in doubt, it's better to pass indices that are 'obviously' correct than to rely on the data to be as expected. It is common practice to wrap string conversions (and non-trivial type conversions in general) in dedicated functions, as this needs to be done in exactly the same way whenever receiving text from C. This could look as follows: .. literalinclude:: ../../examples/tutorial/string/utf_eight.pyx Most likely, you will prefer shorter function names in your code based on the kind of string being handled. Different types of content often imply different ways of handling them on reception. To make the code more readable and to anticipate future changes, it is good practice to use separate conversion functions for different types of strings. Encoding text to bytes ---------------------- The reverse way, converting a Python unicode string to a C :c:type:`char*`, is pretty efficient by itself, assuming that what you actually want is a memory managed byte string:: py_byte_string = py_unicode_string.encode('UTF-8') cdef char* c_string = py_byte_string As noted before, this takes the pointer to the byte buffer of the Python byte string. Trying to do the same without keeping a reference to the Python byte string will fail with a compile error:: # this will not compile ! cdef char* c_string = py_unicode_string.encode('UTF-8') Here, the Cython compiler notices that the code takes a pointer to a temporary string result that will be garbage collected after the assignment. Later access to the invalidated pointer will read invalid memory and likely result in a segfault. Cython will therefore refuse to compile this code. C++ strings ----------- When wrapping a C++ library, strings will usually come in the form of the :c:type:`std::string` class. As with C strings, Python byte strings automatically coerce from and to C++ strings: .. literalinclude:: ../../examples/tutorial/string/cpp_string.pyx The memory management situation is different than in C because the creation of a C++ string makes an independent copy of the string buffer which the string object then owns. It is therefore possible to convert temporarily created Python objects directly into C++ strings. A common way to make use of this is when encoding a Python unicode string into a C++ string:: cdef string cpp_string = py_unicode_string.encode('UTF-8') Note that this involves a bit of overhead because it first encodes the Unicode string into a temporarily created Python bytes object and then copies its buffer into a new C++ string. For the other direction, efficient decoding support is available in Cython 0.17 and later: .. literalinclude:: ../../examples/tutorial/string/decode_cpp_string.pyx For C++ strings, decoding slices will always take the proper length of the string into account and apply Python slicing semantics (e.g. return empty strings for out-of-bounds indices). Auto encoding and decoding -------------------------- Cython 0.19 comes with two new directives: ``c_string_type`` and ``c_string_encoding``. They can be used to change the Python string types that C/C++ strings coerce from and to. By default, they only coerce from and to the bytes type, and encoding or decoding must be done explicitly, as described above. There are two use cases where this is inconvenient. First, if all C strings that are being processed (or the large majority) contain text, automatic encoding and decoding from and to Python unicode objects can reduce the code overhead a little. In this case, you can set the ``c_string_type`` directive in your module to :obj:`unicode` and the ``c_string_encoding`` to the encoding that your C code uses, for example: .. literalinclude:: ../../examples/tutorial/string/auto_conversion_1.pyx The second use case is when all C strings that are being processed only contain ASCII encodable characters (e.g. numbers) and you want your code to use the native legacy string type in Python 2 for them, instead of always using Unicode. In this case, you can set the string type to :obj:`str`: .. literalinclude:: ../../examples/tutorial/string/auto_conversion_2.pyx The other direction, i.e. automatic encoding to C strings, is only supported for ASCII and the "default encoding", which is usually UTF-8 in Python 3 and usually ASCII in Python 2. CPython handles the memory management in this case by keeping an encoded copy of the string alive together with the original unicode string. Otherwise, there would be no way to limit the lifetime of the encoded string in any sensible way, thus rendering any attempt to extract a C string pointer from it a dangerous endeavour. The following safely converts a Unicode string to ASCII (change ``c_string_encoding`` to ``default`` to use the default encoding instead): .. literalinclude:: ../../examples/tutorial/string/auto_conversion_3.pyx (This example uses a function context in order to safely control the lifetime of the Unicode string. Global Python variables can be modified from the outside, which makes it dangerous to rely on the lifetime of their values.) Source code encoding -------------------- When string literals appear in the code, the source code encoding is important. It determines the byte sequence that Cython will store in the C code for bytes literals, and the Unicode code points that Cython builds for unicode literals when parsing the byte encoded source file. Following :PEP:`263`, Cython supports the explicit declaration of source file encodings. For example, putting the following comment at the top of an ``ISO-8859-15`` (Latin-9) encoded source file (into the first or second line) is required to enable ``ISO-8859-15`` decoding in the parser:: # -*- coding: ISO-8859-15 -*- When no explicit encoding declaration is provided, the source code is parsed as UTF-8 encoded text, as specified by :PEP:`3120`. `UTF-8`_ is a very common encoding that can represent the entire Unicode set of characters and is compatible with plain ASCII encoded text that it encodes efficiently. This makes it a very good choice for source code files which usually consist mostly of ASCII characters. .. _`UTF-8`: https://en.wikipedia.org/wiki/UTF-8 As an example, putting the following line into a UTF-8 encoded source file will print ``5``, as UTF-8 encodes the letter ``'ö'`` in the two byte sequence ``'\xc3\xb6'``:: print( len(b'abcö') ) whereas the following ``ISO-8859-15`` encoded source file will print ``4``, as the encoding uses only 1 byte for this letter:: # -*- coding: ISO-8859-15 -*- print( len(b'abcö') ) Note that the unicode literal ``u'abcö'`` is a correctly decoded four character Unicode string in both cases, whereas the unprefixed Python :obj:`str` literal ``'abcö'`` will become a byte string in Python 2 (thus having length 4 or 5 in the examples above), and a 4 character Unicode string in Python 3. If you are not familiar with encodings, this may not appear obvious at first read. See `CEP 108`_ for details. As a rule of thumb, it is best to avoid unprefixed non-ASCII :obj:`str` literals and to use unicode string literals for all text. Cython also supports the ``__future__`` import ``unicode_literals`` that instructs the parser to read all unprefixed :obj:`str` literals in a source file as unicode string literals, just like Python 3. .. _`CEP 108`: https://github.com/cython/cython/wiki/enhancements-stringliterals Single bytes and characters --------------------------- The Python C-API uses the normal C :c:type:`char` type to represent a byte value, but it has two special integer types for a Unicode code point value, i.e. a single Unicode character: :c:type:`Py_UNICODE` and :c:type:`Py_UCS4`. Cython supports the first natively, support for :c:type:`Py_UCS4` is new in Cython 0.15. :c:type:`Py_UNICODE` is either defined as an unsigned 2-byte or 4-byte integer, or as :c:type:`wchar_t`, depending on the platform. The exact type is a compile time option in the build of the CPython interpreter and extension modules inherit this definition at C compile time. The advantage of :c:type:`Py_UCS4` is that it is guaranteed to be large enough for any Unicode code point value, regardless of the platform. It is defined as a 32bit unsigned int or long. In Cython, the :c:type:`char` type behaves differently from the :c:type:`Py_UNICODE` and :c:type:`Py_UCS4` types when coercing to Python objects. Similar to the behaviour of the bytes type in Python 3, the :c:type:`char` type coerces to a Python integer value by default, so that the following prints 65 and not ``A``:: # -*- coding: ASCII -*- cdef char char_val = 'A' assert char_val == 65 # ASCII encoded byte value of 'A' print( char_val ) If you want a Python bytes string instead, you have to request it explicitly, and the following will print ``A`` (or ``b'A'`` in Python 3):: print( char_val ) The explicit coercion works for any C integer type. Values outside of the range of a :c:type:`char` or :c:type:`unsigned char` will raise an :obj:`OverflowError` at runtime. Coercion will also happen automatically when assigning to a typed variable, e.g.:: cdef bytes py_byte_string py_byte_string = char_val On the other hand, the :c:type:`Py_UNICODE` and :c:type:`Py_UCS4` types are rarely used outside of the context of a Python unicode string, so their default behaviour is to coerce to a Python unicode object. The following will therefore print the character ``A``, as would the same code with the :c:type:`Py_UNICODE` type:: cdef Py_UCS4 uchar_val = u'A' assert uchar_val == 65 # character point value of u'A' print( uchar_val ) Again, explicit casting will allow users to override this behaviour. The following will print 65:: cdef Py_UCS4 uchar_val = u'A' print( uchar_val ) Note that casting to a C :c:type:`long` (or :c:type:`unsigned long`) will work just fine, as the maximum code point value that a Unicode character can have is 1114111 (``0x10FFFF``). On platforms with 32bit or more, :c:type:`int` is just as good. Narrow Unicode builds ---------------------- In narrow Unicode builds of CPython before version 3.3, i.e. builds where ``sys.maxunicode`` is 65535 (such as all Windows builds, as opposed to 1114111 in wide builds), it is still possible to use Unicode character code points that do not fit into the 16 bit wide :c:type:`Py_UNICODE` type. For example, such a CPython build will accept the unicode literal ``u'\U00012345'``. However, the underlying system level encoding leaks into Python space in this case, so that the length of this literal becomes 2 instead of 1. This also shows when iterating over it or when indexing into it. The visible substrings are ``u'\uD808'`` and ``u'\uDF45'`` in this example. They form a so-called surrogate pair that represents the above character. For more information on this topic, it is worth reading the `Wikipedia article about the UTF-16 encoding`_. .. _`Wikipedia article about the UTF-16 encoding`: https://en.wikipedia.org/wiki/UTF-16/UCS-2 The same properties apply to Cython code that gets compiled for a narrow CPython runtime environment. In most cases, e.g. when searching for a substring, this difference can be ignored as both the text and the substring will contain the surrogates. So most Unicode processing code will work correctly also on narrow builds. Encoding, decoding and printing will work as expected, so that the above literal turns into exactly the same byte sequence on both narrow and wide Unicode platforms. However, programmers should be aware that a single :c:type:`Py_UNICODE` value (or single 'character' unicode string in CPython) may not be enough to represent a complete Unicode character on narrow platforms. For example, if an independent search for ``u'\uD808'`` and ``u'\uDF45'`` in a unicode string succeeds, this does not necessarily mean that the character ``u'\U00012345`` is part of that string. It may well be that two different characters are in the string that just happen to share a code unit with the surrogate pair of the character in question. Looking for substrings works correctly because the two code units in the surrogate pair use distinct value ranges, so the pair is always identifiable in a sequence of code points. As of version 0.15, Cython has extended support for surrogate pairs so that you can safely use an ``in`` test to search character values from the full :c:type:`Py_UCS4` range even on narrow platforms:: cdef Py_UCS4 uchar = 0x12345 print( uchar in some_unicode_string ) Similarly, it can coerce a one character string with a high Unicode code point value to a Py_UCS4 value on both narrow and wide Unicode platforms:: cdef Py_UCS4 uchar = u'\U00012345' assert uchar == 0x12345 In CPython 3.3 and later, the :c:type:`Py_UNICODE` type is an alias for the system specific :c:type:`wchar_t` type and is no longer tied to the internal representation of the Unicode string. Instead, any Unicode character can be represented on all platforms without resorting to surrogate pairs. This implies that narrow builds no longer exist from that version on, regardless of the size of :c:type:`Py_UNICODE`. See :PEP:`393` for details. Cython 0.16 and later handles this change internally and does the right thing also for single character values as long as either type inference is applied to untyped variables or the portable :c:type:`Py_UCS4` type is explicitly used in the source code instead of the platform specific :c:type:`Py_UNICODE` type. Optimisations that Cython applies to the Python unicode type will automatically adapt to :PEP:`393` at C compile time, as usual. Iteration --------- Cython 0.13 supports efficient iteration over :c:type:`char*`, bytes and unicode strings, as long as the loop variable is appropriately typed. So the following will generate the expected C code: .. literalinclude:: ../../examples/tutorial/string/for_char.pyx The same applies to bytes objects: .. literalinclude:: ../../examples/tutorial/string/for_bytes.pyx For unicode objects, Cython will automatically infer the type of the loop variable as :c:type:`Py_UCS4`: .. literalinclude:: ../../examples/tutorial/string/for_unicode.pyx The automatic type inference usually leads to much more efficient code here. However, note that some unicode operations still require the value to be a Python object, so Cython may end up generating redundant conversion code for the loop variable value inside of the loop. If this leads to a performance degradation for a specific piece of code, you can either type the loop variable as a Python object explicitly, or assign its value to a Python typed variable somewhere inside of the loop to enforce one-time coercion before running Python operations on it. There are also optimisations for ``in`` tests, so that the following code will run in plain C code, (actually using a switch statement): .. literalinclude:: ../../examples/tutorial/string/if_char_in.pyx Combined with the looping optimisation above, this can result in very efficient character switching code, e.g. in unicode parsers. Windows and wide character APIs ------------------------------- Windows system APIs natively support Unicode in the form of zero-terminated UTF-16 encoded :c:type:`wchar_t*` strings, so called "wide strings". By default, Windows builds of CPython define :c:type:`Py_UNICODE` as a synonym for :c:type:`wchar_t`. This makes internal :obj:`unicode` representation compatible with UTF-16 and allows for efficient zero-copy conversions. This also means that Windows builds are always `Narrow Unicode builds`_ with all the caveats. To aid interoperation with Windows APIs, Cython 0.19 supports wide strings (in the form of :c:type:`Py_UNICODE*`) and implicitly converts them to and from :obj:`unicode` string objects. These conversions behave the same way as they do for :c:type:`char*` and :obj:`bytes` as described in `Passing byte strings`_. In addition to automatic conversion, unicode literals that appear in C context become C-level wide string literals and :py:func:`len` built-in function is specialized to compute the length of zero-terminated :c:type:`Py_UNICODE*` string or array. Here is an example of how one would call a Unicode API on Windows:: cdef extern from "Windows.h": ctypedef Py_UNICODE WCHAR ctypedef const WCHAR* LPCWSTR ctypedef void* HWND int MessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, int uType) title = u"Windows Interop Demo - Python %d.%d.%d" % sys.version_info[:3] MessageBoxW(NULL, u"Hello Cython \u263a", title, 0) .. Warning:: The use of :c:type:`Py_UNICODE*` strings outside of Windows is strongly discouraged. :c:type:`Py_UNICODE` is inherently not portable between different platforms and Python versions. CPython 3.3 has moved to a flexible internal representation of unicode strings (:pep:`393`), making all :c:type:`Py_UNICODE` related APIs deprecated and inefficient. One consequence of CPython 3.3 changes is that :py:func:`len` of :obj:`unicode` strings is always measured in *code points* ("characters"), while Windows API expect the number of UTF-16 *code units* (where each surrogate is counted individually). To always get the number of code units, call :c:func:`PyUnicode_GetSize` directly. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/two-syntax-variants-used0000644000175100001770000000163500000000000022163 0ustar00runnerdocker00000000000000.. note:: This page uses two different syntax variants: * Cython specific ``cdef`` syntax, which was designed to make type declarations concise and easily readable from a C/C++ perspective. * Pure Python syntax which allows static Cython type declarations in :ref:`pure Python code `, following `PEP-484 `_ type hints and `PEP 526 `_ variable annotations. To make use of C data types in Python syntax, you need to import the special ``cython`` module in the Python module that you want to compile, e.g. .. code-block:: python import cython If you use the pure Python syntax we strongly recommend you use a recent Cython 3 release, since significant improvements have been made here compared to the 0.29.x releases. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.0687242 Cython-3.0.8/docs/src/userguide/0000755000175100001770000000000000000000000017307 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/buffer.rst0000644000175100001770000001076300000000000021321 0ustar00runnerdocker00000000000000.. _buffer: Implementing the buffer protocol ================================ .. include:: ../two-syntax-variants-used Cython objects can expose memory buffers to Python code by implementing the "buffer protocol". This chapter shows how to implement the protocol and make use of the memory managed by an extension type from NumPy. A matrix class -------------- The following Cython/C++ code implements a matrix of floats, where the number of columns is fixed at construction time but rows can be added dynamically. .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/buffer/matrix.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/buffer/matrix.pyx There are no methods to do anything productive with the matrices' contents. We could implement custom ``__getitem__``, ``__setitem__``, etc. for this, but instead we'll use the buffer protocol to expose the matrix's data to Python so we can use NumPy to do useful work. Implementing the buffer protocol requires adding two methods, ``__getbuffer__`` and ``__releasebuffer__``, which Cython handles specially. .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/buffer/matrix_with_buffer.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/buffer/matrix_with_buffer.pyx The method ``Matrix.__getbuffer__`` fills a descriptor structure, called a ``Py_buffer``, that is defined by the Python C-API. It contains a pointer to the actual buffer in memory, as well as metadata about the shape of the array and the strides (step sizes to get from one element or row to the next). Its ``shape`` and ``strides`` members are pointers that must point to arrays of type and size ``Py_ssize_t[ndim]``. These arrays have to stay alive as long as any buffer views the data, so we store them on the ``Matrix`` object as members. The code is not yet complete, but we can already compile it and test the basic functionality. :: >>> from matrix import Matrix >>> import numpy as np >>> m = Matrix(10) >>> np.asarray(m) array([], shape=(0, 10), dtype=float32) >>> m.add_row() >>> a = np.asarray(m) >>> a[:] = 1 >>> m.add_row() >>> a = np.asarray(m) >>> a array([[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]], dtype=float32) Now we can view the ``Matrix`` as a NumPy ``ndarray``, and modify its contents using standard NumPy operations. Memory safety and reference counting ------------------------------------ The ``Matrix`` class as implemented so far is unsafe. The ``add_row`` operation can move the underlying buffer, which invalidates any NumPy (or other) view on the data. If you try to access values after an ``add_row`` call, you'll get outdated values or a segfault. This is where ``__releasebuffer__`` comes in. We can add a reference count to each matrix, and lock it for mutation whenever a view exists. .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/buffer/view_count.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/buffer/view_count.pyx Flags ----- We skipped some input validation in the code. The ``flags`` argument to ``__getbuffer__`` comes from ``np.asarray`` (and other clients) and is an OR of boolean flags that describe the kind of array that is requested. Strictly speaking, if the flags contain ``PyBUF_ND``, ``PyBUF_SIMPLE``, or ``PyBUF_F_CONTIGUOUS``, ``__getbuffer__`` must raise a ``BufferError``. These macros can be ``cimport``'d from ``cpython.buffer``. (The matrix-in-vector structure actually conforms to ``PyBUF_ND``, but that would prohibit ``__getbuffer__`` from filling in the strides. A single-row matrix is F-contiguous, but a larger matrix is not.) References ---------- The buffer interface used here is set out in :PEP:`3118`, Revising the buffer protocol. A tutorial for using this API from C is on Jake Vanderplas's blog, `An Introduction to the Python Buffer Protocol `_. Reference documentation is available for `Python 3 `_ and `Python 2 `_. The Py2 documentation also describes an older buffer protocol that is no longer in use; since Python 2.6, the :PEP:`3118` protocol has been implemented, and the older protocol is only relevant for legacy code. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/compute_typed_html.jpg0000644000175100001770000034370100000000000023726 0ustar00runnerdocker00000000000000JFIF``"ExifMM*C      C  a=" P!"RST 1a#Abd$2Q3CW%Bq&4'56Dcr Q  !1AQ"Ra2TqSb#BUcde3rC$s4D ?r[n\/MɓgL|X M\pEQUWj:w-`9C5ͭPG$UпӜwx3-v+zFXN(~pAUr9eݍq}zH(dc^]eh͇@ ͷANYc{3M75- -Lj.r j0 hv+dm웏6<̅xUFMybF1vp #{`N;2+&#x)ŶrSd6"nj6ؑ*XuW,EYr(,ܠw,,"|)ǎ.F;TK^ tT[q`TlN &m|$;DĀ,;vFș&qyO1[>-kdJ `U_}jփE? "%X.d$S=d.j &-r :zù/o:_]9dm2%JbHPC;Vܷ6g?ku[dOfMmcWn"託sg#fpt$fFU #t^v^n)U%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"}콇dݣ]fۗn~!]9ʻᾇA 3/B(gv_TA 3/B(0ljl]+ ֟iᎍ9}õ* r:*"te*$J\A&d48iƢ^4l"DW  ;("ey?fyWeT"dʭ@P?;,? y?fyWeT%gv_O)DP?;,? y?fyWeTEgv_O)DP?;,? y?fyWeTEgQ%`9m;fȶ *̌qD$dR[J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"߲V1X^.ֻTc/UmiL|&ƮPe5mHYQ]l݌nۭ*@j73r .ԫP^Cy@UPTyQUjuHZfVpB/DCpِ c}@;r1ԺsTc/STc/W3qY5s+]|;N1FrTzک 2xn-$eVCYoXRnuC;6BYp@"/\y@[T|TE+E.[Iqun992q4*hKA ש_rr='T02&i96\3]-R Ɉ/&#= #8v}Wyz%!8.;U\5.7QԖM+2N2%Ψ"tG|6^@h..mh^0pv{]te݈~rrM1,,ό*zC2˹5*-,PPT5^TUDڸ}jM!p-2Z&(@ @8dN'3@٪r ҭ\%{:E5iMΛN(w>_pXͦ{vrݕv0LDwk6=)臰5.ɩXm( ${HV[k?E)b'z*OƋih9ĚPv 3uppY,l1 sH N~rr9(=u.Ñ5ޠ$Դ7f}]P M \Ne?!KԫL :o`gׁ/(*r]BC^`g:(:vGK4縘"@bH;A=# K4'nXinRƀ;"mFMzڲgw)R 797Hq#w0"ݎrp[1wv{ƿZ|q/v;csRqiq AOIQM&5zD5(8˽iR%͚ǏMpEUU+o8~c^3zSAk+͆E mjY9 ZeYn#3HW&ƖIZ1W(ˏ[MFrЂ,wn֗5eZQ6yAm-Jl+\71kIZ" +юSrNȀ8J"ӐaqxÃ\p2 cX@v$wag \g|pe/LŗZY}udĸX5!'d@N5*ne>U-a9r̎*쨢M"*l=8՞ UwbZr]to6Ÿb@8Ix[xEU[5iUE]S,Q. |oq|aU۳%rW|APRU-4ͭJ{gߒqy./ s 2O2A!X8O~U%YN8.smk_slgimv+5nBKlWySs8.ZkF9C[zeVXw~ʮ{7h`ܼslT 3H꜈&@0ua `))QRJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRE׬ K!/#ˬ>||Ĺ|[K1$KU6pi6ulVeΒ"d#p}P9DԕIjם@a;Mnyf[qK=`A> lGxѡ&U5t#ZHkԗ,z_,Ik)m, BJ&TGT[/fNZ]'Z9 SkAq0A#0 V}0l.w#'$ Uw<b:a!A+_:"o ki+jh>GZ4m ߾?$ԇ2G|q]G#fSQm-F r(k%Nc&mJaݯqm[ J@rC*4*ɨǕfaԫ [rRDUvC,1)#!qФ2Ϡn "^]%-Uv}KNXeo(Dpl`Jk^r̀u=y+H.xSd\5EUkge&9qg<A *r*ɉ!5$۝x"GBXF?龢je MwisLY&EmPxEi\Ꞿt1M+_(2 :f\ kP)[g⚿4+#Hpݤ6C'#2*xMzHHF ]$= \Zz.ܧN.s<=1 K6Gb숕øoi噅+~Iv>n\;#J~aUQFGD6}5"tr)Z{ii 6R6OeE_Jd<7DTUe]Ů7kr\TTU]U~EZoi]3h.6 `Xg[N- 2ߖޕ/ʩۇ䚐Y(o:}Lc:MeHYN]-69ctQo&abn(7HXs$w:@#s;(H"ۂ;/q>ӥکko_2 77fup͕Cn@6/ Mra4uRs40;@9:A#nF"r+I cZGd΋Ȭ<ȬX BAp#˜"H !.ʫ[7EIȰN=2ɢ,YgQMnuhp@H `A (tI4ۏٚ-< b6|o,i̤Cͮ v,-!! ;$萂&Uo+X/mYἚ 2qܙ}uUGۛƯ՘Z٧rPn֞Õo-LˎǑ6yMqmM!z;.$BtT>T*ߑs&H$`dT@``xR 'ēgZ xϧKsDUD%`. GSmUEWU+A2K,D2L!q\ û^ۣ&@4+ 6Ti eDU]P*:éV;sŌ,XbSFCDmHe@ABE޾WV"VmKQ` d5jĉNn؁\''\6NodJpPk9UQ̌jZpTDHcߣL-vpf#!Y$2v3ć/Ji9 _ @㌰^0{~jY~ĹI0ZmYma&(ͳVq'yqo Տs0?2I-h`}mܭ*q˔6d:JH۪Vh7aa8:9QѨ08=b=`0D^8r$O,Qn73%r⒚Q&g,֭Bb&I$e /:rO,2 s6ν߀VUU #|N2$ċ)lkX!k>*=b[ XY wH%D0!qq@Ɯq-Kub.g^C#&q-6 )sq1H 3j&ǖ8k3+r8<_4Y3(v[fgHD/!Lڦ>KlzA nvqzz_sڪ^,^!D a+{2vVd4&WQPz-Jh2aaEEQp P|QQ|kKP0[#Ӥ)k^QLIy$ߔߺ8dD"%Y[wLDc8Yn8IxU:.h0ǽ淬v#= Ņ"p5T6شP~7mk}ÊZl7Kfe6v^¢Ț< uUMƌq:|ǻW1я"[߳],w$7-V4ǤDi9c,8Dc΁ӎ33\ VNjpl9+6Vl$8+&H_!1:$+}T0Iu4 FD$s!gc׈z*EN#\,YQt' .+tq&%hȁI.]> }0նv90ݏ]u} zeEoڑI ڛE.QfMcuHUЯ|ZtܢV2,7nHKmF7"-6طR$NU4VI 2׌ԜӑA$t3FK?68ad^B^ I"+'a8$BQMT@v``wd{z&]!\wr 4L&u] ^lp̉bzagVh}[Q!k3זvm xdʝ}]j}+ `/P|SdTS7CXZplFB=@@Q#^a38LᴂgYXQ8Ӹ;c:F_oKn_`)4+ћHِ-Tq:|ǻW1я"[߳],w$7-V4ǤDi9c,8Dc΁vյ 3$s;gt4݌U? 2I'!G .v(\g29d.굷{LFNY{5zq%3[Ɋ ,Y\h۩*փ fÖj>b7jv 5Gr*kbvq(ۉwCߦN]yBfyOgGF68Y1}(z"**6h &=n f7FdH*x " #"`\ r m޴o Bߺȳ7+0qrMpz \B#$`MBp˗W8u"1>-0r{6EwJ*l+/ՋRfeah3.c'!tȑU7US$j99уDG@s` 6RqLdIIO82"YN@{o]P1رHh"QQ\;zk Vo <./La>8Ng n"G&P@U)k-z5mje6M{Ço N$,@jL[U] +aEr AkZk20@=DH8R3Tzߕ.%&ѫŮ._xcM^l(!JRiW50ME&i= QxZgG.ѯGwVRP%`$*_-o2mHqbۆEczPmMS̋3\&z1:*gUhGZbΈV,AOG v]7EOMih #=5P.Q=5a: /O=0l%pwOyGm1d^+B:j 6*)<qY;D.{ʮenXϝ%L$FbN )/5wGM^ΫyE,t_. [.^QTDU3SO*`R-a^Ǟήe)sG^gU\-T"L?o\lw;=i-k 2#4AcSt!E |BZ5̄.zs@1mu2]`CDcl.ĩ \Zp61sgHApIkq: Xu;2Sw6n =G3!-c(ZpU K]x_LrNлxRܦ>QpZ)|H()D`+fqA_*£_6-m٣JI"۪#"(:n7L 'iK3pc1pՎ] x;o\fFkb*(ڬZict: -[+ls#yیȌzd٠8N/!/'*)TL"׫X\Kv9JjԨDg[puZ4CmMЅk;]3{vTZ0fцCf9-+Gf7c)=2saqR-UvU_VIQ2-7)8p =ry6Ǡ8dV -,J((L{'Պ;Q0;GY2J0^6oօibxLLX{rڮݗvzlD}9lh@ѨTު288oKmr dk[+R&2vɑGrGHtSDm 7N;L#9^j\=i=`maW$bՒpnGfrdtyQ r H8kS3 ; 9yRf얒,ɞEuf#Xwm6>Q}YI1 Lz}6bV*xo-Z:931cˮjv]ۏ1TYFW}HGj9`qmS8?`TmLγޘް,]qYzuɬ2WB&3}C'Am4A/Y'cfXy2# /QEEMEQ*_ca;0 iJ{k.^ymyb3/e'pPEČȄDTk,g17Ս=zdgF~moq9j9* t%$m @ a[WJ=)2tQ]iw-LjB?+mK9H옌o Lu Wf.7ĩbL(ܕ)8,NPu@Wg1f6e:e aۑr; UGq7pVkiuYָ;q"8vBB^aV;3J]֞볆5+(q;,ðkvQsݑ5mC.$$(n(:6٨Jv.qEplD;j1եFv0 p%"%js2YՁL'՗^20A*c|Cw 5HIVFPHyasHHMOKoe}pݱyYG^܌(<’n-Hb%& ߍG*%ډ3LtE"D{u$G4^nM+9f<ʀJ+^ ;\\31izuIǦ b8ŕ>XH긻urJ6]$5F$& k}Si.W?ھmڄƗa9q|Le WRy@>%c$4GDAH/V@u:fo6.m>)$/ *2*0&rNOc,CR[xȴ;mi}Jg,ߗ @tK촗)bHD$7A~d){\Z$*fArdnӘ'FLB  ꮑEf]1 HH GE ԗ₝Jqkm=Qxa-vF;ZThE K3C\r'b!Ѡ ˄жۈ,2-8Nk?ǟbK\rHF3s1 N(3:6hTh64WWtDdv;g^}*L%ĥYs\ϝFd"6$4"-Y(]Q4ö],-O^7Cx.WN`]bMEvTJRvgǷ9qWM`чwFQJtOT.yͦڅVmjarqYjӌ#z1m6T%UAHVz ʋ tLbŇqߙ:#MWҮVmxl#Ol`x`# pI'Yuݧjպ<$+ L*κ6ȣ}1PRpLr՞T7g#0̈RG}EQqqpUq$ED1ULT8|}926Y3*# ֍4K.Խ/lyUüp-w:+0o!Ԡlc4Dɩ*!ˉhF\g0Evv"C(9 o&$v7R^ t(CDTG^c6K]gVU='D`Ԍq-ƵX࿇u3m/%R`s}Iی4GDMF-qiqn%.ym$ Bg*[v åGTzx^s 2èqU<*CL'XGav9t bVF\&iL o}5-[ݻJTTstw J|窖m&" ^$v]u#L9%֝vx^;#I ˆ|T4/YCp+.[*>#"7d^t*09">5t0 z#q8ߊ*wܴnK t`T,˜AcUd>"+t_4 199qoLC2]KrGzFɸ<1IDەmVnZzI$9ؐzlC/1fLfҊK!ٛ[ :)ySq r6kY3+y$⊠"*/eRS 05Lr GDyx] :Ne$}QsRJ`ei 2tJ˸zԄ >#2cMDwKap&1NYr' JM߫"f ar?,D9zs\{Pک^ntoɣnӘi{9^EGT-3HEP}$q\,mPW2qi͢鋹U|lW<ՆFo Ԑ6oT[ݭ=m쒳So?aqv'*t-*-䴵A>z?2PHMZz7j/y>y?qp[cnYZ˭t4U.bs6]k#vTS؅v6+YrU-sM( ܔh _}Q=yS7"#C+ÅL:j6 bLR&B)",'z^k'wydV)JW<'U:mcC[Pq?EK|WIzL+'1F_y8 YV3HEP}ל$q\TN,^i}~[oWTJo4A ɴTDUTicr11eB^b@v%jsêx}출2[.ۙkk8+H[jV$!Q|}zu;xbU|ܦʺ֙Ep.<#&Hڊ"* H ^M.2Pd}e*{ޭ4S,L|zfwԦ; {[ Ǒ)U̶l. E*+ ȕPf3Ycw51FUQٖVDq_MO8QWsW0fXdvՊLVF)-Ȼd<̥m\‹D!pۺiO_O{KOh$Qkni=- GݏVcظi(mz&cq;u:p2E5k}JTGK ø`\V^G95nLE;[g7Ien@s(&E _ (*nn̸7n |s35%%mߑq\@up47>>>:sQZx -1rh@=7:jugH9=[,+߆]G]UN萒!!( ·b{v#Z3q\zKxlvӮł\ļn:&녹-JI3d]@c-F-Ld5ؐIoƩ ЍZk6cV?e[F?D ԛ׎SaJos7ѻXp=$N Zٗ\Ol CToAL/nK,~eBu^q 65Z7\5$=}їe]n.mIf:v+` Fe(nғ)Jm 21'k{'2JAX;^ށvil>fX;bRVZOsN'"8C1 Sh@B!K4Ȱ4<),F.Inj™MauΞ)ĝlQk@>={zoV4>MkqjDK.Nm˂ZGSmAp ąHV!>YZdVG3>4$\gSEAKNb#+qovQifVOXrX8Lp!amEUz[·VnvIڙecV7K4ܐMȷn'LA`wSzIJ:M!}'gX"Nqw~ T.ni]&i^AdWS]-8kgė/rND8r";DLplF]uuW$nZ\+˼50mJNܥX0-#6bŮiHq8e]=jcY?n\ȮG|NeGTZ18

Gc .ciMiZ_/ Oe8ӈvTzKI U\#a\8q iu}˂iʇ-bV%)J0 d-J_'Đۢߞ)\<5SΈP6Sߘ>ڎ>r԰10=]jĥboPK~Y`$B-))_ӈs6\ %,EB '>E@^EUVLϢ"{$v9tw=JmJ8oA4WAIxvܝH.#y^2!EUE$MR.6c(1WtzY |\ үj:6ʱ:. q\ٷG ~PB˲U-ֳ'~VNpT #XϡI)PgۑJr-B*x[;3Ti`EN2[UC]\pv%Uv-[5SFANbFEbF^f#c)P\w-3uew<,KW0];\WP v*uKEai  #^[gД+]e)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQQHn3|xx 3CȶKx Ky:\ 28ac4g:u3Xo_$̬keY~\W6ZKd3&,Qי:#΃n7Zh$*V=`#a xyGoX~p}fo|O.,:yxJ=!j EĆqfkiMaU%2XndK(H,y, d#{$ Y|gzu㈃.i9.:uq1TwTQedPSD* wgoxSm}dmf$$Ɩ*+ GΏ([$}@(ִ #-ȐNhQ[mym|[۸FN&ٟ{GDp'OJ̲Ho-a{mLtt7YY.t^s KJТ:*u.476`n9dq&L VctՌЮ9U {-s.ۙ'K)trk֒궝Й׈zejy o]0Իre=41Dm:GG!!MU7EOZh :kc7&O0lɃ,1mC8ÛF:<Ųs/WNۇ(^ Tz'T7Hn}P0;#*ԹzÒ9iQ̬P!ĺ7{[mّP\IKmUD,~q8 '.k݃ujK.w_a5^~#[m6%?FEJcts]?@p֩kCEєzq>^`7+Qaqсbv:sѱDk\˦}D@%sg8bǡ3aẇ2>gm` 6qUDEEZR ~f5F29O|}:gſ_9Kȶm.\"n8d"(\vFK t[RY'/5#kKsIV`H6d)+Xіkbuɺ.0y@f{=]-ve&v[xXe_L>Lf[mO8[M-drY !X5٪5tN+5sgsm$2ĸHeS&^1 ->±,.Agrf;=@K97U?]Iktxp$VŖdDADDDDDJz:LݬAhMorRH-"Ƞh;s9;?9,I26iӦVnj$N8joI u<8NP:|]"1n}*_њ1a̴0\"^Ln ީ 4Cnj37ʱē;'2pҬy]+>qI<적T)_MdQ==0Xx~D 4QVǦᶨ颃dt?|pѕdFd1׆J/-Bezẋ:le6L[4tIQWd]_ !a,RwR{=:dJDC7ĕV9Ls3qS!Y LnwVT7U6]1oPgE6 ։miH Kt!TUEEMj[4m;%j=91(T:ϯϢk؆En D\MoF›9]HS#[Gu)-"gwdj{OC7̰k'%[~5NzΛ_ieȽ8^fբGa^;7|cp~ۑ~;lz;ֵtx8 $kjM Wz <<Ųs/u?;,-cѐ"\编q{'Z.: A];`CD@.׾34cRUÛ$wJ6GCf+έpTtAEW%֮;tc>#&DGr MŊj'J1 9!Ͳ7zjҊF=J[hѥA  Q/ ym& 1"dbfuFG 2$.3΁]3 Ӗ kl&#y*~t%0%pn=> wxOfOf7ߡ͈U^ܱ2amPFNTNU.UsmQh[MGu,!±%-/Sp!9Ζ:ThԤeequ$mW 39Ez~͛EmYZ,XQ- ŠFBjʗ"5)\m?,ꭩdi2 GTL̸1&vUifzGiJR )DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRDcΔQyy}-ƽbz 9gYV/ sٷClvW^1"_E]~zS펰Z F|NQ4ABḼ\e]ۘd5rUՆFQAB-)'"J{T>CB7d{ڳXuGU -y-T>Ҍnsr/14iʄ([򧠎+x8gbR;T>w}Վ549S5V}+CvOV&3W+]βV~אon ,<ڰǢ$ *]?ceθLc5ibG3V~imB.;9lD8HWMW4]Jl>2sMdm\QD6rpˮeW8 LֳdNy\g^ 9Z3{eʟKB~fU`|:ޠvE+q. 0**~wO?o[c3]S.M䪫&ꪫ]G|8p11Onc\ڎ 8v. L2%~~ljstFE˱aw Q] Y 9ʊ<0㋄L{MU3 6q"\$Ê [mqsdvΞOC?_:Mڔ9`0A}I;V˴u_F$=d$I0G%Xht׳(Ǽ^myk~,#UY/;X# \.Q!JM!I2:Q pMG҇诓ΞOC?_:@5|ntBph֥Ti Z.E d a$蓆 _Y2fjuaX'OYdZ\NoB$#Һܱz(QQpV[6uz3[guVYrrT۔IQh- IN4+u?ce!">(:UNi5xӰYL=uƵ! "I$Y齯i{M-׳@ j;ML {)W2fSWuV\[v!BMjBD&݄O\Ozu~I=~ۗN$CY] yq`PJx)uV<gYqBX#0Xiq^& !W2CU9TvM]Vg} 2^}R%37p\3"3q#3""%%U[>P+UӖ}!BgU˧Ejy/kp{ékt)y"]-Z^NLt tqTBHl6LdZ]jcL*h*W5Tpe`ZI"Uؑq"و8D7DVUS~OC?_:y=|}3MmRH3yAidat-zV@\G$#0C Z Wl|vUbW{e21 I+; Ȇh ˵s?jeZ+[f?s(rfNʢ"BQpMnr?ceν~M&4&P\<Ju i,L&9 /ʎ!mDxՌ~x֩:n1k]ۼ{!)V?,R'[H/shu9UTQ{W,GԬ0i\6.S GNB5 7]w*I?ceG()X>*T$_PPCis\]RGꅭ%]3=]2JROC?_:y=|O韥?C~:b'z2~N' ?j1J=|?cegi{OItz2Ӊ3o{ZROC?_:y=|Z^7=F)R'/<tL-/i֣?ΞOC?_:q?~MOaQT~O'/8?KK&u*O?ceΜO韥?~:b'z2~N' ?j1J=|?cegi{OItz2Ӊ3o{ZROC?_:y=|Z^7=F)R'/<tL-/i֣?ΞOC?_:q?~MOaQT~O'/8?KK&u*O?ceΜO韥?~:b'z2~N' ?j1J=|?cegi{OItz2Ӊ3o{ZROC?_:y=|Z^7=F)R'/<tL-/i֣?ΞOC?_:q?~MOaQT~O'/8?KK&u*O?ceΜO韥?~:b'z2~N' ?j1J=|?cegi{OItz2Ӊ3o{ZROC?_:y=|Z^7=F)R'/<tL-/i֣?ΞOC?_:q?~MOaQT~O'/8?KK&u*O?ceΜO韥?~:b'z2~N' ?j1J=|?cegi{OItz2Ӊ3o{ZROC?_:y=|Z^7=F)R'/<tL-/i֣?ΞOC?_:q?~MOaQT~O'/8?KK&u*O?ceΜO韥?~:_hCsV:bmv262 d)}VҢrN iV P]o?zFMɳ̳"WٍnadH&4fkzNf"<#sA#)8f9NٮW$KU#,?D:?_p|{3n ~gBjRrR4#@:1fhVAL'Zz#}#˦{Tl9ĕ6%HuW8uU{z8x2 8#ȩdn6xO|~~ڦ^Pn::}&-ߤH()%\ܧ;\I:=@:̒\MnqplVdq< R]uJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DX6os<_8pe%b.k)|dXmEiy%J[н9~ ƝUhT6mvfdVg{@1'[B!5TD"UuD񪻈,\((xdT܄G&-P2d%YLqDFOru7Q3Ghz]:pvI`yCL&FS 6@9R;BGI3wN[4W;p]r**s"[QܒdNGZU VHzVAwn9G#EQeNfdk36\PNvA|51e[6 8Pa!hfMa#vL1WެJW4] &/'rg XB̒NFbTab7Ѥyr1x8VC  w.lanq exтu&\& l-4c/Mbfw,1X:9ea1]vT v BQlTTQ?WO/(&jVf=rےv+ŒMLk >ܑGEkE̵MZӰHlOIn`avu+s>p.smJslp vxuyc,UƜ1Miپ*=sqps,ٞ6}w(m~(MJ;dюy1ɼ#lt{A_'-:AWHR::A[# M],AW[M>8تʛj|9,}SO)P:TxnO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nO)P:S}nWrpkˠw#(\-#ڧllݗse:CU'cG_tKm;~Auزa#HmwvۈB*fy/  R~ű;Guy U,x#1o"Fiϓ-"e;UFC`$dH6\A{,r蒩BH6j%.-ø0r{͹͕=_ØWGN`=eMtW(̪߰k6ߏv#VJGn9 m9⑛j6I]l"^?"zLvKquܖ^r5FK䇌h*kٗif͛`vH<"c: $Ymt}̃ȼ*sohmvQ-ii0p0s@B*g*2LA2!z^#svpawk:8NNl6{^$QJ"KNLEjQ0.dNEZVk-ӵ: ~"`AU_fr9Q2#tZQmH#k v%k-p tybsl?yvys RGwqlBr.O6cA>s[RnA zV;J=hzq o(2yi=F %,H\&&pc;&PIE/K}Sjͭdv3k!D_c?g/" gK1TU^.eETAdQ1gKqkykI&b0%^_ $'TyiH_ୂZw+͉/Hڤ]-46Y1Z@q"")*KD`eBѐ5)pn\+*^ˍFڔuw7O'h!rzpZ۞Mv]#{Y%FD+\;'(2 b CG{g-!@ͭa0D$eM,4G3ت{V 2iNm %D, p5BQەzw]R鞯baz!;e%ڝLu'V%gvoa.bU*l5Tz?#(CGtl-dZY*6Ddcj$uz/ff.b3pX[R2̶DJ*dDy Z:w{q_9~*=XD&[\8qIPҡl]QJ7v@"9 9c"N8cm|֏뽜N8Bmd2閻DؒLh=ks*MAEBxTUySyRGZRa{k@)7I8_uJi iRGZRUҟ.w5BWHkN>Ҕ*OjpRGZwTv֦VJcSP>Ӻ{48zS&jTv֝+ݤ|5)Uҟ7sT/{^#M)N"Ƨ }+ݤ|5uJi jiJq`58M ^#;WHkSJS?n_uJi iRGZREX=)Nw5BWHkN>Ҕ*OjpRGZwTv֦VJcSP>Ӻ{48zS&jTv֝+ݤ|5)Uҟ7sT/{^#M)N"Ƨ }+ݤ|5uJi jiJq`58M ^#;WHkSJS?n_uJi iRGZREX=)Nw5BWHkN>Ҕ*OjpRGZwTv֦VJcSP>Ӻ{48zS&jTv֝+ݤ|5)Uҟ7sT/{^#M)N"Ƨ }+ݤ|5uJi jiJq`58M ^#;WHkSJS?n_uJi iRGZREX=)Nw5BWHkN>Ҕ*OjpRGZwTv֦VJcSP>Ӻ{48zS&jTv֝+ݤ|5)Uҟ7sT/{^#M)N"Ƨ }+ݤ|5uJi jiJq`58M ^#;WHkSJS?n_uJi iRGZREX=)Nw5BWHkN>Ҕ*OjpRGZwTv֦VJcSP>Ӻ{48zS&jTv֝+ݤ|5)Uҟ7sT/{^#M)N"Ƨ }+ݤ|5uJi jiJq`58M ^#;WHkSJS?n_uJi iRGZREX=)Nw5BWHkN>Ҕ*Ojp_B^ky 0d'G?rѩ-63ʏ!*')%\U4N,[F%6' ղ S~ ;e-KcA$I yIϦI= ]p+l˨PɋxY߷/a)rQL"ljǔ݈w7|HK}ylX!`!!;Tit`[*D&q4^kCԫ~Iڮ:ioǦ HܛNȠ1m5ږff34v.]0O5FXG)9# r 1&cZKK8òCg wZ n0i#̶NJƥ)QRJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJREfy/W\8uŸ5|m[)KrD<̀ | DNd]j .ᣃDʰS(ȯv&49Z\jη>@Oȸf" .#FSC{'ic gvĕ1Ϲ\wrEY7${ 2S7ƑEK;NH1Y1"ۅ^@OCfin{aoخ8#@oȮVhn(_(2YQ̀HِB,8yr|ɥ6#:ˮGn2 d* " ' ɶ־I6a*\4 cZ/F{Q ŠpcuMaQ\5Q߱wj>a ;,&Bܝ,"vCiԐN"&V]N$^ 'F#= $ JW=o9f hwDk R7 9ť OqӯlD5= lOp }KcI' .bɕ3vqtVgz R~3G}sjL09.yhW:o^tP݃I0 `8 .$w@N-i8Yag^EK*lryyYrDdUWKuE_ NS\+1tc1v^Alw s2bw܋5Qkq.@q 6t 5&u 6NR6AjM0W!5m5peSdȓHF maܻIV#Sn+>FӂjYaBjLYB~ҚEg=QGjSogGm;^恫$ jWe60u#'+<_8/ WjI6HѺڸފ"!"~YM 4f@$N9T9,|S4^k!v@OH>ՠmZa~՝}(H4LJVG(GnLs:pLTo\ 6zL+Y^ :UJUVCǎ̸5NvkM!fk1$2z%9ScZmrײTjlN v ү:W9Fj%R-\of\2,8$;2LVQy ewEG~3=GʳLvg2 KbH/c}.EFzGs쐳څgƘ-.0gQ)1R0Ϲ g!nOFR^6###&kHi8`6P${ q$BZ =I11ROMtdzHrfn!i{i$&mM>fzoEcmV?"FNzG3Nx^U6#8dNt1 in|W[3l mtvHF7ȘzpL :-Pf+)\mc Vf,6Ya[ڏ.W r]Cx@TTG6O ,4qj+:^nl4Eͫ0E(N)Pmgk'I-}7F c^RGŵ-:m*1Mj+ҳ ^|9qGu(pV?[juj2rӥClrLE{W#[',Ҍ+5IVSs/^kKD84$FюQ;MiqA;r#hշ"@\/Zæd ^-Ϲa2ܗNx늦b_"UUyXsK\Zu*8%)JR%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R-$jݙK= i8saL`_1ƜlDTTIQSjjւ`3xk>6=ŠTa.p-w}7_.ʟ3&ced >}A;%D mIUD^m\k],::huAǹ]%>谖Kɘ}1G$tǬׄcaH2!X#/k>u] ')O}X[Y25RшmBB*!*"Wb{=eνcZȆ۲tV$Rk=T+]t .^fKg@X%ݱ;Rcrü,hh^AvhM?GTߞls8`[eakθe ݰVdL!7ꚪHU|ɼGOlMb$HA:p[Oh'ܵo`p, _sB0w4sc1B́9FsI<_ko}^+Tmq,hCLOL\;!]W_cDqwM*6+|=`:@W|?+O[E4)H /•[lZ00 DP!A=+mx>;em#!Am>DS""%iODsǷf؎/X|1peyTz )s"o~̧Fq{]e+# 3i!$ISqQ/!_ԽYbɆZ S#KY4^كaK4iT6BD|:"¿;VA}@nq,1 i>[M#P0HGRb3v-\S;k1`1ĹDhT9UWuMP4 ՜bdʰK&HN <ذA@UTQEMU>^lZLc.qO˵?-2BP54Hjh rI8c&ЋCj$woY~q' mrUhZpYwZljז$Ou< 4kqd/**nH^H Ȝ')qDD?UBpwar0<-tY#\-C)" JRU暧I>/ho$a11ˌ 9$GW$2'?n6#PM;S%2~k"u׼"7-ؖ$ (":"([}5R}ƑsK0`2 h1H BcIpջ'"LNh &鵟*f{6S%]jG#FS 9Ӊ՝,녏`UEm]otߐeMk2 $xئM4./6"l\硺.VUg#}jL Ky?IH0 8}yc([[h|6ȊFZ AHE:ϡLd vqVc=Jӽ ݰ+Z\[qqcf*1R^RTGeO /vފH^e^Gg jbï6BMiDMC.r@m9Gx.^.W1'γĵHhE[ž ,2mA}؇eޚ~;sɝ@K~Uk]'w+ؙA1t;LENL(c 0h4t`1]I5SiVk1gO5ё8=(mlP@6DDDHYFqrg4鍿R;WlY^]eud(#mCF:QF-=ۘ 6yM۳Ds͊IHڋ,U{G:EM-$ iպ]>ݮN72mV#N(۠KG}mô-'ĮE\D :D.e:ԛAd8tI4&k>y]xeQp`(b!CQl 6`l;D}$i'2qƐк̆H IQQQQQvN̵[by rKEiwZp!lieun]S4@fpi'x(nS45h?\iҀM `$/]k.۬9VCd@'k+qA:՗@_'3Fd7i 16XQ$m&_/|ki[pSn$|fۍˎܒMͶ"76e'WdDU*70/ƙr"&afܺ&4Bo7@%P#4!1E_VqXc+XrS6v$7-  !%ppǑloVc,j#2ZkF&&6k=קfc@_5+L0_V >6A!Gf<=>vŤ@vҌZv5ͼgE$gWJ?TDPv-Ӹpg`\ imF!pEEeLKۺ(ԫ֮_)CpJLΖ=\6ID'uDRTDDDJ٩qC`t$l- `DlGZ{nE:E~bj~[;l{ ;ȕ>KqxSs?r )[$;rrL$鷳NAؓdڅ'V<̃U"AoN8 >vV Z"=RR|?)@qC'f"ڱܿo]!36-qj݆pku>ɏ"r;:W=fouьA.luF"bU)`IFA"=`!_A궡 s-?Lcdk*d,GAuD!U*_ts0w~6^ow9~D],j/oԽ??Xb9=˄KPńqMd2&H<""*-UzQZ:w%f( v)x҅%CmCd-4苤89@%en@ ' \=`RFC!GG4!=+p[[g&s%lZ&SȑQ%_k?A06m88^VlȻYabVwmP7LWQ672/(I4'Lo:+;uڔɈ#o4ͼ{'(<'6] >r]ȓO Ʒ#m0^p+m$f^ FDUOT roc32;'I&$ߺ cy$ FjxPKiv‰\~f=Z؈}V@PWtADMJj?>شHzotxHP٤I=ECΰ&:+kbiXMv3pnek\֜A$BD !]SEID5U4Ln̓g͜{GK$I1KjF`ħ9I]m-vx;h$9v$tsC{Cl XzҨ>Wy=O0{JѶava"p{t0SE wvM̾$P}$^jX1L̦zYSPs[A [^vmi1Xa+(kݡ\6UBqR} k0H\^TUAvgs].EvȀ`p NMqccӲCr,6ӥ-~tni/9n+hYg+[%odr9yQnm ln?jo)YÙWk$31^ͱ0۳bNece@5M͢X1#03 f|H Y8w:GjK:lE AH2KB8[rh[*Aq!О&v_Iuˣ &;mh0Է)/6}OI/RU俢j&[H Xr!,[LeQINdaƚ6H^+.? O5/ 8m8W&ië![)v8cDiU$ACM$ r]3'Zjl:v׈=BW ;#ٱX]af6HtNos?P=Mӌɠ\Cӑ}-w=rz:IgM' qU#T"/&}xu `9hً8jZpsrbˣ)\a/yeR~,/s)1%#f8ouXH t]h.c a+[솩6?s{S,fkW{~0Vd(нf;ahd*POiŽFͲ-5o٤5DtcNIqt[=$O,*B-q'E>5ROzʬ:C^^=Rc5>XFg0;G/j 9A+HAZ">舉m0NU c/Vr[b.]8/dJJ8e eՇuv]cdOOίf{":;uȜsk!{݌/]k+B:&iևx"~i33nH n@h 85GDuLǪqV&zg"}q $ ˦~g [m m4 6"(I&J 0 JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(_6nI0tb5^x|w_[7޹gbymmJ2e JRmrb J` y:HQo&$;n mGCո&h#L='^W)-Jj#lwL}$#Wc;ikZ812ؠm" """"Ve)Ys2V ┥aeR *pַݡŔ˵` +V y$NUPte]KbKM̒*-Ek8vw&9k9cܜay ʤm܈l0sJiDAJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DX6oB/ n_oxFH%]#mLjp[ ERify/ Xs, t$4jaL\A;Ϝqr\== T1c2`X:Ŏìt|e\rKqQG%>Xx!BBVn2eÖؼ8H&$* \;njF#ځtu ߰F8rJ& ]-[[SV$8@@IZZ{#.30Φi=+ UbJPVZE𩵢8e0!E.(Lm̸DO'\)QRJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJREVkާѼ]OZlxU%po6eKHUM{5AβK[ 8q7pqZ g=@Lr놌 nw]nV{kS2;?kz)kXNMEŲJ8.^/zKL o39o;):܇ٞ"«@ l^Y5i0>6(fpq>Ln&bkՖo]o@o:[wg.@Fe:aʯ8i\{bSFg7}\6E'b N7"MQe$'|WdrNZetŧ 䗦3ڍ|dxt[TWMU_q*pܛ'1N\fƳ<s-2:`:n jlE^TM+mmmxCZa-A;MS䖴N7ug?).>7ΪmFۅkooyMt;tL_&Yb ]v8"\E|l[NLՉrvKJ'6]qs"*!k-=ij>n.$ 0tbf|嫥v6pv`N8t" Nb\EX3fV{Ф37&L%$u5 ؽD|>pQ+76̙5fIG"8M6̽Sžk&mlvVhwrgGu-]lE\1CEџpMŒ{Z.A2tfNE)L݌ٹ$mU6W{HiFl C {~ڝ 0--G6WIZE趘$CMAĐKLBMI7w_k乳fNGbn*""D\t˯:(g\XԎsrvKۛ}>q/-YFY"kq"^9MIQ&ĕs'Ly1^ۥj}PRrJT7wCFaq]EԺ`H9sD=Ůjۥb4[pw"`Ɵy MFhctvTymVy P`Ȃ+2H5sHk"qyu[PU.<_G.{o g&rʡ1o,MJ\eTRbڃ/KYt3~?_;r+) `"PՖM7S: MM]lwFѦB%/<t L`Dmnr%w go,u͏mԹ9R:=n^[waH>gxӻfc2<Ñ9+Bd)ʊ٢Uv黹L+Ë3 _.~p'80ݩq[Vv^;28ޭbf ۜw\mF`Af(qb !E'<akM]5m6JAHSx4 kX7Q•ؚqvF"F=&v.$qܧQn}>r}[-0&6xzcZ3O-+>zdnyE UV46Dv᫃LAnn=u3 T"Hm&TB܀E~E*Vm+n#j.lYO$_v yU"bq ^\6ãNJSJyFHa6)JwKOLVfDLINxNɂq''5SsB"kɣ̂ģVc͸. */P<=$e/t3Kvb YyFmj(9кl=Gb3-r9[sxYu螌 w#QH ,Ĝ-R-%]=n1A-$`sMf_E{ ;̋1`j914њ5Ů+-ͲsIiNCSjTƼe7p6;kiq !tLڒ2bۄ.H**?2zrŇO,v<̂2`q#ҞS I Q[3q At /B!l9&Zl|+T!t^м-NBaTEKD5Tذ}ڴf8Px Cwkip$@$0Ed;ҢJl^ae+BH***x*-WVn1q7#KRߝD3g~d~l * Nj'!%Ne7"AE]UvM+\,(OknBEbsvb|w⿪cF,VߒY9yt5%ځ_,EfnJbzj[HmVRHgHrI`IFkEu1#$mI2a2#ܒ pU7BEEQS+%r,ZpӤ|lW#=1-$EZxTmPLæk_Jim1dȷT{]tššNGB潢`Q"KJFY>p:=f̋21%y}u LRrC􉖘pwIQngspm9s-7OFĵ8{';.ְG Ѡ}ǑbFM6ߝ~i' m7kK+^IKHvR1]\ Ps/17/l~ܼmF+8ˮ2`؁yuSQcdKHÓbO*H7I@Ÿ'G)}՗f6znf Փg.@A2=yG}4#^#!]TTD$mSwH yhv3s`{>2rruɒRL礠=4/r nɾɮCo\D#cwK_,qkmŸ7X]"qͽ.&曊:FW{<$[d4k*: n'X$ Ҿ!Z鈷a9ŧ1+廄30]QLHWS}Ҥ~R\}o/rg:Y88g3Vh,Q9.#<LLG}s6ȹ*t>+"/w[Z92|++ tEh4jچqh+֗ ]u" mـ-gT` euNpvR45qE#,9#0%bJi O"'M^okkqy~֋wno#vz^E,vo6*8^oU#:yb|IrL[Öø&[V!JlcIƶP_Eo12*n+^R[-֓5\yWE<{&MdrbH8 5f'j% f0&_۹U{CdHB* ~D#Wpy']ek[DV/+)/8}Fۛ"8ӍiUzgp=Ȭ#xfnXV̎~&Ar mGuRuon*G V2XG1ї l+sHQ7H]puVmWeU[ 6ʥquLD4o_t˙r9Ҧ^Q:,rq%͋ ՈJv`d[)*,Ɖ7t @SUQkg%ruNxӭ,Y-6cNN.? M!t_DTJWhNhq20dlYM`.hس|ߎ_:yIquJ>WVn4fIqt~9| >WMƟ4v,).>7ΞR\}o/aRgQ)ś%rK*SL]_?7|س|ߎ_:yIquJ~tiKGO;oO).>7ΰO΍3uiGb~9|%r)Ѧ}.⛍>hYR\}o/<ߎ_:¥?:4ϥSq7K󧔗XTFn4fIqt~9| >WMƟ4v,).>7ΞR\}o/aRgQ)ś%rK*SL]_?7|س|ߎ_:yIquJ~tiKGO;oO).>7ΰO΍3uiGb~9|%r)Ѧ}.⛍>hYR\}o/<ߎ_:¥?:4ϥSq7K󧔗XTFn4fIqt~9| >WMƟ4v,).>7ΞR\}o/aRgQ)ś%rK*SL]_?7|س|ߎ_:yIquJ~tiKGO;oO).>7ΰO΍3uiGb~9|%r)Ѧ}.⛍>hYR\}o/<ߎ_:¥?:4ϥSq7K󧔗XTFn4fIqt~9| >WMƟ4v+j_~'o"%8`7cdmv7FHlM i[f3mm9 CǞYzW$B 48C&T|1j5}MbҶYyެdIrK({iܼͰ:H*pe&Z-HLGʜr:jٺ7PknAr8X8u7l1N=cNP&¥cOzNQ"|:?7gs~²)XޣDӾ"{:pΏv{MM ȥcOzNQ"|:?777+"=?O;'G g߰V?|D>t'Μ3|Ss~²)XޣDӾ"{:pΏv{MM ȥcOzNQ"|:?777+"=?O;'G g߰V?|D>t'Μ3|Ss~²)XޣDӾ"{:pΏv{MM ȥcOzNQ"|:?777+"=?O;'G g߰V?|D>t'Μ3|Ss~²)XޣDӾ"{:pΏv{MM ȥcOzNQ"|:?777+"=?O;'G g߰V?|D>t'Μ3|Ss~²)XޣDӾ"{:pΏv{MM ȥcOzNQ"|:?777+"=?O;'G g߰V?|D>t'Μ3|Ss~²)XޣDӾ"{:pΏv{MM ȥcOzNQ"|:?777+"=?O;'G g߰V?|D>t'Μ3|Ss~²)XޣDӾ"{:pΏv{MM ȥcOzNQ"|:?777+"=?O;'G g߰V?|D>t'Μ3|Ss~²)XޣDӾ"{:pΏv{MM ȥcOzNQ"|:?777+"=?O;'G g߰V?|D>t'Μ3|Ss~²)XޣDӾ"{:pΏv{MM ȥcOzNQ"|:?777+"=?O;'G g߰V?|D>t'Μ3|Ss~²)XޣDӾ"{:pΏv{MM ȥcOzNQ"|:?777+"=?O;'G g߰V?|D>t'Μ3|Ss~²)XޣDӾ"{:pΏv{MM ȥcOzNQ"|:?777+"=?O;'G g߰V?|D>t'Μ3|Ss~²)XޣDӾ"{:pΏv{MM ȥcOzNQ"|:?777+"=?O;'G g߰V?|D>t'Μ3|Ss~²)XޣDӾ"{:pΏv{MM xA/YY|nMiw1k[cw~g򠀙x[mU7\p{k֮hnA ~#g+^`# }.d5vEr =2=0ͲLv!Hi,&M  "*xUo' LGnپiGw1񶬋nL$DW==$M*V򶩮P}2LO ׯ#߳β0S0ysvzۑߤ+,0c*îVFFIO?n]rN:9>蘜ɢL6D"![`.eY.Û$K"Kјnir 9'K2j6kj`Cj쥧ySQ [UmE!I]DbHʰ[ QbƳ[n Ͳۑ81EWšD6I9M~dI@87di<  cCHcF=nҔqUJRzϬv –vntzS0!B;.-FَȪdD"*D"x.9k۔esň x_նꈲmo+Fmٮ\!Y\N5.-CfCDBC(*E2kr ̣*M#lm\ ,/2016@ZΊH[qg,۔ }i7w6舻^7v.j7G'҅iJv2q~nqn*K"DhH"-FU'?gYɨ]φʸ(]d0Qo([pܐu'}czk,G+α[/m5$eI.QKr;*;8(s +}D75]lAnu%xxӾPRdyȌ9- #bVލtjV/1:33BҲGq}@9,ɗps]zoS+[$?1'^TDE2A%E7_DW~6]ossfj^'hy?5rktzkB)J@/]F˜YϖroKtQQLjEw%lRWwy΀ܰr1p36Qcu Ӂǝ 2ӝ|jn\Gl#/&1ePH[&I'lߥ|ɮvv)B-x֨Tj^\1 {W0]a.ηFl(I'e+MQ #RX5+(eڕ+T}{l*{az^ u@Vm[s81$8D+X İO,&&822ɴXsv̔~vwR܃ijC-":b*.?:c?e,KƵǓsnX:2&d\ꪯgaET$U5-nM.O" u8s;wWc8<8NSxDCӴOm٥Kvv1a*[j4xMtE^6K~V]in6*h.Q:"k}s dȼn9VZ-AbF/1frj=dqgo(!z,"kb$>87vj;7ifr[g}i3h1"7^T6iWHluغ`͓t5TX[UE&`n"Knf3ZBfC.3 >MUĖQqa4*g{_Eq^ȓiΘh*"8 &* eAF|`_l"Vِ)K>~ʽй`w4OB6PryL qRbpv쉚)yAXҮT`,ۮ-4FQIm`ue*6 |P[2`Uq 0B(xMn2 CkʀN#|/B^زnnY^.<뀲$j̊m&;-э]́{.GKA+,OXHT/aȲq?gǓ(o[mr*ٻ˧3)7qX @8X7Yd3i)x?">T~+l'Mp]tU$5#p#KfMEif#8N`Y@FE6ɢ1&6ɲTT !UumB/jg,۟/s)!^2BFMBsuI!d'- uv.!$w$i!7v-ḿ-0$aOBfAw&!o2&Hpr1qS%VqT=\u8l\=k7Lӗ!fevZ& FSuFՁU&8F<;QR51_cdiq'dM G7%5%ETGZuA4n "-ͩR,3"m#ʊ \@i"ؑ!TJײгӶ2M2A%%IPH3qHLWAUGw Sy&G{56 ;Q쑟2}$Njk"< tT8Ls Gv"4mn;-bJ !l"BX:IfYT6%v~b̶ȓ3R[PӜ$L!RmQZ3llt썩w33KF_x^}̌r1 ዎˆE by&O +Cqr=y]&a#$M0&O7?,<f9?q)i b:*)-M6_'Sus5IìŁ'E64os-60G&smC1aʷ"t"^tygާJmSt遈cFiA*G>vCMG`˗L̃ aV1a *dXm|Qs[u%3P2 q扵~:r`׮ "I:/}q+veg33nX !dЉOF+K!ij^[ewXTLiş27FL;lEY$|wUE\7fE>癦dYf)uZ̓:;s92DftәGQaز*NkwM^&Ⱦd\Z@ <:#S,/N78F:Op%_UJW1oaMTEDxfaf{rm}JRJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DJRD)DU%C|ɔfm+qjj&7rFlqZBhՈo:M6(PqkľQiI`Rsɷ%8bhl]FHbqc Hف~zTtݮ:zQa--W8VoC`"MP}Q|jxhF6 pyE2CB}yUf*.ۢ*~[uGiXQKkt]#ӯOzu/s]P}Sp_ Va,Nk}2/3AHgns(4.ns]\dVff^geP/-2G}Ne PZ-URcni^1wg&HiWQɏr\]&ɾȉYY vh.W+}s(>ɰk2%˲rǧv- V&ݭ-k 22#:"pJjl)m1n˖ .T^c*D߂ꪪ[xFgv5LpKgd ҲG{ִ6 18_Y|a8\!#oӎж=wvDDNc%"2"UU_U_ ֽFY@s܂y\1Vv4Yaҹ U2ߢFky /GK:4XM2E%eJ}/!(< ""%S` j={CL`2dD-cfH:$ `Atω vŭa`n=IJ uNgZ颼$T[3\;lO׹xn rLm4eR#5NTAEUUDDU*0u/QsV9F lޤwT6c2,G3VUEvu>̟ /y`5K=9 2w=?p$KtCmWu >&*]l.Ƶ#q{'7plx4;2_MDd]. pp*wype6+1e`Ʈ 2$$8bH/(O[k+6tuP@짐19ݩnvT 0ځ30<Xgsx6d-؎5վ`˃nj- $u}er7'Ԛ6o(,y m@Fcq Vgu p3 p:!m& ҎnUl5l E$BQE_Qo_ qabvp޻䍝w(1Ty’4Q[{Z"]w,*նACHXi͖se4Q-IUyWmó̒= jF{{+I_Ųߦngcq@lMq"VCMuy}/%mmEB9O^ F1hxk\\@׶4=VsEun83øZ)].HPJplߙ%͓#bN  (´-}9m77XX2oSfyЌ l*Y&-&\>E]Nh饞lupIm! ^ "dZt'ՖE- Azݐ\΀0A+2xhRLB0xԅvuZD A֭kЪڂnM;PAi_ӭjR=PAKl&A:uMZ/=V,VU tZ37P]Ҝ/7*C'!BiG["avu4#e%{n u@U'DD NU4`R7ĸðh;,'ͻ[r)曛3J0p^|~#ܪ=Si ;5bFvlIѠ'TZnPmAO)巑v MgDWڡg0=ENHhi>b5*#pճ8EMecz3?r՘m )s{jj_Mw4i/ʞCK cd|X,`׮x Śt[事$hģ&N#-pae>@fF& &Hem|^m@!BBDZukⓎe=VmmNAek4Wq S٠ӯ2 ZM'B{]90$"vبm]mqjv"sGUku-ov]#uX)JQ= 8^b86Dyo݂]"e]} c"G2]R> aS4'q] !cƭi6p`Eb5yED-SQO+4; Y٫!V᷹NGnO84$!ne6ml@8asA43L!_KHPn98buF@u/+q_e86 2UɐNm=9ҐC~Z}v%"8W"ez Ħ\Kp^Hx2S. J8; QIpWuU_\ cZp ә%Zax>rCaµ$fۂ  kXNt*M{W@,8#Ǭ#ˌn5w۵Ɂ(q$Fn(#2T@'^Ɩeq uY&x~tn{]UI6݊kiƕKˆs2B(×si/ $^1hF܊鐱)`A{He"(|>KN9qF{-/YG"^示HBm*׵S[+9t}I]C0^pg1v`j[qlm/@$NI ObMgy5#ɼvY%HP75w7w0AC!~$̲ːcL̖gX9s6dpe\5VITMvMk\k~?6=r۱7[A&VP @]ͳirBXo\ fgfl֭aJDЪj%}iOFd^fEv"tMҾCKɻY1c`K=cZZVi~?_<#%TxnVUE.讗:x5TqDE ֛#3izUOnʶ+uXpIpKS|tc~[qso/ڏEoO7x5*3?m<EoO7x5*3?m<EoO7x5*3?m<EoO7x5*3?m<EoO7x5*3?m<EoO7x5*3?m<EoO7x5*ku-KnE'424$n **Vw_'|ycLԨϜ_g~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86*MJO87ig~86+P4]Ci;(X3erllK6"'$H$*/T6oM2\p7~HV|ܦl!iN jÊ2s'VW:,0,8[`Pb`B(DJ)ꪈ篕=0,[Uk(^{*Rx-.wCF`LsNx ϱg`bcI(3'>gJ5<3^e\Q17?>+]GI#DnlxҦ }$iΡ8ӝWdg\?rKi[7l9ӣmGKA"%SRN^'&ߪZ>i T|6:L!ɡZ>‘ :D BC̉⩾>ޡxt 1eFt]fKF(@ "***Wm:E΍7ppY &[,4ɕi"#Sqcp$T+-)DT:7I9W++SeD VTQtMV SWt7p: lJθ^֙Y̵\# "t6pТ kHСGsD=2vaFXzIUJm[tʛDa<ÉuE45S1fn~e af1݃ Qqmk!H5ODgU6[.[d{l:-387InuZ[䃎1Hfi%CTC[فɃwTՄi6mX28ET3gjɵCWx\NߟG'X4h装G+)Q]U/xpƱnN̠:2Z¢,uƻ2U ZbܭnhCj@b*6h$̂oT)`44nd-9Nq[t9qcTk .9P'Fp$!y6>wyZza ESQh?UDmD*|gQyشVi`Cȭy8اӥv _& H=SpyNVh})d2m6qTL] $9'ֻz@ Xuάyo]]ntnU\K2RJqM{;m "-o6JRNM:pcÜMf̺cvFkHbXXX \ *6Em ?x +>ރco`kpg$Ly׌I1m8e93 swO_6x Em3rAn3 &id- &aWei/;qۓ-ED5TMu%ܗK<=[3&/5c`RpÈYR7edtE^SSį lj_뵋 x8Q]O:f!Uw |-i\UfXӇٙY` "ƴ-[n34[:ؐ@~Zf2~pSF2N4s6e"nYSlb="rtb, LhH]T𛕿7nk-VK۲m | DڛQƥq9'kpYK=Zε`۠nG%Eɶ(((rU$xkf^^xfV '4r 6EIEU %[M2/LܞSZTiӺ 'u#5O;K#0te6Vqed؉^GÛ8ձ7ez S4Ԗ}+7J1ZdHc0V^m2pjmaw\Ers^O{WGs2n#'@^5Smf]9yڲA+L3Վ 6^1 =ء\Ncٚ )0rnuy ^tuK5bW;R{% ll8}RHמe7Yi.&ZyIKM$.uMxēMMvUh܅놏f6TطfVNss(ʨ<չ }jV`ecCĎ_(0.rL5emǓ9tFcW̵Ax.ʵk,L.,!B M9pqb~Noe \*xkƎgY5Q-9şJ2}z'Ǵ[t"<hHBd=3p´׃)1|h۞:7[ը,`Gveu'tUz^GFxuF6# oo6 'Z8ݟX,:Ԓlvp^R\6Vܴ$mYa;Eb+O\nۂ lˁ4wiACM Q6.uӌOoOL~b̾Uf`E(/Kw%ۙN+%[ɺ61b. ^yq$X"DjQ*LO-/.tdE%ː4oЌ:]QqMKUW](2uSKHۢ`xz]I+\p(\$OIc6{>S(߼!ű.&@Y rD[gGpiGIXm+ls]+{>m:F-ki `2i]~)] H.N:+P!߱l`w \kЉŌ3aIJE;sĹ pR+#96?: .܌6"bkW;-mլ.sKA]$`\$bq1 RѺH/Fs/sCH0?L7fӮ!$oq FP kBf8q)OBENnR>a˵{_ȵ_Mj\qpsK~Q& d1%[ 6 ܝRp@C4mb%=o푭Q\BO8 @J""}UӖ̯FfkoK#ց# # 'cV7^nrNN )^Mt)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ;:<OgYٹMů I/zxd:= 1*97%Q5GQ:GQuy ھZ_FYqp37^4wcm2 VCzvkz\ɒ#e7\pEQUWjL6!BLD~{ϊ"3t^s1DQI>-4gJڔ@c2 l\;X=aNAA51qx+su^BۮIViw0^ uX!JPH[%ZXFÏa; 3 2cDF"$dOJko2aU&DLF,"z;o0J$[Xk4rcB4HM"x*****}hWJ);-jJH/~P%(!' *oꕇ& ;~ۊ/E$L^u@%UvmҪnn@ $L%nU%yv2yXbgg 3 ;3Ki-^'C2452D%E][AtGr5fkM->ΒfH-:7 x:9uPy ;YeFnaI$Aqk%AQ2zþE:7)09l)ۙ˻.2u+mF+m,▇,pÜ_jϔe,,q! j[?FqEi; +?UXj 㨜%%$A Ŵw'׌ອ9p:]qo7 USݹgX$YOIxWڶ.!ϙښ1&q\m2rR%\ANxg[&(cyE,̝mɝ,uyO67>W_@WGJdݵ=1Vnz}PKsvA5+^1hqiȷw~S舟1!"\}Iṅ^;G|;,.g9ǕD_GopZ tmMIF;@ ӆ\g awv\np>PBgGKcn`m@{xMHo1w[[c_jYd(&aSx.Wk%> \*uiO|L[ry8iChZD.zXݮ3ܼ|Dsmp?4RLłwFmy~X.LVx:OJ3.&.By/,C4]$F6۫^Te]MI=Jj6qċZ^h?ʻUyz%\.>V@'']Su]Q+lfNp;c9JOw(;z= 8ʬ2!kuܰ/;EC򮽇LYh4T%&pfptn+_dzu<͜jiZoFu[㖋UfM4& `Dj7[RuD9QI}nmcE9؄˘,7Ba9[~3 O~ܰ/lSLpsmTp.#/I lӭl5Z5<H$$gT{Ws$^1p ̕q2h&\GY$-"$Hy¥Jx˲v.Ǒ5lz}Bxې2̅ٸD f*wrH~TX~ʵfAӂ؇ uXMpkL4`dgUet >F`ɼ73 F39.x)섩㲭~kh7ڥF[m:}|dʳdl2S>X6OK}ScCVD}X~ʝ"!U7LTeM_-&|H#Yǩv]KM v:cVm<" e8앛\q̖JY$C"$N()'n;ÜI#2s$;84Gmp/vY, )pE_55X~ʝ"!T"~P,.1\_ +ۍD55qO孋K4VoSy[(n;&zQ Q@#r%ȃ1mcJ-zd^7 ) "dFk*Օs.f#ʬq݉nja˄]j/"H>٤4˲)&zm u2AM<|ky{$KKZ^9-.yT[`u̒zc"\R3]obU{q.rpfB:7u+`i9Ar6 r+y;kkk|2oK\wOk}Ïlv[Dp QdiDADDM+aܰ/s~ORm]hp@I1"8`$Df3#?Bx7#q%߲ c ƢOkp͛[,8 ٹ)n!6ԥd݆lTpu`~iܾ\16{eyVLh y rhm(({ [w,?tZHMUF1dѾest^WpH wD]7DO?RZm CMWs9yΆUT&STv23I׀_[(ȼdǢJDtr8,B|lfL9Ҙwt4Mƥp79-]41/3tȸNmnܑ]T-%Xy`)ctu\ %?*{,n* ^fJ9(*Ӎ`6**"׹a_?*wKm=x 6)siZ-L1dN]<`L]?ID8dcݛY[nٕ .9D]n> (\2ws-9Wp?D^\ʼq] "6"trH~TX~ʸMӬHQSmGpa Np Xn1W*f3eE`n,(񍾾@=SlHCyh}%M!#ܖOJECrH~UUNZv}7`A1 fҔd4ϽH[|6ۀg^It[tefz;p)IM7OHnmҋ5zr[[6oBl'mП,V؎**YywEQWECrH~UjCi7tqq2K@qXFQr `Y&Ls?;lOVín5\K3>+bY":Vv79m-M*!b86ˊ pxm`ͯF5rOK &EtmF4mYeVբ`LECrH~Uߑ_(Zw)]4t\n2Bp1bf0\՗ɝDyy{7|LľN\ܩbUܰ/;ECsҕry$IW7KShܫUܰ/;EC>mK).RsJiVrH~TX~ʟ6%' 3U{JECrH~T/L8aҫUܰ/;ECͷIze?e ^Ҭ.~ܰ/>mK).Ng4aw,?tN~m^Orp9W a_?*w,?tOn~˓*X]"!Sa_?*|tS\0iU*X~ʝ"!Sۤ2sJiVrH~TX~ʟ6%' 3U{JECrH~T/L8aҫUܰ/;ECͷIze?e ^Ҭ.~ܰ/>mK).Ng4aw,?tN~m^Orp9W a_?*w,?tOn~˓*X]"!Sa_?*|tS\0iU*X~ʝ"!Sۤ2sJiVrH~TX~ʟ6%' 3U{JECrH~T/L8aҫUܰ/;ECͷIze?e ^Ҭ.~ܰ/>mK).Ng4aw,?tN~m^Orp9W a_?*w,?tOn~˓*X]"!Sa_?*|tS\0iU*X~ʝ"!Sۤ2sJiVrH~TX~ʟ6%' 3U{JECrH~T/L8aҫUܰ/;ECͷIze?e ^Ҭ.~ܰ/>mK).Ng4aw,?tN~m^Orp9W a_?*w,?tOn~˓*X]"!Sa_?*|tS\0iU*X~ʝ"!Sۤ2sJiVrH~TX~ʟ6%' 3W_W -E{^:r*FII1ndt ' :jʫ ~432ENLj u̫-*" *x#U3݅ۦ%gʮwlpb1SSus} W DW[?[B7Gnh qLi2bs`Se.נFR;Vn3n+80Y߳HZn=/E$VȄeWU:!psgW* fbFPQBk<|+rOi]$q;<Ñ۳;kDvÞÍĖ}aEWn-0\]H qr#w"L>b mEB^rDUEU?hdHis-IAd60!E.SO~W*>w_}~W+ukX ]Jd[z>m84/ 6Dn'IPpԽ8,C3tʣʝGug4#ٻ""vH$v.sޒՇ\p8y.31閙"Oz˦̺2nmnFu,GQ[#D3 ׻`4lEǠD}̍Q ttUVOB8.Lb0NonmuU+/JsH6 NǮ3[lJaIwإ8*!."k|k齧U\ ՂZc==uf 3:H'DC*A*DG2NBB=6ut`' Ժ֕ɸwwj6ˣ!r#Z.G߮; )n6jMyDifQhد"i[6@1iǔcd8):+ZWVֺ>E? :7A`TryuJS7Ϥ  _nzWw}DW j`g8R}Q!ABE,?E\,.1\P,6ؚ2L k\5I?r'lJCOre&i7QuW2KQ"" CxJvhkq|*6!lZ?)%FTOnC\#;͏8L)oe]{p]IJ8ɱ+o4+n4 hb$1cL=][v:ƞaTrK~8bv5o.w&E:tyNMEn!;C\QˎF" 7SSp~qbfomK @ffDT7TMIvAt]6or.$x.q1 H]J>KAahd\}ˉ+wJ0+}.^IӖ@ȴeuz+VR-)H8 v\nm Os$G+M7Ua 0H]-& ;Di 5q7N}w+x A ^ (mH#4>cTM%)(mp[EG,n2z!-muU%F_U! $UN-C]s"8Q"'uV\LgN U?JVp;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;pRSu p;lg-a9&;a|+We=ns z/7Τ$$uTr6 aK=%dpB~ה3r3CMwwD:GѸvoAfޜ=ròm<›"oe3%aQ7'H b$\'<n4J` c5e|C#cOcYInf]gP٪$W*_=g íڍk=p)x~JfMNC [K :_aoW  6%+q |f|UJOZxz4*뇸%qKV)K>SjpNh\篼<5-}בa'{:[n;u:<ۯ/6,K+..[WbW'EMV9$ˁ"2J4F )}JX&;%gUi`26*ݦ\\\X$'q*⊋Q#@닲7qD7+&軠IyOIm}RV?bNSUX=jGN<[k-2y $_[n<vSĐ`"ui7 +5 ԙ?̍2a&!Cou?N~mz;FRiZ(6[I,kCOS[xD K s9Z;G\渟N1l YitSS81v4v靨X3[툷:(6G d9oW tH.;ӱv  {jtcHtH{BeoZU.)@AF$IRgw\ue!)$ē<_\=oʬ{kˁD4b a""96V[؄YM˸ӊiX3Kf{e~rR(Mȍa@%ePYxT_4Pmu与Q9H-ln^bb"2F"6Zdfu*=sLr CKvğmPWMZWPPhʺ2FqLʺĻlĉ lS HhQ"D, :%6*ꟓSv !͊tkKCA3 E\ ?F0s>ih0$ă xW>q9n\.N^mܗ!d~niT'!jnc6,UyM9XSXkT{n2tkczA\d*!"TTnUp#1\aYjVDWFp$B/ "(Ъ'3ʞO\=g/Z/D}Oe9U~O\=g/<{ς_*)O^SsB{ς_*y=pUjR4=TU=pTz3> |ԥ>iz'{-N z3> |f|UJ|OZ=SWf|S뇸%RO8z4*뇸%qKV)K>SjpNhU_qKO'3ʭJS既}>Ъ'3ʞO\=g/Z/D}Oe9U~O\=g/<{ς_*)O^SsB{ς_*y=pUjR4=TU=pTz3> |ԥ>iz'{-N z3> |f|UJ|OZ=SWf|S뇸%RO8z4*뇸%qKV)K>SjpNhU_qKO'3ʭJS既}>Ъ'3ʞO\=g/Z/D}Oe9U~O\=g/<{ς_*)O^SsB{ς_*y=pUjR4=TU=pTz3> |ԥ>iz'{-N z3> |f|UJ|OZ=SWf|S뇸%RO8z4*뇸%qKV)K>SjpNhU_qKO'3ʭJS既}>Ъ'3ʞO\=g/Z/D}Oe9`ٿW{;\^cFyw`[\nHb[Ӝ{ B_׌z="Rv9[TW7؋&G8 cǞ23MWpkoD: ⸴Z<5;pO\k 11wK(JΏ$dE%m!2`("m6BƬƌ;|p;l/` \{qdteNmo(*uAqUPQ6Mz5f ܵ  ldz ٷܖ~H ]n)M>'oghp[d\-2S%5wj;x7  :m96POH+b.`?DOXa rBB3l5vY⦔* IJRM{oŻY_/˴Kܒ0M)mqB6򒈉* °Bk5ӻZ&*ylcM(* RWuZL30`0Á#0xjֶR0DI! 3' W+?c(ӾAzW$]gb";m`MxK`up7Y\A嚃: G5ӎ*sZ,7K^}TCwɔ.]\T1><-lcd#2.lv o7XB V=m:qǮ<ȈdF^$J⪫T}J8x"m[cɜlz9K(A($i@Bd/<n=l/ s {;ҩVbA=nk`LݨzuҹI5F]KNlx'99Q8sdBPnX +.);@KM]5ϊ@Ɲl6D O6 3m &ꂪTk?=-FФnN2011bRH~)yik+*`r0ᬆ@Qe=wm_:¦eZa/FܤnH u m[) קѾI !F[sэtqF㘅ny\ʁ-Y6:Cstpr]S7ު:M-9UPab²)v;Wq6ϡ a̒/qD^mhj@l0F2":g-s]n%bfF FeO; Uu9DKLj2&^pf@Q'].1jCXwIr$CGg7Ud)%]~eR\DuN.Wڍ{9]Ubkuhш}(W6Fs:8{t5W//G0Hv <(9 "GP %$-_v;1Cb5'StA?#,kR)J"궑߅cwKTj.HmӭӠH.6Bb*-Do`yV7h\n atuˬCym '#f My<kOL1]+"< $M7)(72CwZu+K7{j9;ʏiŇ.N8'*Mvڹvp^24I dy#l\UK8v/:9Zя92L*HSom|16ic-!3%yLWyY' KF l6h3wp2&] x,OztS"qU&%]~e޿?FR0NJIŏ! m6 )8/)JVR%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R%)J"R,7ޢ65hoԍ>56Kbvf#m4QUE¥6osOҵ-cn`y3Wˢ,9lW2j',i[CpxI[D^NShpk$`vȍGL+(GOٌ8$?=oJyҁۋ _MOr~Sb{=eνcZȆ۲tV$Rk=T+5π\g]q%Ȭr%#r4>;b#[2$8G9Jᡰ-7װ;=^DmGV;c8E& uQ@HeKg'buI VkL@c"cvRJRV'kαٖ{xVeB$G`m(**TEtX,f,͡q 飊̉SUn -@UԣMF"p9Q֠G mcPl={[ȇm,t60Q2"RQDRUU]k|ޛcatlQwlAi 4yB* *Ȣ}^Me;cVg 1 RVыŭcY`#!NJ-Rpu3twE""U]V5B F;JtKyݜ1q Wq$_T_֋_[tDt~e\JX3{'FK}V͞7g-_=nhEDp:k8rhY^g)!#'Q/I ~˺vhq# L]uo&vbHU)JX(&ɭf;:vk0rʐhQR#"_DDUUE^pr mo.Zdr\lmK$SM8(^;*VIVuG-F&X+P,z&@tMU?9')ƭbYh|̋$c&o˰`28< @꒦̫n}:ZZ { `ݛdL괫I3ucWi& i 4jcY$G*e&0%Bfr1\H83½ŃV).´j". f Q7 mȹSuU_[zƫofA25ce"F3hDi[jW9.+lzڇ:.pK+X:[*+*ڡ*>8c{Yc"5 S,6q~^W8#פ\Š߯er.ucgW-Ưcs͠d@ʫ h%lIdzK\-ޥg,m3nn_˔KYTyeT7gnUTڗn wc\I0\6׾] ̆O{D+)UrW W;.Ȳb:H$QETe\RUEe_ {NZ7pl8Io,f2g2UJj$B< B/ ZM}ېfp#ZmNz!.8:_WALt+tNuVZwkZjo9aϹޘWQL䓆u 3a7weޛ[e]g@COy]I Yb4|Yqݲ/Thw6A 01̌.Hѩ(Dp` OuG V|fE(.`6ѺG'$^!ثr7;%Z 4uV|5bcr9&K{$s"4˨@\*{]c~a<3n_j\kj\!nb --s Aެ@H#<.WƢ[H=oOѺ*LOw2)m3fN{q*pG¦dVRFU BʨBC/0{aLkat' G[̻ ZtwLEϮYPζmڻ9m].Iq39͘aʤنvڵ/WYxiud-eG;dW^+{{n\$TH ?^.e D%*4ai 48IjML^\G\X}.|lEqVME U3-r2!bj*jXfG1KM˦u/YDrtIgZo^)g#[ׂ*|o'Brum$$9[._ 0v1ī)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQ)JQi%3^/VM9̛6cxl6$n:ㄨ (JV[88~`ݲR;ч`NdMĀ")*Uiq/ƢbNWc;rm{dN; 曁 x[e!E6}Mִ:\8vpF5Zrkćvȝsw ;xݐd*("{WzE9-ɀ1' <|v' 1 1eoWϿC"%خ 5 J8 s鶮&BF( BApPTI_]KK$ӱ/רlqQacZlyK̋wi$41yR9'x:] r{Oa&NjǼkXܷ-چ[MEd$":/8:4pęgLF0Չ"12p7)JR%)J"R*Uکb YFcߡ=t }b Ćуg!%>B!ﰭYuOR/HݧP1Gۑ1{ rl ) &䩹 XZ],w)xXZ Vȯ:ۡ9 uf3&=ZZF9D7YV`=T ٩Š85kbqq>ne$0tZW1=$=6A3Lo%}oDž.c≮LN!'E.*\\K_(r 7XDOQE+T09_UNZn5b2#hu,n[FݓzuN)j3,"z˽b+Zv9K{;;T/ѷ2nv-`) -lƴg Oᔩw'R<^"a૞^.$1jc0< bLnvԜDU7۹tY. c` LZdqu eSuI2tXz3mH<]s)'$?֫SC LE3lӵWH\ 2B#N"8iԹ7N s$d aq "ܓii"dP$ i (e2 @TTĈKm S뭭-lTM6CMUF!Θ =d`l5OzL Fa[f,X,#m"""'"V=e-mb pY2s-BT|ʥ}_Jڨ*/Pxo mDZ1 eWMv  !@ %TT$ㅽ oxKݏ_mv4O999%'mITi |$%ɓza4u[0F'/$7Pѧ[""MȕvDOZ莳ڵg(p lLAv$NeR D9HJNcvKj3+?]q=&5 lJ>)akqQɄIVЃШ]Otdbb2L 0lvnFY9׹'. @qvf"')]5iS#Y[۹ǴXFa.J`pmW 4D0V(i/vLBd&RexlSdD>3t;LDw~yr uT5jYJ7XR]9|֫pH:W21 vv#d @UQPvEZa?mcx#8-3]іDAUu_Ԭ!|Oۊ;%)JQ_9t& e-uNsl]S}+2Dd(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR>%FߡCffHyD9xŴ"SQDB!E]TOy۰l?lU|557_n<9`U}"Nj6ƦݰˍJn>fb G&Bsܯ5Bwު}`-_˦?r$۞K8R?kr!˄`ۦN;#h|j_x9, )A%L'@zF\u]L_V> xUcq|{b]I!ɫ\ 닼FC|Gy} ;_&7&6mrbO:lG/dMM9"*Rg|J+_~;:*!p 2!"q~KnYUm:ho[h6,dLg po')lb#ELۂ6?]QkA,TisH4lyF.Ztg Ϧoe#9aRA#7j^^zNtn^^zNtn^^zNtn^^zNtn^;: G\b&C3qU][ Gӯ(KH:_+fnpԆɣD]bMN _@ =0}EYNR!L4P8ee vb.FbTe mHFI[Aܜ]2;&a"md-=I/95J'iDdO&wQBoUh?y<]ɠfYy7ydwTgbDbVoD z]q7ۭLq;&;3.GChۏ6x {v?%Sviv$ҙqDEMHcf`aNtW,CɱM7~2./2<˭ٶm`@BB͵ K@3WHG]鶪ᢨm/Vic7-^x2Upse>r&>=G mMABqB2ʹϨP:nQFm=Ҋ*g/y6MDvmnx gd9e=>q8qT,Emm^6BMQSQSt-nsOaɿݲh{\-2si@OE˳X1ZnV"TW Qo%U%UUWIhVk:{c6:]s\e\ڒۣցHy^!@-Qa/wKqtS4p~.gTQ+΍jmrSlv/rUC1=q%\i ?J~|?L\.d5mt?yPǔ\dgh&mb\[:v,0ZݲC¥CXg4 +.~Wj׎wӊi,ϝ\R$,X6p+ٚWI|MFV*f㛉lt=O}@ 8r昨47kqɉYiRG/"ONL@#OӽPSݟ 7;ϲζB1tIeanC.C-X,<>uwІ[6\~p\_$&y*MRDRR^I3"j*bǝRvdMr[n+*؋mV 㯅N˓Gby;wfMǓwA lpKIBi} m__`s5d䴺] ]CUSsMvd8љ0p ύ5i=?z~W6M,.& 4,,E42C̛ViUܖ|$w| v-v]^f$KUc@liyyKhG- ]9Y`GZynM\@19#2\dGmI- ׉,P[*Ҭ:6 K[x\ ~0z. 2pÎd0;2NUGÏ7i-BǯIaS0P]p!Q@+txQyHut2x6x]dn]Spr^e⁙"!hh )""k ]H"s%"gf*")dX%ˤQFyYwEmylЮ4w7Nx%͛.( 7n>^wȜ!9yǒ%b{Cd˳%O|EB""s wPkq9X0aŠɼA:"3#O.(צo<ȎZm?dFo;,Fr;Fθ "lPDq Sf6_7'pk kyxvmmv5(,Ykv趢6*mRy8M5Ou &5dG8'[xOQtK |riMCO:cU'6z;".\]͖15-6<>~oˊr|0By%N<@EI:7̀\ܫ+-Lqy/'H|S41 6rmsh؜$7YVs iAq44i]My 9:'3UWw!7b=igY B,Bʪ$`u8 ˶Ev1܉n<:'2a4M3骑ju`k@7cKy"37p$Կѳ-y+JufHڜ\X28d(JD[$.ɱ-L~C=˝ڦ?g i$pL]uUol쳭r$MS#ɿ3@D[8;*:+=R{ ,N-27q' m##'THU2=²v8az7bpzWD[_IUR NTEReׇ75:ov|Rkqj2J݃mFP)7fAE PŴpk66x$pYHK#((RvWTӕUAT/zե 9arU.d݂,h/Lucg K\㈥-M`N^}F#Z$  Q97.;o4bnH({{dFmVZ$lZ "'}_;uFNNh1ֽRAݪK+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڋ+P}aX~nڊ qYL+cvҷ[HA^Yc13P@LwA-%o4IQ6{K,1%G1y䶍^WgY\ ̏k˭bfK*ɓjBBj$nS- \I8̈́lX>pn.0*gD M쎶ۉ6 ?hrn>]څF/.yG"3#޴.].g x8E?Ha8 Lu oeUBZZ1 taHHB%d隳eҙԸE4&DlJ$UEYE邨3Z̟qYwZ녮#E4)gXӥcmvPEQK|UKҩfEa|0{Ie9# l: 'nms*,Oxig;\`Mǡڝ1 b#n1 eDT/ 2SZצ&mdޭ\o?jzh񻥵%Fq n'AB-(|֮N.qdnm@3. I$y+EMsI\8bx-asʷ̵ݛiQ9Fq!qD&66 2E_k928:mnW&UU6W#0!x/̉sH" ]Mw˜'Iy@@:fj-6<ܠ ?AJ;"ñ|sm#!"j)mU UAE%]u_'Fϣ*n'q[7s }z\gNX)Y#2+o8"衊d"*o$b*~0/LLNidžп /E}e};^&-GW9t[h 2,(  (""'"'U׆{+VaeDg-Qc$*IʄʛWIE KC . 2Z&ii"ߥ ֬N,np["1 T⤕=[2BH,8oĵjcY7vCKPn!Ǜ6K^iESi]m9_}Xn"H{j*9#n`1dwj/. r)򳼗.e ͢abjiE6$򹱸z%cy+ְִ8$T%D"q0T.hr:g ~g.Jc.=l\^qEEBuۗm FtǑA(7`ZWYmTcKO~fTTQ(g?tuZlNpIpuAsH\ -l<i\#R ۑe `᢫i㯃k h J2 [/A&褮6⠒xFm*n$I^S^.a`y&C>$>0d貘Q _t1B4)護@4Ӈ^ɵ@; K*Q!n/Qw5r_UWu]kӸþ/cVwZA.tK`vb28njEd8IWjj@$c}t wDqPyw -%qqwE&E2v!A+ي6:Hhlo;9zS)Y]B,t^׆Г t@wYM.ds&Z!8󱢙d)=,ŝ4)Ce$Sm7O部JGӝN35] ۦ!~8)-0:o.[tЛS¾P&[ܮ1`]q ,B(xMn2 Vו@QElGV`1d\\ByY(I5B@A7E߳hv5I7Z 7]rtnf칠\!yXvF ƛ9 d֢xLq5n ̸s9"w`" N0."fn87.̙4\Zq1v?)h?">T~(0ۦ:!6"Ifj' }JFLxcz͠&FuȲ `M%M 3\$dX.jsP5s>fpG p!2B蒄& &@œpplV=iMԋ.]ŷdxmZV-muKvLb"IjVQ-,CeYRLnbJ[ {/)C>4E ȴc*weW6V Tԟ'[鈣.c Zg8Ɨ&Gۆ3쓬86앸b䦤uAopY1+fh\>dwS_ (]"9$SgBmO [![)j7[B`HN5H0[bdF2ϥkrDε/]7}4>U]2 =CHVu{Jc$6jIQ6\h0m^̰K{ eqTGf@"}bif6Auz;}K0 m{of63^Se6NChhF9Z]*UpghL^]3 YdY6;.DYl)F&6 >?MBFK=`qpb>/.ܻ?7 - 29OF391x]ݮ{r o e2r }QWnQB1EUMƫ?Hq*ήR,Qr=&7mŒBeEw]ll3v{A*syd#"O(d8^Z}*kyrN`q-',2&p ̨/F'GLHA0W_lŰv{f2`m4PxzfG>eOE ?$V+1}=ym GRNuMš6uW>8[>tD#+DWatM|+nQU(cK@&qtZs#0K9$Naj-I8 pRN#/v; XL>|Q`^ aBSEC@m"zJ8^xlGJHd[v2ASeEwDTRGXc|hȉ$-\dWXl7d`ƌ5pq3oOW^N^^{V—J齫sOaKx{ttչRr:vr:ojR^)^9z;9z7ni)x/}_Ν_Λڷ4W^N^M[{ ^ +g/Wg/W=/ﳗӳ{V—J齫sOaKx{ttչRr:vr:ojR^)^9z;9z7ni)x/}_Ν_Λڷ4W^N^M[{ ^ +g/Wg/W=/ﳗӳ{V—J齫sOaKx{ttչRr:vr:ojR^)^9z;9z7ni)x/}_Ν_Λڷ4W^N^M[{ ^ +g/Wg/W=/ﳗӳ{V—J齫sOaKx{ttչRr:vr:ojR^)^9z;9z7ni)x(';+| ͒M+qjj&7rFl7i V#!4آQV r9s\7&ԇcjlc#6gE4>r'!s ] /x"so8i!imPǘqT$tT_e'C's:<&tv5kK}+n򦽺ǣT7kT i0yCh;8;]&٩_άua:>ꕿ m}7Dl[&Ǔ;or!Γ.HmyZLwv鎉dpQkԛ7p8$4ÈHG. *('[KocTq}->B]BqvK %{yJ[NBc27kG+d*ϠbH)TENzatEFq[%i  {!Z߼fsr33//駛//'v//駛//X~ϩ`MgH<M<M8}N ?P$u{3mvk ; y)iy[CTT.MT]_73__Z=Li#Ÿ5]/huɷCS`%MĐ}Q|kbM[k֍PE'1HSo݆R]D8%ʲJCz4ł@W'̲Qvhɣ|X(Q7d䘫u} 9_n &L؊>.Am8 gqH.+fvrhN^-:٧<;.0^aɲi֞o^mm\lLHHQR$Gt0ԎIwW;olCe2ƏꊗRoN: mPdgl5@1mVqri}1+69w-{ނҷOA*\^58{WbsO9-]SDv͸ u$y|RL|}ϣ_NZL;LɨdH -ѭjf|Z\2[/_(A&j\[kſ.td[9 G-ycnrX8Z; 4eFnǗ^q{K6^_w{tj,\"uTd%EۙI#e#; 07 Dp7g"\#@U`=fLhEpkw\{4I92`MgH<M<M8}N ?Jyb"yb"qI7~ s;E4s;E4;o?<(*Awiwi'v~xQTkkӊO,?g)//駛//X~ϩ`MgH<M<M8}N ?Jyb"yb"qI7~ s;E4s;E4;o?<(*Awiwi'v~xQTkkӊO,?g)//駛//X~ϩ`MgH<M<M8}N ?Jyb"yb"qI7~ s;E4s;E4;o?<(*Awiwi'v~xQTkkӊO,?g)//駛//X~ϩ`MgH<M<M8}N ?Jyb"yb"qI7~ s;E4s;E4;o?<(*Awiwi'v~xQTkkӊO,?g)//駛//X~ϩ *_Ӽc ع77,V/y~NΜ7bܲX;?:p݋|srʥb~t/v.qM*_Ӽc ع77,V/y~NΜ7bܲPM#GfY~+Mm/W (A!꺻*/<5b|srʥb~t/7bܲX;?:p݋|srʥb~t/v.qM*_Ӽc ع77,V/y~NΜ7bܲX;?:p݋|srʥb~t/v.qM*_Ӽc ع77,V/y~NΜ7bܲX;?:p݋|srʥb~t/v.qM*_Ӽc ع77,V/y~NΜ7bܲX;?:p݋|srʥb~t/v.qM*_Ӽc ع77,V/y~NΜ7bܲX;?:p݋|srʥb~t/v.qM*_Ӽc ع77,V/y~NΜ7bܲX;?:p݋|srʥb~t/v.qM*_Ӽc ع77,V/y~NΜ7bܲX;?:p݋|srʥb~t/v.qM*_Ӽc ع77,V/y~NΜ7bܲX;?:p݋|srʥb~t/v.qM*_Ӽc ع77,V/y~NΜ7bܲX;?:p݋|srʥb~t/v.qM*_Ӽc ع77,V/y~NΜ7bܲX;?:p݋|srʥb~t/v.qM*_Ӽc ع77,V/y~NΜ7bܲX;?:p݋|sr9M:kSs+w~T,3!p͈ -!j""Cjxax96O u}9,&m?E,7?ȿE_+@+/KEׯU`KL}E^+nWolh٪<#G0?^?3qyc4M04c2Zٗ4\Vd U= ueܽmlޡ4ݽx"dhv*-\r)/$G*rrN'MؾMկe|S_ejp`MѫJu\p`MѪVr+vekJ"0h1ODEDЅ|jR5[i-J.ەd^czf ,P7]/r+6zggÁ@跲\ Ks1z YAW3s?Q1Fy' \`آN*99!>x6mhOZ̝?:z mpD (":"(]/r*U5lclHnv{:˲/FvDF&]9^)ttޏ[-yHAUea?ZK+M!߼EfjJTUY}xef*" }/r*+[XD 8Ꭻa9 iꋧxIx[:H[[gXfKVk{: Lc pQI#?PT%Ro =d N;٦uԘpm }%@lרN\u쭷hAq"qc3$X]8 Vc>91ѫ#$ԍ@,r2 J y7·j@ +0mOqA3%qX&z\N\4KV{(9%~1u˄ KmpĒ2tS_eR h5wFTĈ(W: 1.>2]Z !{/U67?_m_Zu\ʠ\;Um|S_ec-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn_ZWˮ_e:S-{jn^)JWZJR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR(JR././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/cpow_table.csv0000644000175100001770000000132200000000000022141 0ustar00runnerdocker00000000000000Type of ``a``,Type of ``b``,``cpow==True``,``cpow==False`` C integer,Negative integer compile-time constant,Return type is C double,Return type is C double (special case) C integer,C integer (known to be >= 0 at compile time),Return type is integer,Return type is integer C integer,C integer (may be negative),Return type is integer,"Return type is C double (note that Python would dynamically pick ``int`` or ``float`` here, while Cython doesn’t)" C floating point,C integer,Return type is floating point,Return type is floating point C floating point (or C integer),C floating point,"Return type is floating point, result is NaN if the result would be complex",Either a C real or complex number at cost of some speed ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/debugging.rst0000644000175100001770000002264600000000000022006 0ustar00runnerdocker00000000000000.. highlight:: cython .. _debugging: ********************************** Debugging your Cython program ********************************** Cython comes with an extension for the GNU Debugger that helps users debug Cython code. To use this functionality, you will need to install gdb 7.2 or higher, built with Python support (linked to Python 2.6 or higher). The debugger supports debuggees with versions 2.6 and higher. For Python 3, code should be built with Python 3 and the debugger should be run with Python 2 (or at least it should be able to find the Python 2 Cython installation). Note that in recent versions of Ubuntu, for instance, ``gdb`` installed with ``apt-get`` is configured with Python 3. On such systems, the proper configuration of ``gdb`` can be obtained by downloading the ``gdb`` source, and then running:: ./configure --with-python=python2 make sudo make install Installing the Cython debugger can be quite tricky. `This installation script and example code `_ might be useful. The debugger will need debug information that the Cython compiler can export. This can be achieved from within the setup script by passing ``gdb_debug=True`` to ``cythonize()``:: from setuptools import Extension, setup extensions = [Extension('source', ['source.pyx'])] setup(..., ext_modules=cythonize(extensions, gdb_debug=True)) For development it's often helpful to pass the ``--inplace`` flag to the ``setup.py`` script, which makes setuptools build your project "in place", i.e., not in a separate `build` directory. When invoking Cython from the command line directly you can have it write debug information using the ``--gdb`` flag:: cython --gdb myfile.pyx Running the Debugger ===================== .. highlight:: bash To run the Cython debugger and have it import the debug information exported by Cython, run ``cygdb`` in the build directory:: $ python setup.py build_ext --inplace $ cygdb GNU gdb (GDB) 7.2 ... (gdb) When using the Cython debugger, it's preferable that you build and run your code with an interpreter that is compiled with debugging symbols (i.e. configured with ``--with-pydebug`` or compiled with the ``-g`` CFLAG). If your Python is installed and managed by your package manager you probably need to install debug support separately. If using NumPy then you also need to install numpy debugging, or you'll see an `import error for multiarray `_. E.G. for ubuntu:: $ sudo apt-get install python-dbg python-numpy-dbg $ python-dbg setup.py build_ext --inplace Then you need to run your script with ``python-dbg`` also. Ensure that when building your package with debug symbols that cython extensions are re-compiled if they had been previously compiled. If your package is version controlled, you might want to perform ``git clean -fxd`` or ``hg purge --all`` before building. You can also pass additional arguments to gdb:: $ cygdb /path/to/build/directory/ GDBARGS i.e.:: $ cygdb . -- --args python-dbg mainscript.py To tell cygdb not to import any debug information, supply ``--`` as the first argument:: $ cygdb -- Using the Debugger =================== The Cython debugger comes with a set of commands that support breakpoints, stack inspection, source code listing, stepping, stepping over, etc. Most of these commands are analogous to their respective gdb command. .. function:: cy break breakpoints... Break in a Python, Cython or C function. First it will look for a Cython function with that name, if cygdb doesn't know about a function (or method) with that name, it will set a (pending) C breakpoint. The ``-p`` option can be used to specify a Python breakpoint. Breakpoints can be set for either the function or method name, or they can be fully "qualified", which means that the entire "path" to a function is given:: (gdb) cy break cython_function_or_method (gdb) cy break packagename.cython_module.cython_function (gdb) cy break packagename.cython_module.ClassName.cython_method (gdb) cy break c_function You can also break on Cython line numbers:: (gdb) cy break :14 (gdb) cy break cython_module:14 (gdb) cy break packagename.cython_module:14 Python breakpoints currently support names of the module (not the entire package path) and the function or method:: (gdb) cy break -p python_module.python_function_or_method (gdb) cy break -p python_function_or_method .. note:: Python breakpoints only work in Python builds where the Python frame information can be read from the debugger. To ensure this, use a Python debug build or a non-stripped build compiled with debug support. .. function:: cy step Step through Python, Cython or C code. Python, Cython and C functions called directly from Cython code are considered relevant and will be stepped into. .. function:: cy next Step over Python, Cython or C code. .. function:: cy run Run the program. The default interpreter is the interpreter that was used to build your extensions with, or the interpreter ``cygdb`` is run with in case the "don't import debug information" option was in effect. The interpreter can be overridden using gdb's ``file`` command. .. function:: cy cont Continue the program. .. function:: cy up cy down Go up and down the stack to what is considered a relevant frame. .. function:: cy finish Execute until an upward relevant frame is met or something halts execution. .. function:: cy bt cy backtrace Print a traceback of all frames considered relevant. The ``-a`` option makes it print the full traceback (all C frames). .. function:: cy select Select a stack frame by number as listed by ``cy backtrace``. This command is introduced because ``cy backtrace`` prints a reversed stack trace, so frame numbers differ from gdb's ``bt``. .. function:: cy print varname Print a local or global Cython, Python or C variable (depending on the context). Variables may also be dereferenced:: (gdb) cy print x x = 1 (gdb) cy print *x *x = (PyObject) { _ob_next = 0x93efd8, _ob_prev = 0x93ef88, ob_refcnt = 65, ob_type = 0x83a3e0 } .. function:: cy set cython_variable = value Set a Cython variable on the Cython stack to value. .. function:: cy list List the source code surrounding the current line. .. function:: cy locals cy globals Print all the local and global variables and their values. .. function:: cy import FILE... Import debug information from files given as arguments. The easiest way to import debug information is to use the cygdb command line tool. .. function:: cy exec code Execute code in the current Python or Cython frame. This works like Python's interactive interpreter. For Python frames it uses the globals and locals from the Python frame, for Cython frames it uses the dict of globals used on the Cython module and a new dict filled with the local Cython variables. .. note:: ``cy exec`` modifies state and executes code in the debuggee and is therefore potentially dangerous. Example:: (gdb) cy exec x + 1 2 (gdb) cy exec import sys; print sys.version_info (2, 6, 5, 'final', 0) (gdb) cy exec >global foo > >foo = 'something' >end Convenience functions ===================== The following functions are gdb functions, which means they can be used in a gdb expression. .. function:: cy_cname(varname) Returns the C variable name of a Cython variable. For global variables this may not be actually valid. .. function:: cy_cvalue(varname) Returns the value of a Cython variable. .. function:: cy_eval(expression) Evaluates Python code in the nearest Python or Cython frame and returns the result of the expression as a gdb value. This gives a new reference if successful, NULL on error. .. function:: cy_lineno() Returns the current line number in the selected Cython frame. Example:: (gdb) print $cy_cname("x") $1 = "__pyx_v_x" (gdb) watch $cy_cvalue("x") Hardware watchpoint 13: $cy_cvalue("x") (gdb) cy set my_cython_variable = $cy_eval("{'spam': 'ham'}") (gdb) print $cy_lineno() $2 = 12 Configuring the Debugger ======================== A few aspects of the debugger are configurable with gdb parameters. For instance, colors can be disabled, the terminal background color and breakpoint autocompletion can be configured. .. c:macro:: cy_complete_unqualified Tells the Cython debugger whether ``cy break`` should also complete plain function names, i.e. not prefixed by their module name. E.g. if you have a function named ``spam``, in module ``M``, it tells whether to only complete ``M.spam`` or also just ``spam``. The default is true. .. c:macro:: cy_colorize_code Tells the debugger whether to colorize source code. The default is true. .. c:macro:: cy_terminal_background_color Tells the debugger about the terminal background color, which affects source code coloring. The default is "dark", another valid option is "light". This is how these parameters can be used:: (gdb) set cy_complete_unqualified off (gdb) set cy_terminal_background_color light (gdb) show cy_colorize_code ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/early_binding_for_speed.rst0000644000175100001770000000762300000000000024705 0ustar00runnerdocker00000000000000.. highlight:: cython .. _early-binding-for-speed: ************************** Early Binding for Speed ************************** .. include:: ../two-syntax-variants-used As a dynamic language, Python encourages a programming style of considering classes and objects in terms of their methods and attributes, more than where they fit into the class hierarchy. This can make Python a very relaxed and comfortable language for rapid development, but with a price - the 'red tape' of managing data types is dumped onto the interpreter. At run time, the interpreter does a lot of work searching namespaces, fetching attributes and parsing argument and keyword tuples. This run-time 'late binding' is a major cause of Python's relative slowness compared to 'early binding' languages such as C++. However with Cython it is possible to gain significant speed-ups through the use of 'early binding' programming techniques. For example, consider the following (silly) code example: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/early_binding_for_speed/rectangle.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/early_binding_for_speed/rectangle.pyx In the :func:`rectArea` method, the call to :meth:`rect.area` and the :meth:`.area` method contain a lot of Python overhead. However, in Cython, it is possible to eliminate a lot of this overhead in cases where calls occur within Cython code. For example: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/early_binding_for_speed/rectangle_cdef.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/early_binding_for_speed/rectangle_cdef.pyx Here, in the Rectangle extension class, we have defined two different area calculation methods, the efficient :meth:`_area` C method, and the Python-callable :meth:`area` method which serves as a thin wrapper around :meth:`_area`. Note also in the function :func:`rectArea` how we 'early bind' by declaring the local variable ``rect`` which is explicitly given the type Rectangle. By using this declaration, instead of just dynamically assigning to ``rect``, we gain the ability to access the much more efficient C-callable :meth:`_area` method. But Cython offers us more simplicity again, by allowing us to declare dual-access methods - methods that can be efficiently called at C level, but can also be accessed from pure Python code at the cost of the Python access overheads. Consider this code: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/early_binding_for_speed/rectangle_cpdef.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/early_binding_for_speed/rectangle_cpdef.pyx Here, we just have a single area method, declared as :keyword:`cpdef` or with ``@ccall`` decorator to make it efficiently callable as a C function, but still accessible from pure Python (or late-binding Cython) code. If within Cython code, we have a variable already 'early-bound' (ie, declared explicitly as type Rectangle, (or cast to type Rectangle), then invoking its area method will use the efficient C code path and skip the Python overhead. But if in Cython or regular Python code we have a regular object variable storing a Rectangle object, then invoking the area method will require: * an attribute lookup for the area method * packing a tuple for arguments and a dict for keywords (both empty in this case) * using the Python API to call the method and within the area method itself: * parsing the tuple and keywords * executing the calculation code * converting the result to a python object and returning it So within Cython, it is possible to achieve massive optimisations by using strong typing in declaration and casting of variables. For tight loops which use method calls, and where these methods are pure C, the difference can be huge. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/extension_types.rst0000644000175100001770000013057000000000000023307 0ustar00runnerdocker00000000000000.. highlight:: cython .. _extension-types: ****************** Extension Types ****************** Introduction ============== .. include:: ../two-syntax-variants-used As well as creating normal user-defined classes with the Python class statement, Cython also lets you create new built-in Python types, known as :term:`extension types`. You define an extension type using the :keyword:`cdef` class statement or decorating the class with the ``@cclass`` decorator. Here's an example: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/extension_types/shrubbery.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/extension_types/shrubbery.pyx As you can see, a Cython extension type definition looks a lot like a Python class definition. Within it, you use the :keyword:`def` statement to define methods that can be called from Python code. You can even define many of the special methods such as :meth:`__init__` as you would in Python. The main difference is that you can define attributes using * the :keyword:`cdef` statement, * the :func:`cython.declare()` function or * the annotation of an attribute name. .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cclass class Shrubbery: width = cython.declare(cython.int) height: cython.int .. group-tab:: Cython .. code-block:: cython cdef class Shrubbery: cdef int width cdef int height The attributes may be Python objects (either generic or of a particular extension type), or they may be of any C data type. So you can use extension types to wrap arbitrary C data structures and provide a Python-like interface to them. .. _readonly: Static Attributes ================= Attributes of an extension type are stored directly in the object's C struct. The set of attributes is fixed at compile time; you can't add attributes to an extension type instance at run time simply by assigning to them, as you could with a Python class instance. However, you can explicitly enable support for dynamically assigned attributes, or subclass the extension type with a normal Python class, which then supports arbitrary attribute assignments. See :ref:`dynamic_attributes`. There are two ways that attributes of an extension type can be accessed: by Python attribute lookup, or by direct access to the C struct from Cython code. Python code is only able to access attributes of an extension type by the first method, but Cython code can use either method. By default, extension type attributes are only accessible by direct access, not Python access, which means that they are not accessible from Python code. To make them accessible from Python code, you need to declare them as :keyword:`public` or :keyword:`readonly`. For example: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/extension_types/python_access.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/extension_types/python_access.pyx makes the width and height attributes readable and writable from Python code, and the depth attribute readable but not writable. .. note:: You can only expose simple C types, such as ints, floats, and strings, for Python access. You can also expose Python-valued attributes. .. note:: Also the :keyword:`public` and :keyword:`readonly` options apply only to Python access, not direct access. All the attributes of an extension type are always readable and writable by C-level access. .. _dynamic_attributes: Dynamic Attributes ================== It is not possible to add attributes to an extension type at runtime by default. You have two ways of avoiding this limitation, both add an overhead when a method is called from Python code. Especially when calling hybrid methods declared with :keyword:`cpdef` in .pyx files or with the ``@ccall`` decorator. The first approach is to create a Python subclass: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/extension_types/extendable_animal.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/extension_types/extendable_animal.pyx Declaring a ``__dict__`` attribute is the second way of enabling dynamic attributes: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/extension_types/dict_animal.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/extension_types/dict_animal.pyx Type declarations =================== Before you can directly access the attributes of an extension type, the Cython compiler must know that you have an instance of that type, and not just a generic Python object. It knows this already in the case of the ``self`` parameter of the methods of that type, but in other cases you will have to use a type declaration. For example, in the following function: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc def widen_shrubbery(sh, extra_width): # BAD sh.width = sh.width + extra_width .. group-tab:: Cython .. code-block:: cython cdef widen_shrubbery(sh, extra_width): # BAD sh.width = sh.width + extra_width because the ``sh`` parameter hasn't been given a type, the width attribute will be accessed by a Python attribute lookup. If the attribute has been declared :keyword:`public` or :keyword:`readonly` then this will work, but it will be very inefficient. If the attribute is private, it will not work at all -- the code will compile, but an attribute error will be raised at run time. The solution is to declare ``sh`` as being of type :class:`Shrubbery`, as follows: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/extension_types/widen_shrubbery.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/extension_types/widen_shrubbery.pyx Now the Cython compiler knows that ``sh`` has a C attribute called :attr:`width` and will generate code to access it directly and efficiently. The same consideration applies to local variables, for example: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/extension_types/shrubbery_2.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/extension_types/shrubbery_2.pyx .. note:: Here, we *cimport* the class :class:`Shrubbery` (using the :keyword:`cimport` statement or importing from special ``cython.cimports`` package), and this is necessary to declare the type at compile time. To be able to cimport an extension type, we split the class definition into two parts, one in a definition file and the other in the corresponding implementation file. You should read :ref:`sharing_extension_types` to learn to do that. Type Testing and Casting ------------------------ Suppose I have a method :meth:`quest` which returns an object of type :class:`Shrubbery`. To access its width I could write: .. tabs:: .. group-tab:: Pure Python .. code-block:: python sh: Shrubbery = quest() print(sh.width) .. group-tab:: Cython .. code-block:: cython cdef Shrubbery sh = quest() print(sh.width) which requires the use of a local variable and performs a type test on assignment. If you *know* the return value of :meth:`quest` will be of type :class:`Shrubbery` you can use a cast to write: .. tabs:: .. group-tab:: Pure Python .. code-block:: python print( cython.cast(Shrubbery, quest()).width ) .. group-tab:: Cython .. code-block:: cython print( (quest()).width ) This may be dangerous if :meth:`quest()` is not actually a :class:`Shrubbery`, as it will try to access width as a C struct member which may not exist. At the C level, rather than raising an :class:`AttributeError`, either an nonsensical result will be returned (interpreting whatever data is at that address as an int) or a segfault may result from trying to access invalid memory. Instead, one can write: .. tabs:: .. group-tab:: Pure Python .. code-block:: python print( cython.cast(Shrubbery, quest(), typecheck=True).width ) .. group-tab:: Cython .. code-block:: cython print( (quest()).width ) which performs a type check (possibly raising a :class:`TypeError`) before making the cast and allowing the code to proceed. To explicitly test the type of an object, use the :meth:`isinstance` builtin function. For known builtin or extension types, Cython translates these into a fast and safe type check that ignores changes to the object's ``__class__`` attribute etc., so that after a successful :meth:`isinstance` test, code can rely on the expected C structure of the extension type and its C-level attributes (stored in the object’s C struct) and :keyword:`cdef`/``@cfunc`` methods. .. _extension_types_and_none: Extension types and None ========================= Cython handles ``None`` values differently in C-like type declarations and when Python annotations are used. In :keyword:`cdef` declarations and C-like function argument declarations (``func(list x)``), when you declare an argument or C variable as having an extension or Python builtin type, Cython will allow it to take on the value ``None`` as well as values of its declared type. This is analogous to the way a C pointer can take on the value ``NULL``, and you need to exercise the same caution because of it. There is no problem as long as you are performing Python operations on it, because full dynamic type checking will be applied. However, when you access C attributes of an extension type (as in the widen_shrubbery function above), it's up to you to make sure the reference you're using is not ``None`` -- in the interests of efficiency, Cython does not check this. With the C-like declaration syntax, you need to be particularly careful when exposing Python functions which take extension types as arguments:: def widen_shrubbery(Shrubbery sh, extra_width): # This is sh.width = sh.width + extra_width # dangerous! The users of our module could crash it by passing ``None`` for the ``sh`` parameter. As in Python, whenever it is unclear whether a variable can be ``None``, but the code requires a non-None value, an explicit check can help:: def widen_shrubbery(Shrubbery sh, extra_width): if sh is None: raise TypeError sh.width = sh.width + extra_width but since this is anticipated to be such a frequent requirement, Cython language provides a more convenient way. Parameters of a Python function declared as an extension type can have a ``not None`` clause:: def widen_shrubbery(Shrubbery sh not None, extra_width): sh.width = sh.width + extra_width Now the function will automatically check that ``sh`` is ``not None`` along with checking that it has the right type. When annotations are used, the behaviour follows the Python typing semantics of `PEP-484 `_ instead. The value ``None`` is not allowed when a variable is annotated only with its plain type:: def widen_shrubbery(sh: Shrubbery, extra_width): # TypeError is raised sh.width = sh.width + extra_width # when sh is None To also allow ``None``, ``typing.Optional[ ]`` must be used explicitly. For function arguments, this is also automatically allowed when they have a default argument of `None``, e.g. ``func(x: list = None)`` does not require ``typing.Optional``:: import typing def widen_shrubbery(sh: typing.Optional[Shrubbery], extra_width): if sh is None: # We want to raise a custom exception in case of a None value. raise ValueError sh.width = sh.width + extra_width The upside of using annotations here is that they are safe by default because you need to explicitly allow ``None`` values for them. .. note:: The ``not None`` and ``typing.Optional`` can only be used in Python functions (defined with :keyword:`def` and without ``@cython.cfunc`` decorator) and not C functions (defined with :keyword:`cdef` or decorated using ``@cython.cfunc``). If you need to check whether a parameter to a C function is ``None``, you will need to do it yourself. .. note:: Some more things: * The ``self`` parameter of a method of an extension type is guaranteed never to be ``None``. * When comparing a value with ``None``, keep in mind that, if ``x`` is a Python object, ``x is None`` and ``x is not None`` are very efficient because they translate directly to C pointer comparisons, whereas ``x == None`` and ``x != None``, or simply using ``x`` as a boolean value (as in ``if x: ...``) will invoke Python operations and therefore be much slower. Special methods ================ Although the principles are similar, there are substantial differences between many of the :meth:`__xxx__` special methods of extension types and their Python counterparts. There is a :ref:`separate page ` devoted to this subject, and you should read it carefully before attempting to use any special methods in your extension types. .. _properties: Properties ============ You can declare properties in an extension class using the same syntax as in ordinary Python code: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cclass class Spam: @property def cheese(self): # This is called when the property is read. ... @cheese.setter def cheese(self, value): # This is called when the property is written. ... @cheese.deleter def cheese(self): # This is called when the property is deleted. .. group-tab:: Cython .. code-block:: cython cdef class Spam: @property def cheese(self): # This is called when the property is read. ... @cheese.setter def cheese(self, value): # This is called when the property is written. ... @cheese.deleter def cheese(self): # This is called when the property is deleted. There is also a special (deprecated) legacy syntax for defining properties in an extension class:: cdef class Spam: property cheese: "A doc string can go here." def __get__(self): # This is called when the property is read. ... def __set__(self, value): # This is called when the property is written. ... def __del__(self): # This is called when the property is deleted. The :meth:`__get__`, :meth:`__set__` and :meth:`__del__` methods are all optional; if they are omitted, an exception will be raised when the corresponding operation is attempted. Here's a complete example. It defines a property which adds to a list each time it is written to, returns the list when it is read, and empties the list when it is deleted: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/extension_types/cheesy.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/extension_types/cheesy.pyx .. code-block:: text # Test output We don't have: [] We don't have: ['camembert'] We don't have: ['camembert', 'cheddar'] We don't have: [] C methods ========= Extension types can have C methods as well as Python methods. Like C functions, C methods are declared using * :keyword:`cdef` instead of :keyword:`def` or ``@cfunc`` decorator for *C methods*, or * :keyword:`cpdef` instead of :keyword:`def` or ``@ccall`` decorator for *hybrid methods*. C methods are "virtual", and may be overridden in derived extension types. In addition, :keyword:`cpdef`/``@ccall`` methods can even be overridden by Python methods when called as C method. This adds a little to their calling overhead compared to a :keyword:`cdef`/``@cfunc`` method: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/extension_types/pets.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/extension_types/pets.pyx .. code-block:: text # Output p1: This parrot is resting. p2: This parrot is resting. Lovely plumage! The above example also illustrates that a C method can call an inherited C method using the usual Python technique, i.e.:: Parrot.describe(self) :keyword:`cdef`/``@ccall`` methods can be declared static by using the ``@staticmethod`` decorator. This can be especially useful for constructing classes that take non-Python compatible types: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/extension_types/owned_pointer.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/extension_types/owned_pointer.pyx .. note:: Cython currently does not support decorating :keyword:`cdef`/``@ccall`` methods with the ``@classmethod`` decorator. .. _subclassing: Subclassing ============= If an extension type inherits from other types, the first base class must be a built-in type or another extension type: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cclass class Parrot: ... @cython.cclass class Norwegian(Parrot): ... .. group-tab:: Cython .. code-block:: cython cdef class Parrot: ... cdef class Norwegian(Parrot): ... A complete definition of the base type must be available to Cython, so if the base type is a built-in type, it must have been previously declared as an extern extension type. If the base type is defined in another Cython module, it must either be declared as an extern extension type or imported using the :keyword:`cimport` statement or importing from the special ``cython.cimports`` package. Multiple inheritance is supported, however the second and subsequent base classes must be an ordinary Python class (not an extension type or a built-in type). Cython extension types can also be subclassed in Python. A Python class can inherit from multiple extension types provided that the usual Python rules for multiple inheritance are followed (i.e. the C layouts of all the base classes must be compatible). There is a way to prevent extension types from being subtyped in Python. This is done via the ``final`` directive, usually set on an extension type or C method using a decorator: .. tabs:: .. group-tab:: Pure Python .. code-block:: python import cython @cython.final @cython.cclass class Parrot: def describe(self): pass @cython.cclass class Lizard: @cython.final @cython.cfunc def done(self): pass .. group-tab:: Cython .. code-block:: cython cimport cython @cython.final cdef class Parrot: def describe(self): pass cdef class Lizard: @cython.final cdef done(self): pass Trying to create a Python subclass from a final type or overriding a final method will raise a :class:`TypeError` at runtime. Cython will also prevent subtyping a final type or overriding a final method inside of the same module, i.e. creating an extension type that uses a final type as its base type will fail at compile time. Note, however, that this restriction does not currently propagate to other extension modules, so Cython is unable to prevent final extension types from being subtyped at the C level by foreign code. .. _forward_declaring_extension_types: Forward-declaring extension types =================================== Extension types can be forward-declared, like :keyword:`struct` and :keyword:`union` types. This is usually not necessary and violates the DRY principle (Don't Repeat Yourself). If you are forward-declaring an extension type that has a base class, you must specify the base class in both the forward declaration and its subsequent definition, for example,:: cdef class A(B) ... cdef class A(B): # attributes and methods Fast instantiation =================== Cython provides two ways to speed up the instantiation of extension types. The first one is a direct call to the ``__new__()`` special static method, as known from Python. For an extension type ``Penguin``, you could use the following code: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/extension_types/penguin.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/extension_types/penguin.pyx Note that the path through ``__new__()`` will *not* call the type's ``__init__()`` method (again, as known from Python). Thus, in the example above, the first instantiation will print ``eating!``, but the second will not. This is only one of the reasons why the ``__cinit__()`` method is safer than the normal ``__init__()`` method for initialising extension types and bringing them into a correct and safe state. See the :ref:`Initialisation Methods Section ` about the differences. The second performance improvement applies to types that are often created and deleted in a row, so that they can benefit from a freelist. Cython provides the decorator ``@cython.freelist(N)`` for this, which creates a statically sized freelist of ``N`` instances for a given type. Example: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/extension_types/penguin2.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/extension_types/penguin2.pyx .. _existing-pointers-instantiation: Instantiation from existing C/C++ pointers =========================================== It is quite common to want to instantiate an extension class from an existing (pointer to a) data structure, often as returned by external C/C++ functions. As extension classes can only accept Python objects as arguments in their constructors, this necessitates the use of factory functions or factory methods. For example: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/extension_types/wrapper_class.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/extension_types/wrapper_class.pyx To then create a ``WrapperClass`` object from an existing ``my_c_struct`` pointer, ``WrapperClass.from_ptr(ptr)`` can be used in Cython code. To allocate a new structure and wrap it at the same time, ``WrapperClass.new_struct`` can be used instead. It is possible to create multiple Python objects all from the same pointer which point to the same in-memory data, if that is wanted, though care must be taken when de-allocating as can be seen above. Additionally, the ``ptr_owner`` flag can be used to control which ``WrapperClass`` object owns the pointer and is responsible for de-allocation - this is set to ``False`` by default in the example and can be enabled by calling ``from_ptr(ptr, owner=True)``. The GIL must *not* be released in ``__dealloc__`` either, or another lock used if it is, in such cases or race conditions can occur with multiple de-allocations. Being a part of the object constructor, the ``__cinit__`` method has a Python signature, which makes it unable to accept a ``my_c_struct`` pointer as an argument. Attempts to use pointers in a Python signature will result in errors like:: Cannot convert 'my_c_struct *' to Python object This is because Cython cannot automatically convert a pointer to a Python object, unlike with native types like ``int``. Note that for native types, Cython will copy the value and create a new Python object while in the above case, data is not copied and deallocating memory is a responsibility of the extension class. .. _making_extension_types_weak_referenceable: Making extension types weak-referenceable ========================================== By default, extension types do not support having weak references made to them. You can enable weak referencing by declaring a C attribute of type object called :attr:`__weakref__`. For example: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cclass class ExplodingAnimal: """This animal will self-destruct when it is no longer strongly referenced.""" __weakref__: object .. group-tab:: Cython .. code-block:: cython cdef class ExplodingAnimal: """This animal will self-destruct when it is no longer strongly referenced.""" cdef object __weakref__ Controlling deallocation and garbage collection in CPython ========================================================== .. NOTE:: This section only applies to the usual CPython implementation of Python. Other implementations like PyPy work differently. .. _dealloc_intro: Introduction ------------ First of all, it is good to understand that there are two ways to trigger deallocation of Python objects in CPython: CPython uses reference counting for all objects and any object with a reference count of zero is immediately deallocated. This is the most common way of deallocating an object. For example, consider :: >>> x = "foo" >>> x = "bar" After executing the second line, the string ``"foo"`` is no longer referenced, so it is deallocated. This is done using the ``tp_dealloc`` slot, which can be customized in Cython by implementing ``__dealloc__``. The second mechanism is the cyclic garbage collector. This is meant to resolve cyclic reference cycles such as :: >>> class Object: ... pass >>> def make_cycle(): ... x = Object() ... y = [x] ... x.attr = y When calling ``make_cycle``, a reference cycle is created since ``x`` references ``y`` and vice versa. Even though neither ``x`` or ``y`` are accessible after ``make_cycle`` returns, both have a reference count of 1, so they are not immediately deallocated. At regular times, the garbage collector runs, which will notice the reference cycle (using the ``tp_traverse`` slot) and break it. Breaking a reference cycle means taking an object in the cycle and removing all references from it to other Python objects (we call this *clearing* an object). Clearing is almost the same as deallocating, except that the actual object is not yet freed. For ``x`` in the example above, the attributes of ``x`` would be removed from ``x``. Note that it suffices to clear just one object in the reference cycle, since there is no longer a cycle after clearing one object. Once the cycle is broken, the usual refcount-based deallocation will actually remove the objects from memory. Clearing is implemented in the ``tp_clear`` slot. As we just explained, it is sufficient that one object in the cycle implements ``tp_clear``. .. _trashcan: Enabling the deallocation trashcan ---------------------------------- In CPython, it is possible to create deeply recursive objects. For example:: >>> L = None >>> for i in range(2**20): ... L = [L] Now imagine that we delete the final ``L``. Then ``L`` deallocates ``L[0]``, which deallocates ``L[0][0]`` and so on until we reach a recursion depth of ``2**20``. This deallocation is done in C and such a deep recursion will likely overflow the C call stack, crashing Python. CPython invented a mechanism for this called the *trashcan*. It limits the recursion depth of deallocations by delaying some deallocations. By default, Cython extension types do not use the trashcan but it can be enabled by setting the ``trashcan`` directive to ``True``. For example: .. tabs:: .. group-tab:: Pure Python .. code-block:: python import cython @cython.trashcan(True) @cython.cclass class Object: __dict__: dict .. group-tab:: Cython .. code-block:: cython cimport cython @cython.trashcan(True) cdef class Object: cdef dict __dict__ Trashcan usage is inherited by subclasses (unless explicitly disabled by ``@cython.trashcan(False)``). Some builtin types like ``list`` use the trashcan, so subclasses of it use the trashcan by default. Disabling cycle breaking (``tp_clear``) --------------------------------------- By default, each extension type will support the cyclic garbage collector of CPython. If any Python objects can be referenced, Cython will automatically generate the ``tp_traverse`` and ``tp_clear`` slots. This is usually what you want. There is at least one reason why this might not be what you want: If you need to cleanup some external resources in the ``__dealloc__`` special function and your object happened to be in a reference cycle, the garbage collector may have triggered a call to ``tp_clear`` to clear the object (see :ref:`dealloc_intro`). In that case, any object references have vanished when ``__dealloc__`` is called. Now your cleanup code lost access to the objects it has to clean up. To fix this, you can disable clearing instances of a specific class by using the ``no_gc_clear`` directive: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.no_gc_clear @cython.cclass class DBCursor: conn: DBConnection raw_cursor: cython.pointer(DBAPI_Cursor) # ... def __dealloc__(self): DBAPI_close_cursor(self.conn.raw_conn, self.raw_cursor) .. group-tab:: Cython .. code-block:: cython @cython.no_gc_clear cdef class DBCursor: cdef DBConnection conn cdef DBAPI_Cursor *raw_cursor # ... def __dealloc__(self): DBAPI_close_cursor(self.conn.raw_conn, self.raw_cursor) This example tries to close a cursor via a database connection when the Python object is destroyed. The ``DBConnection`` object is kept alive by the reference from ``DBCursor``. But if a cursor happens to be in a reference cycle, the garbage collector may delete the database connection reference, which makes it impossible to clean up the cursor. If you use ``no_gc_clear``, it is important that any given reference cycle contains at least one object *without* ``no_gc_clear``. Otherwise, the cycle cannot be broken, which is a memory leak. Disabling cyclic garbage collection ----------------------------------- In rare cases, extension types can be guaranteed not to participate in cycles, but the compiler won't be able to prove this. This would be the case if the class can never reference itself, even indirectly. In that case, you can manually disable cycle collection by using the ``no_gc`` directive, but beware that doing so when in fact the extension type can participate in cycles could cause memory leaks: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.no_gc @cython.cclass class UserInfo: name: str addresses: tuple .. group-tab:: Cython .. code-block:: cython @cython.no_gc cdef class UserInfo: cdef str name cdef tuple addresses If you can be sure addresses will contain only references to strings, the above would be safe, and it may yield a significant speedup, depending on your usage pattern. .. _auto_pickle: Controlling pickling ==================== By default, Cython will generate a ``__reduce__()`` method to allow pickling an extension type if and only if each of its members are convertible to Python and it has no ``__cinit__`` method. To require this behavior (i.e. throw an error at compile time if a class cannot be pickled) decorate the class with ``@cython.auto_pickle(True)``. One can also annotate with ``@cython.auto_pickle(False)`` to get the old behavior of not generating a ``__reduce__`` method in any case. Manually implementing a ``__reduce__`` or ``__reduce_ex__`` method will also disable this auto-generation and can be used to support pickling of more complicated types. Public and external extension types ==================================== Extension types can be declared extern or public. An extern extension type declaration makes an extension type defined in external C code available to a Cython module. A public extension type declaration makes an extension type defined in a Cython module available to external C code. .. note:: Cython currently does not support Extension types declared as extern or public in Pure Python mode. This is not considered an issue since public/extern extension types are most commonly declared in `.pxd` files and not in `.py` files. .. _external_extension_types: External extension types ------------------------ An extern extension type allows you to gain access to the internals of Python objects defined in the Python core or in a non-Cython extension module. .. note:: In previous versions of Pyrex, extern extension types were also used to reference extension types defined in another Pyrex module. While you can still do that, Cython provides a better mechanism for this. See :ref:`sharing-declarations`. Here is an example which will let you get at the C-level members of the built-in complex object:: from __future__ import print_function cdef extern from "complexobject.h": struct Py_complex: double real double imag ctypedef class __builtin__.complex [object PyComplexObject]: cdef Py_complex cval # A function which uses the above type def spam(complex c): print("Real:", c.cval.real) print("Imag:", c.cval.imag) .. note:: Some important things: 1. In this example, :keyword:`ctypedef` class has been used. This is because, in the Python header files, the ``PyComplexObject`` struct is declared with: .. code-block:: c typedef struct { ... } PyComplexObject; At runtime, a check will be performed when importing the Cython c-extension module that ``__builtin__.complex``'s ``tp_basicsize`` matches ``sizeof(`PyComplexObject)``. This check can fail if the Cython c-extension module was compiled with one version of the ``complexobject.h`` header but imported into a Python with a changed header. This check can be tweaked by using ``check_size`` in the name specification clause. 2. As well as the name of the extension type, the module in which its type object can be found is also specified. See the implicit importing section below. 3. When declaring an external extension type, you don't declare any methods. Declaration of methods is not required in order to call them, because the calls are Python method calls. Also, as with :keyword:`struct` and :keyword:`union`, if your extension class declaration is inside a :keyword:`cdef` extern from block, you only need to declare those C members which you wish to access. .. _name_specification_clause: Name specification clause ------------------------- The part of the class declaration in square brackets is a special feature only available for extern or public extension types. The full form of this clause is:: [object object_struct_name, type type_object_name, check_size cs_option] Where: - ``object_struct_name`` is the name to assume for the type's C struct. - ``type_object_name`` is the name to assume for the type's statically declared type object. - ``cs_option`` is ``warn`` (the default), ``error``, or ``ignore`` and is only used for external extension types. If ``error``, the ``sizeof(object_struct)`` that was found at compile time must match the type's runtime ``tp_basicsize`` exactly, otherwise the module import will fail with an error. If ``warn`` or ``ignore``, the ``object_struct`` is allowed to be smaller than the type's ``tp_basicsize``, which indicates the runtime type may be part of an updated module, and that the external module's developers extended the object in a backward-compatible fashion (only adding new fields to the end of the object). If ``warn``, a warning will be emitted in this case. The clauses can be written in any order. If the extension type declaration is inside a :keyword:`cdef` extern from block, the object clause is required, because Cython must be able to generate code that is compatible with the declarations in the header file. Otherwise, for extern extension types, the object clause is optional. For public extension types, the object and type clauses are both required, because Cython must be able to generate code that is compatible with external C code. Attribute name matching and aliasing ------------------------------------ Sometimes the type's C struct as specified in ``object_struct_name`` may use different labels for the fields than those in the ``PyTypeObject``. This can easily happen in hand-coded C extensions where the ``PyTypeObject_Foo`` has a getter method, but the name does not match the name in the ``PyFooObject``. In NumPy, for instance, python-level ``dtype.itemsize`` is a getter for the C struct field ``elsize``. Cython supports aliasing field names so that one can write ``dtype.itemsize`` in Cython code which will be compiled into direct access of the C struct field, without going through a C-API equivalent of ``dtype.__getattr__('itemsize')``. For example, we may have an extension module ``foo_extension``:: cdef class Foo: cdef public int field0, field1, field2; def __init__(self, f0, f1, f2): self.field0 = f0 self.field1 = f1 self.field2 = f2 but a C struct in a file ``foo_nominal.h``: .. code-block:: c typedef struct { PyObject_HEAD int f0; int f1; int f2; } FooStructNominal; Note that the struct uses ``f0``, ``f1``, ``f2`` but they are ``field0``, ``field1``, and ``field2`` in ``Foo``. We are given this situation, including a header file with that struct, and we wish to write a function to sum the values. If we write an extension module ``wrapper``:: cdef extern from "foo_nominal.h": ctypedef class foo_extension.Foo [object FooStructNominal]: cdef: int field0 int field1 int field2 def sum(Foo f): return f.field0 + f.field1 + f.field2 then ``wrapper.sum(f)`` (where ``f = foo_extension.Foo(1, 2, 3)``) will still use the C-API equivalent of:: return f.__getattr__('field0') + f.__getattr__('field1') + f.__getattr__('field1') instead of the desired C equivalent of ``return f->f0 + f->f1 + f->f2``. We can alias the fields by using:: cdef extern from "foo_nominal.h": ctypedef class foo_extension.Foo [object FooStructNominal]: cdef: int field0 "f0" int field1 "f1" int field2 "f2" def sum(Foo f) except -1: return f.field0 + f.field1 + f.field2 and now Cython will replace the slow ``__getattr__`` with direct C access to the FooStructNominal fields. This is useful when directly processing Python code. No changes to Python need be made to achieve significant speedups, even though the field names in Python and C are different. Of course, one should make sure the fields are equivalent. C inline properties ------------------- Similar to Python property attributes, Cython provides a way to declare C-level properties on external extension types. This is often used to shadow Python attributes through faster C level data access, but can also be used to add certain functionality to existing types when using them from Cython. The declarations must use `cdef inline`. For example, the above ``complex`` type could also be declared like this: .. literalinclude:: ../../examples/userguide/extension_types/c_property.pyx Implicit importing ------------------ Cython requires you to include a module name in an extern extension class declaration, for example,:: cdef extern class MyModule.Spam: ... The type object will be implicitly imported from the specified module and bound to the corresponding name in this module. In other words, in this example an implicit:: from MyModule import Spam statement will be executed at module load time. The module name can be a dotted name to refer to a module inside a package hierarchy, for example,:: cdef extern class My.Nested.Package.Spam: ... You can also specify an alternative name under which to import the type using an as clause, for example,:: cdef extern class My.Nested.Package.Spam as Yummy: ... which corresponds to the implicit import statement:: from My.Nested.Package import Spam as Yummy .. _types_names_vs_constructor_names: Type names vs. constructor names -------------------------------- Inside a Cython module, the name of an extension type serves two distinct purposes. When used in an expression, it refers to a module-level global variable holding the type's constructor (i.e. its type-object). However, it can also be used as a C type name to declare variables, arguments and return values of that type. When you declare:: cdef extern class MyModule.Spam: ... the name Spam serves both these roles. There may be other names by which you can refer to the constructor, but only Spam can be used as a type name. For example, if you were to explicitly import MyModule, you could use ``MyModule.Spam()`` to create a Spam instance, but you wouldn't be able to use :class:`MyModule.Spam` as a type name. When an as clause is used, the name specified in the as clause also takes over both roles. So if you declare:: cdef extern class MyModule.Spam as Yummy: ... then Yummy becomes both the type name and a name for the constructor. Again, there are other ways that you could get hold of the constructor, but only Yummy is usable as a type name. .. _public: Public extension types ====================== An extension type can be declared public, in which case a ``.h`` file is generated containing declarations for its object struct and type object. By including the ``.h`` file in external C code that you write, that code can access the attributes of the extension type. Dataclass extension types ========================= Cython supports extension types that behave like the dataclasses defined in the Python 3.7+ standard library. The main benefit of using a dataclass is that it can auto-generate simple ``__init__``, ``__repr__`` and comparison functions. The Cython implementation behaves as much like the Python standard library implementation as possible and therefore the documentation here only briefly outlines the differences - if you plan on using them then please read `the documentation for the standard library module `_. Dataclasses can be declared using the ``@dataclasses.dataclass`` decorator on a Cython extension type (types marked ``cdef`` or created with the ``cython.cclass`` decorator). Alternatively the ``@cython.dataclasses.dataclass`` decorator can be applied to any class to both turn it into an extension type and a dataclass. If you need to define special properties on a field then use ``dataclasses.field`` (or ``cython.dataclasses.field`` will work too) .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/extension_types/dataclass.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/extension_types/dataclass.pyx You may use C-level types such as structs, pointers, or C++ classes. However, you may find these types are not compatible with the auto-generated special methods - for example if they cannot be converted from a Python type they cannot be passed to a constructor, and so you must use a ``default_factory`` to initialize them. Like with the Python implementation, you can also control which special functions an attribute is used in using ``field()``. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/external_C_code.rst0000644000175100001770000007544400000000000023135 0ustar00runnerdocker00000000000000.. highlight:: cython .. _external-C-code: ********************************** Interfacing with External C Code ********************************** One of the main uses of Cython is wrapping existing libraries of C code. This is achieved by using external declarations to declare the C functions and variables from the library that you want to use. You can also use public declarations to make C functions and variables defined in a Cython module available to external C code. The need for this is expected to be less frequent, but you might want to do it, for example, if you are `embedding Python`_ in another application as a scripting language. Just as a Cython module can be used as a bridge to allow Python code to call C code, it can also be used to allow C code to call Python code. .. _embedding Python: https://web.archive.org/web/20120225082358/http://www.freenet.org.nz:80/python/embeddingpyrex/ External declarations ======================= By default, C functions and variables declared at the module level are local to the module (i.e. they have the C static storage class). They can also be declared extern to specify that they are defined elsewhere, for example,:: cdef extern int spam_counter cdef extern void order_spam(int tons) Referencing C header files --------------------------- When you use an extern definition on its own as in the examples above, Cython includes a declaration for it in the generated C file. This can cause problems if the declaration doesn't exactly match the declaration that will be seen by other C code. If you're wrapping an existing C library, for example, it's important that the generated C code is compiled with exactly the same declarations as the rest of the library. To achieve this, you can tell Cython that the declarations are to be found in a C header file, like this:: cdef extern from "spam.h": int spam_counter void order_spam(int tons) The ``cdef extern`` from clause does three things: 1. It directs Cython to place a ``#include`` statement for the named header file in the generated C code. 2. It prevents Cython from generating any C code for the declarations found in the associated block. 3. It treats all declarations within the block as though they started with ``cdef extern``. It's important to understand that Cython does not itself read the C header file, so you still need to provide Cython versions of any declarations from it that you use. However, the Cython declarations don't always have to exactly match the C ones, and in some cases they shouldn't or can't. In particular: #. Leave out any platform-specific extensions to C declarations such as ``__declspec()``. #. If the header file declares a big struct and you only want to use a few members, you only need to declare the members you're interested in. Leaving the rest out doesn't do any harm, because the C compiler will use the full definition from the header file. In some cases, you might not need any of the struct's members, in which case you can just put pass in the body of the struct declaration, e.g.:: cdef extern from "foo.h": struct spam: pass .. note:: you can only do this inside a ``cdef extern from`` block; struct declarations anywhere else must be non-empty. #. If the header file uses ``typedef`` names such as :c:type:`word` to refer to platform-dependent flavours of numeric types, you will need a corresponding :keyword:`ctypedef` statement, but you don't need to match the type exactly, just use something of the right general kind (int, float, etc). For example,:: ctypedef int word will work okay whatever the actual size of a :c:type:`word` is (provided the header file defines it correctly). Conversion to and from Python types, if any, will also be used for this new type. #. If the header file uses macros to define constants, translate them into a normal external variable declaration. You can also declare them as an :keyword:`enum` if they contain normal :c:type:`int` values. Note that Cython considers :keyword:`enum` to be equivalent to :c:type:`int`, so do not do this for non-int values. #. If the header file defines a function using a macro, declare it as though it were an ordinary function, with appropriate argument and result types. #. For archaic reasons C uses the keyword ``void`` to declare a function taking no parameters. In Cython as in Python, simply declare such functions as :meth:`foo()`. A few more tricks and tips: * If you want to include a C header because it's needed by another header, but don't want to use any declarations from it, put pass in the extern-from block:: cdef extern from "spam.h": pass * If you want to include a system header, put angle brackets inside the quotes:: cdef extern from "": ... * If you want to include some external declarations, but don't want to specify a header file (because it's included by some other header that you've already included) you can put ``*`` in place of the header file name:: cdef extern from *: ... * If a ``cdef extern from "inc.h"`` block is not empty and contains only function or variable declarations (and no type declarations of any kind), Cython will put the ``#include "inc.h"`` statement after all declarations generated by Cython. This means that the included file has access to the variables, functions, structures, ... which are declared by Cython. Implementing functions in C --------------------------- When you want to call C code from a Cython module, usually that code will be in some external library that you link your extension against. However, you can also directly compile C (or C++) code as part of your Cython module. In the ``.pyx`` file, you can put something like:: cdef extern from "spam.c": void order_spam(int tons) Cython will assume that the function ``order_spam()`` is defined in the file ``spam.c``. If you also want to cimport this function from another module, it must be declared (not extern!) in the ``.pxd`` file:: cdef void order_spam(int tons) For this to work, the signature of ``order_spam()`` in ``spam.c`` must match the signature that Cython uses, in particular the function must be static: .. code-block:: c static void order_spam(int tons) { printf("Ordered %i tons of spam!\n", tons); } .. _struct-union-enum-styles: Styles of struct, union and enum declaration ---------------------------------------------- There are two main ways that structs, unions and enums can be declared in C header files: using a tag name, or using a typedef. There are also some variations based on various combinations of these. It's important to make the Cython declarations match the style used in the header file, so that Cython can emit the right sort of references to the type in the code it generates. To make this possible, Cython provides two different syntaxes for declaring a struct, union or enum type. The style introduced above corresponds to the use of a tag name. To get the other style, you prefix the declaration with :keyword:`ctypedef`, as illustrated below. The following table shows the various possible styles that can be found in a header file, and the corresponding Cython declaration that you should put in the ``cdef extern`` from block. Struct declarations are used as an example; the same applies equally to union and enum declarations. +-------------------------+---------------------------------------------+-----------------------------------------------------------------------+ | C code | Possibilities for corresponding Cython Code | Comments | +=========================+=============================================+=======================================================================+ | .. code-block:: c | :: | Cython will refer to the type as ``struct Foo`` in | | | | the generated C code. | | struct Foo { | cdef struct Foo: | | | ... | ... | | | }; | | | +-------------------------+---------------------------------------------+-----------------------------------------------------------------------+ | .. code-block:: c | :: | Cython will refer to the type simply as ``Foo`` in | | | | the generated C code. | | typedef struct { | ctypedef struct Foo: | | | ... | ... | | | } Foo; | | | +-------------------------+---------------------------------------------+-----------------------------------------------------------------------+ | .. code-block:: c | :: | If the C header uses both a tag and a typedef with *different* | | | | names, you can use either form of declaration in Cython | | typedef struct foo { | cdef struct foo: | (although if you need to forward reference the type, | | ... | ... | you'll have to use the first form). | | } Foo; | ctypedef foo Foo #optional | | | | | | | | or:: | | | | | | | | ctypedef struct Foo: | | | | ... | | +-------------------------+---------------------------------------------+-----------------------------------------------------------------------+ | .. code-block:: c | :: | If the header uses the *same* name for the tag and typedef, you | | | | won't be able to include a :keyword:`ctypedef` for it -- but then, | | typedef struct Foo { | cdef struct Foo: | it's not necessary. | | ... | ... | | | } Foo; | | | +-------------------------+---------------------------------------------+-----------------------------------------------------------------------+ See also use of :ref:`external_extension_types`. Note that in all the cases below, you refer to the type in Cython code simply as :c:type:`Foo`, not ``struct Foo``. Pointers -------- When interacting with a C-api there may be functions that require pointers as arguments. Pointers are variables that contain a memory address to another variable. For example:: cdef extern from "": cdef void increase_by_one(int *my_var) This function takes a pointer to an integer as argument. Knowing the address of the integer allows the function to modify the value in place, so that the caller can see the changes afterwards. In order to get the address from an existing variable, use the ``&`` operator:: cdef int some_int = 42 cdef int *some_int_pointer = &some_int increase_by_one(some_int_pointer) # Or without creating the extra variable increase_by_one(&some_int) print(some_int) # prints 44 (== 42+1+1) If you want to manipulate the variable the pointer points to, you can access it by referencing its first element like you would in python ``my_pointer[0]``. For example:: cdef void increase_by_one(int *my_var): my_var[0] += 1 For a deeper introduction to pointers, you can read `this tutorial at tutorialspoint `_. For differences between Cython and C syntax for manipulating pointers, see :ref:`statements_and_expressions`. Accessing Python/C API routines --------------------------------- One particular use of the ``cdef extern from`` statement is for gaining access to routines in the Python/C API. For example,:: cdef extern from "Python.h": object PyString_FromStringAndSize(char *s, Py_ssize_t len) will allow you to create Python strings containing null bytes. Note that Cython comes with ready-to-use declarations of (almost) all C-API functions in the cimportable ``cpython.*`` modules. See the list in https://github.com/cython/cython/tree/master/Cython/Includes/cpython You should always use submodules (e.g. ``cpython.object``, ``cpython.list``) to access these functions. Historically Cython has made some of the C-API functions available under directly under the ``cpython`` module. However, this is deprecated, will be removed eventually, and any new additions will not be added there. Special Types -------------- Cython predefines the name ``Py_ssize_t`` for use with Python/C API routines. To make your extensions compatible with 64-bit systems, you should always use this type where it is specified in the documentation of Python/C API routines. Windows Calling Conventions ---------------------------- The ``__stdcall`` and ``__cdecl`` calling convention specifiers can be used in Cython, with the same syntax as used by C compilers on Windows, for example,:: cdef extern int __stdcall FrobnicateWindow(long handle) cdef void (__stdcall *callback)(void *) If ``__stdcall`` is used, the function is only considered compatible with other ``__stdcall`` functions of the same signature. .. _resolve-conflicts: Resolving naming conflicts - C name specifications -------------------------------------------------- Each Cython module has a single module-level namespace for both Python and C names. This can be inconvenient if you want to wrap some external C functions and provide the Python user with Python functions of the same names. Cython provides a couple of different ways of solving this problem. The best way, especially if you have many C functions to wrap, is to put the extern C function declarations into a ``.pxd`` file and thus a different namespace, using the facilities described in :ref:`sharing declarations between Cython modules `. Writing them into a ``.pxd`` file allows their reuse across modules, avoids naming collisions in the normal Python way and even makes it easy to rename them on cimport. For example, if your ``decl.pxd`` file declared a C function ``eject_tomato``:: cdef extern from "myheader.h": void eject_tomato(float speed) then you can cimport and wrap it in a ``.pyx`` file as follows:: from decl cimport eject_tomato as c_eject_tomato def eject_tomato(speed): c_eject_tomato(speed) or simply cimport the ``.pxd`` file and use it as prefix:: cimport decl def eject_tomato(speed): decl.eject_tomato(speed) Note that this has no runtime lookup overhead, as it would in Python. Cython resolves the names in the ``.pxd`` file at compile time. For special cases where namespacing or renaming on import is not enough, e.g. when a name in C conflicts with a Python keyword, you can use a C name specification to give different Cython and C names to the C function at declaration time. Suppose, for example, that you want to wrap an external C function called :func:`yield`. If you declare it as:: cdef extern from "myheader.h": void c_yield "yield" (float speed) then its Cython visible name will be ``c_yield``, whereas its name in C will be ``yield``. You can then wrap it with:: def call_yield(speed): c_yield(speed) As for functions, C names can be specified for variables, structs, unions, enums, struct and union members, and enum values. For example:: cdef extern int one "eins", two "zwei" cdef extern float three "drei" cdef struct spam "SPAM": int i "eye" cdef enum surprise "inquisition": first "alpha" second "beta" = 3 Note that Cython will not do any validation or name mangling on the string you provide. It will inject the bare text into the C code unmodified, so you are entirely on your own with this feature. If you want to declare a name ``xyz`` and have Cython inject the text "make the C compiler fail here" into the C file for it, you can do this using a C name declaration. Consider this an advanced feature, only for the rare cases where everything else fails. .. _verbatim_c: Including verbatim C code ------------------------- For advanced use cases, Cython allows you to directly write C code as "docstring" of a ``cdef extern from`` block: .. literalinclude:: ../../examples/userguide/external_C_code/verbatim_c_code.pyx The above is essentially equivalent to having the C code in a file ``header.h`` and writing :: cdef extern from "header.h": long square(long x) void assign(long& x, long y) This feature is commonly used for platform specific adaptations at compile time, for example: .. literalinclude:: ../../examples/userguide/external_C_code/platform_adaptation.pyx It is also possible to combine a header file and verbatim C code:: cdef extern from "badheader.h": """ /* This macro breaks stuff */ #undef int """ # Stuff from badheader.h In this case, the C code ``#undef int`` is put right after ``#include "badheader.h"`` in the C code generated by Cython. Verbatim C code can also be used for version specific adaptations, e.g. when a struct field was added to a library but is not available in older versions: .. literalinclude:: ../../examples/userguide/external_C_code/struct_field_adaptation.pyx Note that the string is parsed like any other docstring in Python. If you require character escapes to be passed into the C code file, use a raw docstring, i.e. ``r""" ... """``. Using Cython Declarations from C ================================ Cython provides two methods for making C declarations from a Cython module available for use by external C code---public declarations and C API declarations. .. note:: You do not need to use either of these to make declarations from one Cython module available to another Cython module – you should use the :keyword:`cimport` statement for that. Sharing Declarations Between Cython Modules. .. _inittab_guide: Public Declarations --------------------- You can make C types, variables and functions defined in a Cython module accessible to C code that is linked together with the Cython-generated C file, by declaring them with the public keyword:: cdef public struct Bunny: # a public type declaration int vorpalness cdef public int spam # a public variable declaration cdef public void grail(Bunny *) # a public function declaration If there are any public declarations in a Cython module, a header file called :file:`modulename.h` file is generated containing equivalent C declarations for inclusion in other C code. A typical use case for this is building an extension module from multiple C sources, one of them being Cython generated (i.e. with something like ``Extension("grail", sources=["grail.pyx", "grail_helper.c"])`` in ``setup.py``. In this case, the file ``grail_helper.c`` just needs to add ``#include "grail.h"`` in order to access the public Cython variables. A more advanced use case is embedding Python in C using Cython. In this case, make sure to call Py_Initialize() and Py_Finalize(). For example, in the following snippet that includes :file:`grail.h`: .. code-block:: c #include #include "grail.h" int main() { Py_Initialize(); initgrail(); /* Python 2.x only ! */ Bunny b; grail(b); Py_Finalize(); } This C code can then be built together with the Cython-generated C code in a single program (or library). Be aware that this program will not include any external dependencies that your module uses. Therefore typically this will not generate a truly portable application for most cases. In Python 3.x, calling the module init function directly should be avoided. Instead, use the `inittab mechanism `_ to link Cython modules into a single shared library or program. .. code-block:: c err = PyImport_AppendInittab("grail", PyInit_grail); Py_Initialize(); grail_module = PyImport_ImportModule("grail"); If the Cython module resides within a package, then the name of the ``.h`` file consists of the full dotted name of the module, e.g. a module called :mod:`foo.spam` would have a header file called :file:`foo.spam.h`. .. NOTE:: On some operating systems like Linux, it is also possible to first build the Cython extension in the usual way and then link against the resulting ``.so`` file like a dynamic library. Beware that this is not portable, so it should be avoided. C++ public declarations ^^^^^^^^^^^^^^^^^^^^^^^ When a file is compiled as C++, its public functions are declared as C++ API (using ``extern "C++"``) by default. This disallows to call the functions from C code. If the functions are really meant as a plain C API, the ``extern`` declaration needs to be manually specified by the user. This can be done by setting the ``CYTHON_EXTERN_C`` C macro to ``extern "C"`` during the compilation of the generated C++ file:: from setuptools import Extension, setup from Cython.Build import cythonize extensions = [ Extension( "module", ["module.pyx"], define_macros=[("CYTHON_EXTERN_C", 'extern "C"')], language="c++", ) ] setup( name="My hello app", ext_modules=cythonize(extensions), ) .. _api: C API Declarations ------------------- The other way of making declarations available to C code is to declare them with the :keyword:`api` keyword. You can use this keyword with C functions and extension types. A header file called :file:`modulename_api.h` is produced containing declarations of the functions and extension types, and a function called :func:`import_modulename`. C code wanting to use these functions or extension types needs to include the header and call the :func:`import_modulename` function. The other functions can then be called and the extension types used as usual. If the C code wanting to use these functions is part of more than one shared library or executable, then :func:`import_modulename` function needs to be called in each of the shared libraries which use these functions. If you crash with a segmentation fault (SIGSEGV on linux) when calling into one of these api calls, this is likely an indication that the shared library which contains the api call which is generating the segmentation fault does not call the :func:`import_modulename` function before the api call which crashes. Any public C type or extension type declarations in the Cython module are also made available when you include :file:`modulename_api.h`.: .. literalinclude:: ../../examples/userguide/external_C_code/delorean.pyx .. literalinclude:: ../../examples/userguide/external_C_code/marty.c :language: C .. note:: Any types defined in the Cython module that are used as argument or return types of the exported functions will need to be declared public, otherwise they won't be included in the generated header file, and you will get errors when you try to compile a C file that uses the header. Using the :keyword:`api` method does not require the C code using the declarations to be linked with the extension module in any way, as the Python import machinery is used to make the connection dynamically. However, only functions can be accessed this way, not variables. Note also that for the module import mechanism to be set up correctly, the user must call Py_Initialize() and Py_Finalize(); if you experience a segmentation fault in the call to :func:`import_modulename`, it is likely that this wasn't done. You can use both :keyword:`public` and :keyword:`api` on the same function to make it available by both methods, e.g.:: cdef public api void belt_and_braces() except *: ... However, note that you should include either :file:`modulename.h` or :file:`modulename_api.h` in a given C file, not both, otherwise you may get conflicting dual definitions. If the Cython module resides within a package, then: * The name of the header file contains of the full dotted name of the module. * The name of the importing function contains the full name with dots replaced by double underscores. E.g. a module called :mod:`foo.spam` would have an API header file called :file:`foo.spam_api.h` and an importing function called :func:`import_foo__spam`. Multiple public and API declarations -------------------------------------- You can declare a whole group of items as :keyword:`public` and/or :keyword:`api` all at once by enclosing them in a :keyword:`cdef` block, for example,:: cdef public api: void order_spam(int tons) except * char *get_lunch(float tomato_size) except NULL This can be a useful thing to do in a ``.pxd`` file (see :ref:`sharing-declarations`) to make the module's public interface available by all three methods. Acquiring and Releasing the GIL --------------------------------- Cython provides facilities for acquiring and releasing the Global Interpreter Lock (GIL) (see :term:`our glossary` or `external documentation `_). This may be useful when calling from multi-threaded code into (external C) code that may block, or when wanting to use Python from a (native) C thread callback. Releasing the GIL should obviously only be done for thread-safe code or for code that uses other means of protection against race conditions and concurrency issues. Note that acquiring the GIL is a blocking thread-synchronising operation, and therefore potentially costly. It might not be worth releasing the GIL for minor calculations. Usually, I/O operations and substantial computations in parallel code will benefit from it. .. _nogil: Releasing the GIL ^^^^^^^^^^^^^^^^^ You can release the GIL around a section of code using the ``with nogil`` statement:: with nogil: Code in the body of the with-statement must not manipulate Python objects in any way, and must not call anything that manipulates Python objects without first re-acquiring the GIL. Cython validates these operations at compile time, but cannot look into external C functions, for example. They must be correctly declared as requiring or not requiring the GIL (see below) in order to make Cython's checks effective. Since Cython 3.0, some simple Python statements can be used inside of ``nogil`` sections: ``raise``, ``assert`` and ``print`` (the Py2 statement, not the function). Since they tend to be lone Python statements, Cython will automatically acquire and release the GIL around them for convenience. .. _gil: Acquiring the GIL ^^^^^^^^^^^^^^^^^ A C function that is to be used as a callback from C code that is executed without the GIL needs to acquire the GIL before it can manipulate Python objects. This can be done by specifying ``with gil`` in the function header:: cdef void my_callback(void *data) with gil: ... If the callback may be called from another non-Python thread, care must be taken to initialize the GIL first, through a call to `PyEval_InitThreads() `_. If you're already using :ref:`cython.parallel ` in your module, this will already have been taken care of. The GIL may also be acquired through the ``with gil`` statement:: with gil: .. _gil_conditional: Conditional Acquiring / Releasing the GIL ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Sometimes it is helpful to use a condition to decide whether to run a certain piece of code with or without the GIL. This code would run anyway, the difference is whether the GIL will be held or released. The condition must be constant (at compile time). This could be useful for profiling, debugging, performance testing, and for fused types (see :ref:`fused_gil_conditional`).:: DEF FREE_GIL = True with nogil(FREE_GIL): with gil(False): Declaring a function as callable without the GIL -------------------------------------------------- You can specify :keyword:`nogil` in a C function header or function type to declare that it is safe to call without the GIL.:: cdef void my_gil_free_func(int spam) nogil: ... When you implement such a function in Cython, it cannot have any Python arguments or Python object return type. Furthermore, any operation that involves Python objects (including calling Python functions) must explicitly acquire the GIL first, e.g. by using a ``with gil`` block or by calling a function that has been defined ``with gil``. These restrictions are checked by Cython and you will get a compile error if it finds any Python interaction inside of a ``nogil`` code section. .. NOTE:: The ``nogil`` function annotation declares that it is safe to call the function without the GIL. It is perfectly allowed to execute it while holding the GIL. The function does not in itself release the GIL if it is held by the caller. Declaring a function ``with gil`` (i.e. as acquiring the GIL on entry) also implicitly makes its signature :keyword:`nogil`. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/faq.rst0000644000175100001770000011607500000000000020622 0ustar00runnerdocker00000000000000.. _FAQ: FAQ +++ .. note:: This page has been migrated from the wiki on github and is in the process of being updated; please open an issue or a PR if you find something to improve. Basics ====== Do I need to rename my ``.py`` file to ``.pyx``? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: No. Cython can compile both .py and .pyx files. The difference is that the extended Cython syntax (``cdef …``) is only available in Cython .pyx files and not in Python .py files. But you can use Cython's :ref:`pure Python mode ` to provide type declarations for the compilation, including Python's PEP-484 syntax for type hints. For cases where no interaction with external C libraries is required, this is also the recommended way to type your code, since sticking to .py files with regular Python syntax keeps the whole range of debugging, linting, formatting, profiling etc. tools for Python code available for your software development needs, which usually cannot handle the syntax of .pyx files. ---------- Can Cython generate C code for classes? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: A plain class becomes a fully-fledged Python class. Cython can also generate C classes, where the class data is stored in an efficient C structure at the cost of some additional limitations. ---------- Can I call my Python code from C? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: Yes, easily. Follow the example in `Demos/callback/ `_ in the Cython source distribution. ---------- How do I interface numpy arrays using Cython? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: Follow the :ref:`example `. ---------- How do I compile Cython with subpackages? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: It's highly recommended to arrange Cython modules in exactly the same Python package structure as the Python parts of the code base. As long as you don't keep your Cython code in unusual places, everything should just work. This is in part due to the fact that fully qualified names are resolved at compile time, and moving ``.so`` files around or adding ``__init__`` files between the Cython compile and the Python runtime invocation means that cimports and imports may resolve differently. Failure to do this may result in errors like .pxd files not found or ``'module' object has no attribute '__pyx_capi__'``. ---------- How do I speed up the C compilation? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: Especially with large modules, the code that Cython generates can take the C compiler quite some time to optimise. This is usually ok for production builds, but during development, this can get in the way. It can substantially speed up the C compiler runs to disable the code optimisation, e.g. by setting the environment variable ``CFLAGS="-O0 -ggdb"`` on Linux or MacOS, which also enables full debugging symbols for better crash reports and debugger usage. For MSVC on Windows, you can pass the option ``/Od`` to disable all optimisations. ---------- How do I reduce the size of the binary modules? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: The Python distutils build often includes debugging symbols in the extension modules. The default for gcc is ``-g2``, for example. Disabling them (``CFLAGS=-g0`` for gcc), or setting them to the bare minimum that is required to produce stack traces on crashes (``CFLAGS=-g1`` for gcc), can visibly reduce the size of the binaries. ---------- How well is Unicode supported? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: The support for Unicode is as good as CPython's, but additionally distinguishes between the Python ``str`` (``bytes`` in Python 2.7) and ``unicode`` (always Unicode text) string type. Note that there is no equivalent C type available for Unicode strings, but Cython can automatically convert (encode/decode) from and to encoded C/C++ strings (``char*`` / ``std::string``). See the :ref:`string tutorial `. How do I ...? ============= How do I pickle cdef classes? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: See :ref:`the documentation `. ---------- How do I help Cython find numpy header files? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: If you are seeing errors like these: :: error: numpy/arrayobject.h: No such file or directory error: numpy/ufuncobject.h: No such file or directory You should modify your setup.py file to grab the numpy include directory as follows: :: import numpy ... setup( ... ext_modules = [Extension(..., include_dirs=[numpy.get_include()])] ) ---------- How do I declare numeric or integer C types? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: In most cases, you don't need to. For types declared in ``stdint.h``, just ``cimport`` them from ``libc.stdint`` which comes with Cython, e.g. :: from libc.stdint cimport uint32_t, int64_t cdef int64_t i = 5 For non-standard types, it's enough to provide Cython with a ``ctypedef`` declaration that maps them to a closely related standard C type, e.g. :: cdef extern from "someheader.h": ctypedef unsigned long MySpecialCInt_t cdef MySpecialCInt_t i Make sure you then use the original C (typedef) type name in your code, not the replacement type that you chose for the declaration in Cython! The exact size of the type at C compile time is not that important because Cython generates automatic size detection code (evaluated at C compile time). However, when your code mixes different types in arithmetic code, Cython must know about the correct signedness and the approximate longness in order to infer the appropriate result type of an expression. Therefore, when using a ``ctypedef`` as above, try to come up with a good approximation of the expected C type. Since the largest type wins in mixed arithmetic expressions, it's usually not a problem if the type turns out to be somewhat larger than what the C compiler eventually determines for a given platform. In the worst case, if your replacement type is substantially larger than the real C type (say, 'long long' instead of 'int'), you may end up with slightly slower conversion code. However, if the type is declared too small and Cython considers it smaller than other types it is used together with, Cython may infer the wrong type for an expression and may end up generating incorrect coercion code. You may or may not get a warning by the C compiler in this case. Also note that Cython will consider large integer literals (>32 bit signed) unsafe to use in C code and may therefore use Python objects to represent them. You can make sure a large literal is considered a safe C literal by appending a C suffix, such as 'LL' or 'UL'. Note that a single 'L' is not considered a C suffix in Python 2 code. ---------- How do I declare an object of type bool? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: Well, that depends on whether you want the C99/C++ ``bool`` or the Python ``bool``. Previously, Cython always defaulted to the Python ``bool`` type, which led to hard-to-debug issues when users unsuspectingly used ``bool`` in wrapping C++ code. We decided to make the choice explicit -- you can import whichever you'd like: * For the Python type, do ``from cpython cimport bool``. * For the C++ type, do ``from libcpp cimport bool``. Note that there is also a type called ``bint``, which is essentially a C ``int`` but automatically coerces from and to a Python bool value, i.e. ``cdef object x = some_c_integer_value`` gives either ``True`` or ``False``. ---------- How do I use ``const``? ^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: You can just use it in your code and in your declarations. ---------- How do I use builtins like ``len()`` with the C type ``char *``? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: Cython maps ``len(char*)`` directly to ``strlen()``, which means that it will count the number of characters up to the first 0 byte. Similarly, ``(char*).decode(...)`` is optimised into a C-API call, and applying it to sliced ``char*`` values will skip the length counting step. See the :ref:`string tutorial `. For other Python operations on ``char*``, the generated code may be inefficient, as a temporary object may have to get created. If you notice this for your code and think that Cython can do better, please speak up on the mailing list. ---------- How do I make a cdef'd class that derives from a builtin Python type such as list? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: You can just use the type as a base class in your cdef class declaration. The only exception are the types bytes ('str' in Python 2) and tuple, which can only be subtyped by Python classes (not cdef classes). This is considered a `bug `_. However, you can safely subtype 'unicode' and 'list' instead. ---------- How do I raise an exception in Cython code that will be visible to ancestor (in the callstack) CPython code? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: If your cdef or cpdef function or method does not declare a return type (as is normal in CPython code), then you get exceptions without any extra effort. If your cdef or cpdef function or method declares a C-style return type, see :ref:`error_return_values`. ---------- How do I declare a global variable? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: :: global variable ---------- How do I assign to a global variable? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: You need to declare the variable to be global (see above) before trying to assign to it. Often this occurs when one has code like :: cdef int *data def foo(n): data = malloc(n * sizeof(int)) This will result in an error "Cannot convert ``'int *'`` to Python object." This is because, as in Python, assignment declares a local variable. Instead, you must write :: cdef int *data def foo(n): global data data = malloc(n * sizeof(int)) See http://docs.python.org/tutorial/classes.html#python-scopes-and-namespaces for more details. ---------- How do I create objects or apply operators to locally created objects as pure C code? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: For methods like ``__init__`` and ``__getitem__`` the Python calling convention is mandatory and identical for all objects, so Cython cannot provide a major speed-up for them. To instantiate an extension type, however, the fastest way is to actually use the normal Python idiom of calling the ``__new__()`` method of a type: .. code:: python cdef class ExampleClass: cdef int _value def __init__(self): # calling "__new__()" will not call "__init__()" ! raise TypeError("This class cannot be instantiated from Python") cdef ExampleClass _factory(): cdef ExampleClass instance = ExampleClass.__new__(ExampleClass) instance._value = 1 return instance Note that this has similar restrictions as the normal Python code: it will not call the ``__init__()`` method (which makes it quite a bit faster). Also, while all Python class members will be initialised to None, you have to take care to initialise the C members. Either the ``__cinit__()`` method or a factory function like the one above are good places to do so. How do I implement a single class method in a Cython module? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: As of Cython 3.0, Cython-defined methods bind by default. That means that the following should work: :: #!python import cython_module class A(object): method = cython_module.optimized_method ---------- How do I pass string buffers that may contain 0 bytes to Cython? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: See the :ref:`string tutorial `. You need to use either a Python byte string object or a char*/length pair of variables. The normal way to convert a char* to a Python byte string is as follows: .. code:: python #!python cdef char* s = "a normal C byte string" cdef bytes a_python_byte_string = s However, this will not work for C strings that contain 0 bytes, as a 0 byte is the normal C way of terminating a string. So the above method will cut the string at the first 0 byte. To handle this case correctly, you have to specify the total length of the string that you want to convert: .. code:: python cdef char* s = "an unusual \0 containing C byte string" a_python_byte_string = s[:21] # take the first 21 bytes of the string, including the \0 byte Note that this will not handle the case that the specified slice length is longer than the actual C string. This code will crash if the allocated memory area of the ``char*`` is shorter. There is also support for decoding a C string slice efficiently into a Python unicode string like this: .. code:: python # -*- coding: ISO8859-15 cdef char* s = "a UTF-8 encoded C string with fünny chäräctörs" cdef Py_ssize_t byte_length = 46 a_python_unicode_string = s[:byte_length].decode('ISO8859-15') ---------- How do I pass a Python string parameter on to a C library? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ See the `string tutorial `. **Answer**: It depends on the semantics of the string. Imagine you have this C function: :: cdef extern from "something.h": cdef int c_handle_data(char* data, int length) For **binary data**, you can simply require byte strings at the API level, so that this will work: :: def work_with_binary_data(bytes binary_data): c_handle_data(binary_data, len(binary_data)) It will raise an error (with a message that may or may not be appropriate for your use case) if users pass other things than a byte string. For **textual data**, however, you must handle Unicode data input. What you do with it depends on what your C function accepts. For example, if it requires UTF-8 encoded byte sequences, this might work: :: def work_with_text_data(text): if not isinstance(text, unicode): raise ValueError("requires text input, got %s" % type(text)) utf8_data = text.encode('UTF-8') c_handle_data( utf8_data, len(utf8_data) ) Note that this also accepts subtypes of the Python unicode type. Typing the "text" parameter as "unicode" will not cover this case. ---------- How do I use variable args? ^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: For a regular function, just use ``*args`` as in Python. For a C-function it can't be done cleanly yet, but you can use the C ``va_args`` mechanism: :: cdef extern from "stdarg.h": ctypedef struct va_list: pass ctypedef struct fake_type: pass void va_start(va_list, void* arg) void* va_arg(va_list, fake_type) void va_end(va_list) fake_type int_type "int" cdef int foo(int n, ...): print "starting" cdef va_list args va_start(args, n) while n != 0: print n n = va_arg(args, int_type) va_end(args) print "done" def call_foo(): foo(1, 2, 3, 0) foo(1, 2, 0) ---------- How do I make a standalone binary from a Python program using cython? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: You probably want a recipe something like this: .. highlight::bash PYVERSION=3.9 cython --embed foobar.py -o foobar.c $(CC) -I /usr/include/python$(PYVERSION) foobar.c -lpython$(PYVERSION) -o foobar The magic is the ``--embed`` option, which embeds a copy of the Python interpreter main in the generated C. You'll want to change ``'foobar'`` to reflect the name of your script, of course, and ``PYVERSION`` as appropriate. More details can be found :ref:`in the embedding documentation `. ---------- How do I have to wrap C code that uses the restrict qualifier? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: There currently is no way of doing this directly into C code. Cython does not understand the restrict qualifier. However you can wrap your way around it. See the following example code: slurp.h ------- :: #include #include #include #include #include int th_match(char *, char *); cslurp.c -------- :: #include "slurp.h" int th_match(char *string, char *pattern) { int status; regex_t re; if(regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0) { return 0; } status = regexec(&re, string, (size_t)0, NULL, 0); regfree(&re); if(status != 0) return 0; return 1; } slurp.pyx --------- :: cdef extern from "slurp.h": int th_match(char *st, char *pt) class Slurp: ''' This is a simple, but optimized PEG (Parser Expression Group) parser. It will parse through anything you hand it provided what you hand it has a readline() method. Example: import sys from thci.ext import slurp o = slurp.Slurp() o.register_trigger('^root:.*:.*:.*:.*$', sys.stdout.write) o.process(open('/etc/passwd', 'r')) ''' def __init__(self): ''' __init__(self) ''' self.map = {} self.idx = 0 def register_trigger(self, patt=None, cback=None, args=None): ''' register_trigger(self, patt=None, cback=None, args=None) ''' if patt == None or cback == None: return False if args == None: args = False self.map[self.idx] = (patt, cback, args) self.idx += 0 return True def process(self, fp=None): ''' process(self, fp=None) ''' if fp == None: return False while True: buf = fp.readline() if not buf: break for patt, cback, args in self.map.values(): if th_match(buf, patt) == True: if args == False: cback(buf.strip()) else: cback(buf.strip(), args) This avoids the problems using the restrict qualifiers (Such as are needed with the functions declared in regex.h on FreeBSD [at least 7.X]) by allowing the C compiler to handle things going from C to C, Cython's support for this even using the "const trick" doesn't seem to behave properly (at least as of 0.12). the following commands will generate your compiled module from the above source: :: cython -o slurp.c slurp.pyx cc -shared -I/usr/include -I./ -I/usr/local/include/python2.5 -L/usr/local/lib -lpthread -lpython2.5 cslurp.c slurp.c -o slurp.so It is also possible to use distutils by adding the file cslurp.c (or your files name) to the list of files to be compiled for the extension. ---------- How do I automatically generate Cython definition files from C (.h) or C++ (.hpp) header files ? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: Several people have created scripts to parse header files and automatically produce Cython bindings. **autowrap** autowrap automatically generates python extension modules for wrapping C++ libraries based on annotated (commented) cython pxd files. Current features include wrapping of template classes, enums, free functions and static methods as well as converters from Python data types to (many) STL containers and back. Finally, also manually written Cython code can be incorporated for wrapping code. http://github.com/uweschmitt/autowrap **python-autopxd** Automatically generate pxd from C headers. It uses [pycparser](https://github.com/eliben/pycparser) to parse the definitions, so the only requirement beyond python dependencies is a C preprocessor on PATH. https://github.com/gabrieldemarmiesse/python-autopxd2 (A friendly fork of python-autopxd, supporting recent Python versions) https://github.com/tarruda/python-autopxd (original version) ---------- How do I run doctests in Cython code (pyx files)? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: Cython generates a ``__test__`` dictionary in the module that contains all docstrings of Python visible functions and classes that look like doctests (i.e. that contain ``>>>``). The doctest module will properly pick this up and run the doctests. This module (let's call it "cydoctest") offers a Cython-compatible workaround. :: #!python """ Cython-compatible wrapper for doctest.testmod(). Usage example, assuming a Cython module mymod.pyx is compiled. This is run from the command line, passing a command to Python: python -c "import cydoctest, mymod; cydoctest.testmod(mymod)" (This still won't let a Cython module run its own doctests when called with "python mymod.py", but it's pretty close. Further options can be passed to testmod() as desired, e.g. verbose=True.) """ import doctest import inspect def _from_module(module, object): """ Return true if the given object is defined in the given module. """ if module is None: return True elif inspect.getmodule(object) is not None: return module is inspect.getmodule(object) elif inspect.isfunction(object): return module.__dict__ is object.func_globals elif inspect.isclass(object): return module.__name__ == object.__module__ elif hasattr(object, '__module__'): return module.__name__ == object.__module__ elif isinstance(object, property): return True # [XX] no way not be sure. else: raise ValueError("object must be a class or function") def fix_module_doctest(module): """ Extract docstrings from cython functions, that would be skipped by doctest otherwise. """ module.__test__ = {} for name in dir(module): value = getattr(module, name) if inspect.isbuiltin(value) and isinstance(value.__doc__, str) and _from_module(module, value): module.__test__[name] = value.__doc__ def testmod(m=None, *args, **kwargs): """ Fix a Cython module's doctests, then call doctest.testmod() All other arguments are passed directly to doctest.testmod(). """ fix_module_doctest(m) doctest.testmod(m, *args, **kwargs) ---------- How do I work around the ``-Wno-long-double error`` when installing on OS X? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: This is a known issue in OS X with some Python installs. It has nothing to do with Cython, and you will run on the same trouble **every** time you want to build an C extension module. This is the most sane (if not the only) way to fix it: 1) Enter Python prompt, and type this: :: >>> from distutils import sysconfig >>> sysconfig.get_makefile_filename() That should output the full path of a 'Makefile'... Open that file with any text editor and remove all occurrences of '-Wno-long-double' flag. ---------- How do I work around the "unable to find vcvarsall.bat" error when using MinGW as the compiler (on Windows)? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: This error means that Python cannot find the C++ compiler on your system. Normally, this is managed by distutils, but it may happen that it's not yet up-to-date. For example, you may be using this in setup.py: :: from distutils.core import setup from distutils.extension import Extension Instead, you can try to load setuptools, which will monkey-patch distutils to find vcvarsall.bat: :: try: from setuptools import setup from setuptools import Extension except ImportError: from distutils.core import setup from distutils.extension import Extension In IPython, you can just import setuptools, like this: :: # First cell: import setuptools %load_ext Cython # Second cell: %%cython -a import cython cimport cython cdef int alpha = 255 print alpha If this is unsuccessful, try the following workarounds. If no python libraries are imported, define the compiler by adding the following statement: :: --compiler=mingw32 Therefore, the line should read: :: python pyprog.py build_ext --compiler=mingw32 --inplace This, however, does not solve the issue when using the pyximport method (see the tutorial). Alternatively, the following patch can be applied. **NOTE: This is untested.** Open the file pyximport/pyxbuild.py and add the four lines marked with "+" at the appropriate place. .. highlight::diff diff -r 7fbe931e5ab7 pyximport/pyxbuild.py --- a/pyximport/pyxbuild.py Wed Sep 16 15:50:00 2009 +0200 +++ b/pyximport/pyxbuild.py Fri Sep 18 12:39:51 2009 -0300 @@ -55,6 +55,11 @@ build = dist.get_command_obj('build') build.build_base = pyxbuild_dir + config_files = dist.find_config_files() + try: config_files.remove('setup.cfg') + except ValueError: pass + dist.parse_config_files(config_files) + try: ok = dist.parse_command_line() except DistutilsArgError: Finally, if this does not work, create a file called "pydistutils.cfg" in notepad and give it the contents: :: [build_ext] compiler=mingw32 Save this to the home directory, which can be found by typing at the command prompt: :: import os os.path.expanduser('~') Explanations ============ What is the difference between a ``.pxd`` and ``.pxi`` file? When should either be used? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SHORT **Answer**: You should always use .pxd files for declarations and .pxi files only for code that you want to include. MEDIUM **Answer**: A .pxd files are lists of declarations, .pxi files are textually included, and their use for declarations is a historical artifact of the way common declarations were shared before .pxd files existed. LONG **Answer**: A .pxd file is a declaration file, and is used to declare classes, methods, etc. in a C extension module, (typically as implemented in a .pyx file of the same name). It can contain declarations only, i.e. no executable statements. One can ``cimport`` things from .pxd files just as one would import things in Python. Two separate modules cimporting from the same .pxd file will receive identical objects. A .pxi file is an include file and is textually included (similar to the C ``#include`` directive) and may contain any valid Cython code at the given point in the program. It may contain implementations (e.g. common cdef inline functions) which will be copied into both files. For example, this means that if I have a class A declared in a.pxi, and both b.pyx and c.pyx do ``include a.pxi`` then I will have two distinct classes b.A and c.A. Interfaces to C libraries (including the Python/C API) have usually been declared in .pxi files (as they are not associated to a specific module). It is also re-parsed at every invocation. Now that ``cimport *`` can be used, there is no reason to use .pxi files for external declarations. ---------- What is better, a single big module or multiple separate modules? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: In short, one big module is clumsy to handle but allows broader optimisations by the C compiler. The compile time might actually decrease for multiple modules since the build can be parallelised. The "build_ext" command in distutils has a "-j" option since Py3.5. Also, smaller modules are usually faster to compile by the C compiler, because some optimisations may involve non-linear overhead. The distribution size, and the size per module, will probably increase when splitting a module because there are some things that Cython has to copy into each module. There is a `feature request `_ that would mitigate this. C calls between modules are slightly slower than C calls inside of a module, simply because the C compiler cannot optimise and/or inline them. You will have to use shared .pxd declarations for them, which will then call through a function pointer. If modules use a functional split, however, this should not hurt too much. It might still be a good idea to create a shared .pxd file (or .pxi) with inline functions for performance critical code that is used in multiple modules. When splitting an existing module, you will also have to deal with the API changes. Leaving some legacy imports here and there, or turning a module into a package that merges the module namespaces back together via imports, might prevent code breakage for users of your original module when you move names around and redistribute them across multiple modules. ---------- What is the difference between ``PyObject*`` and ``object``? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: A variable of type ``PyObject*`` is a simple C pointer, just like ``void*``. It is not reference counted, which is sometimes referred to as a borrowed reference. An ``object`` variable is an owned reference to a Python object. You can convert one into the other by casting: :: from cpython.ref cimport PyObject py_object = [1,2,3] cdef PyObject* ptr = py_object cdef object l = ptr # this increases the reference count to the list Note that the lifetime of the object is only bound to its owned references, not to any C pointers that happen to point to it. This means that ``ptr`` in the example above becomes invalid as soon as the last reference to the object dies: :: py_object = [1,2,3] cdef PyObject* ptr = py_object py_object = None # last reference to list dies here # ptr now points to a dead object print(ptr) # expect a crash here! Pointers are commonly used when passing objects through C callbacks, e.g. :: cdef int call_it_from_c(void* py_function, void* args): py_args = args if args is not NULL else () return (py_function)(*py_args) def py_func(a,b,c): print(a,b,c) return -1 args = [1,2,3] call_it_from_c(py_func, args) Once again, care must be taken to keep the objects alive as long as any pointers to them are still in use. ---------- Why does Cython not always give errors for uninitialized variables? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: Cython does some static checks for variable initialization before use during compile time, but these are very basic, as Cython has no definite knowledge what paths of code will be taken at runtime: Consider the following .. code:: python def testUnboundedLocal1(): if False: c = 1 print c def testUnboundedLocal2(): print c With CPython, both functions lead to the following exception: :: NameError: global name 'c' is not defined With Cython, the first variant prints "None", the second variant leads to a compile time error. Both behaviours differ from CPython's. This is considered a BUG and will change in the future. ---------- Why does a function with cdef'd parameters accept None? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: It is a fairly common idiom in Python to use ``None`` as a way to mean "no value" or "invalid". This doesn't play well with C, as ``None`` is not compatible with any C type. To accommodate for this, the default behavior is for functions with cdefed parameters to also accept None. This behavior was inherited from Pyrex, and while it has been proposed that it be changed, it will likely stay (at least for a while) for backwards capability. You have four choices for how to handle ``None`` in your code: 1. In Cython 3.x, use Python type annotations instead of Cython syntax. Python type annotations distinguish between ``func(x: MyType)`` and ``func(x: Optional[MyType])``, where the first **disallows** ``None`` and the second explicitly allows it. ``func(x: MyType = None)`` allows it as well because it is explicitly required by the provided default value. 2. If you want to consider ``None`` invalid input, then you need to write code that checks for it, and raised an appropriate exception. 3. If you want Cython to raise an exception if ``None`` is passed in for an extension type parameter, you can use the ``not None`` declaration: :: def foo(MyClass val not None): <...> which is a short-hand for :: def foo(MyClass val): if val is None: raise <...> <...> 4. You can also put ``#cython: nonecheck=True`` at the top of your file and all access will be checked for None, but it will slow things down, as it is adding a check on every access, rather that once on function call. About the project ================= Is Cython a Python implementation? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: Not officially, no. However, it compiles almost all existing Python code, which gets it pretty close to a real Python implementation. The result depends on the CPython runtime, though, which we consider a major compatibility advantage. In any case, it is an official goal for Cython to compile regular Python code and run (most of) the normal Python test suite - obviously faster than CPython. ;-) ---------- Is Cython faster than CPython? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: For most things, yes. For example, a Cython compiled pybench runs more than 30% faster in total, while being 60-90% faster on control structures like ``if-elif-else`` and ``for``-loops. We regularly run the tests from the CPython benchmark suite (which includes Django templates, 2to3, computational benchmarks and other applications) and most of them work out-of-the-box without modifications or static typing, with a performance increase of 20-60%. However the main advantage of Cython is that it scales very well to even greater performance requirements. For code that operates heavily on common builtin types (lists, dicts, strings), Cython can often speed up processing loops by factors. For numerical code, speed-ups of 100-1000 times compared to CPython are not unusual, and are achieved by simply adding static type declarations to performance critical parts of the code, thus trading Python's dynamic typing for speed. As this can be done at any granularity in the code, Cython makes it easy to write simple Python code that is fast enough, and just tune the critical 5% of your code into maximum performance by using static C types in just the right places. ---------- What Python versions does Cython support? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: From Cython 0.21 on, the supported versions are 2.6, 2.7 and 3.4+, with Python 2.6 being phased out implicitly due to lack of testing capabilities. Cython 3.0 removes support for Python 2.6 completely and requires either Python 2.7 or Python 3.4+. Python 2.x support is scheduled for removal in Cython 3.1, which will probably require Python 3.6 or later at the time of its release. The C code generated by Cython is portable and builds in all supported Python versions. All supported CPython release series are tested regularly. New CPython versions are usually supported before they are released. The source code that Cython compiles can use both Python 2 and Python 3 syntax, defaulting to Python 2 syntax in Cython 0.x and Python 3 syntax in Cython 3.x and later. When compiling Cython modules (.pyx files) in Python 2 mode, most Python 3 syntax features are available by default if they do not interfere with Python 2 syntax (as in Python 2.7), but the general language semantics are defined as in Python 2. When compiling Python modules (.py files), the special Cython syntax (such as the ``cdef`` keyword) is not available. For both input types, the language level can be set to Python 3 by either passing the "-3" option to the compiler, or by putting :: # cython: language_level=3 at the top of the module file (within the first comment and before any code or empty lines). With Cython 3.x, compiling Python 2 code requires the option "-2" or the directive ``language_level=2``. By default, with the Python 3 semantics in Cython 3.0, ``print()`` is a function, loop variables in list comprehensions do not leak into the outer scope, etc. This is equivalent to ``language_level=3str`` or the option ``--3str``. If you instead select ``language_level=3``, then, additionally, unprefixed strings are always unicode strings. ---------- What's the license situation of Cython's output? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: You can use the output of Pyrex/Cython however you like (and license it how you like - be it BSD, public domain, GPL, all rights reserved, whatever). More details: The Python License is different from the GPL used for GCC, for example. GCC requires a special exception clause for its output as it is *linked* against the library part of GCC, i.e. against GPL software, which triggers the GPL restrictions. Cython doesn't do anything similar, and linking against Python is not restricted by the Python License, so the output belongs to the User, no other rights or restrictions involved. Also, all of the copyright holders of Pyrex/Cython stated in mailing list that people are allowed to use the output of Pyrex/Cython however they would like. ---------- How do I cite Cython in an academic paper? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: If you mention Cython, the simplest way to reference us is to add the URL to our website in a footnote. You may also choose to reference our software project in a more formal way, such as :: R. Bradshaw, S. Behnel, D. S. Seljebotn, G. Ewing, et al., The Cython compiler, http://cython.org. (the list of author names were taken from setup.py) For a yet more formal citation, there is a `journal paper `_ on Cython. If you wish to cite it, here's the Bibtex: :: @ARTICLE{ behnel2010cython, author={Behnel, S. and Bradshaw, R. and Citro, C. and Dalcin, L. and Seljebotn, D.S. and Smith, K.}, journal={Computing in Science Engineering}, title={Cython: The Best of Both Worlds}, year={2011}, month=march-april , volume={13}, number={2}, pages={31 -39}, keywords={Cython language;Fortran code;Python language extension;numerical loops;programming language;C language;numerical analysis;}, doi={10.1109/MCSE.2010.118}, ISSN={1521-9615}, } ---------- What is the relation between Cython and Pyrex? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Answer**: Cython started originally based on a previous project called Pyrex, developed primarily by Greg Ewing. Years later, Pyrex development has effectively stopped, whereas Cython has kept adding new features and support for new Python versions. As of 2023, Pyrex is only of historical interest. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/fusedtypes.rst0000644000175100001770000003551700000000000022247 0ustar00runnerdocker00000000000000.. highlight:: cython .. _fusedtypes: *********************** Fused Types (Templates) *********************** .. include:: ../two-syntax-variants-used Fused types allow you to have one type definition that can refer to multiple types. This allows you to write a single static-typed cython algorithm that can operate on values of multiple types. Thus fused types allow `generic programming`_ and are akin to templates in C++ or generics in languages like Java / C#. .. _generic programming: https://en.wikipedia.org/wiki/Generic_programming .. Note:: Fused types are not currently supported as attributes of extension types. Only variables and function/method arguments can be declared with fused types. Quickstart ========== .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/fusedtypes/char_or_float.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/fusedtypes/char_or_float.pyx This gives: .. code-block:: pycon >>> show_me() char -128 float 128.0 ``plus_one(a)`` "specializes" the fused type ``char_or_float`` as a ``char``, whereas ``plus_one(b)`` specializes ``char_or_float`` as a ``float``. Declaring Fused Types ===================== Fused types may be declared as follows: .. tabs:: .. group-tab:: Pure Python .. code-block:: python my_fused_type = cython.fused_type(cython.int, cython.float) .. group-tab:: Cython .. code-block:: cython ctypedef fused my_fused_type: int double This declares a new type called ``my_fused_type`` which can be *either* an ``int`` *or* a ``double``. Only names may be used for the constituent types, but they may be any (non-fused) type, including a typedef. I.e. one may write: .. tabs:: .. group-tab:: Pure Python .. code-block:: python my_double = cython.typedef(cython.double) my_fused_type = cython.fused_type(cython.int, my_double) .. group-tab:: Cython .. code-block:: cython ctypedef double my_double ctypedef fused fused_type: int my_double Using Fused Types ================= Fused types can be used to declare parameters of functions or methods: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc def cfunc(arg: my_fused_type): return arg + 1 .. group-tab:: Cython .. code-block:: cython cdef cfunc(my_fused_type arg): return arg + 1 If the same fused type appears more than once in the function arguments, then they will all have the same specialised type: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc def cfunc(arg1: my_fused_type, arg2: my_fused_type): # arg1 and arg2 always have the same type here return arg1 + arg2 .. group-tab:: Cython .. code-block:: cython cdef cfunc(my_fused_type arg1, my_fused_type arg2): # arg1 and arg2 always have the same type here return arg1 + arg2 Here, the type of both parameters is either an int, or a double (according to the previous examples), because they use the same fused type name ``my_fused_type``. Mixing different fused types (or differently named fused types) in the arguments will specialise them independently: .. tabs:: .. group-tab:: Pure Python .. code-block:: python def func(x: A, y: B): ... .. group-tab:: Cython .. code-block:: cython def func(A x, B y): ... This will result in specialized code paths for all combinations of types contained in ``A`` and ``B``, e.g.: .. tabs:: .. group-tab:: Pure Python .. code-block:: python my_fused_type = cython.fused_type(cython.int, cython.double) my_fused_type2 = cython.fused_type(cython.int, cython.double) @cython.cfunc def func(a: my_fused_type, b: my_fused_type2): # a and b may have the same or different types here print("SAME!" if my_fused_type is my_fused_type2 else "NOT SAME!") return a + b .. group-tab:: Cython .. code-block:: cython ctypedef fused my_fused_type: int double ctypedef fused my_fused_type2: int double cdef func(my_fused_type a, my_fused_type2 b): # a and b may have the same or different types here print("SAME!" if my_fused_type is my_fused_type2 else "NOT SAME!") return a + b .. Note:: A simple typedef to rename the fused type does not currently work here. See Github issue :issue:`4302`. Fused types and arrays ---------------------- Note that specializations of only numeric types may not be very useful, as one can usually rely on promotion of types. This is not true for arrays, pointers and typed views of memory however. Indeed, one may write: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc def myfunc(x: A[:, :]): ... # and @cython.cfunc cdef otherfunc(x: cython.pointer(A)): ... .. group-tab:: Cython .. code-block:: cython cdef myfunc(A[:, :] x): ... # and cdef otherfunc(A *x): ... Following code snippet shows an example with pointer to the fused type: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/fusedtypes/pointer.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/fusedtypes/pointer.pyx .. Note:: In Cython 0.20.x and earlier, the compiler generated the full cross product of all type combinations when a fused type was used by more than one memory view in a type signature, e.g. :: def myfunc(A[:] a, A[:] b): # a and b had independent item types in Cython 0.20.x and earlier. ... This was unexpected for most users, unlikely to be desired, and also inconsistent with other structured type declarations like C arrays of fused types, which were considered the same type. It was thus changed in Cython 0.21 to use the same type for all memory views of a fused type. In order to get the original behaviour, it suffices to declare the same fused type under different names, and then use these in the declarations:: ctypedef fused A: int long ctypedef fused B: int long def myfunc(A[:] a, B[:] b): # a and b are independent types here and may have different item types ... To get only identical types also in older Cython versions (pre-0.21), a ``ctypedef`` can be used:: ctypedef A[:] A_1d def myfunc(A_1d a, A_1d b): # a and b have identical item types here, also in older Cython versions ... Selecting Specializations ========================= You can select a specialization (an instance of the function with specific or specialized (i.e., non-fused) argument types) in two ways: either by indexing or by calling. .. _fusedtypes_indexing: Indexing -------- You can index functions with types to get certain specializations, i.e.: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/fusedtypes/indexing.py :caption: indexing.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/fusedtypes/indexing.pyx :caption: indexing.pyx Indexed functions can be called directly from Python: .. code-block:: pycon >>> import cython >>> import indexing cfunc called: double 5.0 double 1.0 cpfunc called: float 1.0 double 2.0 func called: float 1.0 double 2.0 >>> indexing.cpfunc[cython.float, cython.float](1, 2) cpfunc called: float 1.0 float 2.0 >>> indexing.func[cython.float, cython.float](1, 2) func called: float 1.0 float 2.0 If a fused type is used as a component of a more complex type (for example a pointer to a fused type, or a memoryview of a fused type), then you should index the function with the individual component and not the full argument type: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc def myfunc(x: cython.pointer(A)): ... # Specialize using int, not int * myfunc[cython.int](myint) .. group-tab:: Cython .. code-block:: cython cdef myfunc(A *x): ... # Specialize using int, not int * myfunc[int](myint) For memoryview indexing from python space we can do the following: .. tabs:: .. group-tab:: Pure Python .. code-block:: python my_fused_type = cython.fused_type(cython.int[:, ::1], cython.float[:, ::1]) def func(array: my_fused_type): print("func called:", cython.typeof(array)) my_fused_type[cython.int[:, ::1]](myarray) .. group-tab:: Cython .. code-block:: cython ctypedef fused my_fused_type: int[:, ::1] float[:, ::1] def func(my_fused_type array): print("func called:", cython.typeof(array)) my_fused_type[cython.int[:, ::1]](myarray) The same goes for when using e.g. ``cython.numeric[:, :]``. Calling ------- A fused function can also be called with arguments, where the dispatch is figured out automatically: .. tabs:: .. group-tab:: Pure Python .. code-block:: python def main(): p1: cython.double = 1.0 p2: cython.float = 2.0 cfunc(p1, p1) # prints "cfunc called: double 1.0 double 1.0" cpfunc(p1, p2) # prints "cpfunc called: double 1.0 float 2.0" .. group-tab:: Cython .. code-block:: cython def main(): cdef double p1 = 1.0 cdef float p2 = 2.0 cfunc(p1, p1) # prints "cfunc called: double 1.0 double 1.0" cpfunc(p1, p2) # prints "cpfunc called: double 1.0 float 2.0" For a ``cdef`` or ``cpdef`` function called from Cython this means that the specialization is figured out at compile time. For ``def`` functions the arguments are typechecked at runtime, and a best-effort approach is performed to figure out which specialization is needed. This means that this may result in a runtime ``TypeError`` if no specialization was found. A ``cpdef`` function is treated the same way as a ``def`` function if the type of the function is unknown (e.g. if it is external and there is no cimport for it). The automatic dispatching rules are typically as follows, in order of preference: * try to find an exact match * choose the biggest corresponding numerical type (biggest float, biggest complex, biggest int) Built-in Fused Types ==================== There are some built-in fused types available for convenience, these are:: cython.integral # short, int, long cython.floating # float, double cython.numeric # short, int, long, float, double, float complex, double complex Casting Fused Functions ======================= .. note:: Pointers to functions are currently not supported by pure Python mode. (GitHub issue :issue:`4279`) Fused ``cdef`` and ``cpdef`` functions may be cast or assigned to C function pointers as follows:: cdef myfunc(cython.floating, cython.integral): ... # assign directly cdef object (*funcp)(float, int) funcp = myfunc funcp(f, i) # alternatively, cast it ( myfunc)(f, i) # This is also valid funcp = myfunc[float, int] funcp(f, i) Type Checking Specializations ============================= Decisions can be made based on the specializations of the fused parameters. False conditions are pruned to avoid invalid code. One may check with ``is``, ``is not`` and ``==`` and ``!=`` to see if a fused type is equal to a certain other non-fused type (to check the specialization), or use ``in`` and ``not in`` to figure out whether a specialization is part of another set of types (specified as a fused type). In example: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/fusedtypes/type_checking.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/fusedtypes/type_checking.pyx .. _fused_gil_conditional: Conditional GIL Acquiring / Releasing ===================================== Acquiring and releasing the GIL can be controlled by a condition which is known at compile time (see :ref:`gil_conditional`). This is most useful when combined with fused types. A fused type function may have to handle both cython native types (e.g. cython.int or cython.double) and python types (e.g. object or bytes). Conditional Acquiring / Releasing the GIL provides a method for running the same piece of code either with the GIL released (for cython native types) and with the GIL held (for python types): .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/fusedtypes/conditional_gil.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/fusedtypes/conditional_gil.pyx __signatures__ ============== Finally, function objects from ``def`` or ``cpdef`` functions have an attribute ``__signatures__``, which maps the signature strings to the actual specialized functions. This may be useful for inspection: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/fusedtypes/indexing.py :lines: 1-9,14-16 :caption: indexing.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/fusedtypes/indexing.pyx :lines: 1-9,14-16 :caption: indexing.pyx .. code-block:: pycon >>> from indexing import cpfunc >>> cpfunc.__signatures__, ({'double|double': , 'double|float': , 'float|double': , 'float|float': },) Listed signature strings may also be used as indices to the fused function, but the index format may change between Cython versions .. code-block:: pycon >>> specialized_function = cpfunc["double|float"] >>> specialized_function(5.0, 1.0) cpfunc called: double 5.0 float 1.0 However, the better way how to index is by providing list of types as mentioned in :ref:`fusedtypes_indexing` section. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/glossary.rst0000644000175100001770000000655000000000000021712 0ustar00runnerdocker00000000000000Glossary ======== .. glossary:: Extension type "Extension type" can refer to either a Cython class defined with ``cdef class`` or ``@cclass``, or more generally to any Python type that is ultimately implemented as a native C struct (including the built-in types like `int` or `dict`). Dynamic allocation or Heap allocation A C variable allocated with ``malloc`` (in C) or ``new`` (in C++) is `allocated dynamically/heap allocated `_. Its lifetime is until the user deletes it explicitly (with ``free`` in C or ``del`` in C++). This can happen in a different function than the allocation. Global Interpreter Lock or GIL A lock inside the Python interpreter to ensure that only one Python thread is run at once. This lock is purely to ensure that race conditions do not corrupt internal Python state. Python objects cannot be manipulated unless the GIL is held. It is most relevant to Cython when writing code that should be run in parallel. If you are not aiming to write parallel code then there is usually no benefit to releasing the GIL in Cython. You should not use the GIL as a general locking mechanism in your code since many operations on Python objects can lead to it being released and to control being passed to another thread. Also see the `CPython project's glossary entry `_. pointer A **pointer** is a variable that stores the address of another variable (i.e. direct address of the memory location). They allow for dynamic memory allocation and deallocation. They can be used to build dynamic data structures. `Read more `__. Python object When using Python, the contents of every variable is a Python object (including Cython extension types). Key features of Python objects are that they are passed *by reference* and that their lifetime is *managed* automatically so that they are destroyed when no more references exist to them. In Cython, they are distinct from C types, which are passed *by value* and whose lifetime is managed depending on whether they are allocated on the stack or heap. To explicitly declare a Python object variable in Cython use ``cdef object abc``. Internally in C, they are referred to as ``PyObject*``. Stack allocation A C variable declared within a function as ``cdef SomeType a`` is said to be allocated on the stack. It exists for the duration of the function only. Typed memoryview A useful Cython type for getting quick access to blocks of memory. A memoryview alone does not actually own any memory. However, it can be initialized with a Python object that supports the `buffer protocol`_ (typically "array" types, for example a Numpy array). The memoryview keeps a reference to that Python object alive and provides quick access to the memory without needing to go through the Python API of the object and its :meth:`__getitem__` / :meth:`__setitem__` methods. For more information, see :ref:`memoryviews`. .. _buffer protocol: https://docs.python.org/3/c-api/buffer.html ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/index.rst0000644000175100001770000000105500000000000021151 0ustar00runnerdocker00000000000000Users Guide =========== Contents: .. toctree:: :maxdepth: 2 language_basics extension_types special_methods sharing_declarations external_C_code source_files_and_compilation early_binding_for_speed wrapping_CPlusPlus fusedtypes pypy migrating_to_cy30 limitations pyrex_differences memoryviews buffer parallelism debugging numpy_tutorial numpy_ufuncs numpy_pythran nogil troubleshooting faq Indices and tables ------------------ * :ref:`genindex` * :ref:`modindex` * :ref:`search` ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/language_basics.rst0000644000175100001770000016361100000000000023160 0ustar00runnerdocker00000000000000.. highlight:: cython .. _language-basics: .. _struct: .. _union: .. _enum: .. _ctypedef: ***************** Language Basics ***************** .. include:: ../two-syntax-variants-used .. _declaring_data_types: Declaring Data Types ==================== As a dynamic language, Python encourages a programming style of considering classes and objects in terms of their methods and attributes, more than where they fit into the class hierarchy. This can make Python a very relaxed and comfortable language for rapid development, but with a price - the 'red tape' of managing data types is dumped onto the interpreter. At run time, the interpreter does a lot of work searching namespaces, fetching attributes and parsing argument and keyword tuples. This run-time ‘late binding’ is a major cause of Python’s relative slowness compared to ‘early binding’ languages such as C++. However with Cython it is possible to gain significant speed-ups through the use of ‘early binding’ programming techniques. .. note:: Typing is not a necessity Providing static typing to parameters and variables is convenience to speed up your code, but it is not a necessity. Optimize where and when needed. In fact, typing can *slow down* your code in the case where the typing does not allow optimizations but where Cython still needs to check that the type of some object matches the declared type. .. _c_variable_and_type_definitions: C variable and type definitions =============================== C variables can be declared by * using the Cython specific :keyword:`cdef` statement, * using PEP-484/526 type annotations with C data types or * using the function ``cython.declare()``. The :keyword:`cdef` statement and ``declare()`` can define function-local and module-level variables as well as attributes in classes, but type annotations only affect local variables and attributes and are ignored at the module level. This is because type annotations are not Cython specific, so Cython keeps the variables in the module dict (as Python values) instead of making them module internal C variables. Use ``declare()`` in Python code to explicitly define global C variables. .. tabs:: .. group-tab:: Pure Python .. code-block:: python a_global_variable = declare(cython.int) def func(): i: cython.int j: cython.int k: cython.int f: cython.float g: cython.float[42] h: cython.p_float i = j = 5 .. group-tab:: Cython .. code-block:: cython cdef int a_global_variable def func(): cdef int i, j, k cdef float f cdef float[42] g cdef float *h # cdef float f, g[42], *h # mix of pointers, arrays and values in a single line is deprecated i = j = 5 As known from C, declared global variables are automatically initialised to ``0``, ``NULL`` or ``None``, depending on their type. However, also as known from both Python and C, for a local variable, simply declaring it is not enough to initialise it. If you use a local variable but did not assign a value, both Cython and the C compiler will issue a warning "local variable ... referenced before assignment". You need to assign a value at some point before first using the variable, but you can also assign a value directly as part of the declaration in most cases: .. tabs:: .. group-tab:: Pure Python .. code-block:: python a_global_variable = declare(cython.int, 42) def func(): i: cython.int = 10 f: cython.float = 2.5 g: cython.int[4] = [1, 2, 3, 4] h: cython.p_float = cython.address(f) .. group-tab:: Cython .. code-block:: cython cdef int a_global_variable def func(): cdef int i = 10, j, k cdef float f = 2.5 cdef int[4] g = [1, 2, 3, 4] cdef float *h = &f .. note:: There is also support for giving names to types using the ``ctypedef`` statement or the ``cython.typedef()`` function, e.g. .. tabs:: .. group-tab:: Pure Python .. code-block:: python ULong = cython.typedef(cython.ulong) IntPtr = cython.typedef(cython.p_int) .. group-tab:: Cython .. code-block:: cython ctypedef unsigned long ULong ctypedef int* IntPtr C Arrays -------- C array can be declared by adding ``[ARRAY_SIZE]`` to the type of variable: .. tabs:: .. group-tab:: Pure Python .. code-block:: python def func(): g: cython.float[42] f: cython.int[5][5][5] .. group-tab:: Cython .. code-block:: cython def func(): cdef float[42] g cdef int[5][5][5] f .. note:: Cython syntax currently supports two ways to declare an array: .. code-block:: cython cdef int arr1[4], arr2[4] # C style array declaration cdef int[4] arr1, arr2 # Java style array declaration Both of them generate the same C code, but the Java style is more consistent with :ref:`memoryviews` and :ref:`fusedtypes`. The C style declaration is soft-deprecated and it's recommended to use Java style declaration instead. The soft-deprecated C style array declaration doesn't support initialization. .. code-block:: cython cdef int g[4] = [1, 2, 3, 4] # error cdef int[4] g = [1, 2, 3, 4] # OK cdef int g[4] # OK but not recommended g = [1, 2, 3, 4] .. _structs: Structs, Unions, Enums ---------------------- In addition to the basic types, C :keyword:`struct`, :keyword:`union` and :keyword:`enum` are supported: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/language_basics/struct.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/language_basics/struct.pyx Structs can be declared as ``cdef packed struct``, which has the same effect as the C directive ``#pragma pack(1)``:: cdef packed struct StructArray: int[4] spam signed char[5] eggs .. note:: This declaration removes the empty space between members that C automatically to ensure that they're aligned in memory (see `Wikipedia article `_ for more details). The main use is that numpy structured arrays store their data in packed form, so a ``cdef packed struct`` can be :ref:`used in a memoryview` to match that. Pure python mode does not support packed structs. The following example shows a declaration of unions: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/language_basics/union.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/language_basics/union.pyx Enums are created by ``cdef enum`` statement: .. literalinclude:: ../../examples/userguide/language_basics/enum.pyx .. note:: Currently, Pure Python mode does not support enums. (GitHub issue :issue:`4252`) Declaring an enum as ``cpdef`` will create a :pep:`435`-style Python wrapper:: cpdef enum CheeseState: hard = 1 soft = 2 runny = 3 There is currently no special syntax for defining a constant, but you can use an anonymous :keyword:`enum` declaration for this purpose, for example,:: cdef enum: tons_of_spam = 3 .. note:: In the Cython syntax, the words ``struct``, ``union`` and ``enum`` are used only when defining a type, not when referring to it. For example, to declare a variable pointing to a ``Grail`` struct, you would write:: cdef Grail *gp and not:: cdef struct Grail *gp # WRONG .. _typing_types: .. _types: Types ----- The Cython language uses the normal C syntax for C types, including pointers. It provides all the standard C types, namely ``char``, ``short``, ``int``, ``long``, ``long long`` as well as their ``unsigned`` versions, e.g. ``unsigned int`` (``cython.uint`` in Python code). The special ``bint`` type is used for C boolean values (``int`` with 0/non-0 values for False/True) and ``Py_ssize_t`` for (signed) sizes of Python containers. Pointer types are constructed as in C when using Cython syntax, by appending a ``*`` to the base type they point to, e.g. ``int**`` for a pointer to a pointer to a C int. In Pure python mode, simple pointer types use a naming scheme with "p"s instead, separated from the type name with an underscore, e.g. ``cython.pp_int`` for a pointer to a pointer to a C int. Further pointer types can be constructed with the ``cython.pointer()`` function, e.g. ``cython.pointer(cython.int)``. Arrays use the normal C array syntax, e.g. ``int[10]``, and the size must be known at compile time for stack allocated arrays. Cython doesn't support variable length arrays from C99. Note that Cython uses array access for pointer dereferencing, as ``*x`` is not valid Python syntax, whereas ``x[0]`` is. Also, the Python types ``list``, ``dict``, ``tuple``, etc. may be used for static typing, as well as any user defined :ref:`extension-types`. For example .. tabs:: .. group-tab:: Pure Python .. code-block:: python def main(): foo: list = [] .. group-tab:: Cython .. code-block:: cython cdef list foo = [] This requires an *exact* match of the class, it does not allow subclasses. This allows Cython to optimize code by accessing internals of the builtin class, which is the main reason for declaring builtin types in the first place. For declared builtin types, Cython uses internally a C variable of type ``PyObject*``. .. note:: The Python types ``int``, ``long``, and ``float`` are not available for static typing in ``.pyx`` files and instead interpreted as C ``int``, ``long``, and ``float`` respectively, as statically typing variables with these Python types has zero advantages. On the other hand, annotating in Pure Python with ``int``, ``long``, and ``float`` Python types will be interpreted as Python object types. Cython provides an accelerated and typed equivalent of a Python tuple, the ``ctuple``. A ``ctuple`` is assembled from any valid C types. For example .. tabs:: .. group-tab:: Pure Python .. code-block:: python def main(): bar: tuple[cython.double, cython.int] .. group-tab:: Cython .. code-block:: cython cdef (double, int) bar They compile down to C-structures and can be used as efficient alternatives to Python tuples. While these C types can be vastly faster, they have C semantics. Specifically, the integer types overflow and the C ``float`` type only has 32 bits of precision (as opposed to the 64-bit C ``double`` which Python floats wrap and is typically what one wants). If you want to use these numeric Python types simply omit the type declaration and let them be objects. Type qualifiers --------------- Cython supports ``const`` and ``volatile`` `C type qualifiers `_:: cdef volatile int i = 5 cdef const int sum(const int a, const int b): return a + b cdef void print_const_pointer(const int *value): print(value[0]) cdef void print_pointer_to_const_value(int * const value): print(value[0]) cdef void print_const_pointer_to_const_value(const int * const value): print(value[0]) .. Note:: Both type qualifiers are not supported by pure python mode. Moreover, the ``const`` modifier is unusable in a lot of contexts since Cython needs to generate definitions and their assignments separately. Therefore we suggest using it mainly for function argument and pointer types where ``const`` is necessary to work with an existing C/C++ interface. Extension Types --------------- It is also possible to declare :ref:`extension-types` (declared with ``cdef class`` or the ``@cclass`` decorator). Those will have a behaviour very close to python classes (e.g. creating subclasses), but access to their members is faster from Cython code. Typing a variable as extension type is mostly used to access ``cdef``/``@cfunc`` methods and attributes of the extension type. The C code uses a variable which is a pointer to a structure of the specific type, something like ``struct MyExtensionTypeObject*``. Here is a simple example: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/extension_types/shrubbery.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/extension_types/shrubbery.pyx You can read more about them in :ref:`extension-types`. Grouping multiple C declarations -------------------------------- If you have a series of declarations that all begin with :keyword:`cdef`, you can group them into a :keyword:`cdef` block like this: .. note:: This is supported only in Cython's ``cdef`` syntax. .. literalinclude:: ../../examples/userguide/language_basics/cdef_block.pyx .. _cpdef: .. _cdef: .. _python_functions_vs_c_functions: Python functions vs. C functions ================================== There are two kinds of function definition in Cython: Python functions are defined using the :keyword:`def` statement, as in Python. They take :term:`Python objects` as parameters and return Python objects. C functions are defined using the :keyword:`cdef` statement in Cython syntax or with the ``@cfunc`` decorator. They take either Python objects or C values as parameters, and can return either Python objects or C values. Within a Cython module, Python functions and C functions can call each other freely, but only Python functions can be called from outside the module by interpreted Python code. So, any functions that you want to "export" from your Cython module must be declared as Python functions using ``def``. There is also a hybrid function, declared with :keyword:`cpdef` in ``.pyx`` files or with the ``@ccall`` decorator. These functions can be called from anywhere, but use the faster C calling convention when being called from other Cython code. They can also be overridden by a Python method on a subclass or an instance attribute, even when called from Cython. If this happens, most performance gains are of course lost and even if it does not, there is a tiny overhead in calling such a method from Cython compared to calling a C method. Parameters of either type of function can be declared to have C data types, using normal C declaration syntax. For example, .. tabs:: .. group-tab:: Pure Python .. code-block:: python def spam(i: cython.int, s: cython.p_char): ... @cython.cfunc def eggs(l: cython.ulong, f: cython.float) -> cython.int: ... .. group-tab:: Cython .. code-block:: cython def spam(int i, char *s): ... cdef int eggs(unsigned long l, float f): ... ``ctuples`` may also be used .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc def chips(t: tuple[cython.long, cython.long, cython.double]) -> tuple[cython.int, cython.float]: ... .. group-tab:: Cython .. code-block:: cython cdef (int, float) chips((long, long, double) t): ... When a parameter of a Python function is declared to have a C data type, it is passed in as a Python object and automatically converted to a C value, if possible. In other words, the definition of ``spam`` above is equivalent to writing .. tabs:: .. group-tab:: Pure Python .. code-block:: python def spam(python_i, python_s): i: cython.int = python_i s: cython.p_char = python_s ... .. group-tab:: Cython .. code-block:: cython def spam(python_i, python_s): cdef int i = python_i cdef char* s = python_s ... Automatic conversion is currently only possible for numeric types, string types and structs (composed recursively of any of these types); attempting to use any other type for the parameter of a Python function will result in a compile-time error. Care must be taken with strings to ensure a reference if the pointer is to be used after the call. Structs can be obtained from Python mappings, and again care must be taken with string attributes if they are to be used after the function returns. C functions, on the other hand, can have parameters of any type, since they're passed in directly using a normal C function call. C Functions declared using :keyword:`cdef` or the ``@cfunc`` decorator with a Python object return type, like Python functions, will return a :keyword:`None` value when execution leaves the function body without an explicit return value. This is in contrast to C/C++, which leaves the return value undefined. In the case of non-Python object return types, the equivalent of zero is returned, for example, 0 for ``int``, :keyword:`False` for ``bint`` and :keyword:`NULL` for pointer types. A more complete comparison of the pros and cons of these different method types can be found at :ref:`early-binding-for-speed`. Python objects as parameters and return values ---------------------------------------------- If no type is specified for a parameter or return value, it is assumed to be a Python object. (Note that this is different from the C convention, where it would default to ``int``.) For example, the following defines a C function that takes two Python objects as parameters and returns a Python object .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc def spamobjs(x, y): ... .. group-tab:: Cython .. code-block:: cython cdef spamobjs(x, y): ... Reference counting for these objects is performed automatically according to the standard Python/C API rules (i.e. borrowed references are taken as parameters and a new reference is returned). .. warning:: This only applies to Cython code. Other Python packages which are implemented in C like NumPy may not follow these conventions. The type name ``object`` can also be used to explicitly declare something as a Python object. This can be useful if the name being declared would otherwise be taken as the name of a type, for example, .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc def ftang(int: object): ... .. group-tab:: Cython .. code-block:: cython cdef ftang(object int): ... declares a parameter called ``int`` which is a Python object. You can also use ``object`` as the explicit return type of a function, e.g. .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc def ftang(int: object) -> object: ... .. group-tab:: Cython .. code-block:: cython cdef object ftang(object int): ... In the interests of clarity, it is probably a good idea to always be explicit about object parameters in C functions. To create a borrowed reference, specify the parameter type as ``PyObject*``. Cython won't perform automatic ``Py_INCREF``, or ``Py_DECREF``, e.g.: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/language_basics/parameter_refcount.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/language_basics/parameter_refcount.pyx will display:: Initial refcount: 2 Inside owned_reference: 3 Inside borrowed_reference: 2 .. _optional_arguments: Optional Arguments ------------------ Unlike C, it is possible to use optional arguments in C and ``cpdef``/``@ccall`` functions. There are differences though whether you declare them in a ``.pyx``/``.py`` file or the corresponding ``.pxd`` file. To avoid repetition (and potential future inconsistencies), default argument values are not visible in the declaration (in ``.pxd`` files) but only in the implementation (in ``.pyx`` files). When in a ``.pyx``/``.py`` file, the signature is the same as it is in Python itself: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/language_basics/optional_subclassing.py :caption: optional_subclassing.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/language_basics/optional_subclassing.pyx :caption: optional_subclassing.pyx When in a ``.pxd`` file, the signature is different like this example: ``cdef foo(x=*)``. This is because the program calling the function just needs to know what signatures are possible in C, but doesn't need to know the value of the default arguments.: .. literalinclude:: ../../examples/userguide/language_basics/optional_subclassing.pxd :caption: optional_subclassing.pxd .. note:: The number of arguments may increase when subclassing, but the arg types and order must be the same, as shown in the example above. There may be a slight performance penalty when the optional arg is overridden with one that does not have default values. .. _keyword_only_argument: Keyword-only Arguments ---------------------- As in Python 3, ``def`` functions can have keyword-only arguments listed after a ``"*"`` parameter and before a ``"**"`` parameter if any: .. literalinclude:: ../../examples/userguide/language_basics/kwargs_1.pyx As shown above, the ``c``, ``d`` and ``e`` arguments can not be passed as positional arguments and must be passed as keyword arguments. Furthermore, ``c`` and ``e`` are **required** keyword arguments since they do not have a default value. A single ``"*"`` without argument name can be used to terminate the list of positional arguments: .. literalinclude:: ../../examples/userguide/language_basics/kwargs_2.pyx Shown above, the signature takes exactly two positional parameters and has two required keyword parameters. Function Pointers ----------------- .. note:: Pointers to functions are currently not supported by pure Python mode. (GitHub issue :issue:`4279`) The following example shows declaring a ``ptr_add`` function pointer and assigning the ``add`` function to it: .. literalinclude:: ../../examples/userguide/language_basics/function_pointer.pyx Functions declared in a ``struct`` are automatically converted to function pointers: .. literalinclude:: ../../examples/userguide/language_basics/function_pointer_struct.pyx For using error return values with function pointers, see the note at the bottom of :ref:`error_return_values`. .. _error_return_values: Error return values ------------------- In Python (more specifically, in the CPython runtime), exceptions that occur inside of a function are signaled to the caller and propagated up the call stack through defined error return values. For functions that return a Python object (and thus, a pointer to such an object), the error return value is simply the ``NULL`` pointer, so any function returning a Python object has a well-defined error return value. While this is always the case for Python functions, functions defined as C functions or ``cpdef``/``@ccall`` functions can return arbitrary C types, which do not have such a well-defined error return value. By default Cython uses a dedicated return value to signal that an exception has been raised from non-external ``cpdef``/``@ccall`` functions. However, how Cython handles exceptions from these functions can be changed if needed. A ``cdef`` function may be declared with an exception return value for it as a contract with the caller. Here is an example: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc @cython.exceptval(-1) def spam() -> cython.int: ... .. group-tab:: Cython .. code-block:: cython cdef int spam() except -1: ... With this declaration, whenever an exception occurs inside ``spam``, it will immediately return with the value ``-1``. From the caller's side, whenever a call to spam returns ``-1``, the caller will assume that an exception has occurred and can now process or propagate it. Calling ``spam()`` is roughly translated to the following C code: .. code-block:: C ret_val = spam(); if (ret_val == -1) goto error_handler; When you declare an exception value for a function, you should never explicitly or implicitly return that value. This includes empty :keyword:`return` statements, without a return value, for which Cython inserts the default return value (e.g. ``0`` for C number types). In general, exception return values are best chosen from invalid or very unlikely return values of the function, such as a negative value for functions that return only non-negative results, or a very large value like ``INT_MAX`` for a function that "usually" only returns small results. If all possible return values are legal and you can't reserve one entirely for signalling errors, you can use an alternative form of exception value declaration .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc @cython.exceptval(-1, check=True) def spam() -> cython.int: ... The keyword argument ``check=True`` indicates that the value ``-1`` **may** signal an error. .. group-tab:: Cython .. code-block:: cython cdef int spam() except? -1: ... The ``?`` indicates that the value ``-1`` **may** signal an error. In this case, Cython generates a call to :c:func:`PyErr_Occurred` if the exception value is returned, to make sure it really received an exception and not just a normal result. Calling ``spam()`` is roughly translated to the following C code: .. code-block:: C ret_val = spam(); if (ret_val == -1 && PyErr_Occurred()) goto error_handler; There is also a third form of exception value declaration .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc @cython.exceptval(check=True) def spam() -> cython.void: ... .. group-tab:: Cython .. code-block:: cython cdef void spam() except *: ... This form causes Cython to generate a call to :c:func:`PyErr_Occurred` after *every* call to spam, regardless of what value it returns. Calling ``spam()`` is roughly translated to the following C code: .. code-block:: C spam() if (PyErr_Occurred()) goto error_handler; If you have a function returning ``void`` that needs to propagate errors, you will have to use this form, since there isn't any error return value to test. Otherwise, an explicit error return value allows the C compiler to generate more efficient code and is thus generally preferable. An external C++ function that may raise an exception can be declared with:: cdef int spam() except + .. note:: These declarations are not used in Python code, only in ``.pxd`` and ``.pyx`` files. See :ref:`wrapping-cplusplus` for more details. Finally, if you are certain that your function should not raise an exception, (e.g., it does not use Python objects at all, or you plan to use it as a callback in C code that is unaware of Python exceptions), you can declare it as such using ``noexcept`` or by ``@cython.exceptval(check=False)``: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.cfunc @cython.exceptval(check=False) def spam() -> cython.int: ... .. group-tab:: Cython .. code-block:: cython cdef int spam() noexcept: ... If a ``noexcept`` function *does* finish with an exception then it will print a warning message but not allow the exception to propagate further. On the other hand, calling a ``noexcept`` function has zero overhead related to managing exceptions, unlike the previous declarations. Some things to note: * ``cdef`` functions that are also ``extern`` are implicitly declared ``noexcept`` or ``@cython.exceptval(check=False)``. In the uncommon case of external C/C++ functions that **can** raise Python exceptions, e.g., external functions that use the Python C API, you should explicitly declare them with an exception value. * ``cdef`` functions that are *not* ``extern`` are implicitly declared with a suitable exception specification for the return type (e.g. ``except *`` or ``@cython.exceptval(check=True)`` for a ``void`` return type, ``except? -1`` or ``@cython.exceptval(-1, check=True)`` for an ``int`` return type). * Exception values can only be declared for functions returning a C integer, enum, float or pointer type, and the value must be a constant expression. Functions that return ``void``, or a struct/union by value, can only use the ``except *`` or ``exceptval(check=True)`` form. * The exception value specification is part of the signature of the function. If you're passing a pointer to a function as a parameter or assigning it to a variable, the declared type of the parameter or variable must have the same exception value specification (or lack thereof). Here is an example of a pointer-to-function declaration with an exception value:: int (*grail)(int, char*) except -1 .. note:: Pointers to functions are currently not supported by pure Python mode. (GitHub issue :issue:`4279`) * If the returning type of a ``cdef`` function with ``except *`` or ``@cython.exceptval(check=True)`` is C integer, enum, float or pointer type, Cython calls :c:func:`PyErr_Occurred` only when dedicated value is returned instead of checking after every call of the function. * You don't need to (and shouldn't) declare exception values for functions which return Python objects. Remember that a function with no declared return type implicitly returns a Python object. (Exceptions on such functions are implicitly propagated by returning ``NULL``.) * There's a known performance pitfall when combining ``nogil`` and ``except *`` \ ``@cython.exceptval(check=True)``. In this case Cython must always briefly re-acquire the GIL after a function call to check if an exception has been raised. This can commonly happen with a function returning nothing (C ``void``). Simple workarounds are to mark the function as ``noexcept`` if you're certain that exceptions cannot be thrown, or to change the return type to ``int`` and just let Cython use the return value as an error flag (by default, ``-1`` triggers the exception check). .. _checking_return_values_of_non_cython_functions: Checking return values of non-Cython functions ---------------------------------------------- It's important to understand that the except clause does not cause an error to be raised when the specified value is returned. For example, you can't write something like:: cdef extern FILE *fopen(char *filename, char *mode) except NULL # WRONG! and expect an exception to be automatically raised if a call to :func:`fopen` returns ``NULL``. The except clause doesn't work that way; its only purpose is for propagating Python exceptions that have already been raised, either by a Cython function or a C function that calls Python/C API routines. To get an exception from a non-Python-aware function such as :func:`fopen`, you will have to check the return value and raise it yourself, for example: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/language_basics/open_file.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/language_basics/open_file.pyx .. _overriding_in_extension_types: Overriding in extension types ----------------------------- ``cpdef``/``@ccall`` methods can override C methods: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/language_basics/optional_subclassing.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/language_basics/optional_subclassing.pyx When subclassing an extension type with a Python class, Python methods can override ``cpdef``/``@ccall`` methods but not plain C methods: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/language_basics/override.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/language_basics/override.pyx If ``C`` above would be an extension type (``cdef class``), this would not work correctly. The Cython compiler will give a warning in that case. .. _type-conversion: Automatic type conversions ========================== In most situations, automatic conversions will be performed for the basic numeric and string types when a Python object is used in a context requiring a C value, or vice versa. The following table summarises the conversion possibilities. +----------------------------+--------------------+------------------+ | C types | From Python types | To Python types | +============================+====================+==================+ | [unsigned] char, | int, long | int | | [unsigned] short, | | | | int, long | | | +----------------------------+--------------------+------------------+ | unsigned int, | int, long | long | | unsigned long, | | | | [unsigned] long long | | | +----------------------------+--------------------+------------------+ | float, double, long double | int, long, float | float | +----------------------------+--------------------+------------------+ | char* | str/bytes | str/bytes [#]_ | +----------------------------+--------------------+------------------+ | C array | iterable | list [#2]_ | +----------------------------+--------------------+------------------+ | struct, | | dict [#1]_ [#4]_ | | union | | | +----------------------------+--------------------+------------------+ .. [#] The conversion is to/from str for Python 2.x, and bytes for Python 3.x. .. [#1] The conversion from a C union type to a Python dict will add a value for each of the union fields. Cython 0.23 and later, however, will refuse to automatically convert a union with unsafe type combinations. An example is a union of an ``int`` and a ``char*``, in which case the pointer value may or may not be a valid pointer. .. [#2] Other than signed/unsigned char[]. The conversion will fail if the length of C array is not known at compile time, and when using a slice of a C array. .. [#4] The automatic conversion of a struct to a ``dict`` (and vice versa) does have some potential pitfalls detailed :ref:`elsewhere in the documentation `. Caveats when using a Python string in a C context ------------------------------------------------- You need to be careful when using a Python string in a context expecting a ``char*``. In this situation, a pointer to the contents of the Python string is used, which is only valid as long as the Python string exists. So you need to make sure that a reference to the original Python string is held for as long as the C string is needed. If you can't guarantee that the Python string will live long enough, you will need to copy the C string. Cython detects and prevents some mistakes of this kind. For instance, if you attempt something like .. tabs:: .. group-tab:: Pure Python .. code-block:: python def main(): s: cython.p_char s = pystring1 + pystring2 .. group-tab:: Cython .. code-block:: cython cdef char *s s = pystring1 + pystring2 then Cython will produce the error message ``Storing unsafe C derivative of temporary Python reference``. The reason is that concatenating the two Python strings produces a new Python string object that is referenced only by a temporary internal variable that Cython generates. As soon as the statement has finished, the temporary variable will be decrefed and the Python string deallocated, leaving ``s`` dangling. Since this code could not possibly work, Cython refuses to compile it. The solution is to assign the result of the concatenation to a Python variable, and then obtain the ``char*`` from that, i.e. .. tabs:: .. group-tab:: Pure Python .. code-block:: python def main(): s: cython.p_char p = pystring1 + pystring2 s = p .. group-tab:: Cython .. code-block:: cython cdef char *s p = pystring1 + pystring2 s = p It is then your responsibility to hold the reference p for as long as necessary. Keep in mind that the rules used to detect such errors are only heuristics. Sometimes Cython will complain unnecessarily, and sometimes it will fail to detect a problem that exists. Ultimately, you need to understand the issue and be careful what you do. .. _type_casting: Type Casting ------------ The Cython language supports type casting in a similar way as C. Where C uses ``"("`` and ``")"``, Cython uses ``"<"`` and ``">"``. In pure python mode, the ``cython.cast()`` function is used. For example: .. tabs:: .. group-tab:: Pure Python .. code-block:: python def main(): p: cython.p_char q: cython.p_float p = cython.cast(cython.p_char, q) When casting a C value to a Python object type or vice versa, Cython will attempt a coercion. Simple examples are casts like ``cast(int, pyobj_value)``, which convert a Python number to a plain C ``int`` value, or the statement ``cast(bytes, charptr_value)``, which copies a C ``char*`` string into a new Python bytes object. .. note:: Cython will not prevent a redundant cast, but emits a warning for it. To get the address of some Python object, use a cast to a pointer type like ``cast(p_void, ...)`` or ``cast(pointer(PyObject), ...)``. You can also cast a C pointer back to a Python object reference with ``cast(object, ...)``, or to a more specific builtin or extension type (e.g. ``cast(MyExtType, ptr)``). This will increase the reference count of the object by one, i.e. the cast returns an owned reference. Here is an example: .. group-tab:: Cython .. code-block:: cython cdef char *p cdef float *q p = q When casting a C value to a Python object type or vice versa, Cython will attempt a coercion. Simple examples are casts like ``pyobj_value``, which convert a Python number to a plain C ``int`` value, or the statement ``charptr_value``, which copies a C ``char*`` string into a new Python bytes object. .. note:: Cython will not prevent a redundant cast, but emits a warning for it. To get the address of some Python object, use a cast to a pointer type like ```` or ````. You can also cast a C pointer back to a Python object reference with ````, or to a more specific builtin or extension type (e.g. ``ptr``). This will increase the reference count of the object by one, i.e. the cast returns an owned reference. Here is an example: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/language_basics/casting_python.pxd :caption: casting_python.pxd .. literalinclude:: ../../examples/userguide/language_basics/casting_python.py :caption: casting_python.py Casting with ``cast(object, ...)`` creates an owned reference. Cython will automatically perform a ``Py_INCREF`` and ``Py_DECREF`` operation. Casting to ``cast(pointer(PyObject), ...)`` creates a borrowed reference, leaving the refcount unchanged. .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/language_basics/casting_python.pyx :caption: casting_python.pyx The precedence of ``<...>`` is such that ``a.b.c`` is interpreted as ``(a.b.c)``. Casting to ```` creates an owned reference. Cython will automatically perform a ``Py_INCREF`` and ``Py_DECREF`` operation. Casting to ```` creates a borrowed reference, leaving the refcount unchanged. .. _checked_type_casts: Checked Type Casts ------------------ A cast like ``x`` or ``cast(MyExtensionType, x)`` will cast ``x`` to the class ``MyExtensionType`` without any checking at all. To have a cast checked, use ``x`` in Cython syntax or ``cast(MyExtensionType, x, typecheck=True)``. In this case, Cython will apply a runtime check that raises a ``TypeError`` if ``x`` is not an instance of ``MyExtensionType``. This tests for the exact class for builtin types, but allows subclasses for :ref:`extension-types`. .. _statements_and_expressions: Statements and expressions ========================== Control structures and expressions follow Python syntax for the most part. When applied to Python objects, they have the same semantics as in Python (unless otherwise noted). Most of the Python operators can also be applied to C values, with the obvious semantics. If Python objects and C values are mixed in an expression, conversions are performed automatically between Python objects and C numeric or string types. Reference counts are maintained automatically for all Python objects, and all Python operations are automatically checked for errors, with appropriate action taken. Differences between C and Cython expressions -------------------------------------------- There are some differences in syntax and semantics between C expressions and Cython expressions, particularly in the area of C constructs which have no direct equivalent in Python. * An integer literal is treated as a C constant, and will be truncated to whatever size your C compiler thinks appropriate. To get a Python integer (of arbitrary precision), cast immediately to an object (e.g. ``100000000000000000000`` or ``cast(object, 100000000000000000000)``). The ``L``, ``LL``, and ``U`` suffixes have the same meaning in Cython syntax as in C. * There is no ``->`` operator in Cython. Instead of ``p->x``, use ``p.x`` * There is no unary ``*`` operator in Cython. Instead of ``*p``, use ``p[0]`` * There is an ``&`` operator in Cython, with the same semantics as in C. In pure python mode, use the ``cython.address()`` function instead. * The null C pointer is called ``NULL``, not ``0``. ``NULL`` is a reserved word in Cython and ``cython.NULL`` is a special object in pure python mode. * Type casts are written ``value`` or ``cast(type, value)``, for example, .. tabs:: .. group-tab:: Pure Python .. code-block:: python def main(): p: cython.p_char q: cython.p_float p = cython.cast(cython.p_char, q) .. group-tab:: Cython .. code-block:: cython cdef char* p cdef float* q p = q Scope rules ----------- Cython determines whether a variable belongs to a local scope, the module scope, or the built-in scope completely statically. As with Python, assigning to a variable which is not otherwise declared implicitly declares it to be a variable residing in the scope where it is assigned. The type of the variable depends on type inference, except for the global module scope, where it is always a Python object. .. _built_in_functions: Built-in Functions ------------------ Cython compiles calls to most built-in functions into direct calls to the corresponding Python/C API routines, making them particularly fast. Only direct function calls using these names are optimised. If you do something else with one of these names that assumes it's a Python object, such as assign it to a Python variable, and later call it, the call will be made as a Python function call. +------------------------------+-------------+----------------------------+ | Function and arguments | Return type | Python/C API Equivalent | +==============================+=============+============================+ | abs(obj) | object, | PyNumber_Absolute, fabs, | | | double, ... | fabsf, ... | +------------------------------+-------------+----------------------------+ | callable(obj) | bint | PyObject_Callable | +------------------------------+-------------+----------------------------+ | delattr(obj, name) | None | PyObject_DelAttr | +------------------------------+-------------+----------------------------+ | exec(code, [glob, [loc]]) | object | - | +------------------------------+-------------+----------------------------+ | dir(obj) | list | PyObject_Dir | +------------------------------+-------------+----------------------------+ | divmod(a, b) | tuple | PyNumber_Divmod | +------------------------------+-------------+----------------------------+ | getattr(obj, name, [default])| object | PyObject_GetAttr | | (Note 1) | | | +------------------------------+-------------+----------------------------+ | hasattr(obj, name) | bint | PyObject_HasAttr | +------------------------------+-------------+----------------------------+ | hash(obj) | int / long | PyObject_Hash | +------------------------------+-------------+----------------------------+ | intern(obj) | object | Py*_InternFromString | +------------------------------+-------------+----------------------------+ | isinstance(obj, type) | bint | PyObject_IsInstance | +------------------------------+-------------+----------------------------+ | issubclass(obj, type) | bint | PyObject_IsSubclass | +------------------------------+-------------+----------------------------+ | iter(obj, [sentinel]) | object | PyObject_GetIter | +------------------------------+-------------+----------------------------+ | len(obj) | Py_ssize_t | PyObject_Length | +------------------------------+-------------+----------------------------+ | pow(x, y, [z]) | object | PyNumber_Power | +------------------------------+-------------+----------------------------+ | reload(obj) | object | PyImport_ReloadModule | +------------------------------+-------------+----------------------------+ | repr(obj) | object | PyObject_Repr | +------------------------------+-------------+----------------------------+ | setattr(obj, name) | void | PyObject_SetAttr | +------------------------------+-------------+----------------------------+ Note 1: Pyrex originally provided a function :func:`getattr3(obj, name, default)` corresponding to the three-argument form of the Python builtin :func:`getattr()`. Cython still supports this function, but the usage is deprecated in favour of the normal builtin, which Cython can optimise in both forms. Operator Precedence ------------------- Keep in mind that there are some differences in operator precedence between Python and C, and that Cython uses the Python precedences, not the C ones. Integer for-loops ------------------ .. note:: This syntax is supported only in Cython files. Use a normal `for-in-range()` loop instead. Cython recognises the usual Python for-in-range integer loop pattern:: for i in range(n): ... If ``i`` is declared as a :keyword:`cdef` integer type, it will optimise this into a pure C loop. This restriction is required as otherwise the generated code wouldn't be correct due to potential integer overflows on the target architecture. If you are worried that the loop is not being converted correctly, use the annotate feature of the cython commandline (``-a``) to easily see the generated C code. See :ref:`automatic-range-conversion` For backwards compatibility to Pyrex, Cython also supports a more verbose form of for-loop which you might find in legacy code:: for i from 0 <= i < n: ... or:: for i from 0 <= i < n by s: ... where ``s`` is some integer step size. .. note:: This syntax is deprecated and should not be used in new code. Use the normal Python for-loop instead. Some things to note about the for-from loop: * The target expression must be a plain variable name. * The name between the lower and upper bounds must be the same as the target name. * The direction of iteration is determined by the relations. If they are both from the set {``<``, ``<=``} then it is upwards; if they are both from the set {``>``, ``>=``} then it is downwards. (Any other combination is disallowed.) Like other Python looping statements, break and continue may be used in the body, and the loop may have an else clause. .. _cython_file_types: Cython file types ================= There are three file types in Cython: * The implementation files, carrying a ``.py`` or ``.pyx`` suffix. * The definition files, carrying a ``.pxd`` suffix. * The include files, carrying a ``.pxi`` suffix. The implementation file ----------------------- The implementation file, as the name suggest, contains the implementation of your functions, classes, extension types, etc. Nearly all the python syntax is supported in this file. Most of the time, a ``.py`` file can be renamed into a ``.pyx`` file without changing any code, and Cython will retain the python behavior. It is possible for Cython to compile both ``.py`` and ``.pyx`` files. The name of the file isn't important if one wants to use only the Python syntax, and Cython won't change the generated code depending on the suffix used. Though, if one want to use the Cython syntax, using a ``.pyx`` file is necessary. In addition to the Python syntax, the user can also leverage Cython syntax (such as ``cdef``) to use C variables, can declare functions as ``cdef`` or ``cpdef`` and can import C definitions with :keyword:`cimport`. Many other Cython features usable in implementation files can be found throughout this page and the rest of the Cython documentation. There are some restrictions on the implementation part of some :ref:`extension-types` if the corresponding definition file also defines that type. .. note:: When a ``.pyx`` file is compiled, Cython first checks to see if a corresponding ``.pxd`` file exists and processes it first. It acts like a header file for a Cython ``.pyx`` file. You can put inside functions that will be used by other Cython modules. This allows different Cython modules to use functions and classes from each other without the Python overhead. To read more about what how to do that, you can see :ref:`pxd_files`. The definition file ------------------- A definition file is used to declare various things. Any C declaration can be made, and it can be also a declaration of a C variable or function implemented in a C/C++ file. This can be done with ``cdef extern from``. Sometimes, ``.pxd`` files are used as a translation of C/C++ header files into a syntax that Cython can understand. This allows then the C/C++ variable and functions to be used directly in implementation files with :keyword:`cimport`. You can read more about it in :ref:`external-C-code` and :ref:`wrapping-cplusplus`. It can also contain the definition part of an extension type and the declarations of functions for an external library. It cannot contain the implementations of any C or Python functions, or any Python class definitions, or any executable statements. It is needed when one wants to access :keyword:`cdef` attributes and methods, or to inherit from :keyword:`cdef` classes defined in this module. .. note:: You don't need to (and shouldn't) declare anything in a declaration file :keyword:`public` in order to make it available to other Cython modules; its mere presence in a definition file does that. You only need a public declaration if you want to make something available to external C code. The include statement and include files --------------------------------------- .. warning:: Historically the ``include`` statement was used for sharing declarations. Use :ref:`sharing-declarations` instead. A Cython source file can include material from other files using the include statement, for example,:: include "spamstuff.pxi" The contents of the named file are textually included at that point. The included file can contain any complete statements or declarations that are valid in the context where the include statement appears, including other include statements. The contents of the included file should begin at an indentation level of zero, and will be treated as though they were indented to the level of the include statement that is including the file. The include statement cannot, however, be used outside of the module scope, such as inside of functions or class bodies. .. note:: There are other mechanisms available for splitting Cython code into separate parts that may be more appropriate in many cases. See :ref:`sharing-declarations`. .. _conditional_compilation: Conditional Compilation ======================= Some language features are available for conditional compilation and compile-time constants within a Cython source file. .. note:: This feature has been deprecated and should not be used in new code. It is very foreign to the Python language and also behaves differently from the C preprocessor. It is often misunderstood by users. For the current deprecation status, see https://github.com/cython/cython/issues/4310. For alternatives, see :ref:`deprecated_DEF_IF`. .. note:: This feature has very little use cases. Specifically, it is not a good way to adapt code to platform and environment. Use runtime conditions, conditional Python imports, or C compile time adaptation for this. See, for example, :ref:`verbatim_c` or :ref:`resolve-conflicts`. .. note:: Cython currently does not support conditional compilation and compile-time definitions in Pure Python mode. As it stands, this is unlikely to change. Compile-Time Definitions ------------------------ A compile-time constant can be defined using the DEF statement:: DEF FavouriteFood = u"spam" DEF ArraySize = 42 DEF OtherArraySize = 2 * ArraySize + 17 The right-hand side of the ``DEF`` must be a valid compile-time expression. Such expressions are made up of literal values and names defined using ``DEF`` statements, combined using any of the Python expression syntax. .. note:: Cython does not intend to copy literal compile-time values 1:1 into the generated code. Instead, these values are internally represented and calculated as plain Python values and use Python's ``repr()`` when a serialisation is needed. This means that values defined using ``DEF`` may lose precision or change their type depending on the calculation rules of the Python environment where Cython parses and translates the source code. Specifically, using ``DEF`` to define high-precision floating point constants may not give the intended result and may generate different C values in different Python versions. The following compile-time names are predefined, corresponding to the values returned by :func:`os.uname`. As noted above, they are not considered good ways to adapt code to different platforms and are mostly provided for legacy reasons. UNAME_SYSNAME, UNAME_NODENAME, UNAME_RELEASE, UNAME_VERSION, UNAME_MACHINE The following selection of builtin constants and functions are also available: None, True, False, abs, all, any, ascii, bin, bool, bytearray, bytes, chr, cmp, complex, dict, divmod, enumerate, filter, float, format, frozenset, hash, hex, int, len, list, long, map, max, min, oct, ord, pow, range, reduce, repr, reversed, round, set, slice, sorted, str, sum, tuple, xrange, zip Note that some of these builtins may not be available when compiling under Python 2.x or 3.x, or may behave differently in both. A name defined using ``DEF`` can be used anywhere an identifier can appear, and it is replaced with its compile-time value as though it were written into the source at that point as a literal. For this to work, the compile-time expression must evaluate to a Python value of type ``int``, ``long``, ``float``, ``bytes`` or ``unicode`` (``str`` in Py3). .. literalinclude:: ../../examples/userguide/language_basics/compile_time.pyx Conditional Statements ---------------------- The ``IF`` statement can be used to conditionally include or exclude sections of code at compile time. It works in a similar way to the ``#if`` preprocessor directive in C. :: IF ARRAY_SIZE > 64: include "large_arrays.pxi" ELIF ARRAY_SIZE > 16: include "medium_arrays.pxi" ELSE: include "small_arrays.pxi" The ``ELIF`` and ``ELSE`` clauses are optional. An ``IF`` statement can appear anywhere that a normal statement or declaration can appear, and it can contain any statements or declarations that would be valid in that context, including ``DEF`` statements and other ``IF`` statements. The expressions in the ``IF`` and ``ELIF`` clauses must be valid compile-time expressions as for the ``DEF`` statement, although they can evaluate to any Python value, and the truth of the result is determined in the usual Python way. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/limitations.rst0000644000175100001770000000416300000000000022401 0ustar00runnerdocker00000000000000.. highlight:: cython .. _cython-limitations: ************* Limitations ************* This page used to list bugs in Cython that made the semantics of compiled code differ from that in Python. Most of the missing features have been fixed in Cython 0.15. A future version of Cython is planned to provide full Python language compatibility. For now, the issue tracker can provide an overview of deviations that we are aware of and would like to see fixed. https://github.com/cython/cython/labels/Python%20Semantics Below is a list of differences that we will probably not be addressing. Most of these things that fall more into the implementation details rather than semantics, and we may decide not to fix (or require a --pedantic flag to get). Nested tuple argument unpacking =============================== :: def f((a,b), c): pass This was removed in Python 3. Inspect support =============== While it is quite possible to emulate the interface of functions in Cython's own function type, and recent Cython releases have seen several improvements here, the "inspect" module does not consider a Cython implemented function a "function", because it tests the object type explicitly instead of comparing an abstract interface or an abstract base class. This has a negative impact on code that uses inspect to inspect function objects, but would require a change to Python itself. Stack frames ============ Currently we generate fake tracebacks as part of exception propagation, but don't fill in locals and can't fill in co_code. To be fully compatible, we would have to generate these stack frame objects at function call time (with a potential performance penalty). We may have an option to enable this for debugging. Identity vs. equality for inferred literals =========================================== :: a = 1.0 # a inferred to be C type 'double' b = c = None # b and c inferred to be type 'object' if some_runtime_expression: b = a # creates a new Python float object c = a # creates a new Python float object print(b is c) # most likely not the same object ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/memoryviews.rst0000644000175100001770000007447100000000000022444 0ustar00runnerdocker00000000000000.. highlight:: cython .. _memoryviews: ***************** Typed Memoryviews ***************** .. include:: ../two-syntax-variants-used Typed memoryviews allow efficient access to memory buffers, such as those underlying NumPy arrays, without incurring any Python overhead. Memoryviews are similar to the current NumPy array buffer support (``np.ndarray[np.float64_t, ndim=2]``), but they have more features and cleaner syntax. Memoryviews are more general than the old NumPy array buffer support, because they can handle a wider variety of sources of array data. For example, they can handle C arrays and the Cython array type (:ref:`view_cython_arrays`). A memoryview can be used in any context (function parameters, module-level, cdef class attribute, etc) and can be obtained from nearly any object that exposes writable buffer through the `PEP 3118`_ buffer interface. .. _`PEP 3118`: https://www.python.org/dev/peps/pep-3118/ .. _view_quickstart: Quickstart ========== If you are used to working with NumPy, the following examples should get you started with Cython memory views. .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/memoryviews/quickstart.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/memoryviews/quickstart.pyx This code should give the following output:: NumPy sum of the NumPy array before assignments: 351 NumPy sum of NumPy array after assignments: 81 Memoryview sum of NumPy array is 81 Memoryview sum of C array is 451 Memoryview sum of Cython array is 1351 Memoryview sum of C memoryview is 451 .. _using_memoryviews: Using memoryviews ================= Syntax ------ Memory views use Python slicing syntax in a similar way as NumPy. To create a complete view on a one-dimensional ``int`` buffer: .. tabs:: .. group-tab:: Pure Python .. code-block:: python view1D: cython.int[:] = exporting_object .. group-tab:: Cython .. code-block:: cython cdef int[:] view1D = exporting_object A complete 3D view: .. tabs:: .. group-tab:: Pure Python .. code-block:: python view3D: cython.int[:,:,:] = exporting_object .. group-tab:: Cython .. code-block:: cython cdef int[:,:,:] view3D = exporting_object They also work conveniently as function arguments: .. tabs:: .. group-tab:: Pure Python .. code-block:: python def process_3d_buffer(view: cython.int[:,:,:]): ... .. group-tab:: Cython .. code-block:: cython def process_3d_buffer(int[:,:,:] view not None): ... The Cython ``not None`` declaration for the argument automatically rejects ``None`` values as input, which would otherwise be allowed. The reason why ``None`` is allowed by default is that it is conveniently used for return arguments. On the other hand, when pure python mode is used, ``None`` value is rejected by default. It is allowed only when type is declared as ``Optional``: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/memoryviews/not_none.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/memoryviews/not_none.pyx Cython will reject incompatible buffers automatically, e.g. passing a three dimensional buffer into a function that requires a two dimensional buffer will raise a ``ValueError``. To use a memory view on a numpy array with a custom dtype, you'll need to declare an equivalent packed struct that mimics the dtype: .. literalinclude:: ../../examples/userguide/memoryviews/custom_dtype.pyx .. note:: Pure python mode currently does not support packed structs Indexing -------- In Cython, index access on memory views is automatically translated into memory addresses. The following code requests a two-dimensional memory view of C ``int`` typed items and indexes into it: .. tabs:: .. group-tab:: Pure Python .. code-block:: python buf: cython.int[:,:] = exporting_object print(buf[1,2]) .. group-tab:: Cython .. code-block:: cython cdef int[:,:] buf = exporting_object print(buf[1,2]) Negative indices work as well, counting from the end of the respective dimension:: print(buf[-1,-2]) The following function loops over each dimension of a 2D array and adds 1 to each item: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/memoryviews/add_one.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/memoryviews/add_one.pyx Indexing and slicing can be done with or without the GIL. It basically works like NumPy. If indices are specified for every dimension you will get an element of the base type (e.g. ``int``). Otherwise, you will get a new view. An Ellipsis means you get consecutive slices for every unspecified dimension: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/memoryviews/slicing.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/memoryviews/slicing.pyx Copying ------- Memory views can be copied in place: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/memoryviews/copy.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/memoryviews/copy.pyx They can also be copied with the ``copy()`` and ``copy_fortran()`` methods; see :ref:`view_copy_c_fortran`. .. _view_transposing: Transposing ----------- In most cases (see below), the memoryview can be transposed in the same way that NumPy slices can be transposed: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/memoryviews/transpose.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/memoryviews/transpose.pyx This gives a new, transposed, view on the data. Transposing requires that all dimensions of the memoryview have a direct access memory layout (i.e., there are no indirections through pointers). See :ref:`view_general_layouts` for details. Newaxis ------- As for NumPy, new axes can be introduced by indexing an array with ``None`` : .. tabs:: .. group-tab:: Pure Python .. code-block:: python myslice: cython.double[:] = np.linspace(0, 10, num=50) # 2D array with shape (1, 50) myslice[None] # or myslice[None, :] # 2D array with shape (50, 1) myslice[:, None] # 3D array with shape (1, 10, 1) myslice[None, 10:-20:2, None] .. group-tab:: Cython .. code-block:: cython cdef double[:] myslice = np.linspace(0, 10, num=50) # 2D array with shape (1, 50) myslice[None] # or myslice[None, :] # 2D array with shape (50, 1) myslice[:, None] # 3D array with shape (1, 10, 1) myslice[None, 10:-20:2, None] One may mix new axis indexing with all other forms of indexing and slicing. See also an example_. .. _readonly_views: Read-only views --------------- .. note:: Pure python mode currently does not support read-only views. Since Cython 0.28, the memoryview item type can be declared as ``const`` to support read-only buffers as input: .. literalinclude:: ../../examples/userguide/memoryviews/np_flag_const.pyx Using a non-const memoryview with a binary Python string produces a runtime error. You can solve this issue with a ``const`` memoryview: .. literalinclude:: ../../examples/userguide/memoryviews/view_string.pyx Note that this does not *require* the input buffer to be read-only:: a = np.linspace(0, 10, num=50) myslice = a # read-only view of a writable buffer Writable buffers are still accepted by ``const`` views, but read-only buffers are not accepted for non-const, writable views:: cdef double[:] myslice # a normal read/write memory view a = np.linspace(0, 10, num=50) a.setflags(write=False) myslice = a # ERROR: requesting writable memory view from read-only buffer! Comparison to the old buffer support ==================================== You will probably prefer memoryviews to the older syntax because: * The syntax is cleaner * Memoryviews do not usually need the GIL (see :ref:`view_needs_gil`) * Memoryviews are considerably faster For example, this is the old syntax equivalent of the ``sum3d`` function above: .. literalinclude:: ../../examples/userguide/memoryviews/old_sum3d.pyx Note that we can't use ``nogil`` for the buffer version of the function as we could for the memoryview version of ``sum3d`` above, because buffer objects are Python objects. However, even if we don't use ``nogil`` with the memoryview, it is significantly faster. This is a output from an IPython session after importing both versions:: In [2]: import numpy as np In [3]: arr = np.zeros((40, 40, 40), dtype=int) In [4]: timeit -r15 old_sum3d(arr) 1000 loops, best of 15: 298 us per loop In [5]: timeit -r15 sum3d(arr) 1000 loops, best of 15: 219 us per loop Python buffer support ===================== Cython memoryviews support nearly all objects exporting the interface of Python `new style buffers`_. This is the buffer interface described in `PEP 3118`_. NumPy arrays support this interface, as do :ref:`view_cython_arrays`. The "nearly all" is because the Python buffer interface allows the *elements* in the data array to themselves be pointers; Cython memoryviews do not yet support this. .. _`new style buffers`: https://docs.python.org/3/c-api/buffer.html .. _view_memory_layout: Memory layout ============= The buffer interface allows objects to identify the underlying memory in a variety of ways. With the exception of pointers for data elements, Cython memoryviews support all Python new-type buffer layouts. It can be useful to know or specify memory layout if the memory has to be in a particular format for an external routine, or for code optimization. Background ---------- The concepts are as follows: there is data access and data packing. Data access means either direct (no pointer) or indirect (pointer). Data packing means your data may be contiguous or not contiguous in memory, and may use *strides* to identify the jumps in memory consecutive indices need to take for each dimension. NumPy arrays provide a good model of strided direct data access, so we'll use them for a refresher on the concepts of C and Fortran contiguous arrays, and data strides. Brief recap on C, Fortran and strided memory layouts ---------------------------------------------------- The simplest data layout might be a C contiguous array. This is the default layout in NumPy and Cython arrays. C contiguous means that the array data is continuous in memory (see below) and that neighboring elements in the first dimension of the array are furthest apart in memory, whereas neighboring elements in the last dimension are closest together. For example, in NumPy:: In [2]: arr = np.array([['0', '1', '2'], ['3', '4', '5']], dtype='S1') Here, ``arr[0, 0]`` and ``arr[0, 1]`` are one byte apart in memory, whereas ``arr[0, 0]`` and ``arr[1, 0]`` are 3 bytes apart. This leads us to the idea of *strides*. Each axis of the array has a stride length, which is the number of bytes needed to go from one element on this axis to the next element. In the case above, the strides for axes 0 and 1 will obviously be:: In [3]: arr.strides Out[4]: (3, 1) For a 3D C contiguous array:: In [5]: c_contig = np.arange(24, dtype=np.int8).reshape((2,3,4)) In [6] c_contig.strides Out[6]: (12, 4, 1) A Fortran contiguous array has the opposite memory ordering, with the elements on the first axis closest together in memory:: In [7]: f_contig = np.array(c_contig, order='F') In [8]: np.all(f_contig == c_contig) Out[8]: True In [9]: f_contig.strides Out[9]: (1, 2, 6) A contiguous array is one for which a single continuous block of memory contains all the data for the elements of the array, and therefore the memory block length is the product of number of elements in the array and the size of the elements in bytes. In the example above, the memory block is 2 * 3 * 4 * 1 bytes long, where 1 is the length of an ``np.int8``. An array can be contiguous without being C or Fortran order:: In [10]: c_contig.transpose((1, 0, 2)).strides Out[10]: (4, 12, 1) Slicing an NumPy array can easily make it not contiguous:: In [11]: sliced = c_contig[:,1,:] In [12]: sliced.strides Out[12]: (12, 1) In [13]: sliced.flags Out[13]: C_CONTIGUOUS : False F_CONTIGUOUS : False OWNDATA : False WRITEABLE : True ALIGNED : True UPDATEIFCOPY : False Default behavior for memoryview layouts --------------------------------------- As you'll see in :ref:`view_general_layouts`, you can specify memory layout for any dimension of an memoryview. For any dimension for which you don't specify a layout, then the data access is assumed to be direct, and the data packing assumed to be strided. For example, that will be the assumption for memoryviews like: .. tabs:: .. group-tab:: Pure Python .. code-block:: python my_memoryview: cython.int[:, :, :] = obj .. group-tab:: Cython .. code-block:: cython int [:, :, :] my_memoryview = obj .. _c_and_fortran_contiguous_memoryviews: C and Fortran contiguous memoryviews ------------------------------------ You can specify C and Fortran contiguous layouts for the memoryview by using the ``::1`` step syntax at definition. For example, if you know for sure your memoryview will be on top of a 3D C contiguous layout, you could write: .. tabs:: .. group-tab:: Pure Python .. code-block:: python c_contiguous: cython.int[:, :, ::1] = c_contig .. group-tab:: Cython .. code-block:: cython cdef int[:, :, ::1] c_contiguous = c_contig where ``c_contig`` could be a C contiguous NumPy array. The ``::1`` at the 3rd position means that the elements in this 3rd dimension will be one element apart in memory. If you know you will have a 3D Fortran contiguous array: .. tabs:: .. group-tab:: Pure Python .. code-block:: python f_contiguous: cython.int[::1, :, :] = f_contig .. group-tab:: Cython .. code-block:: cython cdef int[::1, :, :] f_contiguous = f_contig If you pass a non-contiguous buffer, for example: .. tabs:: .. group-tab:: Pure Python .. code-block:: python # This array is C contiguous c_contig = np.arange(24).reshape((2,3,4)) c_contiguous: cython.int[:, :, ::1] = c_contig # But this isn't c_contiguous = np.array(c_contig, order='F') .. group-tab:: Cython .. code-block:: cython # This array is C contiguous c_contig = np.arange(24).reshape((2,3,4)) cdef int[:, :, ::1] c_contiguous = c_contig # But this isn't c_contiguous = np.array(c_contig, order='F') you will get a ``ValueError`` at runtime:: /Users/mb312/dev_trees/minimal-cython/mincy.pyx in init mincy (mincy.c:17267)() 69 70 # But this isn't ---> 71 c_contiguous = np.array(c_contig, order='F') 72 73 # Show the sum of all the arrays before altering it /Users/mb312/dev_trees/minimal-cython/stringsource in View.MemoryView.memoryview_cwrapper (mincy.c:9995)() /Users/mb312/dev_trees/minimal-cython/stringsource in View.MemoryView.memoryview.__cinit__ (mincy.c:6799)() ValueError: ndarray is not C-contiguous Thus the ``::1`` in the slice type specification indicates in which dimension the data is contiguous. It can only be used to specify full C or Fortran contiguity. .. _view_copy_c_fortran: C and Fortran contiguous copies ------------------------------- .. Mark : I could not make this work - should it? # This slice is C contiguous c_contig = np.arange(24).reshape((2,3,4)) f_contig = np.array(c_contig, order='F') cdef int [:, :, ::1] c_contig_view = c_contig cdef int [::1, :, :] f_contig_view = f_contig cdef int[:, :, ::1] f2c = f_contig_view.copy() cdef int[::1, :, :] c2f = c_contig_view.copy_fortran() Copies can be made C or Fortran contiguous using the ``.copy()`` and ``.copy_fortran()`` methods: .. tabs:: .. group-tab:: Pure Python .. code-block:: python # This view is C contiguous c_contiguous: cython.int[:, :, ::1] = myview.copy() # This view is Fortran contiguous f_contiguous_slice: cython.int[::1, :] = myview.copy_fortran() .. group-tab:: Cython .. code-block:: cython # This view is C contiguous cdef int[:, :, ::1] c_contiguous = myview.copy() # This view is Fortran contiguous cdef int[::1, :] f_contiguous_slice = myview.copy_fortran() .. _view_general_layouts: Specifying more general memory layouts -------------------------------------- Data layout can be specified using the previously seen ``::1`` slice syntax, or by using any of the constants in ``cython.view``. If no specifier is given in any dimension, then the data access is assumed to be direct, and the data packing assumed to be strided. If you don't know whether a dimension will be direct or indirect (because you're getting an object with a buffer interface from some library perhaps), then you can specify the ``generic`` flag, in which case it will be determined at runtime. The flags are as follows: * ``generic`` - strided and direct or indirect * ``strided`` - strided and direct (this is the default) * ``indirect`` - strided and indirect * ``contiguous`` - contiguous and direct * ``indirect_contiguous`` - the list of pointers is contiguous and they can be used like this: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/memoryviews/memory_layout.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/memoryviews/memory_layout.pyx Only the first, last or the dimension following an indirect dimension may be specified contiguous: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/memoryviews/memory_layout_2.py :lines: 2-13 .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/memoryviews/memory_layout_2.pyx :lines: 2-12 The difference between the ``contiguous`` flag and the ``::1`` specifier is that the former specifies contiguity for only one dimension, whereas the latter specifies contiguity for all following (Fortran) or preceding (C) dimensions: .. tabs:: .. group-tab:: Pure Python .. code-block:: python c_contig: cython.int[:, ::1] = ... # VALID myslice: cython.int[:, ::view.contiguous] = c_contig[::2] # INVALID myslice: cython.int[:, ::1] = c_contig[::2] .. group-tab:: Cython .. code-block:: cython cdef int[:, ::1] c_contig = ... # VALID cdef int[:, ::view.contiguous] myslice = c_contig[::2] # INVALID cdef int[:, ::1] myslice = c_contig[::2] The former case is valid because the last dimension remains contiguous, but the first dimension does not "follow" the last one anymore (meaning, it was strided already, but it is not C or Fortran contiguous any longer), since it was sliced. .. _view_needs_gil: Memoryviews and the GIL ======================= As you will see from the :ref:`view_quickstart` section, memoryviews often do not need the GIL: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.nogil @cython.ccall def sum3d(arr: cython.int[:, :, :]) -> cython.int: ... .. group-tab:: Cython .. code-block:: cython cpdef int sum3d(int[:, :, :] arr) nogil: ... In particular, you do not need the GIL for memoryview indexing, slicing or transposing. Memoryviews require the GIL for the copy methods (:ref:`view_copy_c_fortran`), or when the dtype is object and an object element is read or written. Memoryview Objects and Cython Arrays ==================================== These typed memoryviews can be converted to Python memoryview objects (``cython.view.memoryview``). These Python objects are indexable, sliceable and transposable in the same way that the original memoryviews are. They can also be converted back to Cython-space memoryviews at any time. They have the following attributes: * ``shape``: size in each dimension, as a tuple. * ``strides``: stride along each dimension, in bytes. * ``suboffsets`` * ``ndim``: number of dimensions. * ``size``: total number of items in the view (product of the shape). * ``itemsize``: size, in bytes, of the items in the view. * ``nbytes``: equal to ``size`` times ``itemsize``. * ``base`` And of course the aforementioned ``T`` attribute (:ref:`view_transposing`). These attributes have the same semantics as in NumPy_. For instance, to retrieve the original object: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/memoryviews/cython_array.py :lines: 2- .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/memoryviews/cython_array.pyx :lines: 2- Note that this example returns the original object from which the view was obtained, and that the view was resliced in the meantime. .. _view_cython_arrays: Cython arrays ============= Whenever a Cython memoryview is copied (using any of the ``copy()`` or ``copy_fortran()`` methods), you get a new memoryview slice of a newly created ``cython.view.array`` object. This array can also be used manually, and will automatically allocate a block of data. It can later be assigned to a C or Fortran contiguous slice (or a strided slice). It can be used like: .. tabs:: .. group-tab:: Pure Python .. code-block:: python from cython.cimports.cython import view my_array = view.array(shape=(10, 2), itemsize=cython.sizeof(cython.int), format="i") my_slice: cython.int[:, :] = my_array .. group-tab:: Cython .. code-block:: cython from cython cimport view my_array = view.array(shape=(10, 2), itemsize=sizeof(int), format="i") cdef int[:, :] my_slice = my_array It also takes an optional argument ``mode`` ('c' or 'fortran') and a boolean ``allocate_buffer``, that indicates whether a buffer should be allocated and freed when it goes out of scope: .. tabs:: .. group-tab:: Pure Python .. code-block:: python my_array: view.array = view.array(..., mode="fortran", allocate_buffer=False) my_array.data = cython.cast(cython.p_char, my_data_pointer) # define a function that can deallocate the data (if needed) my_array.callback_free_data = free .. group-tab:: Cython .. code-block:: cython cdef view.array my_array = view.array(..., mode="fortran", allocate_buffer=False) my_array.data = my_data_pointer # define a function that can deallocate the data (if needed) my_array.callback_free_data = free You can also cast pointers to array, or C arrays to arrays: .. tabs:: .. group-tab:: Pure Python .. code-block:: python my_array: view.array = cython.cast(cython.int[:10, :2], my_data_pointer) my_array: view.array = cython.cast(cython.int[:, :], my_c_array) .. group-tab:: Cython .. code-block:: cython cdef view.array my_array = my_data_pointer cdef view.array my_array = my_c_array Of course, you can also immediately assign a cython.view.array to a typed memoryview slice. A C array may be assigned directly to a memoryview slice: .. tabs:: .. group-tab:: Pure Python .. code-block:: python myslice: cython.int[:, ::1] = my_2d_c_array .. group-tab:: Cython .. code-block:: cython cdef int[:, ::1] myslice = my_2d_c_array The arrays are indexable and sliceable from Python space just like memoryview objects, and have the same attributes as memoryview objects. CPython array module ==================== An alternative to ``cython.view.array`` is the ``array`` module in the Python standard library. In Python 3, the ``array.array`` type supports the buffer interface natively, so memoryviews work on top of it without additional setup. Starting with Cython 0.17, however, it is possible to use these arrays as buffer providers also in Python 2. This is done through explicitly cimporting the ``cpython.array`` module as follows: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/memoryviews/cpython_array.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/memoryviews/cpython_array.pyx Note that the cimport also enables the old buffer syntax for the array type. Therefore, the following also works: .. tabs:: .. group-tab:: Pure Python .. code-block:: python from cython.cimports.cpython import array def sum_array(arr: array.array[cython.int]): # using old buffer syntax ... .. group-tab:: Cython .. code-block:: cython from cpython cimport array def sum_array(array.array[int] arr): # using old buffer syntax ... Coercion to NumPy ================= Memoryview (and array) objects can be coerced to a NumPy ndarray, without having to copy the data. You can e.g. do: .. tabs:: .. group-tab:: Pure Python .. code-block:: python from cython.cimports.numpy import int32_t import numpy as np numpy_array = np.asarray(cython.cast(int32_t[:10, :10], my_pointer)) .. group-tab:: Cython .. code-block:: cython cimport numpy as cnp import numpy as np numpy_array = np.asarray( my_pointer) Of course, you are not restricted to using NumPy's type (such as ``cnp.int32_t`` here), you can use any usable type. None Slices =========== Although memoryview slices are not objects they can be set to ``None`` and they can be checked for being ``None`` as well: .. tabs:: .. group-tab:: Pure Python .. code-block:: python def func(myarray: typing.Optional[cython.double[:]] = None): print(myarray is None) .. group-tab:: Cython .. code-block:: cython def func(double[:] myarray = None): print(myarray is None) If the function requires real memory views as input, it is therefore best to reject ``None`` input straight away in the signature: .. tabs:: .. group-tab:: Pure Python .. code-block:: python def func(myarray: cython.double[:]): ... .. group-tab:: Cython .. code-block:: cython def func(double[:] myarray not None): ... Unlike object attributes of extension classes, memoryview slices are not initialized to ``None``. Pass data from a C function via pointer ======================================= Since use of pointers in C is ubiquitous, here we give a quick example of how to call C functions whose arguments contain pointers. Let's suppose you want to manage an array (allocate and deallocate) with NumPy (it can also be Python arrays, or anything that supports the buffer interface), but you want to perform computation on this array with an external C function implemented in :file:`C_func_file.c`: .. literalinclude:: ../../examples/userguide/memoryviews/C_func_file.c :caption: C_func_file.c :linenos: This file comes with a header file called :file:`C_func_file.h` containing: .. literalinclude:: ../../examples/userguide/memoryviews/C_func_file.h :caption: C_func_file.h :linenos: where ``arr`` points to the array and ``n`` is its size. You can call the function in a Cython file in the following way: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/memoryviews/memview_to_c.pxd :caption: memview_to_c.pxd :linenos: .. literalinclude:: ../../examples/userguide/memoryviews/memview_to_c.py :caption: memview_to_c.py :linenos: .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/memoryviews/memview_to_c.pyx :caption: memview_to_c.pyx :linenos: Several things to note: - ``::1`` requests a C contiguous view, and fails if the buffer is not C contiguous. See :ref:`c_and_fortran_contiguous_memoryviews`. - ``&arr_memview[0]`` and ``cython.address(arr_memview[0]`` can be understood as 'the address of the first element of the memoryview'. For contiguous arrays, this is equivalent to the start address of the flat memory buffer. - ``arr_memview.shape[0]`` could have been replaced by ``arr_memview.size``, ``arr.shape[0]`` or ``arr.size``. But ``arr_memview.shape[0]`` is more efficient because it doesn't require any Python interaction. - ``multiply_by_10`` will perform computation in-place if the array passed is contiguous, and will return a new numpy array if ``arr`` is not contiguous. - If you are using Python arrays instead of numpy arrays, you don't need to check if the data is stored contiguously as this is always the case. See :ref:`array-array`. This way, you can call the C function similar to a normal Python function, and leave all the memory management and cleanup to NumPy arrays and Python's object handling. For the details of how to compile and call functions in C files, see :ref:`using_c_libraries`. Performance: Disabling initialization checks ============================================ Every time the memoryview is accessed, Cython adds a check to make sure that it has been initialized. If you are looking for performance, you can disable them by setting the ``initializedcheck`` directive to ``False``. See: :ref:`compiler-directives` for more information about this directive. .. _GIL: https://docs.python.org/dev/glossary.html#term-global-interpreter-lock .. _NumPy: https://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html#memory-layout .. _example: https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/migrating_to_cy30.rst0000644000175100001770000002755700000000000023402 0ustar00runnerdocker00000000000000.. highlight:: cython .. _cython30: ********************************* Migrating from Cython 0.29 to 3.0 ********************************* Cython 3.0 is a major revision of the compiler and the language that comes with some backwards incompatible changes. This document lists the important ones and explains how to deal with them in existing code. Python 3 syntax/semantics ========================= Cython 3.0 now uses Python 3 syntax and semantics by default, which previously required setting the ``language_level`` `directive ` to either ``3`` or ``3str``. The new default setting is now ``language_level=3str``, which means Python 3 semantics, but unprefixed strings are ``str`` objects, i.e. unicode text strings under Python 3 and byte strings under Python 2.7. You can revert your code to the previous (Python 2.x) semantics by setting ``language_level=2``. Further semantic changes due to the language level include: * ``/``-division uses the true (float) division operator, unless ``cdivision`` is enabled. * ``print`` is a function, not a statement. * Python classes that are defined without bases (``class C: ...``) are "new-style" classes also in Py2.x (if you never heard about "old-style classes", you're probably happy without them). * Annotations (type hints) are now stored as strings. (`PEP 563 `_) * ``StopIteration`` handling in generators has been changed according to `PEP 479 `_. Python semantics ================ Some Python compatibility bugs were fixed, e.g. * Subscripting (``x[1]``) now tries the mapping protocol before the sequence protocol. (https://github.com/cython/cython/issues/1807) * Exponentiation of integer literals now follows Python semantics and not C semantics. (https://github.com/cython/cython/issues/2133) Binding functions ================= The :ref:`binding directive ` is now enabled by default. This makes Cython compiled Python (``def``) functions mostly compatible with normal (non-compiled) Python functions, regarding signature introspection, annotations, etc. It also makes them bind as methods in Python classes on attribute assignments, thus the name. If this is not intended, i.e. if a function is really meant to be a function and never a method, you can disable the binding (and all other Python function features) by setting ``binding=False`` or selectively adding a decorator ``@cython.binding(False)``. In pure Python mode, the decorator was not available in Cython 0.29.16 yet, but compiled code does not suffer from this. We recommend, however, to keep the new function features and instead deal with the binding issue using the standard Python ``staticmethod()`` builtin. :: def func(self, b): ... class MyClass(object): binding_method = func no_method = staticmethod(func) Namespace packages ================== Cython now has support for loading pxd files also from namespace packages according to `PEP-420 `_. This might have an impact on the import path. NumPy C-API =========== Cython used to generate code that depended on the deprecated pre-NumPy-1.7 C-API. This is no longer the case with Cython 3.0. You can now define the macro ``NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION`` to get rid of the long-standing build warnings that the compiled C module uses a deprecated API. Either per file:: # distutils: define_macros=NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION or by setting it in your Extensions in ``setup.py``:: Extension(... define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")] ) One side-effect of the different C-API usage is that your code may now require a call to the `NumPy C-API initialisation function `_ where it previously got away without doing so. In order to reduce the user impact here, Cython 3.0 will now call it automatically when it sees ``numpy`` being cimported, but the function not being used. In the (hopefully rare) cases where this gets in the way, the internal C-API initialisation can be disabled by faking the use of the function without actually calling it, e.g. :: # Explicitly disable the automatic initialisation of NumPy's C-API. import_array Class-private name mangling =========================== Cython has been updated to follow the `Python rules for class-private names `_ more closely. Essentially any name that starts with and doesn't end with ``__`` within a class is mangled with the class name. Most user code should be unaffected -- unlike in Python unmangled global names will still be matched to ensure it is possible to access C names beginning with ``__``:: cdef extern void __foo() class C: # or "cdef class" def call_foo(self): return __foo() # still calls the global name What will no-longer work is overriding methods starting with ``__`` in a ``cdef class``:: cdef class Base: cdef __bar(self): return 1 def call_bar(self): return self.__bar() cdef class Derived(Base): cdef __bar(self): return 2 Here ``Base.__bar`` is mangled to ``_Base__bar`` and ``Derived.__bar`` to ``_Derived__bar``. Therefore ``call_bar`` will always call ``_Base__bar``. This matches established Python behaviour and applies for ``def``, ``cdef`` and ``cpdef`` methods and attributes. Arithmetic special methods ========================== The behaviour of arithmetic special methods (for example ``__add__`` and ``__pow__``) of cdef classes has changed in Cython 3.0. They now support separate "reversed" versions of these methods (e.g. ``__radd__``, ``__rpow__``) that behave like in pure Python. The main incompatible change is that the type of the first operand (usually ``__self__``) is now assumed to be that of the defining class, rather than relying on the user to test and cast the type of each operand. The old behaviour can be restored with the :ref:`directive ` ``c_api_binop_methods=True``. More details are given in :ref:`arithmetic_methods`. Exception values and ``noexcept`` ================================= ``cdef`` functions that are not ``extern`` now safely propagate Python exceptions by default. Previously, they needed to explicitly be declared with an :ref:`exception value ` to prevent them from swallowing exceptions. A new ``noexcept`` modifier can be used to declare ``cdef`` functions that really will not raise exceptions. In existing code, you should mainly look out for ``cdef`` functions that are declared without an exception value:: cdef int spam(int x): pass cdef void silent(int x): pass If you left out the exception value by mistake, i.e., the function should propagate Python exceptions, then the new behaviour will take care of this for you, and correctly propagate any exceptions. This was a common mistake in Cython code and the main reason to change the behaviour. On the other hand, if you didn't declare an exception value because you want to avoid exceptions propagating out of this function, the new behaviour will result in slightly less efficient code being generated, now involving an exception check. To prevent that, you must declare the function explicitly as being ``noexcept``:: cdef int spam(int x) noexcept: pass cdef void silent(int x) noexcept: pass The behaviour for ``cdef`` functions that are also ``extern`` is unchanged as ``extern`` functions are less likely to raise Python exceptions and rather tend to be plain C functions. This mitigates the effect of this change for code that talks to C libraries. The behaviour for any ``cdef`` function that is declared with an explicit exception value (e.g., ``cdef int spam(int x) except -1``) is also unchanged. There is an easy-to-encounter performance pitfall here with ``nogil`` functions with an implicit exception specification of ``except *``. This can happen most commonly when the return type is ``void`` (but in principle applies to most non-numeric return types). In this case, Cython is forced to re-acquire the GIL briefly *after each call* to check the exception state. To avoid this overhead, either change the signature to ``noexcept`` (if you have determined that it's suitable to do so), or to returning an ``int`` instead to let Cython use the ``int`` as an error flag (by default, ``-1`` triggers the exception check). .. note:: The unsafe legacy behaviour of not propagating exceptions by default can be enabled by setting ``legacy_implicit_noexcept`` :ref:`compiler directive` to ``True``. Annotation typing ================= Cython 3 has made substantial improvements in recognising types in annotations and it is well worth reading :ref:`the pure Python tutorial` to understand some of the improvements. A notable backwards-incompatible change is that ``x: int`` is now typed such that ``x`` is an exact Python ``int`` (Cython 0.29 would accept any Python object for ``x``), unless the language level is explicitly set to 2. To mitigate the effect, Cython 3.0 still accepts both Python ``int`` and ``long`` values under Python 2.x. To make it easier to handle cases where your interpretation of type annotations differs from Cython's, Cython 3 now supports setting the ``annotation_typing`` :ref:`directive ` on a per-class or per-function level. C++ postincrement/postdecrement operator ======================================== Cython 3 differentiates between pre/post-increment and pre/post-decrement operators (Cython 0.29 implemented both as pre(in/de)crement operator). This only has an effect when using ``cython.operator.postdecrement`` / ``cython.operator.postincrement``. When running into an error it is required to add the corresponding operator:: cdef cppclass Example: Example operator++(int) Example operator--(int) Public Declarations in C++ ========================== Public declarations in C++ mode are exported as C++ API in Cython 3, using ``extern "C++"``. This behaviour can be changed by setting the export keyword using the ``CYTHON_EXTERN_C`` macro to allow Cython modules to be implemented in C++ but callable from C. .. _power-operator: ``**`` power operator ===================== Cython 3 has changed the behaviour of the power operator to be more like Python. The consequences are that #. ``a**b`` of two ints may return a floating point type, #. ``a**b`` of one or more non-complex floating point numbers may return a complex number. The old behaviour can be restored by setting the ``cpow`` :ref:`compiler directive ` to ``True``. .. _deprecated_DEF_IF: Deprecation of ``DEF`` / ``IF`` =============================== The :ref:`conditional compilation feature ` has been deprecated and should no longer be used in new code. It is expected to get removed in some future release. Usages of ``DEF`` should be replaced by: - global cdef constants - global enums (C or Python) - C macros, e.g. defined in :ref:`verbatim C code ` - the usual Python mechanisms for sharing values across modules and usages Usages of ``IF`` should be replaced by: - runtime conditions and conditional Python imports (i.e. the usual Python patterns) - leaving out unused C struct field names from a Cython extern struct definition (which does not have to be complete) - redefining an extern struct type under different Cython names, with different (e.g. version/platform dependent) attributes, but with the :ref:`same cname string `. - separating out optional (non-trivial) functionality into optional Cython modules and importing/using them at need (with regular runtime Python imports) - code generation, as a last resort ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/nogil.rst0000644000175100001770000001667600000000000021171 0ustar00runnerdocker00000000000000.. _cython_and_gil: Cython and the GIL ================== Python has a global lock (:term:`the GIL `) to ensure that data related to the Python interpreter is not corrupted. It is *sometimes* useful to release this lock in Cython when you are not accessing Python data. There are two occasions when you may want to release the GIL: #. Using :ref:`Cython's parallelism mechanism `. The contents of a ``prange`` loop for example are required to be ``nogil``. #. If you want other (external) Python threads to be able to run at the same time. #. if you have a large computationally/IO-intensive block that doesn't need the GIL then it may be "polite" to release it, just to benefit users of your code who want to do multi-threading. However, this is mostly useful rather than necessary. #. (very, very occasionally) in long-running Cython code that never calls into the Python interpreter, it can sometimes be useful to briefly release the GIL with a short ``with nogil: pass`` block. This is because Cython doesn't release it spontaneously (unlike the Python interpreter), so if you're waiting on another Python thread to complete a task, this can avoid deadlocks. This sub-point probably doesn't apply to you unless you're compiling GUI code with Cython. If neither of these two points apply then you probably do not need to release the GIL. The sort of Cython code that can run without the GIL (no calls to Python, purely C-level numeric operations) is often the sort of code that runs efficiently. This sometimes gives people the impression that the inverse is true and the trick is releasing the GIL, rather than the actual code they’re running. Don’t be misled by this -- your (single-threaded) code will run the same speed with or without the GIL. Marking functions as able to run without the GIL ------------------------------------------------ You can mark a whole function (either a Cython function or an :ref:`external function `) as ``nogil`` by appending this to the function signature or by using the ``@cython.nogil`` decorator: .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.nogil @cython.cfunc @cython.noexcept def some_func() -> None: ... .. group-tab:: Cython .. code-block:: cython cdef void some_func() noexcept nogil: .... Be aware that this does not release the GIL when calling the function. It merely indicates that a function is suitable for use when the GIL is released. It is also fine to call these functions while holding the GIL. In this case we've marked the function as ``noexcept`` to indicate that it cannot raise a Python exception. Be aware that a function with an ``except *`` exception specification (typically functions returning ``void``) will be expensive to call because Cython will need to temporarily reacquire the GIL after every call to check the exception state. Most other exception specifications are cheap to handle in a ``nogil`` block since the GIL is only acquired if an exception is actually thrown. Releasing (and reacquiring) the GIL ----------------------------------- To actually release the GIL you can use context managers .. tabs:: .. group-tab:: Pure Python .. code-block:: python with cython.nogil: ... # some code that runs without the GIL with cython.gil: ... # some code that runs with the GIL ... # some more code without the GIL .. group-tab:: Cython .. code-block:: cython with nogil: ... # some code that runs without the GIL with gil: ... # some code that runs with the GIL ... # some more code without the GIL The ``with gil`` block is a useful trick to allow a small chunk of Python code or Python object processing inside a non-GIL block. Try not to use it too much since there is a cost to waiting for and acquiring the GIL, and because these blocks cannot run in parallel since all executions require the same lock. A function may be marked as ``with gil`` or decorated with ``@cython.with_gil`` to ensure that the GIL is acquired immediately when calling it. .. tabs:: .. group-tab:: Pure Python .. code-block:: python @cython.with_gil @cython.cfunc def some_func() -> cython.int ... with cython.nogil: ... # some code that runs without the GIL some_func() # some_func() will internally acquire the GIL ... # some code that runs without the GIL some_func() # GIL is already held hence the function does not need to acquire the GIL .. group-tab:: Cython .. code-block:: cython cdef int some_func() with gil: ... with nogil: ... # some code that runs without the GIL some_func() # some_func() will internally acquire the GIL ... # some code that runs without the GIL some_func() # GIL is already held hence the function does not need to acquire the GIL Conditionally acquiring the GIL ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ It's possible to release the GIL based on a compile-time condition. This is most often used when working with :ref:`fusedtypes` .. tabs:: .. group-tab:: Pure Python .. code-block:: python with cython.nogil(some_type is not object): ... # some code that runs without the GIL, unless we're processing objects .. group-tab:: Cython .. code-block:: cython with nogil(some_type is not object): ... # some code that runs without the GIL, unless we're processing objects Exceptions and the GIL ---------------------- A small number of "Python operations" may be performed in a ``nogil`` block without needing to explicitly use ``with gil``. The main example is throwing exceptions. Here Cython knows that an exception will always require the GIL and so re-acquires it implicitly. Similarly, if a ``nogil`` function throws an exception, Cython is able to propagate it correctly without you needing to write explicit code to handle it. In most cases this is efficient since Cython is able to use the function's exception specification to check for an error, and then acquire the GIL only if needed, but ``except *`` functions are less efficient since Cython must always re-acquire the GIL. Don't use the GIL as a lock --------------------------- It may be tempting to try to use the GIL for your own locking purposes and to say "the entire contents of a ``with gil`` block will run atomically since we hold the GIL". Don't do this! The GIL is only for the benefit of the interpreter, not for you. There are two issues here: #. that future improvements in the Python interpreter may destroy your "locking". #. Second, that the GIL can be released if any Python code is executed. The easiest way to run arbitrary Python code is to destroy a Python object that has a ``__del__`` function, but there are numerous other creative ways to do so, and it is almost impossible to know that you aren't going to trigger one of these. If you want a reliable lock then use the tools in the standard library's ``threading`` module. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3607223 Cython-3.0.8/docs/src/userguide/numpy_pythran.rst0000644000175100001770000000352000000000000022756 0ustar00runnerdocker00000000000000.. highlight:: python .. _numpy-pythran: ************************** Pythran as a Numpy backend ************************** Using the flag ``--np-pythran``, it is possible to use the `Pythran`_ numpy implementation for numpy related operations. One advantage to use this backend is that the Pythran implementation uses C++ expression templates to save memory transfers and can benefit from SIMD instructions of modern CPU. This can lead to really interesting speedup in some cases, going from 2 up to 16, depending on the targeted CPU architecture and the original algorithm. Please note that this feature is experimental. Usage example with setuptools ----------------------------- You first need to install Pythran. See its `documentation `_ for more information. Then, simply add a ``cython: np_pythran=True`` directive at the top of the Python files that needs to be compiled using Pythran numpy support. Here is an example of a simple ``setup.py`` file using setuptools: .. code:: from setuptools import setup from Cython.Build import cythonize import numpy import pythran setup( name = "My hello app", ext_modules = cythonize('hello_pythran.pyx'), include_dirs = [numpy.get_include(), pythran.get_include()] ) Then, with the following header in ``hello_pythran.pyx``: .. code:: # cython: np_pythran=True ``hello_pythran.pyx`` will be compiled using Pythran numpy support. Please note that Pythran can further be tweaked by adding settings in the ``$HOME/.pythranrc`` file. For instance, this can be used to enable `Boost.SIMD`_ support. See the `Pythran user manual `_ for more information. .. _Pythran: https://github.com/serge-sans-paille/pythran .. _Boost.SIMD: https://github.com/NumScale/boost.simd ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/docs/src/userguide/numpy_tutorial.rst0000644000175100001770000005071300000000000023142 0ustar00runnerdocker00000000000000.. highlight:: cython .. _numpy_tutorial: ************************** Cython for NumPy users ************************** This tutorial is aimed at NumPy users who have no experience with Cython at all. If you have some knowledge of Cython you may want to skip to the ''Efficient indexing'' section. The main scenario considered is NumPy end-use rather than NumPy/SciPy development. The reason is that Cython is not (yet) able to support functions that are generic with respect to the number of dimensions in a high-level fashion. This restriction is much more severe for SciPy development than more specific, "end-user" functions. See the last section for more information on this. The style of this tutorial will not fit everybody, so you can also consider: * Kurt Smith's `video tutorial of Cython at SciPy 2015 `_. The slides and notebooks of this talk are `on github `_. * Basic Cython documentation (see `Cython front page `_). Cython at a glance ================== Cython is a compiler which compiles Python-like code files to C code. Still, ''Cython is not a Python to C translator''. That is, it doesn't take your full program and "turn it into C" -- rather, the result makes full use of the Python runtime environment. A way of looking at it may be that your code is still Python in that it runs within the Python runtime environment, but rather than compiling to interpreted Python bytecode one compiles to native machine code (but with the addition of extra syntax for easy embedding of faster C-like code). This has two important consequences: * Speed. How much depends very much on the program involved though. Typical Python numerical programs would tend to gain very little as most time is spent in lower-level C that is used in a high-level fashion. However for-loop-style programs can gain many orders of magnitude, when typing information is added (and is so made possible as a realistic alternative). * Easy calling into C code. One of Cython's purposes is to allow easy wrapping of C libraries. When writing code in Cython you can call into C code as easily as into Python code. Very few Python constructs are not yet supported, though making Cython compile all Python code is a stated goal, you can see the differences with Python in :ref:`limitations `. Your Cython environment ======================= Using Cython consists of these steps: 1. Write a :file:`.pyx` source file 2. Run the Cython compiler to generate a C file 3. Run a C compiler to generate a compiled library 4. Run the Python interpreter and ask it to import the module However there are several options to automate these steps: 1. The `SAGE `_ mathematics software system provides excellent support for using Cython and NumPy from an interactive command line or through a notebook interface (like Maple/Mathematica). See `this documentation `_. 2. Cython can be used as an extension within a Jupyter notebook, making it easy to compile and use Cython code with just a ``%%cython`` at the top of a cell. For more information see :ref:`Using the Jupyter Notebook `. 3. A version of pyximport is shipped with Cython, so that you can import pyx-files dynamically into Python and have them compiled automatically (See :ref:`pyximport`). 4. Cython supports setuptools so that you can very easily create build scripts which automate the process, this is the preferred method for Cython implemented libraries and packages. See :ref:`Basic setup.py `. 5. Manual compilation (see below) .. Note:: If using another interactive command line environment than SAGE, like IPython or Python itself, it is important that you restart the process when you recompile the module. It is not enough to issue an "import" statement again. Installation ============= If you already have a C compiler, just do: .. code-block:: bash pip install Cython otherwise, see :ref:`the installation page `. As of this writing SAGE comes with an older release of Cython than required for this tutorial. So if using SAGE you should download the newest Cython and then execute : .. code-block:: bash $ cd path/to/cython-distro $ path-to-sage/sage -python setup.py install This will install the newest Cython into SAGE. Manual compilation ==================== As it is always important to know what is going on, I'll describe the manual method here. First Cython is run: .. code-block:: bash $ cython yourmod.pyx This creates :file:`yourmod.c` which is the C source for a Python extension module. A useful additional switch is ``-a`` which will generate a document :file:`yourmod.html`) that shows which Cython code translates to which C code line by line. Then we compile the C file. This may vary according to your system, but the C file should be built like Python was built. Python documentation for writing extensions should have some details. On Linux this often means something like: .. code-block:: bash $ gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I/usr/include/python2.7 -o yourmod.so yourmod.c ``gcc`` should have access to the NumPy C header files so if they are not installed at :file:`/usr/include/numpy` or similar you may need to pass another option for those. You only need to provide the NumPy headers if you write:: cimport numpy in your Cython code. This creates :file:`yourmod.so` in the same directory, which is importable by Python by using a normal ``import yourmod`` statement. The first Cython program ========================== You can easily execute the code of this tutorial by downloading `the Jupyter notebook `_. The code below does the equivalent of this function in numpy:: def compute_np(array_1, array_2, a, b, c): return np.clip(array_1, 2, 10) * a + array_2 * b + c We'll say that ``array_1`` and ``array_2`` are 2D NumPy arrays of integer type and ``a``, ``b`` and ``c`` are three Python integers. This function uses NumPy and is already really fast, so it might be a bit overkill to do it again with Cython. This is for demonstration purposes. Nonetheless, we will show that we achieve a better speed and memory efficiency than NumPy at the cost of more verbosity. This code computes the function with the loops over the two dimensions being unrolled. It is both valid Python and valid Cython code. I'll refer to it as both :file:`compute_py.py` for the Python version and :file:`compute_cy.pyx` for the Cython version -- Cython uses ``.pyx`` as its file suffix (but it can also compile ``.py`` files). .. literalinclude:: ../../examples/userguide/numpy_tutorial/compute_py.py This should be compiled to produce :file:`compute_cy.so` for Linux systems (on Windows systems, this will be a ``.pyd`` file). We run a Python session to test both the Python version (imported from ``.py``-file) and the compiled Cython module. .. code-block:: ipythonconsole In [1]: import numpy as np In [2]: array_1 = np.random.uniform(0, 1000, size=(3000, 2000)).astype(np.intc) In [3]: array_2 = np.random.uniform(0, 1000, size=(3000, 2000)).astype(np.intc) In [4]: a = 4 In [5]: b = 3 In [6]: c = 9 In [7]: def compute_np(array_1, array_2, a, b, c): ...: return np.clip(array_1, 2, 10) * a + array_2 * b + c In [8]: %timeit compute_np(array_1, array_2, a, b, c) 103 ms ± 4.16 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) In [9]: import compute_py In [10]: compute_py.compute(array_1, array_2, a, b, c) 1min 10s ± 844 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) In [11]: import compute_cy In [12]: compute_cy.compute(array_1, array_2, a, b, c) 56.5 s ± 587 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) There's not such a huge difference yet; because the C code still does exactly what the Python interpreter does (meaning, for instance, that a new object is allocated for each number used). You can look at the Python interaction and the generated C code by using ``-a`` when calling Cython from the command line, ``%%cython -a`` when using a Jupyter Notebook, or by using ``cythonize('compute_cy.pyx', annotate=True)`` when using a ``setup.py``. Look at the generated html file and see what is needed for even the simplest statements. You get the point quickly. We need to give Cython more information; we need to add types. Adding types ============= To add types we use custom Cython syntax, so we are now breaking Python source compatibility. Here's :file:`compute_typed.pyx`. *Read the comments!* .. literalinclude:: ../../examples/userguide/numpy_tutorial/compute_typed.pyx .. figure:: compute_typed_html.jpg At this point, have a look at the generated C code for :file:`compute_cy.pyx` and :file:`compute_typed.pyx`. Click on the lines to expand them and see corresponding C. Especially have a look at the ``for-loops``: In :file:`compute_cy.c`, these are ~20 lines of C code to set up while in :file:`compute_typed.c` a normal C for loop is used. After building this and continuing my (very informal) benchmarks, I get: .. code-block:: ipythonconsole In [13]: %timeit compute_typed.compute(array_1, array_2, a, b, c) 26.5 s ± 422 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) So adding types does make the code faster, but nowhere near the speed of NumPy? What happened is that most of the time spend in this code is spent in the following lines, and those lines are slower to execute than in pure Python:: tmp = clip(array_1[x, y], 2, 10) tmp = tmp * a + array_2[x, y] * b result[x, y] = tmp + c So what made those line so much slower than in the pure Python version? ``array_1`` and ``array_2`` are still NumPy arrays, so Python objects, and expect Python integers as indexes. Here we pass C int values. So every time Cython reaches this line, it has to convert all the C integers to Python int objects. Since this line is called very often, it outweighs the speed benefits of the pure C loops that were created from the ``range()`` earlier. Furthermore, ``tmp * a + array_2[x, y] * b`` returns a Python integer and ``tmp`` is a C integer, so Cython has to do type conversions again. In the end those types conversions add up. And made our computation really slow. But this problem can be solved easily by using memoryviews. Efficient indexing with memoryviews =================================== There are still two bottlenecks that degrade the performance, and that is the array lookups and assignments, as well as C/Python types conversion. The ``[]``-operator still uses full Python operations -- what we would like to do instead is to access the data buffer directly at C speed. What we need to do then is to type the contents of the :obj:`ndarray` objects. We do this with a memoryview. There is :ref:`a page in the Cython documentation ` dedicated to it. In short, memoryviews are C structures that can hold a pointer to the data of a NumPy array and all the necessary buffer metadata to provide efficient and safe access: dimensions, strides, item size, item type information, etc... They also support slices, so they work even if the NumPy array isn't contiguous in memory. They can be indexed by C integers, thus allowing fast access to the NumPy array data. Here is how to declare a memoryview of integers:: cdef int [:] foo # 1D memoryview cdef int [:, :] foo # 2D memoryview cdef int [:, :, :] foo # 3D memoryview ... # You get the idea. No data is copied from the NumPy array to the memoryview in our example. As the name implies, it is only a "view" of the memory. So we can use the view ``result_view`` for efficient indexing and at the end return the real NumPy array ``result`` that holds the data that we operated on. Here is how to use them in our code: :file:`compute_memview.pyx` .. literalinclude:: ../../examples/userguide/numpy_tutorial/compute_memview.pyx Let's see how much faster accessing is now. .. code-block:: ipythonconsole In [22]: %timeit compute_memview.compute(array_1, array_2, a, b, c) 22.9 ms ± 197 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) Note the importance of this change. We're now 3081 times faster than an interpreted version of Python and 4.5 times faster than NumPy. Memoryviews can be used with slices too, or even with Python arrays. Check out the :ref:`memoryview page ` to see what they can do for you. Tuning indexing further ======================== The array lookups are still slowed down by two factors: 1. Bounds checking is performed. 2. Negative indices are checked for and handled correctly. The code above is explicitly coded so that it doesn't use negative indices, and it (hopefully) always access within bounds. With decorators, we can deactivate those checks:: ... cimport cython @cython.boundscheck(False) # Deactivate bounds checking @cython.wraparound(False) # Deactivate negative indexing. def compute(int[:, :] array_1, int[:, :] array_2, int a, int b, int c): ... Now bounds checking is not performed (and, as a side-effect, if you ''do'' happen to access out of bounds you will in the best case crash your program and in the worst case corrupt data). It is possible to switch bounds-checking mode in many ways, see :ref:`compiler-directives` for more information. .. code-block:: ipythonconsole In [23]: %timeit compute_index.compute(array_1, array_2, a, b, c) 16.8 ms ± 25.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) We're faster than the NumPy version (6.2x). NumPy is really well written, but does not performs operation lazily, resulting in a lot of intermediate copy operations in memory. Our version is very memory efficient and cache friendly because we can execute the operations in a single run over the data. .. Warning:: Speed comes with some cost. Especially it can be dangerous to set typed objects (like ``array_1``, ``array_2`` and ``result_view`` in our sample code) to ``None``. Setting such objects to ``None`` is entirely legal, but all you can do with them is check whether they are None. All other use (attribute lookup or indexing) can potentially segfault or corrupt data (rather than raising exceptions as they would in Python). The actual rules are a bit more complicated but the main message is clear: Do not use typed objects without knowing that they are not set to ``None``. Declaring the NumPy arrays as contiguous ======================================== For extra speed gains, if you know that the NumPy arrays you are providing are contiguous in memory, you can declare the memoryview as contiguous. We give an example on an array that has 3 dimensions. If you want to give Cython the information that the data is C-contiguous you have to declare the memoryview like this:: cdef int [:,:,::1] a If you want to give Cython the information that the data is Fortran-contiguous you have to declare the memoryview like this:: cdef int [::1, :, :] a If all this makes no sense to you, you can skip this part, declaring arrays as contiguous constrains the usage of your functions as it rejects array slices as input. If you still want to understand what contiguous arrays are all about, you can see `this answer on StackOverflow `_. For the sake of giving numbers, here are the speed gains that you should get by declaring the memoryviews as contiguous: .. code-block:: ipythonconsole In [23]: %timeit compute_contiguous.compute(array_1, array_2, a, b, c) 11.1 ms ± 30.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) We're now around nine times faster than the NumPy version, and 6300 times faster than the pure Python version! Making the function cleaner =========================== Declaring types can make your code quite verbose. If you don't mind Cython inferring the C types of your variables, you can use the ``infer_types=True`` compiler directive at the top of the file. It will save you quite a bit of typing. Note that since type declarations must happen at the top indentation level, Cython won't infer the type of variables declared for the first time in other indentation levels. It would change too much the meaning of our code. This is why, we must still declare manually the type of the ``tmp``, ``x`` and ``y`` variable. And actually, manually giving the type of the ``tmp`` variable will be useful when using fused types. .. literalinclude:: ../../examples/userguide/numpy_tutorial/compute_infer_types.pyx We now do a speed test: .. code-block:: ipythonconsole In [24]: %timeit compute_infer_types.compute(array_1, array_2, a, b, c) 11.5 ms ± 261 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) Lo and behold, the speed has not changed. More generic code ================== All those speed gains are nice, but adding types constrains our code. At the moment, it would mean that our function can only work with NumPy arrays with the ``np.intc`` type. Is it possible to make our code work for multiple NumPy data types? Yes, with the help of a new feature called fused types. You can learn more about it at :ref:`this section of the documentation `. It is similar to C++ 's templates. It generates multiple function declarations at compile time, and then chooses the right one at run-time based on the types of the arguments provided. By comparing types in if-conditions, it is also possible to execute entirely different code paths depending on the specific data type. In our example, since we don't have access anymore to the NumPy's dtype of our input arrays, we use those ``if-else`` statements to know what NumPy data type we should use for our output array. In this case, our function now works for ints, doubles and floats. .. literalinclude:: ../../examples/userguide/numpy_tutorial/compute_fused_types.pyx We can check that the output type is the right one:: >>> compute(array_1, array_2, a, b, c).dtype dtype('int32') >>> compute(array_1.astype(np.double), array_2.astype(np.double), a, b, c).dtype dtype('float64') We now do a speed test: .. code-block:: ipythonconsole In [25]: %timeit compute_fused_types.compute(array_1, array_2, a, b, c) 11.5 ms ± 258 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) More versions of the function are created at compile time. So it makes sense that the speed doesn't change for executing this function with integers as before. Using multiple threads ====================== Cython has support for OpenMP. It also has some nice wrappers around it, like the function :func:`prange`. You can see more information about Cython and parallelism in :ref:`parallel`. Since we do elementwise operations, we can easily distribute the work among multiple threads. It's important not to forget to pass the correct arguments to the compiler to enable OpenMP. When using the Jupyter notebook, you should use the cell magic like this: .. code-block:: ipython %%cython --force # distutils: extra_compile_args=-fopenmp # distutils: extra_link_args=-fopenmp For MSVC (on Windows) you should use ``/openmp`` instead of ``-fopenmp``. The GIL must be released (see :ref:`Releasing the GIL `), so this is why we declare our :func:`clip` function ``nogil``. .. literalinclude:: ../../examples/userguide/numpy_tutorial/compute_prange.pyx We can have substantial speed gains for minimal effort: .. code-block:: ipythonconsole In [25]: %timeit compute_prange.compute(array_1, array_2, a, b, c) 9.33 ms ± 412 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) We're now 7558 times faster than the pure Python version and 11.1 times faster than NumPy! Where to go from here? ====================== * If you want to learn how to make use of `BLAS `_ or `LAPACK `_ with Cython, you can watch `the presentation of Ian Henriksen at SciPy 2015 `_. * If you want to learn how to use Pythran as backend in Cython, you can see how in :ref:`Pythran as a NumPy backend `. Note that using Pythran only works with the :ref:`old buffer syntax ` and not yet with memoryviews. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/docs/src/userguide/numpy_ufuncs.rst0000644000175100001770000000455200000000000022602 0ustar00runnerdocker00000000000000.. highlight:: cython .. _numpy-ufuncs: ********************* Creating Numpy ufuncs ********************* .. include:: ../two-syntax-variants-used Numpy supports a `special type of function called a ufunc `_ . These support array broadcasting (i.e. the ability to handle arguments with any number of dimensions), alongside other useful features. Cython can generate a ufunc from a Cython C function by tagging it with the ``@cython.ufunc`` decorator. The input and output argument types should be scalar variables ("generic ufuncs" are not yet supported) and should either by Python objects or simple numeric types. The body of such a function is inserted into an efficient, compiled loop. .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/numpy_ufuncs/ufunc.py :lines: 2- .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/numpy_ufuncs/ufunc.pyx :lines: 2- You can have as many arguments to your function as you like. If you want to have multiple output arguments then you can use the :ref:`ctuple syntax`: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/numpy_ufuncs/ufunc_ctuple.py :lines: 2- .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/numpy_ufuncs/ufunc_ctuple.pyx :lines: 2- If you want to accept multiple different argument types then you can use :ref:`fusedtypes`: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/numpy_ufuncs/ufunc_fused.py :lines: 2- .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/numpy_ufuncs/ufunc_fused.pyx :lines: 2- Finally, if you declare the ``cdef``/``@cfunc`` function as ``nogil`` then Cython will release the :term:`GIL` once in the generated ufunc. This is a slight difference from the general behaviour of ``nogil`` functions (they generally do not automatically release the GIL, but instead can be run without the GIL). This feature relies on Numpy. Therefore if you create a ufunc in Cython, you must have the Numpy headers available when you build the generated C code, and users of your module must have Numpy installed when they run it. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/docs/src/userguide/parallelism.rst0000644000175100001770000002217500000000000022355 0ustar00runnerdocker00000000000000.. highlight:: cython .. py:module:: cython.parallel .. _parallel: ********************************** Using Parallelism ********************************** .. include:: ../two-syntax-variants-used Cython supports native parallelism through the :py:mod:`cython.parallel` module. To use this kind of parallelism, the :term:`GIL` must be released (see :ref:`Releasing the GIL `). It currently supports OpenMP, but later on more backends might be supported. .. NOTE:: Functionality in this module may only be used from the main thread or parallel regions due to OpenMP restrictions. .. function:: prange([start,] stop[, step][, nogil=False][, schedule=None[, chunksize=None]][, num_threads=None]) This function can be used for parallel loops. OpenMP automatically starts a thread pool and distributes the work according to the schedule used. Thread-locality and reductions are automatically inferred for variables. If you assign to a variable in a prange block, it becomes lastprivate, meaning that the variable will contain the value from the last iteration. If you use an inplace operator on a variable, it becomes a reduction, meaning that the values from the thread-local copies of the variable will be reduced with the operator and assigned to the original variable after the loop. The index variable is always lastprivate. Variables assigned to in a parallel with block will be private and unusable after the block, as there is no concept of a sequentially last value. :param start: The index indicating the start of the loop (same as the start argument in range). :param stop: The index indicating when to stop the loop (same as the stop argument in range). :param step: An integer giving the step of the sequence (same as the step argument in range). It must not be 0. :param nogil: This function can only be used with the GIL released. If ``nogil`` is true, the loop will be wrapped in a nogil section. :param schedule: The ``schedule`` is passed to OpenMP and can be one of the following: static: If a chunksize is provided, iterations are distributed to all threads ahead of time in blocks of the given chunksize. If no chunksize is given, the iteration space is divided into chunks that are approximately equal in size, and at most one chunk is assigned to each thread in advance. This is most appropriate when the scheduling overhead matters and the problem can be cut down into equally sized chunks that are known to have approximately the same runtime. dynamic: The iterations are distributed to threads as they request them, with a default chunk size of 1. This is suitable when the runtime of each chunk differs and is not known in advance and therefore a larger number of smaller chunks is used in order to keep all threads busy. guided: As with dynamic scheduling, the iterations are distributed to threads as they request them, but with decreasing chunk size. The size of each chunk is proportional to the number of unassigned iterations divided by the number of participating threads, decreasing to 1 (or the chunksize if provided). This has an advantage over pure dynamic scheduling when it turns out that the last chunks take more time than expected or are otherwise being badly scheduled, so that most threads start running idle while the last chunks are being worked on by only a smaller number of threads. runtime: The schedule and chunk size are taken from the runtime scheduling variable, which can be set through the ``openmp.omp_set_schedule()`` function call, or the ``OMP_SCHEDULE`` environment variable. Note that this essentially disables any static compile time optimisations of the scheduling code itself and may therefore show a slightly worse performance than when the same scheduling policy is statically configured at compile time. The default schedule is implementation defined. For more information consult the OpenMP specification [#]_. .. auto The decision regarding scheduling is delegated to the .. compiler and/or runtime system. The programmer gives .. the implementation the freedom to choose any possible .. mapping of iterations to threads in the team. :param num_threads: The ``num_threads`` argument indicates how many threads the team should consist of. If not given, OpenMP will decide how many threads to use. Typically this is the number of cores available on the machine. However, this may be controlled through the ``omp_set_num_threads()`` function, or through the ``OMP_NUM_THREADS`` environment variable. :param chunksize: The ``chunksize`` argument indicates the chunksize to be used for dividing the iterations among threads. This is only valid for ``static``, ``dynamic`` and ``guided`` scheduling, and is optional. Different chunksizes may give substantially different performance results, depending on the schedule, the load balance it provides, the scheduling overhead and the amount of false sharing (if any). Example with a reduction: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/parallelism/simple_sum.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/parallelism/simple_sum.pyx Example with a :term:`typed memoryview` (e.g. a NumPy array) .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/parallelism/memoryview_sum.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/parallelism/memoryview_sum.pyx .. function:: parallel(num_threads=None) This directive can be used as part of a ``with`` statement to execute code sequences in parallel. This is currently useful to setup thread-local buffers used by a prange. A contained prange will be a worksharing loop that is not parallel, so any variable assigned to in the parallel section is also private to the prange. Variables that are private in the parallel block are unavailable after the parallel block. Example with thread-local buffers .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/parallelism/parallel.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/parallelism/parallel.pyx Later on sections might be supported in parallel blocks, to distribute code sections of work among threads. .. function:: threadid() Returns the id of the thread. For n threads, the ids will range from 0 to n-1. Compiling ========= To actually use the OpenMP support, you need to tell the C or C++ compiler to enable OpenMP. For gcc this can be done as follows in a ``setup.py``: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/parallelism/setup_py.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/parallelism/setup_pyx.py For the Microsoft Visual C++ compiler, use ``'/openmp'`` instead of ``'-fopenmp'`` for the ``'extra_compile_args'`` option. Don't add any OpenMP flags to the ``'extra_link_args'`` option. Breaking out of loops ===================== The parallel with and prange blocks support the statements break, continue and return in nogil mode. Additionally, it is valid to use a ``with gil`` block inside these blocks, and have exceptions propagate from them. However, because the blocks use OpenMP, they can not just be left, so the exiting procedure is best-effort. For ``prange()`` this means that the loop body is skipped after the first break, return or exception for any subsequent iteration in any thread. It is undefined which value shall be returned if multiple different values may be returned, as the iterations are in no particular order: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/parallelism/breaking_loop.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/parallelism/breaking_loop.pyx In the example above it is undefined whether an exception shall be raised, whether it will simply break or whether it will return 2. Using OpenMP Functions ====================== OpenMP functions can be used by cimporting ``openmp``: .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/parallelism/cimport_openmp.py :lines: 3- .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/parallelism/cimport_openmp.pyx :lines: 3- .. rubric:: References .. [#] https://www.openmp.org/mp-documents/spec30.pdf ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/docs/src/userguide/pypy.rst0000644000175100001770000001733100000000000021047 0ustar00runnerdocker00000000000000Porting Cython code to PyPy =========================== Cython has basic support for cpyext, the layer in `PyPy `_ that emulates CPython's C-API. This is achieved by making the generated C code adapt at C compile time, so the generated code will compile in both CPython and PyPy unchanged. However, beyond what Cython can cover and adapt internally, the cpyext C-API emulation involves some differences to the real C-API in CPython that have a visible impact on user code. This page lists major differences and ways to deal with them in order to write Cython code that works in both CPython and PyPy. Reference counts ---------------- A general design difference in PyPy is that the runtime does not use reference counting internally but always a garbage collector. Reference counting is only emulated at the cpyext layer by counting references being held in C space. This implies that the reference count in PyPy is generally different from that in CPython because it does not count any references held in Python space. Object lifetime --------------- As a direct consequence of the different garbage collection characteristics, objects may see the end of their lifetime at other points than in CPython. Special care therefore has to be taken when objects are expected to have died in CPython but may not in PyPy. Specifically, a deallocator method of an extension type (``__dealloc__()``) may get called at a much later point than in CPython, triggered rather by memory getting tighter than by objects dying. If the point in the code is known when an object is supposed to die (e.g. when it is tied to another object or to the execution time of a function), it is worth considering if it can be invalidated and cleaned up manually at that point, rather than relying on a deallocator. As a side effect, this can sometimes even lead to a better code design, e.g. when context managers can be used together with the ``with`` statement. Borrowed references and data pointers ------------------------------------- The memory management in PyPy is allowed to move objects around in memory. The C-API layer is only an indirect view on PyPy objects and often replicates data or state into C space that is then tied to the lifetime of a C-API object rather then the underlying PyPy object. It is important to understand that these two objects are separate things in cpyext. The effect can be that when data pointers or borrowed references are used, and the owning object is no longer directly referenced from C space, the reference or data pointer may become invalid at some point, even if the object itself is still alive. As opposed to CPython, it is not enough to keep the reference to the object alive in a list (or other Python container), because the contents of those is only managed in Python space and thus only references the PyPy object. A reference in a Python container will not keep the C-API view on it alive. Entries in a Python class dict will obviously not work either. One of the more visible places where this may happen is when accessing the :c:type:`char*` buffer of a byte string. In PyPy, this will only work as long as the Cython code holds a direct reference to the byte string object itself. Another point is when CPython C-API functions are used directly that return borrowed references, e.g. :c:func:`PyTuple_GET_ITEM()` and similar functions, but also some functions that return borrowed references to built-in modules or low-level objects of the runtime environment. The GIL in PyPy only guarantees that the borrowed reference stays valid up to the next call into PyPy (or its C-API), but not necessarily longer. When accessing the internals of Python objects or using borrowed references longer than up to the next call into PyPy, including reference counting or anything that frees the GIL, it is therefore required to additionally keep direct owned references to these objects alive in C space, e.g. in local variables in a function or in the attributes of an extension type. When in doubt, avoid using C-API functions that return borrowed references, or surround the usage of a borrowed reference explicitly by a pair of calls to :c:func:`Py_INCREF()` when getting the reference and :c:func:`Py_DECREF()` when done with it to convert it into an owned reference. Builtin types, slots and fields ------------------------------- The following builtin types are not currently available in cpyext in form of their C level representation: :c:type:`PyComplexObject`, :c:type:`PyFloatObject` and :c:type:`PyBoolObject`. Many of the type slot functions of builtin types are not initialised in cpyext and can therefore not be used directly. Similarly, almost none of the (implementation) specific struct fields of builtin types is exposed at the C level, such as the ``ob_digit`` field of :c:type:`PyLongObject` or the ``allocated`` field of the :c:type:`PyListObject` struct etc. Although the ``ob_size`` field of containers (used by the :c:func:`Py_SIZE()` macro) is available, it is not guaranteed to be accurate. It is best not to access any of these struct fields and slots and to use the normal Python types instead as well as the normal Python protocols for object operations. Cython will map them to an appropriate usage of the C-API in both CPython and cpyext. GIL handling ------------ Currently, the GIL handling function :c:func:`PyGILState_Ensure` is not re-entrant in PyPy and deadlocks when called twice. This means that code that tries to acquire the GIL "just in case", because it might be called with or without the GIL, will not work as expected in PyPy. See `PyGILState_Ensure should not deadlock if GIL already held `_. Efficiency ---------- Simple functions and especially macros that are used for speed in CPython may exhibit substantially different performance characteristics in cpyext. Functions returning borrowed references were already mentioned as requiring special care, but they also induce substantially more runtime overhead because they often create weak references in PyPy where they only return a plain pointer in CPython. A visible example is :c:func:`PyTuple_GET_ITEM()`. Some more high-level functions may also show entirely different performance characteristics, e.g. :c:func:`PyDict_Next()` for dict iteration. While being the fastest way to iterate over a dict in CPython, having linear time complexity and a low overhead, it currently has quadratic runtime in PyPy because it maps to normal dict iteration, which cannot keep track of the current position between two calls and thus needs to restart the iteration on each call. The general advice applies here even more than in CPython, that it is always best to rely on Cython generating appropriately adapted C-API handling code for you than to use the C-API directly - unless you really know what you are doing. And if you find a better way of doing something in PyPy and cpyext than Cython currently does, it's best to fix Cython for everyone's benefit. Known problems -------------- * As of PyPy 1.9, subtyping builtin types can result in infinite recursion on method calls in some rare cases. * Docstrings of special methods are not propagated to Python space. * The Python 3.x adaptations in pypy3 only slowly start to include the C-API, so more incompatibilities can be expected there. Bugs and crashes ---------------- The cpyext implementation in PyPy is much younger and substantially less mature than the well tested C-API and its underlying native implementation in CPython. This should be remembered when running into crashes, as the problem may not always be in your code or in Cython. Also, PyPy and its cpyext implementation are less easy to debug at the C level than CPython and Cython, simply because they were not designed for it. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/docs/src/userguide/pyrex_differences.rst0000644000175100001770000002642600000000000023557 0ustar00runnerdocker00000000000000.. highlight:: cython .. _pyrex-differences: ************************************** Differences between Cython and Pyrex ************************************** .. warning:: Both Cython and Pyrex are moving targets. It has come to the point that an explicit list of all the differences between the two projects would be laborious to list and track, but hopefully this high-level list gives an idea of the differences that are present. It should be noted that both projects make an effort at mutual compatibility, but Cython's goal is to be as close to and complete as Python as reasonable. Python 3 Support ================ Cython creates ``.c`` files that can be built and used with both Python 2.x and Python 3.x. In fact, compiling your module with Cython may very well be an easy way to port code to Python 3. Cython also supports various syntax additions that came with Python 3.0 and later major Python releases. If they do not conflict with existing Python 2.x syntax or semantics, they are usually just accepted by the compiler. Everything else depends on the compiler directive ``language_level=3`` (see :ref:`compiler directives`). List/Set/Dict Comprehensions ---------------------------- Cython supports the different comprehensions defined by Python 3 for lists, sets and dicts:: [expr(x) for x in A] # list {expr(x) for x in A} # set {key(x) : value(x) for x in A} # dict Looping is optimized if ``A`` is a list, tuple or dict. You can use the :keyword:`for` ... :keyword:`from` syntax, too, but it is generally preferred to use the usual :keyword:`for` ... :keyword:`in` ``range(...)`` syntax with a C run variable (e.g. ``cdef int i``). .. note:: see :ref:`automatic-range-conversion` Note that Cython also supports set literals starting from Python 2.4. Keyword-only arguments ---------------------- Python functions can have keyword-only arguments listed after the ``*`` parameter and before the ``**`` parameter if any, e.g.:: def f(a, b, *args, c, d = 42, e, **kwds): ... Here ``c``, ``d`` and ``e`` cannot be passed as position arguments and must be passed as keyword arguments. Furthermore, ``c`` and ``e`` are required keyword arguments, since they do not have a default value. If the parameter name after the ``*`` is omitted, the function will not accept any extra positional arguments, e.g.:: def g(a, b, *, c, d): ... takes exactly two positional parameters and has two required keyword parameters. Conditional expressions "x if b else y" ========================================= Conditional expressions as described in https://www.python.org/dev/peps/pep-0308/:: X if C else Y Only one of ``X`` and ``Y`` is evaluated (depending on the value of C). .. _inline: cdef inline ============= Module level functions can now be declared inline, with the :keyword:`inline` keyword passed on to the C compiler. These can be as fast as macros.:: cdef inline int something_fast(int a, int b): return a*a + b Note that class-level :keyword:`cdef` functions are handled via a virtual function table, so the compiler won't be able to inline them in almost all cases. Assignment on declaration (e.g. "cdef int spam = 5") ====================================================== In Pyrex, one must write:: cdef int i, j, k i = 2 j = 5 k = 7 Now, with cython, one can write:: cdef int i = 2, j = 5, k = 7 The expression on the right hand side can be arbitrarily complicated, e.g.:: cdef int n = python_call(foo(x,y), a + b + c) - 32 'by' expression in for loop (e.g. "for i from 0 <= i < 10 by 2") ================================================================== :: for i from 0 <= i < 10 by 2: print i yields:: 0 2 4 6 8 .. note:: Usage of this syntax is discouraged as it is redundant with the normal Python :keyword:`for` loop. See :ref:`automatic-range-conversion`. Boolean int type (e.g. it acts like a c int, but coerces to/from python as a boolean) ====================================================================================== In C, ints are used for truth values. In python, any object can be used as a truth value (using the :meth:`__nonzero__` method), but the canonical choices are the two boolean objects ``True`` and ``False``. The :c:type:`bint` (for "boolean int") type is compiled to a C int, but coerces to and from Python as booleans. The return type of comparisons and several builtins is a :c:type:`bint` as well. This reduces the need for wrapping things in :func:`bool()`. For example, one can write:: def is_equal(x): return x == y which would return ``1`` or ``0`` in Pyrex, but returns ``True`` or ``False`` in Cython. One can declare variables and return values for functions to be of the :c:type:`bint` type. For example:: cdef int i = x cdef bint b = x The first conversion would happen via ``x.__int__()`` whereas the second would happen via ``x.__bool__()`` (a.k.a. ``__nonzero__()``), with appropriate optimisations for known builtin types. Executable class bodies ======================= Including a working :func:`classmethod`:: cdef class Blah: def some_method(self): print self some_method = classmethod(some_method) a = 2*3 print "hi", a cpdef functions ================= Cython adds a third function type on top of the usual :keyword:`def` and :keyword:`cdef`. If a function is declared :keyword:`cpdef` it can be called from and overridden by both extension and normal python subclasses. You can essentially think of a :keyword:`cpdef` method as a :keyword:`cdef` method + some extras. (That's how it's implemented at least.) First, it creates a :keyword:`def` method that does nothing but call the underlying :keyword:`cdef` method (and does argument unpacking/coercion if needed). At the top of the :keyword:`cdef` method a little bit of code is added to see if it's overridden, similar to the following pseudocode:: if hasattr(type(self), '__dict__'): foo = self.foo if foo is not wrapper_foo: return foo(args) [cdef method body] To detect whether or not a type has a dictionary, it just checks the ``tp_dictoffset`` slot, which is ``NULL`` (by default) for extension types, but non- null for instance classes. If the dictionary exists, it does a single attribute lookup and can tell (by comparing pointers) whether or not the returned result is actually a new function. If, and only if, it is a new function, then the arguments packed into a tuple and the method called. This is all very fast. A flag is set so this lookup does not occur if one calls the method on the class directly, e.g.:: cdef class A: cpdef foo(self): pass x = A() x.foo() # will check to see if overridden A.foo(x) # will call A's implementation whether overridden or not See :ref:`early-binding-for-speed` for explanation and usage tips. .. _automatic-range-conversion: Automatic range conversion ============================ This will convert statements of the form ``for i in range(...)`` to ``for i from ...`` when ``i`` is any cdef'd integer type, and the direction (i.e. sign of step) can be determined. .. warning:: This may change the semantics if the range causes assignment to ``i`` to overflow. Specifically, if this option is set, an error will be raised before the loop is entered, whereas without this option the loop will execute until a overflowing value is encountered. If this affects you, change ``Cython/Compiler/Options.py`` (eventually there will be a better way to set this). More friendly type casting =========================== In Pyrex, if one types ``x`` where ``x`` is a Python object, one will get the memory address of ``x``. Likewise, if one types ``i`` where ``i`` is a C int, one will get an "object" at location ``i`` in memory. This leads to confusing results and segfaults. In Cython ``x`` will try and do a coercion (as would happen on assignment of ``x`` to a variable of type type) if exactly one of the types is a python object. It does not stop one from casting where there is no conversion (though it will emit a warning). If one really wants the address, cast to a ``void *`` first. As in Pyrex ``x`` will cast ``x`` to type :c:type:`MyExtensionType` without any type checking. Cython supports the syntax ```` to do the cast with type checking (i.e. it will throw an error if ``x`` is not a (subclass of) :c:type:`MyExtensionType`. Optional arguments in cdef/cpdef functions ============================================ Cython now supports optional arguments for :keyword:`cdef` and :keyword:`cpdef` functions. The syntax in the ``.pyx`` file remains as in Python, but one declares such functions in the ``.pxd`` file by writing ``cdef foo(x=*)``. The number of arguments may increase on subclassing, but the argument types and order must remain the same. There is a slight performance penalty in some cases when a cdef/cpdef function without any optional is overridden with one that does have default argument values. For example, one can have the ``.pxd`` file: .. literalinclude:: ../../examples/userguide/language_basics/optional_subclassing.pxd with corresponding ``.pyx`` file: .. literalinclude:: ../../examples/userguide/language_basics/optional_subclassing.pyx .. note:: this also demonstrates how :keyword:`cpdef` functions can override :keyword:`cdef` functions. Function pointers in structs ============================= Functions declared in :keyword:`struct` are automatically converted to function pointers for convenience. C++ Exception handling ========================= :keyword:`cdef` functions can now be declared as:: cdef int foo(...) except + cdef int foo(...) except +TypeError cdef int foo(...) except +python_error_raising_function in which case a Python exception will be raised when a C++ error is caught. See :ref:`wrapping-cplusplus` for more details. Synonyms ========= ``cdef import from`` means the same thing as ``cdef extern from`` Source code encoding ====================== Cython supports :PEP:`3120` and :PEP:`263`, i.e. you can start your Cython source file with an encoding comment and generally write your source code in UTF-8. This impacts the encoding of byte strings and the conversion of unicode string literals like ``u'abcd'`` to unicode objects. Automatic ``typecheck`` ======================== Rather than introducing a new keyword ``typecheck`` as explained in the `Pyrex docs `_, Cython emits a (non-spoofable and faster) typecheck whenever :func:`isinstance` is used with an extension type as the second parameter. From __future__ directives ========================== Cython supports several ``from __future__ import ...`` directives, namely ``absolute_import``, ``unicode_literals``, ``print_function`` and ``division``. With statements are always enabled. Pure Python mode ================ Cython has support for compiling ``.py`` files, and accepting type annotations using decorators and other valid Python syntax. This allows the same source to be interpreted as straight Python, or compiled for optimized results. See :ref:`pure-mode` for more details. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/docs/src/userguide/sharing_declarations.rst0000644000175100001770000002631200000000000024230 0ustar00runnerdocker00000000000000.. highlight:: cython .. _sharing-declarations: ******************************************** Sharing Declarations Between Cython Modules ******************************************** .. include:: ../two-syntax-variants-used This section describes how to make C declarations, functions and extension types in one Cython module available for use in another Cython module. These facilities are closely modeled on the Python import mechanism, and can be thought of as a compile-time version of it. Definition and Implementation files ==================================== A Cython module can be split into two parts: a definition file with a ``.pxd`` suffix, containing C declarations that are to be available to other Cython modules, and an implementation file with a ``.pyx``/``.py`` suffix, containing everything else. When a module wants to use something declared in another module's definition file, it imports it using the :keyword:`cimport` statement or using special :py:mod:`cython.cimports` package. A ``.pxd`` file that consists solely of extern declarations does not need to correspond to an actual ``.pyx``/``.py`` file or Python module. This can make it a convenient place to put common declarations, for example declarations of functions from an :ref:`external library ` that one wants to use in several modules. What a Definition File contains ================================ A definition file can contain: * Any kind of C type declaration. * extern C function or variable declarations. * Declarations of C functions defined in the module. * The definition part of an extension type (see below). It cannot contain the implementations of any C or Python functions, or any Python class definitions, or any executable statements. It is needed when one wants to access :keyword:`cdef`/``@cfunc`` attributes and methods, or to inherit from :keyword:`cdef`/``@cclass`` classes defined in this module. .. note:: You don't need to (and shouldn't) declare anything in a declaration file public in order to make it available to other Cython modules; its mere presence in a definition file does that. You only need a public declaration if you want to make something available to external C code. What an Implementation File contains ====================================== An implementation file can contain any kind of Cython statement, although there are some restrictions on the implementation part of an extension type if the corresponding definition file also defines that type (see below). If one doesn't need to :keyword:`cimport` anything from this module, then this is the only file one needs. .. _cimport: The cimport statement ======================= The :keyword:`cimport` statement is used in a definition or implementation file to gain access to names declared in another definition file. Its syntax exactly parallels that of the normal Python import statement. When pure python syntax is used, the same effect can be done by importing from special :py:mod:`cython.cimports` package. In later text the term to ``cimport`` refers to using both :keyword:`cimport` statement or :py:mod:`cython.cimports` package. .. tabs:: .. group-tab:: Pure Python .. code-block:: python from cython.cimports.module import name [as name][, name [as name] ...] .. group-tab:: Cython .. code-block:: cython cimport module [, module...] from module cimport name [as name] [, name [as name] ...] Here is an example. :file:`dishes.pxd` is a definition file which exports a C data type. :file:`restaurant.pyx`/:file:`restaurant.py` is an implementation file which imports and uses it. .. literalinclude:: ../../examples/userguide/sharing_declarations/dishes.pxd :caption: dishes.pxd .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/sharing_declarations/restaurant.py :caption: dishes.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/sharing_declarations/restaurant.pyx :caption: dishes.pyx It is important to understand that the :keyword:`cimport` statement can only be used to import C data types, C functions and variables, and extension types. It cannot be used to import any Python objects, and (with one exception) it doesn't imply any Python import at run time. If you want to refer to any Python names from a module that you have cimported, you will have to include a regular import statement for it as well. The exception is that when you use :keyword:`cimport` to import an extension type, its type object is imported at run time and made available by the name under which you imported it. Using :keyword:`cimport` to import extension types is covered in more detail below. If a ``.pxd`` file changes, any modules that :keyword:`cimport` from it may need to be recompiled. The ``Cython.Build.cythonize`` utility can take care of this for you. Search paths for definition files ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ When you :keyword:`cimport` a module called ``modulename``, the Cython compiler searches for a file called :file:`modulename.pxd`. It searches for this file along the path for include files (as specified by ``-I`` command line options or the ``include_path`` option to ``cythonize()``), as well as ``sys.path``. Using ``package_data`` to install ``.pxd`` files in your ``setup.py`` script allows other packages to cimport items from your module as a dependency. Also, whenever you compile a file :file:`modulename.pyx`/:file:`modulename.py`, the corresponding definition file :file:`modulename.pxd` is first searched for along the include path (but not ``sys.path``), and if found, it is processed before processing the ``.pyx`` file. Using cimport to resolve naming conflicts ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The :keyword:`cimport` mechanism provides a clean and simple way to solve the problem of wrapping external C functions with Python functions of the same name. All you need to do is put the extern C declarations into a ``.pxd`` file for an imaginary module, and :keyword:`cimport` that module. You can then refer to the C functions by qualifying them with the name of the module. Here's an example: .. literalinclude:: ../../examples/userguide/sharing_declarations/c_lunch.pxd :caption: c_lunch.pxd .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/sharing_declarations/lunch.py :caption: lunch.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/sharing_declarations/lunch.pyx :caption: lunch.pyx You don't need any :file:`c_lunch.pyx`/:file:`c_lunch.py` file, because the only things defined in :file:`c_lunch.pxd` are extern C entities. There won't be any actual ``c_lunch`` module at run time, but that doesn't matter; the :file:`c_lunch.pxd` file has done its job of providing an additional namespace at compile time. Sharing C Functions =================== C functions defined at the top level of a module can be made available via :keyword:`cimport` by putting headers for them in the ``.pxd`` file, for example: .. literalinclude:: ../../examples/userguide/sharing_declarations/volume.pxd :caption: volume.pxd .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/sharing_declarations/volume.py :caption: volume.py .. literalinclude:: ../../examples/userguide/sharing_declarations/spammery.py :caption: spammery.py .. note:: Type definitions of function ``cube()`` in :file:`volume.py` are not provided since they are used from .pxd definition file. See :ref:`augmenting_pxd` and GitHub issue :issue:`4388`. .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/sharing_declarations/volume.pyx :caption: volume.pyx .. literalinclude:: ../../examples/userguide/sharing_declarations/spammery.pyx :caption: spammery.pyx .. _sharing_extension_types: Sharing Extension Types ======================= An extension type can be made available via :keyword:`cimport` by splitting its definition into two parts, one in a definition file and the other in the corresponding implementation file. The definition part of the extension type can only declare C attributes and C methods, not Python methods, and it must declare all of that type's C attributes and C methods. The implementation part must implement all of the C methods declared in the definition part, and may not add any further C attributes. It may also define Python methods. Here is an example of a module which defines and exports an extension type, and another module which uses it: .. literalinclude:: ../../examples/userguide/sharing_declarations/shrubbing.pxd :caption: shrubbing.pxd .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/sharing_declarations/shrubbing.py :caption: shrubbing.py .. literalinclude:: ../../examples/userguide/sharing_declarations/landscaping.py :caption: landscaping.py One would then need to compile both of these modules, e.g. using .. literalinclude:: ../../examples/userguide/sharing_declarations/setup_py.py :caption: setup.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/sharing_declarations/shrubbing.pyx :caption: shrubbing.pyx .. literalinclude:: ../../examples/userguide/sharing_declarations/landscaping.pyx :caption: landscaping.pyx One would then need to compile both of these modules, e.g. using .. literalinclude:: ../../examples/userguide/sharing_declarations/setup_pyx.py :caption: setup.py Some things to note about this example: * There is a :keyword:`cdef`/``@cclass`` class Shrubbery declaration in both :file:`shrubbing.pxd` and :file:`shrubbing.pyx`. When the shrubbing module is compiled, these two declarations are combined into one. * In :file:`landscaping.pyx`/:file:`landscaping.py`, the :keyword:`cimport` shrubbing declaration allows us to refer to the Shrubbery type as :class:`shrubbing.Shrubbery`. But it doesn't bind the name shrubbing in landscaping's module namespace at run time, so to access :func:`shrubbing.standard_shrubbery` we also need to ``import shrubbing``. .. _versioning: Versioning ========== ``.pxd`` files can be labelled with a minimum Cython version as part of their file name, similar to the version tagging of ``.so`` files in PEP 3149. For example a file called :file:`shrubbing.cython-30.pxd` will only be found by ``cimport shrubbing`` on Cython 3.0 and higher. Cython will use the file tagged with the highest compatible version number. Note that versioned files that are distributed across different directories will not be found. Only the first directory in the Python module search path in which a matching ``.pxd`` file is found will be considered. The purpose of this feature is to allow third-party packages to release Cython interfaces to their packages that take advantage of the latest Cython features while not breaking compatibility for users with older versions of Cython. Users intending to use ``.pxd`` files solely within their own project need not produce these tagged files. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/docs/src/userguide/source_files_and_compilation.rst0000644000175100001770000012476300000000000025760 0ustar00runnerdocker00000000000000.. highlight:: cython .. _compilation: **************************** Source Files and Compilation **************************** Cython source file names consist of the name of the module followed by a ``.pyx`` extension, for example a module called primes would have a source file named :file:`primes.pyx`. Cython code, unlike Python, must be compiled. This happens in two stages: * A ``.pyx`` (or ``.py``) file is compiled by Cython to a ``.c`` file. * The ``.c`` file is compiled by a C compiler to a ``.so`` file (or a ``.pyd`` file on Windows) Once you have written your ``.pyx``/``.py`` file, there are a couple of ways how to turn it into an extension module. The following sub-sections describe several ways to build your extension modules, and how to pass directives to the Cython compiler. There are also a number of tools that process ``.pyx`` files apart from Cython, e.g. - Linting: https://pypi.org/project/cython-lint/ .. _compiling_command_line: Compiling from the command line =============================== There are two ways of compiling from the command line. * The ``cython`` command takes a ``.py`` or ``.pyx`` file and compiles it into a C/C++ file. * The ``cythonize`` command takes a ``.py`` or ``.pyx`` file and compiles it into a C/C++ file. It then compiles the C/C++ file into an extension module which is directly importable from Python. Compiling with the ``cython`` command ------------------------------------- One way is to compile it manually with the Cython compiler, e.g.: .. code-block:: text $ cython primes.pyx This will produce a file called :file:`primes.c`, which then needs to be compiled with the C compiler using whatever options are appropriate on your platform for generating an extension module. For these options look at the official Python documentation. The other, and probably better, way is to use the :mod:`setuptools` extension provided with Cython. The benefit of this method is that it will give the platform specific compilation options, acting like a stripped down autotools. Compiling with the ``cythonize`` command ---------------------------------------- Run the ``cythonize`` compiler command with your options and list of ``.pyx`` files to generate an extension module. For example: .. code-block:: bash $ cythonize -a -i yourmod.pyx This creates a ``yourmod.c`` file (or ``yourmod.cpp`` in C++ mode), compiles it, and puts the resulting extension module (``.so`` or ``.pyd``, depending on your platform) next to the source file for direct import (``-i`` builds "in place"). The ``-a`` switch additionally produces an annotated html file of the source code. The ``cythonize`` command accepts multiple source files and glob patterns like ``**/*.pyx`` as argument and also understands the common ``-j`` option for running multiple parallel build jobs. When called without further options, it will only translate the source files to ``.c`` or ``.cpp`` files. Pass the ``-h`` flag for a complete list of supported options. There simpler command line tool ``cython`` only invokes the source code translator. In the case of manual compilation, how to compile your ``.c`` files will vary depending on your operating system and compiler. The Python documentation for writing extension modules should have some details for your system. On a Linux system, for example, it might look similar to this: .. code-block:: bash $ gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing \ -I/usr/include/python3.5 -o yourmod.so yourmod.c (``gcc`` will need to have paths to your included header files and paths to libraries you want to link with.) After compilation, a ``yourmod.so`` (:file:`yourmod.pyd` for Windows) file is written into the target directory and your module, ``yourmod``, is available for you to import as with any other Python module. Note that if you are not relying on ``cythonize`` or setuptools, you will not automatically benefit from the platform specific file extension that CPython generates for disambiguation, such as ``yourmod.cpython-35m-x86_64-linux-gnu.so`` on a regular 64bit Linux installation of CPython 3.5. .. _basic_setup.py: Basic setup.py =============== The setuptools extension provided with Cython allows you to pass ``.pyx`` files directly to the ``Extension`` constructor in your setup file. If you have a single Cython file that you want to turn into a compiled extension, say with filename :file:`example.pyx` the associated :file:`setup.py` would be:: from setuptools import setup from Cython.Build import cythonize setup( ext_modules = cythonize("example.pyx") ) If your build depends directly on Cython in this way, then you may also want to inform pip that :mod:`Cython` is required for :file:`setup.py` to execute, following `PEP 518 `, creating a :file:`pyproject.toml` file containing, at least: .. code-block:: ini [build-system] requires = ["setuptools", "wheel", "Cython"] To understand the :file:`setup.py` more fully look at the official `setuptools documentation`_. To compile the extension for use in the current directory use: .. code-block:: text $ python setup.py build_ext --inplace Configuring the C-Build ------------------------ If you have include files in non-standard places you can pass an ``include_path`` parameter to ``cythonize``:: from setuptools import setup from Cython.Build import cythonize setup( name="My hello app", ext_modules=cythonize("src/*.pyx", include_path=[...]), ) Often, Python packages that offer a C-level API provide a way to find the necessary include files, e.g. for NumPy:: include_path = [numpy.get_include()] .. note:: Using memoryviews or importing NumPy with ``import numpy`` does not mean that you have to add the path to NumPy include files. You need to add this path only if you use ``cimport numpy``. Despite this, you may still get warnings like the following from the compiler, because Cython is not disabling the usage of the old deprecated Numpy API:: .../include/numpy/npy_1_7_deprecated_api.h:15:2: warning: #warning "Using deprecated NumPy API, disable it by " "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp] In Cython 3.0, you can get rid of this warning by defining the C macro ``NPY_NO_DEPRECATED_API`` as ``NPY_1_7_API_VERSION`` in your build, e.g.:: # distutils: define_macros=NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION or (see below):: Extension( ..., define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")], ) With older Cython releases, setting this macro will fail the C compilation, because Cython generates code that uses this deprecated C-API. However, the warning has no negative effects even in recent NumPy versions including 1.18.x. You can ignore it until you (or your library's users) switch to a newer NumPy version that removes this long deprecated API, in which case you also need to use Cython 3.0 or later. Thus, the earlier you switch to Cython 3.0, the better for your users. If you need to specify compiler options, libraries to link with or other linker options you will need to create ``Extension`` instances manually (note that glob syntax can still be used to specify multiple extensions in one line):: from setuptools import Extension, setup from Cython.Build import cythonize extensions = [ Extension("primes", ["primes.pyx"], include_dirs=[...], libraries=[...], library_dirs=[...]), # Everything but primes.pyx is included here. Extension("*", ["*.pyx"], include_dirs=[...], libraries=[...], library_dirs=[...]), ] setup( name="My hello app", ext_modules=cythonize(extensions), ) Note that when using setuptools, you should import it before Cython, otherwise, both might disagree about the class to use here. If your options are static (for example you do not need to call a tool like ``pkg-config`` to determine them) you can also provide them directly in your .pyx or .pxd source file using a special comment block at the start of the file:: # distutils: libraries = spam eggs # distutils: include_dirs = /opt/food/include If you cimport multiple .pxd files defining libraries, then Cython merges the list of libraries, so this works as expected (similarly with other options, like ``include_dirs`` above). If you have some C files that have been wrapped with Cython and you want to compile them into your extension, you can define the setuptools ``sources`` parameter:: # distutils: sources = helper.c, another_helper.c Note that these sources are added to the list of sources of the current extension module. Spelling this out in the :file:`setup.py` file looks as follows:: from setuptools import Extension, setup from Cython.Build import cythonize sourcefiles = ['example.pyx', 'helper.c', 'another_helper.c'] extensions = [Extension("example", sourcefiles)] setup( ext_modules=cythonize(extensions) ) The :class:`Extension` class takes many options, and a fuller explanation can be found in the `setuptools documentation`_. Some useful options to know about are ``include_dirs``, ``libraries``, and ``library_dirs`` which specify where to find the ``.h`` and library files when linking to external libraries. .. _setuptools documentation: https://setuptools.readthedocs.io/ Sometimes this is not enough and you need finer customization of the setuptools :class:`Extension`. To do this, you can provide a custom function ``create_extension`` to create the final :class:`Extension` object after Cython has processed the sources, dependencies and ``# distutils`` directives but before the file is actually Cythonized. This function takes 2 arguments ``template`` and ``kwds``, where ``template`` is the :class:`Extension` object given as input to Cython and ``kwds`` is a :class:`dict` with all keywords which should be used to create the :class:`Extension`. The function ``create_extension`` must return a 2-tuple ``(extension, metadata)``, where ``extension`` is the created :class:`Extension` and ``metadata`` is metadata which will be written as JSON at the top of the generated C files. This metadata is only used for debugging purposes, so you can put whatever you want in there (as long as it can be converted to JSON). The default function (defined in ``Cython.Build.Dependencies``) is:: def default_create_extension(template, kwds): if 'depends' in kwds: include_dirs = kwds.get('include_dirs', []) + ["."] depends = resolve_depends(kwds['depends'], include_dirs) kwds['depends'] = sorted(set(depends + template.depends)) t = template.__class__ ext = t(**kwds) metadata = dict(distutils=kwds, module_name=kwds['name']) return ext, metadata In case that you pass a string instead of an :class:`Extension` to ``cythonize()``, the ``template`` will be an :class:`Extension` without sources. For example, if you do ``cythonize("*.pyx")``, the ``template`` will be ``Extension(name="*.pyx", sources=[])``. Just as an example, this adds ``mylib`` as library to every extension:: from Cython.Build.Dependencies import default_create_extension def my_create_extension(template, kwds): libs = kwds.get('libraries', []) + ["mylib"] kwds['libraries'] = libs return default_create_extension(template, kwds) ext_modules = cythonize(..., create_extension=my_create_extension) .. note:: If you Cythonize in parallel (using the ``nthreads`` argument), then the argument to ``create_extension`` must be pickleable. In particular, it cannot be a lambda function. .. _cythonize_arguments: Cythonize arguments ------------------- The function :func:`cythonize` can take extra arguments which will allow you to customize your build. .. autofunction:: Cython.Build.cythonize Multiple Cython Files in a Package =================================== To automatically compile multiple Cython files without listing all of them explicitly, you can use glob patterns:: setup( ext_modules = cythonize("package/*.pyx") ) You can also use glob patterns in :class:`Extension` objects if you pass them through :func:`cythonize`:: extensions = [Extension("*", ["*.pyx"])] setup( ext_modules = cythonize(extensions) ) .. _distributing_cython_modules: Distributing Cython modules ---------------------------- It is strongly recommended that you distribute the generated ``.c`` files as well as your Cython sources, so that users can install your module without needing to have Cython available. It is also recommended that Cython compilation not be enabled by default in the version you distribute. Even if the user has Cython installed, he/she probably doesn't want to use it just to install your module. Also, the installed version may not be the same one you used, and may not compile your sources correctly. This simply means that the :file:`setup.py` file that you ship with will just be a normal setuptools file on the generated `.c` files, for the basic example we would have instead:: from setuptools import Extension, setup setup( ext_modules = [Extension("example", ["example.c"])] ) This is easy to combine with :func:`cythonize` by changing the file extension of the extension module sources:: from setuptools import Extension, setup USE_CYTHON = ... # command line option, try-import, ... ext = '.pyx' if USE_CYTHON else '.c' extensions = [Extension("example", ["example"+ext])] if USE_CYTHON: from Cython.Build import cythonize extensions = cythonize(extensions) setup( ext_modules = extensions ) If you have many extensions and want to avoid the additional complexity in the declarations, you can declare them with their normal Cython sources and then call the following function instead of ``cythonize()`` to adapt the sources list in the Extensions when not using Cython:: import os.path def no_cythonize(extensions, **_ignore): for extension in extensions: sources = [] for sfile in extension.sources: path, ext = os.path.splitext(sfile) if ext in ('.pyx', '.py'): if extension.language == 'c++': ext = '.cpp' else: ext = '.c' sfile = path + ext sources.append(sfile) extension.sources[:] = sources return extensions Another option is to make Cython a setup dependency of your system and use Cython's build_ext module which runs ``cythonize`` as part of the build process:: setup( extensions = [Extension("*", ["*.pyx"])], cmdclass={'build_ext': Cython.Build.build_ext}, ... ) This depends on pip knowing that :mod:`Cython` is a setup dependency, by having a :file:`pyproject.toml` file:: [build-system] requires = ["setuptools", "wheel", "Cython"] If you want to expose the C-level interface of your library for other libraries to cimport from, use package_data to install the ``.pxd`` files, e.g.:: setup( package_data = { 'my_package': ['*.pxd'], 'my_package/sub_package': ['*.pxd'], }, ... ) These ``.pxd`` files need not have corresponding ``.pyx`` modules if they contain purely declarations of external libraries. .. _integrating_multiple_modules: Integrating multiple modules ============================ In some scenarios, it can be useful to link multiple Cython modules (or other extension modules) into a single binary, e.g. when embedding Python in another application. This can be done through the inittab import mechanism of CPython. Create a new C file to integrate the extension modules and add this macro to it:: #if PY_MAJOR_VERSION < 3 # define MODINIT(name) init ## name #else # define MODINIT(name) PyInit_ ## name #endif If you are only targeting Python 3.x, just use ``PyInit_`` as prefix. Then, for each of the modules, declare its module init function as follows, replacing ``some_module_name`` with the name of the module:: PyMODINIT_FUNC MODINIT(some_module_name) (void); In C++, declare them as ``extern C``. If you are not sure of the name of the module init function, refer to your generated module source file and look for a function name starting with ``PyInit_``. Next, before you start the Python runtime from your application code with ``Py_Initialize()``, you need to initialise the modules at runtime using the ``PyImport_AppendInittab()`` C-API function, again inserting the name of each of the modules:: PyImport_AppendInittab("some_module_name", MODINIT(some_module_name)); This enables normal imports for the embedded extension modules. In order to prevent the joined binary from exporting all of the module init functions as public symbols, Cython 0.28 and later can hide these symbols if the macro ``CYTHON_NO_PYINIT_EXPORT`` is defined while C-compiling the module C files. Also take a look at the `cython_freeze `_ tool. It can generate the necessary boilerplate code for linking one or more modules into a single Python executable. .. _pyximport: Compiling with :mod:`pyximport` =============================== For building Cython modules during development without explicitly running ``setup.py`` after each change, you can use :mod:`pyximport`:: >>> import pyximport; pyximport.install() >>> import helloworld Hello World This allows you to automatically run Cython on every ``.pyx`` that Python is trying to import. You should use this for simple Cython builds only where no extra C libraries and no special building setup is needed. It is also possible to compile new ``.py`` modules that are being imported (including the standard library and installed packages). For using this feature, just tell that to :mod:`pyximport`:: >>> pyximport.install(pyimport=True) In the case that Cython fails to compile a Python module, :mod:`pyximport` will fall back to loading the source modules instead. Note that it is not recommended to let :mod:`pyximport` build code on end user side as it hooks into their import system. The best way to cater for end users is to provide pre-built binary packages in the `wheel `_ packaging format. Arguments --------- The function ``pyximport.install()`` can take several arguments to influence the compilation of Cython or Python files. .. autofunction:: pyximport.install Dependency Handling -------------------- Since :mod:`pyximport` does not use :func:`cythonize()` internally, it currently requires a different setup for dependencies. It is possible to declare that your module depends on multiple files, (likely ``.h`` and ``.pxd`` files). If your Cython module is named ``foo`` and thus has the filename :file:`foo.pyx` then you should create another file in the same directory called :file:`foo.pyxdep`. The :file:`modname.pyxdep` file can be a list of filenames or "globs" (like ``*.pxd`` or ``include/*.h``). Each filename or glob must be on a separate line. Pyximport will check the file date for each of those files before deciding whether to rebuild the module. In order to keep track of the fact that the dependency has been handled, Pyximport updates the modification time of your ".pyx" source file. Future versions may do something more sophisticated like informing setuptools of the dependencies directly. Limitations ------------ :mod:`pyximport` does not use :func:`cythonize()`. Thus it is not possible to do things like using compiler directives at the top of Cython files or compiling Cython code to C++. Pyximport does not give you any control over how your Cython file is compiled. Usually the defaults are fine. You might run into problems if you wanted to write your program in half-C, half-Cython and build them into a single library. Pyximport does not hide the setuptools/GCC warnings and errors generated by the import process. Arguably this will give you better feedback if something went wrong and why. And if nothing went wrong it will give you the warm fuzzy feeling that pyximport really did rebuild your module as it was supposed to. Basic module reloading support is available with the option ``reload_support=True``. Note that this will generate a new module filename for each build and thus end up loading multiple shared libraries into memory over time. CPython has limited support for reloading shared libraries as such, see `PEP 489 `_. Pyximport puts both your ``.c`` file and the platform-specific binary into a separate build directory, usually ``$HOME/.pyxblx/``. To copy it back into the package hierarchy (usually next to the source file) for manual reuse, you can pass the option ``inplace=True``. .. _compiling_with_cython_inline: Compiling with ``cython.inline`` ================================= One can also compile Cython in a fashion similar to SciPy's ``weave.inline``. For example:: >>> import cython >>> def f(a): ... ret = cython.inline("return a+b", b=3) ... Unbound variables are automatically pulled from the surrounding local and global scopes, and the result of the compilation is cached for efficient reuse. Compiling with ``cython.compile`` ================================= Cython supports transparent compiling of the cython code in a function using the ``@cython.compile`` decorator:: @cython.compile def plus(a, b): return a + b Parameters of the decorated function cannot have type declarations. Their types are automatically determined from values passed to the function, thus leading to one or more specialised compiled functions for the respective argument types. Executing example:: import cython @cython.compile def plus(a, b): return a + b print(plus('3', '5')) print(plus(3, 5)) will produce following output:: 35 8 .. _compiling_with_sage: Compiling with Sage =================== The Sage notebook allows transparently editing and compiling Cython code simply by typing ``%cython`` at the top of a cell and evaluate it. Variables and functions defined in a Cython cell are imported into the running session. Please check `Sage documentation `_ for details. You can tailor the behavior of the Cython compiler by specifying the directives below. .. _compiling_notebook: Compiling with a Jupyter Notebook ================================= It's possible to compile code in a notebook cell with Cython. For this you need to load the Cython magic:: %load_ext cython Then you can define a Cython cell by writing ``%%cython`` on top of it. Like this:: %%cython cdef int a = 0 for i in range(10): a += i print(a) Note that each cell will be compiled into a separate extension module. So if you use a package in a Cython cell, you will have to import this package in the same cell. It's not enough to have imported the package in a previous cell. Cython will tell you that there are "undefined global names" at compilation time if you don't comply. The global names (top level functions, classes, variables and modules) of the cell are then loaded into the global namespace of the notebook. So in the end, it behaves as if you executed a Python cell. Additional allowable arguments to the Cython magic are listed below. You can see them also by typing ```%%cython?`` in IPython or a Jupyter notebook. ============================================ ======================================================================================================================================= -a, --annotate Produce a colorized HTML version of the source. --annotate-fullc Produce a colorized HTML version of the source which includes entire generated C/C++-code. -+, --cplus Output a C++ rather than C file. -f, --force Force the compilation of a new module, even if the source has been previously compiled. -3 Select Python 3 syntax -2 Select Python 2 syntax -c=COMPILE_ARGS, --compile-args=COMPILE_ARGS Extra flags to pass to compiler via the extra_compile_args. --link-args LINK_ARGS Extra flags to pass to linker via the extra_link_args. -l LIB, --lib LIB Add a library to link the extension against (can be specified multiple times). -L dir Add a path to the list of library directories (can be specified multiple times). -I INCLUDE, --include INCLUDE Add a path to the list of include directories (can be specified multiple times). -S, --src Add a path to the list of src files (can be specified multiple times). -n NAME, --name NAME Specify a name for the Cython module. --pgo Enable profile guided optimisation in the C compiler. Compiles the cell twice and executes it in between to generate a runtime profile. --verbose Print debug information like generated .c/.cpp file location and exact gcc/g++ command invoked. ============================================ ======================================================================================================================================= .. _compiler_options: Compiler options ---------------- Compiler options can be set in the :file:`setup.py`, before calling :func:`cythonize`, like this:: from setuptools import setup from Cython.Build import cythonize from Cython.Compiler import Options Options.docstrings = False setup( name = "hello", ext_modules = cythonize("lib.pyx"), ) Here are the options that are available: .. autodata:: Cython.Compiler.Options.docstrings .. autodata:: Cython.Compiler.Options.embed_pos_in_docstring .. pre_import .. autodata:: Cython.Compiler.Options.generate_cleanup_code .. autodata:: Cython.Compiler.Options.clear_to_none .. autodata:: Cython.Compiler.Options.annotate .. annotate_coverage_xml .. autodata:: Cython.Compiler.Options.fast_fail .. autodata:: Cython.Compiler.Options.warning_errors .. autodata:: Cython.Compiler.Options.error_on_unknown_names .. autodata:: Cython.Compiler.Options.error_on_uninitialized .. autodata:: Cython.Compiler.Options.convert_range .. autodata:: Cython.Compiler.Options.cache_builtins .. autodata:: Cython.Compiler.Options.gcc_branch_hints .. autodata:: Cython.Compiler.Options.lookup_module_cpdef .. autodata:: Cython.Compiler.Options.embed .. old_style_globals .. autodata:: Cython.Compiler.Options.cimport_from_pyx .. autodata:: Cython.Compiler.Options.buffer_max_dims .. autodata:: Cython.Compiler.Options.closure_freelist_size .. _compiler-directives: Compiler directives ==================== Compiler directives are instructions which affect the behavior of Cython code. Here is the list of currently supported directives: ``binding`` (True / False) Controls whether free functions behave more like Python's CFunctions (e.g. :func:`len`) or, when set to True, more like Python's functions. When enabled, functions will bind to an instance when looked up as a class attribute (hence the name) and will emulate the attributes of Python functions, including introspections like argument names and annotations. Default is True. .. versionchanged:: 3.0.0 Default changed from False to True ``boundscheck`` (True / False) If set to False, Cython is free to assume that indexing operations ([]-operator) in the code will not cause any IndexErrors to be raised. Lists, tuples, and strings are affected only if the index can be determined to be non-negative (or if ``wraparound`` is False). Conditions which would normally trigger an IndexError may instead cause segfaults or data corruption if this is set to False. Default is True. ``wraparound`` (True / False) In Python, arrays and sequences can be indexed relative to the end. For example, A[-1] indexes the last value of a list. In C, negative indexing is not supported. If set to False, Cython is allowed to neither check for nor correctly handle negative indices, possibly causing segfaults or data corruption. If bounds checks are enabled (the default, see ``boundschecks`` above), negative indexing will usually raise an ``IndexError`` for indices that Cython evaluates itself. However, these cases can be difficult to recognise in user code to distinguish them from indexing or slicing that is evaluated by the underlying Python array or sequence object and thus continues to support wrap-around indices. It is therefore safest to apply this option only to code that does not process negative indices at all. Default is True. ``initializedcheck`` (True / False) If set to True, Cython checks that - a memoryview is initialized whenever its elements are accessed or assigned to. - a C++ class is initialized when it is accessed (only when ``cpp_locals`` is on) Setting this to False disables these checks. Default is True. ``nonecheck`` (True / False) If set to False, Cython is free to assume that native field accesses on variables typed as an extension type, or buffer accesses on a buffer variable, never occurs when the variable is set to ``None``. Otherwise a check is inserted and the appropriate exception is raised. This is off by default for performance reasons. Default is False. ``overflowcheck`` (True / False) If set to True, raise errors on overflowing C integer arithmetic operations. Incurs a modest runtime penalty, but is much faster than using Python ints. Default is False. ``overflowcheck.fold`` (True / False) If set to True, and overflowcheck is True, check the overflow bit for nested, side-effect-free arithmetic expressions once rather than at every step. Depending on the compiler, architecture, and optimization settings, this may help or hurt performance. A simple suite of benchmarks can be found in ``Demos/overflow_perf.pyx``. Default is True. ``embedsignature`` (True / False) If set to True, Cython will embed a textual copy of the call signature in the docstring of all Python visible functions and classes. Tools like IPython and epydoc can thus display the signature, which cannot otherwise be retrieved after compilation. Default is False. ``embedsignature.format`` (``c`` / ``python`` / ``clinic``) If set to ``c``, Cython will generate signatures preserving C type declarations and Python type annotations. If set to ``python``, Cython will do a best attempt to use pure-Python type annotations in embedded signatures. For arguments without Python type annotations, the C type is mapped to the closest Python type equivalent (e.g., C ``short`` is mapped to Python ``int`` type and C ``double`` is mapped to Python ``float`` type). The specific output and type mapping are experimental and may change over time. The ``clinic`` format generates signatures that are compatible with those understood by CPython's Argument Clinic tool. The CPython runtime strips these signatures from docstrings and translates them into a ``__text_signature__`` attribute. This is mainly useful when using ``binding=False``, since the Cython functions generated with ``binding=True`` do not have (nor need) a ``__text_signature__`` attribute. Default is ``c``. ``cdivision`` (True / False) If set to False, Cython will adjust the remainder and quotient operators C types to match those of Python ints (which differ when the operands have opposite signs) and raise a ``ZeroDivisionError`` when the right operand is 0. This has up to a 35% speed penalty. If set to True, no checks are performed. See `CEP 516 `_. Default is False. ``cdivision_warnings`` (True / False) If set to True, Cython will emit a runtime warning whenever division is performed with negative operands. See `CEP 516 `_. Default is False. ``cpow`` (True / False) ``cpow`` modifies the return type of ``a**b``, as shown in the table below: .. csv-table:: cpow behaviour :file: cpow_table.csv :header-rows: 1 :class: longtable :widths: 1 1 3 3 The ``cpow==True`` behaviour largely keeps the result type the same as the operand types, while the ``cpow==False`` behaviour follows Python and returns a flexible type depending on the inputs. Introduced in Cython 3.0 with a default of False; before that, the behaviour matched the ``cpow=True`` version. ``always_allow_keywords`` (True / False) When disabled, uses the ``METH_NOARGS`` and ``METH_O`` signatures when constructing functions/methods which take zero or one arguments. Has no effect on special methods and functions with more than one argument. The ``METH_NOARGS`` and ``METH_O`` signatures provide slightly faster calling conventions but disallow the use of keywords. ``c_api_binop_methods`` (True / False) When enabled, makes the special binary operator methods (``__add__``, etc.) behave according to the low-level C-API slot semantics, i.e. only a single method implements both the normal and reversed operator. This used to be the default in Cython 0.x and was now replaced by Python semantics, i.e. the default in Cython 3.x and later is ``False``. ``profile`` (True / False) Write hooks for Python profilers into the compiled C code. Default is False. ``linetrace`` (True / False) Write line tracing hooks for Python profilers or coverage reporting into the compiled C code. This also enables profiling. Default is False. Note that the generated module will not actually use line tracing, unless you additionally pass the C macro definition ``CYTHON_TRACE=1`` to the C compiler (e.g. using the setuptools option ``define_macros``). Define ``CYTHON_TRACE_NOGIL=1`` to also include ``nogil`` functions and sections. ``infer_types`` (True / False) Infer types of untyped variables in function bodies. Default is None, indicating that only safe (semantically-unchanging) inferences are allowed. In particular, inferring *integral* types for variables *used in arithmetic expressions* is considered unsafe (due to possible overflow) and must be explicitly requested. ``language_level`` (2/3/3str) Globally set the Python language level to be used for module compilation. Default is compatibility with Python 3 in Cython 3.x and with Python 2 in Cython 0.x. To enable Python 3 source code semantics, set this to 3 (or 3str) at the start of a module or pass the "-3" or "--3str" command line options to the compiler. For Python 2 semantics, use 2 and "-2" accordingly. The ``3str`` option enables Python 3 semantics but does not change the ``str`` type and unprefixed string literals to ``unicode`` when the compiled code runs in Python 2.x. Language level 2 ignores ``x: int`` type annotations due to the int/long ambiguity. Note that cimported files inherit this setting from the module being compiled, unless they explicitly set their own language level. Included source files always inherit this setting. ``c_string_type`` (bytes / str / unicode) Globally set the type of an implicit coercion from char* or std::string. ``c_string_encoding`` (ascii, default, utf-8, etc.) Globally set the encoding to use when implicitly coercing char* or std:string to a unicode object. Coercion from a unicode object to C type is only allowed when set to ``ascii`` or ``default``, the latter being utf-8 in Python 3 and nearly-always ascii in Python 2. ``type_version_tag`` (True / False) Enables the attribute cache for extension types in CPython by setting the type flag ``Py_TPFLAGS_HAVE_VERSION_TAG``. Default is True, meaning that the cache is enabled for Cython implemented types. To disable it explicitly in the rare cases where a type needs to juggle with its ``tp_dict`` internally without paying attention to cache consistency, this option can be set to False. ``unraisable_tracebacks`` (True / False) Whether to print tracebacks when suppressing unraisable exceptions. ``iterable_coroutine`` (True / False) `PEP 492 `_ specifies that async-def coroutines must not be iterable, in order to prevent accidental misuse in non-async contexts. However, this makes it difficult and inefficient to write backwards compatible code that uses async-def coroutines in Cython but needs to interact with async Python code that uses the older yield-from syntax, such as asyncio before Python 3.5. This directive can be applied in modules or selectively as decorator on an async-def coroutine to make the affected coroutine(s) iterable and thus directly interoperable with yield-from. ``annotation_typing`` (True / False) Uses function argument annotations to determine the type of variables. Default is True, but can be disabled. Since Python does not enforce types given in annotations, setting to False gives greater compatibility with Python code. From Cython 3.0, ``annotation_typing`` can be set on a per-function or per-class basis. ``emit_code_comments`` (True / False) Copy the original source code line by line into C code comments in the generated code file to help with understanding the output. This is also required for coverage analysis. ``cpp_locals`` (True / False) Make C++ variables behave more like Python variables by allowing them to be "unbound" instead of always default-constructing them at the start of a function. See :ref:`cpp_locals directive` for more detail. ``legacy_implicit_noexcept`` (True / False) When enabled, ``cdef`` functions will not propagate raised exceptions by default. Hence, the function will behave in the same way as if declared with `noexcept` keyword. See :ref:`error_return_values` for details. Setting this directive to ``True`` will cause Cython 3.0 to have the same semantics as Cython 0.x. This directive was solely added to help migrate legacy code written before Cython 3. It will be removed in a future release. .. _configurable_optimisations: Configurable optimisations -------------------------- ``optimize.use_switch`` (True / False) Whether to expand chained if-else statements (including statements like ``if x == 1 or x == 2:``) into C switch statements. This can have performance benefits if there are lots of values but cause compiler errors if there are any duplicate values (which may not be detectable at Cython compile time for all C constants). Default is True. ``optimize.unpack_method_calls`` (True / False) Cython can generate code that optimistically checks for Python method objects at call time and unpacks the underlying function to call it directly. This can substantially speed up method calls, especially for builtins, but may also have a slight negative performance impact in some cases where the guess goes completely wrong. Disabling this option can also reduce the code size. Default is True. .. _warnings: Warnings -------- All warning directives take True / False as options to turn the warning on / off. ``warn.undeclared`` (default False) Warns about any variables that are implicitly declared without a ``cdef`` declaration ``warn.unreachable`` (default True) Warns about code paths that are statically determined to be unreachable, e.g. returning twice unconditionally. ``warn.maybe_uninitialized`` (default False) Warns about use of variables that are conditionally uninitialized. ``warn.unused`` (default False) Warns about unused variables and declarations ``warn.unused_arg`` (default False) Warns about unused function arguments ``warn.unused_result`` (default False) Warns about unused assignment to the same name, such as ``r = 2; r = 1 + 2`` ``warn.multiple_declarators`` (default True) Warns about multiple variables declared on the same line with at least one pointer type. For example ``cdef double* a, b`` - which, as in C, declares ``a`` as a pointer, ``b`` as a value type, but could be mininterpreted as declaring two pointers. ``show_performance_hints`` (default True) Show performance hints during compilation pointing to places in the code which can yield performance degradation. Note that performance hints are not warnings and hence the directives starting with ``warn.`` above do not affect them and they will not trigger a failure when "error on warnings" is enabled. .. _how_to_set_directives: How to set directives --------------------- Globally ::::::::: One can set compiler directives through a special header comment near the top of the file, like this:: # cython: language_level=3, boundscheck=False The comment must appear before any code (but can appear after other comments or whitespace). One can also pass a directive on the command line by using the -X switch: .. code-block:: bash $ cython -X boundscheck=True ... Directives passed on the command line will override directives set in header comments. Locally :::::::: For local blocks, you need to cimport the special builtin ``cython`` module:: #!python cimport cython Then you can use the directives either as decorators or in a with statement, like this:: #!python @cython.boundscheck(False) # turn off boundscheck for this function def f(): ... # turn it temporarily on again for this block with cython.boundscheck(True): ... .. Warning:: These two methods of setting directives are **not** affected by overriding the directive on the command-line using the -X option. In :file:`setup.py` ::::::::::::::::::: Compiler directives can also be set in the :file:`setup.py` file by passing a keyword argument to ``cythonize``:: from setuptools import setup from Cython.Build import cythonize setup( name="My hello app", ext_modules=cythonize('hello.pyx', compiler_directives={'embedsignature': True}), ) This will override the default directives as specified in the ``compiler_directives`` dictionary. Note that explicit per-file or local directives as explained above take precedence over the values passed to ``cythonize``. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/docs/src/userguide/special_methods.rst0000644000175100001770000011334300000000000023211 0ustar00runnerdocker00000000000000.. _special-methods: Special Methods of Extension Types =================================== .. include:: ../two-syntax-variants-used This page describes the special methods currently supported by Cython extension types. A complete list of all the special methods appears in the table at the bottom. Some of these methods behave differently from their Python counterparts or have no direct Python counterparts, and require special mention. .. Note:: Everything said on this page applies only to extension types, defined with the :keyword:`cdef` class statement or decorated using ``@cclass`` decorator. It doesn't apply to classes defined with the Python :keyword:`class` statement, where the normal Python rules apply. .. _declaration: Declaration ------------ Special methods of extension types must be declared with :keyword:`def`, not :keyword:`cdef`/``@cfunc``. This does not impact their performance--Python uses different calling conventions to invoke these special methods. .. _docstrings: Docstrings ----------- Currently, docstrings are not fully supported in some special methods of extension types. You can place a docstring in the source to serve as a comment, but it won't show up in the corresponding :attr:`__doc__` attribute at run time. (This seems to be is a Python limitation -- there's nowhere in the `PyTypeObject` data structure to put such docstrings.) .. _initialisation_methods: Initialisation methods: :meth:`__cinit__` and :meth:`__init__` --------------------------------------------------------------- There are two methods concerned with initialising the object, the normal Python :meth:`__init__` method and a special :meth:`__cinit__` method where basic C level initialisation can be performed. The main difference between the two is when they are called. The :meth:`__cinit__` method is guaranteed to be called as part of the object allocation, but before the object is fully initialised. Specifically, methods and object attributes that belong to subclasses or that were overridden by subclasses may not have been initialised at all yet and must not be used by :meth:`__cinit__` in a base class. Note that the object allocation in Python clears all fields and sets them to zero (or ``NULL``). Cython additionally takes responsibility of setting all object attributes to ``None``, but again, this may not yet have been done for the attributes defined or overridden by subclasses. If your object needs anything more than this basic attribute clearing in order to get into a correct and safe state, :meth:`__cinit__` may be a good place to do it. The :meth:`__init__` method, on the other hand, works exactly like in Python. It is called after allocation and basic initialisation of the object, including the complete inheritance chain. By the time :meth:`__init__` is called, the object is a fully valid Python object and all operations are safe. Any initialisation which cannot safely be done in the :meth:`__cinit__` method should be done in the :meth:`__init__` method. However, as in Python, it is the responsibility of the subclasses to call up the hierarchy and make sure that the :meth:`__init__` methods in the base class are called correctly. If a subclass forgets (or refuses) to call the :meth:`__init__` method of one of its base classes, that method will not be called. Also, if the object gets created by calling directly its :meth:`__new__` method [#]_ (as opposed to calling the class itself), then none of the :meth:`__init__` methods will be called. The :meth:`__cinit__` method is where you should perform basic safety C-level initialisation of the object, possibly including allocation of any C data structures that your object will own. In contrast to :meth:`__init__`, your :meth:`__cinit__` method is guaranteed to be called exactly once. If your extension type has a base type, any existing :meth:`__cinit__` methods in the base type hierarchy are automatically called before your :meth:`__cinit__` method. You cannot explicitly call the inherited :meth:`__cinit__` methods, and the base types are free to choose whether they implement :meth:`__cinit__` at all. If you need to pass a modified argument list to the base type, you will have to do the relevant part of the initialisation in the :meth:`__init__` method instead, where the normal rules for calling inherited methods apply. Any arguments passed to the constructor will be passed to both the :meth:`__cinit__` method and the :meth:`__init__` method. If you anticipate subclassing your extension type, you may find it useful to give the :meth:`__cinit__` method ``*`` and ``**`` arguments so that it can accept and ignore arbitrary extra arguments, since the arguments that are passed through the hierarchy during allocation cannot be changed by subclasses. Alternatively, as a convenience, if you declare your :meth:`__cinit__` method to take no arguments (other than self) it will simply ignore any extra arguments passed to the constructor without complaining about the signature mismatch. .. Note:: All constructor arguments will be passed as Python objects. This implies that non-convertible C types such as pointers or C++ objects cannot be passed into the constructor, neither from Python nor from Cython code. If this is needed, use a factory function or method instead that handles the object initialisation. It often helps to directly call the :meth:`__new__` method in this function to explicitly bypass the call to the :meth:`__init__` constructor. See :ref:`existing-pointers-instantiation` for an example. .. Note:: Implementing a :meth:`__cinit__` method currently excludes the type from :ref:`auto-pickling `. .. [#] https://docs.python.org/reference/datamodel.html#object.__new__ .. _finalization_method: Finalization methods: :meth:`__dealloc__` and :meth:`__del__` ------------------------------------------------------------- The counterpart to the :meth:`__cinit__` method is the :meth:`__dealloc__` method, which should perform the inverse of the :meth:`__cinit__` method. Any C data that you explicitly allocated (e.g. via malloc) in your :meth:`__cinit__` method should be freed in your :meth:`__dealloc__` method. You need to be careful what you do in a :meth:`__dealloc__` method. By the time your :meth:`__dealloc__` method is called, the object may already have been partially destroyed and may not be in a valid state as far as Python is concerned, so you should avoid invoking any Python operations which might touch the object. In particular, don't call any other methods of the object or do anything which might cause the object to be resurrected. It's best if you stick to just deallocating C data. You don't need to worry about deallocating Python attributes of your object, because that will be done for you by Cython after your :meth:`__dealloc__` method returns. When subclassing extension types, be aware that the :meth:`__dealloc__` method of the superclass will always be called, even if it is overridden. This is in contrast to typical Python behavior where superclass methods will not be executed unless they are explicitly called by the subclass. Python 3.4 made it possible for extension types to safely define finalizers for objects. When running a Cython module on Python 3.4 and higher you can add a :meth:`__del__` method to extension types in order to perform Python cleanup operations. When the :meth:`__del__` is called the object is still in a valid state (unlike in the case of :meth:`__dealloc__`), permitting the use of Python operations on its class members. On Python <3.4 :meth:`__del__` will not be called. .. _arithmetic_methods: Arithmetic methods ------------------- Arithmetic operator methods, such as :meth:`__add__`, used to behave differently from their Python counterparts in Cython 0.x, following the low-level semantics of the C-API slot functions. Since Cython 3.0, they are called in the same way as in Python, including the separate "reversed" versions of these methods (:meth:`__radd__`, etc.). Previously, if the first operand could not perform the operation, the same method of the second operand was called, with the operands in the same order. This means that you could not rely on the first parameter of these methods being "self" or being the right type, and you needed to test the types of both operands before deciding what to do. If backwards compatibility is needed, the normal operator method (``__add__``, etc.) can still be implemented to support both variants, applying a type check to the arguments. The reversed method (``__radd__``, etc.) can always be implemented with ``self`` as first argument and will be ignored by older Cython versions, whereas Cython 3.x and later will only call the normal method with the expected argument order, and otherwise call the reversed method instead. Alternatively, the old Cython 0.x (or native C-API) behaviour is still available with the directive ``c_api_binop_methods=True``. If you can't handle the combination of types you've been given, you should return ``NotImplemented``. This will let Python's operator implementation first try to apply the reversed operator to the second operand, and failing that as well, report an appropriate error to the user. This change in behaviour also applies to the in-place arithmetic method :meth:`__ipow__`. It does not apply to any of the other in-place methods (:meth:`__iadd__`, etc.) which always take ``self`` as the first argument. .. _rich_comparisons: Rich comparisons ----------------- There are a few ways to implement comparison methods. Depending on the application, one way or the other may be better: * Use the 6 Python `special methods `_ :meth:`__eq__`, :meth:`__lt__`, etc. This is supported since Cython 0.27 and works exactly as in plain Python classes. * Use a single special method :meth:`__richcmp__`. This implements all rich comparison operations in one method. The signature is ``def __richcmp__(self, other, int op)``. The integer argument ``op`` indicates which operation is to be performed as shown in the table below: +-----+-------+ | < | Py_LT | +-----+-------+ | == | Py_EQ | +-----+-------+ | > | Py_GT | +-----+-------+ | <= | Py_LE | +-----+-------+ | != | Py_NE | +-----+-------+ | >= | Py_GE | +-----+-------+ These constants can be cimported from the ``cpython.object`` module. * If you use the `functools.total_ordering`_ decorator on an extension type/``cdef`` class, Cython replaces it with a low-level reimplementation designed specifically for extension types. (On a normal Python classes, the ``functools`` decorator continues to work as before.) As a shortcut you can also use ``cython.total_ordering``, which applies the same re-implementation but also transforms the class to an extension type if it isn't already. .. tabs:: .. group-tab:: Pure Python .. literalinclude:: ../../examples/userguide/special_methods/total_ordering.py .. group-tab:: Cython .. literalinclude:: ../../examples/userguide/special_methods/total_ordering.pyx .. _the__next__method: The :meth:`__next__` method ---------------------------- Extension types wishing to implement the iterator interface should define a method called :meth:`__next__`, not next. The Python system will automatically supply a next method which calls your :meth:`__next__`. Do *NOT* explicitly give your type a :meth:`next` method, or bad things could happen. .. _special_methods_table: Special Method Table --------------------- This table lists all of the special methods together with their parameter and return types. In the table below, a parameter name of self is used to indicate that the parameter has the type that the method belongs to. Other parameters with no type specified in the table are generic Python objects. You don't have to declare your method as taking these parameter types. If you declare different types, conversions will be performed as necessary. General ^^^^^^^ https://docs.python.org/3/reference/datamodel.html#special-method-names +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | Name | Parameters | Return type | Description | +=======================+=======================================+=============+=====================================================+ | __cinit__ |self, ... | | Basic initialisation (no direct Python equivalent) | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __init__ |self, ... | | Further initialisation | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __dealloc__ |self | | Basic deallocation (no direct Python equivalent) | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __cmp__ |x, y | int | 3-way comparison (Python 2 only) | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __str__ |self | object | str(self) | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __repr__ |self | object | repr(self) | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __hash__ |self | Py_hash_t | Hash function (returns 32/64 bit integer) | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __call__ |self, ... | object | self(...) | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __iter__ |self | object | Return iterator for sequence | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __getattr__ |self, name | object | Get attribute | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __getattribute__ |self, name | object | Get attribute, unconditionally | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __setattr__ |self, name, val | | Set attribute | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __delattr__ |self, name | | Delete attribute | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ Rich comparison operators ^^^^^^^^^^^^^^^^^^^^^^^^^ https://docs.python.org/3/reference/datamodel.html#basic-customization You can choose to either implement the standard Python special methods like :meth:`__eq__` or the single special method :meth:`__richcmp__`. Depending on the application, one way or the other may be better. +-----------------------+---------------------------------------+-------------+--------------------------------------------------------+ | Name | Parameters | Return type | Description | +=======================+=======================================+=============+========================================================+ | __eq__ |self, y | object | self == y | +-----------------------+---------------------------------------+-------------+--------------------------------------------------------+ | __ne__ |self, y | object | self != y (falls back to ``__eq__`` if not available) | +-----------------------+---------------------------------------+-------------+--------------------------------------------------------+ | __lt__ |self, y | object | self < y | +-----------------------+---------------------------------------+-------------+--------------------------------------------------------+ | __gt__ |self, y | object | self > y | +-----------------------+---------------------------------------+-------------+--------------------------------------------------------+ | __le__ |self, y | object | self <= y | +-----------------------+---------------------------------------+-------------+--------------------------------------------------------+ | __ge__ |self, y | object | self >= y | +-----------------------+---------------------------------------+-------------+--------------------------------------------------------+ | __richcmp__ |self, y, int op | object | Joined rich comparison method for all of the above | | | | | (no direct Python equivalent) | +-----------------------+---------------------------------------+-------------+--------------------------------------------------------+ Arithmetic operators ^^^^^^^^^^^^^^^^^^^^ https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | Name | Parameters | Return type | Description | +=============================+====================+=============+=====================================================+ | __add__, __radd__ | self, other | object | binary `+` operator | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __sub__, __rsub__ | self, other | object | binary `-` operator | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __mul__, __rmul__ | self, other | object | `*` operator | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __div__, __rdiv__ | self, other | object | `/` operator for old-style division | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __floordiv__, __rfloordiv__ | self, other | object | `//` operator | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __truediv__, __rtruediv__ | self, other | object | `/` operator for new-style division | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __mod__, __rmod__ | self, other | object | `%` operator | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __divmod__, __rdivmod__ | self, other | object | combined div and mod | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __pow__, __rpow__ | self, other, [mod] | object | `**` operator or pow(x, y, [mod]) | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __neg__ | self | object | unary `-` operator | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __pos__ | self | object | unary `+` operator | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __abs__ | self | object | absolute value | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __nonzero__ | self | int | convert to boolean | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __invert__ | self | object | `~` operator | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __lshift__, __rlshift__ | self, other | object | `<<` operator | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __rshift__, __rrshift__ | self, other | object | `>>` operator | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __and__, __rand__ | self, other | object | `&` operator | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __or__, __ror__ | self, other | object | `|` operator | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ | __xor__, __rxor__ | self, other | object | `^` operator | +-----------------------------+--------------------+-------------+-----------------------------------------------------+ Note that Cython 0.x did not make use of the ``__r...__`` variants and instead used the bidirectional C slot signature for the regular methods, thus making the first argument ambiguous (not 'self' typed). Since Cython 3.0, the operator calls are passed to the respective special methods. See the section on :ref:`Arithmetic methods ` above. Cython 0.x also did not support the 2 argument version of ``__pow__`` and ``__rpow__``, or the 3 argument version of ``__ipow__``. Numeric conversions ^^^^^^^^^^^^^^^^^^^ https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | Name | Parameters | Return type | Description | +=======================+=======================================+=============+=====================================================+ | __int__ | self | object | Convert to integer | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __long__ | self | object | Convert to long integer | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __float__ | self | object | Convert to float | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __oct__ | self | object | Convert to octal | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __hex__ | self | object | Convert to hexadecimal | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __index__ | self | object | Convert to sequence index | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ In-place arithmetic operators ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | Name | Parameters | Return type | Description | +=======================+=======================================+=============+=====================================================+ | __iadd__ | self, x | object | `+=` operator | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __isub__ | self, x | object | `-=` operator | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __imul__ | self, x | object | `*=` operator | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __idiv__ | self, x | object | `/=` operator for old-style division | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __ifloordiv__ | self, x | object | `//=` operator | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __itruediv__ | self, x | object | `/=` operator for new-style division | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __imod__ | self, x | object | `%=` operator | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __ipow__ | self, y, [z] | object | `**=` operator (3-arg form only on Python >= 3.8) | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __ilshift__ | self, x | object | `<<=` operator | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __irshift__ | self, x | object | `>>=` operator | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __iand__ | self, x | object | `&=` operator | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __ior__ | self, x | object | `|=` operator | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __ixor__ | self, x | object | `^=` operator | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ Sequences and mappings ^^^^^^^^^^^^^^^^^^^^^^ https://docs.python.org/3/reference/datamodel.html#emulating-container-types +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | Name | Parameters | Return type | Description | +=======================+=======================================+=============+=====================================================+ | __len__ | self | Py_ssize_t | len(self) | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __getitem__ | self, x | object | self[x] | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __setitem__ | self, x, y | | self[x] = y | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __delitem__ | self, x | | del self[x] | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __getslice__ | self, Py_ssize_t i, Py_ssize_t j | object | self[i:j] | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __setslice__ | self, Py_ssize_t i, Py_ssize_t j, x | | self[i:j] = x | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __delslice__ | self, Py_ssize_t i, Py_ssize_t j | | del self[i:j] | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __contains__ | self, x | int | x in self | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ Iterators ^^^^^^^^^ https://docs.python.org/3/reference/datamodel.html#emulating-container-types +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | Name | Parameters | Return type | Description | +=======================+=======================================+=============+=====================================================+ | __next__ | self | object | Get next item (called next in Python) | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ Buffer interface [:PEP:`3118`] (no Python equivalents - see note 1) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | Name | Parameters | Return type | Description | +=======================+=======================================+=============+=====================================================+ | __getbuffer__ | self, Py_buffer `*view`, int flags | | | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __releasebuffer__ | self, Py_buffer `*view` | | | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ Buffer interface [legacy] (no Python equivalents - see note 1) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | Name | Parameters | Return type | Description | +=======================+=======================================+=============+=====================================================+ | __getreadbuffer__ | self, Py_ssize_t i, void `**p` | | | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __getwritebuffer__ | self, Py_ssize_t i, void `**p` | | | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __getsegcount__ | self, Py_ssize_t `*p` | | | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __getcharbuffer__ | self, Py_ssize_t i, char `**p` | | | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ Descriptor objects (see note 2) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ https://docs.python.org/3/reference/datamodel.html#emulating-container-types +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | Name | Parameters | Return type | Description | +=======================+=======================================+=============+=====================================================+ | __get__ | self, instance, class | object | Get value of attribute | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __set__ | self, instance, value | | Set value of attribute | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ | __delete__ | self, instance | | Delete attribute | +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ .. note:: (1) The buffer interface was intended for use by C code and is not directly accessible from Python. It is described in the Python/C API Reference Manual of Python 2.x under sections 6.6 and 10.6. It was superseded by the new :PEP:`3118` buffer protocol in Python 2.6 and is no longer available in Python 3. For a how-to guide to the new API, see :ref:`buffer`. .. note:: (2) Descriptor objects are part of the support mechanism for new-style Python classes. See the discussion of descriptors in the Python documentation. See also :PEP:`252`, "Making Types Look More Like Classes", and :PEP:`253`, "Subtyping Built-In Types". ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/docs/src/userguide/troubleshooting.rst0000644000175100001770000002163200000000000023274 0ustar00runnerdocker00000000000000Troubleshooting =============== This section provides some general troubleshooting advice about commonly-seen errors. If you're having a problem with Cython it may be worth reading this. If you encounter a commonly-seen error that we haven't covered here, we'd appreciate a PR adding it to this section! Where the language is "messy" ----------------------------- By necessity, Cython is a slightly odd mix of the resolved-at-run-time, dynamic behaviour of Python, and the statically-defined, resolved at compile-time behaviour of C. These don't always combine perfectly, and the places that often cause confusion are often the places they meet. As example, for a ``cdef class``, Cython is able to access ``cdef`` attributes directly (as a simple C lookup). However, if the direct attribute lookup "misses" then Cython doesn't produce an error message - instead it assumes that it will be able to resolve that attribute through the standard Python "string lookup from a dictionary" mechanism at runtime. The two mechanisms are quite different in how they work and what they can return (the Python mechanism can only return Python objects, while the the direct lookup can return largely any C type). Much the same can occur when a name is imported rather "cimported" - Cython does not know where the name comes from so treats it as a regular Python object. This silent-fallback to Python behaviour is often a source of confusion. In the best case it gives the same overall behaviour but slightly slower (for example calling a ``cpdef`` function through the Python mechanism rather than directly to C). Often it just causes an ``AttributeError`` exception at runtime. Very occasionally it might do something quite different - invoke a Python method with the same name as a ``cdef`` method, or cause a convert from a C++ container to a Python one. This kind of dual-layered behaviour probably isn't how one would design a language from scratch, but is needed for Cython's goals for being Python compatible and allowing C types to be used fairly seamlessly. ``AttributeErrors`` ------------------- Untyped objects ^^^^^^^^^^^^^^^ A common reason to get ``AttributeErrors`` is that Cython does not know the type of your object:: cdef class Counter: cdef int count_so_far ... The attribute ``count_so_far`` is only accessible from Cython code, and Cython accesses it through a direct lookup into the C struct that it defines for ``Counter`` (i.e. it's really quick!). Now try run the following Cython code on a pair of ``Counter`` objects:: def bigger_count(c1, c2): return c1.count_so_far < c2.count_so_far This will give an ``AttributeError`` because Cython does not know the types of ``c1`` and ``c2``. Typing them as ``Counter c1`` and ``Counter c2`` fixes the problem:: def bigger_count(c1, c2): return c1.count_so_far < c2.count_so_far A common variation of the same problem happens for global objects:: def count_something(): c = Counter() # code goes here!!! print(c.count_so_far) # works global_count = Counter() print(global_count.count_so_far) # AttributeError! Within a function Cython usually manages to infer the type. So it knows that ``c`` is a ``Counter`` even though you have not told it. However the same *doesn't* apply at global/module scope. Here there's a strong assumption that you want objects to be exposed as Python attributes of the module (and remember that Python attributes could be modified from elsewhere...), so Cython essentially disables all type-inference. Therefore it doesn't know the type of ``global_count``. Writing into extension types ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ``AttributeErrors`` can also happen when writing into a ``cdef class``, commonly in ``__init__``:: cdef class Company: def __init__(self, staff): self.staff = staff # AttributeError! Unlike a regular class, ``cdef class`` has a fixed list of attributes that you can write to and you need to declare them explicitly. For example:: cdef class Company: cdef list staff # ... (use ``cdef staff`` or ``cdef object staff`` if you don't want to specify a type). If you do want the ability to add arbitrary attributes then you can add a ``__dict__`` member:: cdef class Company: cdef dict __dict__ def __init__(self, staff): self.staff = staff This gives extra flexibility, but loses some of the performance benefits of using an extension type. It also adds restrictions to inheritance. Extension type class attributes vs instance attributes ------------------------------------------------------ A common pattern in Python (used a lot within the Cython code-base itself) is to use instance attributes that shadow class attributes:: class Email: message = "hello" # sensible default def actually_I_really_dislike_this_person(self): self.message = "go away!" On access to ``message`` Python first looks up the instance dictionary to see if it has a value for ``message`` and if that fails looks up the class dictionary to get the default value. The advantages are * it provides an easy sensible default, * it potentially saves a bit of memory by not populating the instance dictionary if not necessary (although modern versions of Python are pretty good at sharing keys for common attributes between instances), * it saves a bit of time reference counting (vs if you initialized the defaults in the constructor), Cython extension types don't support this pattern. You should just set the defaults in the constructor. If you don't set defaults for a ``cdef`` attribute then they'll be set to an "empty" value (``None`` for Python object attributes). .. _automatic_conversion_pitfalls: Pitfalls of automatic type conversions -------------------------------------- Cython automatically generates type conversions between certain C/C++ types and Python types. These are often undesirable. First we should look at what conversions Cython generates: * C ``struct`` to/from Python ``dict`` - if all elements of a ``struct`` are themselves convertible to a Python object, then the ``struct`` will be converted to a Python ``dict`` if returned from a function that returns a Python object:: # taken from the Cython documentation cdef struct Grail: int age float volume def get_grail(): cdef Grail g g.age = 100 g.volume = 2.5 return g print(get_grail()) # prints something similar to: # {'age': 100, 'volume': 2.5} * C++ standard library containers :ref:`to/from their Python equivalent `. A common pattern is to use a ``def`` function with an argument typed as ``std::vector``. This will be auto-converted from a Python list:: from libcpp vector cimport vector def print_list(vector[int] x): for xi in x: print(x) Most of these conversions should work both ways. They have a couple of non-obvious downsides. The conversion isn't free ^^^^^^^^^^^^^^^^^^^^^^^^^ Especially for the C++ container conversions. Consider the ``print_list`` function above. The function is appealing because iteration over the vector is faster than iteration over a Python list. However, Cython must iterate over *each element* of your input list, checking that it is something convertible to a C integer. Therefore, you haven't actually saved yourself any time - you've just hidden the "expensive" loop in a function signature. These conversions may be worthwhile if you're doing sufficient work inside your function. You should also consider also having a single place in your Cython code where the conversion happens as your interface to Python, then keeping the type as the C++ type and working on it across multiple Cython functions. In many cases it might be better to type your function with a 1D typed memoryview (``int[:]``) and pass in an ``array.array`` or a Numpy array instead of using a C++ vector. Changes do not propagate back ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Especially to attributes of ``cdef classes`` exposed to Python via properties (including via ``cdef public`` attributes). For example:: from libcpp.vector cimport vector cdef class VecHolder: def __init__(self, max): self.value = list(range(max)) # just fill it for demo purposes cdef public vector[double] values then from Python:: vh = VecHolder(5) print(vh.values) # Output: [ 0, 1, 2, 3, 4 ] vh.values[0] = 100 print(vh.values) # Output: [ 0, 1, 2, 3, 4 ] # However you can re-assign it completely vh.values = [] print(vh.values) # Output: [] Essentially your Python code modifies the ``list`` that is returned to it an not the underlying ``vector`` used to generate the ``list``. This is sufficiently non-intuitive that I really recommend against exposing convertible types as attributes! ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/docs/src/userguide/wrapping_CPlusPlus.rst0000644000175100001770000007171100000000000023651 0ustar00runnerdocker00000000000000.. highlight:: cython .. _wrapping-cplusplus: ******************************** Using C++ in Cython ******************************** Overview ========= Cython has native support for most of the C++ language. Specifically: * C++ objects can be :term:`dynamically allocated` with ``new`` and ``del`` keywords. * C++ objects can be :term:`stack-allocated`. * C++ classes can be declared with the new keyword ``cppclass``. * Templated classes and functions are supported. * Overloaded functions are supported. * Overloading of C++ operators (such as operator+, operator[],...) is supported. Procedure Overview ------------------- The general procedure for wrapping a C++ file can now be described as follows: * Specify C++ language in a :file:`setup.py` script or locally in a source file. * Create one or more ``.pxd`` files with ``cdef extern from`` blocks and (if existing) the C++ namespace name. In these blocks: * declare classes as ``cdef cppclass`` blocks * declare public names (variables, methods and constructors) * ``cimport`` them in one or more extension modules (``.pyx`` files). A simple Tutorial ================== An example C++ API ------------------- Here is a tiny C++ API which we will use as an example throughout this document. Let's assume it will be in a header file called :file:`Rectangle.h`: .. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/Rectangle.h :language: c++ :tab-width: 4 and the implementation in the file called :file:`Rectangle.cpp`: .. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/Rectangle.cpp :language: c++ :tab-width: 4 This is pretty dumb, but should suffice to demonstrate the steps involved. Declaring a C++ class interface -------------------------------- The procedure for wrapping a C++ class is quite similar to that for wrapping normal C structs, with a couple of additions. Let's start here by creating the basic ``cdef extern from`` block:: cdef extern from "Rectangle.h" namespace "shapes": This will make the C++ class def for Rectangle available. Note the namespace declaration. Namespaces are simply used to make the fully qualified name of the object, and can be nested (e.g. ``"outer::inner"``) or even refer to classes (e.g. ``"namespace::MyClass`` to declare static members on MyClass). Declare class with cdef cppclass ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Now, let's add the Rectangle class to this extern from block - just copy the class name from Rectangle.h and adjust for Cython syntax, so now it becomes:: cdef extern from "Rectangle.h" namespace "shapes": cdef cppclass Rectangle: Add public attributes ^^^^^^^^^^^^^^^^^^^^^^ We now need to declare the attributes and methods for use on Cython. We put those declarations in a file called :file:`Rectangle.pxd`. You can see it as a header file which is readable by Cython: .. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/Rectangle.pxd Note that the constructor is declared as "except +". If the C++ code or the initial memory allocation raises an exception due to a failure, this will let Cython safely raise an appropriate Python exception instead (see below). Without this declaration, C++ exceptions originating from the constructor will not be handled by Cython. We use the lines:: cdef extern from "Rectangle.cpp": pass to include the C++ code from :file:`Rectangle.cpp`. It is also possible to specify to setuptools that :file:`Rectangle.cpp` is a source. To do that, you can add this directive at the top of the ``.pyx`` (not ``.pxd``) file:: # distutils: sources = Rectangle.cpp Note that when you use ``cdef extern from``, the path that you specify is relative to the current file, but if you use the distutils directive, the path is relative to the :file:`setup.py`. If you want to discover the path of the sources when running the :file:`setup.py`, you can use the ``aliases`` argument of the :func:`cythonize` function. Declare a var with the wrapped C++ class ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ We'll create a ``.pyx`` file named ``rect.pyx`` to build our wrapper. We're using a name other than ``Rectangle``, but if you prefer giving the same name to the wrapper as the C++ class, see the section on :ref:`resolving naming conflicts `. Within, we use cdef to declare a var of the class with the C++ ``new`` statement: .. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/cython_usage.pyx The line:: # distutils: language = c++ is to indicate to Cython that this ``.pyx`` file has to be compiled to C++. It's also possible to declare a stack allocated object, as long as it has a "default" constructor:: cdef extern from "Foo.h": cdef cppclass Foo: Foo() def func(): cdef Foo foo ... See the section on the :ref:`cpp_locals directive` for a way to avoid requiring a nullary/default constructor. Note that, like C++, if the class has only one constructor and it is a nullary one, it's not necessary to declare it. Create Cython wrapper class ---------------------------- At this point, we have exposed into our pyx file's namespace the interface of the C++ Rectangle type. Now, we need to make this accessible from external Python code (which is our whole point). Common programming practice is to create a Cython extension type which holds a C++ instance as an attribute and create a bunch of forwarding methods. So we can implement the Python extension type as: .. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/rect.pyx And there we have it. From a Python perspective, this extension type will look and feel just like a natively defined Rectangle class. It should be noted that if you want to give attribute access, you could just implement some properties: .. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/rect_with_attributes.pyx Cython initializes C++ class attributes of a cdef class using the nullary constructor. If the class you're wrapping does not have a nullary constructor, you must store a pointer to the wrapped class and manually allocate and deallocate it. Alternatively, the :ref:`cpp_locals directive` avoids the need for the pointer and only initializes the C++ class attribute when it is assigned to. A convenient and safe place to do so is in the `__cinit__` and `__dealloc__` methods which are guaranteed to be called exactly once upon creation and deletion of the Python instance. .. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/rect_ptr.pyx Compilation and Importing ========================= To compile a Cython module, it is necessary to have a :file:`setup.py` file: .. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/setup.py Run ``$ python setup.py build_ext --inplace`` To test it, open the Python interpreter:: >>> import rect >>> x0, y0, x1, y1 = 1, 2, 3, 4 >>> rect_obj = rect.PyRectangle(x0, y0, x1, y1) >>> print(dir(rect_obj)) ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', 'get_area', 'get_size', 'move'] Advanced C++ features ====================== We describe here all the C++ features that were not discussed in the above tutorial. Overloading ------------ Overloading is very simple. Just declare the method with different parameters and use any of them:: cdef extern from "Foo.h": cdef cppclass Foo: Foo(int) Foo(bool) Foo(int, bool) Foo(int, int) Overloading operators ---------------------- Cython uses C++ naming for overloading operators:: cdef extern from "foo.h": cdef cppclass Foo: Foo() Foo operator+(Foo) Foo operator-(Foo) int operator*(Foo) int operator/(int) int operator*(int, Foo) # allows 1*Foo() # nonmember operators can also be specified outside the class double operator/(double, Foo) cdef Foo foo = new Foo() foo2 = foo + foo foo2 = foo - foo x = foo * foo2 x = foo / 1 x = foo[0] * foo2 x = foo[0] / 1 x = 1*foo[0] cdef double y y = 2.0/foo[0] Note that if one has *pointers* to C++ objects, dereferencing must be done to avoid doing pointer arithmetic rather than arithmetic on the objects themselves:: cdef Foo* foo_ptr = new Foo() foo = foo_ptr[0] + foo_ptr[0] x = foo_ptr[0] / 2 del foo_ptr Nested class declarations -------------------------- C++ allows nested class declaration. Class declarations can also be nested in Cython: .. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/nested_class.pyx Note that the nested class is declared with a ``cppclass`` but without a ``cdef``, as it is already part of a ``cdef`` declaration section. C++ operators not compatible with Python syntax ------------------------------------------------ Cython tries to keep its syntax as close as possible to standard Python. Because of this, certain C++ operators, like the preincrement ``++foo`` or the dereferencing operator ``*foo`` cannot be used with the same syntax as C++. Cython provides functions replacing these operators in a special module ``cython.operator``. The functions provided are: * ``cython.operator.dereference`` for dereferencing. ``dereference(foo)`` will produce the C++ code ``*(foo)`` * ``cython.operator.preincrement`` for pre-incrementation. ``preincrement(foo)`` will produce the C++ code ``++(foo)``. Similarly for ``predecrement``, ``postincrement`` and ``postdecrement``. * ``cython.operator.comma`` for the comma operator. ``comma(a, b)`` will produce the C++ code ``((a), (b))``. These functions need to be cimported. Of course, one can use a ``from ... cimport ... as`` to have shorter and more readable functions. For example: ``from cython.operator cimport dereference as deref``. For completeness, it's also worth mentioning ``cython.operator.address`` which can also be written ``&foo``. Templates ---------- Cython uses a bracket syntax for templating. A simple example for wrapping C++ vector: .. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/templates.pyx Multiple template parameters can be defined as a list, such as ``[T, U, V]`` or ``[int, bool, char]``. Optional template parameters can be indicated by writing ``[T, U, V=*]``. In the event that Cython needs to explicitly reference the type of a default template parameter for an incomplete template instantiation, it will write ``MyClass::V``, so if the class provides a typedef for its template parameters it is preferable to use that name here. Template functions are defined similarly to class templates, with the template parameter list following the function name: .. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/function_templates.pyx .. _stl_types: Standard library ----------------- Most of the containers of the C++ Standard Library have been declared in pxd files located in `/Cython/Includes/libcpp `_. These containers are: deque, list, map, pair, queue, set, stack, vector. For example: .. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/vector_demo.pyx The pxd files in `/Cython/Includes/libcpp `_ also work as good examples on how to declare C++ classes. The STL containers coerce from and to the corresponding Python builtin types. The conversion is triggered either by an assignment to a typed variable (including typed function arguments) or by an explicit cast, e.g.: .. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/python_to_cpp.pyx The following coercions are available: +------------------+------------------------+-----------------+ | Python type => | *C++ type* | => Python type | +==================+========================+=================+ | bytes | std::string | bytes | +------------------+------------------------+-----------------+ | iterable | std::vector | list | +------------------+------------------------+-----------------+ | iterable | std::list | list | +------------------+------------------------+-----------------+ | iterable | std::set | set | +------------------+------------------------+-----------------+ | iterable | std::unordered_set | set | +------------------+------------------------+-----------------+ | mapping | std::map | dict | +------------------+------------------------+-----------------+ | mapping | std::unordered_map | dict | +------------------+------------------------+-----------------+ | iterable (len 2) | std::pair | tuple (len 2) | +------------------+------------------------+-----------------+ | complex | std::complex | complex | +------------------+------------------------+-----------------+ All conversions create a new container and copy the data into it. The items in the containers are converted to a corresponding type automatically, which includes recursively converting containers inside of containers, e.g. a C++ vector of maps of strings. Be aware that the conversions do have some pitfalls, which are detailed in :ref:`the troubleshooting section `. Iteration over stl containers (or indeed any class with ``begin()`` and ``end()`` methods returning an object supporting incrementing, dereferencing, and comparison) is supported via the ``for .. in`` syntax (including in list comprehensions). For example, one can write: .. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/iterate.pyx If the loop target variable is unspecified, an assignment from type ``*container.begin()`` is used for :ref:`type inference `. .. note:: Slicing stl containers is supported, you can do ``for x in my_vector[:5]: ...`` but unlike pointers slices, it will create a temporary Python object and iterate over it. Thus making the iteration very slow. You might want to avoid slicing C++ containers for performance reasons. Simplified wrapping with default constructor -------------------------------------------- If your extension type instantiates a wrapped C++ class using the default constructor (not passing any arguments), you may be able to simplify the lifecycle handling by tying it directly to the lifetime of the Python wrapper object. Instead of a pointer attribute, you can declare an instance: .. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/wrapper_vector.pyx Cython will automatically generate code that instantiates the C++ object instance when the Python object is created and deletes it when the Python object is garbage collected. Exceptions ----------- Cython cannot throw C++ exceptions, or catch them with a try-except statement, but it is possible to declare a function as potentially raising an C++ exception and converting it into a Python exception. For example, :: cdef extern from "some_file.h": cdef int foo() except + This will translate try and the C++ error into an appropriate Python exception. The translation is performed according to the following table (the ``std::`` prefix is omitted from the C++ identifiers): +-----------------------+---------------------+ | C++ | Python | +=======================+=====================+ | ``bad_alloc`` | ``MemoryError`` | +-----------------------+---------------------+ | ``bad_cast`` | ``TypeError`` | +-----------------------+---------------------+ | ``bad_typeid`` | ``TypeError`` | +-----------------------+---------------------+ | ``domain_error`` | ``ValueError`` | +-----------------------+---------------------+ | ``invalid_argument`` | ``ValueError`` | +-----------------------+---------------------+ | ``ios_base::failure`` | ``IOError`` | +-----------------------+---------------------+ | ``out_of_range`` | ``IndexError`` | +-----------------------+---------------------+ | ``overflow_error`` | ``OverflowError`` | +-----------------------+---------------------+ | ``range_error`` | ``ArithmeticError`` | +-----------------------+---------------------+ | ``underflow_error`` | ``ArithmeticError`` | +-----------------------+---------------------+ | (all others) | ``RuntimeError`` | +-----------------------+---------------------+ The ``what()`` message, if any, is preserved. Note that a C++ ``ios_base_failure`` can denote EOF, but does not carry enough information for Cython to discern that, so watch out with exception masks on IO streams. :: cdef int bar() except +MemoryError This will catch any C++ error and raise a Python MemoryError in its place. (Any Python exception is valid here.) Cython also supports using a custom exception handler. This is an advanced feature that most users won't need, but for those that do a full example follows:: cdef int raise_py_error() cdef int something_dangerous() except +raise_py_error If something_dangerous raises a C++ exception then raise_py_error will be called, which allows one to do custom C++ to Python error "translations." If raise_py_error does not actually raise an exception a RuntimeError will be raised. This approach may also be used to manage custom Python exceptions created using the Python C API. :: # raising.pxd cdef extern from "Python.h" nogil: ctypedef struct PyObject cdef extern from *: """ #include #include #include PyObject *CustomLogicError; void create_custom_exceptions() { CustomLogicError = PyErr_NewException("raiser.CustomLogicError", NULL, NULL); } void custom_exception_handler() { try { if (PyErr_Occurred()) { ; // let the latest Python exn pass through and ignore the current one } else { throw; } } catch (const std::logic_error& exn) { // Add mapping of std::logic_error -> CustomLogicError PyErr_SetString(CustomLogicError, exn.what()); } catch (...) { PyErr_SetString(PyExc_RuntimeError, "Unknown exception"); } } class Raiser { public: Raiser () {} void raise_exception() { throw std::logic_error("Failure"); } }; """ cdef PyObject* CustomLogicError cdef void create_custom_exceptions() cdef void custom_exception_handler() cdef cppclass Raiser: Raiser() noexcept void raise_exception() except +custom_exception_handler # raising.pyx create_custom_exceptions() PyCustomLogicError = CustomLogicError cdef class PyRaiser: cdef Raiser c_obj def raise_exception(self): self.c_obj.raise_exception() The above example leverages Cython's ability to include :ref:`verbatim C code ` in pxd files to create a new Python exception type ``CustomLogicError`` and map it to the standard C++ ``std::logic_error`` using the ``custom_exception_handler`` function. There is nothing special about using a standard exception class here, ``std::logic_error`` could easily be replaced with some new C++ exception type defined in this file. The ``Raiser::raise_exception`` is marked with ``+custom_exception_handler`` to indicate that this function should be called whenever an exception is raised. The corresponding Python function ``PyRaiser.raise_exception`` will raise a ``CustomLogicError`` whenever it is called. Defining ``PyCustomLogicError`` allows other code to catch this exception, as shown below: :: try: PyRaiser().raise_exception() except PyCustomLogicError: print("Caught the exception") When defining custom exception handlers it is typically good to also include logic to handle all the standard exceptions that Cython typically handles as listed in the table above. The code for this standard exception handler can be found `here `__. There is also the special form:: cdef int raise_py_or_cpp() except +* for those functions that may raise either a Python or a C++ exception. Static member method -------------------- If the Rectangle class has a static member: .. code-block:: c++ namespace shapes { class Rectangle { ... public: static void do_something(); }; } you can declare it using the Python @staticmethod decorator, i.e.:: cdef extern from "Rectangle.h" namespace "shapes": cdef cppclass Rectangle: ... @staticmethod void do_something() Declaring/Using References --------------------------- Cython supports declaring lvalue references using the standard ``Type&`` syntax. Note, however, that it is unnecessary to declare the arguments of extern functions as references (const or otherwise) as it has no impact on the caller's syntax. Scoped Enumerations ------------------- Cython supports scoped enumerations (:keyword:`enum class`) in C++ mode:: cdef enum class Cheese: cheddar = 1 camembert = 2 As with "plain" enums, you may access the enumerators as attributes of the type. Unlike plain enums however, the enumerators are not visible to the enclosing scope:: cdef Cheese c1 = Cheese.cheddar # OK cdef Cheese c2 = cheddar # ERROR! Optionally, you may specify the underlying type of a scoped enumeration. This is especially important when declaring an external scoped enumeration with an underlying type:: cdef extern from "Foo.h": cdef enum class Spam(unsigned int): x = 10 y = 20 ... Declaring an enum class as ``cpdef`` will create a :pep:`435`-style Python wrapper. ``auto`` Keyword ---------------- Though Cython does not have an ``auto`` keyword, Cython local variables not explicitly typed with ``cdef`` are deduced from the types of the right hand side of *all* their assignments (see the ``infer_types`` :ref:`compiler directive `). This is particularly handy when dealing with functions that return complicated, nested, templated types, e.g.:: cdef vector[int] v = ... it = v.begin() (Though of course the ``for .. in`` syntax is preferred for objects supporting the iteration protocol.) RTTI and typeid() ================= Cython has support for the ``typeid(...)`` operator. from cython.operator cimport typeid The ``typeid(...)`` operator returns an object of the type ``const type_info &``. If you want to store a type_info value in a C variable, you will need to store it as a pointer rather than a reference:: from libcpp.typeinfo cimport type_info cdef const type_info* info = &typeid(MyClass) If an invalid type is passed to ``typeid``, it will throw an ``std::bad_typeid`` exception which is converted into a ``TypeError`` exception in Python. An additional C++11-only RTTI-related class, ``std::type_index``, is available in ``libcpp.typeindex``. Specify C++ language in setup.py ================================ Instead of specifying the language and the sources in the source files, it is possible to declare them in the :file:`setup.py` file:: from setuptools import setup from Cython.Build import cythonize setup(ext_modules = cythonize( "rect.pyx", # our Cython source sources=["Rectangle.cpp"], # additional source file(s) language="c++", # generate C++ code )) Cython will generate and compile the :file:`rect.cpp` file (from :file:`rect.pyx`), then it will compile :file:`Rectangle.cpp` (implementation of the ``Rectangle`` class) and link both object files together into :file:`rect.so` on Linux, or :file:`rect.pyd` on windows, which you can then import in Python using ``import rect`` (if you forget to link the :file:`Rectangle.o`, you will get missing symbols while importing the library in Python). Note that the ``language`` option has no effect on user provided Extension objects that are passed into ``cythonize()``. It is only used for modules found by file name (as in the example above). The ``cythonize()`` function in Cython versions up to 0.21 does not recognize the ``language`` option and it needs to be specified as an option to an :class:`Extension` that describes your extension and that is then handled by ``cythonize()`` as follows:: from setuptools import Extension, setup from Cython.Build import cythonize setup(ext_modules = cythonize(Extension( "rect", # the extension name sources=["rect.pyx", "Rectangle.cpp"], # the Cython source and # additional C++ source files language="c++", # generate and compile C++ code ))) The options can also be passed directly from the source file, which is often preferable (and overrides any global option). Starting with version 0.17, Cython also allows passing external source files into the ``cythonize()`` command this way. Here is a simplified setup.py file:: from setuptools import setup from Cython.Build import cythonize setup( name = "rectangleapp", ext_modules = cythonize('*.pyx'), ) And in the .pyx source file, write this into the first comment block, before any source code, to compile it in C++ mode and link it statically against the :file:`Rectangle.cpp` code file:: # distutils: language = c++ # distutils: sources = Rectangle.cpp .. note:: When using distutils directives, the paths are relative to the working directory of the setuptools run (which is usually the project root where the :file:`setup.py` resides). To compile manually (e.g. using ``make``), the ``cython`` command-line utility can be used to generate a C++ ``.cpp`` file, and then compile it into a python extension. C++ mode for the ``cython`` command is turned on with the ``--cplus`` option. .. _cpp_locals directive: ``cpp_locals`` directive ======================== The ``cpp_locals`` compiler directive is an experimental feature that makes C++ variables behave like normal Python object variables. With this directive they are only initialized at their first assignment, and thus they no longer require a nullary constructor to be stack-allocated. Trying to access an uninitialized C++ variable will generate an ``UnboundLocalError`` (or similar) in the same way as a Python variable would. For example:: def function(dont_write): cdef SomeCppClass c # not initialized if dont_write: return c.some_cpp_function() # UnboundLocalError else: c = SomeCppClass(...) # initialized return c.some_cpp_function() # OK Additionally, the directive avoids initializing temporary C++ objects before they are assigned, for cases where Cython needs to use such objects in its own code-generation (often for return values of functions that can throw exceptions). For extra speed, the ``initializedcheck`` directive disables the check for an unbound-local. With this directive on, accessing a variable that has not been initialized will trigger undefined behaviour, and it is entirely the user's responsibility to avoid such access. The ``cpp_locals`` directive is currently implemented using ``std::optional`` and thus requires a C++17 compatible compiler. Defining ``CYTHON_USE_BOOST_OPTIONAL`` (as define for the C++ compiler) uses ``boost::optional`` instead (but is even more experimental and untested). The directive may come with a memory and performance cost due to the need to store and check a boolean that tracks if a variable is initialized, but the C++ compiler should be able to eliminate the check in most cases. Caveats and Limitations ======================== Access to C-only functions --------------------------- Whenever generating C++ code, Cython generates declarations of and calls to functions assuming these functions are C++ (ie, not declared as ``extern "C" {...}``. This is ok if the C functions have C++ entry points, but if they're C only, you will hit a roadblock. If you have a C++ Cython module needing to make calls to pure-C functions, you will need to write a small C++ shim module which: * includes the needed C headers in an extern "C" block * contains minimal forwarding functions in C++, each of which calls the respective pure-C function C++ left-values ---------------- C++ allows functions returning a reference to be left-values. This is currently not supported in Cython. ``cython.operator.dereference(foo)`` is also not considered a left-value. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/pylintrc0000644000175100001770000001721600000000000015372 0ustar00runnerdocker00000000000000[MASTER] # Specify a configuration file. #rcfile= # Python code to execute, usually for sys.path manipulation such as # pygtk.require(). #init-hook= # Profiled execution. profile=no # Add files or directories to the ignorelist. They should be base names, not # paths. ignore=.git,.gitmarker # Pickle collected data for later comparisons. persistent=yes # List of plugins (as comma separated values of python modules names) to load, # usually to register additional checkers. load-plugins= [MESSAGES CONTROL] # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option # multiple time. #enable= # Disable the message, report, category or checker with the given id(s). You # can either give multiple identifier separated by comma (,) or put this option # multiple time (only on the command line, not in the configuration file where # it should appear only once). ## R0201: Method could be a function ## R0904: Too many public methods ## W0201: Attribute defined outside __init__() ## W0141: Used builtin function 'map' disable=E1101,C0111,R0201,R0904,W0201,W0141 [REPORTS] # Set the output format. Available formats are text, parseable, colorized, msvs # (visual studio) and html. You can also give a reporter class, eg # mypackage.mymodule.MyReporterClass. output-format=parseable # Include message's id in output include-ids=yes # Include symbolic ids of messages in output symbols=no # Put messages in a separate file for each module / package specified on the # command line instead of printing them on stdout. Reports (if any) will be # written in a file name "pylint_global.[txt|html]". files-output=no # Tells whether to display a full report or only the messages reports=no # Python expression which should return a note less than 10 (10 is the highest # note). You have access to the variables errors warning, statement which # respectively contain the number of errors / warnings messages and the total # number of statements analyzed. This is used by the global evaluation report # (RP0004). evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) # Add a comment according to your evaluation note. This is used by the global # evaluation report (RP0004). comment=no [MISCELLANEOUS] # List of note tags to take in consideration, separated by a comma. notes=FIXME,XXX,TODO [BASIC] # Required attributes for module, separated by a comma required-attributes= # List of builtins function names that should not be used, separated by a comma bad-functions=map,filter,apply,input # Regular expression which should only match correct module names module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ # Regular expression which should only match correct module level names const-rgx=(([a-zA-Z_][a-zA-Z0-9_]*)|(__.*__))$ # Regular expression which should only match correct class names class-rgx=[A-Z_][a-zA-Z0-9]+$ # Regular expression which should only match correct function names function-rgx=[a-z_][a-z0-9_]{2,30}$ # Regular expression which should only match correct method names method-rgx=[a-z_][a-z0-9_]{2,30}|visit_[A-Za-z]+$ # Regular expression which should only match correct instance attribute names attr-rgx=[a-z_][a-z0-9_]{2,30}|sy$ # Regular expression which should only match correct argument names argument-rgx=[a-z_][a-z0-9_]{0,30}$ # Regular expression which should only match correct variable names variable-rgx=[a-z_][a-z0-9_]{0,30}$ # Regular expression which should only match correct list comprehension / # generator expression variable names inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ # Good variable names which should always be accepted, separated by a comma good-names=i,j,k,ex,Run,_ # Bad variable names which should always be refused, separated by a comma bad-names=foo,bar,baz,toto,tutu,tata # Regular expression which should only match functions or classes name which do # not require a docstring no-docstring-rgx=__.*__ [FORMAT] # Maximum number of characters on a single line. max-line-length=120 # Maximum number of lines in a module max-module-lines=15000 # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 # tab). indent-string=' ' [SIMILARITIES] # Minimum lines number of a similarity. min-similarity-lines=4 # Ignore comments when computing similarities. ignore-comments=yes # Ignore docstrings when computing similarities. ignore-docstrings=yes # Ignore imports when computing similarities. ignore-imports=no [TYPECHECK] # Tells whether missing members accessed in mixin class should be ignored. A # mixin class is detected if its name ends with "mixin" (case insensitive). ignore-mixin-members=yes # List of classes names for which member attributes should not be checked # (useful for classes with attributes dynamically set). ignored-classes= # When zope mode is activated, add a predefined set of Zope acquired attributes # to generated-members. zope=no # List of members which are set dynamically and missed by pylint inference # system, and so shouldn't trigger E0201 when accessed. Python regular # expressions are accepted. generated-members=REQUEST,acl_users,aq_parent [VARIABLES] # Tells whether we should check for unused import in __init__ files. init-import=no # A regular expression matching the beginning of the name of dummy variables # (i.e. not used). dummy-variables-rgx=_|dummy # List of additional names supposed to be defined in builtins. Remember that # you should avoid to define new builtins when possible. additional-builtins= [IMPORTS] # Deprecated modules which should not be used, separated by a comma deprecated-modules=regsub,string,TERMIOS,Bastion,rexec # Create a graph of every (i.e. internal and external) dependencies in the # given file (report RP0402 must not be disabled) import-graph= # Create a graph of external dependencies in the given file (report RP0402 must # not be disabled) ext-import-graph= # Create a graph of internal dependencies in the given file (report RP0402 must # not be disabled) int-import-graph= [DESIGN] # Maximum number of arguments for function / method max-args=12 # Argument names that match this expression will be ignored. Default to name # with leading underscore ignored-argument-names=_.* # Maximum number of locals for function / method body max-locals=15 # Maximum number of return / yield for function / method body max-returns=6 # Maximum number of branch for function / method body max-branchs=12 # Maximum number of statements in function / method body max-statements=50 # Maximum number of parents for a class (see R0901). max-parents=7 # Maximum number of attributes for a class (see R0902). max-attributes=7 # Minimum number of public methods for a class (see R0903). min-public-methods=2 # Maximum number of public methods for a class (see R0904). max-public-methods=20 [CLASSES] # List of interface methods to ignore, separated by a comma. This is used for # instance to not check methods defines in Zope's Interface base class. ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by # List of method names used to declare (i.e. assign) instance attributes. defining-attr-methods=__init__,__new__,setUp # List of valid names for the first argument in a class method. valid-classmethod-first-arg=cls # List of valid names for the first argument in a metaclass class method. valid-metaclass-classmethod-first-arg=mcs [EXCEPTIONS] # Exceptions that will emit a warning when being caught. Defaults to # "Exception" overgeneral-exceptions=Exception ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.0687242 Cython-3.0.8/pyximport/0000755000175100001770000000000000000000000015647 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/pyximport/PKG-INFO0000644000175100001770000000046600000000000016752 0ustar00runnerdocker00000000000000Metadata-Version: 1.0 Name: pyximport Version: 1.0 Summary: Hooks to build and run Pyrex files as if they were simple Python files Home-page: http://www.prescod.net/pyximport Author: Paul Prescod Author-email: paul@prescod.net License: Python Description: UNKNOWN Keywords: pyrex import hook Platform: UNKNOWN ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/pyximport/__init__.py0000644000175100001770000000011700000000000017757 0ustar00runnerdocker00000000000000from .pyximport import * # replicate docstring from .pyximport import __doc__ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/pyximport/_pyximport2.py0000644000175100001770000005740000000000000020523 0ustar00runnerdocker00000000000000""" Import hooks; when installed with the install() function, these hooks allow importing .pyx files as if they were Python modules. If you want the hook installed every time you run Python you can add it to your Python version by adding these lines to sitecustomize.py (which you can create from scratch in site-packages if it doesn't exist there or somewhere else on your python path):: import pyximport pyximport.install() For instance on the Mac with a non-system Python 2.3, you could create sitecustomize.py with only those two lines at /usr/local/lib/python2.3/site-packages/sitecustomize.py . A custom distutils.core.Extension instance and setup() args (Distribution) for for the build can be defined by a .pyxbld file like: # examplemod.pyxbld def make_ext(modname, pyxfilename): from distutils.extension import Extension return Extension(name = modname, sources=[pyxfilename, 'hello.c'], include_dirs=['/myinclude'] ) def make_setup_args(): return dict(script_args=["--compiler=mingw32"]) Extra dependencies can be defined by a .pyxdep . See README. Since Cython 0.11, the :mod:`pyximport` module also has experimental compilation support for normal Python modules. This allows you to automatically run Cython on every .pyx and .py module that Python imports, including parts of the standard library and installed packages. Cython will still fail to compile a lot of Python modules, in which case the import mechanism will fall back to loading the Python source modules instead. The .py import mechanism is installed like this:: pyximport.install(pyimport = True) Running this module as a top-level script will run a test and then print the documentation. This code is based on the Py2.3+ import protocol as described in PEP 302. """ import glob import imp import os import sys from zipimport import zipimporter, ZipImportError mod_name = "pyximport" PYX_EXT = ".pyx" PYXDEP_EXT = ".pyxdep" PYXBLD_EXT = ".pyxbld" DEBUG_IMPORT = False def _print(message, args): if args: message = message % args print(message) def _debug(message, *args): if DEBUG_IMPORT: _print(message, args) def _info(message, *args): _print(message, args) # Performance problem: for every PYX file that is imported, we will # invoke the whole distutils infrastructure even if the module is # already built. It might be more efficient to only do it when the # mod time of the .pyx is newer than the mod time of the .so but # the question is how to get distutils to tell me the name of the .so # before it builds it. Maybe it is easy...but maybe the performance # issue isn't real. def _load_pyrex(name, filename): "Load a pyrex file given a name and filename." def get_distutils_extension(modname, pyxfilename, language_level=None): # try: # import hashlib # except ImportError: # import md5 as hashlib # extra = "_" + hashlib.md5(open(pyxfilename).read()).hexdigest() # modname = modname + extra extension_mod,setup_args = handle_special_build(modname, pyxfilename) if not extension_mod: if not isinstance(pyxfilename, str): # distutils is stupid in Py2 and requires exactly 'str' # => encode accidentally coerced unicode strings back to str pyxfilename = pyxfilename.encode(sys.getfilesystemencoding()) from distutils.extension import Extension extension_mod = Extension(name = modname, sources=[pyxfilename]) if language_level is not None: extension_mod.cython_directives = {'language_level': language_level} return extension_mod,setup_args def handle_special_build(modname, pyxfilename): special_build = os.path.splitext(pyxfilename)[0] + PYXBLD_EXT ext = None setup_args={} if os.path.exists(special_build): # globls = {} # locs = {} # execfile(special_build, globls, locs) # ext = locs["make_ext"](modname, pyxfilename) with open(special_build) as fid: mod = imp.load_source("XXXX", special_build, fid) make_ext = getattr(mod,'make_ext',None) if make_ext: ext = make_ext(modname, pyxfilename) assert ext and ext.sources, "make_ext in %s did not return Extension" % special_build make_setup_args = getattr(mod, 'make_setup_args',None) if make_setup_args: setup_args = make_setup_args() assert isinstance(setup_args,dict), ("make_setup_args in %s did not return a dict" % special_build) assert set or setup_args, ("neither make_ext nor make_setup_args %s" % special_build) ext.sources = [os.path.join(os.path.dirname(special_build), source) for source in ext.sources] return ext, setup_args def handle_dependencies(pyxfilename): testing = '_test_files' in globals() dependfile = os.path.splitext(pyxfilename)[0] + PYXDEP_EXT # by default let distutils decide whether to rebuild on its own # (it has a better idea of what the output file will be) # but we know more about dependencies so force a rebuild if # some of the dependencies are newer than the pyxfile. if os.path.exists(dependfile): with open(dependfile) as fid: depends = fid.readlines() depends = [depend.strip() for depend in depends] # gather dependencies in the "files" variable # the dependency file is itself a dependency files = [dependfile] for depend in depends: fullpath = os.path.join(os.path.dirname(dependfile), depend) files.extend(glob.glob(fullpath)) # only for unit testing to see we did the right thing if testing: _test_files[:] = [] #$pycheck_no # if any file that the pyxfile depends upon is newer than # the pyx file, 'touch' the pyx file so that distutils will # be tricked into rebuilding it. for file in files: from distutils.dep_util import newer if newer(file, pyxfilename): _debug("Rebuilding %s because of %s", pyxfilename, file) filetime = os.path.getmtime(file) os.utime(pyxfilename, (filetime, filetime)) if testing: _test_files.append(file) def build_module(name, pyxfilename, pyxbuild_dir=None, inplace=False, language_level=None): assert os.path.exists(pyxfilename), "Path does not exist: %s" % pyxfilename handle_dependencies(pyxfilename) extension_mod, setup_args = get_distutils_extension(name, pyxfilename, language_level) build_in_temp = pyxargs.build_in_temp sargs = pyxargs.setup_args.copy() sargs.update(setup_args) build_in_temp = sargs.pop('build_in_temp',build_in_temp) from . import pyxbuild olddir = os.getcwd() common = '' if pyxbuild_dir: # Windows concatenates the pyxbuild_dir to the pyxfilename when # compiling, and then complains that the filename is too long common = os.path.commonprefix([pyxbuild_dir, pyxfilename]) if len(common) > 30: pyxfilename = os.path.relpath(pyxfilename) pyxbuild_dir = os.path.relpath(pyxbuild_dir) os.chdir(common) try: so_path = pyxbuild.pyx_to_dll(pyxfilename, extension_mod, build_in_temp=build_in_temp, pyxbuild_dir=pyxbuild_dir, setup_args=sargs, inplace=inplace, reload_support=pyxargs.reload_support) finally: os.chdir(olddir) so_path = os.path.join(common, so_path) assert os.path.exists(so_path), "Cannot find: %s" % so_path junkpath = os.path.join(os.path.dirname(so_path), name+"_*") #very dangerous with --inplace ? yes, indeed, trying to eat my files ;) junkstuff = glob.glob(junkpath) for path in junkstuff: if path != so_path: try: os.remove(path) except IOError: _info("Couldn't remove %s", path) return so_path def load_module(name, pyxfilename, pyxbuild_dir=None, is_package=False, build_inplace=False, language_level=None, so_path=None): try: if so_path is None: if is_package: module_name = name + '.__init__' else: module_name = name so_path = build_module(module_name, pyxfilename, pyxbuild_dir, inplace=build_inplace, language_level=language_level) mod = imp.load_dynamic(name, so_path) if is_package and not hasattr(mod, '__path__'): mod.__path__ = [os.path.dirname(so_path)] assert mod.__file__ == so_path, (mod.__file__, so_path) except Exception as failure_exc: _debug("Failed to load extension module: %r" % failure_exc) if pyxargs.load_py_module_on_import_failure and pyxfilename.endswith('.py'): # try to fall back to normal import mod = imp.load_source(name, pyxfilename) assert mod.__file__ in (pyxfilename, pyxfilename+'c', pyxfilename+'o'), (mod.__file__, pyxfilename) else: tb = sys.exc_info()[2] import traceback exc = ImportError("Building module %s failed: %s" % ( name, traceback.format_exception_only(*sys.exc_info()[:2]))) if sys.version_info[0] >= 3: raise exc.with_traceback(tb) else: exec("raise exc, None, tb", {'exc': exc, 'tb': tb}) return mod # import hooks class PyxImporter(object): """A meta-path importer for .pyx files. """ def __init__(self, extension=PYX_EXT, pyxbuild_dir=None, inplace=False, language_level=None): self.extension = extension self.pyxbuild_dir = pyxbuild_dir self.inplace = inplace self.language_level = language_level def find_module(self, fullname, package_path=None): if fullname in sys.modules and not pyxargs.reload_support: return None # only here when reload() # package_path might be a _NamespacePath. Convert that into a list... if package_path is not None and not isinstance(package_path, list): package_path = list(package_path) try: fp, pathname, (ext,mode,ty) = imp.find_module(fullname,package_path) if fp: fp.close() # Python should offer a Default-Loader to avoid this double find/open! if pathname and ty == imp.PKG_DIRECTORY: pkg_file = os.path.join(pathname, '__init__'+self.extension) if os.path.isfile(pkg_file): return PyxLoader(fullname, pathname, init_path=pkg_file, pyxbuild_dir=self.pyxbuild_dir, inplace=self.inplace, language_level=self.language_level) if pathname and pathname.endswith(self.extension): return PyxLoader(fullname, pathname, pyxbuild_dir=self.pyxbuild_dir, inplace=self.inplace, language_level=self.language_level) if ty != imp.C_EXTENSION: # only when an extension, check if we have a .pyx next! return None # find .pyx fast, when .so/.pyd exist --inplace pyxpath = os.path.splitext(pathname)[0]+self.extension if os.path.isfile(pyxpath): return PyxLoader(fullname, pyxpath, pyxbuild_dir=self.pyxbuild_dir, inplace=self.inplace, language_level=self.language_level) # .so/.pyd's on PATH should not be remote from .pyx's # think no need to implement PyxArgs.importer_search_remote here? except ImportError: pass # searching sys.path ... #if DEBUG_IMPORT: print "SEARCHING", fullname, package_path mod_parts = fullname.split('.') module_name = mod_parts[-1] pyx_module_name = module_name + self.extension # this may work, but it returns the file content, not its path #import pkgutil #pyx_source = pkgutil.get_data(package, pyx_module_name) paths = package_path or sys.path for path in paths: pyx_data = None if not path: path = os.getcwd() elif os.path.isfile(path): try: zi = zipimporter(path) pyx_data = zi.get_data(pyx_module_name) except (ZipImportError, IOError, OSError): continue # Module not found. # unzip the imported file into the build dir # FIXME: can interfere with later imports if build dir is in sys.path and comes before zip file path = self.pyxbuild_dir elif not os.path.isabs(path): path = os.path.abspath(path) pyx_module_path = os.path.join(path, pyx_module_name) if pyx_data is not None: if not os.path.exists(path): try: os.makedirs(path) except OSError: # concurrency issue? if not os.path.exists(path): raise with open(pyx_module_path, "wb") as f: f.write(pyx_data) elif not os.path.isfile(pyx_module_path): continue # Module not found. return PyxLoader(fullname, pyx_module_path, pyxbuild_dir=self.pyxbuild_dir, inplace=self.inplace, language_level=self.language_level) # not found, normal package, not a .pyx file, none of our business _debug("%s not found" % fullname) return None class PyImporter(PyxImporter): """A meta-path importer for normal .py files. """ def __init__(self, pyxbuild_dir=None, inplace=False, language_level=None): if language_level is None: language_level = sys.version_info[0] self.super = super(PyImporter, self) self.super.__init__(extension='.py', pyxbuild_dir=pyxbuild_dir, inplace=inplace, language_level=language_level) self.uncompilable_modules = {} self.blocked_modules = ['Cython', 'pyxbuild', 'pyximport.pyxbuild', 'distutils'] self.blocked_packages = ['Cython.', 'distutils.'] def find_module(self, fullname, package_path=None): if fullname in sys.modules: return None if any([fullname.startswith(pkg) for pkg in self.blocked_packages]): return None if fullname in self.blocked_modules: # prevent infinite recursion return None if _lib_loader.knows(fullname): return _lib_loader _debug("trying import of module '%s'", fullname) if fullname in self.uncompilable_modules: path, last_modified = self.uncompilable_modules[fullname] try: new_last_modified = os.stat(path).st_mtime if new_last_modified > last_modified: # import would fail again return None except OSError: # module is no longer where we found it, retry the import pass self.blocked_modules.append(fullname) try: importer = self.super.find_module(fullname, package_path) if importer is not None: if importer.init_path: path = importer.init_path real_name = fullname + '.__init__' else: path = importer.path real_name = fullname _debug("importer found path %s for module %s", path, real_name) try: so_path = build_module( real_name, path, pyxbuild_dir=self.pyxbuild_dir, language_level=self.language_level, inplace=self.inplace) _lib_loader.add_lib(fullname, path, so_path, is_package=bool(importer.init_path)) return _lib_loader except Exception: if DEBUG_IMPORT: import traceback traceback.print_exc() # build failed, not a compilable Python module try: last_modified = os.stat(path).st_mtime except OSError: last_modified = 0 self.uncompilable_modules[fullname] = (path, last_modified) importer = None finally: self.blocked_modules.pop() return importer class LibLoader(object): def __init__(self): self._libs = {} def load_module(self, fullname): try: source_path, so_path, is_package = self._libs[fullname] except KeyError: raise ValueError("invalid module %s" % fullname) _debug("Loading shared library module '%s' from %s", fullname, so_path) return load_module(fullname, source_path, so_path=so_path, is_package=is_package) def add_lib(self, fullname, path, so_path, is_package): self._libs[fullname] = (path, so_path, is_package) def knows(self, fullname): return fullname in self._libs _lib_loader = LibLoader() class PyxLoader(object): def __init__(self, fullname, path, init_path=None, pyxbuild_dir=None, inplace=False, language_level=None): _debug("PyxLoader created for loading %s from %s (init path: %s)", fullname, path, init_path) self.fullname = fullname self.path, self.init_path = path, init_path self.pyxbuild_dir = pyxbuild_dir self.inplace = inplace self.language_level = language_level def load_module(self, fullname): assert self.fullname == fullname, ( "invalid module, expected %s, got %s" % ( self.fullname, fullname)) if self.init_path: # package #print "PACKAGE", fullname module = load_module(fullname, self.init_path, self.pyxbuild_dir, is_package=True, build_inplace=self.inplace, language_level=self.language_level) module.__path__ = [self.path] else: #print "MODULE", fullname module = load_module(fullname, self.path, self.pyxbuild_dir, build_inplace=self.inplace, language_level=self.language_level) return module #install args class PyxArgs(object): build_dir=True build_in_temp=True setup_args={} #None ##pyxargs=None def _have_importers(): has_py_importer = False has_pyx_importer = False for importer in sys.meta_path: if isinstance(importer, PyxImporter): if isinstance(importer, PyImporter): has_py_importer = True else: has_pyx_importer = True return has_py_importer, has_pyx_importer def install(pyximport=True, pyimport=False, build_dir=None, build_in_temp=True, setup_args=None, reload_support=False, load_py_module_on_import_failure=False, inplace=False, language_level=None): """ Main entry point for pyxinstall. Call this to install the ``.pyx`` import hook in your meta-path for a single Python process. If you want it to be installed whenever you use Python, add it to your ``sitecustomize`` (as described above). :param pyximport: If set to False, does not try to import ``.pyx`` files. :param pyimport: You can pass ``pyimport=True`` to also install the ``.py`` import hook in your meta-path. Note, however, that it is rather experimental, will not work at all for some ``.py`` files and packages, and will heavily slow down your imports due to search and compilation. Use at your own risk. :param build_dir: By default, compiled modules will end up in a ``.pyxbld`` directory in the user's home directory. Passing a different path as ``build_dir`` will override this. :param build_in_temp: If ``False``, will produce the C files locally. Working with complex dependencies and debugging becomes more easy. This can principally interfere with existing files of the same name. :param setup_args: Dict of arguments for Distribution. See ``distutils.core.setup()``. :param reload_support: Enables support for dynamic ``reload(my_module)``, e.g. after a change in the Cython code. Additional files ``.reloadNN`` may arise on that account, when the previously loaded module file cannot be overwritten. :param load_py_module_on_import_failure: If the compilation of a ``.py`` file succeeds, but the subsequent import fails for some reason, retry the import with the normal ``.py`` module instead of the compiled module. Note that this may lead to unpredictable results for modules that change the system state during their import, as the second import will rerun these modifications in whatever state the system was left after the import of the compiled module failed. :param inplace: Install the compiled module (``.so`` for Linux and Mac / ``.pyd`` for Windows) next to the source file. :param language_level: The source language level to use: 2 or 3. The default is to use the language level of the current Python runtime for .py files and Py2 for ``.pyx`` files. """ if setup_args is None: setup_args = {} if not build_dir: build_dir = os.path.join(os.path.expanduser('~'), '.pyxbld') global pyxargs pyxargs = PyxArgs() #$pycheck_no pyxargs.build_dir = build_dir pyxargs.build_in_temp = build_in_temp pyxargs.setup_args = (setup_args or {}).copy() pyxargs.reload_support = reload_support pyxargs.load_py_module_on_import_failure = load_py_module_on_import_failure has_py_importer, has_pyx_importer = _have_importers() py_importer, pyx_importer = None, None if pyimport and not has_py_importer: py_importer = PyImporter(pyxbuild_dir=build_dir, inplace=inplace, language_level=language_level) # make sure we import Cython before we install the import hook import Cython.Compiler.Main, Cython.Compiler.Pipeline, Cython.Compiler.Optimize sys.meta_path.insert(0, py_importer) if pyximport and not has_pyx_importer: pyx_importer = PyxImporter(pyxbuild_dir=build_dir, inplace=inplace, language_level=language_level) sys.meta_path.append(pyx_importer) return py_importer, pyx_importer def uninstall(py_importer, pyx_importer): """ Uninstall an import hook. """ try: sys.meta_path.remove(py_importer) except ValueError: pass try: sys.meta_path.remove(pyx_importer) except ValueError: pass # MAIN def show_docs(): import __main__ __main__.__name__ = mod_name for name in dir(__main__): item = getattr(__main__, name) try: setattr(item, "__module__", mod_name) except (AttributeError, TypeError): pass help(__main__) if __name__ == '__main__': show_docs() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/pyximport/_pyximport3.py0000644000175100001770000004364000000000000020525 0ustar00runnerdocker00000000000000""" Import hooks; when installed with the install() function, these hooks allow importing .pyx files as if they were Python modules. If you want the hook installed every time you run Python you can add it to your Python version by adding these lines to sitecustomize.py (which you can create from scratch in site-packages if it doesn't exist there or somewhere else on your python path):: import pyximport pyximport.install() For instance on the Mac with a non-system Python 2.3, you could create sitecustomize.py with only those two lines at /usr/local/lib/python2.3/site-packages/sitecustomize.py . A custom distutils.core.Extension instance and setup() args (Distribution) for for the build can be defined by a .pyxbld file like: # examplemod.pyxbld def make_ext(modname, pyxfilename): from distutils.extension import Extension return Extension(name = modname, sources=[pyxfilename, 'hello.c'], include_dirs=['/myinclude'] ) def make_setup_args(): return dict(script_args=["--compiler=mingw32"]) Extra dependencies can be defined by a .pyxdep . See README. Since Cython 0.11, the :mod:`pyximport` module also has experimental compilation support for normal Python modules. This allows you to automatically run Cython on every .pyx and .py module that Python imports, including parts of the standard library and installed packages. Cython will still fail to compile a lot of Python modules, in which case the import mechanism will fall back to loading the Python source modules instead. The .py import mechanism is installed like this:: pyximport.install(pyimport = True) Running this module as a top-level script will run a test and then print the documentation. """ import glob import importlib import os import sys from importlib.abc import MetaPathFinder from importlib.machinery import ExtensionFileLoader, SourceFileLoader from importlib.util import spec_from_file_location mod_name = "pyximport" PY_EXT = ".py" PYX_EXT = ".pyx" PYXDEP_EXT = ".pyxdep" PYXBLD_EXT = ".pyxbld" DEBUG_IMPORT = False def _print(message, args): if args: message = message % args print(message) def _debug(message, *args): if DEBUG_IMPORT: _print(message, args) def _info(message, *args): _print(message, args) def load_source(file_path): import importlib.util from importlib.machinery import SourceFileLoader spec = importlib.util.spec_from_file_location("XXXX", file_path, loader=SourceFileLoader("XXXX", file_path)) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module def get_distutils_extension(modname, pyxfilename, language_level=None): # try: # import hashlib # except ImportError: # import md5 as hashlib # extra = "_" + hashlib.md5(open(pyxfilename).read()).hexdigest() # modname = modname + extra extension_mod,setup_args = handle_special_build(modname, pyxfilename) if not extension_mod: if not isinstance(pyxfilename, str): # distutils is stupid in Py2 and requires exactly 'str' # => encode accidentally coerced unicode strings back to str pyxfilename = pyxfilename.encode(sys.getfilesystemencoding()) from distutils.extension import Extension extension_mod = Extension(name = modname, sources=[pyxfilename]) if language_level is not None: extension_mod.cython_directives = {'language_level': language_level} return extension_mod,setup_args def handle_special_build(modname, pyxfilename): special_build = os.path.splitext(pyxfilename)[0] + PYXBLD_EXT ext = None setup_args={} if os.path.exists(special_build): # globls = {} # locs = {} # execfile(special_build, globls, locs) # ext = locs["make_ext"](modname, pyxfilename) mod = load_source(special_build) make_ext = getattr(mod,'make_ext',None) if make_ext: ext = make_ext(modname, pyxfilename) assert ext and ext.sources, "make_ext in %s did not return Extension" % special_build make_setup_args = getattr(mod, 'make_setup_args',None) if make_setup_args: setup_args = make_setup_args() assert isinstance(setup_args,dict), ("make_setup_args in %s did not return a dict" % special_build) assert set or setup_args, ("neither make_ext nor make_setup_args %s" % special_build) ext.sources = [os.path.join(os.path.dirname(special_build), source) for source in ext.sources] return ext, setup_args def handle_dependencies(pyxfilename): testing = '_test_files' in globals() dependfile = os.path.splitext(pyxfilename)[0] + PYXDEP_EXT # by default let distutils decide whether to rebuild on its own # (it has a better idea of what the output file will be) # but we know more about dependencies so force a rebuild if # some of the dependencies are newer than the pyxfile. if os.path.exists(dependfile): with open(dependfile) as fid: depends = fid.readlines() depends = [depend.strip() for depend in depends] # gather dependencies in the "files" variable # the dependency file is itself a dependency files = [dependfile] for depend in depends: fullpath = os.path.join(os.path.dirname(dependfile), depend) files.extend(glob.glob(fullpath)) # only for unit testing to see we did the right thing if testing: _test_files[:] = [] #$pycheck_no # if any file that the pyxfile depends upon is newer than # the pyx file, 'touch' the pyx file so that distutils will # be tricked into rebuilding it. for file in files: from distutils.dep_util import newer if newer(file, pyxfilename): _debug("Rebuilding %s because of %s", pyxfilename, file) filetime = os.path.getmtime(file) os.utime(pyxfilename, (filetime, filetime)) if testing: _test_files.append(file) def build_module(name, pyxfilename, pyxbuild_dir=None, inplace=False, language_level=None): assert os.path.exists(pyxfilename), "Path does not exist: %s" % pyxfilename handle_dependencies(pyxfilename) extension_mod, setup_args = get_distutils_extension(name, pyxfilename, language_level) build_in_temp = pyxargs.build_in_temp sargs = pyxargs.setup_args.copy() sargs.update(setup_args) build_in_temp = sargs.pop('build_in_temp',build_in_temp) from . import pyxbuild olddir = os.getcwd() common = '' if pyxbuild_dir: # Windows concatenates the pyxbuild_dir to the pyxfilename when # compiling, and then complains that the filename is too long common = os.path.commonprefix([pyxbuild_dir, pyxfilename]) if len(common) > 30: pyxfilename = os.path.relpath(pyxfilename) pyxbuild_dir = os.path.relpath(pyxbuild_dir) os.chdir(common) try: so_path = pyxbuild.pyx_to_dll(pyxfilename, extension_mod, build_in_temp=build_in_temp, pyxbuild_dir=pyxbuild_dir, setup_args=sargs, inplace=inplace, reload_support=pyxargs.reload_support) finally: os.chdir(olddir) so_path = os.path.join(common, so_path) assert os.path.exists(so_path), "Cannot find: %s" % so_path junkpath = os.path.join(os.path.dirname(so_path), name+"_*") #very dangerous with --inplace ? yes, indeed, trying to eat my files ;) junkstuff = glob.glob(junkpath) for path in junkstuff: if path != so_path: try: os.remove(path) except IOError: _info("Couldn't remove %s", path) return so_path # import hooks class PyxImportMetaFinder(MetaPathFinder): def __init__(self, extension=PYX_EXT, pyxbuild_dir=None, inplace=False, language_level=None): self.pyxbuild_dir = pyxbuild_dir self.inplace = inplace self.language_level = language_level self.extension = extension def find_spec(self, fullname, path, target=None): if not path: path = [os.getcwd()] # top level import -- if "." in fullname: *parents, name = fullname.split(".") else: name = fullname for entry in path: if os.path.isdir(os.path.join(entry, name)): # this module has child modules filename = os.path.join(entry, name, "__init__" + self.extension) submodule_locations = [os.path.join(entry, name)] else: filename = os.path.join(entry, name + self.extension) submodule_locations = None if not os.path.exists(filename): continue return spec_from_file_location( fullname, filename, loader=PyxImportLoader(filename, self.pyxbuild_dir, self.inplace, self.language_level), submodule_search_locations=submodule_locations) return None # we don't know how to import this class PyImportMetaFinder(MetaPathFinder): def __init__(self, extension=PY_EXT, pyxbuild_dir=None, inplace=False, language_level=None): self.pyxbuild_dir = pyxbuild_dir self.inplace = inplace self.language_level = language_level self.extension = extension self.uncompilable_modules = {} self.blocked_modules = ['Cython', 'pyxbuild', 'pyximport.pyxbuild', 'distutils', 'cython'] self.blocked_packages = ['Cython.', 'distutils.'] def find_spec(self, fullname, path, target=None): if fullname in sys.modules: return None if any([fullname.startswith(pkg) for pkg in self.blocked_packages]): return None if fullname in self.blocked_modules: # prevent infinite recursion return None self.blocked_modules.append(fullname) name = fullname if not path: path = [os.getcwd()] # top level import -- try: for entry in path: if os.path.isdir(os.path.join(entry, name)): # this module has child modules filename = os.path.join(entry, name, "__init__" + self.extension) submodule_locations = [os.path.join(entry, name)] else: filename = os.path.join(entry, name + self.extension) submodule_locations = None if not os.path.exists(filename): continue return spec_from_file_location( fullname, filename, loader=PyxImportLoader(filename, self.pyxbuild_dir, self.inplace, self.language_level), submodule_search_locations=submodule_locations) finally: self.blocked_modules.pop() return None # we don't know how to import this class PyxImportLoader(ExtensionFileLoader): def __init__(self, filename, pyxbuild_dir, inplace, language_level): module_name = os.path.splitext(os.path.basename(filename))[0] super().__init__(module_name, filename) self._pyxbuild_dir = pyxbuild_dir self._inplace = inplace self._language_level = language_level def create_module(self, spec): try: so_path = build_module(spec.name, pyxfilename=spec.origin, pyxbuild_dir=self._pyxbuild_dir, inplace=self._inplace, language_level=self._language_level) self.path = so_path spec.origin = so_path return super().create_module(spec) except Exception as failure_exc: _debug("Failed to load extension module: %r" % failure_exc) if pyxargs.load_py_module_on_import_failure and spec.origin.endswith(PY_EXT): spec = importlib.util.spec_from_file_location(spec.name, spec.origin, loader=SourceFileLoader(spec.name, spec.origin)) mod = importlib.util.module_from_spec(spec) assert mod.__file__ in (spec.origin, spec.origin + 'c', spec.origin + 'o'), (mod.__file__, spec.origin) return mod else: tb = sys.exc_info()[2] import traceback exc = ImportError("Building module %s failed: %s" % ( spec.name, traceback.format_exception_only(*sys.exc_info()[:2]))) raise exc.with_traceback(tb) def exec_module(self, module): try: return super().exec_module(module) except Exception as failure_exc: import traceback _debug("Failed to load extension module: %r" % failure_exc) raise ImportError("Executing module %s failed %s" % ( module.__file__, traceback.format_exception_only(*sys.exc_info()[:2]))) #install args class PyxArgs(object): build_dir=True build_in_temp=True setup_args={} #None def _have_importers(): has_py_importer = False has_pyx_importer = False for importer in sys.meta_path: if isinstance(importer, PyxImportMetaFinder): if isinstance(importer, PyImportMetaFinder): has_py_importer = True else: has_pyx_importer = True return has_py_importer, has_pyx_importer def install(pyximport=True, pyimport=False, build_dir=None, build_in_temp=True, setup_args=None, reload_support=False, load_py_module_on_import_failure=False, inplace=False, language_level=None): """ Main entry point for pyxinstall. Call this to install the ``.pyx`` import hook in your meta-path for a single Python process. If you want it to be installed whenever you use Python, add it to your ``sitecustomize`` (as described above). :param pyximport: If set to False, does not try to import ``.pyx`` files. :param pyimport: You can pass ``pyimport=True`` to also install the ``.py`` import hook in your meta-path. Note, however, that it is rather experimental, will not work at all for some ``.py`` files and packages, and will heavily slow down your imports due to search and compilation. Use at your own risk. :param build_dir: By default, compiled modules will end up in a ``.pyxbld`` directory in the user's home directory. Passing a different path as ``build_dir`` will override this. :param build_in_temp: If ``False``, will produce the C files locally. Working with complex dependencies and debugging becomes more easy. This can principally interfere with existing files of the same name. :param setup_args: Dict of arguments for Distribution. See ``distutils.core.setup()``. :param reload_support: Enables support for dynamic ``reload(my_module)``, e.g. after a change in the Cython code. Additional files ``.reloadNN`` may arise on that account, when the previously loaded module file cannot be overwritten. :param load_py_module_on_import_failure: If the compilation of a ``.py`` file succeeds, but the subsequent import fails for some reason, retry the import with the normal ``.py`` module instead of the compiled module. Note that this may lead to unpredictable results for modules that change the system state during their import, as the second import will rerun these modifications in whatever state the system was left after the import of the compiled module failed. :param inplace: Install the compiled module (``.so`` for Linux and Mac / ``.pyd`` for Windows) next to the source file. :param language_level: The source language level to use: 2 or 3. The default is to use the language level of the current Python runtime for .py files and Py2 for ``.pyx`` files. """ if setup_args is None: setup_args = {} if not build_dir: build_dir = os.path.join(os.path.expanduser('~'), '.pyxbld') global pyxargs pyxargs = PyxArgs() #$pycheck_no pyxargs.build_dir = build_dir pyxargs.build_in_temp = build_in_temp pyxargs.setup_args = (setup_args or {}).copy() pyxargs.reload_support = reload_support pyxargs.load_py_module_on_import_failure = load_py_module_on_import_failure has_py_importer, has_pyx_importer = _have_importers() py_importer, pyx_importer = None, None if pyimport and not has_py_importer: py_importer = PyImportMetaFinder(pyxbuild_dir=build_dir, inplace=inplace, language_level=language_level) # make sure we import Cython before we install the import hook import Cython.Compiler.Main, Cython.Compiler.Pipeline, Cython.Compiler.Optimize sys.meta_path.insert(0, py_importer) if pyximport and not has_pyx_importer: pyx_importer = PyxImportMetaFinder(pyxbuild_dir=build_dir, inplace=inplace, language_level=language_level) sys.meta_path.append(pyx_importer) return py_importer, pyx_importer def uninstall(py_importer, pyx_importer): """ Uninstall an import hook. """ try: sys.meta_path.remove(py_importer) except ValueError: pass try: sys.meta_path.remove(pyx_importer) except ValueError: pass # MAIN def show_docs(): import __main__ __main__.__name__ = mod_name for name in dir(__main__): item = getattr(__main__, name) try: setattr(item, "__module__", mod_name) except (AttributeError, TypeError): pass help(__main__) if __name__ == '__main__': show_docs() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/pyximport/pyxbuild.py0000644000175100001770000001310600000000000020062 0ustar00runnerdocker00000000000000"""Build a Pyrex file from .pyx source to .so loadable module using the installed distutils infrastructure. Call: out_fname = pyx_to_dll("foo.pyx") """ import os import sys from distutils.errors import DistutilsArgError, DistutilsError, CCompilerError from distutils.extension import Extension from distutils.util import grok_environment_error try: from Cython.Distutils.build_ext import build_ext HAS_CYTHON = True except ImportError: HAS_CYTHON = False DEBUG = 0 _reloads={} def pyx_to_dll(filename, ext=None, force_rebuild=0, build_in_temp=False, pyxbuild_dir=None, setup_args=None, reload_support=False, inplace=False): """Compile a PYX file to a DLL and return the name of the generated .so or .dll .""" assert os.path.exists(filename), "Could not find %s" % os.path.abspath(filename) path, name = os.path.split(os.path.abspath(filename)) if not ext: modname, extension = os.path.splitext(name) assert extension in (".pyx", ".py"), extension if not HAS_CYTHON: filename = filename[:-len(extension)] + '.c' ext = Extension(name=modname, sources=[filename]) if setup_args is None: setup_args = {} if not pyxbuild_dir: pyxbuild_dir = os.path.join(path, "_pyxbld") package_base_dir = path for package_name in ext.name.split('.')[-2::-1]: package_base_dir, pname = os.path.split(package_base_dir) if pname != package_name: # something is wrong - package path doesn't match file path package_base_dir = None break script_args=setup_args.get("script_args",[]) if DEBUG or "--verbose" in script_args: quiet = "--verbose" else: quiet = "--quiet" if build_in_temp: args = [quiet, "build_ext", '--cython-c-in-temp'] else: args = [quiet, "build_ext"] if force_rebuild: args.append("--force") if inplace and package_base_dir: args.extend(['--build-lib', package_base_dir]) if ext.name == '__init__' or ext.name.endswith('.__init__'): # package => provide __path__ early if not hasattr(ext, 'cython_directives'): ext.cython_directives = {'set_initial_path' : 'SOURCEFILE'} elif 'set_initial_path' not in ext.cython_directives: ext.cython_directives['set_initial_path'] = 'SOURCEFILE' sargs = setup_args.copy() sargs.update({ "script_name": None, "script_args": args + script_args, }) # late import, in case setuptools replaced it from distutils.dist import Distribution dist = Distribution(sargs) if not dist.ext_modules: dist.ext_modules = [] dist.ext_modules.append(ext) if HAS_CYTHON: dist.cmdclass = {'build_ext': build_ext} build = dist.get_command_obj('build') build.build_base = pyxbuild_dir cfgfiles = dist.find_config_files() dist.parse_config_files(cfgfiles) try: ok = dist.parse_command_line() except DistutilsArgError: raise if DEBUG: print("options (after parsing command line):") dist.dump_option_dicts() assert ok try: obj_build_ext = dist.get_command_obj("build_ext") dist.run_commands() so_path = obj_build_ext.get_outputs()[0] if obj_build_ext.inplace: # Python distutils get_outputs()[ returns a wrong so_path # when --inplace ; see https://bugs.python.org/issue5977 # workaround: so_path = os.path.join(os.path.dirname(filename), os.path.basename(so_path)) if reload_support: org_path = so_path timestamp = os.path.getmtime(org_path) global _reloads last_timestamp, last_path, count = _reloads.get(org_path, (None,None,0) ) if last_timestamp == timestamp: so_path = last_path else: basename = os.path.basename(org_path) while count < 100: count += 1 r_path = os.path.join(obj_build_ext.build_lib, basename + '.reload%s' % count) try: import shutil # late import / reload_support is: debugging try: # Try to unlink first --- if the .so file # is mmapped by another process, # overwriting its contents corrupts the # loaded image (on Linux) and crashes the # other process. On Windows, unlinking an # open file just fails. if os.path.isfile(r_path): os.unlink(r_path) except OSError: continue shutil.copy2(org_path, r_path) so_path = r_path except IOError: continue break else: # used up all 100 slots raise ImportError("reload count for %s reached maximum" % org_path) _reloads[org_path]=(timestamp, so_path, count) return so_path except KeyboardInterrupt: sys.exit(1) except (IOError, os.error): exc = sys.exc_info()[1] error = grok_environment_error(exc) if DEBUG: sys.stderr.write(error + "\n") raise if __name__=="__main__": pyx_to_dll("dummy.pyx") from . import test ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/pyximport/pyximport.py0000644000175100001770000000050100000000000020270 0ustar00runnerdocker00000000000000from __future__ import absolute_import import sys if sys.version_info < (3, 5): # _pyximport3 module requires at least Python 3.5 from pyximport._pyximport2 import install, uninstall, show_docs else: from pyximport._pyximport3 import install, uninstall, show_docs if __name__ == '__main__': show_docs() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.0687242 Cython-3.0.8/pyximport/test/0000755000175100001770000000000000000000000016626 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/pyximport/test/test_pyximport.py0000644000175100001770000000613000000000000022312 0ustar00runnerdocker00000000000000from __future__ import absolute_import, print_function from pyximport import pyximport pyximport.install(reload_support=True) import os import shutil import sys import tempfile import time from zipfile import ZipFile try: from __builtin__ import reload except ImportError: from importlib import reload def make_tempdir(): tempdir = os.path.join(tempfile.gettempdir(), "pyrex_temp") if os.path.exists(tempdir): remove_tempdir(tempdir) os.mkdir(tempdir) return tempdir def remove_tempdir(tempdir): shutil.rmtree(tempdir, 0, on_remove_file_error) def on_remove_file_error(func, path, excinfo): print("Sorry! Could not remove a temp file:", path) print("Extra information.") print(func, excinfo) print("You may want to delete this yourself when you get a chance.") def test_with_reload(): pyximport._test_files = [] tempdir = make_tempdir() sys.path.append(tempdir) filename = os.path.join(tempdir, "dummy.pyx") with open(filename, "w") as fid: fid.write("print 'Hello world from the Pyrex install hook'") import dummy reload(dummy) depend_filename = os.path.join(tempdir, "dummy.pyxdep") with open(depend_filename, "w") as depend_file: depend_file.write("*.txt\nfoo.bar") build_filename = os.path.join(tempdir, "dummy.pyxbld") with open(build_filename, "w") as build_file: build_file.write(""" from distutils.extension import Extension def make_ext(name, filename): return Extension(name=name, sources=[filename]) """) with open(os.path.join(tempdir, "foo.bar"), "w") as fid: fid.write(" ") with open(os.path.join(tempdir, "1.txt"), "w") as fid: fid.write(" ") with open(os.path.join(tempdir, "abc.txt"), "w") as fid: fid.write(" ") reload(dummy) assert len(pyximport._test_files)==1, pyximport._test_files reload(dummy) time.sleep(1) # sleep a second to get safer mtimes with open(os.path.join(tempdir, "abc.txt"), "w") as fid: fid.write(" ") print("Here goes the reload") reload(dummy) assert len(pyximport._test_files) == 1, pyximport._test_files reload(dummy) assert len(pyximport._test_files) == 0, pyximport._test_files remove_tempdir(tempdir) def test_zip(): try: import test_zip_module except ImportError: pass else: assert False, "test_zip_module already exists" fd, zip_path = tempfile.mkstemp(suffix=".zip") os.close(fd) try: with ZipFile(zip_path, "w") as zf: zf.writestr("test_zip_module.pyx", b"x = 42") sys.path.insert(0, zip_path) import test_zip_module assert test_zip_module.x == 42 finally: if zip_path in sys.path: sys.path.remove(zip_path) os.remove(zip_path) def test_zip_nonexisting(): sys.path.append("nonexisting_zip_module.zip") try: import nonexisting_zip_module except ImportError: pass finally: sys.path.remove("nonexisting_zip_module.zip") if __name__== "__main__": test_with_reload() test_zip() test_zip_nonexisting() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/pyximport/test/test_reload.py0000644000175100001770000000171400000000000021510 0ustar00runnerdocker00000000000000from __future__ import absolute_import, print_function import time, os, sys from . import test_pyximport if 1: from distutils import sysconfig try: sysconfig.set_python_build() except AttributeError: pass import pyxbuild print(pyxbuild.distutils.sysconfig == sysconfig) def test(): tempdir = test_pyximport.make_tempdir() sys.path.append(tempdir) hello_file = os.path.join(tempdir, "hello.pyx") with open(hello_file, "w") as fid: fid.write("x = 1; print x; before = 'before'\n") import hello assert hello.x == 1 time.sleep(1) # sleep to make sure that new "hello.pyx" has later # timestamp than object file. with open(hello_file, "w") as fid: fid.write("x = 2; print x; after = 'after'\n") reload(hello) assert hello.x == 2, "Reload should work on Python 2.3 but not 2.2" test_pyximport.remove_tempdir(tempdir) if __name__=="__main__": test() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/runtests.py0000755000175100001770000036007000000000000016046 0ustar00runnerdocker00000000000000#!/usr/bin/env python from __future__ import print_function import atexit import base64 import doctest import gc import glob import heapq import locale import math import operator import os import re import shutil import subprocess import sys import tempfile import time import traceback import unittest import warnings import zlib from collections import defaultdict from contextlib import contextmanager try: import platform IS_PYPY = platform.python_implementation() == 'PyPy' IS_CPYTHON = platform.python_implementation() == 'CPython' IS_GRAAL = platform.python_implementation() == 'GraalVM' except (ImportError, AttributeError): IS_CPYTHON = True IS_PYPY = False IS_GRAAL = False IS_PY2 = sys.version_info[0] < 3 CAN_SYMLINK = sys.platform != 'win32' and hasattr(os, 'symlink') from io import open as io_open try: from StringIO import StringIO except ImportError: from io import StringIO # doesn't accept 'str' in Py2 try: import cPickle as pickle except ImportError: import pickle try: import threading except ImportError: # No threads, no problems threading = None try: from unittest import SkipTest except ImportError: class SkipTest(Exception): # don't raise, only provided to allow except-ing it! pass def skip_test(reason): sys.stderr.write("Skipping test: %s\n" % reason) else: def skip_test(reason): raise SkipTest(reason) try: basestring except NameError: basestring = str WITH_CYTHON = True try: # Py3.12+ doesn't have distutils any more and requires setuptools to provide it. import setuptools except ImportError: pass from distutils.command.build_ext import build_ext as _build_ext from distutils import sysconfig _to_clean = [] @atexit.register def _cleanup_files(): """ This is only used on Cygwin to clean up shared libraries that are unsafe to delete while the test suite is running. """ for filename in _to_clean: if os.path.isdir(filename): shutil.rmtree(filename, ignore_errors=True) else: try: os.remove(filename) except OSError: pass def get_distutils_distro(_cache=[]): if _cache: return _cache[0] # late import to accommodate for setuptools override from distutils.dist import Distribution distutils_distro = Distribution() if sys.platform == 'win32': # TODO: Figure out why this hackery (see https://thread.gmane.org/gmane.comp.python.cython.devel/8280/). config_files = distutils_distro.find_config_files() try: config_files.remove('setup.cfg') except ValueError: pass distutils_distro.parse_config_files(config_files) cfgfiles = distutils_distro.find_config_files() try: cfgfiles.remove('setup.cfg') except ValueError: pass distutils_distro.parse_config_files(cfgfiles) _cache.append(distutils_distro) return distutils_distro EXT_DEP_MODULES = { 'tag:numpy': 'numpy', 'tag:pythran': 'pythran', 'tag:setuptools': 'setuptools.sandbox', 'tag:asyncio': 'asyncio', 'tag:pstats': 'pstats', 'tag:posix': 'posix', 'tag:array': 'array', 'tag:coverage': 'Cython.Coverage', 'Coverage': 'Cython.Coverage', 'tag:ipython': 'IPython.testing.globalipapp', 'tag:jedi': 'jedi_BROKEN_AND_DISABLED', 'tag:test.support': 'test.support', # support module for CPython unit tests } def patch_inspect_isfunction(): import inspect orig_isfunction = inspect.isfunction def isfunction(obj): return orig_isfunction(obj) or type(obj).__name__ == 'cython_function_or_method' isfunction._orig_isfunction = orig_isfunction inspect.isfunction = isfunction def unpatch_inspect_isfunction(): import inspect try: orig_isfunction = inspect.isfunction._orig_isfunction except AttributeError: pass else: inspect.isfunction = orig_isfunction def def_to_cdef(source): ''' Converts the module-level def methods into cdef methods, i.e. @decorator def foo([args]): """ [tests] """ [body] becomes def foo([args]): """ [tests] """ return foo_c([args]) cdef foo_c([args]): [body] ''' output = [] skip = False def_node = re.compile(r'def (\w+)\(([^()*]*)\):').match lines = iter(source.split('\n')) for line in lines: if not line.strip(): output.append(line) continue if skip: if line[0] != ' ': skip = False else: continue if line[0] == '@': skip = True continue m = def_node(line) if m: name = m.group(1) args = m.group(2) if args: args_no_types = ", ".join(arg.split()[-1] for arg in args.split(',')) else: args_no_types = "" output.append("def %s(%s):" % (name, args_no_types)) line = next(lines) if '"""' in line: has_docstring = True output.append(line) for line in lines: output.append(line) if '"""' in line: break else: has_docstring = False output.append(" return %s_c(%s)" % (name, args_no_types)) output.append('') output.append("cdef %s_c(%s):" % (name, args)) if not has_docstring: output.append(line) else: output.append(line) return '\n'.join(output) def exclude_extension_in_pyver(*versions): def check(ext): return EXCLUDE_EXT if sys.version_info[:2] in versions else ext return check def exclude_extension_on_platform(*platforms): def check(ext): return EXCLUDE_EXT if sys.platform in platforms else ext return check def update_linetrace_extension(ext): ext.define_macros.append(('CYTHON_TRACE', 1)) return ext def update_numpy_extension(ext, set_api17_macro=True): import numpy as np # Add paths for npyrandom and npymath libraries: lib_path = [ os.path.abspath(os.path.join(np.get_include(), '..', '..', 'random', 'lib')), os.path.abspath(os.path.join(np.get_include(), '..', 'lib')) ] ext.library_dirs += lib_path if sys.platform == "win32": ext.libraries += ["npymath"] else: ext.libraries += ["npymath", "m"] ext.include_dirs.append(np.get_include()) if set_api17_macro and getattr(np, '__version__', '') not in ('1.19.0', '1.19.1'): ext.define_macros.append(('NPY_NO_DEPRECATED_API', 'NPY_1_7_API_VERSION')) del np def update_gdb_extension(ext, _has_gdb=[None]): # We should probably also check for Python support. if not include_debugger: _has_gdb[0] = False if _has_gdb[0] is None: try: subprocess.check_call(["gdb", "--version"]) except (IOError, subprocess.CalledProcessError): _has_gdb[0] = False else: _has_gdb[0] = True if not _has_gdb[0]: return EXCLUDE_EXT return ext def update_openmp_extension(ext): ext.openmp = True language = ext.language if sys.platform == 'win32' and sys.version_info[:2] == (3,4): # OpenMP tests fail in appveyor in Py3.4 -> just ignore them, EoL of Py3.4 is early 2019... return EXCLUDE_EXT if language == 'cpp': flags = OPENMP_CPP_COMPILER_FLAGS else: flags = OPENMP_C_COMPILER_FLAGS if flags: compile_flags, link_flags = flags ext.extra_compile_args.extend(compile_flags.split()) ext.extra_link_args.extend(link_flags.split()) return ext elif sys.platform == 'win32': return ext return EXCLUDE_EXT def update_cpp_extension(cpp_std, min_gcc_version=None, min_clang_version=None, min_macos_version=None): def _update_cpp_extension(ext): """ Update cpp[cpp_std] extensions that will run on minimum versions of gcc / clang / macos. """ # If the extension provides a -std=... option, assume that whatever C compiler we use # will probably be ok with it. already_has_std = any( ca for ca in ext.extra_compile_args if "-std" in ca and "-stdlib" not in ca ) use_gcc = use_clang = already_has_std # check for a usable gcc version gcc_version = get_gcc_version(ext.language) if gcc_version: if cpp_std >= 17 and sys.version_info[0] < 3: # The Python 2.7 headers contain the 'register' modifier # which gcc warns about in C++17 mode. ext.extra_compile_args.append('-Wno-register') if not already_has_std: compiler_version = gcc_version.group(1) if not min_gcc_version or float(compiler_version) >= float(min_gcc_version): use_gcc = True ext.extra_compile_args.append("-std=c++%s" % cpp_std) if use_gcc: return ext # check for a usable clang version clang_version = get_clang_version(ext.language) if clang_version: if cpp_std >= 17 and sys.version_info[0] < 3: # The Python 2.7 headers contain the 'register' modifier # which clang warns about in C++17 mode. ext.extra_compile_args.append('-Wno-register') if not already_has_std: compiler_version = clang_version.group(1) if not min_clang_version or float(compiler_version) >= float(min_clang_version): use_clang = True ext.extra_compile_args.append("-std=c++%s" % cpp_std) if sys.platform == "darwin": ext.extra_compile_args.append("-stdlib=libc++") if min_macos_version is not None: ext.extra_compile_args.append("-mmacosx-version-min=" + min_macos_version) if use_clang: return ext # no usable C compiler found => exclude the extension return EXCLUDE_EXT return _update_cpp_extension def require_gcc(version): def check(ext): gcc_version = get_gcc_version(ext.language) if gcc_version: if float(gcc_version.group(1)) >= float(version): return ext return EXCLUDE_EXT return check def get_cc_version(language): """ finds gcc version using Popen """ cc = '' if language == 'cpp': cc = os.environ.get('CXX') or sysconfig.get_config_var('CXX') if not cc: cc = os.environ.get('CC') or sysconfig.get_config_var('CC') if not cc: from distutils import ccompiler cc = ccompiler.get_default_compiler() if not cc: return '' # For some reason, cc can be e.g. 'gcc -pthread' cc = cc.split()[0] # Force english output env = os.environ.copy() env['LC_MESSAGES'] = 'C' try: p = subprocess.Popen([cc, "-v"], stderr=subprocess.PIPE, env=env) except EnvironmentError as exc: warnings.warn("Unable to find the %s compiler: %s: %s" % (language, os.strerror(exc.errno), cc)) return '' _, output = p.communicate() return output.decode(locale.getpreferredencoding() or 'ASCII', 'replace') def get_gcc_version(language): matcher = re.compile(r"gcc version (\d+\.\d+)").search return matcher(get_cc_version(language)) def get_clang_version(language): matcher = re.compile(r"clang(?:-|\s+version\s+)(\d+\.\d+)").search return matcher(get_cc_version(language)) def get_openmp_compiler_flags(language): """ As of gcc 4.2, it supports OpenMP 2.5. Gcc 4.4 implements 3.0. We don't (currently) check for other compilers. returns a two-tuple of (CFLAGS, LDFLAGS) to build the OpenMP extension """ gcc_version = get_gcc_version(language) if not gcc_version: if sys.platform == 'win32': return '/openmp', '' else: return None # not gcc - FIXME: do something about other compilers # gcc defines "__int128_t", assume that at least all 64 bit architectures have it global COMPILER_HAS_INT128 COMPILER_HAS_INT128 = getattr(sys, 'maxsize', getattr(sys, 'maxint', 0)) > 2**60 compiler_version = gcc_version.group(1) if compiler_version: compiler_version = [int(num) for num in compiler_version.split('.')] if compiler_version >= [4, 2]: return '-fopenmp', '-fopenmp' try: locale.setlocale(locale.LC_ALL, '') except locale.Error: pass COMPILER = None COMPILER_HAS_INT128 = False OPENMP_C_COMPILER_FLAGS = get_openmp_compiler_flags('c') OPENMP_CPP_COMPILER_FLAGS = get_openmp_compiler_flags('cpp') # Return this from the EXT_EXTRAS matcher callback to exclude the extension EXCLUDE_EXT = object() EXT_EXTRAS = { 'tag:numpy' : update_numpy_extension, 'tag:openmp': update_openmp_extension, 'tag:gdb': update_gdb_extension, 'tag:cpp11': update_cpp_extension(11, min_gcc_version="4.9", min_macos_version="10.7"), 'tag:cpp17': update_cpp_extension(17, min_gcc_version="5.0", min_macos_version="10.13"), 'tag:cpp20': update_cpp_extension(20, min_gcc_version="11.0", min_clang_version="13.0", min_macos_version="10.13"), 'tag:trace' : update_linetrace_extension, 'tag:bytesformat': exclude_extension_in_pyver((3, 3), (3, 4)), # no %-bytes formatting 'tag:no-macos': exclude_extension_on_platform('darwin'), 'tag:py3only': exclude_extension_in_pyver((2, 7)), 'tag:cppexecpolicies': require_gcc("9.1"), } # TODO: use tags VER_DEP_MODULES = { # tests are excluded if 'CurrentPythonVersion OP VersionTuple', i.e. # (2,4) : (operator.lt, ...) excludes ... when PyVer < 2.4.x # The next line should start (3,); but this is a dictionary, so # we can only have one (3,) key. Since 2.7 is supposed to be the # last 2.x release, things would have to change drastically for this # to be unsafe... (2,999): (operator.lt, lambda x: x in ['run.special_methods_T561_py3', 'run.test_raisefrom', 'run.different_package_names', 'run.unicode_imports', # encoding problems on appveyor in Py2 'run.reimport_failure', # reimports don't do anything in Py2 'run.cpp_stl_cmath_cpp17', 'run.cpp_stl_cmath_cpp20' ]), (3,): (operator.ge, lambda x: x in ['run.non_future_division', 'compile.extsetslice', 'compile.extdelslice', 'run.special_methods_T561_py2', 'run.builtin_type_inheritance_T608_py2only', ]), (3,3) : (operator.lt, lambda x: x in ['build.package_compilation', 'build.cythonize_pep420_namespace', 'run.yield_from_py33', 'pyximport.pyximport_namespace', 'run.qualname', ]), (3,4): (operator.lt, lambda x: x in ['run.py34_signature', 'run.test_unicode', # taken from Py3.7, difficult to backport 'run.pep442_tp_finalize', 'run.pep442_tp_finalize_cimport', ]), (3,4,999): (operator.gt, lambda x: x in ['run.initial_file_path', ]), (3,5): (operator.lt, lambda x: x in ['run.py35_pep492_interop', 'run.py35_asyncio_async_def', 'run.mod__spec__', 'run.pep526_variable_annotations', # typing module 'run.test_exceptions', # copied from Py3.7+ 'run.time_pxd', # _PyTime_GetSystemClock doesn't exist in 3.4 'run.cpython_capi_py35', 'embedding.embedded', # From the docs, needs Py_DecodeLocale ]), (3,7): (operator.lt, lambda x: x in ['run.pycontextvar', 'run.pep557_dataclasses', # dataclasses module 'run.test_dataclasses', 'run.isolated_limited_api_tests', ]), (3,8): (operator.lt, lambda x: x in ['run.special_methods_T561_py38', ]), (3,11,999): (operator.gt, lambda x: x in [ 'run.py_unicode_strings', # Py_UNICODE was removed 'compile.pylong', # PyLongObject changed its structure 'run.longintrepr', # PyLongObject changed its structure ]), # See https://github.com/python/cpython/issues/104614 - fixed in Py3.12.0b2, remove eventually. (3,12,0,'beta',1): (operator.eq, lambda x: 'cdef_multiple_inheritance' in x or 'pep442' in x), # Profiling is broken on Python 3.12 (3,12): ((lambda actual, v3_12: actual[:2]==v3_12), (lambda x: "pstats" in x)), } INCLUDE_DIRS = [ d for d in os.getenv('INCLUDE', '').split(os.pathsep) if d ] CFLAGS = os.getenv('CFLAGS', '').split() CCACHE = os.getenv('CYTHON_RUNTESTS_CCACHE', '').split() CDEFS = [] TEST_SUPPORT_DIR = 'testsupport' BACKENDS = ['c', 'cpp'] UTF8_BOM_BYTES = r'\xef\xbb\xbf'.encode('ISO-8859-1').decode('unicode_escape') # A selector that can be used to determine whether to run with Py_LIMITED_API # (if run in limited api mode) limited_api_full_tests = None def memoize(f): uncomputed = object() f._cache = {} def func(*args): res = f._cache.get(args, uncomputed) if res is uncomputed: res = f._cache[args] = f(*args) return res return func @memoize def parse_tags(filepath): tags = defaultdict(list) parse_tag = re.compile(r'#\s*(\w+)\s*:(.*)$').match with io_open(filepath, encoding='ISO-8859-1', errors='ignore') as f: for line in f: # ignore BOM-like bytes and whitespace line = line.lstrip(UTF8_BOM_BYTES).strip() if not line: if tags: break # assume all tags are in one block else: continue if line[0] != '#': break parsed = parse_tag(line) if parsed: tag, values = parsed.groups() if tag in ('coding', 'encoding'): continue if tag == 'tags': raise RuntimeError("test tags use the 'tag' directive, not 'tags' (%s)" % filepath) if tag not in ('mode', 'tag', 'ticket', 'cython', 'distutils', 'preparse'): print("WARNING: unknown test directive '%s' found (%s)" % (tag, filepath)) values = values.split(',') tags[tag].extend(filter(None, [value.strip() for value in values])) elif tags: break # assume all tags are in one block return tags list_unchanging_dir = memoize(lambda x: os.listdir(x)) # needs lambda to set function attribute @memoize def _list_pyregr_data_files(test_directory): is_data_file = re.compile('(?:[.](txt|pem|db|html)|^bad.*[.]py)$').search return ['__init__.py'] + [ filename for filename in list_unchanging_dir(test_directory) if is_data_file(filename)] def import_module_from_file(module_name, file_path, execute=True): import importlib.util spec = importlib.util.spec_from_file_location(module_name, file_path) m = importlib.util.module_from_spec(spec) if execute: sys.modules[module_name] = m spec.loader.exec_module(m) return m def import_ext(module_name, file_path=None): if file_path: if sys.version_info >= (3, 5): return import_module_from_file(module_name, file_path) else: import imp return imp.load_dynamic(module_name, file_path) else: try: from importlib import invalidate_caches except ImportError: pass else: invalidate_caches() return __import__(module_name, globals(), locals(), ['*']) class build_ext(_build_ext): def build_extension(self, ext): try: try: # Py2.7+ & Py3.2+ compiler_obj = self.compiler_obj except AttributeError: compiler_obj = self.compiler if ext.language == 'c++': compiler_obj.compiler_so.remove('-Wstrict-prototypes') if CCACHE: compiler_obj.compiler_so = CCACHE + compiler_obj.compiler_so if getattr(ext, 'openmp', None) and compiler_obj.compiler_type == 'msvc': ext.extra_compile_args.append('/openmp') except Exception: pass _build_ext.build_extension(self, ext) class ErrorWriter(object): match_error = re.compile( r'(?:(warning|performance hint):)?(?:.*:)?\s*([-0-9]+)\s*:\s*([-0-9]+)\s*:\s*(.*)').match def __init__(self, encoding=None): self.output = [] self.encoding = encoding def write(self, value): if self.encoding: value = value.encode('ISO-8859-1').decode(self.encoding) self.output.append(value) def _collect(self): s = ''.join(self.output) results = {'error': [], 'warning': [], 'performance hint': []} for line in s.splitlines(): match = self.match_error(line) if match: message_type, line, column, message = match.groups() results[message_type or 'error'].append((int(line), int(column), message.strip())) return [ ["%d:%d: %s" % values for values in sorted(results[key])] for key in ('error', 'warning', 'performance hint') ] def geterrors(self): return self._collect()[0] def getall(self): return self._collect() def close(self): pass # ignore, only to match file-like interface class Stats(object): def __init__(self, top_n=8): self.top_n = top_n self.test_counts = defaultdict(int) self.test_times = defaultdict(float) self.top_tests = defaultdict(list) def add_time(self, name, language, metric, t, count=1): self.test_counts[metric] += count self.test_times[metric] += t top = self.top_tests[metric] push = heapq.heappushpop if len(top) >= self.top_n else heapq.heappush # min-heap => pop smallest/shortest until longest times remain push(top, (t, name, language)) @contextmanager def time(self, name, language, metric): t = time.time() yield t = time.time() - t self.add_time(name, language, metric, t) def update(self, stats): # type: (Stats) -> None for metric, t in stats.test_times.items(): self.test_times[metric] += t self.test_counts[metric] += stats.test_counts[metric] top = self.top_tests[metric] for entry in stats.top_tests[metric]: push = heapq.heappushpop if len(top) >= self.top_n else heapq.heappush push(top, entry) def print_stats(self, out=sys.stderr): if not self.test_times: return lines = ['Times:\n'] for metric, t in sorted(self.test_times.items(), key=operator.itemgetter(1), reverse=True): count = self.test_counts[metric] top = self.top_tests[metric] lines.append("%-12s: %8.2f sec (%4d, %6.3f / run) - slowest: %s\n" % ( metric, t, count, t / count, ', '.join("'{2}:{1}' ({0:.2f}s)".format(*item) for item in heapq.nlargest(self.top_n, top)))) out.write(''.join(lines)) class TestBuilder(object): def __init__(self, rootdir, workdir, selectors, exclude_selectors, options, with_pyregr, languages, test_bugs, language_level, common_utility_dir, pythran_dir=None, default_mode='run', stats=None, add_embedded_test=False, add_cython_import=False, add_cpp_locals_extra_tests=False): self.rootdir = rootdir self.workdir = workdir self.selectors = selectors self.exclude_selectors = exclude_selectors self.shard_num = options.shard_num self.annotate = options.annotate_source self.cleanup_workdir = options.cleanup_workdir self.cleanup_sharedlibs = options.cleanup_sharedlibs self.cleanup_failures = options.cleanup_failures self.with_pyregr = with_pyregr self.cython_only = options.cython_only self.test_selector = re.compile(options.only_pattern).search if options.only_pattern else None self.languages = languages self.test_bugs = test_bugs self.fork = options.fork self.language_level = language_level self.test_determinism = options.test_determinism self.common_utility_dir = common_utility_dir self.pythran_dir = pythran_dir self.default_mode = default_mode self.stats = stats self.add_embedded_test = add_embedded_test self.add_cython_import = add_cython_import self.capture = options.capture self.add_cpp_locals_extra_tests = add_cpp_locals_extra_tests def build_suite(self): suite = unittest.TestSuite() filenames = os.listdir(self.rootdir) filenames.sort() # TODO: parallelise I/O with a thread pool for the different directories once we drop Py2 support for filename in filenames: path = os.path.join(self.rootdir, filename) if os.path.isdir(path) and filename != TEST_SUPPORT_DIR: if filename == 'pyregr' and not self.with_pyregr: continue if filename == 'broken' and not self.test_bugs: continue suite.addTest( self.handle_directory(path, filename)) if (sys.platform not in ['win32'] and self.add_embedded_test # the embedding test is currently broken in Py3.8+ and Py2.7, except on Linux. and ((3, 0) <= sys.version_info < (3, 8) or sys.platform != 'darwin')): # Non-Windows makefile. if [1 for selector in self.selectors if selector("embedded")] \ and not [1 for selector in self.exclude_selectors if selector("embedded")]: suite.addTest(unittest.TestLoader().loadTestsFromTestCase(EmbedTest)) return suite def handle_directory(self, path, context): workdir = os.path.join(self.workdir, context) if not os.path.exists(workdir): os.makedirs(workdir) suite = unittest.TestSuite() filenames = list_unchanging_dir(path) filenames.sort() for filename in filenames: filepath = os.path.join(path, filename) module, ext = os.path.splitext(filename) if ext not in ('.py', '.pyx', '.srctree'): continue if filename.startswith('.'): continue # certain emacs backup files if context == 'pyregr': tags = defaultdict(list) else: tags = parse_tags(filepath) fqmodule = "%s.%s" % (context, module) if not [ 1 for match in self.selectors if match(fqmodule, tags) ]: continue if self.exclude_selectors: if [1 for match in self.exclude_selectors if match(fqmodule, tags)]: continue full_limited_api_mode = False if limited_api_full_tests and limited_api_full_tests(fqmodule): # TODO this (and CYTHON_LIMITED_API) don't yet make it into end-to-end tests full_limited_api_mode = True mode = self.default_mode if tags['mode']: mode = tags['mode'][0] elif context == 'pyregr': mode = 'pyregr' if ext == '.srctree': if self.cython_only: # EndToEnd tests always execute arbitrary build and test code continue if skip_limited(tags): continue if 'cpp' not in tags['tag'] or 'cpp' in self.languages: suite.addTest(EndToEndTest(filepath, workdir, self.cleanup_workdir, stats=self.stats, capture=self.capture, shard_num=self.shard_num)) continue # Choose the test suite. if mode == 'pyregr': if not filename.startswith('test_'): continue test_class = CythonPyregrTestCase elif mode == 'run': if module.startswith("test_"): test_class = CythonUnitTestCase else: test_class = CythonRunTestCase elif mode in ['compile', 'error']: test_class = CythonCompileTestCase else: raise KeyError('Invalid test mode: ' + mode) for test in self.build_tests(test_class, path, workdir, module, filepath, mode == 'error', tags, full_limited_api_mode=full_limited_api_mode): suite.addTest(test) if mode == 'run' and ext == '.py' and not self.cython_only and not filename.startswith('test_'): # additionally test file in real Python min_py_ver = [ (int(pyver.group(1)), int(pyver.group(2))) for pyver in map(re.compile(r'pure([0-9]+)[.]([0-9]+)').match, tags['tag']) if pyver ] if not min_py_ver or any(sys.version_info >= min_ver for min_ver in min_py_ver): suite.addTest(PureDoctestTestCase( module, filepath, tags, stats=self.stats, shard_num=self.shard_num)) return suite def build_tests(self, test_class, path, workdir, module, module_path, expect_errors, tags, full_limited_api_mode): warning_errors = 'werror' in tags['tag'] expect_log = ("errors",) if expect_errors else () if 'warnings' in tags['tag']: expect_log += ("warnings",) if "perf_hints" in tags['tag']: expect_log += ("perf_hints",) extra_directives_list = [{}] if expect_errors: if skip_c(tags) and 'cpp' in self.languages: languages = ['cpp'] else: languages = self.languages[:1] else: languages = self.languages if 'c' in languages and skip_c(tags): languages = list(languages) languages.remove('c') if 'cpp' in languages and 'no-cpp' in tags['tag']: languages = list(languages) languages.remove('cpp') if (self.add_cpp_locals_extra_tests and 'cpp' in languages and 'cpp' in tags['tag'] and not 'no-cpp-locals' in tags['tag']): extra_directives_list.append({'cpp_locals': True}) if not languages: return [] if skip_limited(tags): return [] language_levels = [2, 3] if 'all_language_levels' in tags['tag'] else [None] pythran_dir = self.pythran_dir if 'pythran' in tags['tag'] and not pythran_dir and 'cpp' in languages: import pythran.config try: pythran_ext = pythran.config.make_extension(python=True) except TypeError: # old pythran version syntax pythran_ext = pythran.config.make_extension() pythran_dir = pythran_ext['include_dirs'][0] add_cython_import = self.add_cython_import and module_path.endswith('.py') preparse_list = tags.get('preparse', ['id']) tests = [ self.build_test(test_class, path, workdir, module, module_path, tags, language, language_level, expect_log, warning_errors, preparse, pythran_dir if language == "cpp" else None, add_cython_import=add_cython_import, extra_directives=extra_directives, full_limited_api_mode=full_limited_api_mode) for language in languages for preparse in preparse_list for language_level in language_levels for extra_directives in extra_directives_list ] return tests def build_test(self, test_class, path, workdir, module, module_path, tags, language, language_level, expect_log, warning_errors, preparse, pythran_dir, add_cython_import, extra_directives, full_limited_api_mode): language_workdir = os.path.join(workdir, language) if not os.path.exists(language_workdir): os.makedirs(language_workdir) workdir = os.path.join(language_workdir, module) if preparse != 'id': workdir += '_%s' % (preparse,) if language_level: workdir += '_cy%d' % (language_level,) if extra_directives: workdir += ('_directives_'+ '_'.join('%s_%s' % (k, v) for k,v in extra_directives.items())) return test_class(path, workdir, module, module_path, tags, language=language, preparse=preparse, expect_log=expect_log, annotate=self.annotate, cleanup_workdir=self.cleanup_workdir, cleanup_sharedlibs=self.cleanup_sharedlibs, cleanup_failures=self.cleanup_failures, cython_only=self.cython_only, test_selector=self.test_selector, shard_num=self.shard_num, fork=self.fork, language_level=language_level or self.language_level, warning_errors=warning_errors, test_determinism=self.test_determinism, common_utility_dir=self.common_utility_dir, pythran_dir=pythran_dir, stats=self.stats, add_cython_import=add_cython_import, full_limited_api_mode=full_limited_api_mode, ) def skip_c(tags): if 'cpp' in tags['tag']: return True # We don't want to create a distutils key in the # dictionary so we check before looping. if 'distutils' in tags: for option in tags['distutils']: split = option.split('=') if len(split) == 2: argument, value = split if argument.strip() == 'language' and value.strip() == 'c++': return True return False def skip_limited(tags): if 'limited-api' in tags['tag']: # Run limited-api tests only on CPython 3.x. if sys.version_info[0] < 3: return True if sys.implementation.name != 'cpython': return True return False def filter_stderr(stderr_bytes): """ Filter annoying warnings from output. """ if b"Command line warning D9025" in stderr_bytes: # MSCV: cl : Command line warning D9025 : overriding '/Ox' with '/Od' stderr_bytes = b'\n'.join( line for line in stderr_bytes.splitlines() if b"Command line warning D9025" not in line) return stderr_bytes def filter_test_suite(test_suite, selector): filtered_tests = [] for test in test_suite._tests: if isinstance(test, unittest.TestSuite): filter_test_suite(test, selector) elif not selector(test.id()): continue filtered_tests.append(test) test_suite._tests[:] = filtered_tests class CythonCompileTestCase(unittest.TestCase): def __init__(self, test_directory, workdir, module, module_path, tags, language='c', preparse='id', expect_log=(), annotate=False, cleanup_workdir=True, cleanup_sharedlibs=True, cleanup_failures=True, cython_only=False, test_selector=None, fork=True, language_level=2, warning_errors=False, test_determinism=False, shard_num=0, common_utility_dir=None, pythran_dir=None, stats=None, add_cython_import=False, extra_directives=None, full_limited_api_mode=False): if extra_directives is None: extra_directives = {} self.test_directory = test_directory self.tags = tags self.workdir = workdir self.module = module self.module_path = module_path self.language = language self.preparse = preparse self.name = module if self.preparse == "id" else "%s_%s" % (module, preparse) self.expect_log = expect_log self.annotate = annotate self.cleanup_workdir = cleanup_workdir self.cleanup_sharedlibs = cleanup_sharedlibs self.cleanup_failures = cleanup_failures self.cython_only = cython_only self.test_selector = test_selector self.shard_num = shard_num self.fork = fork self.language_level = language_level self.warning_errors = warning_errors self.test_determinism = test_determinism self.common_utility_dir = common_utility_dir self.pythran_dir = pythran_dir self.stats = stats self.add_cython_import = add_cython_import self.extra_directives = extra_directives self.full_limited_api_mode = full_limited_api_mode unittest.TestCase.__init__(self) def shortDescription(self): return "[%d] compiling (%s%s%s) %s" % ( self.shard_num, self.language, "/cy2" if self.language_level == 2 else "/cy3" if self.language_level == 3 else "", "/pythran" if self.pythran_dir is not None else "", self.description_name() ) def description_name(self): return self.name def setUp(self): from Cython.Compiler import Options self._saved_options = [ (name, getattr(Options, name)) for name in ( 'warning_errors', 'clear_to_none', 'error_on_unknown_names', 'error_on_uninitialized', # 'cache_builtins', # not currently supported due to incorrect global caching ) ] self._saved_default_directives = list(Options.get_directive_defaults().items()) Options.warning_errors = self.warning_errors if sys.version_info >= (3, 4): Options._directive_defaults['autotestdict'] = False Options._directive_defaults.update(self.extra_directives) if not os.path.exists(self.workdir): os.makedirs(self.workdir) if self.workdir not in sys.path: sys.path.insert(0, self.workdir) if self.add_cython_import: with open(self.module_path, 'rb') as f: source = f.read() if b'cython.cimports.' in source: from Cython.Shadow import CythonCImports for name in set(re.findall(br"(cython\.cimports(?:\.\w+)+)", source)): name = name.decode() sys.modules[name] = CythonCImports(name) def tearDown(self): from Cython.Compiler import Options for name, value in self._saved_options: setattr(Options, name, value) Options._directive_defaults = dict(self._saved_default_directives) unpatch_inspect_isfunction() try: sys.path.remove(self.workdir) except ValueError: pass try: del sys.modules[self.module] except KeyError: pass # remove any stubs of cimported modules in pure Python mode if self.add_cython_import: for name in list(sys.modules): if name.startswith('cython.cimports.'): del sys.modules[name] cleanup = self.cleanup_failures or self.success cleanup_c_files = WITH_CYTHON and self.cleanup_workdir and cleanup cleanup_lib_files = self.cleanup_sharedlibs and cleanup is_cygwin = sys.platform == 'cygwin' if os.path.exists(self.workdir): if cleanup_c_files and cleanup_lib_files and not is_cygwin: shutil.rmtree(self.workdir, ignore_errors=True) else: for rmfile in os.listdir(self.workdir): ext = os.path.splitext(rmfile)[1] if not cleanup_c_files: # Keep C, C++ files, header files, preprocessed sources # and assembly sources (typically the .i and .s files # are intentionally generated when -save-temps is given) if ext in (".c", ".cpp", ".h", ".i", ".ii", ".s"): continue if ext == ".html" and rmfile.startswith(self.module): continue is_shared_obj = ext in (".so", ".dll") if not cleanup_lib_files and is_shared_obj: continue try: rmfile = os.path.join(self.workdir, rmfile) if os.path.isdir(rmfile): shutil.rmtree(rmfile, ignore_errors=True) elif is_cygwin and is_shared_obj: # Delete later _to_clean.append(rmfile) else: os.remove(rmfile) except IOError: pass if cleanup_c_files and cleanup_lib_files and is_cygwin: # Finally, remove the work dir itself _to_clean.append(self.workdir) if cleanup_c_files and os.path.exists(self.workdir + '-again'): shutil.rmtree(self.workdir + '-again', ignore_errors=True) def runTest(self): self.success = False self.runCompileTest() self.success = True def runCompileTest(self): return self.compile( self.test_directory, self.module, self.module_path, self.workdir, self.test_directory, self.expect_log, self.annotate, self.add_cython_import) def find_module_source_file(self, source_file): if not os.path.exists(source_file): source_file = source_file[:-1] return source_file def build_target_filename(self, module_name): target = '%s.%s' % (module_name, self.language) return target def related_files(self, test_directory, module_name): is_related = re.compile('%s_.*[.].*' % module_name).match return [filename for filename in list_unchanging_dir(test_directory) if is_related(filename)] def copy_files(self, test_directory, target_directory, file_list): if self.preparse and self.preparse != 'id': preparse_func = globals()[self.preparse] def copy(src, dest): with open(src) as fin: with open(dest, 'w') as fout: fout.write(preparse_func(fin.read())) else: # use symlink on Unix, copy on Windows copy = os.symlink if CAN_SYMLINK else shutil.copy join = os.path.join for filename in file_list: file_path = join(test_directory, filename) if os.path.exists(file_path): copy(file_path, join(target_directory, filename)) def source_files(self, workdir, module_name, file_list): return ([self.build_target_filename(module_name)] + [filename for filename in file_list if not os.path.isfile(os.path.join(workdir, filename))]) def split_source_and_output(self, source_file, workdir, add_cython_import=False): from Cython.Utils import detect_opened_file_encoding with io_open(source_file, 'rb') as f: # encoding is passed to ErrorWriter but not used on the source # since it is sometimes deliberately wrong encoding = detect_opened_file_encoding(f, default=None) with io_open(source_file, 'r', encoding='ISO-8859-1') as source_and_output: error_writer = warnings_writer = perf_hint_writer = None out = io_open(os.path.join(workdir, os.path.basename(source_file)), 'w', encoding='ISO-8859-1') try: for line in source_and_output: if line.startswith(u"_ERRORS"): out.close() out = error_writer = ErrorWriter(encoding=encoding) elif line.startswith(u"_WARNINGS"): out.close() out = warnings_writer = ErrorWriter(encoding=encoding) elif line.startswith(u"_PERFORMANCE_HINTS"): out.close() out = perf_hint_writer = ErrorWriter(encoding=encoding) else: if add_cython_import and line.strip() and not ( line.startswith(u'#') or line.startswith(u"from __future__ import ")): # insert "import cython" statement after any directives or future imports if line != u"import cython\n": out.write(u"import cython\n") add_cython_import = False out.write(line) finally: out.close() return (error_writer.geterrors() if error_writer else [], warnings_writer.geterrors() if warnings_writer else [], perf_hint_writer.geterrors() if perf_hint_writer else []) def run_cython(self, test_directory, module, module_path, targetdir, incdir, annotate, extra_compile_options=None): include_dirs = INCLUDE_DIRS + [os.path.join(test_directory, '..', TEST_SUPPORT_DIR)] if incdir: include_dirs.append(incdir) if self.preparse != 'id' and test_directory != targetdir: file_name = os.path.basename(module_path) self.copy_files(test_directory, targetdir, [file_name]) module_path = os.path.join(targetdir, file_name) target = os.path.join(targetdir, self.build_target_filename(module)) if extra_compile_options is None: extra_compile_options = {} if 'allow_unknown_names' in self.tags['tag']: from Cython.Compiler import Options Options.error_on_unknown_names = False try: # see configure_cython() CompilationOptions, cython_compile, pyrex_default_options except NameError: from Cython.Compiler.Options import ( CompilationOptions, default_options as pyrex_default_options, ) from Cython.Compiler.Main import compile as cython_compile common_utility_include_dir = self.common_utility_dir options = CompilationOptions( pyrex_default_options, include_path = include_dirs, output_file = target, annotate = annotate, use_listing_file = False, cplus = self.language == 'cpp', np_pythran = self.pythran_dir is not None, language_level = self.language_level, generate_pxi = False, evaluate_tree_assertions = True, common_utility_include_dir = common_utility_include_dir, **extra_compile_options ) cython_compile(module_path, options=options, full_module_name=module) def run_distutils(self, test_directory, module, workdir, incdir, extra_extension_args=None): cwd = os.getcwd() os.chdir(workdir) try: build_extension = build_ext(get_distutils_distro()) build_extension.include_dirs = INCLUDE_DIRS[:] if incdir: build_extension.include_dirs.append(incdir) build_extension.finalize_options() if COMPILER: build_extension.compiler = COMPILER ext_compile_flags = CFLAGS[:] ext_compile_defines = CDEFS[:] if build_extension.compiler == 'mingw32': ext_compile_flags.append('-Wno-format') if extra_extension_args is None: extra_extension_args = {} related_files = self.related_files(test_directory, module) self.copy_files(test_directory, workdir, related_files) from distutils.core import Extension extension = Extension( module, sources=self.source_files(workdir, module, related_files), extra_compile_args=ext_compile_flags, define_macros=ext_compile_defines, **extra_extension_args ) if self.language == 'cpp': # Set the language now as the fixer might need it extension.language = 'c++' if self.extra_directives.get('cpp_locals'): extension = update_cpp17_extension(extension) if extension is EXCLUDE_EXT: return if 'distutils' in self.tags: from Cython.Build.Dependencies import DistutilsInfo from Cython.Utils import open_source_file pyx_path = self.find_module_source_file( os.path.join(self.test_directory, self.module + ".pyx")) with open_source_file(pyx_path) as f: DistutilsInfo(f).apply(extension) if self.pythran_dir: from Cython.Build.Dependencies import update_pythran_extension update_pythran_extension(extension) # Compile with -DCYTHON_CLINE_IN_TRACEBACK=1 unless we have # the "traceback" tag if 'traceback' not in self.tags['tag']: extension.define_macros.append(("CYTHON_CLINE_IN_TRACEBACK", 1)) # Allow tests to be incrementally enabled with Py_LIMITED_API set. # This is intended to be temporary while limited API support # is improved. Eventually we'll want to move to excluding tests if self.full_limited_api_mode: extension.define_macros.append(("Py_LIMITED_API", 'PY_VERSION_HEX')) for matcher, fixer in list(EXT_EXTRAS.items()): if isinstance(matcher, str): # lazy init del EXT_EXTRAS[matcher] matcher = string_selector(matcher) EXT_EXTRAS[matcher] = fixer if matcher(module, self.tags): newext = fixer(extension) if newext is EXCLUDE_EXT: return skip_test("Test '%s' excluded due to tags '%s'" % ( self.name, ', '.join(self.tags.get('tag', '')))) extension = newext or extension if self.language == 'cpp': extension.language = 'c++' if IS_PY2: workdir = str(workdir) # work around type check in distutils that disallows unicode strings build_extension.extensions = [extension] build_extension.build_temp = workdir build_extension.build_lib = workdir from Cython.Utils import captured_fd, prepare_captured from distutils.errors import CompileError error = None with captured_fd(2) as get_stderr: try: build_extension.run() except CompileError as exc: error = str(exc) stderr = get_stderr() if stderr and b"Command line warning D9025" in stderr: # Manually suppress annoying MSVC warnings about overridden CLI arguments. stderr = b''.join([ line for line in stderr.splitlines(keepends=True) if b"Command line warning D9025" not in line ]) if stderr: # The test module name should always be ASCII, but let's not risk encoding failures. output = b"Compiler output for module " + module.encode('utf-8') + b":\n" + stderr + b"\n" out = sys.stdout if sys.version_info[0] == 2 else sys.stdout.buffer out.write(output) if error is not None: raise CompileError(u"%s\nCompiler output:\n%s" % (error, prepare_captured(stderr))) finally: os.chdir(cwd) try: get_ext_fullpath = build_extension.get_ext_fullpath except AttributeError: def get_ext_fullpath(ext_name, self=build_extension): # copied from distutils.command.build_ext (missing in Py2.[45]) fullname = self.get_ext_fullname(ext_name) modpath = fullname.split('.') filename = self.get_ext_filename(modpath[-1]) if not self.inplace: filename = os.path.join(*modpath[:-1]+[filename]) return os.path.join(self.build_lib, filename) package = '.'.join(modpath[0:-1]) build_py = self.get_finalized_command('build_py') package_dir = os.path.abspath(build_py.get_package_dir(package)) return os.path.join(package_dir, filename) return get_ext_fullpath(module) def compile(self, test_directory, module, module_path, workdir, incdir, expect_log, annotate, add_cython_import): expected_errors = expected_warnings = expected_perf_hints = errors = warnings = perf_hints = () expect_errors = "errors" in expect_log expect_warnings = "warnings" in expect_log expect_perf_hints = "perf_hints" in expect_log if expect_errors or expect_warnings or expect_perf_hints or add_cython_import: expected_errors, expected_warnings, expected_perf_hints = self.split_source_and_output( module_path, workdir, add_cython_import) test_directory = workdir module_path = os.path.join(workdir, os.path.basename(module_path)) if WITH_CYTHON: old_stderr = sys.stderr try: sys.stderr = ErrorWriter() with self.stats.time(self.name, self.language, 'cython'): self.run_cython(test_directory, module, module_path, workdir, incdir, annotate) errors, warnings, perf_hints = sys.stderr.getall() finally: sys.stderr = old_stderr if self.test_determinism and not expect_errors: workdir2 = workdir + '-again' os.mkdir(workdir2) self.run_cython(test_directory, module, module_path, workdir2, incdir, annotate) diffs = [] for file in os.listdir(workdir2): with open(os.path.join(workdir, file)) as fid: txt1 = fid.read() with open(os.path.join(workdir2, file)) as fid: txt2 = fid.read() if txt1 != txt2: diffs.append(file) os.system('diff -u %s/%s %s/%s > %s/%s.diff' % ( workdir, file, workdir2, file, workdir2, file)) if diffs: self.fail('Nondeterministic file generation: %s' % ', '.join(diffs)) tostderr = sys.__stderr__.write if expected_warnings or (expect_warnings and warnings): self._match_output(expected_warnings, warnings, tostderr) if expected_perf_hints or (expect_perf_hints and perf_hints): self._match_output(expected_perf_hints, perf_hints, tostderr) if 'cerror' in self.tags['tag']: if errors: tostderr("\n=== Expected C compile error ===\n") tostderr("\n=== Got Cython errors: ===\n") tostderr('\n'.join(errors)) tostderr('\n\n') raise RuntimeError('should have generated extension code') elif errors or expected_errors: self._match_output(expected_errors, errors, tostderr) return None so_path = None if not self.cython_only: from Cython.Utils import captured_fd, print_bytes from distutils.errors import CompileError, LinkError show_output = True get_stderr = get_stdout = None try: with captured_fd(1) as get_stdout: with captured_fd(2) as get_stderr: with self.stats.time(self.name, self.language, 'compile-%s' % self.language): so_path = self.run_distutils(test_directory, module, workdir, incdir) except Exception as exc: if ('cerror' in self.tags['tag'] and ((get_stderr and get_stderr()) or isinstance(exc, (CompileError, LinkError)))): show_output = False # expected C compiler failure else: raise else: if 'cerror' in self.tags['tag']: raise RuntimeError('should have failed C compile') finally: if show_output: stdout = get_stdout and get_stdout().strip() stderr = get_stderr and filter_stderr(get_stderr()).strip() if so_path and not stderr: # normal success case => ignore non-error compiler output stdout = None if stdout: print_bytes( stdout, header_text="\n=== C/C++ compiler output: =========\n", end=None, file=sys.__stderr__) if stderr: print_bytes( stderr, header_text="\n=== C/C++ compiler error output: ===\n", end=None, file=sys.__stderr__) if stdout or stderr: tostderr("\n====================================\n") return so_path def _match_output(self, expected_output, actual_output, write): try: for expected, actual in zip(expected_output, actual_output): if expected != actual and '\\' in actual and os.sep == '\\' and '/' in expected and '\\' not in expected: expected = expected.replace('/', '\\') self.assertEqual(expected, actual) if len(actual_output) < len(expected_output): expected = expected_output[len(actual_output)] self.assertEqual(expected, None) elif len(actual_output) > len(expected_output): unexpected = actual_output[len(expected_output)] self.assertEqual(None, unexpected) except AssertionError: write("\n=== Expected: ===\n") write('\n'.join(expected_output)) write("\n\n=== Got: ===\n") write('\n'.join(actual_output)) write('\n\n') raise class CythonRunTestCase(CythonCompileTestCase): def setUp(self): CythonCompileTestCase.setUp(self) from Cython.Compiler import Options Options.clear_to_none = False def description_name(self): return self.name if self.cython_only else "and running %s" % self.name def run(self, result=None): if result is None: result = self.defaultTestResult() result.startTest(self) try: self.setUp() try: self.success = False ext_so_path = self.runCompileTest() failures, errors, skipped = len(result.failures), len(result.errors), len(result.skipped) if not self.cython_only and ext_so_path is not None: self.run_tests(result, ext_so_path) if failures == len(result.failures) and errors == len(result.errors): # No new errors... self.success = True finally: check_thread_termination() except SkipTest as exc: result.addSkip(self, str(exc)) result.stopTest(self) except Exception: result.addError(self, sys.exc_info()) result.stopTest(self) try: self.tearDown() except Exception: pass def run_tests(self, result, ext_so_path): self.run_doctests(self.module, result, ext_so_path) def run_doctests(self, module_or_name, result, ext_so_path): def run_test(result): if isinstance(module_or_name, basestring): with self.stats.time(self.name, self.language, 'import'): module = import_ext(module_or_name, ext_so_path) else: module = module_or_name tests = doctest.DocTestSuite(module) if self.test_selector: filter_test_suite(tests, self.test_selector) with self.stats.time(self.name, self.language, 'run'): tests.run(result) run_forked_test(result, run_test, self.shortDescription(), self.fork) def run_forked_test(result, run_func, test_name, fork=True): if not fork or sys.version_info[0] >= 3 or not hasattr(os, 'fork'): run_func(result) sys.stdout.flush() sys.stderr.flush() gc.collect() return # fork to make sure we do not keep the tested module loaded result_handle, result_file = tempfile.mkstemp() os.close(result_handle) child_id = os.fork() if not child_id: result_code = 0 try: try: tests = partial_result = None try: partial_result = PartialTestResult(result) run_func(partial_result) sys.stdout.flush() sys.stderr.flush() gc.collect() except Exception: result_code = 1 if partial_result is not None: if tests is None: # importing failed, try to fake a test class tests = _FakeClass( failureException=sys.exc_info()[1], _shortDescription=test_name, module_name=None) partial_result.addError(tests, sys.exc_info()) if partial_result is not None: with open(result_file, 'wb') as output: pickle.dump(partial_result.data(), output) except: traceback.print_exc() finally: try: sys.stderr.flush() except: pass try: sys.stdout.flush() except: pass os._exit(result_code) try: cid, result_code = os.waitpid(child_id, 0) module_name = test_name.split()[-1] # os.waitpid returns the child's result code in the # upper byte of result_code, and the signal it was # killed by in the lower byte if result_code & 255: raise Exception( "Tests in module '%s' were unexpectedly killed by signal %d, see test output for details." % ( module_name, result_code & 255)) result_code >>= 8 if result_code in (0,1): try: with open(result_file, 'rb') as f: PartialTestResult.join_results(result, pickle.load(f)) except Exception: raise Exception( "Failed to load test result from test in module '%s' after exit status %d," " see test output for details." % (module_name, result_code)) if result_code: raise Exception( "Tests in module '%s' exited with status %d, see test output for details." % ( module_name, result_code)) finally: try: os.unlink(result_file) except: pass class PureDoctestTestCase(unittest.TestCase): def __init__(self, module_name, module_path, tags, stats=None, shard_num=0): self.tags = tags self.module_name = self.name = module_name self.module_path = module_path self.stats = stats self.shard_num = shard_num unittest.TestCase.__init__(self, 'run') def shortDescription(self): return "[%d] running pure doctests in %s" % ( self.shard_num, self.module_name) def run(self, result=None): if result is None: result = self.defaultTestResult() loaded_module_name = 'pure_doctest__' + self.module_name result.startTest(self) try: self.setUp() with self.stats.time(self.name, 'py', 'pyimport'): if sys.version_info >= (3, 5): m = import_module_from_file(self.module_name, self.module_path) else: import imp m = imp.load_source(loaded_module_name, self.module_path) try: with self.stats.time(self.name, 'py', 'pyrun'): doctest.DocTestSuite(m).run(result) finally: del m if loaded_module_name in sys.modules: del sys.modules[loaded_module_name] check_thread_termination() except Exception: result.addError(self, sys.exc_info()) result.stopTest(self) try: self.tearDown() except Exception: pass if 'mypy' in self.tags['tag']: try: from mypy import api as mypy_api except ImportError: pass else: with self.stats.time(self.name, 'py', 'mypy'): mypy_result = mypy_api.run([ self.module_path, '--ignore-missing-imports', '--follow-imports', 'skip', ]) if mypy_result[2]: self.fail(mypy_result[0]) is_private_field = re.compile('^_[^_]').match class _FakeClass(object): def __init__(self, **kwargs): self._shortDescription = kwargs.get('module_name') self.__dict__.update(kwargs) def shortDescription(self): return self._shortDescription from unittest import TextTestResult class PartialTestResult(TextTestResult): def __init__(self, base_result): TextTestResult.__init__( self, self._StringIO(), True, base_result.dots + base_result.showAll*2) def strip_error_results(self, results): for test_case, error in results: for attr_name in filter(is_private_field, dir(test_case)): if attr_name == '_dt_test': test_case._dt_test = _FakeClass( name=test_case._dt_test.name) elif attr_name != '_shortDescription': setattr(test_case, attr_name, None) def data(self): self.strip_error_results(self.failures) self.strip_error_results(self.errors) return (self.failures, self.errors, self.skipped, self.testsRun, self.stream.getvalue()) def join_results(result, data): """Static method for merging the result back into the main result object. """ failures, errors, skipped, tests_run, output = data if output: result.stream.write(output) result.errors.extend(errors) result.skipped.extend(skipped) result.failures.extend(failures) result.testsRun += tests_run join_results = staticmethod(join_results) class _StringIO(StringIO): def writeln(self, line): self.write("%s\n" % line) class CythonUnitTestCase(CythonRunTestCase): def shortDescription(self): return "[%d] compiling (%s) tests in %s" % ( self.shard_num, self.language, self.description_name()) def run_tests(self, result, ext_so_path): with self.stats.time(self.name, self.language, 'import'): module = import_ext(self.module, ext_so_path) tests = unittest.defaultTestLoader.loadTestsFromModule(module) if self.test_selector: filter_test_suite(tests, self.test_selector) with self.stats.time(self.name, self.language, 'run'): tests.run(result) class CythonPyregrTestCase(CythonRunTestCase): def setUp(self): CythonRunTestCase.setUp(self) from Cython.Compiler import Options Options.error_on_unknown_names = False Options.error_on_uninitialized = False Options._directive_defaults.update(dict( binding=True, always_allow_keywords=True, set_initial_path="SOURCEFILE")) patch_inspect_isfunction() def related_files(self, test_directory, module_name): return _list_pyregr_data_files(test_directory) def _run_unittest(self, result, *classes): """Run tests from unittest.TestCase-derived classes.""" valid_types = (unittest.TestSuite, unittest.TestCase) suite = unittest.TestSuite() load_tests = unittest.TestLoader().loadTestsFromTestCase for cls in classes: if isinstance(cls, str): if cls in sys.modules: suite.addTest(unittest.findTestCases(sys.modules[cls])) else: raise ValueError("str arguments must be keys in sys.modules") elif isinstance(cls, valid_types): suite.addTest(cls) else: suite.addTest(load_tests(cls)) with self.stats.time(self.name, self.language, 'run'): suite.run(result) def _run_doctest(self, result, module): self.run_doctests(module, result, None) def run_tests(self, result, ext_so_path): try: from test import support except ImportError: # Python2.x from test import test_support as support def run_test(result): def run_unittest(*classes): return self._run_unittest(result, *classes) def run_doctest(module, verbosity=None): return self._run_doctest(result, module) backup = (support.run_unittest, support.run_doctest) support.run_unittest = run_unittest support.run_doctest = run_doctest try: try: sys.stdout.flush() # helps in case of crashes with self.stats.time(self.name, self.language, 'import'): module = import_ext(self.module, ext_so_path) sys.stdout.flush() # helps in case of crashes if hasattr(module, 'test_main'): # help 'doctest.DocFileTest' find the module path through frame inspection fake_caller_module_globals = { 'module': module, '__name__': module.__name__, } call_tests = eval( 'lambda: module.test_main()', fake_caller_module_globals, fake_caller_module_globals) call_tests() sys.stdout.flush() # helps in case of crashes except (unittest.SkipTest, support.ResourceDenied): result.addSkip(self, 'ok') finally: support.run_unittest, support.run_doctest = backup run_forked_test(result, run_test, self.shortDescription(), self.fork) class TestCodeFormat(unittest.TestCase): def __init__(self, cython_dir): self.cython_dir = cython_dir unittest.TestCase.__init__(self) def runTest(self): source_dirs = ['Cython', 'Demos', 'docs', 'pyximport', 'tests'] import pycodestyle config_file = os.path.join(self.cython_dir, "setup.cfg") if not os.path.exists(config_file): config_file = os.path.join(os.path.dirname(__file__), "setup.cfg") total_errors = 0 # checks for .py files paths = [] for codedir in source_dirs: paths += glob.glob(os.path.join(self.cython_dir, codedir + "/**/*.py"), recursive=True) style = pycodestyle.StyleGuide(config_file=config_file) print("") # Fix the first line of the report. result = style.check_files(paths) total_errors += result.total_errors # checks for non-Python source files paths = [] for codedir in ['Cython', 'Demos', 'pyximport']: # source_dirs: paths += glob.glob(os.path.join(self.cython_dir, codedir + "/**/*.p[yx][xdi]"), recursive=True) style = pycodestyle.StyleGuide(config_file=config_file, select=[ # whitespace "W1", "W2", "W3", # indentation "E101", "E111", ]) print("") # Fix the first line of the report. result = style.check_files(paths) total_errors += result.total_errors """ # checks for non-Python test files paths = [] for codedir in ['tests']: paths += glob.glob(os.path.join(self.cython_dir, codedir + "/**/*.p[yx][xdi]"), recursive=True) style = pycodestyle.StyleGuide(select=[ # whitespace "W1", "W2", "W3", ]) result = style.check_files(paths) total_errors += result.total_errors """ self.assertEqual(total_errors, 0, "Found code style errors.") include_debugger = IS_CPYTHON def collect_unittests(path, module_prefix, suite, selectors, exclude_selectors): def file_matches(filename): return filename.startswith("Test") and filename.endswith(".py") def package_matches(dirname): return dirname == "Tests" loader = unittest.TestLoader() if include_debugger: skipped_dirs = [] else: skipped_dirs = ['Cython' + os.path.sep + 'Debugger' + os.path.sep] for dirpath, dirnames, filenames in os.walk(path): if dirpath != path and "__init__.py" not in filenames: skipped_dirs.append(dirpath + os.path.sep) continue skip = False for dir in skipped_dirs: if dirpath.startswith(dir): skip = True if skip: continue parentname = os.path.split(dirpath)[-1] if package_matches(parentname): for f in filenames: if file_matches(f): filepath = os.path.join(dirpath, f)[:-len(".py")] modulename = module_prefix + filepath[len(path)+1:].replace(os.path.sep, '.') if not any(1 for match in selectors if match(modulename)): continue if any(1 for match in exclude_selectors if match(modulename)): continue module = __import__(modulename) for x in modulename.split('.')[1:]: module = getattr(module, x) suite.addTests([loader.loadTestsFromModule(module)]) def collect_doctests(path, module_prefix, suite, selectors, exclude_selectors): def package_matches(dirname): if dirname == 'Debugger' and not include_debugger: return False return dirname not in ("Mac", "Distutils", "Plex", "Tempita") def file_matches(filename): filename, ext = os.path.splitext(filename) excludelist = ['libcython', 'libpython', 'test_libcython_in_gdb', 'TestLibCython'] return (ext == '.py' and not '~' in filename and not '#' in filename and not filename.startswith('.') and not filename in excludelist) import doctest for dirpath, dirnames, filenames in os.walk(path): for dir in list(dirnames): if not package_matches(dir): dirnames.remove(dir) for f in filenames: if file_matches(f): if not f.endswith('.py'): continue filepath = os.path.join(dirpath, f) if os.path.getsize(filepath) == 0: continue filepath = filepath[:-len(".py")] modulename = module_prefix + filepath[len(path)+1:].replace(os.path.sep, '.') if not [ 1 for match in selectors if match(modulename) ]: continue if [ 1 for match in exclude_selectors if match(modulename) ]: continue if 'in_gdb' in modulename: # These should only be imported from gdb. continue module = __import__(modulename) for x in modulename.split('.')[1:]: module = getattr(module, x) if hasattr(module, "__doc__") or hasattr(module, "__test__"): try: suite.addTest(doctest.DocTestSuite(module)) except ValueError: # no tests pass class EndToEndTest(unittest.TestCase): """ This is a test of build/*.srctree files, where srctree defines a full directory structure and its header gives a list of commands to run. """ cython_root = os.path.dirname(os.path.abspath(__file__)) def __init__(self, treefile, workdir, cleanup_workdir=True, stats=None, capture=True, shard_num=0): self.name = os.path.splitext(os.path.basename(treefile))[0] self.treefile = treefile self.workdir = os.path.join(workdir, self.name) self.cleanup_workdir = cleanup_workdir self.stats = stats self.capture = capture self.shard_num = shard_num cython_syspath = [self.cython_root] for path in sys.path: if path.startswith(self.cython_root) and path not in cython_syspath: # Py3 installation and refnanny build prepend their # fixed paths to sys.path => prefer that over the # generic one (cython_root itself goes last) cython_syspath.append(path) self.cython_syspath = os.pathsep.join(cython_syspath[::-1]) unittest.TestCase.__init__(self) def shortDescription(self): return "[%d] End-to-end %s" % ( self.shard_num, self.name) def setUp(self): from Cython.TestUtils import unpack_source_tree _, self.commands = unpack_source_tree(self.treefile, self.workdir, self.cython_root) self.old_dir = os.getcwd() os.chdir(self.workdir) def tearDown(self): if self.cleanup_workdir: for trial in range(5): try: shutil.rmtree(self.workdir) except OSError: time.sleep(0.1) else: break os.chdir(self.old_dir) def _try_decode(self, content): if not isinstance(content, bytes): return content try: return content.decode() except UnicodeDecodeError: return content.decode('iso-8859-1') def runTest(self): self.success = False old_path = os.environ.get('PYTHONPATH') env = dict(os.environ) new_path = self.cython_syspath if old_path: new_path = new_path + os.pathsep + self.workdir + os.pathsep + old_path env['PYTHONPATH'] = new_path if not env.get("PYTHONIOENCODING"): env["PYTHONIOENCODING"] = sys.stdout.encoding or sys.getdefaultencoding() cmd = [] out = [] err = [] for command_no, command in enumerate(self.commands, 1): with self.stats.time('%s(%d)' % (self.name, command_no), 'c', 'etoe-build' if 'setup.py' in command else 'etoe-run'): if self.capture: p = subprocess.Popen(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE, env=env) _out, _err = p.communicate() res = p.returncode else: p = subprocess.call(command, env=env) _out, _err = b'', b'' res = p cmd.append(command) out.append(_out) err.append(_err) if res == 0 and b'REFNANNY: ' in _out: res = -1 if res != 0: for c, o, e in zip(cmd, out, err): sys.stderr.write("[%d] %s\n%s\n%s\n\n" % ( self.shard_num, c, self._try_decode(o), self._try_decode(e))) sys.stderr.write("Final directory layout of '%s':\n%s\n\n" % ( self.name, '\n'.join(os.path.join(dirpath, filename) for dirpath, dirs, files in os.walk(".") for filename in files), )) self.assertEqual(0, res, "non-zero exit status, last output was:\n%r\n-- stdout:%s\n-- stderr:%s\n" % ( ' '.join(command), self._try_decode(out[-1]), self._try_decode(err[-1]))) self.success = True # TODO: Support cython_freeze needed here as well. # TODO: Windows support. class EmbedTest(unittest.TestCase): working_dir = "Demos/embed" def setUp(self): self.old_dir = os.getcwd() os.chdir(self.working_dir) os.system( "make PYTHON='%s' clean > /dev/null" % sys.executable) def tearDown(self): try: os.system( "make PYTHON='%s' clean > /dev/null" % sys.executable) except: pass os.chdir(self.old_dir) def test_embed(self): libname = sysconfig.get_config_var('LIBRARY') libdir = sysconfig.get_config_var('LIBDIR') if not os.path.isdir(libdir) or libname not in os.listdir(libdir): libdir = os.path.join(os.path.dirname(sys.executable), '..', 'lib') if not os.path.isdir(libdir) or libname not in os.listdir(libdir): libdir = os.path.join(libdir, 'python%d.%d' % sys.version_info[:2], 'config') if not os.path.isdir(libdir) or libname not in os.listdir(libdir): # report the error for the original directory libdir = sysconfig.get_config_var('LIBDIR') cython = os.path.abspath(os.path.join('..', '..', 'cython.py')) try: subprocess.check_output([ "make", "PYTHON='%s'" % sys.executable, "CYTHON='%s'" % cython, "LIBDIR1='%s'" % libdir, "paths", "test", ], stderr=subprocess.STDOUT, ) except subprocess.CalledProcessError as err: if err.output: self.fail("EmbedTest failed: " + err.output.decode().strip()) raise self.assertTrue(True) # :) def load_listfile(filename): # just reuse the FileListExclude implementation return list(FileListExcluder(filename)) class MissingDependencyExcluder(object): def __init__(self, deps): # deps: { matcher func : module name } self.exclude_matchers = [] for matcher, module_name in deps.items(): try: module = __import__(module_name) except ImportError: self.exclude_matchers.append(string_selector(matcher)) print("Test dependency not found: '%s'" % module_name) else: version = self.find_dep_version(module_name, module) print("Test dependency found: '%s' version %s" % (module_name, version)) self.tests_missing_deps = [] def find_dep_version(self, name, module): try: version = module.__version__ except AttributeError: stdlib_dir = os.path.dirname(shutil.__file__) + os.sep module_path = getattr(module, '__file__', stdlib_dir) # no __file__? => builtin stdlib module # GraalPython seems to return None for some unknown reason if module_path and module_path.startswith(stdlib_dir): # stdlib module version = sys.version.partition(' ')[0] elif '.' in name: # incrementally look for a parent package with version name = name.rpartition('.')[0] return self.find_dep_version(name, __import__(name)) else: version = '?.?' return version def __call__(self, testname, tags=None): for matcher in self.exclude_matchers: if matcher(testname, tags): self.tests_missing_deps.append(testname) return True return False class VersionDependencyExcluder(object): def __init__(self, deps): # deps: { version : matcher func } from sys import version_info self.exclude_matchers = [] for ver, (compare, matcher) in deps.items(): if compare(version_info, ver): self.exclude_matchers.append(matcher) self.tests_missing_deps = [] def __call__(self, testname, tags=None): for matcher in self.exclude_matchers: if matcher(testname): self.tests_missing_deps.append(testname) return True return False class FileListExcluder(object): def __init__(self, list_file, verbose=False): self.verbose = verbose self.excludes = {} self._list_file = os.path.relpath(list_file) with open(list_file) as f: for line in f: line = line.strip() if line and line[0] != '#': self.excludes[line.split()[0]] = True def __call__(self, testname, tags=None): exclude = any(string_selector(ex)(testname) for ex in self.excludes) if exclude and self.verbose: print("Excluding %s because it's listed in %s" % (testname, self._list_file)) return exclude class TagsSelector(object): def __init__(self, tag, value): self.tag = tag self.value = value def __call__(self, testname, tags=None): if tags is None: return False else: return self.value in tags[self.tag] class RegExSelector(object): def __init__(self, pattern_string): try: self.regex_matches = re.compile(pattern_string, re.I|re.U).search except re.error: print('Invalid pattern: %r' % pattern_string) raise def __call__(self, testname, tags=None): return self.regex_matches(testname) def string_selector(s): if ':' in s: return TagsSelector(*s.split(':', 1)) else: return RegExSelector(s) class ShardExcludeSelector(object): # This is an exclude selector so it can override the (include) selectors. # It may not provide uniform distribution (in time or count), but is a # determanistic partition of the tests which is important. # Random seed to improve the hash distribution. _seed = base64.b64decode(b'2ged1EtsGz/GkisJr22UcLeP6n9XIaA5Vby2wM49Wvg=') def __init__(self, shard_num, shard_count): self.shard_num = shard_num self.shard_count = shard_count def __call__(self, testname, tags=None, _hash=zlib.crc32, _is_py2=IS_PY2): # Cannot use simple hash() here as shard processes might use different hash seeds. # CRC32 is fast and simple, but might return negative values in Py2. hashval = _hash(self._seed + testname) & 0x7fffffff if _is_py2 else _hash(self._seed + testname.encode()) return hashval % self.shard_count != self.shard_num class PendingThreadsError(RuntimeError): pass threads_seen = [] def check_thread_termination(ignore_seen=True): if threading is None: # no threading enabled in CPython return current = threading.current_thread() blocking_threads = [] for t in threading.enumerate(): if not t.is_alive() or t == current or t.name == 'time_stamper': continue t.join(timeout=2) if t.is_alive(): if not ignore_seen: blocking_threads.append(t) continue for seen in threads_seen: if t is seen: break else: threads_seen.append(t) blocking_threads.append(t) if not blocking_threads: return sys.stderr.write("warning: left-over threads found after running test:\n") for t in blocking_threads: sys.stderr.write('...%s\n' % repr(t)) raise PendingThreadsError("left-over threads found after running test") def subprocess_output(cmd): try: p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) return p.communicate()[0].decode('UTF-8') except OSError: return '' def get_version(): from Cython.Compiler.Version import version as cython_version full_version = cython_version top = os.path.dirname(os.path.abspath(__file__)) if os.path.exists(os.path.join(top, '.git')): old_dir = os.getcwd() try: os.chdir(top) head_commit = subprocess_output(['git', 'rev-parse', 'HEAD']).strip() version_commit = subprocess_output(['git', 'rev-parse', cython_version]).strip() diff = subprocess_output(['git', 'diff', '--stat']).strip() if head_commit != version_commit: full_version += " " + head_commit if diff: full_version += ' + uncommitted changes' finally: os.chdir(old_dir) return full_version _orig_stdout, _orig_stderr = sys.stdout, sys.stderr def flush_and_terminate(status): try: _orig_stdout.flush() _orig_stderr.flush() finally: os._exit(status) def main(): global DISTDIR, WITH_CYTHON # Set an environment variable to the top directory os.environ['CYTHON_PROJECT_DIR'] = os.path.abspath(os.path.dirname(__file__)) DISTDIR = os.path.join(os.getcwd(), os.path.dirname(sys.argv[0])) from Cython.Compiler import DebugFlags args = [] for arg in sys.argv[1:]: if arg.startswith('--debug') and arg[2:].replace('-', '_') in dir(DebugFlags): setattr(DebugFlags, arg[2:].replace('-', '_'), True) else: args.append(arg) from optparse import OptionParser parser = OptionParser(usage="usage: %prog [options] [selector ...]") parser.add_option("--no-cleanup", dest="cleanup_workdir", action="store_false", default=True, help="do not delete the generated C files (allows passing --no-cython on next run)") parser.add_option("--no-cleanup-sharedlibs", dest="cleanup_sharedlibs", action="store_false", default=True, help="do not delete the generated shared library files (allows manual module experimentation)") parser.add_option("--no-cleanup-failures", dest="cleanup_failures", action="store_false", default=True, help="enable --no-cleanup and --no-cleanup-sharedlibs for failed tests only") parser.add_option("--no-cython", dest="with_cython", action="store_false", default=True, help="do not run the Cython compiler, only the C compiler") parser.add_option("--compiler", dest="compiler", default=None, help="C compiler type") backend_list = ','.join(BACKENDS) parser.add_option("--backends", dest="backends", default=backend_list, help="select backends to test (default: %s)" % backend_list) parser.add_option("--no-c", dest="use_c", action="store_false", default=True, help="do not test C compilation backend") parser.add_option("--no-cpp", dest="use_cpp", action="store_false", default=True, help="do not test C++ compilation backend") parser.add_option("--no-cpp-locals", dest="use_cpp_locals", action="store_false", default=True, help="do not rerun select C++ tests with cpp_locals directive") parser.add_option("--no-unit", dest="unittests", action="store_false", default=True, help="do not run the unit tests") parser.add_option("--no-doctest", dest="doctests", action="store_false", default=True, help="do not run the doctests") parser.add_option("--no-file", dest="filetests", action="store_false", default=True, help="do not run the file based tests") parser.add_option("--no-pyregr", dest="pyregr", action="store_false", default=True, help="do not run the regression tests of CPython in tests/pyregr/") parser.add_option("--no-examples", dest="examples", action="store_false", default=True, help="Do not run the documentation tests in the examples directory.") parser.add_option("--no-code-style", dest="code_style", action="store_false", default=True, help="Do not run the code style (PEP8) checks.") parser.add_option("--cython-only", dest="cython_only", action="store_true", default=False, help="only compile pyx to c, do not run C compiler or run the tests") parser.add_option("--no-refnanny", dest="with_refnanny", action="store_false", default=True, help="do not regression test reference counting") parser.add_option("--no-fork", dest="fork", action="store_false", default=True, help="do not fork to run tests") parser.add_option("--sys-pyregr", dest="system_pyregr", action="store_true", default=False, help="run the regression tests of the CPython installation") parser.add_option("-x", "--exclude", dest="exclude", action="append", metavar="PATTERN", help="exclude tests matching the PATTERN") parser.add_option("--listfile", dest="listfile", action="append", help="specify a file containing a list of tests to run") parser.add_option("-j", "--shard_count", dest="shard_count", metavar="N", type=int, default=1, help="shard this run into several parallel runs") parser.add_option("--shard_num", dest="shard_num", metavar="K", type=int, default=-1, help="test only this single shard") parser.add_option("--profile", dest="profile", action="store_true", default=False, help="enable profiling of the tests") parser.add_option("-C", "--coverage", dest="coverage", action="store_true", default=False, help="collect source coverage data for the Compiler") parser.add_option("--coverage-xml", dest="coverage_xml", action="store_true", default=False, help="collect source coverage data for the Compiler in XML format") parser.add_option("--coverage-html", dest="coverage_html", action="store_true", default=False, help="collect source coverage data for the Compiler in HTML format") parser.add_option("-A", "--annotate", dest="annotate_source", action="store_true", default=True, help="generate annotated HTML versions of the test source files") parser.add_option("--no-annotate", dest="annotate_source", action="store_false", help="do not generate annotated HTML versions of the test source files") parser.add_option("-v", "--verbose", dest="verbosity", action="count", default=0, help="display test progress, pass twice to print test names") parser.add_option("-T", "--ticket", dest="tickets", action="append", help="a bug ticket number to run the respective test in 'tests/*'") parser.add_option("-k", dest="only_pattern", help="a regex pattern for selecting doctests and test functions in the test modules") parser.add_option("-3", dest="language_level", action="store_const", const=3, default=2, help="set language level to Python 3 (useful for running the CPython regression tests)'") parser.add_option("--xml-output", dest="xml_output_dir", metavar="DIR", help="write test results in XML to directory DIR") parser.add_option("--exit-ok", dest="exit_ok", default=False, action="store_true", help="exit without error code even on test failures") parser.add_option("--failfast", dest="failfast", default=False, action="store_true", help="stop on first failure or error") parser.add_option("--root-dir", dest="root_dir", default=os.path.join(DISTDIR, 'tests'), help=("Directory to look for the file based " "tests (the ones which are deactivated with '--no-file'.")) parser.add_option("--examples-dir", dest="examples_dir", default=os.path.join(DISTDIR, 'docs', 'examples'), help="Directory to look for documentation example tests") parser.add_option("--work-dir", dest="work_dir", default=os.path.join(os.getcwd(), 'TEST_TMP'), help="working directory") parser.add_option("--cython-dir", dest="cython_dir", default=os.getcwd(), help="Cython installation directory (default: use local source version)") parser.add_option("--debug", dest="for_debugging", default=False, action="store_true", help="configure for easier use with a debugger (e.g. gdb)") parser.add_option("--pyximport-py", dest="pyximport_py", default=False, action="store_true", help="use pyximport to automatically compile imported .pyx and .py files") parser.add_option("--watermark", dest="watermark", default=None, help="deterministic generated by string") parser.add_option("--use_common_utility_dir", default=False, action="store_true") parser.add_option("--use_formal_grammar", default=False, action="store_true") parser.add_option("--test_determinism", default=False, action="store_true", help="test whether Cython's output is deterministic") parser.add_option("--pythran-dir", dest="pythran_dir", default=None, help="specify Pythran include directory. This will run the C++ tests using Pythran backend for Numpy") parser.add_option("--no-capture", dest="capture", default=True, action="store_false", help="do not capture stdout, stderr in srctree tests. Makes pdb.set_trace interactive") parser.add_option("--limited-api", dest="limited_api", default=False, action="store_true", help="Compiles Cython using CPython's LIMITED_API") options, cmd_args = parser.parse_args(args) if options.with_cython and sys.version_info[0] >= 3: sys.path.insert(0, options.cython_dir) # requires glob with the wildcard. if sys.version_info < (3, 5) or cmd_args: options.code_style = False WITH_CYTHON = options.with_cython coverage = None if options.coverage or options.coverage_xml or options.coverage_html: if not WITH_CYTHON: options.coverage = options.coverage_xml = options.coverage_html = False elif options.shard_num == -1: print("Enabling coverage analysis") from coverage import coverage as _coverage coverage = _coverage(branch=True) coverage.erase() coverage.start() if options.xml_output_dir: shutil.rmtree(options.xml_output_dir, ignore_errors=True) if options.listfile: for listfile in options.listfile: cmd_args.extend(load_listfile(listfile)) if options.capture and not options.for_debugging: keep_alive_interval = 10 else: keep_alive_interval = None if options.shard_count > 1 and options.shard_num == -1: if "PYTHONIOENCODING" not in os.environ: # Make sure subprocesses can print() Unicode text. os.environ["PYTHONIOENCODING"] = sys.stdout.encoding or sys.getdefaultencoding() import multiprocessing pool = multiprocessing.Pool(options.shard_count) tasks = [(options, cmd_args, shard_num) for shard_num in range(options.shard_count)] error_shards = [] failure_outputs = [] # NOTE: create process pool before time stamper thread to avoid forking issues. total_time = time.time() stats = Stats() merged_pipeline_stats = defaultdict(lambda: (0, 0)) with time_stamper_thread(interval=keep_alive_interval): for shard_num, shard_stats, pipeline_stats, return_code, failure_output in pool.imap_unordered(runtests_callback, tasks): if return_code != 0: error_shards.append(shard_num) failure_outputs.append(failure_output) sys.stderr.write("FAILED (%s/%s)\n" % (shard_num, options.shard_count)) sys.stderr.write("ALL DONE (%s/%s)\n" % (shard_num, options.shard_count)) stats.update(shard_stats) for stage_name, (stage_time, stage_count) in pipeline_stats.items(): old_time, old_count = merged_pipeline_stats[stage_name] merged_pipeline_stats[stage_name] = (old_time + stage_time, old_count + stage_count) pool.close() pool.join() total_time = time.time() - total_time sys.stderr.write("Sharded tests run in %d seconds (%.1f minutes)\n" % (round(total_time), total_time / 60.)) if error_shards: sys.stderr.write("Errors found in shards %s\n" % ", ".join([str(e) for e in error_shards])) for failure_output in zip(error_shards, failure_outputs): sys.stderr.write("\nErrors from shard %s:\n%s" % failure_output) return_code = 1 else: return_code = 0 else: with time_stamper_thread(interval=keep_alive_interval): _, stats, merged_pipeline_stats, return_code, _ = runtests(options, cmd_args, coverage) if coverage: if options.shard_count > 1 and options.shard_num == -1: coverage.combine() coverage.stop() def as_msecs(t, unit=1000000): # pipeline times are in msecs return t // unit + float(t % unit) / unit pipeline_stats = [ (as_msecs(stage_time), as_msecs(stage_time) / stage_count, stage_count, stage_name) for stage_name, (stage_time, stage_count) in merged_pipeline_stats.items() ] total_pipeline_time_percent = math.fsum(stats[0] for stats in pipeline_stats) / 100.0 pipeline_stats.sort(reverse=True) sys.stderr.write("Most expensive pipeline stages: %s\n" % ", ".join( "%r: %.2f / %d (%.3f / run, %.1f%%)" % ( stage_name, total_stage_time, stage_count, stage_time, total_stage_time / total_pipeline_time_percent) for total_stage_time, stage_time, stage_count, stage_name in pipeline_stats[:10] )) stats.print_stats(sys.stderr) if coverage: save_coverage(coverage, options) sys.stderr.write("ALL DONE\n") sys.stderr.flush() try: check_thread_termination(ignore_seen=False) except PendingThreadsError: # normal program exit won't kill the threads, do it the hard way here flush_and_terminate(return_code) else: sys.exit(return_code) @contextmanager def time_stamper_thread(interval=10): """ Print regular time stamps into the build logs to find slow tests. @param interval: time interval in seconds """ if not interval or interval < 0: # Do nothing yield return try: _xrange = xrange except NameError: _xrange = range import threading import datetime from time import sleep interval = _xrange(interval * 4) now = datetime.datetime.now stop = False # We capture stderr in some places. # => make sure we write to the real (original) stderr of the test runner. stderr = os.dup(2) def write(s): os.write(stderr, s if type(s) is bytes else s.encode('ascii')) def time_stamper(): while True: for _ in interval: if stop: return sleep(1./4) write('\n#### %s\n' % now()) thread = threading.Thread(target=time_stamper, name='time_stamper') thread.daemon = True thread.start() try: yield finally: stop = True thread.join() os.close(stderr) def configure_cython(options): global CompilationOptions, pyrex_default_options, cython_compile from Cython.Compiler.Options import \ CompilationOptions, \ default_options as pyrex_default_options from Cython.Compiler.Options import _directive_defaults as directive_defaults from Cython.Compiler import Errors Errors.LEVEL = 0 # show all warnings from Cython.Compiler import Options Options.generate_cleanup_code = 3 # complete cleanup code from Cython.Compiler import DebugFlags DebugFlags.debug_temp_code_comments = 1 DebugFlags.debug_no_exception_intercept = 1 # provide better crash output in CI runs pyrex_default_options['formal_grammar'] = options.use_formal_grammar if options.profile: directive_defaults['profile'] = True if options.watermark: import Cython.Compiler.Version Cython.Compiler.Version.watermark = options.watermark def save_coverage(coverage, options): if options.coverage: coverage.report(show_missing=0) if options.coverage_xml: coverage.xml_report(outfile="coverage-report.xml") if options.coverage_html: coverage.html_report(directory="coverage-report-html") def runtests_callback(args): options, cmd_args, shard_num = args options.shard_num = shard_num return runtests(options, cmd_args) def runtests(options, cmd_args, coverage=None): # faulthandler should be able to provide a limited traceback # in the event of a segmentation fault. Only available on Python 3.3+ try: import faulthandler except ImportError: pass # OK - not essential else: faulthandler.enable() if sys.platform == "win32" and sys.version_info < (3, 6): # enable Unicode console output, if possible try: import win_unicode_console except ImportError: pass else: win_unicode_console.enable() WITH_CYTHON = options.with_cython ROOTDIR = os.path.abspath(options.root_dir) WORKDIR = os.path.abspath(options.work_dir) if WITH_CYTHON: configure_cython(options) xml_output_dir = options.xml_output_dir if options.shard_num > -1: WORKDIR = os.path.join(WORKDIR, str(options.shard_num)) if xml_output_dir: xml_output_dir = os.path.join(xml_output_dir, 'shard-%03d' % options.shard_num) # RUN ALL TESTS! UNITTEST_MODULE = "Cython" UNITTEST_ROOT = os.path.join(os.path.dirname(__file__), UNITTEST_MODULE) if WITH_CYTHON: if os.path.exists(WORKDIR): for path in os.listdir(WORKDIR): if path in ("support", "Cy3"): continue shutil.rmtree(os.path.join(WORKDIR, path), ignore_errors=True) if not os.path.exists(WORKDIR): os.makedirs(WORKDIR) if options.shard_num <= 0: sys.stderr.write("Python %s\n" % sys.version) sys.stderr.write("\n") if WITH_CYTHON: sys.stderr.write("Running tests against Cython %s\n" % get_version()) else: sys.stderr.write("Running tests without Cython.\n") if options.for_debugging: options.cleanup_workdir = False options.cleanup_sharedlibs = False options.fork = False if WITH_CYTHON and include_debugger: from Cython.Compiler.Options import default_options as compiler_default_options compiler_default_options['gdb_debug'] = True compiler_default_options['output_dir'] = os.getcwd() if IS_PYPY: if options.with_refnanny: sys.stderr.write("Disabling refnanny in PyPy\n") options.with_refnanny = False if options.with_refnanny: from pyximport.pyxbuild import pyx_to_dll libpath = pyx_to_dll(os.path.join("Cython", "Runtime", "refnanny.pyx"), build_in_temp=True, pyxbuild_dir=os.path.join(WORKDIR, "support")) sys.path.insert(0, os.path.split(libpath)[0]) CDEFS.append(('CYTHON_REFNANNY', '1')) if options.limited_api: global limited_api_full_tests CDEFS.append(('CYTHON_LIMITED_API', '1')) CFLAGS.append('-Wno-unused-function') # limited_api_full_tests is not actually "excludes" but just reusing the mechanism. # These files will be run with Py_LIMITED_API defined limited_api_full_tests = FileListExcluder( os.path.join(ROOTDIR, "test_in_limited_api.txt")) if xml_output_dir and options.fork: # doesn't currently work together sys.stderr.write("Disabling forked testing to support XML test output\n") options.fork = False if WITH_CYTHON: sys.stderr.write("Using Cython language level %d.\n" % options.language_level) test_bugs = False if options.tickets: for ticket_number in options.tickets: test_bugs = True cmd_args.append('ticket:%s' % ticket_number) if not test_bugs: for selector in cmd_args: if selector.startswith('bugs'): test_bugs = True selectors = [ string_selector(r) for r in cmd_args ] verbose_excludes = selectors or options.verbosity >= 2 if not selectors: selectors = [ lambda x, tags=None: True ] # Check which external modules are not present and exclude tests # which depends on them (by prefix) missing_dep_excluder = MissingDependencyExcluder(EXT_DEP_MODULES) version_dep_excluder = VersionDependencyExcluder(VER_DEP_MODULES) exclude_selectors = [missing_dep_excluder, version_dep_excluder] # want to print msg at exit try: import IPython.core.release if list(IPython.core.release._ver) < [1, 0, 0]: raise ImportError except (ImportError, AttributeError, TypeError): exclude_selectors.append(RegExSelector('IPython')) try: raise ImportError("Jedi typer is currently broken, see GH#1845") import jedi if not ([0, 9] <= list(map(int, re.findall('[0-9]+', jedi.__version__ or '0')))): raise ImportError except (ImportError, AttributeError, TypeError): exclude_selectors.append(RegExSelector('Jedi')) if options.exclude: exclude_selectors += [ string_selector(r) for r in options.exclude ] if not COMPILER_HAS_INT128: exclude_selectors += [RegExSelector('int128')] if options.shard_num > -1: exclude_selectors.append(ShardExcludeSelector(options.shard_num, options.shard_count)) if not test_bugs: bug_files = [ ('bugs.txt', True), ('pypy_bugs.txt', IS_PYPY), ('pypy2_bugs.txt', IS_PYPY and IS_PY2), ('pypy_crash_bugs.txt', IS_PYPY), ('pypy_implementation_detail_bugs.txt', IS_PYPY), ('graal_bugs.txt', IS_GRAAL), ('limited_api_bugs.txt', options.limited_api), ('windows_bugs.txt', sys.platform == 'win32'), ('cygwin_bugs.txt', sys.platform == 'cygwin'), ('windows_bugs_39.txt', sys.platform == 'win32' and sys.version_info[:2] == (3, 9)) ] exclude_selectors += [ FileListExcluder(os.path.join(ROOTDIR, bugs_file_name), verbose=verbose_excludes) for bugs_file_name, condition in bug_files if condition ] global COMPILER if options.compiler: COMPILER = options.compiler selected_backends = [ name.strip() for name in options.backends.split(',') if name.strip() ] backends = [] for backend in selected_backends: if backend == 'c' and not options.use_c: continue elif backend == 'cpp' and not options.use_cpp: continue elif backend not in BACKENDS: sys.stderr.write("Unknown backend requested: '%s' not one of [%s]\n" % ( backend, ','.join(BACKENDS))) sys.exit(1) backends.append(backend) if options.shard_num <= 0: sys.stderr.write("Backends: %s\n" % ','.join(backends)) languages = backends if 'CI' in os.environ and sys.platform == 'darwin' and 'cpp' in languages: bugs_file_name = 'macos_cpp_bugs.txt' exclude_selectors += [ FileListExcluder(os.path.join(ROOTDIR, bugs_file_name), verbose=verbose_excludes) ] if options.use_common_utility_dir: common_utility_dir = os.path.join(WORKDIR, 'utility_code') if not os.path.exists(common_utility_dir): os.makedirs(common_utility_dir) else: common_utility_dir = None sys.stderr.write("\n") test_suite = unittest.TestSuite() stats = Stats() if options.unittests: collect_unittests(UNITTEST_ROOT, UNITTEST_MODULE + ".", test_suite, selectors, exclude_selectors) if options.doctests: collect_doctests(UNITTEST_ROOT, UNITTEST_MODULE + ".", test_suite, selectors, exclude_selectors) if options.filetests and languages: filetests = TestBuilder(ROOTDIR, WORKDIR, selectors, exclude_selectors, options, options.pyregr, languages, test_bugs, options.language_level, common_utility_dir, options.pythran_dir, add_embedded_test=True, stats=stats, add_cpp_locals_extra_tests=options.use_cpp_locals) test_suite.addTest(filetests.build_suite()) if options.examples and languages: examples_workdir = os.path.join(WORKDIR, 'examples') for subdirectory in glob.glob(os.path.join(options.examples_dir, "*/")): filetests = TestBuilder(subdirectory, examples_workdir, selectors, exclude_selectors, options, options.pyregr, languages, test_bugs, options.language_level, common_utility_dir, options.pythran_dir, default_mode='compile', stats=stats, add_cython_import=True) test_suite.addTest(filetests.build_suite()) if options.system_pyregr and languages: sys_pyregr_dir = os.path.join(sys.prefix, 'lib', 'python'+sys.version[:3], 'test') if not os.path.isdir(sys_pyregr_dir): sys_pyregr_dir = os.path.join(os.path.dirname(sys.executable), 'Lib', 'test') # source build if os.path.isdir(sys_pyregr_dir): filetests = TestBuilder(ROOTDIR, WORKDIR, selectors, exclude_selectors, options, True, languages, test_bugs, sys.version_info[0], common_utility_dir, stats=stats) sys.stderr.write("Including CPython regression tests in %s\n" % sys_pyregr_dir) test_suite.addTest(filetests.handle_directory(sys_pyregr_dir, 'pyregr')) if options.code_style and options.shard_num <= 0: try: import pycodestyle except ImportError: # Hack to make the exclusion visible. missing_dep_excluder.tests_missing_deps.append('TestCodeFormat') else: test_suite.addTest(TestCodeFormat(options.cython_dir)) if xml_output_dir: from Cython.Tests.xmlrunner import XMLTestRunner if not os.path.exists(xml_output_dir): try: os.makedirs(xml_output_dir) except OSError: pass # concurrency issue? test_runner = XMLTestRunner(output=xml_output_dir, verbose=options.verbosity > 0) if options.failfast: sys.stderr.write("--failfast not supported with XML runner\n") else: text_runner_options = {} if options.failfast: text_runner_options['failfast'] = True test_runner = unittest.TextTestRunner(verbosity=options.verbosity, **text_runner_options) if options.pyximport_py: from pyximport import pyximport pyximport.install(pyimport=True, build_dir=os.path.join(WORKDIR, '_pyximport'), load_py_module_on_import_failure=True, inplace=True) try: gc.set_debug(gc.DEBUG_UNCOLLECTABLE) except AttributeError: pass # not available on PyPy enable_faulthandler = False try: import faulthandler except ImportError: pass else: enable_faulthandler = not faulthandler.is_enabled() if enable_faulthandler: faulthandler.enable() # Run the collected tests. try: if options.shard_num > -1: sys.stderr.write("Tests in shard %d/%d starting\n" % (options.shard_num, options.shard_count)) result = test_runner.run(test_suite) except Exception as exc: # Make sure we print exceptions also from shards. if options.shard_num > -1: sys.stderr.write("Tests in shard %d/%d crashed: %s\n" % (options.shard_num, options.shard_count, exc)) import traceback traceback.print_exc() raise finally: if enable_faulthandler: faulthandler.disable() if common_utility_dir and options.shard_num < 0 and options.cleanup_workdir: shutil.rmtree(common_utility_dir) from Cython.Compiler.Pipeline import get_timings pipeline_stats = get_timings() if missing_dep_excluder.tests_missing_deps: sys.stderr.write("Following tests excluded because of missing dependencies on your system:\n") for test in missing_dep_excluder.tests_missing_deps: sys.stderr.write(" %s\n" % test) if options.with_refnanny: import refnanny sys.stderr.write("\n".join([repr(x) for x in refnanny.reflog])) result_code = 0 if options.exit_ok else not result.wasSuccessful() if xml_output_dir: failure_output = "" else: failure_output = "".join(collect_failure_output(result)) return options.shard_num, stats, pipeline_stats, result_code, failure_output def collect_failure_output(result): """Extract test error/failure output from a TextTestResult.""" failure_output = [] for flavour, errors in (("ERROR", result.errors), ("FAIL", result.failures)): for test, err in errors: failure_output.append("%s\n%s: %s\n%s\n%s\n" % ( result.separator1, flavour, result.getDescription(test), result.separator2, err)) return failure_output if __name__ == '__main__': try: main() except Exception: traceback.print_exc() try: check_thread_termination(ignore_seen=False) except PendingThreadsError: # normal program exit won't kill the threads, do it the hard way here flush_and_terminate(1) sys.exit(1) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/setup.cfg0000644000175100001770000000170200000000000015415 0ustar00runnerdocker00000000000000[flake8] max-complexity = 10 [pycodestyle] exclude = .git,build,__pycache__,venv*,TEST*,tests/run/test*.py,Cython/Debugger/libpython.py max-line-length = 150 format = pylint # See https://pycodestyle.pycqa.org/en/latest/intro.html#configuration select = E711, E713, E714, E501, W291, W292, E502, E703, # indentation E101, E111, E112, E113, E117 E121, E125, E129, # E114, E115, E116, E122, # whitespace E211, E223, E224, E227, E228, E242, E261, E273, E274, E275, # E201, E202, E203, E211, E265 # E303, E306, W1, W2, W3 #ignore = W, E ignore = W504, # W504 line break after binary operator S001, # S001 found module formatter E226, # E226 missing whitespace around operator[run] [coverage:run] branch = True parallel = True concurrency = multiprocessing,thread include = Cython/* source = Cython omit = Test* [bdist_wheel] universal = 1 [metadata] license_files = LICENSE.txt COPYING.txt ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/setup.py0000755000175100001770000002710000000000000015311 0ustar00runnerdocker00000000000000#!/usr/bin/env python try: from setuptools import setup, Extension except ImportError: from distutils.core import setup, Extension import os import stat import subprocess import textwrap import sys import platform is_cpython = platform.python_implementation() == 'CPython' # this specifies which versions of python we support, pip >= 9 knows to skip # versions of packages which are not compatible with the running python PYTHON_REQUIRES = '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*' if sys.platform == "darwin": # Don't create resource files on OS X tar. os.environ['COPY_EXTENDED_ATTRIBUTES_DISABLE'] = 'true' os.environ['COPYFILE_DISABLE'] = 'true' setup_args = {} def add_command_class(name, cls): cmdclasses = setup_args.get('cmdclass', {}) cmdclasses[name] = cls setup_args['cmdclass'] = cmdclasses from distutils.command.sdist import sdist as sdist_orig class sdist(sdist_orig): def run(self): self.force_manifest = 1 if (sys.platform != "win32" and os.path.isdir('.git')): assert os.system("git rev-parse --verify HEAD > .gitrev") == 0 sdist_orig.run(self) add_command_class('sdist', sdist) pxd_include_dirs = [ directory for directory, dirs, files in os.walk(os.path.join('Cython', 'Includes')) if '__init__.pyx' in files or '__init__.pxd' in files or directory == os.path.join('Cython', 'Includes')] pxd_include_patterns = [ p+'/*.pxd' for p in pxd_include_dirs ] + [ p+'/*.pyx' for p in pxd_include_dirs ] setup_args['package_data'] = { 'Cython.Plex' : ['*.pxd'], 'Cython.Compiler' : ['*.pxd'], 'Cython.Runtime' : ['*.pyx', '*.pxd'], 'Cython.Utility' : ['*.pyx', '*.pxd', '*.c', '*.h', '*.cpp'], 'Cython' : [ p[7:] for p in pxd_include_patterns ], 'Cython.Debugger.Tests': ['codefile', 'cfuncs.c'], } # This dict is used for passing extra arguments that are setuptools # specific to setup setuptools_extra_args = {} if 'setuptools' in sys.modules: setuptools_extra_args['python_requires'] = PYTHON_REQUIRES setuptools_extra_args['zip_safe'] = False setuptools_extra_args['entry_points'] = { 'console_scripts': [ 'cython = Cython.Compiler.Main:setuptools_main', 'cythonize = Cython.Build.Cythonize:main', 'cygdb = Cython.Debugger.Cygdb:main', ] } scripts = [] else: if os.name == "posix": scripts = ["bin/cython", "bin/cythonize", "bin/cygdb"] else: scripts = ["cython.py", "cythonize.py", "cygdb.py"] def compile_cython_modules(profile=False, coverage=False, compile_minimal=False, compile_more=False, cython_with_refnanny=False): source_root = os.path.abspath(os.path.dirname(__file__)) compiled_modules = [ "Cython.Plex.Actions", "Cython.Plex.Scanners", "Cython.Compiler.FlowControl", "Cython.Compiler.Scanning", "Cython.Compiler.Visitor", "Cython.Runtime.refnanny", ] if not compile_minimal: compiled_modules.extend([ "Cython.Plex.Machines", "Cython.Plex.Transitions", "Cython.Plex.DFA", "Cython.Compiler.Code", "Cython.Compiler.FusedNode", "Cython.Compiler.Parsing", "Cython.Tempita._tempita", "Cython.StringIOTree", "Cython.Utils", ]) if compile_more and not compile_minimal: compiled_modules.extend([ "Cython.Compiler.Lexicon", "Cython.Compiler.Pythran", "Cython.Build.Dependencies", "Cython.Compiler.ParseTreeTransforms", "Cython.Compiler.Nodes", "Cython.Compiler.ExprNodes", "Cython.Compiler.ModuleNode", "Cython.Compiler.Optimize", ]) from distutils.spawn import find_executable from distutils.sysconfig import get_python_inc pgen = find_executable( 'pgen', os.pathsep.join([os.environ['PATH'], os.path.join(get_python_inc(), '..', 'Parser')])) if not pgen: sys.stderr.write("Unable to find pgen, not compiling formal grammar.\n") else: parser_dir = os.path.join(os.path.dirname(__file__), 'Cython', 'Parser') grammar = os.path.join(parser_dir, 'Grammar') subprocess.check_call([ pgen, os.path.join(grammar), os.path.join(parser_dir, 'graminit.h'), os.path.join(parser_dir, 'graminit.c'), ]) cst_pyx = os.path.join(parser_dir, 'ConcreteSyntaxTree.pyx') if os.stat(grammar)[stat.ST_MTIME] > os.stat(cst_pyx)[stat.ST_MTIME]: mtime = os.stat(grammar)[stat.ST_MTIME] os.utime(cst_pyx, (mtime, mtime)) compiled_modules.extend([ "Cython.Parser.ConcreteSyntaxTree", ]) defines = [] if cython_with_refnanny: defines.append(('CYTHON_REFNANNY', '1')) if coverage: defines.append(('CYTHON_TRACE', '1')) extensions = [] for module in compiled_modules: source_file = os.path.join(source_root, *module.split('.')) pyx_source_file = source_file + ".py" if not os.path.exists(pyx_source_file): pyx_source_file += "x" # .py -> .pyx dep_files = [] if os.path.exists(source_file + '.pxd'): dep_files.append(source_file + '.pxd') extensions.append(Extension( module, sources=[pyx_source_file], define_macros=defines if '.refnanny' not in module else [], depends=dep_files)) # XXX hack around setuptools quirk for '*.pyx' sources extensions[-1].sources[0] = pyx_source_file # optimise build parallelism by starting with the largest modules extensions.sort(key=lambda ext: os.path.getsize(ext.sources[0]), reverse=True) from Cython.Distutils.build_ext import build_ext from Cython.Compiler.Options import get_directive_defaults get_directive_defaults().update( language_level=2, binding=False, always_allow_keywords=False, autotestdict=False, ) if profile: get_directive_defaults()['profile'] = True sys.stderr.write("Enabled profiling for the Cython binary modules\n") if coverage: get_directive_defaults()['linetrace'] = True sys.stderr.write("Enabled line tracing and profiling for the Cython binary modules\n") # not using cythonize() directly to let distutils decide whether building extensions was requested add_command_class("build_ext", build_ext) setup_args['ext_modules'] = extensions def check_option(name): cli_arg = "--" + name if cli_arg in sys.argv: sys.argv.remove(cli_arg) return True env_var = name.replace("-", "_").upper() if os.environ.get(env_var) == "true": return True return False cython_profile = check_option('cython-profile') cython_coverage = check_option('cython-coverage') cython_with_refnanny = check_option('cython-with-refnanny') compile_cython_itself = not check_option('no-cython-compile') if compile_cython_itself: cython_compile_more = check_option('cython-compile-all') cython_compile_minimal = check_option('cython-compile-minimal') setup_args.update(setuptools_extra_args) def dev_status(version): if 'b' in version or 'c' in version: # 1b1, 1beta1, 2rc1, ... return 'Development Status :: 4 - Beta' elif 'a' in version: # 1a1, 1alpha1, ... return 'Development Status :: 3 - Alpha' else: return 'Development Status :: 5 - Production/Stable' packages = [ 'Cython', 'Cython.Build', 'Cython.Compiler', 'Cython.Runtime', 'Cython.Distutils', 'Cython.Debugger', 'Cython.Debugger.Tests', 'Cython.Plex', 'Cython.Tests', 'Cython.Build.Tests', 'Cython.Compiler.Tests', 'Cython.Utility', 'Cython.Tempita', 'pyximport', ] def run_build(): if compile_cython_itself and (is_cpython or cython_compile_more or cython_compile_minimal): compile_cython_modules(cython_profile, cython_coverage, cython_compile_minimal, cython_compile_more, cython_with_refnanny) from Cython import __version__ as version setup( name='Cython', version=version, url='https://cython.org/', author='Robert Bradshaw, Stefan Behnel, Dag Seljebotn, Greg Ewing, et al.', author_email='cython-devel@python.org', description="The Cython compiler for writing C extensions in the Python language.", long_description=textwrap.dedent("""\ The Cython language makes writing C extensions for the Python language as easy as Python itself. Cython is a source code translator based on Pyrex_, but supports more cutting edge functionality and optimizations. The Cython language is a superset of the Python language (almost all Python code is also valid Cython code), but Cython additionally supports optional static typing to natively call C functions, operate with C++ classes and declare fast C types on variables and class attributes. This allows the compiler to generate very efficient C code from Cython code. This makes Cython the ideal language for writing glue code for external C/C++ libraries, and for fast C modules that speed up the execution of Python code. Note that for one-time builds, e.g. for CI/testing, on platforms that are not covered by one of the wheel packages provided on PyPI *and* the pure Python wheel that we provide is not used, it is substantially faster than a full source build to install an uncompiled (slower) version of Cython with:: pip install Cython --install-option="--no-cython-compile" .. _Pyrex: https://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/ """), license='Apache-2.0', classifiers=[ dev_status(version), "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Programming Language :: C", "Programming Language :: Cython", "Topic :: Software Development :: Code Generators", "Topic :: Software Development :: Compilers", "Topic :: Software Development :: Libraries :: Python Modules" ], project_urls={ "Documentation": "https://cython.readthedocs.io/", "Donate": "https://cython.readthedocs.io/en/latest/src/donating.html", "Source Code": "https://github.com/cython/cython", "Bug Tracker": "https://github.com/cython/cython/issues", "User Group": "https://groups.google.com/g/cython-users", }, scripts=scripts, packages=packages, py_modules=["cython"], **setup_args ) if __name__ == '__main__': run_build() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/setupegg.py0000755000175100001770000000024400000000000015774 0ustar00runnerdocker00000000000000#!/usr/bin/env python """Wrapper to run setup.py using setuptools.""" import setuptools with open('setup.py') as f: exec(compile(f.read(), 'setup.py', 'exec')) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/test-requirements-27.txt0000644000175100001770000000253300000000000020266 0ustar00runnerdocker00000000000000attrs==20.3.0 backports-abc==0.5 backports.functools-lru-cache==1.6.3 backports.shutil-get-terminal-size==1.0.0 bleach==3.3.0 configparser==4.0.2 contextlib2==0.6.0.post1 coverage==5.5 decorator==4.4.2 defusedxml==0.7.1 entrypoints==0.3 enum34==1.1.10 functools32==3.2.3.post2 futures==3.3.0 importlib-metadata==2.1.1 ipaddress==1.0.23 ipykernel==4.10.1 ipython==5.10.0 ipython-genutils==0.2.0 ipywidgets==7.6.3 Jinja2==2.11.3 jsonschema==3.2.0 jupyter==1.0.0 jupyter-client==5.3.5 jupyter-console==5.2.0 jupyter-core==4.6.3 line-profiler==3.1.0 ; sys_platform != "darwin" MarkupSafe==1.1.1 maturin==0.7.6; os_name == "nt" # actually 0.9.4, but it's not available; pywinpty dependency mistune==0.8.4 nbconvert==5.6.1 nbformat==4.4.0 notebook==5.7.10 numpy==1.16.6 packaging==20.9 pandocfilters==1.4.3 pathlib2==2.3.5 pexpect==4.8.0 pickleshare==0.7.5 prometheus-client==0.10.0 prompt-toolkit==1.0.18 ptyprocess==0.7.0 pycodestyle==2.7.0 Pygments==2.5.2 pyparsing==2.4.7 pyrsistent==0.15.7 python-dateutil==2.8.1 pywinpty==0.5.7 ; os_name == "nt" # terminado dependency (pywinpty>=0.5) pyzmq==16.0.4 qtconsole==4.7.7 QtPy==1.9.0 scandir==1.10.0 Send2Trash==1.5.0 simplegeneric==0.8.1 singledispatch==3.6.1 six==1.15.0 terminado==0.8.3 testpath==0.4.4 tornado==5.1.1 traitlets==4.3.3 wcwidth==0.2.5 webencodings==0.5.1 widgetsnbextension==3.5.1 zipp==1.2.0 mock==3.0.5 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/test-requirements-312.txt0000644000175100001770000000004600000000000020340 0ustar00runnerdocker00000000000000numpy coverage pycodestyle setuptools ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/test-requirements-34.txt0000644000175100001770000000004200000000000020255 0ustar00runnerdocker00000000000000numpy<1.16.0 coverage pycodestyle ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/test-requirements-36.txt0000644000175100001770000000033400000000000020263 0ustar00runnerdocker00000000000000jupyter pytest # needed by IPython/Jupyter integration tests line_profiler<4 # currently 4 appears to collect no profiling info setuptools<60 pywinpty<2.0.0 ; os_name == "nt" # jupyter dependency, no wheels after 2.0 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/test-requirements-cpython.txt0000644000175100001770000000022000000000000021511 0ustar00runnerdocker00000000000000jupyter pytest # needed by IPython/Jupyter integration tests line_profiler<4 # currently 4 appears to collect no profiling info setuptools<60 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/test-requirements-pypy27.txt0000644000175100001770000000004500000000000021204 0ustar00runnerdocker00000000000000-r test-requirements.txt mock==3.0.5 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/test-requirements.txt0000644000175100001770000000005100000000000020031 0ustar00runnerdocker00000000000000numpy coverage pycodestyle setuptools<60 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.0687242 Cython-3.0.8/tests/0000755000175100001770000000000000000000000014736 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.072724 Cython-3.0.8/tests/broken/0000755000175100001770000000000000000000000016216 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/b_extimpinherit.pyx0000644000175100001770000000021600000000000022151 0ustar00runnerdocker00000000000000cdef class Parrot: cdef describe(self): print "This is a parrot." cdef action(self): print "Polly wants a cracker!" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/big_t.pyx0000644000175100001770000000014000000000000020037 0ustar00runnerdocker00000000000000cdef extern from "foo.h": ctypedef long long big_t cdef void spam(big_t b) spam(grail) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/builtinconst.pyx0000644000175100001770000000250700000000000021501 0ustar00runnerdocker00000000000000cdef int f() except -1: cdef type t cdef object x t = buffer t = enumerate t = file t = float t = int t = long t = open t = property t = str t = tuple t = xrange x = True x = False x = Ellipsis x = Exception x = StopIteration x = StandardError x = ArithmeticError x = LookupError x = AssertionError x = AssertionError x = EOFError x = FloatingPointError x = EnvironmentError x = IOError x = OSError x = ImportError x = IndexError x = KeyError x = KeyboardInterrupt x = MemoryError x = NameError x = OverflowError x = RuntimeError x = NotImplementedError x = SyntaxError x = IndentationError x = TabError x = ReferenceError x = SystemError x = SystemExit x = TypeError x = UnboundLocalError x = UnicodeError x = UnicodeEncodeError x = UnicodeDecodeError x = UnicodeTranslateError x = ValueError x = ZeroDivisionError x = MemoryErrorInst x = Warning x = UserWarning x = DeprecationWarning x = PendingDeprecationWarning x = SyntaxWarning #x = OverflowWarning # Does not seem to exist in 2.5 x = RuntimeWarning x = FutureWarning typecheck(x, Exception) try: pass except ValueError: pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/builtindict.pyx0000644000175100001770000000041100000000000021266 0ustar00runnerdocker00000000000000cdef int f() except -1: cdef dict d cdef object x, z cdef int i z = dict d = dict(x) d = dict(*x) d.clear() z = d.copy() z = d.items() z = d.keys() z = d.values() d.merge(x, i) d.update(x) d.merge_pairs(x, i) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/cascadedass.pyx0000644000175100001770000000023100000000000021212 0ustar00runnerdocker00000000000000cdef void foo(): cdef int i, j, k i = j = k a = b = c i = j = c a = b = k (a, b), c = (d, e), f = (x, y), z # a, b = p, q = x, y ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/cexportfunc.pyx0000644000175100001770000000007700000000000021324 0ustar00runnerdocker00000000000000cdef int f(): pass cdef char *g(int k, float z): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/cimport.pyx0000644000175100001770000000022600000000000020435 0ustar00runnerdocker00000000000000cimport spam cimport pkg.eggs cdef spam.Spam yummy cdef pkg.eggs.Eggs fried spam.eat(yummy) spam.tons = 3.14 ova = pkg.eggs fried = pkg.eggs.Eggs() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/cimportfrom.pyx0000644000175100001770000000015600000000000021323 0ustar00runnerdocker00000000000000from spam cimport Spam from pkg.eggs cimport Eggs as ova cdef extern Spam yummy cdef ova fried fried = None ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/cimportfrompkgdir.pyx0000644000175100001770000000006200000000000022520 0ustar00runnerdocker00000000000000from package.inpackage cimport Spam cdef Spam s2 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/cimportfunc.pyx0000644000175100001770000000003600000000000021310 0ustar00runnerdocker00000000000000from cexportfunc cimport f, g ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/ctypedefextern.pyx0000644000175100001770000000025000000000000022006 0ustar00runnerdocker00000000000000cdef extern from "ctypedefextern.h": ctypedef int some_int ctypedef some_int *some_ptr cdef void spam(): cdef some_int i cdef some_ptr p p[0] = i ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/externfunc.pyx0000644000175100001770000000005200000000000021136 0ustar00runnerdocker00000000000000cdef extern from "foo.h": int fred() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/externsue.pyx0000644000175100001770000000042300000000000021001 0ustar00runnerdocker00000000000000cdef extern from "externsue.h": enum Eggs: runny, firm, hard struct Spam: int i union Soviet: char c cdef extern Eggs e cdef extern Spam s cdef extern Soviet u cdef void tomato(): global e e = runny e = firm e = hard ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/fwddeclcclass.pyx0000644000175100001770000000015100000000000021556 0ustar00runnerdocker00000000000000cdef class Widget: pass cdef class Container: pass cdef Widget w cdef Container c w.parent = c ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/getattr.pyx0000644000175100001770000000016300000000000020432 0ustar00runnerdocker00000000000000cdef class Spam: cdef public object eggs def __getattr__(self, name): print "Spam getattr:", name ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/getattr3ref.pyx0000644000175100001770000000005100000000000021206 0ustar00runnerdocker00000000000000cdef int f() except -1: g = getattr3 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/i_public.pyx0000644000175100001770000000025600000000000020551 0ustar00runnerdocker00000000000000cdef public int grail cdef public spam(int servings): pass cdef public class sandwich [object sandwich, type sandwich_Type]: cdef int tomato cdef float lettuce ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/includepublic.pyx0000644000175100001770000000003000000000000021573 0ustar00runnerdocker00000000000000include "i_public.pxi" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/intindex.pyx0000644000175100001770000000025000000000000020577 0ustar00runnerdocker00000000000000cdef int f() except -1: cdef object x, y, z cdef int i cdef unsigned int ui z = x[y] z = x[i] x[y] = z x[i] = z z = x[ui] x[ui] = z ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/invalid-module-name.pyx0000644000175100001770000000000000000000000022575 0ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/l_capi.pyx0000644000175100001770000000006200000000000020205 0ustar00runnerdocker00000000000000cdef api float f(float x): return 0.5 * x * x ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/l_cfuncexport.pyx0000644000175100001770000000011100000000000021624 0ustar00runnerdocker00000000000000cdef int f(int x): return x * x cdef int g(int x): return 5 * x ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/naanou_1.pyx0000644000175100001770000000003400000000000020456 0ustar00runnerdocker00000000000000def f(a, *p, **n): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/pkg.cimport.pyx0000644000175100001770000000012300000000000021211 0ustar00runnerdocker00000000000000cimport spam, eggs cdef extern spam.Spam yummy cdef eggs.Eggs fried fried = None ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/pkg.cimportfrom.pyx0000644000175100001770000000014400000000000022100 0ustar00runnerdocker00000000000000from spam cimport Spam from eggs cimport Eggs cdef extern Spam yummy cdef Eggs fried fried = None ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/plex2.pyx0000644000175100001770000000016600000000000020015 0ustar00runnerdocker00000000000000cdef class Spam: pass cdef void foo(object blarg): pass cdef void xyzzy(): cdef Spam spam foo(spam) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_capi.pyx0000644000175100001770000000021000000000000020206 0ustar00runnerdocker00000000000000cdef extern from "l_capi_api.h": float f(float) int import_l_capi() except -1 def test(): print f(3.1415) import_l_capi() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_cfuncimport.pyx0000644000175100001770000000013200000000000021626 0ustar00runnerdocker00000000000000cimport l_cfuncexport from l_cfuncexport cimport g print l_cfuncexport.f(42) print g(42) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_classdoc.pyx0000644000175100001770000000005400000000000021073 0ustar00runnerdocker00000000000000class Spam: """Spam, glorious spam!""" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_classmodname.pyx0000644000175100001770000000002500000000000021744 0ustar00runnerdocker00000000000000class Spam: pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_excval.pyx0000644000175100001770000000060100000000000020560 0ustar00runnerdocker00000000000000cdef int tomato() except -1: print "Entering tomato" raise Exception("Eject! Eject! Eject!") print "Leaving tomato" cdef void sandwich(): print "Entering sandwich" tomato() print "Leaving sandwich" def snack(): print "Entering snack" tomato() print "Leaving snack" def lunch(): print "Entering lunch" sandwich() print "Leaving lunch" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_extimpinherit.pyx0000644000175100001770000000062200000000000022172 0ustar00runnerdocker00000000000000from b_extimpinherit cimport Parrot cdef class Norwegian(Parrot): cdef action(self): print "This parrot is resting." cdef plumage(self): print "Lovely plumage!" def main(): cdef Parrot p cdef Norwegian n p = Parrot() n = Norwegian() print "Parrot:" p.describe() p.action() print "Norwegian:" n.describe() n.action() n.plumage() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_extinherit.pyx0000644000175100001770000000042500000000000021465 0ustar00runnerdocker00000000000000cdef class Parrot: cdef object plumage def __init__(self): self.plumage = "yellow" def describe(self): print "This bird has lovely", self.plumage, "plumage." cdef class Norwegian(Parrot): def __init__(self): self.plumage = "blue" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_extmember.pyx0000644000175100001770000000047700000000000021301 0ustar00runnerdocker00000000000000cdef class Spam: cdef public int tons cdef readonly float tastiness cdef int temperature def __init__(self, tons, tastiness, temperature): self.tons = tons self.tastiness = tastiness self.temperature = temperature def get_temperature(self): return self.temperature ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_extnumeric2.pyx0000644000175100001770000000112600000000000021546 0ustar00runnerdocker00000000000000cdef extern from "numeric.h": struct PyArray_Descr: int type_num, elsize char type ctypedef class Numeric.ArrayType [object PyArrayObject]: cdef char *data cdef int nd cdef int *dimensions, *strides cdef object base cdef PyArray_Descr *descr cdef int flags def ogle(ArrayType a): print "No. of dimensions:", a.nd print " Dim Value" for i in range(a.nd): print "%5d %5d" % (i, a.dimensions[i]) print "flags:", a.flags print "Type no.", a.descr.type_num print "Element size:", a.descr.elsize ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_extproperty.pyx0000644000175100001770000000057500000000000021715 0ustar00runnerdocker00000000000000cdef class CheeseShop: cdef object cheeses def __cinit__(self): self.cheeses = [] property cheese: "A senseless waste of a property." def __get__(self): return "We don't have: %s" % self.cheeses def __set__(self, value): self.cheeses.append(value) def __del__(self): del self.cheeses[:] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_extweakref.pyx0000644000175100001770000000011300000000000021441 0ustar00runnerdocker00000000000000cdef class Animal: cdef object __weakref__ cdef public object name ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_getattr3.pyx0000644000175100001770000000010000000000000021025 0ustar00runnerdocker00000000000000def test(obj, attr, dflt): return getattr3(obj, attr, dflt) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_import.pyx0000644000175100001770000000013600000000000020613 0ustar00runnerdocker00000000000000import spam print "Imported spam" print dir(spam) import sys print "Imported sys" print sys ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_inhcmethcall.pyx0000644000175100001770000000042700000000000021737 0ustar00runnerdocker00000000000000cdef class Parrot: cdef void describe(self): print "This parrot is resting." cdef class Norwegian(Parrot): cdef void describe(self): Parrot.describe(self) print "Lovely plumage!" cdef Parrot p1, p2 p1 = Parrot() p2 = Norwegian() p1.describe() p2.describe() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_kwonlyargs.pyx0000644000175100001770000000131100000000000021475 0ustar00runnerdocker00000000000000def pd(d): l = [] i = d.items() i.sort() for kv in i: l.append("%r: %r" % kv) return "{%s}" % ", ".join(l) def c(a, b, c): print "a =", a, "b =", b, "c =", c def d(a, b, *, c = 88): print "a =", a, "b =", b, "c =", c def e(a, b, c = 88, **kwds): print "a =", a, "b =", b, "c =", c, "kwds =", pd(kwds) def f(a, b, *, c, d = 42): print "a =", a, "b =", b, "c =", c, "d =", d def g(a, b, *, c, d = 42, e = 17, f, **kwds): print "a =", a, "b =", b, "c =", c, "d =", d, "e =", e, "f =", f, "kwds =", pd(kwds) def h(a, b, *args, c, d = 42, e = 17, f, **kwds): print "a =", a, "b =", b, "args =", args, "c =", c, "d =", d, "e =", e, "f =", f, "kwds =", pd(kwds) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_newstyleclass.pyx0000644000175100001770000000017000000000000022177 0ustar00runnerdocker00000000000000class Inquisition(object): """Something that nobody expects.""" def __repr__(self): return "Surprise!" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_simpcall.pyx0000644000175100001770000000004000000000000021077 0ustar00runnerdocker00000000000000def f(): print "Spam!" f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_tbfilename.pyx0000644000175100001770000000003700000000000021407 0ustar00runnerdocker00000000000000def foo(): raise Exception ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_traceback.pyx0000644000175100001770000000020100000000000021211 0ustar00runnerdocker00000000000000cdef int spam() except -1: raise Exception("Spam error") cdef int grail() except -1: spam() def tomato(): grail() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3647223 Cython-3.0.8/tests/broken/r_unpack.pyx0000644000175100001770000000021700000000000020562 0ustar00runnerdocker00000000000000seq = [1, [2, 3]] def f(): a, (b, c) = [1, [2, 3]] print a print b print c def g(): a, b, c = seq def h(): a, = seq ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/broken/raise.pyx0000644000175100001770000000021000000000000020054 0ustar00runnerdocker00000000000000def f(a, b, c): #raise raise a raise "spam" raise a, b raise "spam", 42 raise a, b, c raise "spam", 42, c() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/broken/retconvert.pyx0000644000175100001770000000010500000000000021147 0ustar00runnerdocker00000000000000def f(): return 42 cdef int g(): cdef object x return x ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/broken/test_include_options.pyx0000644000175100001770000000020200000000000023207 0ustar00runnerdocker00000000000000import sys from Pyrex.Compiler.Main import main sys.argv[1:] = "-I spam -Ieggs --include-dir ham".split() main(command_line = 1) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/broken/tryexceptelse.pyx0000644000175100001770000000044300000000000021661 0ustar00runnerdocker00000000000000def f(): cdef int i try: i = 1 raise x i = 2 else: i = 3 raise y i = 4 def g(): cdef int i try: i = 1 raise x i = 2 except a: i = 3 else: i = 4 raise y i = 5 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/broken/tslots.pyx0000644000175100001770000000006100000000000020305 0ustar00runnerdocker00000000000000cdef class Spam: pass def probe(): pass ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.072724 Cython-3.0.8/tests/buffers/0000755000175100001770000000000000000000000016372 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/buffers/bufaccess.h0000644000175100001770000000016300000000000020501 0ustar00runnerdocker00000000000000/* See bufaccess.pyx */ typedef short td_h_short; typedef double td_h_double; typedef unsigned short td_h_ushort; ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/buffers/bufaccess.pyx0000644000175100001770000007271700000000000021110 0ustar00runnerdocker00000000000000# Tests the buffer access syntax functionality by constructing # mock buffer objects. # # Note that the buffers are mock objects created for testing # the buffer access behaviour -- for instance there is no flag # checking in the buffer objects (why test our test case?), rather # what we want to test is what is passed into the flags argument. # from __future__ import unicode_literals from cpython.object cimport PyObject from cpython.ref cimport Py_INCREF, Py_DECREF, Py_CLEAR cimport cython import sys #import re exclude = []#re.compile('object').search] if getattr(sys, 'pypy_version_info', None) is not None: # disable object-in-buffer tests in PyPy import re exclude.append(re.compile('object').search) def testcase(func): for e in exclude: if e(func.__name__): func.__doc__ = "" # disable the test return func include "mockbuffers.pxi" # # Buffer acquire and release tests # def nousage(): """ The challenge here is just compilation. """ cdef object[int, ndim=2] buf @testcase def disabled_usage(obj): """ The challenge here is just compilation. >>> disabled_usage(None) """ cdef object[int, ndim=2] buf if False: buf = obj return obj @testcase def nousage_cleanup(x): """ >>> nousage_cleanup(False) >>> nousage_cleanup(True) Traceback (most recent call last): RuntimeError """ cdef object[int, ndim=2] buf if x: raise RuntimeError() @testcase def acquire_release(o1, o2): """ >>> A = IntMockBuffer("A", range(6)) >>> B = IntMockBuffer("B", range(6)) >>> acquire_release(A, B) acquired A released A acquired B released B >>> acquire_release(None, None) >>> acquire_release(None, B) acquired B released B """ cdef object[int] buf buf = o1 buf = o2 @testcase def acquire_raise(o): """ Apparently, doctest won't handle mixed exceptions and print stats, so need to circumvent this. >>> A = IntMockBuffer("A", range(6)) >>> A.resetlog() >>> acquire_raise(A) Traceback (most recent call last): ... Exception: on purpose >>> A.printlog() acquired A released A """ cdef object[int] buf buf = o raise Exception("on purpose") @testcase def acquire_failure1(): """ >>> acquire_failure1() acquired working 0 3 0 3 released working """ cdef object[int] buf buf = IntMockBuffer("working", range(4)) print buf[0], buf[3] try: buf = ErrorBuffer() assert False except Exception: print buf[0], buf[3] @testcase def acquire_failure2(): """ >>> acquire_failure2() acquired working 0 3 0 3 released working """ cdef object[int] buf = IntMockBuffer("working", range(4)) print buf[0], buf[3] try: buf = ErrorBuffer() assert False except Exception: print buf[0], buf[3] @testcase def acquire_failure3(): """ >>> acquire_failure3() acquired working 0 3 released working acquired working 0 3 released working """ cdef object[int] buf buf = IntMockBuffer("working", range(4)) print buf[0], buf[3] try: buf = 3 assert False except Exception: print buf[0], buf[3] @testcase def acquire_failure4(): """ >>> acquire_failure4() acquired working 0 3 released working acquired working 0 3 released working """ cdef object[int] buf = IntMockBuffer("working", range(4)) print buf[0], buf[3] try: buf = 2 assert False except Exception: print buf[0], buf[3] @testcase def acquire_failure5(): """ >>> acquire_failure5() Traceback (most recent call last): ... ValueError: Buffer acquisition failed on assignment; and then reacquiring the old buffer failed too! """ cdef object[int] buf buf = IntMockBuffer("working", range(4)) buf.fail = True buf = 3 @testcase def acquire_nonbuffer1(first, second=None): """ >>> acquire_nonbuffer1(3) # doctest: +ELLIPSIS Traceback (most recent call last): TypeError:... 'int'... >>> acquire_nonbuffer1(type) # doctest: +ELLIPSIS Traceback (most recent call last): TypeError:... 'type'... >>> acquire_nonbuffer1(None, 2) # doctest: +ELLIPSIS Traceback (most recent call last): TypeError:... 'int'... """ cdef object[int] buf buf = first buf = second @testcase def acquire_nonbuffer2(): """ >>> acquire_nonbuffer2() acquired working 0 3 released working acquired working 0 3 released working """ cdef object[int] buf = IntMockBuffer("working", range(4)) print buf[0], buf[3] try: buf = ErrorBuffer assert False except Exception: print buf[0], buf[3] @testcase def as_argument(object[int] bufarg, int n): """ >>> A = IntMockBuffer("A", range(6)) >>> as_argument(A, 6) acquired A 0 1 2 3 4 5 END released A """ cdef int i for i in range(n): print bufarg[i], print 'END' @testcase def as_argument_not_none(object[int] bufarg not None): """ >>> A = IntMockBuffer("A", range(6)) >>> as_argument_not_none(A) acquired A ACCEPTED released A >>> as_argument_not_none(None) Traceback (most recent call last): TypeError: Argument 'bufarg' must not be None """ print 'ACCEPTED' @testcase def as_argument_defval(object[int] bufarg=IntMockBuffer('default', range(6)), int n=6): """ >>> as_argument_defval() acquired default 0 1 2 3 4 5 END released default >>> A = IntMockBuffer("A", range(6)) >>> as_argument_defval(A, 6) acquired A 0 1 2 3 4 5 END released A """ cdef int i for i in range(n): print bufarg[i], print 'END' @testcase def cdef_assignment(obj, n): """ >>> A = IntMockBuffer("A", range(6)) >>> cdef_assignment(A, 6) acquired A 0 1 2 3 4 5 END released A """ cdef object[int] buf = obj cdef int i for i in range(n): print buf[i], print 'END' @testcase def forin_assignment(objs, int pick): """ >>> A = IntMockBuffer("A", range(6)) >>> B = IntMockBuffer("B", range(6)) >>> forin_assignment([A, B, A, A], 2) acquired A 2 released A acquired B 2 released B acquired A 2 released A acquired A 2 released A """ cdef object[int] buf for buf in objs: print buf[pick] @testcase def cascaded_buffer_assignment(obj): """ >>> A = IntMockBuffer("A", range(6)) >>> cascaded_buffer_assignment(A) acquired A acquired A released A released A """ cdef object[int] a, b a = b = obj @testcase def tuple_buffer_assignment1(a, b): """ >>> A = IntMockBuffer("A", range(6)) >>> B = IntMockBuffer("B", range(6)) >>> tuple_buffer_assignment1(A, B) acquired A acquired B released A released B """ cdef object[int] x, y x, y = a, b @testcase def tuple_buffer_assignment2(tup): """ >>> A = IntMockBuffer("A", range(6)) >>> B = IntMockBuffer("B", range(6)) >>> tuple_buffer_assignment2((A, B)) acquired A acquired B released A released B """ cdef object[int] x, y x, y = tup @testcase def explicitly_release_buffer(): """ >>> explicitly_release_buffer() acquired A released A After release """ cdef object[int] x = IntMockBuffer("A", range(10)) x = None print "After release" # # Getting items and index bounds checking # @testcase def get_int_2d(object[int, ndim=2] buf, int i, int j): """ >>> C = IntMockBuffer("C", range(6), (2,3)) >>> get_int_2d(C, 1, 1) acquired C released C 4 Check negative indexing: >>> get_int_2d(C, -1, 0) acquired C released C 3 >>> get_int_2d(C, -1, -2) acquired C released C 4 >>> get_int_2d(C, -2, -3) acquired C released C 0 Out-of-bounds errors: >>> get_int_2d(C, 2, 0) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) >>> get_int_2d(C, 0, -4) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 1) """ return buf[i, j] @testcase def get_int_2d_uintindex(object[int, ndim=2] buf, unsigned int i, unsigned int j): """ Unsigned indexing: >>> C = IntMockBuffer("C", range(6), (2,3)) >>> get_int_2d_uintindex(C, 0, 0) acquired C released C 0 >>> get_int_2d_uintindex(C, 1, 2) acquired C released C 5 """ # This is most interesting with regards to the C code # generated. return buf[i, j] @testcase def set_int_2d(object[int, ndim=2] buf, int i, int j, int value): """ Uses get_int_2d to read back the value afterwards. For pure unit test, one should support reading in MockBuffer instead. >>> C = IntMockBuffer("C", range(6), (2,3)) >>> set_int_2d(C, 1, 1, 10) acquired C released C >>> get_int_2d(C, 1, 1) acquired C released C 10 Check negative indexing: >>> set_int_2d(C, -1, 0, 3) acquired C released C >>> get_int_2d(C, -1, 0) acquired C released C 3 >>> set_int_2d(C, -1, -2, 8) acquired C released C >>> get_int_2d(C, -1, -2) acquired C released C 8 >>> set_int_2d(C, -2, -3, 9) acquired C released C >>> get_int_2d(C, -2, -3) acquired C released C 9 Out-of-bounds errors: >>> set_int_2d(C, 2, 0, 19) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) >>> set_int_2d(C, 0, -4, 19) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 1) """ buf[i, j] = value @testcase def set_int_2d_cascaded(object[int, ndim=2] buf, int i, int j, int value): """ Uses get_int_2d to read back the value afterwards. For pure unit test, one should support reading in MockBuffer instead. >>> C = IntMockBuffer("C", range(6), (2,3)) >>> set_int_2d_cascaded(C, 1, 1, 10) acquired C released C 10 >>> get_int_2d(C, 1, 1) acquired C released C 10 Check negative indexing: >>> set_int_2d_cascaded(C, -1, 0, 3) acquired C released C 3 >>> get_int_2d(C, -1, 0) acquired C released C 3 >>> set_int_2d_cascaded(C, -1, -2, 8) acquired C released C 8 >>> get_int_2d(C, -1, -2) acquired C released C 8 >>> set_int_2d_cascaded(C, -2, -3, 9) acquired C released C 9 >>> get_int_2d(C, -2, -3) acquired C released C 9 Out-of-bounds errors: >>> set_int_2d_cascaded(C, 2, 0, 19) Traceback (most recent call last): IndexError: Out of bounds on buffer access (axis 0) >>> set_int_2d_cascaded(C, 0, -4, 19) Traceback (most recent call last): IndexError: Out of bounds on buffer access (axis 1) """ cdef int casc_value buf[i, j] = casc_value = value return casc_value @testcase def list_comprehension(object[int] buf, len): """ >>> list_comprehension(IntMockBuffer(None, [1,2,3]), 3) 1|2|3 """ cdef int i print u"|".join([unicode(buf[i]) for i in range(len)]) # # The negative_indices buffer option # @testcase def no_negative_indices(object[int, negative_indices=False] buf, int idx): """ The most interesting thing here is to inspect the C source and make sure optimal code is produced. >>> A = IntMockBuffer(None, range(6)) >>> no_negative_indices(A, 3) 3 >>> no_negative_indices(A, -1) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) """ return buf[idx] @testcase @cython.wraparound(False) def wraparound_directive(object[int] buf, int pos_idx, int neg_idx): """ Again, the most interesting thing here is to inspect the C source. >>> A = IntMockBuffer(None, range(4)) >>> wraparound_directive(A, 2, -1) 5 >>> wraparound_directive(A, -1, 2) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) """ cdef int byneg with cython.wraparound(True): byneg = buf[neg_idx] return buf[pos_idx] + byneg # # Test which flags are passed. # @testcase def readonly(obj): """ >>> R = UnsignedShortMockBuffer("R", range(27), shape=(3, 3, 3)) >>> readonly(R) acquired R 25 released R >>> [str(x) for x in R.received_flags] # Works in both py2 and py3 ['FORMAT', 'INDIRECT', 'ND', 'STRIDES'] """ cdef object[unsigned short int, ndim=3] buf = obj print buf[2, 2, 1] @testcase def writable(obj): """ >>> R = UnsignedShortMockBuffer("R", range(27), shape=(3, 3, 3)) >>> writable(R) acquired R released R >>> [str(x) for x in R.received_flags] # Py2/3 ['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE'] """ cdef object[unsigned short int, ndim=3] buf = obj buf[2, 2, 1] = 23 @testcase def strided(object[int, ndim=1, mode='strided'] buf): """ >>> A = IntMockBuffer("A", range(4)) >>> strided(A) acquired A released A 2 >>> [str(x) for x in A.received_flags] # Py2/3 ['FORMAT', 'ND', 'STRIDES'] Check that the suboffsets were patched back prior to release. >>> A.release_ok True """ return buf[2] @testcase def c_contig(object[int, ndim=1, mode='c'] buf): """ >>> A = IntMockBuffer(None, range(4)) >>> c_contig(A) 2 >>> [str(x) for x in A.received_flags] ['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS'] """ return buf[2] @testcase def c_contig_2d(object[int, ndim=2, mode='c'] buf): """ Multi-dim has separate implementation >>> A = IntMockBuffer(None, range(12), shape=(3,4)) >>> c_contig_2d(A) 7 >>> [str(x) for x in A.received_flags] ['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS'] """ return buf[1, 3] @testcase def f_contig(object[int, ndim=1, mode='fortran'] buf): """ >>> A = IntMockBuffer(None, range(4)) >>> f_contig(A) 2 >>> [str(x) for x in A.received_flags] ['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS'] """ return buf[2] @testcase def f_contig_2d(object[int, ndim=2, mode='fortran'] buf): """ Must set up strides manually to ensure Fortran ordering. >>> A = IntMockBuffer(None, range(12), shape=(4,3), strides=(1, 4)) >>> f_contig_2d(A) 7 >>> [str(x) for x in A.received_flags] ['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS'] """ return buf[3, 1] # # Test compiler options for bounds checking. We create an array with a # safe "boundary" (memory # allocated outside of what it published) and then check whether we get back # what we stored in the memory or an error. @testcase def safe_get(object[int] buf, int idx): """ >>> A = IntMockBuffer(None, range(10), shape=(3,), offset=5) Validate our testing buffer... >>> safe_get(A, 0) 5 >>> safe_get(A, 2) 7 >>> safe_get(A, -3) 5 Access outside it. This is already done above for bounds check testing but we include it to tell the story right. >>> safe_get(A, -4) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) >>> safe_get(A, 3) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) """ return buf[idx] @testcase @cython.boundscheck(False) # outer decorators should take precedence @cython.boundscheck(True) def unsafe_get(object[int] buf, int idx): """ Access outside of the area the buffer publishes. >>> A = IntMockBuffer(None, range(10), shape=(3,), offset=5) >>> unsafe_get(A, -4) 4 >>> unsafe_get(A, -5) 3 >>> unsafe_get(A, 3) 8 """ return buf[idx] @testcase @cython.boundscheck(False) def unsafe_get_nonegative(object[int, negative_indices=False] buf, int idx): """ Also inspect the C source to see that it is optimal... >>> A = IntMockBuffer(None, range(10), shape=(3,), offset=5) >>> unsafe_get_nonegative(A, -2) 3 """ return buf[idx] @testcase def mixed_get(object[int] buf, int unsafe_idx, int safe_idx): """ >>> A = IntMockBuffer(None, range(10), shape=(3,), offset=5) >>> mixed_get(A, -4, 0) (4, 5) >>> mixed_get(A, 0, -4) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) """ with cython.boundscheck(False): one = buf[unsafe_idx] with cython.boundscheck(True): two = buf[safe_idx] return (one, two) # # Coercions # ## @testcase ## def coercions(object[unsigned char] uc): ## """ ## TODO ## """ ## print type(uc[0]) ## uc[0] = -1 ## print uc[0] ## uc[0] = 3.14 ## print uc[0] ## cdef char* ch = b"asfd" ## cdef object[object] objbuf ## objbuf[3] = ch # # Testing that accessing data using various types of buffer access # all works. # def printbuf_int(object[int] buf, shape): # Utility func cdef int i for i in range(shape[0]): print buf[i], print 'END' @testcase def printbuf_int_2d(o, shape): """ Strided: >>> printbuf_int_2d(IntMockBuffer("A", range(6), (2,3)), (2,3)) acquired A 0 1 2 END 3 4 5 END released A >>> printbuf_int_2d(IntMockBuffer("A", range(100), (3,3), strides=(20,5)), (3,3)) acquired A 0 5 10 END 20 25 30 END 40 45 50 END released A Indirect: >>> printbuf_int_2d(IntMockBuffer("A", [[1,2],[3,4]]), (2,2)) acquired A 1 2 END 3 4 END released A """ # should make shape builtin cdef object[int, ndim=2] buf buf = o cdef int i, j for i in range(shape[0]): for j in range(shape[1]): print buf[i, j], print 'END' @testcase def printbuf_float(o, shape): """ >>> printbuf_float(FloatMockBuffer("F", [1.0, 1.25, 0.75, 1.0]), (4,)) acquired F 1.0 1.25 0.75 1.0 END released F """ # should make shape builtin cdef object[float] buf buf = o cdef int i, j for i in range(shape[0]): print buf[i], print "END" # # Test assignments # @testcase def inplace_operators(object[int] buf): """ >>> buf = IntMockBuffer(None, [2, 2]) >>> inplace_operators(buf) >>> printbuf_int(buf, (2,)) 0 3 END """ cdef int j = 0 buf[1] += 1 buf[j] *= 2 buf[0] -= 4 # # Typedefs # # Test three layers of typedefs going through a h file for plain int, and # simply a header file typedef for floats and unsigned. ctypedef int td_cy_int cdef extern from "bufaccess.h": ctypedef td_cy_int td_h_short # Defined as short, but Cython doesn't know this! ctypedef float td_h_double # Defined as double ctypedef unsigned int td_h_ushort # Defined as unsigned short ctypedef td_h_short td_h_cy_short @testcase def printbuf_td_cy_int(object[td_cy_int] buf, shape): """ >>> printbuf_td_cy_int(IntMockBuffer(None, range(3)), (3,)) 0 1 2 END >>> printbuf_td_cy_int(ShortMockBuffer(None, range(3)), (3,)) Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'td_cy_int' but got 'short' """ cdef int i for i in range(shape[0]): print buf[i], print 'END' @testcase def printbuf_td_h_short(object[td_h_short] buf, shape): """ >>> printbuf_td_h_short(ShortMockBuffer(None, range(3)), (3,)) 0 1 2 END >>> printbuf_td_h_short(IntMockBuffer(None, range(3)), (3,)) Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'td_h_short' but got 'int' """ cdef int i for i in range(shape[0]): print buf[i], print 'END' @testcase def printbuf_td_h_cy_short(object[td_h_cy_short] buf, shape): """ >>> printbuf_td_h_cy_short(ShortMockBuffer(None, range(3)), (3,)) 0 1 2 END >>> printbuf_td_h_cy_short(IntMockBuffer(None, range(3)), (3,)) Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'td_h_cy_short' but got 'int' """ cdef int i for i in range(shape[0]): print buf[i], print 'END' @testcase def printbuf_td_h_ushort(object[td_h_ushort] buf, shape): """ >>> printbuf_td_h_ushort(UnsignedShortMockBuffer(None, range(3)), (3,)) 0 1 2 END >>> printbuf_td_h_ushort(ShortMockBuffer(None, range(3)), (3,)) Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'td_h_ushort' but got 'short' """ cdef int i for i in range(shape[0]): print buf[i], print 'END' @testcase def printbuf_td_h_double(object[td_h_double] buf, shape): """ >>> printbuf_td_h_double(DoubleMockBuffer(None, [0.25, 1, 3.125]), (3,)) 0.25 1.0 3.125 END >>> printbuf_td_h_double(FloatMockBuffer(None, [0.25, 1, 3.125]), (3,)) Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'td_h_double' but got 'float' """ cdef int i for i in range(shape[0]): print buf[i], print 'END' # # Object access # def addref(*args): for item in args: Py_INCREF(item) def decref(*args): for item in args: Py_DECREF(item) @cython.binding(False) @cython.always_allow_keywords(False) def get_refcount(x): return (x).ob_refcnt @testcase def printbuf_object(object[object] buf, shape): """ Only play with unique objects, interned numbers etc. will have unpredictable refcounts. ObjectMockBuffer doesn't do anything about increfing/decrefing, we to the "buffer implementor" refcounting directly in the testcase. >>> _x = 1 >>> a, b, c = "globally_unique_string_2323412" + "3" * _x, {4:23}, [34,3] >>> get_refcount(a), get_refcount(b), get_refcount(c) (2, 2, 2) >>> A = ObjectMockBuffer(None, [a, b, c]) >>> printbuf_object(A, (3,)) 'globally_unique_string_23234123' 2 {4: 23} 2 [34, 3] 2 """ cdef int i for i in range(shape[0]): print repr(buf[i]), (buf[i]).ob_refcnt @testcase def assign_to_object(object[object] buf, int idx, obj): """ See comments on printbuf_object above. >>> a, b = [1, 2, 3], [4, 5, 6] >>> rca1, rcb1 = get_refcount(a), get_refcount(b) >>> rca1 == rcb1 True >>> addref(a) >>> A = ObjectMockBuffer(None, [1, a]) # 1, ...,otherwise it thinks nested lists... >>> get_refcount(a) == rca1+1, get_refcount(b) == rcb1 (True, True) >>> assign_to_object(A, 1, b) >>> get_refcount(a) == rca1, get_refcount(b) == rcb1+1 (True, True) >>> decref(b) """ buf[idx] = obj @testcase def check_object_nulled_1d(MockBuffer[object, ndim=1] buf, int idx, obj): """ See comments on printbuf_object above. >>> a = object() >>> rc1 = get_refcount(a) >>> A = ObjectMockBuffer(None, [a, a]) >>> check_object_nulled_1d(A, 0, a) >>> check_object_nulled_1d(A, 1, a) >>> A = ObjectMockBuffer(None, [a, a, a, a], strides=(2,)) >>> check_object_nulled_1d(A, 0, a) # only 0 due to stride >>> get_refcount(a) == rc1 True """ cdef PyObject **data = buf.buffer Py_CLEAR(data[idx]) res = buf[idx] # takes None buf[idx] = obj return res @testcase def check_object_nulled_2d(MockBuffer[object, ndim=2] buf, int idx1, int idx2, obj): """ See comments on printbuf_object above. >>> a = object() >>> rc1 = get_refcount(a) >>> A = ObjectMockBuffer(None, [a, a, a, a], shape=(2, 2)) >>> check_object_nulled_2d(A, 0, 0, a) >>> check_object_nulled_2d(A, 1, 1, a) >>> get_refcount(a) == rc1 True """ cdef PyObject **data = buf.buffer Py_CLEAR(data[idx1 + 2*idx2]) res = buf[idx1, idx2] # takes None buf[idx1, idx2] = obj return res @testcase def assign_temporary_to_object(object[object] buf): """ See comments on printbuf_object above. >>> a, b = [1, 2, 3], {4:23} >>> rc1 = get_refcount(a) >>> addref(a) >>> A = ObjectMockBuffer(None, [b, a]) >>> get_refcount(a) == rc1+1 True >>> assign_temporary_to_object(A) >>> get_refcount(a) == rc1 True >>> printbuf_object(A, (2,)) {4: 23} 2 {1: 8} 2 To avoid leaking a reference in our testcase we need to replace the temporary with something we can manually decref :-) >>> assign_to_object(A, 1, a) >>> decref(a) """ buf[1] = {3-2: 2+(2*4)-2} # # cast option # @testcase def buffer_cast(object[unsigned int, cast=True] buf, int idx): """ Round-trip a signed int through unsigned int buffer access. >>> A = IntMockBuffer(None, [-100]) >>> buffer_cast(A, 0) -100 """ cdef unsigned int data = buf[idx] return data @testcase def buffer_cast_fails(object[char, cast=True] buf): """ Cannot cast between datatype of different sizes. >>> buffer_cast_fails(IntMockBuffer(None, [0])) Traceback (most recent call last): ... ValueError: Item size of buffer (4 bytes) does not match size of 'char' (1 byte) """ return buf[0] # # Typed buffers # @testcase def typedbuffer1(obj): """ >>> typedbuffer1(IntMockBuffer("A", range(10))) acquired A released A >>> typedbuffer1(None) >>> typedbuffer1(4) Traceback (most recent call last): ... TypeError: Cannot convert int to bufaccess.IntMockBuffer """ cdef IntMockBuffer[int, ndim=1] buf = obj @testcase def typedbuffer2(IntMockBuffer[int, ndim=1] obj): """ >>> typedbuffer2(IntMockBuffer("A", range(10))) acquired A released A >>> typedbuffer2(None) >>> typedbuffer2(4) Traceback (most recent call last): ... TypeError: Argument 'obj' has incorrect type (expected bufaccess.IntMockBuffer, got int) """ pass # # Test __cythonbufferdefaults__ # @testcase def bufdefaults1(IntStridedMockBuffer[int, ndim=1] buf): """ For IntStridedMockBuffer, mode should be "strided" by defaults which should show up in the flags. >>> A = IntStridedMockBuffer("A", range(10)) >>> bufdefaults1(A) acquired A released A >>> [str(x) for x in A.received_flags] ['FORMAT', 'ND', 'STRIDES'] """ pass @testcase def basic_struct(object[MyStruct] buf): """ See also buffmt.pyx >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)])) 1 2 3 4 5 >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ccqii")) 1 2 3 4 5 """ print buf[0].a, buf[0].b, buf[0].c, buf[0].d, buf[0].e @testcase def nested_struct(object[NestedStruct] buf): """ See also buffmt.pyx >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)])) 1 2 3 4 5 >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="T{ii}T{2i}i")) 1 2 3 4 5 """ print buf[0].x.a, buf[0].x.b, buf[0].y.a, buf[0].y.b, buf[0].z @testcase def packed_struct(object[PackedStruct] buf): """ See also buffmt.pyx >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)])) 1 2 >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c^i}")) 1 2 >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c=i}")) 1 2 """ print buf[0].a, buf[0].b @testcase def nested_packed_struct(object[NestedPackedStruct] buf): """ See also buffmt.pyx >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)])) 1 2 3 4 5 >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ci^ci@i")) 1 2 3 4 5 >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="^c@i^ci@i")) 1 2 3 4 5 """ print buf[0].a, buf[0].b, buf[0].sub.a, buf[0].sub.b, buf[0].c @testcase def complex_dtype(object[long double complex] buf): """ >>> complex_dtype(LongComplexMockBuffer(None, [(0, -1)])) -1j """ print buf[0] @testcase def complex_inplace(object[long double complex] buf): """ >>> complex_inplace(LongComplexMockBuffer(None, [(0, -1)])) (1+1j) """ buf[0] = buf[0] + 1 + 2j print buf[0] @testcase def complex_struct_dtype(object[LongComplex] buf): """ Note that the format string is "Zg" rather than "2g", yet a struct is accessed. >>> complex_struct_dtype(LongComplexMockBuffer(None, [(0, -1)])) 0.0 -1.0 """ print buf[0].real, buf[0].imag @testcase def complex_struct_inplace(object[LongComplex] buf): """ >>> complex_struct_inplace(LongComplexMockBuffer(None, [(0, -1)])) 1.0 1.0 """ buf[0].real += 1 buf[0].imag += 2 print buf[0].real, buf[0].imag # # Nogil # @testcase @cython.boundscheck(False) def buffer_nogil(): """ >>> buffer_nogil() 10 """ cdef object[int] buf = IntMockBuffer(None, [1,2,3]) with nogil: buf[1] = 10 return buf[1] @testcase def buffer_nogil_oob(): """ >>> buffer_nogil_oob() Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) """ cdef object[int] buf = IntMockBuffer(None, [1,2,3]) with nogil: buf[5] = 10 return buf[1] def get_int(): return 10 @testcase def test_inplace_assignment(): """ >>> test_inplace_assignment() 10 """ cdef object[int, ndim=1] buf = IntMockBuffer(None, [1, 2, 3]) buf[0] = get_int() print buf[0] @testcase def test_nested_assignment(): """ >>> test_nested_assignment() 100 """ cdef object[int] inner = IntMockBuffer(None, [1, 2, 3]) cdef object[int] outer = IntMockBuffer(None, [1, 2, 3]) outer[inner[0]] = 100 return outer[inner[0]] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/buffers/buffer.pyx0000644000175100001770000000236500000000000020413 0ustar00runnerdocker00000000000000__doc__ = u""" >>> b1 = TestBuffer() >>> b2 = TestBufferRelease() """ import sys if sys.version_info[0] >= 3: __doc__ += u""" >>> ms = memoryview(s) >>> ms.tobytes() b'abcdefg' >>> m1 = memoryview(b1) __getbuffer__ called Semantics changed in python 3.3 >> m1.tobytes() __getbuffer__ called b'abcdefg' >>> m2 = memoryview(b2) __getbuffer__ called Semantics changed in python 3.3 >> m2.tobytes() __getbuffer__ called releasing! b'abcdefg' >>> del m1 >>> del m2 releasing! """ s = b"abcdefg" cdef class TestBuffer: def __getbuffer__(self, Py_buffer* buffer, int flags): print u"__getbuffer__ called" buffer.buf = s buffer.obj = self buffer.len = len(s) buffer.readonly = 0 buffer.format = "B" buffer.ndim = 0 buffer.shape = NULL buffer.strides = NULL buffer.suboffsets = NULL buffer.itemsize = 1 buffer.internal = NULL cdef class TestBufferRelease(TestBuffer): def __releasebuffer__(self, Py_buffer* buffer): print u"releasing!" cdef class TestCompileWithDocstring(object): def __getbuffer__(self, Py_buffer* buffer, int flags): "I am a docstring!" def __releasebuffer__(self, Py_buffer* buf): "I am a docstring!" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/buffers/buffmt.pyx0000644000175100001770000002563400000000000020431 0ustar00runnerdocker00000000000000from __future__ import unicode_literals import struct # Tests buffer format string parsing. from libc cimport stdlib def little_endian(): cdef unsigned int n = 1 return (&n)[0] != 0 if little_endian(): current_endian = '<' other_endian = '>' else: current_endian = '>' other_endian = '<' cdef struct align_of_float_helper: char ch float d cdef struct align_of_int_helper: char ch int i float_align = sizeof(align_of_float_helper) - sizeof(float) int_align = sizeof(align_of_int_helper) - sizeof(int) if float_align != 4 or sizeof(float) != 4: raise RuntimeError("Alignment or size of float is %d on this system, please report to cython-dev for a testcase fix" % float_align) if int_align != 4 or sizeof(int) != 4: raise RuntimeError("Alignment or size of int is %d on this system, please report to cython-dev for a testcase fix" % int_align) cdef class MockBuffer: cdef Py_ssize_t zero cdef Py_ssize_t minusone cdef bytes format cdef object itemsize def __init__(self, format, itemsize): self.format = unicode(format).encode(u"ASCII") self.itemsize = itemsize self.zero = 0 self.minusone = -1 def __getbuffer__(self, Py_buffer* info, int flags): info.buf = NULL info.strides = &self.zero info.suboffsets = &self.minusone info.shape = &self.zero info.ndim = 1 info.format = self.format info.itemsize = self.itemsize def _int(fmt): """ >>> _int("i") >>> _int("b") Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'int' but got 'signed char' >>> _int("if") Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected end but got 'float' >>> _int("$$") Traceback (most recent call last): ... ValueError: Does not understand character buffer dtype format string ('$') """ cdef object[int] buf = MockBuffer(fmt, sizeof(int)) def _ulong(fmt): """ >>> _ulong("L") """ cdef object[unsigned long] buf = MockBuffer(fmt, sizeof(unsigned long)) def wrongsize(): """ >>> wrongsize() Traceback (most recent call last): ... ValueError: Item size of buffer (1 byte) does not match size of 'float' (4 bytes) """ cdef object[float] buf = MockBuffer("f", 1) def _obj(fmt): """ >>> _obj("O") >>> _obj("i") Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'Python object' but got 'int' """ cdef object[object] buf = MockBuffer(fmt, sizeof(void*)) cdef struct ComplexFloat: float real float imag ctypedef struct Char3Int: char a int b int c int d ctypedef struct LongString: char[90198] c cdef struct CharIntCFloat: char a int b ComplexFloat c float d cdef struct UnpackedStruct1: char a int b ComplexFloat c float c2 Char3Int d ctypedef struct UnpackedStruct2: CharIntCFloat a Char3Int b ctypedef struct UnpackedStruct3: CharIntCFloat a char b int c, d, e cdef struct UnpackedStruct4: char a int b ComplexFloat c float c2 char d int e, f, g def char3int(fmt): """ >>> char3int("ciii") >>> char3int("c1i1i1i") >>> char3int("c3i") >>> char3int("ci2i") >>> char3int("c@i@2i") Extra pad bytes (assuming int size is 4 or more) >>> char3int("cxiii") >>> char3int("c3xiii") >>> char3int("cxxxiii") Standard alignment (assuming int size is 4) >>> char3int("=c3xiii") >>> char3int("=ciii") Traceback (most recent call last): ... ValueError: Buffer dtype mismatch; next field is at offset 1 but 4 expected >>> char3int("=cxxx@iii") Error: >>> char3int("cii") Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'int' but got end in 'Char3Int.d' """ cdef object obj = MockBuffer(fmt, sizeof(Char3Int)) cdef object[Char3Int, ndim=1] buf = obj def long_string(fmt): """ >>> long_string("90198s") """ cdef object obj = MockBuffer(fmt, sizeof(LongString)) cdef object[LongString, ndim=1] buf = obj def unpacked_struct(fmt): """ Native formats: >>> unpacked_struct("ciZffciii") >>> unpacked_struct("@ci3fc3i") >>> unpacked_struct("@ciZffci2i") >>> unpacked_struct("ciZffT{ciii}") >>> unpacked_struct("cT{ifffc2i}i") >>> unpacked_struct("ciZffc3T{i}") >>> unpacked_struct("T{c}T{T{iZffT{ci}}}2T{T{i}}") """ assert (sizeof(UnpackedStruct1) == sizeof(UnpackedStruct2) == sizeof(UnpackedStruct3) == sizeof(UnpackedStruct4)) cdef object obj = MockBuffer(fmt, sizeof(UnpackedStruct1)) cdef object[UnpackedStruct1, ndim=1] buf1 = obj cdef object[UnpackedStruct2, ndim=1] buf2 = obj cdef object[UnpackedStruct3, ndim=1] buf3 = obj cdef object[UnpackedStruct4, ndim=1] buf4 = obj cdef struct ComplexTest: ComplexFloat a, b, c def complex_test(fmt): """ >>> complex_test("ZfZfZf") >>> complex_test("3Zf") >>> complex_test("6f") >>> complex_test("3T{Zf}") >>> complex_test("fZfZff") Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'float' but got 'complex float' in 'ComplexFloat.imag' """ cdef object obj = MockBuffer(fmt, sizeof(ComplexTest)) cdef object[ComplexTest] buf1 = obj def alignment_string(fmt, exc=None): """ >>> alignment_string("@i") >>> alignment_string("%si" % current_endian) >>> alignment_string("%si" % other_endian, "X-endian buffer not supported on X-endian compiler") >>> alignment_string("=i") """ cdef object[int] buf try: buf = MockBuffer(fmt, sizeof(int)) except ValueError, e: msg = unicode(e).replace("Big", "X").replace("Little", "X").replace("big", "X").replace("little", "X") if msg != exc: print msg print " is not equal to" print exc return if exc: print "fail" def int_and_long_are_same(): """ >>> int_and_long_are_same() """ cdef object[int] intarr cdef object[long] longarr if sizeof(int) == sizeof(long): intarr = MockBuffer("l", sizeof(int)) longarr = MockBuffer("i", sizeof(int)) cdef struct MixedComplex: double real float imag def mixed_complex_struct(): """ Triggering a specific execution path for this case. >>> mixed_complex_struct() Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'double' but got 'complex double' in 'MixedComplex.real' """ cdef object[MixedComplex] buf = MockBuffer("Zd", sizeof(MixedComplex)) cdef packed struct PackedSubStruct: char x int y cdef struct UnpackedSubStruct: char x int y cdef packed struct PackedStruct: char a int b PackedSubStruct sub cdef struct PartiallyPackedStruct: char a int b PackedSubStruct sub cdef packed struct PartiallyPackedStruct2: char a UnpackedSubStruct sub char b int c def packed_struct(fmt): """ Assuming int is four bytes: >>> packed_struct("^cici") >>> packed_struct("=cici") However aligned access won't work: >>> packed_struct("^c@i^ci") Traceback (most recent call last): ... ValueError: Buffer dtype mismatch; next field is at offset 4 but 1 expected >>> packed_struct("@cici") Traceback (most recent call last): ... ValueError: Buffer dtype mismatch; next field is at offset 4 but 1 expected """ cdef object[PackedStruct] buf = MockBuffer(fmt, sizeof(PackedStruct)) def partially_packed_struct(fmt): """ Assuming int is four bytes: >>> partially_packed_struct("^c@i^ci") >>> partially_packed_struct("@ci^ci") >>> partially_packed_struct("^c@i=ci") >>> partially_packed_struct("@ci=ci") >>> partially_packed_struct("ci^ci") >>> partially_packed_struct("ci=ci") Incorrectly aligned accesses won't work: >>> partially_packed_struct("^cici") Traceback (most recent call last): ... ValueError: Buffer dtype mismatch; next field is at offset 1 but 4 expected >>> partially_packed_struct("=cibi") Traceback (most recent call last): ... ValueError: Buffer dtype mismatch; next field is at offset 1 but 4 expected """ cdef object[PartiallyPackedStruct] buf = MockBuffer( fmt, sizeof(PartiallyPackedStruct)) def partially_packed_struct_2(fmt): """ Assuming int is four bytes: >>> partially_packed_struct_2("^ccxxxici") >>> partially_packed_struct_2("^ccxxxi^ci") >>> partially_packed_struct_2("c=cxxxi^ci") >>> partially_packed_struct_2("c^cxxxi^ci") >>> partially_packed_struct_2("c^cxxxi=ci") >>> partially_packed_struct_2("ccxxx^i@c^i") Incorrectly aligned accesses won't work: >>> partially_packed_struct_2("ccxxxici") Traceback (most recent call last): ... ValueError: Buffer dtype mismatch; next field is at offset 8 but 5 expected >>> partially_packed_struct_2("ccici") Traceback (most recent call last): ... ValueError: Buffer dtype mismatch; next field is at offset 4 but 5 expected """ cdef object[PartiallyPackedStruct2] buf = MockBuffer( fmt, sizeof(PartiallyPackedStruct2)) cdef packed struct PackedStructWithCharArrays: float a int b char[5] c char[3] d def packed_struct_with_strings(fmt): """ >>> packed_struct_with_strings("T{f:a:i:b:5s:c:3s:d:}") """ cdef object[PackedStructWithCharArrays] buf = MockBuffer( fmt, sizeof(PackedStructWithCharArrays)) ctypedef struct PackedStructWithArrays: double a[16] double b[16] double c ctypedef struct UnpackedStructWithArrays: int a float b[8] float c unsigned long long d int e[5] int f int g double h[4] int i ctypedef struct PackedStructWithNDArrays: double a double b[2][2] float c float d def packed_struct_with_arrays(fmt): """ >>> packed_struct_with_arrays("T{(16)d:a:(16)d:b:d:c:}") """ cdef object[PackedStructWithArrays] buf = MockBuffer( fmt, sizeof(PackedStructWithArrays)) def unpacked_struct_with_arrays(fmt): """ >>> if struct.calcsize('P') == 8: # 64 bit ... unpacked_struct_with_arrays("T{i:a:(8)f:b:f:c:Q:d:(5)i:e:i:f:i:g:xxxx(4)d:h:i:i:}") ... elif struct.calcsize('P') == 4: # 32 bit ... unpacked_struct_with_arrays("T{i:a:(8)f:b:f:c:Q:d:(5)i:e:i:f:i:g:(4)d:h:i:i:}") """ cdef object[UnpackedStructWithArrays] buf = MockBuffer( fmt, sizeof(UnpackedStructWithArrays)) def packed_struct_with_ndarrays(fmt): """ >>> packed_struct_with_ndarrays("T{d:a:(2,2)d:b:f:c:f:d:}") """ cdef object[PackedStructWithNDArrays] buf = MockBuffer( fmt, sizeof(PackedStructWithNDArrays)) # TODO: empty struct # TODO: Incomplete structs # TODO: mixed structs ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/buffers/mockbuffers.pxi0000644000175100001770000002621700000000000021432 0ustar00runnerdocker00000000000000from libc cimport stdlib cimport cpython.buffer import sys available_flags = ( ('FORMAT', cpython.buffer.PyBUF_FORMAT), ('INDIRECT', cpython.buffer.PyBUF_INDIRECT), ('ND', cpython.buffer.PyBUF_ND), ('STRIDES', cpython.buffer.PyBUF_STRIDES), ('C_CONTIGUOUS', cpython.buffer.PyBUF_C_CONTIGUOUS), ('F_CONTIGUOUS', cpython.buffer.PyBUF_F_CONTIGUOUS), ('WRITABLE', cpython.buffer.PyBUF_WRITABLE) ) cdef class MockBuffer: cdef object format, offset cdef void* buffer cdef Py_ssize_t len, itemsize cdef Py_ssize_t* strides cdef Py_ssize_t* shape cdef Py_ssize_t* suboffsets cdef object label, log cdef int ndim cdef bint writable cdef readonly object received_flags, release_ok cdef public object fail def __init__(self, label, data, shape=None, strides=None, format=None, writable=True, offset=0): # It is important not to store references to data after the constructor # as refcounting is checked on object buffers. cdef Py_ssize_t x, s, cumprod, itemsize self.label = label self.release_ok = True self.log = u"" self.offset = offset self.itemsize = itemsize = self.get_itemsize() self.writable = writable if format is None: format = self.get_default_format() if shape is None: shape = (len(data),) if strides is None: strides = [] cumprod = 1 for s in shape[::-1]: strides.append(cumprod) cumprod *= s strides.reverse() strides = [x * itemsize for x in strides] suboffsets = [-1] * len(shape) datashape = [len(data)] p = data while True: p = p[0] if isinstance(p, list): datashape.append(len(p)) else: break if len(datashape) > 1: # indirect access self.ndim = len(datashape) shape = datashape self.buffer = self.create_indirect_buffer(data, shape) suboffsets = [0] * self.ndim suboffsets[-1] = -1 strides = [sizeof(void*)] * self.ndim strides[-1] = itemsize self.suboffsets = self.list_to_sizebuf(suboffsets) else: # strided and/or simple access self.buffer = self.create_buffer(data) self.ndim = len(shape) self.suboffsets = NULL try: format = format.encode('ASCII') except AttributeError: pass self.format = format self.len = len(data) * itemsize self.strides = self.list_to_sizebuf(strides) self.shape = self.list_to_sizebuf(shape) def __dealloc__(self): stdlib.free(self.strides) stdlib.free(self.shape) if self.suboffsets != NULL: stdlib.free(self.suboffsets) # must recursively free indirect... else: stdlib.free(self.buffer) cdef void* create_buffer(self, data) except NULL: cdef size_t n = (len(data) * self.itemsize) cdef char* buf = stdlib.malloc(n) if buf == NULL: raise MemoryError cdef char* it = buf for value in data: self.write(it, value) it += self.itemsize return buf cdef void* create_indirect_buffer(self, data, shape) except NULL: cdef size_t n = 0 cdef void** buf assert shape[0] == len(data), (shape[0], len(data)) if len(shape) == 1: return self.create_buffer(data) else: shape = shape[1:] n = len(data) * sizeof(void*) buf = stdlib.malloc(n) if buf == NULL: return NULL for idx, subdata in enumerate(data): buf[idx] = self.create_indirect_buffer(subdata, shape) return buf cdef Py_ssize_t* list_to_sizebuf(self, l): cdef Py_ssize_t i, x cdef size_t n = len(l) * sizeof(Py_ssize_t) cdef Py_ssize_t* buf = stdlib.malloc(n) for i, x in enumerate(l): buf[i] = x return buf def __getbuffer__(MockBuffer self, Py_buffer* buffer, int flags): if self.fail: raise ValueError("Failing on purpose") self.received_flags = [] cdef int value for name, value in available_flags: if (value & flags) == value: self.received_flags.append(name) if flags & cpython.buffer.PyBUF_WRITABLE and not self.writable: raise BufferError(f"Writable buffer requested from read-only mock: {' | '.join(self.received_flags)}") buffer.buf = (self.buffer + (self.offset * self.itemsize)) buffer.obj = self buffer.len = self.len buffer.readonly = not self.writable buffer.format = self.format buffer.ndim = self.ndim buffer.shape = self.shape buffer.strides = self.strides buffer.suboffsets = self.suboffsets buffer.itemsize = self.itemsize buffer.internal = NULL if self.label: msg = f"acquired {self.label}" print(msg) self.log += msg + u"\n" def __releasebuffer__(MockBuffer self, Py_buffer* buffer): if buffer.suboffsets != self.suboffsets: self.release_ok = False if self.label: msg = f"released {self.label}" print(msg) self.log += msg + u"\n" def printlog(self): print(self.log[:-1]) def resetlog(self): self.log = u"" cdef int write(self, char* buf, object value) except -1: raise Exception() cdef get_itemsize(self): print(f"ERROR, not subclassed: {self.__class__}") cdef get_default_format(self): print(f"ERROR, not subclassed {self.__class__}") cdef class CharMockBuffer(MockBuffer): cdef int write(self, char* buf, object value) except -1: (buf)[0] = value return 0 cdef get_itemsize(self): return sizeof(char) cdef get_default_format(self): return b"@b" cdef class IntMockBuffer(MockBuffer): cdef int write(self, char* buf, object value) except -1: (buf)[0] = value return 0 cdef get_itemsize(self): return sizeof(int) cdef get_default_format(self): return b"@i" cdef class UnsignedIntMockBuffer(MockBuffer): cdef int write(self, char* buf, object value) except -1: (buf)[0] = value return 0 cdef get_itemsize(self): return sizeof(unsigned int) cdef get_default_format(self): return b"@I" cdef class ShortMockBuffer(MockBuffer): cdef int write(self, char* buf, object value) except -1: (buf)[0] = value return 0 cdef get_itemsize(self): return sizeof(short) cdef get_default_format(self): return b"h" # Try without endian specifier cdef class UnsignedShortMockBuffer(MockBuffer): cdef int write(self, char* buf, object value) except -1: (buf)[0] = value return 0 cdef get_itemsize(self): return sizeof(unsigned short) cdef get_default_format(self): return b"@1H" # Try with repeat count cdef class FloatMockBuffer(MockBuffer): cdef int write(self, char* buf, object value) except -1: (buf)[0] = (value) return 0 cdef get_itemsize(self): return sizeof(float) cdef get_default_format(self): return b"f" cdef class DoubleMockBuffer(MockBuffer): cdef int write(self, char* buf, object value) except -1: (buf)[0] = value return 0 cdef get_itemsize(self): return sizeof(double) cdef get_default_format(self): return b"d" cdef extern from *: void* addr_of_pyobject "(void*)"(object) cdef class ObjectMockBuffer(MockBuffer): cdef int write(self, char* buf, object value) except -1: (buf)[0] = addr_of_pyobject(value) return 0 cdef get_itemsize(self): return sizeof(void*) cdef get_default_format(self): return b"@O" cdef class IntStridedMockBuffer(IntMockBuffer): cdef __cythonbufferdefaults__ = {"mode" : "strided"} cdef class ErrorBuffer: cdef object label def __init__(self, label): self.label = label def __getbuffer__(ErrorBuffer self, Py_buffer* buffer, int flags): raise Exception(f"acquiring {self.label}") def __releasebuffer__(ErrorBuffer self, Py_buffer* buffer): raise Exception(f"releasing {self.label}") # # Structs # cdef struct MyStruct: signed char a signed char b long long int c int d int e cdef struct SmallStruct: int a int b cdef struct NestedStruct: SmallStruct x SmallStruct y int z cdef packed struct PackedStruct: signed char a int b cdef struct NestedPackedStruct: signed char a int b PackedStruct sub int c cdef class MyStructMockBuffer(MockBuffer): cdef int write(self, char* buf, object value) except -1: cdef MyStruct* s s = buf s.a, s.b, s.c, s.d, s.e = value return 0 cdef get_itemsize(self): return sizeof(MyStruct) cdef get_default_format(self): return b"2cq2i" cdef class NestedStructMockBuffer(MockBuffer): cdef int write(self, char* buf, object value) except -1: cdef NestedStruct* s s = buf s.x.a, s.x.b, s.y.a, s.y.b, s.z = value return 0 cdef get_itemsize(self): return sizeof(NestedStruct) cdef get_default_format(self): return b"2T{ii}i" cdef class PackedStructMockBuffer(MockBuffer): cdef int write(self, char* buf, object value) except -1: cdef PackedStruct* s s = buf s.a, s.b = value return 0 cdef get_itemsize(self): return sizeof(PackedStruct) cdef get_default_format(self): return b"^ci" cdef class NestedPackedStructMockBuffer(MockBuffer): cdef int write(self, char* buf, object value) except -1: cdef NestedPackedStruct* s s = buf s.a, s.b, s.sub.a, s.sub.b, s.c = value return 0 cdef get_itemsize(self): return sizeof(NestedPackedStruct) cdef get_default_format(self): return b"ci^ci@i" cdef struct LongComplex: long double real long double imag cdef class LongComplexMockBuffer(MockBuffer): cdef int write(self, char* buf, object value) except -1: cdef LongComplex* s s = buf s.real, s.imag = value return 0 cdef get_itemsize(self): return sizeof(LongComplex) cdef get_default_format(self): return b"Zg" def print_offsets(*args, size, newline=True): sys.stdout.write(' '.join([str(item // size) for item in args]) + ('\n' if newline else '')) def print_int_offsets(*args, newline=True): print_offsets(*args, size=sizeof(int), newline=newline) shape_5_3_4_list = [[list(range(k * 12 + j * 4, k * 12 + j * 4 + 4)) for j in range(3)] for k in range(5)] stride1 = 21 * 14 stride2 = 21 shape_9_14_21_list = [[list(range(k * stride1 + j * stride2, k * stride1 + j * stride2 + 21)) for j in range(14)] for k in range(9)] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/buffers/userbuffer.pyx0000644000175100001770000000353300000000000021310 0ustar00runnerdocker00000000000000 __doc__ = u""" >>> b1 = UserBuffer1() >>> m1 = memoryview(b1) >>> m1.tolist() [0, 1, 2, 3, 4] >>> del m1, b1 >>> b2 = UserBuffer2() >>> m2 = memoryview(b2) UserBuffer2: getbuffer >>> m2.tolist() [5, 6, 7, 8, 9] >>> del m2, b2 UserBuffer2: release """ cdef extern from *: ctypedef struct Py_buffer # redeclared enum: PyBUF_SIMPLE int PyBuffer_FillInfo(Py_buffer *, object, void *, Py_ssize_t, bint, int) except -1 int PyObject_GetBuffer(object, Py_buffer *, int) except -1 void PyBuffer_Release(Py_buffer *) cdef char global_buf[5] global_buf[0:5] = [0, 1, 2, 3, 4] cdef class UserBuffer1: def __getbuffer__(self, Py_buffer* view, int flags): PyBuffer_FillInfo(view, None, global_buf, 5, 1, flags) cdef class UserBuffer2: cdef char buf[5] def __cinit__(self): self.buf[0:5] = [5, 6, 7, 8, 9] def __getbuffer__(self, Py_buffer* view, int flags): print('UserBuffer2: getbuffer') PyBuffer_FillInfo(view, self, self.buf, 5, 0, flags) def __releasebuffer__(self, Py_buffer* view): print('UserBuffer2: release') cdef extern from *: ctypedef struct PyBuffer"Py_buffer": void *buf Py_ssize_t len bint readonly cdef class _memoryview: """ Memory """ cdef PyBuffer view def __cinit__(self, obj): cdef Py_buffer *view = &self.view PyObject_GetBuffer(obj, view, PyBUF_SIMPLE) def __dealloc__(self): cdef Py_buffer *view = &self.view PyBuffer_Release(view ) def __getbuffer__(self, Py_buffer *view, int flags): PyBuffer_FillInfo(view, self, self.view.buf, self.view.len, self.view.readonly, flags) def tolist(self): cdef char *b = self.view.buf return [b[i] for i in range(self.view.len)] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/bugs.txt0000644000175100001770000000305700000000000016444 0ustar00runnerdocker00000000000000# This file contains tests corresponding to unresolved bugs, # which will be skipped in the normal testing run. setuptools_reimport class_attribute_init_values_T18 unsignedbehaviour_T184 missing_baseclass_in_predecl_T262 cfunc_call_tuple_args_T408 generator_expressions_in_class for_from_pyvar_loop_T601 temp_sideeffects_T654 # not really a bug, Cython warns about it inherited_final_method cimport_alias_subclass # PEP-489 is currently disabled run.mod__spec__ # CPython regression tests that don't current work: pyregr.test_signal pyregr.test_capi pyregr.test_socket pyregr.test_sys pyregr.test_pep3131 pyregr.test_multiprocessing pyregr.test_tempfile pyregr.test_ioctl # CPython regression tests with threading issues pyregr.test_threadsignals pyregr.test_threading pyregr.test_threaded_import pyregr.test_logging # CPython regression tests that don't make sense pyregr.test_gdb pyregr.test_support pyregr.test_peepholer # the atexit test runs the registered atexit functions => module cleanup => crash pyregr.test_atexit # a settrace test bypasses a with statement and currently crashes pyregr.test_sys_settrace # tests for exception on infinite recursion - may crash with stack overflow when calling C function pyregr.test_exceptions # CPython regression tests that take too long pyregr.test_subprocess pyregr.test_zipfile64 pyregr.test_tuple pyregr.test_urllib2net pyregr.test_urllibnet # Inlined generators inlined_generator_expressions # crash in C++ on i686 (possibly others?) # See https://github.com/cython/cython/issues/5768 gil_in_var_initialization_tests ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.076724 Cython-3.0.8/tests/build/0000755000175100001770000000000000000000000016035 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/basic_cythonize.srctree0000644000175100001770000000041400000000000022602 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "import a" ######## setup.py ######## # TODO: Better interface... from Cython.Build.Dependencies import cythonize from distutils.core import setup setup( ext_modules = cythonize("*.pyx"), ) ######## a.pyx ######## ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/basic_distutils.srctree0000644000175100001770000000050000000000000022606 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "import a" ######## setup.py ######## from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext setup( cmdclass = {'build_ext': build_ext}, ext_modules = [Extension("a", ["a.pyx"])], ) ######## a.pyx ######## ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/build_dir.srctree0000644000175100001770000000357300000000000021373 0ustar00runnerdocker00000000000000PYTHON symlink_or_copy.py subdir fake PYTHON setup.py build_ext --inplace PYTHON -c "import a" PYTHON -c "import pkg.b" PYTHON check_paths.py ######## symlink_or_copy.py ######## import platform import sys if platform.system() == "Windows": import shutil shutil.copytree(sys.argv[1], sys.argv[2]) else: import os os.symlink(sys.argv[1], sys.argv[2]) ######## setup.py ######## # TODO: Better interface... from Cython.Build.Dependencies import cythonize from distutils.core import setup setup( ext_modules = (cythonize("*.pyx", build_dir="scratchA") + cythonize("pkg/*.pyx", build_dir="scratchB")), ) ######## a.pyx ######## cdef extern from "helper.h": int value1 cdef extern from "subdir/helper.h": int value2 cdef extern from "pkg/pkg_helper.h": int value3 assert value1 == 100 assert value2 == 200 assert value3 == 300 ######## helper.h ######## int value1 = 100; ######## subdir/helper.h ######## int value2 = 200; ######## pkg/__init__.py ######## ######## pkg/b.pyx ######## cdef extern from "../fake/helper.h": int value2 cdef extern from "pkg_helper.h": int value3 cdef extern from "subdir/pkg_helper.h": int value4 assert value2 == 200 assert value3 == 300 assert value4 == 400 ######## pkg/pkg_helper.h ######## int value3 = 300; ######## pkg/subdir/pkg_helper.h ######## int value4 = 400; ######## check_paths.py ######## import os assert os.path.exists("scratchA/a.c") assert os.path.exists("scratchA/helper.h") assert os.path.exists("scratchA/subdir/helper.h") assert os.path.exists("scratchA/pkg/pkg_helper.h") assert not os.path.exists("a.c") assert os.path.exists("scratchB/pkg/b.c") assert os.path.exists("scratchB/pkg/pkg_helper.h") assert os.path.exists("scratchB/pkg/subdir/pkg_helper.h") assert os.path.exists("scratchB/fake/helper.h") assert not os.path.exists("b.c") assert not os.path.exists("pkg/b.c") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/build_dir_src.srctree0000644000175100001770000000403300000000000022232 0ustar00runnerdocker00000000000000# Mostly the same test as build_dir.srctree but with everything inside # a common "src" directory. We don't use --inplace and don't actually # import the built modules. PYTHON shutil_copy.py src/subdir src/fake PYTHON setup.py build_ext PYTHON check_paths.py ######## shutil_copy.py ######## import shutil, sys shutil.copytree(sys.argv[1], sys.argv[2]) ######## setup.py ######## from Cython.Build.Dependencies import cythonize from Cython.Distutils.extension import Extension from distutils.core import setup ext_modules = cythonize( Extension("a", ["src/a.pyx"]), build_dir="scratchA") ext_modules += cythonize( Extension("pkg.b", ["src/pkg/b.pyx"]), build_dir="scratchB") setup(ext_modules=ext_modules) ######## src/a.pyx ######## cdef extern from "helper.h": int value1 cdef extern from "subdir/helper.h": int value2 cdef extern from "pkg/pkg_helper.h": int value3 assert value1 == 100 assert value2 == 200 assert value3 == 300 ######## src/helper.h ######## int value1 = 100; ######## src/subdir/helper.h ######## int value2 = 200; ######## src/pkg/__init__.py ######## ######## src/pkg/b.pyx ######## cdef extern from "../fake/helper.h": int value2 cdef extern from "pkg_helper.h": int value3 cdef extern from "subdir/pkg_helper.h": int value4 assert value2 == 200 assert value3 == 300 assert value4 == 400 ######## src/pkg/pkg_helper.h ######## int value3 = 300; ######## src/pkg/subdir/pkg_helper.h ######## int value4 = 400; ######## check_paths.py ######## import os assert os.path.exists("scratchA/src/a.c") assert os.path.exists("scratchA/src/helper.h") assert os.path.exists("scratchA/src/subdir/helper.h") assert os.path.exists("scratchA/src/pkg/pkg_helper.h") assert not os.path.exists("src/a.c") assert os.path.exists("scratchB/src/pkg/b.c") assert os.path.exists("scratchB/src/pkg/pkg_helper.h") assert os.path.exists("scratchB/src/pkg/subdir/pkg_helper.h") assert os.path.exists("scratchB/src/fake/helper.h") assert not os.path.exists("src/b.c") assert not os.path.exists("src/pkg/b.c") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/build_ext_cython_c_in_temp.srctree0000644000175100001770000000120200000000000025001 0ustar00runnerdocker00000000000000 PYTHON setup.py build_ext --inplace --cython-c-in-temp PYTHON -c 'import mymodule; assert mymodule.test_string == "TEST"' PYTHON check_paths.py ############# setup.py ############# from Cython.Distutils.extension import Extension from Cython.Build import build_ext from distutils.core import setup setup( name='Hello world app', ext_modules = [ Extension( name = 'mymodule', sources=['mymodule.pyx'], ) ], cmdclass={'build_ext': build_ext}, ) ######## mymodule.pyx ######## test_string = "TEST" ######## check_paths.py ######## import os assert not os.path.exists("mymodule.c") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/build_ext_cython_cplus.srctree0000644000175100001770000000122200000000000024174 0ustar00runnerdocker00000000000000# tag: cpp PYTHON setup.py build_ext --inplace --cython-cplus PYTHON -c "import a; a.use_vector([1,2,3])" ######## setup.py ######## from Cython.Distutils.extension import Extension from Cython.Build import build_ext from distutils.core import setup setup( name='Hello world app', ext_modules = [ Extension( name = 'a', sources=['a.pyx'], ) ], cmdclass={'build_ext': build_ext}, ) ######## a.pyx ######## from libcpp.vector cimport vector def use_vector(L): try: v = new vector[int]() for a in L: v.push_back(a) return v.size() finally: del v ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/build_ext_cython_include_dirs.srctree0000644000175100001770000000240500000000000025516 0ustar00runnerdocker00000000000000 PYTHON setup.py build_ext --inplace --cython-include-dirs=./headers1 --include-dirs=./headers2 PYTHON -c 'import mymodule; assert mymodule.test_string == "TEST"; assert mymodule.header_value1 == 1; assert mymodule.header_value2 == 2; assert mymodule.header_value3 == 3; assert mymodule.header_value4 == 4' ############# setup.py ############# from Cython.Distutils.extension import Extension from Cython.Build import build_ext from distutils.core import setup setup( name='Hello world app', ext_modules = [ Extension( name = 'mymodule', sources=['mymodule.pyx'], cython_include_dirs=['headers3'], include_dirs=['./headers4'] ) ], cmdclass={'build_ext': build_ext}, ) ######## mymodule.pyx ######## include "myheader1.pxi" include "myheader2.pxi" include "myheader3.pxi" include "myheader4.pxi" header_value1 = test_value1 header_value2 = test_value2 header_value3 = test_value3 header_value4 = test_value4 test_string = "TEST" ######## headers1/myheader1.pxi ######## cdef int test_value1 = 1 ######## headers2/myheader2.pxi ######## cdef int test_value2 = 2 ######## headers3/myheader3.pxi ######## cdef int test_value3 = 3 ######## headers4/myheader4.pxi ######## cdef int test_value4 = 4 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/common_include_dir.srctree0000644000175100001770000000427700000000000023271 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "import runner" # Verify some files were created. # ls common/AddTraceback_impl*.h common/RaiseException_impl_*.h PYTHON -c "import glob; assert glob.glob('common/AddTraceback_impl*.h')" PYTHON -c "import glob; assert glob.glob('common/RaiseException_impl_*.h')" # Verify that they're used. PYTHON fake_grep.py -c '#include "common/AddTraceback_impl_.*h"' a.c PYTHON fake_grep.py -c '#include "common/AddTraceback_impl_.*h"' b.c PYTHON fake_grep.py -c '#include "common/AddTraceback_impl_.*h"' c.c ######## setup.py ######## import sys from Cython.Build.Dependencies import cythonize import os from distutils.core import setup # os x on CI specifically seems to crash with nthreads>0 osx_on_ci = (sys.platform == "darwin" and os.getenv("CI")) # Test concurrent safety if multiprocessing is available. # (In particular, CI providers like Travis and Github Actions do not support spawning processes from tests.) nthreads = 0 if not (hasattr(sys, 'pypy_version_info') or (hasattr(sys, 'implementation') and sys.implementation.name == 'graalpython') or osx_on_ci): try: import multiprocessing multiprocessing.Pool(2).close() nthreads = 2 except (ImportError, OSError): pass setup( ext_modules = cythonize("*.pyx", common_utility_include_dir='common', nthreads=nthreads), ) ######## a.pyx ######## def generator(n): for k in range(n): yield k assert list(generator(10)) == list(range(10)) ######## b.pyx ######## def generator(n): for k in range(n): yield k assert list(generator(10)) == list(range(10)) if __name__ == "__main__": print("here b") ######## c.pyx ######## if __name__ == "__main__": print("here c") ######## runner.py ######## import a, b, c ######## fake_grep.py ######## import re import sys if sys.platform == 'win32': opt, pattern, file = sys.argv[1:] assert opt == '-c' count = 0 regex = re.compile(pattern) with open(file) as fid: for line in fid: if regex.search(line): count += 1 print(count) sys.exit(count == 0) else: import subprocess sys.exit(subprocess.call(['grep'] + sys.argv[1:])) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/compile_env_distutils.srctree0000644000175100001770000000101700000000000024031 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "import a; import sys; sys.exit(a.compile_env_test())" ######## setup.py ######## from distutils.core import setup from Cython.Distutils.extension import Extension from Cython.Distutils.old_build_ext import old_build_ext setup( cmdclass = {'build_ext': old_build_ext}, ext_modules = [Extension( "a", ["a.pyx"], pyrex_compile_time_env = {'TEST': True}, )], ) ######## a.pyx ######## def compile_env_test(): IF TEST: return 0 ELSE: return 1 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/cpp_cythonize.srctree0000644000175100001770000000075700000000000022315 0ustar00runnerdocker00000000000000# tag: cpp PYTHON setup.py build_ext --inplace PYTHON -c "import a; a.use_vector([1,2,3])" ######## setup.py ######## from Cython.Build.Dependencies import cythonize from distutils.core import setup setup( ext_modules = cythonize("*.pyx"), ) ######## a.pyx ######## # distutils: language=c++ from libcpp.vector cimport vector def use_vector(L): try: v = new vector[int]() for a in L: v.push_back(a) return v.size() finally: del v ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/cython_language_level.srctree0000644000175100001770000000063500000000000023770 0ustar00runnerdocker00000000000000# The test is checking the combination of passing command-line compiler directives # and language level to make sure that language level is preserved. The test # is designed to fail when language_level isn't 3 due to fstring # being unicode and str being ambiguous. CYTHON -3 foo.pyx CYTHON -3 -X always_allow_keywords=true foo.pyx ######## foo.pyx ######## def join(a: str, b: str) -> str: return f'{a}{b}' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/cythonize_additional_sources.srctree0000644000175100001770000000077200000000000025403 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "import a; assert a.test() == 43" ######## setup.py ######## from Cython.Build.Dependencies import cythonize from distutils.core import setup setup( ext_modules = cythonize("*.pyx"), ) ######## a.pyx ######## # distutils: sources=alib.c cdef extern from "alib.h": int c_function(int x) def test(): return c_function(42) ######## alib.c ######## int c_function(int x) { return x + 1; } ######## alib.h ######## int c_function(int x); ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/cythonize_additional_sources_ext.srctree0000644000175100001770000000120700000000000026255 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "from pkg import a; assert a.test() == 43" ######## setup.py ######## from Cython.Build import cythonize from distutils.core import setup, Extension extensions = [ Extension('pkg.a', sources=['pkg/a.pyx', 'pkg/alib.c'], include_dirs=['pkg']) ] setup( ext_modules = cythonize(extensions) ) ######## pkg/__init__.py ######## ######## pkg/a.pyx ######## cdef extern from "alib.h": int c_function(int x) def test(): return c_function(42) ######## pkg/alib.c ######## int c_function(int x) { return x + 1; } ######## pkg/alib.h ######## int c_function(int x); ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/cythonize_cython.srctree0000644000175100001770000000336300000000000023033 0ustar00runnerdocker00000000000000PYTHON -c "import cythonize_tests" PYTHON -c "import cython_tests" ######## cythonize_tests.py ######## from Cython.Build.Cythonize import main as cythonize for test_case in ["cython.pyx", "src2/cython.pyx", "src/cython/helper.pyx"]: try: cythonize([test_case]) except ValueError: pass else: assert False, "ValueError not raised - forbidding cythonize "+test_case+" doesn't work" for test_case in ["notcython.pyx", "my_module/cython.pyx", "cythontest/helper.pyx"]: try: cythonize([test_case]) except ValueError: assert False, "ValueError raised - cythonize "+test_case+" should work" else: pass ######## cython_tests.py ######## from Cython.Compiler.Main import main as cython import sys for test_case in ["cython.pyx", "src2/cython.pyx", "src/cython/helper.pyx"]: sys.argv=["cython", test_case] #cython.py will extract parameters from sys.argv try: cython(command_line=1) except ValueError: pass else: assert False, "ValueError not raised - forbidding cython "+test_case+" doesn't work" for test_case in ["notcython.pyx", "my_module/cython.pyx", "cythontest/helper.pyx"]: sys.argv=["cython", test_case] #cython.py will extract parameters from sys.argv try: cython([test_case]) except ValueError: assert False, "ValueError raised - cython "+test_case+" should work" else: pass ######## cython.pyx ######## ######## my_module/__init__.py ######## ######## my_module/cython.pyx ######## ######## notcython.pyx ######## ######## src2/cython.pyx ######## ######## src/cython/__init__.py ######## ######## src/cython/helper.pyx ######## ######## cythontest/__init__.py ######## ######## cythontest/helper.pyx ######## ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/cythonize_glob.srctree0000644000175100001770000000124300000000000022445 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "import runner" ######## setup.py ######## from Cython.Build.Dependencies import cythonize from distutils.core import setup setup( ext_modules = cythonize("**/a*.pyx", include_path=['subdir'], compiler_directives={'cdivision': True}), ) ######## a.pyx ######## ######## p1/__init__.py ######## ######## p1/a.pyx ######## ######## p1/ab.pyx ######## ######## p1/b.pyx ######## ######## p1/p2/__init__.py ######## ######## p1/p2/a.pyx ######## ######## runner.py ######## import a import p1.a import p1.ab import p1.p2.a try: import p1.b assert False, "b should not be complied" except ImportError: pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/cythonize_newer_files.srctree0000644000175100001770000000453600000000000024034 0ustar00runnerdocker00000000000000""" PYTHON test.py """ ######## a.pyx ######## ######## test.py ######## import os.path import time from Cython.Utils import GENERATED_BY_MARKER_BYTES, clear_function_caches, clear_method_caches from Cython.Build.Dependencies import cythonize, DependencyTree import Cython.Build.Dependencies getmtime = os.path.getmtime def wait_for_newer_mtime(filename, old_mtime): mtime = old_mtime while mtime <= old_mtime: os.utime(filename, None) mtime = getmtime(filename) return mtime # test the mtime waiting itself with open("test_file.txt", 'wb') as f: pass orig_mtime = getmtime("test_file.txt") wait_for_newer_mtime("test_file.txt", orig_mtime) assert orig_mtime < getmtime("test_file.txt") def fresh_cythonize(*args): clear_function_caches() clear_method_caches(DependencyTree.timestamp) Cython.Build.Dependencies._dep_tree = None cythonize(*args) assert not os.path.exists("a.c") # new fresh_cythonize("*.pyx") assert os.path.isfile("a.c") mtime = getmtime("a.c") # already exists fresh_cythonize("*.pyx") assert mtime == getmtime("a.c") # outdated wait_for_newer_mtime("a.pyx", mtime) assert mtime < getmtime("a.pyx") fresh_cythonize("*.pyx") new_mtime = getmtime("a.c") assert mtime < new_mtime # now up to date fresh_cythonize("*.pyx") assert new_mtime == getmtime("a.c") # different Cython version (even though newer) marker = b"/* Generated by Cython " assert GENERATED_BY_MARKER_BYTES.startswith(marker) # safety belt with open("a.c", "rb") as f: content = f.read() assert content.startswith(GENERATED_BY_MARKER_BYTES) content = marker + b"123" + content[len(marker):] with open("a.c", "wb") as f: f.write(content) wait_for_newer_mtime("a.c", new_mtime) other_cython_mtime = getmtime("a.c") assert mtime < new_mtime < other_cython_mtime fresh_cythonize("*.pyx") latest_mtime = getmtime("a.c") assert mtime < new_mtime < other_cython_mtime <= latest_mtime with open("a.c", "rb") as f: assert f.read(len(GENERATED_BY_MARKER_BYTES)) == GENERATED_BY_MARKER_BYTES # file was rewritten # now up to date fresh_cythonize("*.pyx") assert mtime < new_mtime < other_cython_mtime <= latest_mtime == getmtime("a.c") # force regeneration with environment variable os.environ["CYTHON_FORCE_REGEN"] = "1" time.sleep(0.1) assert latest_mtime == getmtime("a.c") fresh_cythonize("*.pyx") assert latest_mtime < getmtime("a.c") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/cythonize_options.srctree0000644000175100001770000000207000000000000023214 0ustar00runnerdocker00000000000000# mode: run PYTHON setup.py build_ext --inplace PYTHON -c "import a" ######## setup.py ######## from Cython.Build.Dependencies import cythonize import sys from distutils.core import setup try: # io.StringIO cannot handle 'str' in Py2 from StringIO import StringIO except ImportError: from io import StringIO old_stderr = sys.stderr captured = sys.stderr = StringIO() try: setup( ext_modules = cythonize( "*.pyx", include_path=['subdir'], compiler_directives={'cdivision': True}, show_all_warnings=True, ), ) output = sys.stderr.getvalue() finally: sys.stderr = old_stderr sys.stderr.write(captured.getvalue()) assert "Unraisable exception in function" in output, output ######## subdir/x.pxd ######## ######## subdir/y.pxi ######## ######## a.pyx ######## cimport x include "y.pxi" # cdivision from setup.py def mod_int_c(int a, int b): return a % b assert mod_int_c(-1, 10) < 0 # unraisable exceptions should produce a warning cdef int no_exc_propagate() noexcept: raise TypeError() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/cythonize_pep420_namespace.srctree0000644000175100001770000000164300000000000024554 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "import runner" ######## setup.py ######## from Cython.Build.Dependencies import cythonize from distutils.core import setup, Extension setup( ext_modules=cythonize([ Extension("nsp.m1.a", ["nsp/m1/a.pyx"]), Extension("nsp.m2.b", ["nsp/m2/b.pyx"]), Extension("nsp.m3.c.d", ["nsp/m3/c/d.pyx"]), ]), ) ######## nsp/m1/__init__.py ######## ######## nsp/m1/a.pyx ######## cdef class A: pass ######## nsp/m1/a.pxd ######## cdef class A: pass ######## nsp/m2/__init__.py ######## ######## nsp/m2/b.pyx ######## from nsp.m1.a cimport A from nsp.m3.c.d cimport D cdef class B(A): pass ######## nsp/m3/__init__.py ######## ######## nsp/m3/c/d.pyx ######## cdef class D: pass ######## nsp/m3/c/d.pxd ######## cdef class D: pass ######## runner.py ######## from nsp.m1.a import A from nsp.m2.b import B from nsp.m3.c.d import D a = A() b = B() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/cythonize_rename_ext.srctree0000644000175100001770000000120700000000000023651 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "from pkg import b; assert b.test() == 43" ######## setup.py ######## from Cython.Build import cythonize from distutils.core import setup, Extension extensions = [ Extension('pkg.b', sources=['pkg/a.pyx', 'pkg/alib.c'], include_dirs=['pkg']) ] setup( ext_modules = cythonize(extensions) ) ######## pkg/__init__.py ######## ######## pkg/a.pyx ######## cdef extern from "alib.h": int c_function(int x) def test(): return c_function(42) ######## pkg/alib.c ######## int c_function(int x) { return x + 1; } ######## pkg/alib.h ######## int c_function(int x); ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/cythonize_script.srctree0000644000175100001770000000160700000000000023032 0ustar00runnerdocker00000000000000''' PYTHON -m Cython.Build.Cythonize -i '**/*_test.py' PYTHON -c "import cy_test; assert cy_test.TEST == 'cy_test', cy_test.TEST; assert not cy_test.__file__.rstrip('oc').endswith('.py'), cy_test.__file__" PYTHON -c "import pkg.cy_test; assert pkg.cy_test.TEST == 'pkg.cy_test', pkg.cy_test.TEST; assert not pkg.cy_test.__file__.rstrip('oc').endswith('.py'), pkg.cy_test.__file__" PYTHON -c "import pkg.sub.cy_test; assert pkg.sub.cy_test.TEST == 'pkg.sub.cy_test', pkg.sub.cy_test.TEST; assert not pkg.sub.cy_test.__file__.rstrip('oc').endswith('.py'), pkg.cy_test.__file__" ''' ######## cy_test.py ######## TEST = 'cy_test' ######## pkg/__init__.py ######## ######## pkg/cy_test.py ######## TEST = 'pkg.cy_test' ######## pkg/sub/__init__.py ######## ######## pkg/sub/cy_test.py ######## # cython: language_level=3 TEST = 'pkg.sub.cy_test' ustring = 'abc' assert isinstance(ustring, unicode) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/cythonize_script_excludes.srctree0000644000175100001770000000223300000000000024722 0ustar00runnerdocker00000000000000PYTHON -m Cython.Build.Cythonize -i '**/*.pyx' -x '**/t/**/*.pyx' -x '**/m/**/*.pyx' PYTHON -c "import tests; assert tests.X.x == 2" ######## tests.py ######## import sys sys.path.append('src') import a.f.c.d.x as X assert X.x == 2 assert 'src/a/' in X.__file__ or 'src\\a\\' in X.__file__ try: import a.t.c.d.x except ImportError: pass else: assert False, "ImportError not raised - exclude of 't' package did not work" try: import a.m.c.d.x except ImportError: pass else: assert False, "ImportError not raised - exclude of 'm' package did not work" ######## src/a/__init__.py ######## ######## src/a/t/__init__.py ######## ######## src/a/t/c/__init__.py ######## ######## src/a/t/c/d/__init__.py ######## ######## src/a/t/c/d/x.pyx ######## x = 1 ######## src/a/__init__.py ######## ######## src/a/f/__init__.py ######## ######## src/a/f/c/__init__.py ######## ######## src/a/f/c/d/__init__.py ######## ######## src/a/f/c/d/x.pyx ######## x = 2 ######## src/a/__init__.py ######## ######## src/a/m/__init__.py ######## ######## src/a/m/c/__init__.py ######## ######## src/a/m/c/d/__init__.py ######## ######## src/a/m/c/d/x.pyx ######## x = 3 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/cythonize_script_package.srctree0000644000175100001770000000125200000000000024501 0ustar00runnerdocker00000000000000''' PYTHON -m Cython.Build.Cythonize -i pkg -j1 PYTHON package_test.py ''' ######## package_test.py ######## import sys if sys.version_info[0] < 3 or sys.version_info >= (3,3): # __init__.py compilation isn't supported in Py 3.[012] import pkg.sub.test assert pkg.sub.test.TEST == 'pkg.sub.test' assert not pkg.sub.test.__file__.rstrip('oc').endswith('.py') ######## test.py ######## TEST = 'test' ######## pkg/__init__.py ######## ######## pkg/test.py ######## TEST = 'pkg.test' ######## pkg/sub/__init__.py ######## ######## pkg/sub/test.py ######## # cython: language_level=3 TEST = 'pkg.sub.test' ustring = 'abc' assert isinstance(ustring, unicode) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/cythonize_with_annotate.srctree0000644000175100001770000000272700000000000024376 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "import not_annotated; not_annotated.check()" PYTHON -c "import default_annotated; default_annotated.check()" PYTHON -c "import fullc_annotated; fullc_annotated.check()" ######## setup.py ######## from Cython.Build.Dependencies import cythonize from distutils.core import setup setup( ext_modules = cythonize(["not_annotated.pyx"], language_level=3) + cythonize(["default_annotated.pyx"], annotate=True, language_level=3) + cythonize(["fullc_annotated.pyx"], annotate='fullc', language_level=3) ) ######## not_annotated.pyx ######## # check that html-file doesn't exist: def check(): import os.path as os_path assert not os_path.isfile(__name__+'.html') ######## default_annotated.pyx ######## # load html-site and check that the marker isn't there: def check(): from codecs import open with open(__name__+'.html', 'r', 'utf8') as html_file: html = html_file.read() from Cython.Compiler.Annotate import AnnotationCCodeWriter assert (AnnotationCCodeWriter.COMPLETE_CODE_TITLE not in html) # per default no complete c code ######## fullc_annotated.pyx ######## # load html-site and check that the marker is there: def check(): from codecs import open with open(__name__+'.html', 'r', 'utf8') as html_file: html = html_file.read() from Cython.Compiler.Annotate import AnnotationCCodeWriter assert (AnnotationCCodeWriter.COMPLETE_CODE_TITLE in html) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/cythonize_with_annotate_via_Options.srctree0000644000175100001770000000127700000000000026747 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "import fullc_annotated; fullc_annotated.check()" ######## setup.py ######## from Cython.Build.Dependencies import cythonize from Cython.Compiler import Options Options.annotate = 'fullc' from distutils.core import setup setup( ext_modules = cythonize(["fullc_annotated.pyx"], language_level=3) ) ######## fullc_annotated.pyx ######## # load html-site and check that the marker is there: def check(): from codecs import open with open(__name__+'.html', 'r', 'utf8') as html_file: html = html_file.read() from Cython.Compiler.Annotate import AnnotationCCodeWriter assert (AnnotationCCodeWriter.COMPLETE_CODE_TITLE in html) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/cythonize_with_annotate_via_cli.srctree0000644000175100001770000000231600000000000026056 0ustar00runnerdocker00000000000000CYTHONIZE -i -3 not_annotated.pyx PYTHON -c "import not_annotated; not_annotated.check()" CYTHONIZE -i -3 --annotate default_annotated.pyx PYTHON -c "import default_annotated; default_annotated.check()" CYTHONIZE -i -3 --annotate-fullc fullc_annotated.pyx PYTHON -c "import fullc_annotated; fullc_annotated.check()" ######## not_annotated.pyx ######## # check that html-file doesn't exist: def check(): import os.path as os_path assert not os_path.isfile(__name__+'.html') ######## default_annotated.pyx ######## # load html-site and check that the marker isn't there: def check(): from codecs import open with open(__name__+'.html', 'r', 'utf8') as html_file: html = html_file.read() from Cython.Compiler.Annotate import AnnotationCCodeWriter assert (AnnotationCCodeWriter.COMPLETE_CODE_TITLE not in html) # per default no complete c code ######## fullc_annotated.pyx ######## # load html-site and check that the marker is there: def check(): from codecs import open with open(__name__+'.html', 'r', 'utf8') as html_file: html = html_file.read() from Cython.Compiler.Annotate import AnnotationCCodeWriter assert (AnnotationCCodeWriter.COMPLETE_CODE_TITLE in html) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/depfile.srctree0000644000175100001770000000074600000000000021045 0ustar00runnerdocker00000000000000""" CYTHONIZE -M foo.pyx PYTHON check.py """ ######## foo.pyx ######## from bar cimport empty include "baz.pxi" empty() print(foo()) ######## baz.pxi ######## def foo(): return "foo" ######## bar.pxd ######## cdef inline void empty(): print("empty") ######## check.py ######## with open("foo.c.dep", "r") as f: contents = f.read().replace("\\\n", " ").replace("\n", " ") assert sorted(contents.split()) == ['bar.pxd', 'baz.pxi', 'foo.c:', 'foo.pyx'], contents ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/depfile_numpy.srctree0000644000175100001770000000266600000000000022300 0ustar00runnerdocker00000000000000# tag: numpy """ CYTHONIZE -M dep_np.pyx PYTHON check_np.py """ ######## dep_np.pyx ######## cimport numpy as np np.import_array() ######## check_np.py ######## import os.path import re import numpy as np import Cython with open("dep_np.c.dep", "r") as f: contents = f.read().replace('\\\n', ' ').replace('\n', ' ') contents = contents.split() cy_prefix, _ = os.path.split(Cython.__file__) contents = [fname.replace(cy_prefix, "cy_prefix") for fname in contents] np_prefix, _ = os.path.split(np.__file__) contents = [fname.replace(np_prefix, "np_prefix") for fname in contents] # filter out the version number from `np_prefix/__init__.cython-30.pxd`. contents = [re.sub('[.]cython-[0-9]+', '', entry) for entry in contents] contents = [path.split(os.sep) for path in contents] contents.sort() expected = [path.split('/') for path in [ 'cy_prefix/Includes/cpython/object.pxd', 'cy_prefix/Includes/cpython/ref.pxd', 'cy_prefix/Includes/cpython/type.pxd', 'cy_prefix/Includes/libc/stdio.pxd', 'cy_prefix/Includes/libc/string.pxd', 'dep_np.c:', 'dep_np.pyx', ]] # Also account for legacy numpy versions, which do not ship # `__init__.pxd` hence the fallback is used: if ['cy_prefix', 'Includes', 'numpy', '__init__.pxd'] in contents: expected.append(['cy_prefix', 'Includes', 'numpy', '__init__.pxd']) else: expected.append(['np_prefix', '__init__.pxd']) expected.sort() assert contents == expected, contents ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/depfile_package_cython.srctree0000644000175100001770000000271100000000000024076 0ustar00runnerdocker00000000000000""" PYTHON -c 'import os; os.makedirs("builddir/pkg/sub")' CYTHON -M pkg/test.pyx -o builddir/pkg/test.c CYTHON --depfile pkg/sub/test.pyx -o builddir/pkg/sub/test.c PYTHON check.py """ ######## check.py ######## import os.path def pkgpath(*args): return os.path.join('pkg', *args) with open(os.path.join("builddir", "pkg", "test.c.dep"), "r") as f: contents = f.read().replace("\\\n", " ").replace("\n", " ") assert sorted(contents.split()) == sorted([os.path.join('builddir', 'pkg', 'test.c:'), pkgpath('sub', 'incl.pxi'), pkgpath('test.pxd'), pkgpath('test.pyx')]), contents with open(os.path.join("builddir", "pkg", "sub", "test.c.dep"), "r") as f: contents = f.read().replace("\\\n", " ").replace("\n", " ") contents = [os.path.relpath(entry, '.') if os.path.isabs(entry) else entry for entry in contents.split()] assert sorted(contents) == sorted([os.path.join('builddir', 'pkg', 'sub', 'test.c:'), pkgpath('sub', 'incl.pxi'), pkgpath('sub', 'test.pyx'), pkgpath('test.pxd')]), contents # last is really one level up ######## pkg/__init__.py ######## ######## pkg/test.pyx ######## TEST = "pkg.test" include "sub/incl.pxi" cdef object get_str(): return TEST ######## pkg/test.pxd ######## cdef object get_str() ######## pkg/sub/__init__.py ######## ######## pkg/sub/test.pyx ######## # cython: language_level=3 from ..test cimport get_str include 'incl.pxi' TEST = 'pkg.sub.test' ######## pkg/sub/incl.pxi ######## pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/depfile_package_cythonize.srctree0000644000175100001770000000241100000000000024603 0ustar00runnerdocker00000000000000""" CYTHONIZE -i pkg --depfile PYTHON package_test.py """ ######## package_test.py ######## import os.path def pkgpath(*args): return os.path.join('pkg', *args) with open(os.path.join("pkg", "test.c.dep"), "r") as f: contents = f.read().replace("\\\n", " ").replace("\n", " ") assert sorted(contents.split()) == sorted([pkgpath('test.c:'), pkgpath('sub', 'incl.pxi'), pkgpath('test.pxd'), pkgpath('test.pyx')]), contents with open(os.path.join("pkg", "sub", "test.c.dep"), "r") as f: contents = f.read().replace("\\\n", " ").replace("\n", " ") contents = [os.path.relpath(entry, '.') if os.path.isabs(entry) else entry for entry in contents.split()] assert sorted(contents) == sorted([pkgpath('sub', 'test.c:'), pkgpath('sub', 'incl.pxi'), pkgpath('sub', 'test.pyx'), pkgpath('test.pxd')]), contents # last is really one level up ######## pkg/__init__.py ######## ######## pkg/test.pyx ######## TEST = "pkg.test" include "sub/incl.pxi" cdef object get_str(): return TEST ######## pkg/test.pxd ######## cdef object get_str() ######## pkg/sub/__init__.py ######## ######## pkg/sub/test.pyx ######## # cython: language_level=3 from ..test cimport get_str include 'incl.pxi' TEST = 'pkg.sub.test' ######## pkg/sub/incl.pxi ######## pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/dotted.filename.modules.pxd0000644000175100001770000000000000000000000023251 0ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/dotted.filename.modules.pyx0000644000175100001770000000045500000000000023314 0ustar00runnerdocker00000000000000# mode: compile # tag: warnings _WARNINGS=""" 1:0: Dotted filenames ('dotted.filename.modules.pxd') are deprecated. Please use the normal Python package directory layout. 1:0: Dotted filenames ('dotted.filename.modules.pyx') are deprecated. Please use the normal Python package directory layout. """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/inline_distutils.srctree0000644000175100001770000000122300000000000023006 0ustar00runnerdocker00000000000000# tag: cpp PYTHON setup.py build_ext --inplace PYTHON -c "import a" ######## setup.py ######## # TODO: Better interface... from Cython.Build.Dependencies import cythonize from distutils.core import setup import sys if sys.platform == 'win32': MATH_LIBS = [] else: MATH_LIBS = ['m'] setup( ext_modules = cythonize("*.pyx", aliases={'MATH_LIBS': MATH_LIBS}), ) ######## my_lib.pxd ######## # distutils: language = c++ # distutils: libraries = MATH_LIBS cdef extern from "my_lib_helper.cpp" namespace "A": int x ######## my_lib_helper.cpp ####### namespace A { int x = 100; }; ######## a.pyx ######## from my_lib cimport x print(x) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/module_api.srctree0000644000175100001770000000564500000000000021556 0ustar00runnerdocker00000000000000# tag: cpp PYTHON setup.py build_ext --inplace PYTHON test.py ######## setup.py ######## from Cython.Build.Dependencies import cythonize from distutils.core import setup exts = cythonize("*.pyx") for e in exts: if e.name == "d": e.sources.append("a.c") setup( ext_modules = exts, ) ######## a.pxd ######## ctypedef api float flt cdef int int0 cdef float flt0 cdef api int int1 cdef api float flt1 cdef public api int int2 cdef public api flt flt2 cdef class A0: pass ctypedef api class A1 [ type A1_Type, object A1Object ]: pass ctypedef public api class A2 [ type A2_Type, object A2Object ]: pass cdef A0 a0 cdef api A1 a1 cdef public api A2 a2 ######## a.pyx ######## cdef int int0 = 1, int1 = 1, int2 = 1 cdef float flt0 = 1, flt1 = 1, flt2 = 1 cdef api int int3 = 1 cdef api flt flt3 = 1 cdef public int int4 = 1 cdef public flt flt4 = 1 def get_int(): return (int0, int1, int2, int3, int4) def get_flt(): return (flt0, flt1, flt2, flt3, flt4) cdef class A0: pass cdef class A1: pass cdef class A2: pass cdef A0 a0 = A0() cdef api A1 a1 = A1() cdef public api A2 a2 = A2() ######## b.pyx ######## from a cimport * int0 = int1 = int2 = 7 flt0 = flt1 = flt2 = 7 ######## c.pyx ######## # distutils: language = c++ cdef extern from "a_api.h": int import_a() except -1 ctypedef float flt int int1, int2, int3 flt flt1, flt2, flt3 import_a() int1 = int2 = int3 = 5 flt1 = flt2 = flt3 = 5 ######## inita.h ######## #if PY_MAJOR_VERSION >= 3 void inita(void) { PyObject *sys_modules = NULL; PyObject *mod = NULL; sys_modules = PyImport_GetModuleDict(); if (!sys_modules) return; mod = PyInit_a(); if (!mod) return; #if PY_VERSION_HEX >= 0x03050000 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) /* FIXME: this is incomplete and users shouldn't have to do this in the first place... */ if (!PyModule_Check(mod)) { /* In PEP 489 multi-phase init, PyInit_a returns PyModuleDef */ PyModuleDef *mdef = (PyModuleDef*)mod; PyObject *modname = PyUnicode_FromString("a"); if (!modname) return; mod = PyModule_NewObject(modname); Py_DECREF(modname); if (!mod) return; PyModule_ExecDef(mod, mdef); } #endif PyDict_SetItemString(sys_modules, (char*)"a", mod); } #endif ######## d.pyx ######## cdef extern from "a.h": pass cdef extern from "inita.h": pass cdef extern from "a.h": void inita() except * ctypedef float flt int int2, int4 flt flt2, flt4 inita() int2 = int4 = 3 flt2 = flt4 = 3 ######## test.py ######## import a assert a.get_int() == (1,1,1,1,1) assert a.get_flt() == (1,1,1,1,1) import b assert a.get_int() == (7,7,7,1,1) assert a.get_flt() == (7,7,7,1,1) import c assert a.get_int() == (7,5,5,5,1) assert a.get_flt() == (7,5,5,5,1) import d import a assert a.get_int() == (1,1,3,1,3) assert a.get_flt() == (1,1,3,1,3) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/package_compilation.srctree0000644000175100001770000000235600000000000023425 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "import toppkg; assert not toppkg.__file__.rstrip('oc').endswith('.py'); assert toppkg.PACKAGE == 1" PYTHON -c "import toppkg.subpkg; assert not toppkg.__file__.rstrip('oc').endswith('.py'); assert not toppkg.subpkg.__file__.rstrip('oc').endswith('.py'); assert toppkg.subpkg.PACKAGE == 2" PYTHON -c "import toppkg.a; assert toppkg.a.MODULE == 'a'" PYTHON -c "from toppkg.subpkg import a; assert a.MODULE == 'subpkg.a'" ######## setup.py ######## from Cython.Build import cythonize from distutils.core import setup setup( ext_modules = cythonize("toppkg/**/*.py"), ) ######## toppkg/__init__.py ######## import sys assert 'toppkg' in sys.modules assert __path__ is not None, "__path__ is None" assert __path__, "__path__ is empty" assert 'toppkg' in __path__[0], "toppkg not in __path__[0]" assert 'toppkg' in __file__ from . import a assert a.MODULE == 'a' from . import b assert b.MODULE == 'b' PACKAGE = 1 ######## toppkg/a.py ######## MODULE = 'a' ######## toppkg/b.py ######## MODULE = 'b' ######## toppkg/subpkg/__init__.py ######## PACKAGE = 2 from . import a assert a.__name__ == 'toppkg.subpkg.a' assert a.MODULE == 'subpkg.a' ######## toppkg/subpkg/a.py ######## MODULE = 'subpkg.a' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/build/setuptools_reimport.srctree0000644000175100001770000000051700000000000023573 0ustar00runnerdocker00000000000000# mode: run # tag: setuptools PYTHON setup.py ######## module.pyx ######## cimport cython ######## import_cython.py ######## import Cython.Compiler.Main ######## setup.py ######## from setuptools.sandbox import run_setup run_setup('import_cython.py', ['egg_info']) from Cython.Build import cythonize cythonize('module.pyx') ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.1047242 Cython-3.0.8/tests/compile/0000755000175100001770000000000000000000000016366 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.1047242 Cython-3.0.8/tests/compile/a/0000755000175100001770000000000000000000000016606 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/a/__init__.py0000644000175100001770000000001500000000000020713 0ustar00runnerdocker00000000000000# empty file ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/a/b.pxd0000644000175100001770000000002600000000000017542 0ustar00runnerdocker00000000000000cdef int **foo(void*) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/a_capi.pyx0000644000175100001770000000072300000000000020346 0ustar00runnerdocker00000000000000# mode: compile cdef public struct Foo: int a, b ctypedef struct Blarg: int c, d ctypedef public Foo Zax cdef public class C[type C_Type, object C_Obj]: pass cdef public Zax *blarg cdef public C c_pub = C() cdef api C c_api = C() cdef public dict o_pub = C() cdef api list o_api = C() cdef api float f(Foo *x): pass cdef public void g(Blarg *x): pass cdef public api void h(Zax *x): pass cdef extern from "a_capi.h": pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/altet1.h0000644000175100001770000000002400000000000017725 0ustar00runnerdocker00000000000000typedef int blarg; ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/altet1.pyx.BROKEN0000644000175100001770000000033100000000000021276 0ustar00runnerdocker00000000000000__doc__ = """ >>> flub(25) 25 >>> g() 0 """ cdef extern from "altet1.h": ctypedef int blarg cdef blarg globvar def flub(blarg bobble): print bobble globvar = 0 def g(): return globvar ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/argdefault.pyx0000644000175100001770000000013400000000000021244 0ustar00runnerdocker00000000000000# mode: compile cdef swallow def spam(w, int x = 42, y = "grail", z = swallow): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/arrayargs.pyx0000644000175100001770000000062300000000000021124 0ustar00runnerdocker00000000000000# mode: compile cdef extern from *: cdef void foo(int[]) ctypedef int MyInt cdef void foo(MyInt[]) struct MyStruct: pass cdef void bar(MyStruct[]) ctypedef MyStruct* MyStructP cdef void baz(MyStructP[]) cdef struct OtherStruct: int a a = sizeof(int[23][34]) b = sizeof(OtherStruct[43]) DEF COUNT = 4 c = sizeof(int[COUNT]) d = sizeof(OtherStruct[COUNT]) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/arrayptrcompat.pyx0000644000175100001770000000036400000000000022203 0ustar00runnerdocker00000000000000# mode: compile cdef enum E: z cdef void f(): cdef int *p cdef void *v cdef int[5] a cdef int i=0 cdef E e=z p = a v = a p = a + i p = a + e p = i + a p = e + a p = a - i p = a - e f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/arraytoptrarg.pyx0000644000175100001770000000015200000000000022027 0ustar00runnerdocker00000000000000# mode: compile cdef void f1(char *argv[]): f2(argv) cdef void f2(char *argv[]): pass f1(NULL) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/ass2longlong.pyx0000644000175100001770000000024300000000000021537 0ustar00runnerdocker00000000000000# mode: compile cdef void spam(): cdef long long L cdef unsigned long long U cdef object x = object() L = x x = L U = x x = U spam() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/assert2.pyx0000644000175100001770000000006000000000000020507 0ustar00runnerdocker00000000000000# mode: compile def f(a, b): assert a, a+b ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/behnel4.pyx0000644000175100001770000000013300000000000020446 0ustar00runnerdocker00000000000000# mode: compile cdef enum E: spam, eggs cdef E f() except spam: return eggs f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/belchenko1.pyx0000644000175100001770000000025200000000000021142 0ustar00runnerdocker00000000000000# mode: compile cdef extern from *: ctypedef int intptr_t cdef int _is_aligned(void *ptr): return ((ptr) & ((sizeof(int))-1)) == 0 _is_aligned(NULL) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/belchenko2.h0000644000175100001770000000004200000000000020547 0ustar00runnerdocker00000000000000void c_func(unsigned char pixel); ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/belchenko2.pyx.BROKEN0000644000175100001770000000031100000000000022116 0ustar00runnerdocker00000000000000cdef extern from "belchenko2.h": void c_func(unsigned char pixel) def f(unsigned char pixel): c_func(pixel) def g(signed char pixel): c_func(pixel) def h(char pixel): c_func(pixel) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/branch_hints.pyx0000644000175100001770000000337100000000000021576 0ustar00runnerdocker00000000000000# mode: compile # tag: if, unlikely cimport cython @cython.test_assert_path_exists( "//IfClauseNode", "//IfClauseNode[not(@branch_hint)]", ) def if_simple(x): if x: x = 2 @cython.test_assert_path_exists( "//IfClauseNode", "//IfClauseNode[not(@branch_hint)]", ) def if_return(x): if x: return 1 raise TypeError() @cython.test_assert_path_exists( "//IfClauseNode", "//IfClauseNode[@branch_hint = 'unlikely']", ) def if_raise_else(x): if x: raise TypeError() else: return 1 @cython.test_assert_path_exists( "//IfClauseNode", "//IfClauseNode[@branch_hint = 'likely']", ) def if_else_raise(x): if x: return 1 else: raise TypeError() @cython.test_assert_path_exists( "//IfClauseNode", "//IfClauseNode[@branch_hint = 'unlikely']", ) def if_raise_else_raise(x): if x: raise ValueError() else: raise TypeError() @cython.test_assert_path_exists( "//IfClauseNode", "//IfClauseNode[@branch_hint = 'unlikely']", ) @cython.test_fail_if_path_exists( "//IfClauseNode[@branch_hint = 'likely']", "//IfClauseNode[not(@branch_hint)]", ) def if_elif_raise_else_raise(x): if x: raise ValueError() elif not x: raise AttributeError() else: raise TypeError() @cython.test_assert_path_exists( "//IfClauseNode", "//IfClauseNode[@branch_hint = 'unlikely']", "//IfClauseNode[@branch_hint = 'unlikely']//GILStatNode", ) @cython.test_fail_if_path_exists( "//IfClauseNode[@branch_hint = 'likely']", "//IfClauseNode[not(@branch_hint)]", ) cpdef int nogil_if_raise(int x) except -1 nogil: if x: raise TypeError() elif not x: raise ValueError() else: x = 2 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/buildenv.pyx0000644000175100001770000001102200000000000020734 0ustar00runnerdocker00000000000000""" Non-test that prints debug information about the current build environment. """ from __future__ import print_function import os import sys from distutils import sysconfig cdef extern from *: """ #ifndef PyLong_SHIFT #define PyLong_SHIFT 0 typedef int digit; typedef int sdigit; #endif #ifndef PyLong_BASE #define PyLong_BASE 0 #endif #ifndef PyLong_MASK #define PyLong_MASK 0 #endif #ifndef SIZEOF_UINTPTR_T #define SIZEOF_UINTPTR_T 0 #endif #ifndef SIZEOF_OFF_T #define SIZEOF_OFF_T 0 #endif """ # Python runtime cdef long PY_VERSION_HEX # Cython config cdef int CYTHON_COMPILING_IN_CPYTHON cdef int CYTHON_COMPILING_IN_LIMITED_API cdef int CYTHON_COMPILING_IN_PYPY cdef int CYTHON_COMPILING_IN_GRAAL cdef int CYTHON_COMPILING_IN_NOGIL cdef int CYTHON_USE_PYLONG_INTERNALS cdef int CYTHON_USE_PYLIST_INTERNALS cdef int CYTHON_USE_UNICODE_INTERNALS cdef int CYTHON_USE_UNICODE_WRITER cdef int CYTHON_AVOID_BORROWED_REFS cdef int CYTHON_ASSUME_SAFE_MACROS cdef int CYTHON_USE_TYPE_SLOTS cdef int CYTHON_UNPACK_METHODS cdef int CYTHON_FAST_THREAD_STATE cdef int CYTHON_FAST_PYCALL cdef int CYTHON_PEP489_MULTI_PHASE_INIT cdef int CYTHON_USE_TP_FINALIZE # C and platform specifics cdef int SIZEOF_INT cdef int SIZEOF_LONG cdef int SIZEOF_SIZE_T cdef int SIZEOF_LONG_LONG cdef int SIZEOF_VOID_P cdef int SIZEOF_OFF_T cdef int SIZEOF_UINTPTR_T # PyLong internals cdef long PyLong_BASE cdef long PyLong_MASK cdef int PyLong_SHIFT cdef int digit cdef int sdigit def config_var(name, default=''): return sysconfig.get_config_var(name) or default get_env = os.environ.get print(f"""Python build environment: Python {sys.version_info} PY_VERSION_HEX 0x{PY_VERSION_HEX:X} CYTHON_COMPILING_IN_CPYTHON {CYTHON_COMPILING_IN_CPYTHON} CYTHON_COMPILING_IN_LIMITED_API {CYTHON_COMPILING_IN_LIMITED_API} CYTHON_COMPILING_IN_PYPY {CYTHON_COMPILING_IN_PYPY} CYTHON_COMPILING_IN_GRAAL {CYTHON_COMPILING_IN_GRAAL} CYTHON_COMPILING_IN_NOGIL {CYTHON_COMPILING_IN_NOGIL} CYTHON_USE_PYLONG_INTERNALS {CYTHON_USE_PYLONG_INTERNALS} CYTHON_USE_PYLIST_INTERNALS {CYTHON_USE_PYLIST_INTERNALS} CYTHON_USE_UNICODE_INTERNALS {CYTHON_USE_UNICODE_INTERNALS} CYTHON_USE_UNICODE_WRITER {CYTHON_USE_UNICODE_WRITER} CYTHON_AVOID_BORROWED_REFS {CYTHON_AVOID_BORROWED_REFS} CYTHON_ASSUME_SAFE_MACROS {CYTHON_ASSUME_SAFE_MACROS} CYTHON_USE_TYPE_SLOTS {CYTHON_USE_TYPE_SLOTS} CYTHON_UNPACK_METHODS {CYTHON_UNPACK_METHODS} CYTHON_FAST_THREAD_STATE {CYTHON_FAST_THREAD_STATE} CYTHON_FAST_PYCALL {CYTHON_FAST_PYCALL} CYTHON_PEP489_MULTI_PHASE_INIT {CYTHON_PEP489_MULTI_PHASE_INIT} CYTHON_USE_TP_FINALIZE {CYTHON_USE_TP_FINALIZE} PyLong_BASE 0x{PyLong_BASE:X} PyLong_MASK 0x{PyLong_MASK:X} PyLong_SHIFT {PyLong_SHIFT} sizeof(digit) {sizeof(digit)} sizeof(sdigit) {sizeof(sdigit)} sys.int_info {getattr(sys, 'int_info', '-')} sys.getsizeof(1, 2**14, 2**15, 2**29, 2**30, 2**59, 2**60, 2**64) {tuple(sys.getsizeof(n) for n in (1, 2**14, 2**15, 2**29, 2**30, 2**59, 2**60, 2**64))} SIZEOF_INT {SIZEOF_INT} ({sizeof(int)}) SIZEOF_LONG {SIZEOF_LONG} ({sizeof(long)}) SIZEOF_SIZE_T {SIZEOF_SIZE_T} ({sizeof(Py_ssize_t)}, {getattr(sys, 'maxsize', getattr(sys, 'maxint', None))}) SIZEOF_LONG_LONG {SIZEOF_LONG_LONG} ({sizeof(long long)}) SIZEOF_VOID_P {SIZEOF_VOID_P} ({sizeof(void*)}) SIZEOF_UINTPTR_T {SIZEOF_UINTPTR_T} ({sizeof(unsigned int *)}) SIZEOF_OFF_T {SIZEOF_OFF_T} Paths: sys.executable = {sys.executable} sys.exec_prefix = {sys.exec_prefix} sys.base_exec_prefix = {getattr(sys, 'base_exec_prefix', "")} sys.prefix = {sys.prefix} sys.path = {sys.path} PYTHONPATH (env) = {get_env('PYTHONPATH', '')} PYTHONHOME (env) = {get_env('PYTHONHOME', '')} Distutils: INCDIR = {sysconfig.get_python_inc()} LIBS = {config_var('LIBS')} LIBDIR = {config_var('LIBDIR')} LIBPL = {config_var('LIBPL')} Python LIBRARY = {config_var('LIBRARY')} LINKFORSHARED = {config_var('LINKFORSHARED')} CC (distutils) = {config_var('CC')} CC (env) = {get_env('CC', '')} CFLAGS (distutils) = {config_var('CFLAGS')} CFLAGS (env) = {get_env('CFLAGS', '')} LINKCC (distutils) = {config_var('LINKCC')} LINKCC (env) = {get_env('LINKCC', '')} Encodings: sys maxunicode = {sys.maxunicode} LANG (env) = {get_env('LANG', '')} PYTHONIOENCODING (env) = {get_env('PYTHONIOENCODING', '')} sys stdout encoding = {sys.stdout.encoding} sys default encoding = {sys.getdefaultencoding()} sys FS encoding = {sys.getfilesystemencoding()} """) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/builtin.pyx0000644000175100001770000000005600000000000020577 0ustar00runnerdocker00000000000000# mode: compile def f(): x = open("foo") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/builtinbuffer.py0000644000175100001770000000015000000000000021574 0ustar00runnerdocker00000000000000# mode: compile import cython @cython.cclass class BuiltinRef: cython.declare(pybuf = 'Py_buffer') ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/builtinfuncs.pyx0000644000175100001770000000130200000000000021631 0ustar00runnerdocker00000000000000# mode: compile cdef int f() except -1: cdef object x, y = 0, z = 0, w = 0 cdef str sstring cdef basestring sustring cdef int i cdef long lng cdef Py_ssize_t s x = abs(y) delattr(x, 'spam') x = dir(y) x = divmod(y, z) x = getattr(y, 'spam') i = hasattr(y, 'spam') lng = hash(y) x = intern(y) i = isinstance(y, z) i = issubclass(y, z) x = iter(y) s = len(x) x = open(y, z) x = pow(y, z, w) x = pow(y, z) x = reload(y) x = repr(y) sstring = repr(x) sustring = repr(x) setattr(x, y, z) #i = typecheck(x, y) #i = issubtype(x, y) x = abs def not_called(): response = raw_input('xyz') f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/builtinlist.pyx0000644000175100001770000000044300000000000021473 0ustar00runnerdocker00000000000000# mode: compile cdef int f() except -1: cdef list l cdef object x = (), y = (1,), z z = list l = list(x) l = list(*y) z = l.insert l.insert(17, 42) l.append(88) l.sort() l.reverse() z = l.as_tuple() return z is not None def test(): f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/burton1.pyx.BROKEN0000644000175100001770000000011600000000000021477 0ustar00runnerdocker00000000000000cdef void f(): cdef void (*p)() p = 0 (p)() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/c_directives.pyx0000644000175100001770000000172700000000000021602 0ustar00runnerdocker00000000000000# mode: compile # cython: boundscheck = False # cython: ignoreme = OK # cython: warn.undeclared = False # cython: test_assert_c_code_has = Generated by Cython # cython: test_fail_if_c_code_has = Generated by Python # This testcase is most useful if you inspect the generated C file print 3 cimport cython as cy def e(object[int, ndim=2] buf): print buf[3, 2] # no bc @cy.boundscheck(False) def f(object[int, ndim=2] buf): print buf[3, 2] # no bc @cy.boundscheck(True) def g(object[int, ndim=2] buf): # The below line should have no meaning # cython: boundscheck = False # even if the above line doesn't follow indentation. print buf[3, 2] # bc def h(object[int, ndim=2] buf): print buf[3, 2] # no bc with cy.boundscheck(True): print buf[3,2] # bc from cython cimport boundscheck as bc def i(object[int] buf): with bc(True): print buf[3] # bs from cython cimport warn as my_warn @my_warn(undeclared=True) def j(): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/callingconvention.srctree0000644000175100001770000000403000000000000023470 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "import callingconvention" ######## setup.py ######## from distutils.core import setup from Cython.Distutils import build_ext from Cython.Distutils.extension import Extension setup( ext_modules = [ Extension("callingconvention", ["callingconvention.pyx", "external_callingconvention.c"]), ], cmdclass={'build_ext': build_ext}, ) ######## callingconvention.pyx ######## # mode: compile cdef extern from "callingconvention.h": pass cdef extern int f1() cdef extern int __cdecl f2() cdef extern int __stdcall f3() cdef extern int __fastcall f4() cdef extern int (*p1)() cdef extern int (__cdecl *p2)() cdef extern int (__stdcall *p3)() cdef extern int (__fastcall *p4)() p1 = f1 p2 = f2 p3 = f3 p4 = f4 ######## callingconvention.h ######## #define DLL_EXPORT #include "external_callingconvention.h" ######## external_callingconvention.h ######## #ifndef DL_IMPORT #define DL_IMPORT(t) t #elif defined(DLL_EXPORT) #define DL_IMPORT(t) DL_EXPORT(t) #endif #ifdef __cplusplus extern "C" { #endif extern DL_IMPORT(int) f1(void); extern DL_IMPORT(int) __cdecl f2(void); extern DL_IMPORT(int) __stdcall f3(void); extern DL_IMPORT(int) __fastcall f4(void); extern DL_IMPORT(int) (*p1)(void); extern DL_IMPORT(int) (__cdecl *p2)(void); extern DL_IMPORT(int) (__stdcall *p3)(void); extern DL_IMPORT(int) (__fastcall *p4)(void); #ifdef __cplusplus } #endif ######## external_callingconvention.c ######## #include #ifndef DL_EXPORT #define DL_EXPORT(t) t #endif #if !defined(WIN32) && !defined(MS_WINDOWS) #ifndef __stdcall #define __stdcall #endif #ifndef __cdecl #define __cdecl #endif #ifndef __fastcall #define __fastcall #endif #endif DL_EXPORT(int) f1(void) {return 0;} DL_EXPORT(int) __cdecl f2(void) {return 0;} DL_EXPORT(int) __stdcall f3(void) {return 0;} DL_EXPORT(int) __fastcall f4(void) {return 0;} DL_EXPORT(int) (*p1)(void); DL_EXPORT(int) (__cdecl *p2)(void); DL_EXPORT(int) (__stdcall *p3)(void); DL_EXPORT(int) (__fastcall *p4)(void); ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cargdef.pyx0000644000175100001770000000037300000000000020526 0ustar00runnerdocker00000000000000# mode: compile def f(obj, int i, double f, char *s1, char s2[]): pass cdef g(obj, int i, double f, char *s1, char s2[]): pass cdef do_g(object (*func)(object, int, double, char*, char*)): return func(1, 2, 3.14159, "a", "b") do_g(&g) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/carrdecl.pyx0000644000175100001770000000006300000000000020706 0ustar00runnerdocker00000000000000# mode: compile cdef extern: cdef func(int[]) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cassign.pyx0000644000175100001770000000036400000000000020562 0ustar00runnerdocker00000000000000# mode: compile cdef void foo(): cdef int i1, i2=0 cdef char c1=0, c2 cdef char *p1, *p2=NULL cdef object obj1 i1 = i2 i1 = c1 p1 = p2 obj1 = i1 i1 = obj1 p1 = obj1 p1 = "spanish inquisition" foo() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cast_ctypedef_array_T518.pyx0000644000175100001770000000054500000000000023670 0ustar00runnerdocker00000000000000# ticket: t518 # mode: compile cdef extern from "cast_ctypedef_array_T518_helper.h": cdef struct __foo_struct: int i, j ctypedef __foo_struct foo_t[1] void foo_init(foo_t) void foo_clear(foo_t) cdef foo_t value foo_init(value) foo_clear(value) cdef void *pointer = value foo_init(pointer) foo_clear(pointer) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cast_ctypedef_array_T518_helper.h0000644000175100001770000000030200000000000024625 0ustar00runnerdocker00000000000000struct __foo_struct { int i, j; }; typedef struct __foo_struct foo_t[1]; static void foo_init (foo_t v) { v[0].i = 0; v[0].j = 0; } static void foo_clear (foo_t v) { v[0].i = 0; v[0].j = 0; } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/casttoexttype.pyx0000644000175100001770000000027700000000000022056 0ustar00runnerdocker00000000000000# mode: compile cdef extern class external.Spam: pass cdef void foo(object x): pass cdef void blarg(void *y, object z): foo(y) foo(z) blarg(None, None) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cdef_syntax.pyx0000644000175100001770000000032700000000000021441 0ustar00runnerdocker00000000000000# mode: compile # the following are valid syntax constructs and should not produce errors ctypedef int x; cdef no_semi(): cdef int i cdef with_semi(): cdef int i; def use_cdef(): &no_semi, &with_semi ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cdefemptysue.pyx0000644000175100001770000000137400000000000021632 0ustar00runnerdocker00000000000000# mode: compile # tag: struct, union, enum, cdefextern cdef extern from *: """ struct spam { int a; }; struct flat_spam { int a; }; typedef struct { int a; } flat_spam_type; typedef union { int a; long b; } eggs; typedef union { int a; long b; } flat_eggs; enum ham { TOAST }; enum flat_ham { FLAT_TOAST }; """ cdef struct spam: pass cdef struct flat_spam: pass ctypedef struct flat_spam_type: pass ctypedef union eggs: pass ctypedef union flat_eggs: pass cdef enum ham: pass cdef enum flat_ham: pass cdef extern spam s cdef extern flat_spam fs cdef extern flat_spam_type fst cdef extern eggs e cdef extern flat_eggs fe cdef extern ham h cdef extern flat_ham fh ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cdefexternblock.pyx0000644000175100001770000000057400000000000022300 0ustar00runnerdocker00000000000000# mode: compile # tag: struct, union, enum, cdefextern cdef extern from "cheese.h": ctypedef int camembert struct roquefort: int x char *swiss void cheddar() # FIXME: find a real declaration here. #class external.runny [object runny_obj]: # cdef int a # def __init__(self): # pass #cdef runny r = runny() #r.a = 42 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cdefexternempty.pyx0000644000175100001770000000007000000000000022333 0ustar00runnerdocker00000000000000# mode: compile cdef extern from "cheese.h": pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cdefexternfromstar.pyx0000644000175100001770000000006300000000000023034 0ustar00runnerdocker00000000000000# mode: compile cdef extern from *: int spam ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cenum.pyx0000644000175100001770000000025300000000000020237 0ustar00runnerdocker00000000000000# mode: compile cdef enum Spam: a b, c, d, e, f g = 42 cdef void eggs(): cdef Spam s1, s2=a cdef int i s1 = s2 s1 = c i = s1 eggs() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cforfromloop.pyx0000644000175100001770000000067600000000000021650 0ustar00runnerdocker00000000000000# mode: compile cdef int i, j, k cdef object a, b, x for i from 0 <= i < 10: pass for i from 0 < i <= 10: pass for i from 10 >= i > 0: pass for i from 10 > i >= 0: pass for x from 0 <= x <= 10: pass for i from a <= i <= b: pass for i from k <= i <= j: pass for i from k * 42 <= i <= j / 18: pass while j: for i from 0 <= i <= 10: continue break else: continue break ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cheese.h0000644000175100001770000000000000000000000017761 0ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cimport_package_module_T4.pyx0000644000175100001770000000011300000000000024167 0ustar00runnerdocker00000000000000# ticket: t4 # mode: compile from a cimport b cdef int **t = b.foo(NULL) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cimported_class_base.srctree0000644000175100001770000000127000000000000024124 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace ######## setup.py ######## from Cython.Build import cythonize from Cython.Distutils.extension import Extension import sys sys.path.append("path") ext_modules = [ Extension("importer", ["importer.pyx"]), ] ext_modules = cythonize(ext_modules, include_path=["include"]) ######## pkg/__init__.py ######## ######## pkg/a.pxd ######## cdef class A(object): pass ######## importer.pyx ######## cimport pkg.a cimport pkg.a as a cimport pkg.a as a_by_another_name from pkg cimport a as from_cimported_a cdef class A1(a.A): pass cdef class A2(a_by_another_name.A): pass cdef class A3(pkg.a.A): pass cdef class A4(from_cimported_a.A): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cimportfrom_T248.pyx0000644000175100001770000000032700000000000022214 0ustar00runnerdocker00000000000000# ticket: t248 # mode: compile from ewing8 cimport (Foo, Blarg) from declandimpl cimport (Sandwich , Tomato) cdef extern Foo yummy ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/classmethargdefault.pyx0000644000175100001770000000061300000000000023152 0ustar00runnerdocker00000000000000# mode: compile __doc__ = u""" >>> s = Swallow() >>> s.spam(1) 1 42 'grail' True >>> s.spam(1, 2) 1 2 'grail' True >>> s.spam(1, z = 2) 1 42 'grail' 2 >>> s.spam(1, y = 2) 1 42 2 True >>> s.spam(1, x = 2, y = 'test') 1 2 'test' True """ swallow = True class Swallow: def spam(w, int x = 42, y = "grail", z = swallow): print w, x, y, z ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cnamespec.pyx0000644000175100001770000000073500000000000021073 0ustar00runnerdocker00000000000000# mode: compile cdef extern from *: """ int c_a, c_b; """ int a "c_a", b "c_b" cdef struct foo "c_foo": int i "c_i" ctypedef enum blarg "c_blarg": x "c_x" y "c_y" = 42 cdef double spam "c_spam" (int i, float f): cdef double d "c_d" cdef foo *p global b if i: d = spam(a, f) cdef foo q q.i = 7 p = &q b = p.i p.i = x p.i = y cdef inline double spam2 "c_spam2" (int i, float f): return spam(i,f) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cnumop.pyx0000644000175100001770000000045300000000000020433 0ustar00runnerdocker00000000000000# mode: compile def f(): cdef int int1, int2=0, int3=1 cdef char char1=0 cdef long long1, long2=0 cdef float float1, float2=0 cdef double double1 int1 = int2 * int3 int1 = int2 / int3 long1 = long2 * char1 float1 = int1 * float2 double1 = float1 * int2 f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/coercetovoidptr.pyx0000644000175100001770000000012600000000000022342 0ustar00runnerdocker00000000000000# mode: compile cdef void f(): cdef void *p cdef char *q=NULL p = q f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/complex_annotations.pyx0000644000175100001770000000045000000000000023213 0ustar00runnerdocker00000000000000# mode: compile # Complex numbers defined in annotations weren't having their utility code imported directly # leading to compile-errors that the type wasn't defined. The test is intentionally minimal since # anything more thorough ends up creating the utility code cdef f(x: complex): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/complex_decorators.pyx0000644000175100001770000000051500000000000023025 0ustar00runnerdocker00000000000000# mode: compile cimport cython # Complex numbers defined in "cython.locals" weren't having their utility code imported directly # leading to compile-errors that the type wasn't defined. The test is intentionally minimal since # anything more thorough ends up creating the utility code @cython.locals(x=complex) cdef f(x): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/complexbasetype.pyx0000644000175100001770000000016200000000000022333 0ustar00runnerdocker00000000000000# mode: compile cdef extern (int *[42]) spam, grail, swallow cdef (int (*)()) brian(): return NULL brian() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/conditional_dependencies.srctree0000644000175100001770000000124500000000000024772 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace ######## setup.py ######## from Cython.Build import cythonize ext_modules = cythonize("foo.pyx") assert set(ext_modules[0].depends) == set(["a.h", "b.h", "c.h", "d.h"]) ######## foo.pyx ######## IF 1: cimport a from b cimport something include "c.pxi" cdef extern from "d.h": pass ######## a.pxd ######## cdef extern from "a.h": pass ######## b.pxd ######## cdef extern from "b.h": cdef void something() ######## c.pxi ######## cdef extern from "c.h": pass ######## a.h ######## /* empty */ ######## b.h ######## /* empty */ ######## c.h ######## /* empty */ ######## d.h ######## /* empty */ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/const_T42.srctree0000644000175100001770000000121400000000000021534 0ustar00runnerdocker00000000000000# tag: cpp PYTHON setup.py build_ext --inplace PYTHON -c "import test" ######## test.pyx ######## # distutils: language = c++ cdef extern from "test.h": ctypedef struct c_Test "Test": const char *getString() except +RuntimeError cdef class Test: cdef c_Test *thisptr def getString(self): return self.thisptr.getString() ######## test.h ######## static const char *astring = "123"; class Test { public: const char *getString(void) { return astring; } }; ######## setup.py ######## from distutils.core import setup from Cython.Build.Dependencies import cythonize setup(name='test', ext_modules=cythonize('*.pyx')) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/const_decl.pyx0000644000175100001770000000113100000000000021241 0ustar00runnerdocker00000000000000# mode: compile cdef const_args(const int a, const int *b, const (int*) c, int *const d, int **const e, int *const *f): print a print b[0] b = NULL # OK, the pointer itself is not const c[0] = 4 # OK, the value is not const d[0] = 7 # OK, the value is not const e[0][0] = 1 # OK, the value is not const e[0] = NULL # OK, the pointed pointer is not const f[0][0] = 1 # OK, the value is not const f = NULL # OK, the pointer is not const def call_const_args(x): cdef int k = x cdef int* arr = [x] const_args(x, &k, &k, &k, &arr, &arr) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/constcast.pyx0000644000175100001770000000024400000000000021131 0ustar00runnerdocker00000000000000# mode: compile from libc.stdlib cimport malloc, free cdef void f(): cdef const int **allocated = malloc(sizeof(int *)) free(allocated) f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/constexpr.pyx0000644000175100001770000000016100000000000021153 0ustar00runnerdocker00000000000000# mode: compile cdef enum Grail: k = 42 cdef enum Spam: a = -1 b = 2 + 3 c = 42 > 17 d = k ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/coventry1.pyx0000644000175100001770000000005700000000000021064 0ustar00runnerdocker00000000000000# mode: compile cdef class Tst: cdef foo, ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cpdef.pyx0000644000175100001770000000013500000000000020210 0ustar00runnerdocker00000000000000# mode: compile cdef class A: cpdef a(self): ma(self) cpdef ma(x): print x ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cpp_class_redefinition.pyx0000644000175100001770000000033200000000000023634 0ustar00runnerdocker00000000000000# mode: compile # tag: cpp, warnings cdef extern from "templates.h": cdef cppclass TemplateTest1[T]: TemplateTest1() T value int t T getValue() cdef cppclass TemplateTest1[T] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cpp_nogil.h0000644000175100001770000000020700000000000020510 0ustar00runnerdocker00000000000000struct NoGilTest1 { NoGilTest1() { } void doSomething() { } }; struct NoGilTest2 { NoGilTest2() { } void doSomething() { } }; ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cpp_nogil.pyx0000644000175100001770000000112200000000000021076 0ustar00runnerdocker00000000000000# tag: cpp # mode: compile cdef extern from "cpp_nogil.h" nogil: cdef cppclass NoGilTest1: NoGilTest1() void doSomething() # This is declared in cpp_nogil.h, but here we're testing # that we can put nogil directly on the cppclass. cdef extern from *: cdef cppclass NoGilTest2 nogil: NoGilTest2() void doSomething() with nogil: NoGilTest1().doSomething() NoGilTest2().doSomething() # We can override nogil methods as with gil methods. cdef cppclass WithGilSubclass(NoGilTest1): void doSomething() noexcept with gil: print "have the gil" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cpp_rvalue_reference_binding.pyx0000644000175100001770000000076200000000000025005 0ustar00runnerdocker00000000000000# tag: cpp, cpp11 # mode: compile cdef extern from *: """ template void accept(T&& x) { (void) x; } """ cdef void accept[T](T&& x) cdef int make_int_py() except *: # might raise Python exception (thus needs a temp) return 1 cdef int make_int_cpp() except +: # might raise C++ exception (thus needs a temp) return 1 def test_func_arg(): # won't compile if move() isn't called on the temp: accept(make_int_py()) accept(make_int_cpp()) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cpp_structs.pyx0000644000175100001770000000046200000000000021503 0ustar00runnerdocker00000000000000# tag: cpp # mode: compile from cython.view import array cdef extern from "point.h" namespace "geometry": cdef struct Point: double x double y int color cdef Point p = Point(0.0, 0.0, 0) the_point = p cdef Point[::1] ps = array((10,), itemsize=sizeof(Point), format='ddi') ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cpp_temp_assignment.pyx0000644000175100001770000000552600000000000023177 0ustar00runnerdocker00000000000000# tag: cpp,cpp11 # mode: compile # tag: no-cpp-locals # TODO cpp_locals works fine with the standard library that comes with gcc11 # but not with gcc8. Therefore disable the test for now cdef extern from *: """ class NoAssignIterator { public: explicit NoAssignIterator(int pos) : pos_(pos) {} NoAssignIterator(NoAssignIterator&) = delete; NoAssignIterator(NoAssignIterator&&) {} NoAssignIterator& operator=(NoAssignIterator&) = delete; NoAssignIterator& operator=(NoAssignIterator&&) { return *this; } // Default constructor of temp variable is needed by Cython // as of 3.0a6. NoAssignIterator() : pos_(0) {} int operator*() { return pos_; } NoAssignIterator operator++() { return NoAssignIterator(pos_ + 1); } int operator!=(NoAssignIterator other) { return pos_ != other.pos_; } int pos_; }; class NoAssign { public: NoAssign() {} NoAssign(NoAssign&) = delete; NoAssign(NoAssign&&) {} NoAssign& operator=(NoAssign&) = delete; NoAssign& operator=(NoAssign&&) { return *this; } void func() {} NoAssignIterator begin() { return NoAssignIterator(0); } NoAssignIterator end() { return NoAssignIterator(2); } }; NoAssign get_NoAssign_Py() { return NoAssign(); } NoAssign get_NoAssign_Cpp() { return NoAssign(); } """ cdef cppclass NoAssignIterator: int operator*() NoAssignIterator operator++() int operator!=(NoAssignIterator) cdef cppclass NoAssign: void func() NoAssignIterator begin() NoAssignIterator end() # might raise Python exception (thus needs a temp) NoAssign get_NoAssign_Py() except * # might raise C++ exception (thus needs a temp) NoAssign get_NoAssign_Cpp() except + cdef internal_cpp_func(NoAssign arg): pass def test_call_to_function(): # will fail to compile if move constructors aren't used internal_cpp_func(get_NoAssign_Py()) internal_cpp_func(get_NoAssign_Cpp()) def test_assignment_to_name(): # will fail if move constructors aren't used cdef NoAssign value value = get_NoAssign_Py() value = get_NoAssign_Cpp() def test_assignment_to_scope(): cdef NoAssign value value = get_NoAssign_Py() value = get_NoAssign_Cpp() def inner(): value.func() cdef class AssignToClassAttr: cdef NoAssign attr def __init__(self): self.attr = get_NoAssign_Py() self.attr = get_NoAssign_Cpp() def test_generator_cpp_iterator_as_temp(): for i in get_NoAssign_Py(): yield i ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cpp_templated_ctypedef.pyx0000644000175100001770000000016400000000000023635 0ustar00runnerdocker00000000000000# tag: cpp # mode: compile cdef extern from *: cdef cppclass Foo[T]: pass ctypedef Foo[int] IntFoo ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cpp_templates.pyx0000644000175100001770000000221300000000000021766 0ustar00runnerdocker00000000000000# tag: cpp # mode: compile # ticket: t767 cdef extern from "templates.h": cdef cppclass TemplateTest1[T]: TemplateTest1() T value int t T getValue() cdef cppclass TemplateTest2[T, U]: TemplateTest2() T value1 U value2 T getValue1() U getValue2() void template_function[T](TemplateTest1[T] &) cdef TemplateTest1[int] a cdef TemplateTest1[int]* b = new TemplateTest1[int]() cdef int c = a.getValue() c = b.getValue() cdef TemplateTest2[int, char] d cdef TemplateTest2[int, char]* e = new TemplateTest2[int, char]() c = d.getValue1() c = e.getValue2() cdef char f = d.getValue2() f = e.getValue2() del b, e ctypedef TemplateTest1[int] TemplateTest1_int cdef TemplateTest1_int aa # Verify that T767 is fixed. cdef public int func(int arg): return arg # Regression test: the function call used to produce # template_function>(__pyx_v_t); # which is valid C++11, but not valid C++98 because the ">>" would be # parsed as a single token. cdef public void use_nested_templates(): cdef TemplateTest1[TemplateTest1[int]] t template_function(t) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cpp_templates_nested.pyx0000644000175100001770000000053000000000000023330 0ustar00runnerdocker00000000000000# tag: cpp # mode: compile from libcpp.vector cimport vector cdef extern from *: cdef cppclass Foo[T]: pass cdef cppclass Bar: pass cdef vector[vector[int]] a cdef vector[vector[const int]] b cdef vector[vector[vector[int]]] c cdef vector[vector[vector[const int]]] d cdef Foo[Foo[Bar]] e cdef Foo[Foo[const Bar]] f ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/cppenum.pyx0000644000175100001770000000114400000000000020577 0ustar00runnerdocker00000000000000# mode: compile # tag: cpp,cpp11 cpdef enum class Spam: a, b c d e f = 42 cpdef enum class Cheese(unsigned int): x = 1 y = 2 cdef enum struct parrot_state: alive = 1 dead = 0 cdef void eggs(): cdef Spam s1 s1 = Spam.a s2 = Spam.b cdef Cheese c1 c1 = Cheese.x eggs() # enum interdependency cdef enum class Color(int): RED = 1 GREEN = 2 cdef enum class Color2(int): RED = ( Color.RED) GREEN = ( Color.GREEN) # enum class as cdef class function parameter cdef class A: cdef Spam f(self, Spam s): return s ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3687222 Cython-3.0.8/tests/compile/create_extension.srctree0000644000175100001770000000120700000000000023316 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace ######## setup.py ######## from Cython.Build import cythonize from Cython.Distutils.extension import Extension ext_modules = [ Extension("foo", ["foo.pyx"]), ] # Example documented in docs/src/reference/compilation.rst from Cython.Build.Dependencies import default_create_extension def my_create_extension(template, kwds): libs = kwds.get('libraries', []) + ["mylib"] kwds['libraries'] = libs return default_create_extension(template, kwds) ext_modules = cythonize(ext_modules, create_extension=my_create_extension) assert ext_modules[0].libraries == ["mylib"] ######## foo.pyx ######## ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/crunchytype.pxd0000644000175100001770000000034000000000000021455 0ustar00runnerdocker00000000000000cdef extern from *: """ struct CrunchyType { int number; PyObject* string; }; """ cdef class crunchytype.Crunchy [ object CrunchyType ]: cdef int number cdef object string ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/cstructreturn.pyx0000644000175100001770000000022000000000000022051 0ustar00runnerdocker00000000000000# mode: compile ctypedef struct Foo: int blarg cdef Foo f(): blarg = 1 + 2 cdef Foo foo foo.blarg = blarg return foo f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ctuple_cimport.pxd0000644000175100001770000000062300000000000022135 0ustar00runnerdocker00000000000000# Verify defined before function prototype cdef (int, int) get_a_ctuple() # Verify defined before typedef ctypedef (int, double) int_double # Verify typedef defined cdef int_double tuple_global = (1, 2.) # Verify defined before opt args cdef void test_opt_args((double, int) x=*) # Verify defined before class declaration cdef class CTupleClass: cdef void get_a_ctuple(self, (double, double) x) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ctuple_cimport_T1427.pyx0000644000175100001770000000026400000000000022764 0ustar00runnerdocker00000000000000# ticket: 1427 # mode: compile cimport ctuple_cimport # Verify same tuple defined in multiple pxd not redeclared ctypedef (int, double) int_double ctuple_cimport.get_a_ctuple() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ctuple_unused_T3543.pyx0000644000175100001770000000025100000000000022607 0ustar00runnerdocker00000000000000# ticket: 3543 # mode: compile # Views define unused ctuples, including (long,) from cython cimport view # Implicitly generate a ctuple (long,) obj = None obj or (1,) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ctypedef.pyx0000644000175100001770000000016300000000000020733 0ustar00runnerdocker00000000000000# mode: compile ctypedef int *IntPtr ctypedef unsigned long ULong cdef extern IntPtr spam cdef extern ULong grail ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ctypedef_public_class_T355.pxd0000644000175100001770000000030700000000000024151 0ustar00runnerdocker00000000000000ctypedef public class Time [type MyTime_Type, object MyTimeObject]: cdef public double seconds ctypedef public class Event [type MyEvent_Type, object MyEventObject]: cdef public Time time ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ctypedef_public_class_T355.pyx0000644000175100001770000000045400000000000024201 0ustar00runnerdocker00000000000000# ticket: t355 # mode: compile ctypedef public class Time [type MyTime_Type, object MyTimeObject]: def __init__(self, seconds): self.seconds = seconds ctypedef public class Event [type MyEvent_Type, object MyEventObject]: def __init__(self, Time time): self.time = time ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ctypedefclass.pyx0000644000175100001770000000010600000000000021756 0ustar00runnerdocker00000000000000# mode: compile ctypedef class spam: pass cdef spam s s = None ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ctypedefenum.pyx0000644000175100001770000000016000000000000021615 0ustar00runnerdocker00000000000000# mode: compile ctypedef enum parrot_state: alive = 1 dead = 2 cdef parrot_state polly polly = dead ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ctypedefpubapi.pyx0000644000175100001770000000043100000000000022132 0ustar00runnerdocker00000000000000# mode: compile ctypedef public api class Foo [type PyFoo_Type, object PyFooObject]: pass cdef api: ctypedef public class Bar [type PyBar_Type, object PyBarObject]: pass cdef public api: ctypedef class Baz [type PyBaz_Type, object PyBazObject]: pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ctypedefstruct.pyx0000644000175100001770000000025200000000000022177 0ustar00runnerdocker00000000000000# mode: compile ctypedef struct order: int spam int eggs cdef order order1 order1.spam = 7 order1.eggs = 2 ctypedef struct linked: int a linked *next ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ctypedefunion.pyx0000644000175100001770000000015100000000000022001 0ustar00runnerdocker00000000000000# mode: compile ctypedef union pet: int cat float dog cdef pet sam sam.cat = 1 sam.dog = 2.7 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/cunsignedlong.pyx0000644000175100001770000000014600000000000021770 0ustar00runnerdocker00000000000000# mode: compile cdef void f(): cdef unsigned long x cdef object y=0 x = y y = x f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/cvardef.pyx0000644000175100001770000000244400000000000020546 0ustar00runnerdocker00000000000000# mode: compile # tag: cdef def f(): cdef char a_char cdef short a_short cdef int i1, i2 cdef long a_long cdef float a_float cdef double a_double cdef unsigned char an_unsigned_char cdef unsigned short an_unsigned_short cdef unsigned int an_unsigned_int cdef unsigned long an_unsigned_long cdef char *a_char_ptr, *another_char_ptr cdef char **a_char_ptr_ptr cdef char ***a_char_ptr_ptr_ptr cdef char[10] a_sized_char_array cdef char[10][20] a_2d_char_array cdef char *a_2d_char_ptr_array[10][20] cdef char **a_2d_char_ptr_ptr_array[10][20] cdef int (*a_0arg_function)() cdef int (*a_1arg_function)(int i) cdef int (*a_2arg_function)(int i, int j) cdef void (*a_void_function)() a_char = 0 a_short = 0 i1 = 0 i2 = 0 a_long = 0 a_float = 0 a_double = 0 an_unsigned_char = 0 an_unsigned_short = 0 an_unsigned_int = 0 an_unsigned_long = 0 a_char_ptr = NULL another_char_ptr = NULL a_char_ptr_ptr = NULL a_char_ptr_ptr_ptr = NULL a_sized_char_array[0] = 0 a_2d_char_array[0][0] = 0 a_2d_char_ptr_array[0][0] = NULL a_2d_char_ptr_ptr_array[0][0] = NULL a_0arg_function = NULL a_1arg_function = NULL a_2arg_function = NULL a_void_function = NULL ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/cverylongtypes.pyx0000644000175100001770000000016400000000000022226 0ustar00runnerdocker00000000000000# mode: compile cdef extern short int s cdef extern long int l cdef extern long long ll cdef extern long double ld ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/cython_compiled_folding.pxd0000644000175100001770000000006000000000000023761 0ustar00runnerdocker00000000000000from libc.math cimport sin, cos, sqrt, tan, log ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/cython_compiled_folding.py0000644000175100001770000000124100000000000023620 0ustar00runnerdocker00000000000000# mode: compile # libc sin, cos and sqrt cimported in the pxd file import cython from cython import compiled if not cython.compiled: from math import sin if cython.compiled: pass else: from math import cos if "aa" == "bb": pass elif cython.compiled: pass elif True: from math import sqrt if "aa" == "bb": pass elif compiled: pass else: from math import tan # log10 isn't defined in the pxd file from math import log10 @cython.test_fail_if_path_exists("//FromImportStatNode//ImportNode") @cython.test_assert_path_exists("//AddNode") def import_log(x, y): if compiled: return x+y else: from math import log ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/declandimpl.pxd0000644000175100001770000000011500000000000021354 0ustar00runnerdocker00000000000000cdef struct Sandwich: int i char *s cdef class Tomato: cdef float danger ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/declandimpl.pyx0000644000175100001770000000021100000000000021376 0ustar00runnerdocker00000000000000# mode: compile cdef class Tomato: def eject(self): pass cdef extern Sandwich butty cdef Tomato supertom supertom = None ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/declarations.srctree0000644000175100001770000000456200000000000022436 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "import declarations" ######## setup.py ######## from distutils.core import setup from Cython.Distutils import build_ext from Cython.Distutils.extension import Extension setup( ext_modules = [ Extension("declarations", ["declarations.pyx", "external_declarations.c"]), ], cmdclass={'build_ext': build_ext}, ) ######## declarations.pyx ######## # mode: compile cdef extern from "declarations.h": pass cdef extern char *cp cdef extern char *cpa[5] cdef extern int (*ifnpa[5])() cdef extern char *(*cpfnpa[5])() cdef extern int (*ifnp)() cdef extern int (*iap)[5] cdef extern int ifn() cdef extern char *cpfn() cdef extern int (*iapfn())[5] cdef extern char *(*cpapfn())[5] cdef extern int fnargfn(int ()) cdef extern int ia[] cdef extern int iaa[][3] cdef extern int a(int[][3], int[][3][5]) cdef void f(): cdef void *p=NULL global ifnp, cpa ifnp = p cdef char *g(): pass f() g() ######## declarations.h ######## #define DLL_EXPORT #include "external_declarations.h" ######## external_declarations.h ######## #ifndef DL_IMPORT #define DL_IMPORT(t) t #elif defined(DLL_EXPORT) #define DL_IMPORT(t) DL_EXPORT(t) #endif #ifdef __cplusplus extern "C" { #endif extern DL_IMPORT(char) *cp; extern DL_IMPORT(char) *cpa[5]; extern DL_IMPORT(int) (*ifnpa[5])(void); extern DL_IMPORT(char) *(*cpfnpa[5])(void); extern DL_IMPORT(int) (*ifnp)(void); extern DL_IMPORT(int) (*iap)[5]; #ifdef __cplusplus } #endif #ifdef __cplusplus extern "C" { #endif extern DL_IMPORT(int) ifn(void); extern DL_IMPORT(char *) cpfn(void); extern DL_IMPORT(int) fnargfn(int (void)); extern DL_IMPORT(int) (*iapfn(void))[5]; extern DL_IMPORT(char *)(*cpapfn(void))[5]; extern DL_IMPORT(int) ia[]; extern DL_IMPORT(int) iaa[][3]; extern DL_IMPORT(int) a(int[][3], int[][3][5]); #ifdef __cplusplus } #endif ######## external_declarations.c ######## #include #ifndef DL_EXPORT #define DL_EXPORT(t) t #endif DL_EXPORT(char) *cp; DL_EXPORT(char) *cpa[5]; DL_EXPORT(int) (*ifnpa[5])(void); DL_EXPORT(char) *(*cpfnpa[5])(void); DL_EXPORT(int) (*ifnp)(void); DL_EXPORT(int) (*iap)[5]; DL_EXPORT(int) ifn(void) {return 0;} DL_EXPORT(char) *cpfn(void) {return 0;} DL_EXPORT(int) fnargfn(int f(void)) {return 0;} DL_EXPORT(int) ia[1]; DL_EXPORT(int) iaa[1][3]; DL_EXPORT(int) a(int a[][3], int b[][3][5]) {return 0;} ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/del.pyx0000644000175100001770000000016600000000000017677 0ustar00runnerdocker00000000000000# mode: compile def f(a, b): global g del g del a[b] del a[b][42] del a.spam del a.spam.eggs ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/distutils_libraries_T845.srctree0000644000175100001770000000123700000000000024566 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace ######## setup.py ######## from Cython.Build import cythonize from Cython.Distutils.extension import Extension ext_modules = [ Extension("a", ["a.pyx"]), Extension("x", ["x.pyx"]), Extension("y", ["y.pyx"]), ] ext_modules = cythonize(ext_modules) assert len(ext_modules[0].libraries) == 2 assert ext_modules[1].libraries == ["lib_x"] assert ext_modules[2].libraries == ["lib_y"] ######## libx.pxd ######## # distutils: libraries = lib_x ######## liby.pxd ######## # distutils: libraries = lib_y ######## a.pyx ######## cimport libx , liby ######## x.pyx ######## cimport libx ######## y.pyx ######## cimport liby ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/docstrings.pyx0000644000175100001770000000044000000000000021305 0ustar00runnerdocker00000000000000# mode: compile "Welcome to the parrot module. It is currently resting." def zap(polly, volts): "Wake up polly." class Parrot: "Standard Norwegian Blue." def admire_plumage(self): "Lovely, ain't it?" cdef class SuperParrot: "Special high-performance model." ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/doda1.pyx0000644000175100001770000000026200000000000020120 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: pass cdef Spam foo(): return blarg() #cdef Spam grail #grail = blarg() #return grail cdef object blarg(): pass foo() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/dotted_cimport.pyx0000644000175100001770000000012600000000000022147 0ustar00runnerdocker00000000000000# mode: compile cimport dotted_cimport_submodule.a import dotted_cimport_submodule.b ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.1047242 Cython-3.0.8/tests/compile/dotted_cimport_submodule/0000755000175100001770000000000000000000000023465 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/dotted_cimport_submodule/__init__.pyx0000644000175100001770000000001500000000000025762 0ustar00runnerdocker00000000000000# empty file ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/dotted_cimport_submodule/a.pxd0000644000175100001770000000000000000000000024410 0ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/drake1.pyx0000644000175100001770000000005400000000000020276 0ustar00runnerdocker00000000000000# mode: compile cdef char *s s = r'\"HT\"' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ellipsis_T488.pyx0000644000175100001770000000016000000000000021500 0ustar00runnerdocker00000000000000# ticket: t488 # mode: compile #from ... import foo print ... def test(): x = ... assert x is Ellipsis ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/emptytry.pyx0000644000175100001770000000012500000000000021023 0ustar00runnerdocker00000000000000# mode: compile cdef void f(): try: pass finally: pass f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/enumintcompat.pyx0000644000175100001770000000061000000000000022010 0ustar00runnerdocker00000000000000# mode: compile cdef enum E: a cdef enum G: b cdef void f(): cdef E e=a cdef G g=b cdef int i, j=0 cdef float f, h=0 i = j | e i = e | j i = j ^ e i = j & e i = j << e i = j >> e i = j + e i = j - e i = j * e i = j / e i = j % e # f = j ** e # Cython prohibits this i = e + g f = h i = ~a i = -a f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/eqcmp.pyx0000644000175100001770000000052700000000000020241 0ustar00runnerdocker00000000000000# mode: compile cdef void foo(): cdef int bool, int1=0, int2=0 cdef float float1=0, float2=0 cdef char *ptr1=NULL, *ptr2=NULL cdef int *ptr3 bool = int1 == int2 bool = int1 != int2 bool = float1 == float2 bool = ptr1 == ptr2 bool = int1 == float2 bool = ptr1 is ptr2 bool = ptr1 is not ptr2 foo() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ewing1.pyx0000644000175100001770000000022000000000000020314 0ustar00runnerdocker00000000000000# mode: compile cdef int blarg(int i): pass cdef void foo(): cdef float f=0 cdef int i if blarg( f): pass foo() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ewing3.pyx0000644000175100001770000000007600000000000020327 0ustar00runnerdocker00000000000000# mode: compile cdef class C: cdef f(self): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ewing4.pyx0000644000175100001770000000011000000000000020315 0ustar00runnerdocker00000000000000# mode: compile cdef void f(): "This is a pseudo doc string." f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ewing5.pyx0000644000175100001770000000007200000000000020325 0ustar00runnerdocker00000000000000# mode: compile cdef char *f(): raise Exception f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ewing6.pyx0000644000175100001770000000056300000000000020333 0ustar00runnerdocker00000000000000# mode: compile # Spurious gcc3.3 warnings about incompatible pointer # types passed to C method # Ordering of declarations in C code is important cdef class C cdef class D(C) cdef class E cdef class C: cdef void a(self): pass cdef class D(C): cdef void m(self, E e): pass cdef class E: pass cdef void f(D d, E e): d.m(e) f(D(),E()) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ewing7.pyx0000644000175100001770000000027700000000000020336 0ustar00runnerdocker00000000000000# mode: compile cdef class A: cdef void f(self, x): pass cdef class B(A): cdef void f(self, object x): pass cdef extern void g(A a, b) cdef extern void g(A a, b) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ewing8.pxd0000644000175100001770000000024400000000000020304 0ustar00runnerdocker00000000000000cdef struct Foo cdef class Blarg ctypedef Foo FooType ctypedef Blarg BlargType cdef struct Foo: FooType *f cdef class Blarg: cdef FooType *f cdef BlargType b ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ewing8.pyx0000644000175100001770000000005400000000000020330 0ustar00runnerdocker00000000000000# mode: compile cdef class Blarg: pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ewing9.pxd0000644000175100001770000000002300000000000020300 0ustar00runnerdocker00000000000000cdef struct xmlDoc ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ewing9.pyx0000644000175100001770000000005700000000000020334 0ustar00runnerdocker00000000000000# mode: compile cdef struct xmlDoc: int i ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/excvalcheck.h0000644000175100001770000000030200000000000021012 0ustar00runnerdocker00000000000000extern DL_EXPORT(int) spam(void); extern DL_EXPORT(void) grail(void); extern DL_EXPORT(char *)tomato(void); int spam(void) {return 0;} void grail(void) {return;} char *tomato(void) {return 0;} ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/excvalcheck.pyx0000644000175100001770000000041700000000000021412 0ustar00runnerdocker00000000000000# mode: compile cdef extern from "excvalcheck.h": pass cdef extern int spam() except -1 cdef extern void grail() except * cdef extern char *tomato() except? NULL cdef void eggs(): cdef int i cdef char *p i = spam() grail() p = tomato() eggs() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/excvaldecl.pyx0000644000175100001770000000045200000000000021243 0ustar00runnerdocker00000000000000# mode: compile cdef int spam() except 42: pass cdef float eggs() except 3.14: pass cdef char *grail() except NULL: pass cdef int tomato() except *: pass cdef int brian() except? 0: pass cdef int silly() except -1: pass spam() eggs() grail() tomato() brian() silly() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/excvalreturn.pyx0000644000175100001770000000010200000000000021643 0ustar00runnerdocker00000000000000# mode: compile cdef int spam() except -1: eggs = 42 spam() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extargdefault.pyx0000644000175100001770000000021300000000000021763 0ustar00runnerdocker00000000000000# mode: compile cdef extern class somewhere.Swallow: pass cdef Swallow swallow def spam(x = swallow, Swallow y = swallow): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extcmethcall.pyx0000644000175100001770000000046500000000000021612 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: cdef int tons cdef void add_tons(self, int x): pass cdef class SuperSpam(Spam): pass cdef void tomato(): cdef Spam spam cdef SuperSpam superspam = SuperSpam() spam = superspam spam.add_tons(42) superspam.add_tons(1764) tomato() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extcoerce.pyx0000644000175100001770000000041400000000000021110 0ustar00runnerdocker00000000000000# mode: compile cdef class Grail: def __add__(int x, float y): pass cdef class Swallow: pass def f(Grail g): cdef int i = 0 cdef Swallow s = Swallow() cdef object x = Grail() g = x x = g g = i i = g g = s s = g ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extdelattr.pyx0000644000175100001770000000011600000000000021306 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: def __delattr__(self, n): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extdelitem.pyx0000644000175100001770000000011600000000000021272 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: def __delitem__(self, i): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extdelslice.pyx0000644000175100001770000000015000000000000021431 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: def __delslice__(self, Py_ssize_t i, Py_ssize_t j): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extdescrdel.pyx0000644000175100001770000000011400000000000021432 0ustar00runnerdocker00000000000000# mode: compile cdef class Foo: def __delete__(self, i): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extdescrget.pyx0000644000175100001770000000011400000000000021445 0ustar00runnerdocker00000000000000# mode: compile cdef class Foo: def __get__(self, i, c): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extdescrset.pyx0000644000175100001770000000011400000000000021461 0ustar00runnerdocker00000000000000# mode: compile cdef class Foo: def __set__(self, i, v): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extern.pyx0000644000175100001770000000023600000000000020436 0ustar00runnerdocker00000000000000# mode: compile cdef extern int i cdef extern char *s[] cdef extern void spam(char c) cdef extern int eggs(): pass cdef int grail(): pass grail() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extexttype.pyx0000644000175100001770000000043600000000000021356 0ustar00runnerdocker00000000000000# mode: compile cdef extern class external.Spam [object SpamObject]: pass ctypedef extern class external.Grail [object Grail]: pass cdef extern from "food.h": class external.Tomato [object Tomato]: pass class external.Bicycle [object Bicycle]: pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extforward.pyx0000644000175100001770000000014300000000000021313 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam cdef class Grail: cdef Spam spam cdef class Spam: pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extgetattr.pyx0000644000175100001770000000011600000000000021321 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: def __getattr__(self, x): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extgetitem.pyx0000644000175100001770000000011700000000000021306 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: def __getitem__(self, x): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/exthash.pyx0000644000175100001770000000011100000000000020565 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: def __hash__(self): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extimported.pyx0000644000175100001770000000012500000000000021472 0ustar00runnerdocker00000000000000# mode: compile cdef extern class Spam.Eggs.Ham: pass cdef Ham ham ham = None ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extimportedsubtype.pyx0000644000175100001770000000020600000000000023106 0ustar00runnerdocker00000000000000# mode: compile from crunchytype cimport Crunchy cdef class Sub2(Crunchy): cdef char character cdef class Sub1(Sub2): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extindex.pyx0000644000175100001770000000011600000000000020756 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: def __index__(self): return 42 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extinheritdel.pyx0000644000175100001770000000031700000000000022001 0ustar00runnerdocker00000000000000# mode: compile cdef class Parrot: pass cdef class Norwegian(Parrot): def __delitem__(self, i): pass def __delattr__(self, n): pass def __delete__(self, i): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extinheritset.pyx0000644000175100001770000000032500000000000022027 0ustar00runnerdocker00000000000000# mode: compile cdef class Parrot: pass cdef class Norwegian(Parrot): def __setitem__(self, i, x): pass def __setattr__(self, n, x): pass def __set__(self, i, v): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extpropertyall.pyx0000644000175100001770000000032000000000000022221 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: property eggs: "Ova" def __get__(self): pass def __set__(self, x): pass def __del__(self): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extpropertydel.pyx0000644000175100001770000000014300000000000022220 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: property eggs: def __del__(self): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extpropertydoc.pyx0000644000175100001770000000010500000000000022217 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: property eggs: "Ova" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extpropertyget.pyx0000644000175100001770000000014400000000000022234 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: property eggs: def __get__(self): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extpropertyset.pyx0000644000175100001770000000014600000000000022252 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: property eggs: def __set__(self, x): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extpymemberdef.pyx0000644000175100001770000000057000000000000022152 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: cdef public char c cdef public int i cdef public long l cdef public unsigned char uc cdef public unsigned int ui cdef public unsigned long ul cdef public float f cdef public double d cdef public char *s cdef readonly char[42] a cdef public object o cdef readonly int r cdef readonly Spam e ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extsetattr.pyx0000644000175100001770000000012100000000000021331 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: def __setattr__(self, n, x): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extsetitem.pyx0000644000175100001770000000012100000000000021315 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: def __setitem__(self, i, x): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/extsetslice.pyx0000644000175100001770000000015300000000000021463 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: def __setslice__(self, Py_ssize_t i, Py_ssize_t j, x): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/finally_GH1744.pyx0000644000175100001770000000350300000000000021465 0ustar00runnerdocker00000000000000# mode: compile # This caused a "maximum recursion depth exceeded" at some point, # see https://github.com/cython/cython/issues/1744 cdef inline bint g(int x, int y): return True cdef cython_bug(int u): try: g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) g(u, u) finally: g(u, u) cython_bug(1) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/find_pxd.srctree0000644000175100001770000000204300000000000021551 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace ######## setup.py ######## from Cython.Build import cythonize from Cython.Distutils.extension import Extension import sys sys.path.insert(0, "path") ext_modules = [ Extension("a", ["a.pyx"]), Extension("b", ["b.pyx"]), Extension("c", ["c.pyx"]), Extension("d", ["d.pyx"]), ] ext_modules = cythonize(ext_modules, include_path=["include"]) ######## a.pyx ######## # Implicit cimport looking in include_path cdef my_type foo ######## include/a.pxd ######## ctypedef int my_type ######## b.pyx ######## # Explicit cimport looking in sys.path from b cimport * cdef my_type foo ######## path/b.pxd ######## ctypedef int my_type ######## c.pyx ######## # Implicit cimport NOT looking in sys.path ######## path/c.pxd ######## +++syntax error just to show that this file is not actually cimported+++ ######## path/numpy/__init__.pxd ######## # gh-2905: This should be found before Cython/Includes/numpy/__init__.pxd ctypedef int my_type ######## d.pyx ######## cimport numpy cdef numpy.my_type foo ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/first_assignment.pyx0000644000175100001770000000146300000000000022513 0ustar00runnerdocker00000000000000# mode: compile cimport cython @cython.test_assert_path_exists( "//SingleAssignmentNode", "//SingleAssignmentNode[./NameNode[@name = 'a']]", "//SingleAssignmentNode[./NameNode[@name = 'a'] and @first = True]", ) def test_cdef(): cdef int a = 1 @cython.test_assert_path_exists( "//SingleAssignmentNode", "//SingleAssignmentNode[./NameNode[@name = 'a']]", # FIXME: currently not working # "//SingleAssignmentNode[./NameNode[@name = 'a'] and @first = True]", ) def test_py(): a = 1 @cython.test_assert_path_exists( "//SingleAssignmentNode", "//SingleAssignmentNode[./NameNode[@name = 'a']]", # FIXME: currently not working # "//SingleAssignmentNode[./NameNode[@name = 'a'] and @first = True]", ) def test_cond(): if True: a = 1 else: a = 2 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/food.h0000644000175100001770000000010600000000000017463 0ustar00runnerdocker00000000000000struct Tomato { PyObject_HEAD }; struct Bicycle{ PyObject_HEAD }; ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/for.pyx0000644000175100001770000000046300000000000017721 0ustar00runnerdocker00000000000000# mode: compile def f(a, b, c): cdef int i for a in b: i = 1 continue i = 2 break i = 3 for i in b: i = 1 for a in "spam": i = 1 for a[b] in c: i = 1 for a,b in c: i = 1 for a in b,c: i = 1 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/forfromelse.pyx0000644000175100001770000000032300000000000021451 0ustar00runnerdocker00000000000000# mode: compile cdef void spam(): cdef int i, j=0, k=0 for i from 0 <= i < 10: j = k else: k = j # new syntax for 0 <= i < 10: j = i else: j = k spam() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/formfeed.pyx0000644000175100001770000000005700000000000020721 0ustar00runnerdocker00000000000000# mode: compile cdef int x x = 42 y = 88 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/forward.pyx0000644000175100001770000000121600000000000020574 0ustar00runnerdocker00000000000000# mode: compile ctypedef enum MyEnum: Value1 Value2 Value3 = 100 cdef MyEnum my_enum = Value3 ctypedef struct StructA: StructA *a StructB *b cdef struct StructB: StructA *a StructB *b cdef class ClassA: cdef ClassA a cdef ClassB b ctypedef public class ClassB [ object ClassB, type TypeB ]: cdef ClassA a cdef ClassB b cdef StructA struct_a cdef StructB struct_b struct_a.a = &struct_a struct_a.b = &struct_b struct_b.a = &struct_a struct_b.b = &struct_b cdef ClassA class_a = ClassA() cdef ClassB class_b = ClassB() class_a.a = class_a class_a.b = class_b class_b.a = class_a class_b.b = class_b ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/fromimport.pyx0000644000175100001770000000234300000000000021330 0ustar00runnerdocker00000000000000# mode: compile def f(): from spam import eggs from spam.morespam import bacon, eggs, ham from spam import eggs as ova from . import spam from ... import spam from .. . import spam from . .. import spam from . . . import spam from .. import spam, foo from . . import spam, foo from ... import spam, foobar from .. . import spam, foobar from . .. import spam, foobar from . . . import spam, foobar from .spam import foo from . spam import foo from ...spam import foo, bar from .. . spam import foo, bar from . .. spam import foo, bar from . . . spam import foo, bar from ...spam.foo import bar from ... spam.foo import bar from .. . spam.foo import bar from . .. spam.foo import bar from . . . spam.foo import bar from ...spam.foo import foo, bar from ... spam.foo import foo, bar from .. . spam.foo import foo, bar from . .. spam.foo import foo, bar from . . . spam.foo import foo, bar from ...spam.foo import (foo, bar) from ... spam.foo import (foo, bar) from .. . spam.foo import (foo, bar) from .. . spam.foo import (foo, bar) from . .. spam.foo import (foo, bar) from . . . spam.foo import (foo, bar) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/fromimport_star.pyx0000644000175100001770000000041200000000000022354 0ustar00runnerdocker00000000000000# mode: compile from spam import * from ...spam.foo import * from ... spam.foo import * from .. . spam.foo import * from . . . spam.foo import * from . .. spam.foo import * from . import * from ... import * from .. . import * from . .. import * from . . . import * ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/fused_buffers.pyx0000644000175100001770000000071600000000000021756 0ustar00runnerdocker00000000000000# mode: compile # cython: test_assert_c_code_has = __Pyx_ImportNumPyArrayTypeIfAvailable # cython: test_assert_c_code_has = ndarray # counterpart test to fused_no_numpy - buffer types are compared against Numpy # dtypes as a quick test. fused_no_numpy tests that the mechanism isn't # accidentally generated, while this just confirms that the same mechanism is # still in use ctypedef fused IntOrFloat: int float def f(IntOrFloat[:] x): return x ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/fused_no_numpy.pyx0000644000175100001770000000053200000000000022162 0ustar00runnerdocker00000000000000# mode: compile # cython: test_fail_if_c_code_has = __Pyx_ImportNumPyArrayTypeIfAvailable ctypedef fused IntOrFloat: int float # This function does not use buffers so has no reason to import numpy to # look up dtypes. fused_buffers.pyx is the corresponding test for the case # where numpy is imported def f(IntOrFloat x): return x ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/fused_redeclare_T3111.pyx0000644000175100001770000000200300000000000023030 0ustar00runnerdocker00000000000000# ticket: 3111 # mode: compile # tag: warnings ctypedef unsigned char npy_uint8 ctypedef unsigned short npy_uint16 ctypedef fused dtype_t: npy_uint8 ctypedef fused dtype_t_out: npy_uint8 npy_uint16 def foo(dtype_t[:] a, dtype_t_out[:, :] b): pass # The primary thing we're trying to test here is the _absence_ of the warning # "__pyxutil:16:4: '___pyx_npy_uint8' redeclared". The remaining warnings are # unrelated to this test. _WARNINGS = """ # cpdef redeclaration bug, from TestCythonScope.pyx 25:10: 'cpdef_method' redeclared 36:10: 'cpdef_cname_method' redeclared # from MemoryView.pyx 961:29: Ambiguous exception value, same as default return value: 0 961:29: Ambiguous exception value, same as default return value: 0 1002:46: Ambiguous exception value, same as default return value: 0 1002:46: Ambiguous exception value, same as default return value: 0 1092:29: Ambiguous exception value, same as default return value: 0 1092:29: Ambiguous exception value, same as default return value: 0 """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/fused_unused.pyx0000644000175100001770000000022700000000000021622 0ustar00runnerdocker00000000000000# mode: compile # tag: fused # This previously lead to a crash due to an empty module body. ctypedef fused cinteger: int long Py_ssize_t ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/fused_wraparound.pyx0000644000175100001770000000070400000000000022501 0ustar00runnerdocker00000000000000# mode: compile # tag: fused, werror """ Very short test for https://github.com/cython/cython/issues/3492 (Needs its own file since werror fails on the main fused-test files) wraparound and boundscheck directives shouldn't break the fused dispatcher function """ cimport cython ctypedef fused fused_t: str int long complex @cython.wraparound(False) @cython.boundscheck(False) def func(fused_t a, cython.floating b): return a, b ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/future_imports.pyx0000644000175100001770000000034500000000000022221 0ustar00runnerdocker00000000000000# mode: compile from __future__ import nested_scopes from __future__ import with_statement pass from __future__ import nested_scopes ; from __future__ import nested_scopes from __future__ import print_function print(end='') ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/gencall.pyx0000644000175100001770000000024300000000000020534 0ustar00runnerdocker00000000000000# mode: compile def f(x, y): x = y def z(a, b, c): f(x = 42, y = "spam") f(*a) f(**b) f(x = 42, **b) f(a, *b) f(a, x = 42, *b, **c) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/getattr3ref.pyx.BROKEN0000644000175100001770000000012500000000000022337 0ustar00runnerdocker00000000000000__doc__ = """ >>> print f() """ def f(): g = getattr3 return g.__name__ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/globalonly.pyx0000644000175100001770000000006100000000000021267 0ustar00runnerdocker00000000000000# mode: compile global __name__ print __name__ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/globalstmt.pyx0000644000175100001770000000010100000000000021270 0ustar00runnerdocker00000000000000# mode: compile def f(): global a,b,c,d a = b c = d ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/globvardef.pyx0000644000175100001770000000017500000000000021246 0ustar00runnerdocker00000000000000# mode: compile cdef int a_global_int cdef a_global_pyobject a_global_int = 0 a_global_pyobject = None cdef object unused ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/gustafsson2.pyx0000644000175100001770000000031400000000000021404 0ustar00runnerdocker00000000000000# mode: compile ctypedef enum someenum_t: ENUMVALUE_1 ENUMVALUE_2 cdef somefunction(someenum_t val): if val == ENUMVALUE_1: pass somefunction(ENUMVALUE_1) somefunction(ENUMVALUE_2) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/hinsen1.h0000644000175100001770000000006000000000000020100 0ustar00runnerdocker00000000000000typedef struct { PyObject_HEAD } PySpamObject; ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/hinsen1.pyx.BROKEN0000644000175100001770000000043500000000000021456 0ustar00runnerdocker00000000000000__doc__ = """ >>> test() 1 """ cdef extern from "hinsen1.h": ctypedef class spam.Spam [object PySpamObject]: pass cdef class SpamAndEggs(Spam): cdef cook(self): return 1 def test(): cdef SpamAndEggs s s = SpamAndEggs() return s.cook() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/hinsen2.pyx0000644000175100001770000000021500000000000020474 0ustar00runnerdocker00000000000000# mode: compile cdef class vector: def __div__(vector self, double factor): cdef object result = vector() return result ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/huss2.pyx0000644000175100001770000000030500000000000020172 0ustar00runnerdocker00000000000000# mode: compile cdef enum Color: red white blue cdef void f(): cdef Color e cdef int i i = red i = red + 1 i = red | 1 e = white i = e i = e + 1 f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ia_cdefblock.pyx0000644000175100001770000000063400000000000021520 0ustar00runnerdocker00000000000000# mode: compile cdef: struct PrivFoo: int i int priv_i void priv_f(): global priv_i priv_i = 42 cdef public: struct PubFoo: int i int pub_v void pub_f(): pass class PubBlarg [object PubBlargObj, type PubBlargType]: pass cdef api: void api_f(): pass cdef public api: void pub_api_f(): pass priv_f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/import.pyx0000644000175100001770000000016400000000000020443 0ustar00runnerdocker00000000000000# mode: compile def f(): import spam import spam.eggs import spam, eggs, ham import spam as tasty ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/index.pyx0000644000175100001770000000064600000000000020245 0ustar00runnerdocker00000000000000# mode: compile def f(obj1, obj2, obj3): cdef int int1, int2=0, int3=0 cdef float flt1, *ptr1=NULL cdef int[42] array1 array1[int2] = 0 int1 = array1[int2] flt1 = ptr1[int2] array1[int1] = int2 ptr1[int1] = int2 obj1 = obj2[obj3] int1 = array1[obj3] obj1 = obj2[int3] obj1[obj2] = obj3 array1[obj2] = int3 obj1[int2] = obj3 obj1[obj2] = 42 f(None, None, None) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/indices.pyx0000644000175100001770000000027100000000000020546 0ustar00runnerdocker00000000000000# mode: compile cdef int* a cdef object x cdef int f(int i): print i return i x[f(1)] = 3 a[f(1)] = 3 x[f(2)] += 4 a[f(2)] += 4 print x[1] print a[1] x[f(1)] = 15 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/inplace_lhs.pyx0000644000175100001770000000075300000000000021416 0ustar00runnerdocker00000000000000# mode: compile cdef struct S: int q def test(): cdef int i = 1, j = 2, k = 3 cdef float x = 1, y = 2, z = 3 cdef object a = 1, b = 2, c = 3, d = 4, e = 5 cdef int[3] m m[0] = 0 m[1] = 1 m[2] = 1 cdef S s = [1] global g i += j + k x += y + z x += i a += b + c g += a m[i] += j a[i] += b + c a[b + c] += d (a + b)[c] += d a[i : j] += b (a + b)[i : j] += c a.b += c + d (a + b).c += d s.q += i ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/inplace_ops.pyx0000644000175100001770000000036200000000000021425 0ustar00runnerdocker00000000000000# mode: compile def test(): cdef object a = 1, b = 2 cdef char *p = 'abc' a += b a -= b a *= b a /= b a %= b a **= b a <<= b a >>= b a &= b a ^= b a |= b p += 42 p -= 42 p += a ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ishimoto1.pyx0000644000175100001770000000011300000000000021037 0ustar00runnerdocker00000000000000# mode: compile cdef class A: def __getitem__(self, x): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/ishimoto4.pyx0000644000175100001770000000007000000000000021044 0ustar00runnerdocker00000000000000# mode: compile cdef void __stdcall f(): pass f() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3727221 Cython-3.0.8/tests/compile/jiba3.pyx0000644000175100001770000000062700000000000020125 0ustar00runnerdocker00000000000000# mode: compile cdef class Position cdef class Point(Position) cdef class Vector(Point) cdef class CoordSyst cdef void test(float* f): pass cdef class Position: cdef readonly CoordSyst parent cdef class Point(Position): cdef void bug(self): test(self.parent._matrix) cdef class Vector(Point): cdef void bug(self): test(self.parent._matrix) cdef class CoordSyst: cdef float* _matrix ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/jiba4.pyx0000644000175100001770000000005700000000000020123 0ustar00runnerdocker00000000000000# mode: compile cdef class A: cdef object x ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/jiba5.pyx0000644000175100001770000000013200000000000020116 0ustar00runnerdocker00000000000000# mode: compile def f(): cdef int i=0 global mylist del mylist[i] return ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/jiba6.pyx0000644000175100001770000000030100000000000020115 0ustar00runnerdocker00000000000000# mode: compile cdef extern from "string.h": void memcpy(void* des, void* src, int size) cdef void f(): cdef float[3] f1 cdef float* f2 f2 = f1 + 1 memcpy(f1, f2, 1) f() ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/johnson1.pyx0000644000175100001770000000016500000000000020671 0ustar00runnerdocker00000000000000# mode: compile ctypedef enum foo: FOO cdef void func(): cdef foo x map = [FOO] x = map[0] func() ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/johnson2.pyx0000644000175100001770000000012000000000000020661 0ustar00runnerdocker00000000000000# mode: compile cdef class C: cdef object foo cdef object __weakref__ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/khavkine1.pyx0000644000175100001770000000020200000000000021003 0ustar00runnerdocker00000000000000# mode: compile cdef class T: cdef int[1] a cdef object b cdef void f(void *obj): ( obj).a[0] = 1 b = None f(NULL) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/kleckner1.pyx0000644000175100001770000000011200000000000021001 0ustar00runnerdocker00000000000000# mode: compile def f(x,): pass cdef void g(int x,): pass g(0) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/lepage_2.pyx0000644000175100001770000000010100000000000020576 0ustar00runnerdocker00000000000000# mode: compile ctypedef struct BB: void (*f) (void* state) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/libc_all.pyx0000644000175100001770000000144300000000000020673 0ustar00runnerdocker00000000000000# mode: compile cimport libc cimport libc.stdio cimport libc.errno cimport libc.float cimport libc.limits cimport libc.locale cimport libc.signal cimport libc.stddef #cimport libc.stdint # XXX MSVC cimport libc.stdio cimport libc.stdlib cimport libc.string from libc cimport errno from libc cimport float from libc cimport limits from libc cimport locale from libc cimport signal from libc cimport stddef #from libc cimport stdint # XXX MSVC from libc cimport stdio from libc cimport stdlib from libc cimport string from libc.errno cimport * from libc.float cimport * from libc.limits cimport * from libc.locale cimport * from libc.signal cimport * from libc.stddef cimport * #from libc.stdint cimport * # XXX MSVC from libc.stdio cimport * from libc.stdlib cimport * from libc.string cimport * ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/libc_errno.pyx0000644000175100001770000000020600000000000021244 0ustar00runnerdocker00000000000000# mode: compile from libc.errno cimport * if errno == EDOM : pass if errno == EILSEQ : pass if errno == ERANGE : pass errno = 0 ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/libc_signal.pyx0000644000175100001770000000054300000000000021400 0ustar00runnerdocker00000000000000# mode: compile from libc.signal cimport * cdef void sighdl(int signum) noexcept nogil: pass cdef sighandler_t h h = signal(SIGABRT, sighdl) if h == SIG_ERR: pass h = signal(SIGABRT, SIG_IGN) if h == SIG_ERR: pass h = signal(SIGABRT, SIG_DFL) if h == SIG_ERR: pass h = signal(SIGABRT, SIG_IGN) cdef int e = raise_(SIGABRT) h = signal(SIGABRT, h) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/libc_stdio.pyx0000644000175100001770000000066300000000000021250 0ustar00runnerdocker00000000000000# mode: compile cimport libc.stdio from libc cimport stdio from libc.stdio cimport printf, puts, fputs, putchar, fputc, putc, stdout with nogil: libc.stdio.printf("hello %s\n", b"world") stdio.printf("hello %s\n", b"world") printf("hello %s\n", b"world") printf("printf_output %d %d\n", 1, 2) puts("puts_output") fputs("fputs_output", stdout) putchar(b'z') fputc(b'x', stdout) putc(b'c', stdout) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/longunsigned.pyx0000644000175100001770000000011100000000000021615 0ustar00runnerdocker00000000000000# mode: compile cdef extern unsigned long x cdef extern long unsigned y ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/magcmp.pyx0000644000175100001770000000025100000000000020372 0ustar00runnerdocker00000000000000# mode: compile cdef void foo(): cdef int bool, int1=0, int2=0 bool = int1 < int2 bool = int1 > int2 bool = int1 <= int2 bool = int1 >= int2 foo() ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/min_async.pyx0000644000175100001770000000023200000000000021105 0ustar00runnerdocker00000000000000# mode: compile # tag: pep492, await # Need to include all utility code ! async def sleep(x): pass async def call(): await sleep(1) yield ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/module_name_arg.srctree0000644000175100001770000000230400000000000023074 0ustar00runnerdocker00000000000000# Test that we can set module name with --module-name arg to cython CYTHON a.pyx CYTHON --module-name w b.pyx CYTHON --module-name my_module.submod.x c.pyx PYTHON setup.py build_ext --inplace PYTHON checks.py ######## checks.py ######## from importlib import import_module try: exc = ModuleNotFoundError except NameError: exc = ImportError for module_name, should_import in ( ('a', True), ('b', False), ('w', True), ('my_module.submod.x', True), ('c', False), ): try: import_module(module_name) except exc: if should_import: assert False, "Cannot import module " + module_name else: if not should_import: assert False, ("Can import module " + module_name + " but import should not be possible") ######## setup.py ######## from distutils.core import setup from distutils.extension import Extension setup( ext_modules = [ Extension("a", ["a.c"]), Extension("w", ["b.c"]), Extension("my_module.submod.x", ["c.c"]), ], ) ######## a.pyx ######## ######## b.pyx ######## ######## c.pyx ######## ######## my_module/__init__.py ######## ######## my_module/submod/__init__.py ######## ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/msvc_strings.pyx0000644000175100001770000021454100000000000021660 0ustar00runnerdocker00000000000000# mode: compile """A long module docstring. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer sit amet mauris mauris, sit amet venenatis nisl. Vivamus a est porta enim sollicitudin mollis. Proin fringilla massa vel ante gravida luctus. Nunc quis nunc id quam hendrerit posuere. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam porttitor interdum sollicitudin. Mauris malesuada tellus tellus. Mauris condimentum nunc et sapien pellentesque gravida. Suspendisse sed ipsum orci. Duis ut lacus dui. Integer ac gravida sem. Vivamus fermentum porttitor velit ac blandit. Maecenas pulvinar ullamcorper enim, vitae aliquet tortor scelerisque et. Vestibulum ante massa, sodales et bibendum dignissim, consectetur vitae metus. Quisque vel dui erat, vel commodo metus. Aliquam arcu dolor, viverra sit amet porttitor a, faucibus eu augue. Sed ornare, enim eget ultricies suscipit, nunc dui lacinia enim, vitae tempus nunc libero vitae ligula. Nam et commodo ligula. Pellentesque tincidunt lorem at elit aliquam at fringilla libero tempor. Donec molestie consectetur nibh, ac varius ante dictum id. Suspendisse lectus nibh, molestie vel dapibus eget, egestas ut eros. Mauris vel mauris turpis, vitae bibendum nunc. Vestibulum nulla enim, vestibulum vitae tincidunt et, gravida eu metus. Nulla sagittis, odio a placerat laoreet, arcu lectus vestibulum nunc, in hendrerit tortor quam sit amet turpis. In et purus vel dui pellentesque tincidunt. Donec dictum nibh sed quam luctus sit amet luctus justo dapibus. Integer nulla elit, lacinia aliquet euismod sed, tempus vitae lectus. Fusce non sapien dolor. Suspendisse ut est ut dui tempor ultricies id ut elit. Aenean adipiscing sollicitudin enim, nec porttitor est porttitor eget. Proin lobortis ante ut diam sodales volutpat. Donec urna diam, porttitor nec laoreet ut, rhoncus non diam. Ut sed mi vitae turpis semper semper. Integer sit amet lorem sapien. Aliquam risus diam, vulputate id sagittis et, molestie ut lectus. Aliquam erat volutpat. Morbi aliquet venenatis metus in posuere. Cras vitae purus nunc, ut vestibulum ipsum. Nullam vehicula dui in urna iaculis lobortis. Ut a est non est tincidunt iaculis. Vivamus rutrum velit non nunc malesuada sed bibendum mi iaculis. Sed id lacus in sem tempor vestibulum. Cras bibendum accumsan suscipit. Phasellus congue nisl consectetur turpis rhoncus aliquet posuere libero fringilla. Sed eros tellus, hendrerit nec imperdiet vitae, blandit ac dolor. Nulla facilisi. Morbi ullamcorper libero odio, at cursus tortor. Cras ultricies tellus eget justo cursus cursus. Donec at mi massa, auctor suscipit sem. Proin dolor purus, semper sed ultrices ut, iaculis at tortor. Donec risus enim, interdum et convallis nec, aliquam eget velit. Curabitur eget lectus dolor. Integer id turpis eu nulla euismod tincidunt. Fusce elit nibh, dapibus sit amet tempus ac, convallis eu libero. Donec dui justo, molestie sed euismod porta, ultricies id orci. Praesent a tellus et risus faucibus porttitor pellentesque in purus. Fusce blandit risus ac tortor viverra vitae molestie odio convallis. Donec rhoncus volutpat mauris, sit amet mattis libero dapibus id. Ut rhoncus venenatis nisi ac dictum. In non nulla eget massa convallis facilisis. Praesent nec odio id odio semper lobortis non eu erat. Proin quis gravida magna. Sed rhoncus lectus auctor arcu posuere a auctor dui pellentesque. Sed enim nulla, luctus quis sagittis sed, vestibulum eget metus. Mauris ornare pretium fringilla. Proin ligula eros, fermentum in placerat sit amet, placerat vel mauris. Nulla magna enim, luctus eget euismod ac, lacinia vel lorem. Duis mi leo, porttitor vitae dictum ac, ultrices iaculis metus. Quisque libero mi, aliquet quis vestibulum eget, porttitor non justo. Praesent ac metus felis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec vel enim sit amet ante imperdiet commodo sed vel nisi. Praesent semper viverra nulla vehicula sollicitudin. Fusce lacinia aliquet ullamcorper. Donec vitae diam est. Integer volutpat hendrerit turpis ut bibendum. Integer et dui augue. Nunc ut nisl in felis feugiat semper nec sit amet purus. Proin convallis ultrices nisl ut vehicula. Pellentesque neque mi, elementum vel placerat nec, laoreet ac nulla. Pellentesque aliquam dui a metus iaculis posuere. Curabitur dapibus faucibus metus. Donec quis diam dui. Proin at mi nec augue cursus pulvinar eu vel metus. Curabitur eget turpis ac risus dignissim luctus sed id ligula. Etiam lectus neque, varius ut euismod nec, euismod quis nulla. Ut feugiat, quam id tempor luctus, metus eros lacinia diam, nec dapibus tellus dui quis diam. Nam interdum, orci id fringilla mattis, ipsum eros pellentesque turpis, hendrerit dignissim justo dui interdum ante. Curabitur aliquam nisi ut dui lacinia tempor. Nulla lobortis tellus non sapien dignissim ut dapibus dui aliquet. Nam scelerisque, urna a aliquam malesuada, mi tortor scelerisque libero, quis pellentesque erat eros ut justo. Phasellus nulla purus, suscipit vel gravida euismod, malesuada et odio. Vestibulum non libero eget lacus venenatis auctor quis a est. Nunc id leo est. Curabitur pulvinar viverra sapien at viverra. Cras pretium justo et lorem lobortis id tempor nisi accumsan. Cras egestas tortor in risus hendrerit eu varius purus suscipit. Nullam mauris eros, mattis at tempor vitae, mollis vitae velit. Etiam at adipiscing lectus. Quisque molestie, metus id posuere pharetra, lorem enim vehicula mauris, ut ultricies purus justo a lacus. Vivamus blandit euismod adipiscing. Nam eu ligula at elit ultricies tempus. Nunc ac sodales neque. Ut dui diam, porttitor a pulvinar vel, sodales sit amet turpis. Donec vitae eros at neque luctus scelerisque. In consequat elementum iaculis. Donec ullamcorper dolor eu quam volutpat rhoncus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras laoreet ante eget dolor sagittis imperdiet. Proin magna urna, porta id blandit nec, commodo eget lorem. Etiam imperdiet, orci sit amet rutrum consectetur, orci augue tempus lacus, id venenatis sapien nisl a est. Sed accumsan massa sed libero consectetur scelerisque. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed nunc risus, lobortis id egestas nec, suscipit id magna. Morbi at iaculis mauris. Proin felis sem, tempus non pellentesque congue, vehicula sit amet eros. Maecenas porttitor erat ac dolor pharetra iaculis. Cras tincidunt, nulla eget malesuada egestas, sem diam consequat quam, sed feugiat nulla orci at mauris. Quisque non arcu diam, ac lacinia felis. Nunc iaculis mollis egestas. Etiam imperdiet dolor consectetur eros feugiat fringilla sed in lacus. Nunc nec tincidunt dolor. Etiam sagittis tortor condimentum nunc fermentum vestibulum. Vivamus lobortis, magna sit amet scelerisque lobortis, sem eros molestie leo, eget aliquet ligula est in lectus. Duis placerat porta pulvinar. Sed sed adipiscing ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nam accumsan iaculis augue, sed varius dui sagittis id. Etiam sit amet eleifend augue. Ut sit amet nibh sit amet justo tempor condimentum. Ut faucibus sagittis volutpat. Duis vestibulum feugiat sollicitudin. Aenean cursus luctus urna at consectetur. Nullam tincidunt, eros a iaculis sodales, tellus est imperdiet arcu, sit amet tincidunt orci felis et tortor. Mauris rutrum venenatis nunc ut rutrum. Phasellus nec erat magna, in tincidunt orci. Sed sit amet suscipit tellus. Mauris ut nisi turpis. Suspendisse augue turpis, condimentum ac bibendum in, vestibulum nec eros. Curabitur dapibus pulvinar vehicula. Fusce consequat, erat in malesuada hendrerit, tellus urna pharetra lacus, sed euismod nisi urna sed nisi. Etiam fermentum accumsan nunc, sed bibendum dui iaculis id. Etiam blandit fermentum ligula nec viverra. Vivamus venenatis arcu in nulla euismod euismod. Donec sit amet augue nec metus varius fringilla. Vivamus pulvinar elit ac mi rhoncus in luctus diam egestas. Curabitur a felis eget arcu pretium tempus eu sed mauris. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris malesuada, nibh ac venenatis hendrerit, ligula dui condimentum tellus, sit amet pretium diam tortor vel risus. Suspendisse suscipit consequat eros id dignissim. Cras interdum lorem ac massa euismod non porta enim pretium. Aliquam ultrices nibh vitae ligula consectetur vel sollicitudin lacus volutpat. Phasellus vulputate iaculis sem nec laoreet. Nam leo sem, tempor eu condimentum id, imperdiet sed dolor. Donec pharetra velit non libero euismod tempor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed fermentum, libero a posuere posuere, enim elit imperdiet enim, a sollicitudin est felis non libero. Sed vel dolor ut arcu dapibus iaculis nec a mauris. Morbi ullamcorper ultrices venenatis. Fusce luctus ante sit amet lacus venenatis ut rutrum elit lobortis. Nulla fermentum tortor ac sapien fringilla quis iaculis quam egestas. Aliquam et tortor est, at elementum mauris. Morbi posuere erat nec leo vulputate in pellentesque tortor condimentum. Vestibulum at orci augue. Aenean pellentesque sapien id felis consequat varius. Suspendisse bibendum enim sit amet mi imperdiet vel suscipit nisi tristique. Curabitur velit massa, consectetur ac mattis vel, accumsan at nunc. Donec porta, nibh nec consequat convallis, urna neque auctor erat, eu convallis lorem leo convallis turpis. Morbi non mauris non metus ornare vulputate. Sed aliquet, dolor ut egestas fermentum, metus purus mollis elit, nec commodo odio quam quis nisl. Aliquam erat volutpat. Suspendisse sed faucibus urna. Integer suscipit rutrum condimentum. Praesent dignissim libero eget metus luctus consectetur. Vestibulum ac erat felis, vitae iaculis erat. Duis interdum lacinia arcu, non lacinia urna luctus in. Curabitur feugiat sapien sapien, in vestibulum diam. Phasellus lobortis massa ut metus pretium dignissim. Fusce quis sem odio. Integer pellentesque sodales augue id tincidunt. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum lorem odio, semper vel scelerisque sit amet, sagittis ac libero. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nam egestas ultricies dui at gravida. Duis tristique, eros id consectetur pellentesque, nulla arcu ultricies tortor, ut pulvinar sapien lacus in elit. Vivamus dolor massa, pulvinar at mollis vitae, euismod ut dolor. Vivamus a magna ante. Vestibulum vitae fringilla leo. Ut gravida magna in quam fringilla ultricies. Mauris rhoncus enim id sem interdum blandit. Pellentesque luctus leo sit amet felis viverra ac accumsan purus mollis. Aenean pretium fringilla quam nec laoreet. Nulla id mauris mauris. Nam varius bibendum tristique. Integer ante felis, volutpat sed dignissim vel, interdum molestie nisi. Etiam mollis accumsan elit, ut gravida eros molestie nec. Nullam quis velit ac purus imperdiet sodales. Donec semper placerat venenatis. Cras dolor risus, sodales sed scelerisque nec, sollicitudin pretium felis. Quisque pretium felis id turpis bibendum pulvinar ornare id nibh. Morbi lobortis leo non mi porttitor vulputate. Vestibulum nec odio tellus, ut blandit ligula. In pellentesque neque sit amet dui pulvinar sed laoreet dui vehicula. In hac habitasse platea dictumst. Etiam feugiat dictum blandit. Praesent lacinia tincidunt elit, quis consectetur tortor molestie commodo. Ut sit amet accumsan lorem. Cras quam nunc, malesuada tempor volutpat vitae, aliquam eu diam. Sed sem nibh, bibendum nec sollicitudin at, interdum et magna. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam vitae sem non elit pharetra vestibulum et condimentum libero. Nam egestas ultricies hendrerit. Nunc nec fringilla nulla. Aliquam risus tellus, hendrerit non dapibus a, tincidunt vel ante. Vivamus mollis, magna et lacinia tincidunt, dui massa porta odio, ac ornare felis massa nec lorem. Mauris sagittis lacus sed metus mollis ac egestas lectus porttitor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer vitae lacinia libero. Phasellus at neque enim, sit amet dictum mi. Ut risus nisi, vestibulum vel congue eget, egestas in ipsum. Duis faucibus tempus sodales. Duis convallis pellentesque arcu rhoncus congue. Nunc ac mauris eu purus vestibulum congue. Praesent convallis semper augue vel volutpat. Integer dictum varius placerat. Vestibulum convallis tortor non mi lacinia ac aliquet dui ultricies. Donec ultrices purus eros. Maecenas venenatis posuere massa, nec consectetur lacus cursus eget. Donec quam lacus, tempus id placerat et, posuere sed libero. Proin auctor diam ut arcu viverra ut imperdiet tellus dapibus. Morbi ac mauris quis tellus porttitor eleifend. Sed et ante magna, ut sodales sapien. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer mattis venenatis mi non ullamcorper. Vestibulum magna enim, aliquam non interdum ut, dignissim vitae ante. Praesent dignissim, est at pretium posuere, nisl ante varius felis, vitae posuere enim nulla et nunc. Morbi sagittis suscipit leo, eu accumsan ligula volutpat non. Donec ut tincidunt magna. Integer ac libero mi. Sed non eros dolor, in tincidunt enim. Curabitur iaculis erat quis felis iaculis ut volutpat augue malesuada. Pellentesque eget arcu ligula, ut volutpat purus. Suspendisse dictum lorem quis sapien lacinia pretium. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin sagittis egestas massa et tempor. Mauris et eros ante, id porta sem. Duis ac eros vitae ipsum ultrices malesuada eget a risus. Morbi imperdiet, est a hendrerit tristique, mi erat molestie lacus, ac tempor risus nulla id erat. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Etiam congue, lacus quis ultricies consequat, diam metus convallis enim, ut volutpat enim urna vitae erat. In quam risus, molestie et dapibus id, elementum sit amet ligula. Nam faucibus lacus id dolor facilisis viverra. Nullam vehicula massa ac arcu consectetur vulputate. Praesent nec augue ac justo dapibus vehicula. Aliquam consectetur hendrerit dolor, et mollis nisl auctor ut. Ut sagittis risus at felis fringilla ultricies. Vestibulum non urna nibh, nec pretium dolor. Nulla imperdiet lobortis eros at pharetra. Vivamus cursus pellentesque ornare. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce arcu quam, pulvinar at rutrum vitae, ornare vitae leo. Maecenas vehicula magna sit amet nulla bibendum condimentum. Curabitur ultrices tempor fringilla. Vivamus pretium suscipit molestie. Donec arcu diam, ultricies ac pellentesque eu, venenatis et sapien. Nam dictum orci augue, vel eleifend leo. Nam at lacus sapien, nec pretium eros. In egestas, enim sed sagittis feugiat, purus odio tristique lectus, vel condimentum leo turpis ac odio. Nam iaculis mi quis odio posuere et venenatis velit ultricies. Nulla facilisi. Proin nec dolor ac quam euismod gravida quis et eros. Nam interdum condimentum mattis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent a nisi eu massa mollis posuere sed a nunc. Aenean tempus enim a justo rhoncus quis ultrices nisl commodo. Aenean imperdiet mauris a ipsum venenatis vel scelerisque lorem rutrum. Donec ut nunc eros, eget accumsan felis. Nullam ullamcorper porta dictum. Donec accumsan cursus vestibulum. Aenean in sapien velit. Vivamus nec massa mi. Fusce felis tortor, bibendum non volutpat a, fringilla quis nisi. Duis varius bibendum erat, quis fermentum sem accumsan eget. Maecenas massa felis, porta sed laoreet eu, luctus eu lectus. Cras id nibh vitae erat fringilla rutrum. Maecenas eget consequat est. Vivamus viverra, felis vel faucibus rhoncus, quam ipsum elementum libero, quis convallis urna purus ut mauris. Nam quis urna vitae enim consequat placerat. Vivamus congue augue sit amet lectus luctus tempor. Cras ut justo convallis est egestas pellentesque ac nec orci. Vivamus rutrum bibendum ante, at cursus erat pulvinar ornare. Proin imperdiet scelerisque ante eu vestibulum. Nullam ullamcorper metus nec purus auctor lobortis. Proin sed lacus et ipsum tempor tempus. Vivamus odio dolor, vulputate vitae semper sit amet, aliquet egestas orci. Nullam non quam eu quam sagittis porta. Nunc in velit id erat commodo viverra. Praesent nec est augue, nec sagittis erat. Cras sed turpis quis enim tempor sagittis. Donec in justo ac nisl porta condimentum id vestibulum nulla. Nam elementum ultricies nunc a bibendum. Aenean tincidunt nisl non augue pellentesque sit amet convallis neque semper. Cras placerat suscipit massa sed volutpat. Integer vulputate imperdiet enim, vitae vulputate sapien mattis feugiat. Vivamus pharetra facilisis mauris a gravida. Nulla non venenatis est. Duis lobortis consectetur sem ac aliquam. In eget sapien odio. Vivamus pulvinar ultricies magna, quis laoreet dui porta et. Integer tempus malesuada velit, et consequat odio ultrices sed. Aliquam malesuada commodo diam vel posuere. Morbi porttitor, elit vitae auctor gravida, lorem massa bibendum arcu, vel placerat nulla justo at augue. Aliquam libero quam, mattis blandit congue sit amet, fermentum ac augue. Aliquam malesuada molestie vulputate. Duis id porta augue. Vestibulum diam dolor, ultrices sit amet porttitor id, convallis id lectus. Etiam ac augue tincidunt nisi tempor molestie euismod id nisl. Nam et tortor ac arcu viverra pulvinar. Fusce pulvinar rhoncus leo, a faucibus enim interdum non. Aliquam vulputate mattis consectetur. Pellentesque sit amet quam sem. Cras eget arcu eu elit volutpat volutpat. Integer sed varius enim. Integer sit amet felis orci, id dignissim sapien. Sed vitae lorem sed libero facilisis fringilla. Pellentesque congue tristique purus, eleifend semper risus suscipit quis. Phasellus rutrum quam vitae arcu vulputate porta. Sed tristique arcu nec mi porttitor lacinia. Donec congue feugiat diam quis pretium. Vivamus at luctus nunc. Integer vulputate laoreet mauris quis auctor. Nunc at ultrices libero. Maecenas porta faucibus purus non vehicula. Sed sit amet metus vitae mi ultrices scelerisque nec quis risus. Phasellus pellentesque tincidunt massa id ultricies. Aliquam dictum arcu ac dolor interdum rutrum. Nulla facilisi. Duis nisi est, tincidunt a sagittis id, sollicitudin at odio. Curabitur sed est eu sapien faucibus dignissim in quis tortor. Nunc ac elit tortor, non lobortis massa. Proin posuere ante ut metus vehicula suscipit. Proin mattis mauris ac lectus consequat rutrum. Nam arcu lectus, commodo non pretium a, pharetra semper dolor. Fusce eleifend hendrerit adipiscing. Nunc et eleifend erat. Suspendisse tempus nisl ut arcu blandit ut adipiscing nisi tristique. Suspendisse molestie facilisis risus sed fermentum. Praesent tempor convallis ultricies. Integer et elit velit, at consectetur risus. Vestibulum mollis adipiscing sodales. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris dictum molestie porta. Nam convallis nisl quis lacus vulputate in convallis risus sagittis. Vivamus accumsan faucibus cursus. Ut ultricies imperdiet ligula scelerisque blandit. In ornare egestas purus, at convallis velit egestas laoreet. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nulla quis imperdiet est. Nunc tempus magna quis lacus feugiat et posuere lacus vehicula. Cras lacinia aliquam est at vehicula. Aenean congue elit in ante dignissim vitae fermentum lectus aliquam. Mauris at odio magna, at interdum dui. Cras fringilla mi velit, nec varius neque. Fusce et volutpat lacus. Suspendisse id turpis et urna varius convallis in eu purus. Nulla facilisi. Etiam mauris nisl, ultrices ac porttitor sit amet, facilisis ut neque. Nullam ut velit quis velit tincidunt rhoncus. Praesent tristique porttitor euismod. Nulla non felis ante, feugiat commodo turpis. In nec venenatis mi. Duis tempus tempor purus, vitae consectetur mi ornare eu. Proin sed consequat erat. Quisque nec sem dui. Nam semper, ligula facilisis pretium interdum, diam lectus sollicitudin lorem, in elementum nisi lorem scelerisque justo. Nullam ac fringilla nunc. Maecenas malesuada ligula in massa sollicitudin sit amet auctor ipsum malesuada. Vestibulum ut augue in magna lobortis varius eget in ipsum. In hac habitasse platea dictumst. Cras vel sagittis mi. Aenean urna sapien, ultrices et tristique et, aliquam vel libero. Nullam in consequat ante. Suspendisse libero augue, pulvinar a dignissim vitae, fringilla malesuada dui. Phasellus augue ante, pulvinar eget tincidunt vel, venenatis sed arcu. Pellentesque ac purus orci, vel molestie turpis. Nulla consectetur sollicitudin dolor, sed ornare arcu accumsan fermentum. Fusce vestibulum nisi at leo interdum eu sollicitudin lacus dictum. Fusce malesuada consequat ipsum ut convallis. Maecenas in eros sit amet elit consectetur fringilla nec a nibh. Ut et velit vel ligula pharetra elementum. Nullam aliquam, tellus vel cursus lacinia, dui libero dictum turpis, nec lacinia dolor nunc vel diam. Pellentesque convallis dui quis lacus ornare at rutrum lorem pellentesque. Suspendisse potenti. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nunc ac nibh sed mauris ornare cursus. Praesent enim mauris, tincidunt vitae convallis ac, ultricies imperdiet sapien. Duis sodales ligula eget lorem suscipit sed consectetur metus pretium. Nam in magna augue, quis volutpat mauris. Quisque pretium lobortis orci quis laoreet. Nam ut nisi diam. Sed ultrices ultrices dapibus. Integer feugiat mauris id orci pulvinar eu tempus nibh viverra. Etiam venenatis bibendum massa a consequat. Fusce interdum velit ac mauris rhoncus non cursus neque consectetur. Vestibulum dictum eros ac metus fringilla venenatis. Phasellus auctor dui non nulla molestie id malesuada mauris euismod. Aenean id tortor ac justo eleifend mollis non vel arcu. Duis ac lorem tortor. Donec volutpat purus sed nunc luctus interdum hendrerit nulla ullamcorper. Sed consectetur interdum aliquet. Proin ullamcorper risus ut ante lacinia sagittis. Nunc varius eleifend purus, ac pellentesque urna viverra id. Praesent euismod, sapien accumsan gravida dictum, massa massa euismod sapien, ut auctor tellus arcu sed diam. Vivamus tincidunt dolor non lorem pellentesque at tempus elit adipiscing. Vestibulum tempor aliquam consectetur. Mauris nec dictum nisl. Donec scelerisque ornare condimentum. Phasellus laoreet justo nec nibh convallis convallis. Duis id orci sapien, eget pulvinar justo. Aenean id arcu felis, eu iaculis nibh. Aenean eleifend pretium rutrum. Aliquam molestie sem quis tellus aliquam eleifend. Mauris et purus orci. Nunc et accumsan tortor. Phasellus semper eleifend nisi, a faucibus risus vehicula id. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas in felis et est lacinia eleifend vel sed ipsum. Aliquam commodo molestie lorem id hendrerit. Nam sed tellus urna, sed dignissim eros. """ A_LONG_STRING = """A long string. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer sit amet mauris mauris, sit amet venenatis nisl. Vivamus a est porta enim sollicitudin mollis. Proin fringilla massa vel ante gravida luctus. Nunc quis nunc id quam hendrerit posuere. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam porttitor interdum sollicitudin. Mauris malesuada tellus tellus. Mauris condimentum nunc et sapien pellentesque gravida. Suspendisse sed ipsum orci. Duis ut lacus dui. Integer ac gravida sem. Vivamus fermentum porttitor velit ac blandit. Maecenas pulvinar ullamcorper enim, vitae aliquet tortor scelerisque et. Vestibulum ante massa, sodales et bibendum dignissim, consectetur vitae metus. Quisque vel dui erat, vel commodo metus. Aliquam arcu dolor, viverra sit amet porttitor a, faucibus eu augue. Sed ornare, enim eget ultricies suscipit, nunc dui lacinia enim, vitae tempus nunc libero vitae ligula. Nam et commodo ligula. Pellentesque tincidunt lorem at elit aliquam at fringilla libero tempor. Donec molestie consectetur nibh, ac varius ante dictum id. Suspendisse lectus nibh, molestie vel dapibus eget, egestas ut eros. Mauris vel mauris turpis, vitae bibendum nunc. Vestibulum nulla enim, vestibulum vitae tincidunt et, gravida eu metus. Nulla sagittis, odio a placerat laoreet, arcu lectus vestibulum nunc, in hendrerit tortor quam sit amet turpis. In et purus vel dui pellentesque tincidunt. Donec dictum nibh sed quam luctus sit amet luctus justo dapibus. Integer nulla elit, lacinia aliquet euismod sed, tempus vitae lectus. Fusce non sapien dolor. Suspendisse ut est ut dui tempor ultricies id ut elit. Aenean adipiscing sollicitudin enim, nec porttitor est porttitor eget. Proin lobortis ante ut diam sodales volutpat. Donec urna diam, porttitor nec laoreet ut, rhoncus non diam. Ut sed mi vitae turpis semper semper. Integer sit amet lorem sapien. Aliquam risus diam, vulputate id sagittis et, molestie ut lectus. Aliquam erat volutpat. Morbi aliquet venenatis metus in posuere. Cras vitae purus nunc, ut vestibulum ipsum. Nullam vehicula dui in urna iaculis lobortis. Ut a est non est tincidunt iaculis. Vivamus rutrum velit non nunc malesuada sed bibendum mi iaculis. Sed id lacus in sem tempor vestibulum. Cras bibendum accumsan suscipit. Phasellus congue nisl consectetur turpis rhoncus aliquet posuere libero fringilla. Sed eros tellus, hendrerit nec imperdiet vitae, blandit ac dolor. Nulla facilisi. Morbi ullamcorper libero odio, at cursus tortor. Cras ultricies tellus eget justo cursus cursus. Donec at mi massa, auctor suscipit sem. Proin dolor purus, semper sed ultrices ut, iaculis at tortor. Donec risus enim, interdum et convallis nec, aliquam eget velit. Curabitur eget lectus dolor. Integer id turpis eu nulla euismod tincidunt. Fusce elit nibh, dapibus sit amet tempus ac, convallis eu libero. Donec dui justo, molestie sed euismod porta, ultricies id orci. Praesent a tellus et risus faucibus porttitor pellentesque in purus. Fusce blandit risus ac tortor viverra vitae molestie odio convallis. Donec rhoncus volutpat mauris, sit amet mattis libero dapibus id. Ut rhoncus venenatis nisi ac dictum. In non nulla eget massa convallis facilisis. Praesent nec odio id odio semper lobortis non eu erat. Proin quis gravida magna. Sed rhoncus lectus auctor arcu posuere a auctor dui pellentesque. Sed enim nulla, luctus quis sagittis sed, vestibulum eget metus. Mauris ornare pretium fringilla. Proin ligula eros, fermentum in placerat sit amet, placerat vel mauris. Nulla magna enim, luctus eget euismod ac, lacinia vel lorem. Duis mi leo, porttitor vitae dictum ac, ultrices iaculis metus. Quisque libero mi, aliquet quis vestibulum eget, porttitor non justo. Praesent ac metus felis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec vel enim sit amet ante imperdiet commodo sed vel nisi. Praesent semper viverra nulla vehicula sollicitudin. Fusce lacinia aliquet ullamcorper. Donec vitae diam est. Integer volutpat hendrerit turpis ut bibendum. Integer et dui augue. Nunc ut nisl in felis feugiat semper nec sit amet purus. Proin convallis ultrices nisl ut vehicula. Pellentesque neque mi, elementum vel placerat nec, laoreet ac nulla. Pellentesque aliquam dui a metus iaculis posuere. Curabitur dapibus faucibus metus. Donec quis diam dui. Proin at mi nec augue cursus pulvinar eu vel metus. Curabitur eget turpis ac risus dignissim luctus sed id ligula. Etiam lectus neque, varius ut euismod nec, euismod quis nulla. Ut feugiat, quam id tempor luctus, metus eros lacinia diam, nec dapibus tellus dui quis diam. Nam interdum, orci id fringilla mattis, ipsum eros pellentesque turpis, hendrerit dignissim justo dui interdum ante. Curabitur aliquam nisi ut dui lacinia tempor. Nulla lobortis tellus non sapien dignissim ut dapibus dui aliquet. Nam scelerisque, urna a aliquam malesuada, mi tortor scelerisque libero, quis pellentesque erat eros ut justo. Phasellus nulla purus, suscipit vel gravida euismod, malesuada et odio. Vestibulum non libero eget lacus venenatis auctor quis a est. Nunc id leo est. Curabitur pulvinar viverra sapien at viverra. Cras pretium justo et lorem lobortis id tempor nisi accumsan. Cras egestas tortor in risus hendrerit eu varius purus suscipit. Nullam mauris eros, mattis at tempor vitae, mollis vitae velit. Etiam at adipiscing lectus. Quisque molestie, metus id posuere pharetra, lorem enim vehicula mauris, ut ultricies purus justo a lacus. Vivamus blandit euismod adipiscing. Nam eu ligula at elit ultricies tempus. Nunc ac sodales neque. Ut dui diam, porttitor a pulvinar vel, sodales sit amet turpis. Donec vitae eros at neque luctus scelerisque. In consequat elementum iaculis. Donec ullamcorper dolor eu quam volutpat rhoncus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras laoreet ante eget dolor sagittis imperdiet. Proin magna urna, porta id blandit nec, commodo eget lorem. Etiam imperdiet, orci sit amet rutrum consectetur, orci augue tempus lacus, id venenatis sapien nisl a est. Sed accumsan massa sed libero consectetur scelerisque. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed nunc risus, lobortis id egestas nec, suscipit id magna. Morbi at iaculis mauris. Proin felis sem, tempus non pellentesque congue, vehicula sit amet eros. Maecenas porttitor erat ac dolor pharetra iaculis. Cras tincidunt, nulla eget malesuada egestas, sem diam consequat quam, sed feugiat nulla orci at mauris. Quisque non arcu diam, ac lacinia felis. Nunc iaculis mollis egestas. Etiam imperdiet dolor consectetur eros feugiat fringilla sed in lacus. Nunc nec tincidunt dolor. Etiam sagittis tortor condimentum nunc fermentum vestibulum. Vivamus lobortis, magna sit amet scelerisque lobortis, sem eros molestie leo, eget aliquet ligula est in lectus. Duis placerat porta pulvinar. Sed sed adipiscing ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nam accumsan iaculis augue, sed varius dui sagittis id. Etiam sit amet eleifend augue. Ut sit amet nibh sit amet justo tempor condimentum. Ut faucibus sagittis volutpat. Duis vestibulum feugiat sollicitudin. Aenean cursus luctus urna at consectetur. Nullam tincidunt, eros a iaculis sodales, tellus est imperdiet arcu, sit amet tincidunt orci felis et tortor. Mauris rutrum venenatis nunc ut rutrum. Phasellus nec erat magna, in tincidunt orci. Sed sit amet suscipit tellus. Mauris ut nisi turpis. Suspendisse augue turpis, condimentum ac bibendum in, vestibulum nec eros. Curabitur dapibus pulvinar vehicula. Fusce consequat, erat in malesuada hendrerit, tellus urna pharetra lacus, sed euismod nisi urna sed nisi. Etiam fermentum accumsan nunc, sed bibendum dui iaculis id. Etiam blandit fermentum ligula nec viverra. Vivamus venenatis arcu in nulla euismod euismod. Donec sit amet augue nec metus varius fringilla. Vivamus pulvinar elit ac mi rhoncus in luctus diam egestas. Curabitur a felis eget arcu pretium tempus eu sed mauris. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris malesuada, nibh ac venenatis hendrerit, ligula dui condimentum tellus, sit amet pretium diam tortor vel risus. Suspendisse suscipit consequat eros id dignissim. Cras interdum lorem ac massa euismod non porta enim pretium. Aliquam ultrices nibh vitae ligula consectetur vel sollicitudin lacus volutpat. Phasellus vulputate iaculis sem nec laoreet. Nam leo sem, tempor eu condimentum id, imperdiet sed dolor. Donec pharetra velit non libero euismod tempor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed fermentum, libero a posuere posuere, enim elit imperdiet enim, a sollicitudin est felis non libero. Sed vel dolor ut arcu dapibus iaculis nec a mauris. Morbi ullamcorper ultrices venenatis. Fusce luctus ante sit amet lacus venenatis ut rutrum elit lobortis. Nulla fermentum tortor ac sapien fringilla quis iaculis quam egestas. Aliquam et tortor est, at elementum mauris. Morbi posuere erat nec leo vulputate in pellentesque tortor condimentum. Vestibulum at orci augue. Aenean pellentesque sapien id felis consequat varius. Suspendisse bibendum enim sit amet mi imperdiet vel suscipit nisi tristique. Curabitur velit massa, consectetur ac mattis vel, accumsan at nunc. Donec porta, nibh nec consequat convallis, urna neque auctor erat, eu convallis lorem leo convallis turpis. Morbi non mauris non metus ornare vulputate. Sed aliquet, dolor ut egestas fermentum, metus purus mollis elit, nec commodo odio quam quis nisl. Aliquam erat volutpat. Suspendisse sed faucibus urna. Integer suscipit rutrum condimentum. Praesent dignissim libero eget metus luctus consectetur. Vestibulum ac erat felis, vitae iaculis erat. Duis interdum lacinia arcu, non lacinia urna luctus in. Curabitur feugiat sapien sapien, in vestibulum diam. Phasellus lobortis massa ut metus pretium dignissim. Fusce quis sem odio. Integer pellentesque sodales augue id tincidunt. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum lorem odio, semper vel scelerisque sit amet, sagittis ac libero. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nam egestas ultricies dui at gravida. Duis tristique, eros id consectetur pellentesque, nulla arcu ultricies tortor, ut pulvinar sapien lacus in elit. Vivamus dolor massa, pulvinar at mollis vitae, euismod ut dolor. Vivamus a magna ante. Vestibulum vitae fringilla leo. Ut gravida magna in quam fringilla ultricies. Mauris rhoncus enim id sem interdum blandit. Pellentesque luctus leo sit amet felis viverra ac accumsan purus mollis. Aenean pretium fringilla quam nec laoreet. Nulla id mauris mauris. Nam varius bibendum tristique. Integer ante felis, volutpat sed dignissim vel, interdum molestie nisi. Etiam mollis accumsan elit, ut gravida eros molestie nec. Nullam quis velit ac purus imperdiet sodales. Donec semper placerat venenatis. Cras dolor risus, sodales sed scelerisque nec, sollicitudin pretium felis. Quisque pretium felis id turpis bibendum pulvinar ornare id nibh. Morbi lobortis leo non mi porttitor vulputate. Vestibulum nec odio tellus, ut blandit ligula. In pellentesque neque sit amet dui pulvinar sed laoreet dui vehicula. In hac habitasse platea dictumst. Etiam feugiat dictum blandit. Praesent lacinia tincidunt elit, quis consectetur tortor molestie commodo. Ut sit amet accumsan lorem. Cras quam nunc, malesuada tempor volutpat vitae, aliquam eu diam. Sed sem nibh, bibendum nec sollicitudin at, interdum et magna. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam vitae sem non elit pharetra vestibulum et condimentum libero. Nam egestas ultricies hendrerit. Nunc nec fringilla nulla. Aliquam risus tellus, hendrerit non dapibus a, tincidunt vel ante. Vivamus mollis, magna et lacinia tincidunt, dui massa porta odio, ac ornare felis massa nec lorem. Mauris sagittis lacus sed metus mollis ac egestas lectus porttitor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer vitae lacinia libero. Phasellus at neque enim, sit amet dictum mi. Ut risus nisi, vestibulum vel congue eget, egestas in ipsum. Duis faucibus tempus sodales. Duis convallis pellentesque arcu rhoncus congue. Nunc ac mauris eu purus vestibulum congue. Praesent convallis semper augue vel volutpat. Integer dictum varius placerat. Vestibulum convallis tortor non mi lacinia ac aliquet dui ultricies. Donec ultrices purus eros. Maecenas venenatis posuere massa, nec consectetur lacus cursus eget. Donec quam lacus, tempus id placerat et, posuere sed libero. Proin auctor diam ut arcu viverra ut imperdiet tellus dapibus. Morbi ac mauris quis tellus porttitor eleifend. Sed et ante magna, ut sodales sapien. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer mattis venenatis mi non ullamcorper. Vestibulum magna enim, aliquam non interdum ut, dignissim vitae ante. Praesent dignissim, est at pretium posuere, nisl ante varius felis, vitae posuere enim nulla et nunc. Morbi sagittis suscipit leo, eu accumsan ligula volutpat non. Donec ut tincidunt magna. Integer ac libero mi. Sed non eros dolor, in tincidunt enim. Curabitur iaculis erat quis felis iaculis ut volutpat augue malesuada. Pellentesque eget arcu ligula, ut volutpat purus. Suspendisse dictum lorem quis sapien lacinia pretium. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin sagittis egestas massa et tempor. Mauris et eros ante, id porta sem. Duis ac eros vitae ipsum ultrices malesuada eget a risus. Morbi imperdiet, est a hendrerit tristique, mi erat molestie lacus, ac tempor risus nulla id erat. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Etiam congue, lacus quis ultricies consequat, diam metus convallis enim, ut volutpat enim urna vitae erat. In quam risus, molestie et dapibus id, elementum sit amet ligula. Nam faucibus lacus id dolor facilisis viverra. Nullam vehicula massa ac arcu consectetur vulputate. Praesent nec augue ac justo dapibus vehicula. Aliquam consectetur hendrerit dolor, et mollis nisl auctor ut. Ut sagittis risus at felis fringilla ultricies. Vestibulum non urna nibh, nec pretium dolor. Nulla imperdiet lobortis eros at pharetra. Vivamus cursus pellentesque ornare. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce arcu quam, pulvinar at rutrum vitae, ornare vitae leo. Maecenas vehicula magna sit amet nulla bibendum condimentum. Curabitur ultrices tempor fringilla. Vivamus pretium suscipit molestie. Donec arcu diam, ultricies ac pellentesque eu, venenatis et sapien. Nam dictum orci augue, vel eleifend leo. Nam at lacus sapien, nec pretium eros. In egestas, enim sed sagittis feugiat, purus odio tristique lectus, vel condimentum leo turpis ac odio. Nam iaculis mi quis odio posuere et venenatis velit ultricies. Nulla facilisi. Proin nec dolor ac quam euismod gravida quis et eros. Nam interdum condimentum mattis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent a nisi eu massa mollis posuere sed a nunc. Aenean tempus enim a justo rhoncus quis ultrices nisl commodo. Aenean imperdiet mauris a ipsum venenatis vel scelerisque lorem rutrum. Donec ut nunc eros, eget accumsan felis. Nullam ullamcorper porta dictum. Donec accumsan cursus vestibulum. Aenean in sapien velit. Vivamus nec massa mi. Fusce felis tortor, bibendum non volutpat a, fringilla quis nisi. Duis varius bibendum erat, quis fermentum sem accumsan eget. Maecenas massa felis, porta sed laoreet eu, luctus eu lectus. Cras id nibh vitae erat fringilla rutrum. Maecenas eget consequat est. Vivamus viverra, felis vel faucibus rhoncus, quam ipsum elementum libero, quis convallis urna purus ut mauris. Nam quis urna vitae enim consequat placerat. Vivamus congue augue sit amet lectus luctus tempor. Cras ut justo convallis est egestas pellentesque ac nec orci. Vivamus rutrum bibendum ante, at cursus erat pulvinar ornare. Proin imperdiet scelerisque ante eu vestibulum. Nullam ullamcorper metus nec purus auctor lobortis. Proin sed lacus et ipsum tempor tempus. Vivamus odio dolor, vulputate vitae semper sit amet, aliquet egestas orci. Nullam non quam eu quam sagittis porta. Nunc in velit id erat commodo viverra. Praesent nec est augue, nec sagittis erat. Cras sed turpis quis enim tempor sagittis. Donec in justo ac nisl porta condimentum id vestibulum nulla. Nam elementum ultricies nunc a bibendum. Aenean tincidunt nisl non augue pellentesque sit amet convallis neque semper. Cras placerat suscipit massa sed volutpat. Integer vulputate imperdiet enim, vitae vulputate sapien mattis feugiat. Vivamus pharetra facilisis mauris a gravida. Nulla non venenatis est. Duis lobortis consectetur sem ac aliquam. In eget sapien odio. Vivamus pulvinar ultricies magna, quis laoreet dui porta et. Integer tempus malesuada velit, et consequat odio ultrices sed. Aliquam malesuada commodo diam vel posuere. Morbi porttitor, elit vitae auctor gravida, lorem massa bibendum arcu, vel placerat nulla justo at augue. Aliquam libero quam, mattis blandit congue sit amet, fermentum ac augue. Aliquam malesuada molestie vulputate. Duis id porta augue. Vestibulum diam dolor, ultrices sit amet porttitor id, convallis id lectus. Etiam ac augue tincidunt nisi tempor molestie euismod id nisl. Nam et tortor ac arcu viverra pulvinar. Fusce pulvinar rhoncus leo, a faucibus enim interdum non. Aliquam vulputate mattis consectetur. Pellentesque sit amet quam sem. Cras eget arcu eu elit volutpat volutpat. Integer sed varius enim. Integer sit amet felis orci, id dignissim sapien. Sed vitae lorem sed libero facilisis fringilla. Pellentesque congue tristique purus, eleifend semper risus suscipit quis. Phasellus rutrum quam vitae arcu vulputate porta. Sed tristique arcu nec mi porttitor lacinia. Donec congue feugiat diam quis pretium. Vivamus at luctus nunc. Integer vulputate laoreet mauris quis auctor. Nunc at ultrices libero. Maecenas porta faucibus purus non vehicula. Sed sit amet metus vitae mi ultrices scelerisque nec quis risus. Phasellus pellentesque tincidunt massa id ultricies. Aliquam dictum arcu ac dolor interdum rutrum. Nulla facilisi. Duis nisi est, tincidunt a sagittis id, sollicitudin at odio. Curabitur sed est eu sapien faucibus dignissim in quis tortor. Nunc ac elit tortor, non lobortis massa. Proin posuere ante ut metus vehicula suscipit. Proin mattis mauris ac lectus consequat rutrum. Nam arcu lectus, commodo non pretium a, pharetra semper dolor. Fusce eleifend hendrerit adipiscing. Nunc et eleifend erat. Suspendisse tempus nisl ut arcu blandit ut adipiscing nisi tristique. Suspendisse molestie facilisis risus sed fermentum. Praesent tempor convallis ultricies. Integer et elit velit, at consectetur risus. Vestibulum mollis adipiscing sodales. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris dictum molestie porta. Nam convallis nisl quis lacus vulputate in convallis risus sagittis. Vivamus accumsan faucibus cursus. Ut ultricies imperdiet ligula scelerisque blandit. In ornare egestas purus, at convallis velit egestas laoreet. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nulla quis imperdiet est. Nunc tempus magna quis lacus feugiat et posuere lacus vehicula. Cras lacinia aliquam est at vehicula. Aenean congue elit in ante dignissim vitae fermentum lectus aliquam. Mauris at odio magna, at interdum dui. Cras fringilla mi velit, nec varius neque. Fusce et volutpat lacus. Suspendisse id turpis et urna varius convallis in eu purus. Nulla facilisi. Etiam mauris nisl, ultrices ac porttitor sit amet, facilisis ut neque. Nullam ut velit quis velit tincidunt rhoncus. Praesent tristique porttitor euismod. Nulla non felis ante, feugiat commodo turpis. In nec venenatis mi. Duis tempus tempor purus, vitae consectetur mi ornare eu. Proin sed consequat erat. Quisque nec sem dui. Nam semper, ligula facilisis pretium interdum, diam lectus sollicitudin lorem, in elementum nisi lorem scelerisque justo. Nullam ac fringilla nunc. Maecenas malesuada ligula in massa sollicitudin sit amet auctor ipsum malesuada. Vestibulum ut augue in magna lobortis varius eget in ipsum. In hac habitasse platea dictumst. Cras vel sagittis mi. Aenean urna sapien, ultrices et tristique et, aliquam vel libero. Nullam in consequat ante. Suspendisse libero augue, pulvinar a dignissim vitae, fringilla malesuada dui. Phasellus augue ante, pulvinar eget tincidunt vel, venenatis sed arcu. Pellentesque ac purus orci, vel molestie turpis. Nulla consectetur sollicitudin dolor, sed ornare arcu accumsan fermentum. Fusce vestibulum nisi at leo interdum eu sollicitudin lacus dictum. Fusce malesuada consequat ipsum ut convallis. Maecenas in eros sit amet elit consectetur fringilla nec a nibh. Ut et velit vel ligula pharetra elementum. Nullam aliquam, tellus vel cursus lacinia, dui libero dictum turpis, nec lacinia dolor nunc vel diam. Pellentesque convallis dui quis lacus ornare at rutrum lorem pellentesque. Suspendisse potenti. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nunc ac nibh sed mauris ornare cursus. Praesent enim mauris, tincidunt vitae convallis ac, ultricies imperdiet sapien. Duis sodales ligula eget lorem suscipit sed consectetur metus pretium. Nam in magna augue, quis volutpat mauris. Quisque pretium lobortis orci quis laoreet. Nam ut nisi diam. Sed ultrices ultrices dapibus. Integer feugiat mauris id orci pulvinar eu tempus nibh viverra. Etiam venenatis bibendum massa a consequat. Fusce interdum velit ac mauris rhoncus non cursus neque consectetur. Vestibulum dictum eros ac metus fringilla venenatis. Phasellus auctor dui non nulla molestie id malesuada mauris euismod. Aenean id tortor ac justo eleifend mollis non vel arcu. Duis ac lorem tortor. Donec volutpat purus sed nunc luctus interdum hendrerit nulla ullamcorper. Sed consectetur interdum aliquet. Proin ullamcorper risus ut ante lacinia sagittis. Nunc varius eleifend purus, ac pellentesque urna viverra id. Praesent euismod, sapien accumsan gravida dictum, massa massa euismod sapien, ut auctor tellus arcu sed diam. Vivamus tincidunt dolor non lorem pellentesque at tempus elit adipiscing. Vestibulum tempor aliquam consectetur. Mauris nec dictum nisl. Donec scelerisque ornare condimentum. Phasellus laoreet justo nec nibh convallis convallis. Duis id orci sapien, eget pulvinar justo. Aenean id arcu felis, eu iaculis nibh. Aenean eleifend pretium rutrum. Aliquam molestie sem quis tellus aliquam eleifend. Mauris et purus orci. Nunc et accumsan tortor. Phasellus semper eleifend nisi, a faucibus risus vehicula id. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas in felis et est lacinia eleifend vel sed ipsum. Aliquam commodo molestie lorem id hendrerit. Nam sed tellus urna, sed dignissim eros. """ def a_function(): """A long function docstring. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer sit amet mauris mauris, sit amet venenatis nisl. Vivamus a est porta enim sollicitudin mollis. Proin fringilla massa vel ante gravida luctus. Nunc quis nunc id quam hendrerit posuere. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam porttitor interdum sollicitudin. Mauris malesuada tellus tellus. Mauris condimentum nunc et sapien pellentesque gravida. Suspendisse sed ipsum orci. Duis ut lacus dui. Integer ac gravida sem. Vivamus fermentum porttitor velit ac blandit. Maecenas pulvinar ullamcorper enim, vitae aliquet tortor scelerisque et. Vestibulum ante massa, sodales et bibendum dignissim, consectetur vitae metus. Quisque vel dui erat, vel commodo metus. Aliquam arcu dolor, viverra sit amet porttitor a, faucibus eu augue. Sed ornare, enim eget ultricies suscipit, nunc dui lacinia enim, vitae tempus nunc libero vitae ligula. Nam et commodo ligula. Pellentesque tincidunt lorem at elit aliquam at fringilla libero tempor. Donec molestie consectetur nibh, ac varius ante dictum id. Suspendisse lectus nibh, molestie vel dapibus eget, egestas ut eros. Mauris vel mauris turpis, vitae bibendum nunc. Vestibulum nulla enim, vestibulum vitae tincidunt et, gravida eu metus. Nulla sagittis, odio a placerat laoreet, arcu lectus vestibulum nunc, in hendrerit tortor quam sit amet turpis. In et purus vel dui pellentesque tincidunt. Donec dictum nibh sed quam luctus sit amet luctus justo dapibus. Integer nulla elit, lacinia aliquet euismod sed, tempus vitae lectus. Fusce non sapien dolor. Suspendisse ut est ut dui tempor ultricies id ut elit. Aenean adipiscing sollicitudin enim, nec porttitor est porttitor eget. Proin lobortis ante ut diam sodales volutpat. Donec urna diam, porttitor nec laoreet ut, rhoncus non diam. Ut sed mi vitae turpis semper semper. Integer sit amet lorem sapien. Aliquam risus diam, vulputate id sagittis et, molestie ut lectus. Aliquam erat volutpat. Morbi aliquet venenatis metus in posuere. Cras vitae purus nunc, ut vestibulum ipsum. Nullam vehicula dui in urna iaculis lobortis. Ut a est non est tincidunt iaculis. Vivamus rutrum velit non nunc malesuada sed bibendum mi iaculis. Sed id lacus in sem tempor vestibulum. Cras bibendum accumsan suscipit. Phasellus congue nisl consectetur turpis rhoncus aliquet posuere libero fringilla. Sed eros tellus, hendrerit nec imperdiet vitae, blandit ac dolor. Nulla facilisi. Morbi ullamcorper libero odio, at cursus tortor. Cras ultricies tellus eget justo cursus cursus. Donec at mi massa, auctor suscipit sem. Proin dolor purus, semper sed ultrices ut, iaculis at tortor. Donec risus enim, interdum et convallis nec, aliquam eget velit. Curabitur eget lectus dolor. Integer id turpis eu nulla euismod tincidunt. Fusce elit nibh, dapibus sit amet tempus ac, convallis eu libero. Donec dui justo, molestie sed euismod porta, ultricies id orci. Praesent a tellus et risus faucibus porttitor pellentesque in purus. Fusce blandit risus ac tortor viverra vitae molestie odio convallis. Donec rhoncus volutpat mauris, sit amet mattis libero dapibus id. Ut rhoncus venenatis nisi ac dictum. In non nulla eget massa convallis facilisis. Praesent nec odio id odio semper lobortis non eu erat. Proin quis gravida magna. Sed rhoncus lectus auctor arcu posuere a auctor dui pellentesque. Sed enim nulla, luctus quis sagittis sed, vestibulum eget metus. Mauris ornare pretium fringilla. Proin ligula eros, fermentum in placerat sit amet, placerat vel mauris. Nulla magna enim, luctus eget euismod ac, lacinia vel lorem. Duis mi leo, porttitor vitae dictum ac, ultrices iaculis metus. Quisque libero mi, aliquet quis vestibulum eget, porttitor non justo. Praesent ac metus felis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec vel enim sit amet ante imperdiet commodo sed vel nisi. Praesent semper viverra nulla vehicula sollicitudin. Fusce lacinia aliquet ullamcorper. Donec vitae diam est. Integer volutpat hendrerit turpis ut bibendum. Integer et dui augue. Nunc ut nisl in felis feugiat semper nec sit amet purus. Proin convallis ultrices nisl ut vehicula. Pellentesque neque mi, elementum vel placerat nec, laoreet ac nulla. Pellentesque aliquam dui a metus iaculis posuere. Curabitur dapibus faucibus metus. Donec quis diam dui. Proin at mi nec augue cursus pulvinar eu vel metus. Curabitur eget turpis ac risus dignissim luctus sed id ligula. Etiam lectus neque, varius ut euismod nec, euismod quis nulla. Ut feugiat, quam id tempor luctus, metus eros lacinia diam, nec dapibus tellus dui quis diam. Nam interdum, orci id fringilla mattis, ipsum eros pellentesque turpis, hendrerit dignissim justo dui interdum ante. Curabitur aliquam nisi ut dui lacinia tempor. Nulla lobortis tellus non sapien dignissim ut dapibus dui aliquet. Nam scelerisque, urna a aliquam malesuada, mi tortor scelerisque libero, quis pellentesque erat eros ut justo. Phasellus nulla purus, suscipit vel gravida euismod, malesuada et odio. Vestibulum non libero eget lacus venenatis auctor quis a est. Nunc id leo est. Curabitur pulvinar viverra sapien at viverra. Cras pretium justo et lorem lobortis id tempor nisi accumsan. Cras egestas tortor in risus hendrerit eu varius purus suscipit. Nullam mauris eros, mattis at tempor vitae, mollis vitae velit. Etiam at adipiscing lectus. Quisque molestie, metus id posuere pharetra, lorem enim vehicula mauris, ut ultricies purus justo a lacus. Vivamus blandit euismod adipiscing. Nam eu ligula at elit ultricies tempus. Nunc ac sodales neque. Ut dui diam, porttitor a pulvinar vel, sodales sit amet turpis. Donec vitae eros at neque luctus scelerisque. In consequat elementum iaculis. Donec ullamcorper dolor eu quam volutpat rhoncus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras laoreet ante eget dolor sagittis imperdiet. Proin magna urna, porta id blandit nec, commodo eget lorem. Etiam imperdiet, orci sit amet rutrum consectetur, orci augue tempus lacus, id venenatis sapien nisl a est. Sed accumsan massa sed libero consectetur scelerisque. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed nunc risus, lobortis id egestas nec, suscipit id magna. Morbi at iaculis mauris. Proin felis sem, tempus non pellentesque congue, vehicula sit amet eros. Maecenas porttitor erat ac dolor pharetra iaculis. Cras tincidunt, nulla eget malesuada egestas, sem diam consequat quam, sed feugiat nulla orci at mauris. Quisque non arcu diam, ac lacinia felis. Nunc iaculis mollis egestas. Etiam imperdiet dolor consectetur eros feugiat fringilla sed in lacus. Nunc nec tincidunt dolor. Etiam sagittis tortor condimentum nunc fermentum vestibulum. Vivamus lobortis, magna sit amet scelerisque lobortis, sem eros molestie leo, eget aliquet ligula est in lectus. Duis placerat porta pulvinar. Sed sed adipiscing ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nam accumsan iaculis augue, sed varius dui sagittis id. Etiam sit amet eleifend augue. Ut sit amet nibh sit amet justo tempor condimentum. Ut faucibus sagittis volutpat. Duis vestibulum feugiat sollicitudin. Aenean cursus luctus urna at consectetur. Nullam tincidunt, eros a iaculis sodales, tellus est imperdiet arcu, sit amet tincidunt orci felis et tortor. Mauris rutrum venenatis nunc ut rutrum. Phasellus nec erat magna, in tincidunt orci. Sed sit amet suscipit tellus. Mauris ut nisi turpis. Suspendisse augue turpis, condimentum ac bibendum in, vestibulum nec eros. Curabitur dapibus pulvinar vehicula. Fusce consequat, erat in malesuada hendrerit, tellus urna pharetra lacus, sed euismod nisi urna sed nisi. Etiam fermentum accumsan nunc, sed bibendum dui iaculis id. Etiam blandit fermentum ligula nec viverra. Vivamus venenatis arcu in nulla euismod euismod. Donec sit amet augue nec metus varius fringilla. Vivamus pulvinar elit ac mi rhoncus in luctus diam egestas. Curabitur a felis eget arcu pretium tempus eu sed mauris. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris malesuada, nibh ac venenatis hendrerit, ligula dui condimentum tellus, sit amet pretium diam tortor vel risus. Suspendisse suscipit consequat eros id dignissim. Cras interdum lorem ac massa euismod non porta enim pretium. Aliquam ultrices nibh vitae ligula consectetur vel sollicitudin lacus volutpat. Phasellus vulputate iaculis sem nec laoreet. Nam leo sem, tempor eu condimentum id, imperdiet sed dolor. Donec pharetra velit non libero euismod tempor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed fermentum, libero a posuere posuere, enim elit imperdiet enim, a sollicitudin est felis non libero. Sed vel dolor ut arcu dapibus iaculis nec a mauris. Morbi ullamcorper ultrices venenatis. Fusce luctus ante sit amet lacus venenatis ut rutrum elit lobortis. Nulla fermentum tortor ac sapien fringilla quis iaculis quam egestas. Aliquam et tortor est, at elementum mauris. Morbi posuere erat nec leo vulputate in pellentesque tortor condimentum. Vestibulum at orci augue. Aenean pellentesque sapien id felis consequat varius. Suspendisse bibendum enim sit amet mi imperdiet vel suscipit nisi tristique. Curabitur velit massa, consectetur ac mattis vel, accumsan at nunc. Donec porta, nibh nec consequat convallis, urna neque auctor erat, eu convallis lorem leo convallis turpis. Morbi non mauris non metus ornare vulputate. Sed aliquet, dolor ut egestas fermentum, metus purus mollis elit, nec commodo odio quam quis nisl. Aliquam erat volutpat. Suspendisse sed faucibus urna. Integer suscipit rutrum condimentum. Praesent dignissim libero eget metus luctus consectetur. Vestibulum ac erat felis, vitae iaculis erat. Duis interdum lacinia arcu, non lacinia urna luctus in. Curabitur feugiat sapien sapien, in vestibulum diam. Phasellus lobortis massa ut metus pretium dignissim. Fusce quis sem odio. Integer pellentesque sodales augue id tincidunt. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum lorem odio, semper vel scelerisque sit amet, sagittis ac libero. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nam egestas ultricies dui at gravida. Duis tristique, eros id consectetur pellentesque, nulla arcu ultricies tortor, ut pulvinar sapien lacus in elit. Vivamus dolor massa, pulvinar at mollis vitae, euismod ut dolor. Vivamus a magna ante. Vestibulum vitae fringilla leo. Ut gravida magna in quam fringilla ultricies. Mauris rhoncus enim id sem interdum blandit. Pellentesque luctus leo sit amet felis viverra ac accumsan purus mollis. Aenean pretium fringilla quam nec laoreet. Nulla id mauris mauris. Nam varius bibendum tristique. Integer ante felis, volutpat sed dignissim vel, interdum molestie nisi. Etiam mollis accumsan elit, ut gravida eros molestie nec. Nullam quis velit ac purus imperdiet sodales. Donec semper placerat venenatis. Cras dolor risus, sodales sed scelerisque nec, sollicitudin pretium felis. Quisque pretium felis id turpis bibendum pulvinar ornare id nibh. Morbi lobortis leo non mi porttitor vulputate. Vestibulum nec odio tellus, ut blandit ligula. In pellentesque neque sit amet dui pulvinar sed laoreet dui vehicula. In hac habitasse platea dictumst. Etiam feugiat dictum blandit. Praesent lacinia tincidunt elit, quis consectetur tortor molestie commodo. Ut sit amet accumsan lorem. Cras quam nunc, malesuada tempor volutpat vitae, aliquam eu diam. Sed sem nibh, bibendum nec sollicitudin at, interdum et magna. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam vitae sem non elit pharetra vestibulum et condimentum libero. Nam egestas ultricies hendrerit. Nunc nec fringilla nulla. Aliquam risus tellus, hendrerit non dapibus a, tincidunt vel ante. Vivamus mollis, magna et lacinia tincidunt, dui massa porta odio, ac ornare felis massa nec lorem. Mauris sagittis lacus sed metus mollis ac egestas lectus porttitor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer vitae lacinia libero. Phasellus at neque enim, sit amet dictum mi. Ut risus nisi, vestibulum vel congue eget, egestas in ipsum. Duis faucibus tempus sodales. Duis convallis pellentesque arcu rhoncus congue. Nunc ac mauris eu purus vestibulum congue. Praesent convallis semper augue vel volutpat. Integer dictum varius placerat. Vestibulum convallis tortor non mi lacinia ac aliquet dui ultricies. Donec ultrices purus eros. Maecenas venenatis posuere massa, nec consectetur lacus cursus eget. Donec quam lacus, tempus id placerat et, posuere sed libero. Proin auctor diam ut arcu viverra ut imperdiet tellus dapibus. Morbi ac mauris quis tellus porttitor eleifend. Sed et ante magna, ut sodales sapien. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer mattis venenatis mi non ullamcorper. Vestibulum magna enim, aliquam non interdum ut, dignissim vitae ante. Praesent dignissim, est at pretium posuere, nisl ante varius felis, vitae posuere enim nulla et nunc. Morbi sagittis suscipit leo, eu accumsan ligula volutpat non. Donec ut tincidunt magna. Integer ac libero mi. Sed non eros dolor, in tincidunt enim. Curabitur iaculis erat quis felis iaculis ut volutpat augue malesuada. Pellentesque eget arcu ligula, ut volutpat purus. Suspendisse dictum lorem quis sapien lacinia pretium. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin sagittis egestas massa et tempor. Mauris et eros ante, id porta sem. Duis ac eros vitae ipsum ultrices malesuada eget a risus. Morbi imperdiet, est a hendrerit tristique, mi erat molestie lacus, ac tempor risus nulla id erat. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Etiam congue, lacus quis ultricies consequat, diam metus convallis enim, ut volutpat enim urna vitae erat. In quam risus, molestie et dapibus id, elementum sit amet ligula. Nam faucibus lacus id dolor facilisis viverra. Nullam vehicula massa ac arcu consectetur vulputate. Praesent nec augue ac justo dapibus vehicula. Aliquam consectetur hendrerit dolor, et mollis nisl auctor ut. Ut sagittis risus at felis fringilla ultricies. Vestibulum non urna nibh, nec pretium dolor. Nulla imperdiet lobortis eros at pharetra. Vivamus cursus pellentesque ornare. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce arcu quam, pulvinar at rutrum vitae, ornare vitae leo. Maecenas vehicula magna sit amet nulla bibendum condimentum. Curabitur ultrices tempor fringilla. Vivamus pretium suscipit molestie. Donec arcu diam, ultricies ac pellentesque eu, venenatis et sapien. Nam dictum orci augue, vel eleifend leo. Nam at lacus sapien, nec pretium eros. In egestas, enim sed sagittis feugiat, purus odio tristique lectus, vel condimentum leo turpis ac odio. Nam iaculis mi quis odio posuere et venenatis velit ultricies. Nulla facilisi. Proin nec dolor ac quam euismod gravida quis et eros. Nam interdum condimentum mattis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent a nisi eu massa mollis posuere sed a nunc. Aenean tempus enim a justo rhoncus quis ultrices nisl commodo. Aenean imperdiet mauris a ipsum venenatis vel scelerisque lorem rutrum. Donec ut nunc eros, eget accumsan felis. Nullam ullamcorper porta dictum. Donec accumsan cursus vestibulum. Aenean in sapien velit. Vivamus nec massa mi. Fusce felis tortor, bibendum non volutpat a, fringilla quis nisi. Duis varius bibendum erat, quis fermentum sem accumsan eget. Maecenas massa felis, porta sed laoreet eu, luctus eu lectus. Cras id nibh vitae erat fringilla rutrum. Maecenas eget consequat est. Vivamus viverra, felis vel faucibus rhoncus, quam ipsum elementum libero, quis convallis urna purus ut mauris. Nam quis urna vitae enim consequat placerat. Vivamus congue augue sit amet lectus luctus tempor. Cras ut justo convallis est egestas pellentesque ac nec orci. Vivamus rutrum bibendum ante, at cursus erat pulvinar ornare. Proin imperdiet scelerisque ante eu vestibulum. Nullam ullamcorper metus nec purus auctor lobortis. Proin sed lacus et ipsum tempor tempus. Vivamus odio dolor, vulputate vitae semper sit amet, aliquet egestas orci. Nullam non quam eu quam sagittis porta. Nunc in velit id erat commodo viverra. Praesent nec est augue, nec sagittis erat. Cras sed turpis quis enim tempor sagittis. Donec in justo ac nisl porta condimentum id vestibulum nulla. Nam elementum ultricies nunc a bibendum. Aenean tincidunt nisl non augue pellentesque sit amet convallis neque semper. Cras placerat suscipit massa sed volutpat. Integer vulputate imperdiet enim, vitae vulputate sapien mattis feugiat. Vivamus pharetra facilisis mauris a gravida. Nulla non venenatis est. Duis lobortis consectetur sem ac aliquam. In eget sapien odio. Vivamus pulvinar ultricies magna, quis laoreet dui porta et. Integer tempus malesuada velit, et consequat odio ultrices sed. Aliquam malesuada commodo diam vel posuere. Morbi porttitor, elit vitae auctor gravida, lorem massa bibendum arcu, vel placerat nulla justo at augue. Aliquam libero quam, mattis blandit congue sit amet, fermentum ac augue. Aliquam malesuada molestie vulputate. Duis id porta augue. Vestibulum diam dolor, ultrices sit amet porttitor id, convallis id lectus. Etiam ac augue tincidunt nisi tempor molestie euismod id nisl. Nam et tortor ac arcu viverra pulvinar. Fusce pulvinar rhoncus leo, a faucibus enim interdum non. Aliquam vulputate mattis consectetur. Pellentesque sit amet quam sem. Cras eget arcu eu elit volutpat volutpat. Integer sed varius enim. Integer sit amet felis orci, id dignissim sapien. Sed vitae lorem sed libero facilisis fringilla. Pellentesque congue tristique purus, eleifend semper risus suscipit quis. Phasellus rutrum quam vitae arcu vulputate porta. Sed tristique arcu nec mi porttitor lacinia. Donec congue feugiat diam quis pretium. Vivamus at luctus nunc. Integer vulputate laoreet mauris quis auctor. Nunc at ultrices libero. Maecenas porta faucibus purus non vehicula. Sed sit amet metus vitae mi ultrices scelerisque nec quis risus. Phasellus pellentesque tincidunt massa id ultricies. Aliquam dictum arcu ac dolor interdum rutrum. Nulla facilisi. Duis nisi est, tincidunt a sagittis id, sollicitudin at odio. Curabitur sed est eu sapien faucibus dignissim in quis tortor. Nunc ac elit tortor, non lobortis massa. Proin posuere ante ut metus vehicula suscipit. Proin mattis mauris ac lectus consequat rutrum. Nam arcu lectus, commodo non pretium a, pharetra semper dolor. Fusce eleifend hendrerit adipiscing. Nunc et eleifend erat. Suspendisse tempus nisl ut arcu blandit ut adipiscing nisi tristique. Suspendisse molestie facilisis risus sed fermentum. Praesent tempor convallis ultricies. Integer et elit velit, at consectetur risus. Vestibulum mollis adipiscing sodales. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris dictum molestie porta. Nam convallis nisl quis lacus vulputate in convallis risus sagittis. Vivamus accumsan faucibus cursus. Ut ultricies imperdiet ligula scelerisque blandit. In ornare egestas purus, at convallis velit egestas laoreet. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nulla quis imperdiet est. Nunc tempus magna quis lacus feugiat et posuere lacus vehicula. Cras lacinia aliquam est at vehicula. Aenean congue elit in ante dignissim vitae fermentum lectus aliquam. Mauris at odio magna, at interdum dui. Cras fringilla mi velit, nec varius neque. Fusce et volutpat lacus. Suspendisse id turpis et urna varius convallis in eu purus. Nulla facilisi. Etiam mauris nisl, ultrices ac porttitor sit amet, facilisis ut neque. Nullam ut velit quis velit tincidunt rhoncus. Praesent tristique porttitor euismod. Nulla non felis ante, feugiat commodo turpis. In nec venenatis mi. Duis tempus tempor purus, vitae consectetur mi ornare eu. Proin sed consequat erat. Quisque nec sem dui. Nam semper, ligula facilisis pretium interdum, diam lectus sollicitudin lorem, in elementum nisi lorem scelerisque justo. Nullam ac fringilla nunc. Maecenas malesuada ligula in massa sollicitudin sit amet auctor ipsum malesuada. Vestibulum ut augue in magna lobortis varius eget in ipsum. In hac habitasse platea dictumst. Cras vel sagittis mi. Aenean urna sapien, ultrices et tristique et, aliquam vel libero. Nullam in consequat ante. Suspendisse libero augue, pulvinar a dignissim vitae, fringilla malesuada dui. Phasellus augue ante, pulvinar eget tincidunt vel, venenatis sed arcu. Pellentesque ac purus orci, vel molestie turpis. Nulla consectetur sollicitudin dolor, sed ornare arcu accumsan fermentum. Fusce vestibulum nisi at leo interdum eu sollicitudin lacus dictum. Fusce malesuada consequat ipsum ut convallis. Maecenas in eros sit amet elit consectetur fringilla nec a nibh. Ut et velit vel ligula pharetra elementum. Nullam aliquam, tellus vel cursus lacinia, dui libero dictum turpis, nec lacinia dolor nunc vel diam. Pellentesque convallis dui quis lacus ornare at rutrum lorem pellentesque. Suspendisse potenti. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nunc ac nibh sed mauris ornare cursus. Praesent enim mauris, tincidunt vitae convallis ac, ultricies imperdiet sapien. Duis sodales ligula eget lorem suscipit sed consectetur metus pretium. Nam in magna augue, quis volutpat mauris. Quisque pretium lobortis orci quis laoreet. Nam ut nisi diam. Sed ultrices ultrices dapibus. Integer feugiat mauris id orci pulvinar eu tempus nibh viverra. Etiam venenatis bibendum massa a consequat. Fusce interdum velit ac mauris rhoncus non cursus neque consectetur. Vestibulum dictum eros ac metus fringilla venenatis. Phasellus auctor dui non nulla molestie id malesuada mauris euismod. Aenean id tortor ac justo eleifend mollis non vel arcu. Duis ac lorem tortor. Donec volutpat purus sed nunc luctus interdum hendrerit nulla ullamcorper. Sed consectetur interdum aliquet. Proin ullamcorper risus ut ante lacinia sagittis. Nunc varius eleifend purus, ac pellentesque urna viverra id. Praesent euismod, sapien accumsan gravida dictum, massa massa euismod sapien, ut auctor tellus arcu sed diam. Vivamus tincidunt dolor non lorem pellentesque at tempus elit adipiscing. Vestibulum tempor aliquam consectetur. Mauris nec dictum nisl. Donec scelerisque ornare condimentum. Phasellus laoreet justo nec nibh convallis convallis. Duis id orci sapien, eget pulvinar justo. Aenean id arcu felis, eu iaculis nibh. Aenean eleifend pretium rutrum. Aliquam molestie sem quis tellus aliquam eleifend. Mauris et purus orci. Nunc et accumsan tortor. Phasellus semper eleifend nisi, a faucibus risus vehicula id. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas in felis et est lacinia eleifend vel sed ipsum. Aliquam commodo molestie lorem id hendrerit. Nam sed tellus urna, sed dignissim eros. """ return A_LONG_STRING ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/nogil.h0000644000175100001770000000044400000000000017651 0ustar00runnerdocker00000000000000extern DL_EXPORT(void) e1(void); extern DL_EXPORT(int*) e2(void); void e1(void) {return;} int* e2(void) {return 0;} extern DL_EXPORT(PyObject *) g(PyObject*); extern DL_EXPORT(void) g2(PyObject*); PyObject *g(PyObject* o) {if (o) {}; return 0;} void g2(PyObject* o) {if (o) {}; return;} ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/nogil.pyx0000644000175100001770000000060500000000000020241 0ustar00runnerdocker00000000000000# mode: compile cdef extern object g(object x) nogil cdef extern void g2(object x) nogil cdef extern from "nogil.h": void e1() nogil int *e2() nogil cdef void f(int x) nogil: cdef int y y = 42 cdef void h(object x) nogil: cdef void *p=None g2(x) g2(p) p = x e1() e2() f(0) h(None) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/nonctypedefclass.pyx0000644000175100001770000000010200000000000022465 0ustar00runnerdocker00000000000000# mode: compile cdef class spam: pass cdef spam s s = None ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/none.pyx0000644000175100001770000000007300000000000020067 0ustar00runnerdocker00000000000000# mode: compile cdef void spam(): eggs = None spam() ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/notnonearg.pyx0000644000175100001770000000024500000000000021303 0ustar00runnerdocker00000000000000# mode: compile cdef extern class external.Spam [object Spam]: pass cdef extern class external.Eggs [object Eggs]: pass def ham(Spam s, Eggs e not None): pass ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/nullptr.pyx0000644000175100001770000000015200000000000020626 0ustar00runnerdocker00000000000000# mode: compile cdef char *p1 cdef int *p2 cdef int x p1 = NULL p2 = NULL x = p1 == NULL x = NULL == p2 ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/omittedargnames.pyx0000644000175100001770000000006500000000000022314 0ustar00runnerdocker00000000000000# mode: compile cdef extern void spam(int, char *) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/operators.h0000644000175100001770000000216600000000000020562 0ustar00runnerdocker00000000000000#ifndef _OPERATORS_H_ #define _OPERATORS_H_ class Operators { public: int value; Operators() { } Operators(int value) { this->value = value; } virtual ~Operators() { } Operators operator+(Operators f) { return Operators(this->value + f.value); } Operators operator-(Operators f) { return Operators(this->value - f.value); } Operators operator*(Operators f) { return Operators(this->value * f.value); } Operators operator/(Operators f) { return Operators(this->value / f.value); } bool operator<(Operators f) { return this->value < f.value; } bool operator<=(Operators f) { return this->value <= f.value; } bool operator==(Operators f) { return this->value == f.value; } bool operator!=(Operators f) { return this->value != f.value; } bool operator>(Operators f) { return this->value > f.value; } bool operator>=(Operators f) { return this->value >= f.value; } Operators operator>>(int v) { return Operators(this->value >> v); } Operators operator<<(int v) { return Operators(this->value << v); } Operators operator%(int v) { return Operators(this->value % v); } }; #endif ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/packed_structs.pyx0000644000175100001770000000024600000000000022150 0ustar00runnerdocker00000000000000# mode: compile cdef extern from *: cdef packed struct MyStruct: char a cdef public packed struct PublicStruct: int a unsigned char b int c ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/parallel_compile_float_rank.pyx0000644000175100001770000000017200000000000024634 0ustar00runnerdocker00000000000000# mode: compile from cython.parallel import * cdef ssize_t i with nogil, parallel(): for i in range(10): pass ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/pinard4.pyx0000644000175100001770000000014400000000000020470 0ustar00runnerdocker00000000000000# mode: compile __doc__ = u""" >>> fiches_CP [] """ fiches_CP = [1,2,3] fiches_CP[:] = [] ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/point.h0000644000175100001770000000022600000000000017670 0ustar00runnerdocker00000000000000#ifndef POINT_H #define POINT_H namespace geometry { struct Point { double x; double y; int color; }; } #endif ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/posix_pxds.pyx0000644000175100001770000000240700000000000021333 0ustar00runnerdocker00000000000000# tag: posix # mode: compile # This file is generated by `Tools/gen_tests_for_posix_pxds.py`. cimport posix cimport posix.dlfcn from posix cimport dlfcn from posix.dlfcn cimport * cimport posix.fcntl from posix cimport fcntl from posix.fcntl cimport * cimport posix.ioctl from posix cimport ioctl from posix.ioctl cimport * cimport posix.mman from posix cimport mman from posix.mman cimport * cimport posix.resource from posix cimport resource from posix.resource cimport * cimport posix.select from posix cimport select from posix.select cimport * cimport posix.signal from posix cimport signal from posix.signal cimport * cimport posix.stat from posix cimport stat from posix.stat cimport * cimport posix.stdio from posix cimport stdio from posix.stdio cimport * cimport posix.stdlib from posix cimport stdlib from posix.stdlib cimport * cimport posix.strings from posix cimport strings from posix.strings cimport * cimport posix.time from posix cimport time from posix.time cimport * cimport posix.types from posix cimport types from posix.types cimport * cimport posix.uio from posix cimport uio from posix.uio cimport * cimport posix.unistd from posix cimport unistd from posix.unistd cimport * cimport posix.wait from posix cimport wait from posix.wait cimport * ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/publicapi_api.pyx0000644000175100001770000000215700000000000021736 0ustar00runnerdocker00000000000000# mode: compile # -- ctypedef int Int0 ctypedef api int Int1 ctypedef enum EnumA0: EA0 ctypedef api enum EnumA1: EA1 cdef enum EnumB0: EB0=0 cdef api enum EnumB1: EB1=1 cdef Int0 i0 = 0 cdef EnumA0 ea0 = EA0 cdef EnumB0 eb0 = EB0 cdef api Int1 i1 = 0 cdef api EnumA1 ea1 = EA1 cdef api EnumB1 eb1 = EB1 # -- ctypedef struct StructA0: int SA0 ctypedef api struct StructA1: int SA1 cdef struct StructB0: int SB0 cdef api struct StructB1: int SB1 cdef StructA0 sa0 = {'SA0':0} cdef StructB0 sb0 = {'SB0':2} cdef api StructA1 sa1 = {'SA1':1} cdef api StructB1 sb1 = {'SB1':3} # -- ctypedef class Foo0: pass ctypedef api class Foo1 [type PyFoo1_Type, object PyFoo1_Object]: pass cdef class Bar0: pass cdef api class Bar1 [type PyBar1_Type, object PyBar1_Object]: pass cdef Foo0 f0 = None cdef Bar0 b0 = None cdef api Foo1 f1 = None cdef api Bar1 b1 = None # -- cdef void bar0(): pass cdef api void bar1(): pass cdef void* spam0(object o) except NULL: return NULL cdef api void* spam1(object o) except NULL: return NULL bar0() bar1() spam0(None) spam1(None) # -- ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/publicapi_cimport.pyx0000644000175100001770000000023500000000000022635 0ustar00runnerdocker00000000000000# mode: compile from publicapi_pxd_mix cimport * bar0() bar1() bar2() bar3() spam0(None) spam1(None) spam2(None) spam3(None) i0 = 0 i1 = 1 i2 = 2 i3 = 3 ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/publicapi_mix.pyx0000644000175100001770000000375600000000000021770 0ustar00runnerdocker00000000000000# mode: compile # -- ctypedef int Int0 ctypedef public int Int1 ctypedef api int Int2 ctypedef public api int Int3 ctypedef enum EnumA0: EA0 ctypedef public enum EnumA1: EA1 ctypedef api enum EnumA2: EA2 ctypedef public api enum EnumA3: EA3 cdef enum EnumB0: EB0=0 cdef public enum EnumB1: EB1=1 cdef api enum EnumB2: EB2=2 cdef public api enum EnumB3: EB3=3 # -- ctypedef struct StructA0: int SA0 ctypedef public struct StructA1: int SA1 ctypedef api struct StructA2: int SA2 ctypedef public api struct StructA3: int SA3 cdef struct StructB0: int SB0 cdef public struct StructB1: int SB1 cdef api struct StructB2: int SB2 cdef public api struct StructB3: int SB3 # -- ctypedef class Foo0: pass ctypedef public class Foo1 [type PyFoo1_Type, object PyFoo1_Object]: pass ctypedef api class Foo2 [type PyFoo2_Type, object PyFoo2_Object]: pass ctypedef public api class Foo3 [type PyFoo3_Type, object PyFoo3_Object]: pass cdef class Bar0: pass cdef public class Bar1 [type PyBar1_Type, object PyBar1_Object]: pass cdef api class Bar2 [type PyBar2_Type, object PyBar2_Object]: pass cdef public api class Bar3 [type PyBar3_Type, object PyBar3_Object]: pass # -- cdef void bar0(): pass cdef public void bar1(): pass cdef api void bar2(): pass cdef public api void bar3(): pass cdef void* spam0(object o) except NULL: return NULL cdef public void* spam1(object o) except NULL: return NULL cdef api void* spam2(object o) except NULL: return NULL cdef public api void* spam3(object o) except NULL: return NULL bar0() spam0(None) # -- cdef double d0 = 0 cdef public double d1 = 1 cdef api double d2 = 2 cdef public api double d3 = 3 cdef object o0 = None cdef public object o1 = None cdef api object o2 = None cdef public api object o3 = None # -- ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/publicapi_pub.pyx0000644000175100001770000000227200000000000021751 0ustar00runnerdocker00000000000000# mode: compile # -- ctypedef int Int0 ctypedef public int Int1 ctypedef enum EnumA0: EA0 ctypedef public enum EnumA1: EA1 cdef enum EnumB0: EB0=0 cdef public enum EnumB1: EB1=1 cdef Int0 i0 = 0 cdef EnumA0 ea0 = EA0 cdef EnumB0 eb0 = EB0 cdef public Int1 i1 = 0 cdef public EnumA1 ea1 = EA1 cdef public EnumB1 eb1 = EB1 # -- ctypedef struct StructA0: int SA0 ctypedef public struct StructA1: int SA1 cdef struct StructB0: int SB0 cdef public struct StructB1: int SB1 cdef StructA0 sa0 = {'SA0':0} cdef StructB0 sb0 = {'SB0':2} cdef public StructA1 sa1 = {'SA1':1} cdef public StructB1 sb1 = {'SB1':3} # -- ctypedef class Foo0: pass ctypedef public class Foo1 [type PyFoo1_Type, object PyFoo1_Object]: pass cdef class Bar0: pass cdef public class Bar1 [type PyBar1_Type, object PyBar1_Object]: pass cdef Foo0 f0 = None cdef Bar0 b0 = None cdef public Foo1 f1 = None cdef public Bar1 b1 = None # -- cdef void bar0(): pass cdef public void bar1(): pass cdef void* spam0(object o) except NULL: return NULL cdef public void* spam1(object o) except NULL: return NULL bar0() bar1() spam0(None) spam1(None) # -- ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/publicapi_pxd_mix.pxd0000644000175100001770000000362700000000000022613 0ustar00runnerdocker00000000000000# -- ctypedef int Int0 ctypedef public int Int1 ctypedef api int Int2 ctypedef public api int Int3 ctypedef enum EnumA0: EA0 ctypedef public enum EnumA1: EA1 ctypedef api enum EnumA2: EA2 ctypedef public api enum EnumA3: EA3 cdef enum EnumB0: EB0=0 cdef public enum EnumB1: EB1=1 cdef api enum EnumB2: EB2=2 cdef public api enum EnumB3: EB3=3 # -- ctypedef struct StructA0: int SA0 ctypedef public struct StructA1: int SA1 ctypedef api struct StructA2: int SA2 ctypedef public api struct StructA3: int SA3 cdef struct StructB0: int SB0 cdef public struct StructB1: int SB1 cdef api struct StructB2: int SB2 cdef public api struct StructB3: int SB3 # -- ctypedef class Foo0: pass ctypedef public class Foo1 [type PyFoo1_Type, object PyFoo1_Object]: pass ctypedef api class Foo2 [type PyFoo2_Type, object PyFoo2_Object]: pass ctypedef public api class Foo3 [type PyFoo3_Type, object PyFoo3_Object]: pass cdef class Bar0: pass cdef public class Bar1 [type PyBar1_Type, object PyBar1_Object]: pass cdef api class Bar2 [type PyBar2_Type, object PyBar2_Object]: pass cdef public api class Bar3 [type PyBar3_Type, object PyBar3_Object]: pass # -- cdef extern from *: void foo() cdef inline void bar (): pass cdef void bar0() cdef public void bar1() cdef api void bar2() cdef public api void bar3() cdef inline void* spam (object o) except NULL: return NULL cdef void* spam0(object o) except NULL cdef public void* spam1(object o) except NULL cdef api void* spam2(object o) except NULL nogil cdef public api void* spam3(object o) except NULL with gil # -- cdef int i0 = 0 # XXX implement initialization!!! cdef public int i1 cdef api int i2 cdef public api int i3 # -- ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/publicapi_pxd_mix.pyx0000644000175100001770000000127300000000000022633 0ustar00runnerdocker00000000000000# mode: compile cdef class Foo1: pass cdef class Foo2: pass cdef class Foo3: pass cdef class Bar1: pass cdef class Bar2: pass cdef class Bar3: pass cdef void bar0(): pass cdef public void bar1(): pass cdef api void bar2(): pass cdef public api void bar3(): pass cdef void* spam0(object o) except NULL: return NULL cdef public void* spam1(object o) except NULL: return NULL cdef api void* spam2(object o) except NULL nogil: return NULL cdef public api void* spam3(object o) except NULL with gil: return NULL cdef int i0 = 0 # XXX This should not be required! cdef public int i1 = 1 cdef api int i2 = 2 cdef public api int i3 = 3 ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/pxd_mangling_names.srctree0000644000175100001770000000117100000000000023611 0ustar00runnerdocker00000000000000# mode: compile # ticket: 2940 PYTHON setup.py build_ext --inplace PYTHON -c "import a; a.test()" ######## setup.py ######## from Cython.Build import cythonize from Cython.Distutils.extension import Extension from distutils.core import setup setup( ext_modules=cythonize([Extension("a", ["a.py", "b.c"])]), ) ######## a.pxd ######## cdef public int foo() cdef extern from "b.h": cpdef int bar() ######## a.py ######## def foo(): return 42 def test(): assert bar() == 42 ######## b.h ######## #ifndef B_H #define B_H int bar(); #endif ######## b.c ######## #include "a.h" int bar() { return foo(); } ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/pxd_override_T230.pxd0000644000175100001770000000011000000000000022275 0ustar00runnerdocker00000000000000cdef class A: cpdef foo(self) cdef class B(A): cpdef foo(self) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/pxd_override_T230.py0000644000175100001770000000016300000000000022142 0ustar00runnerdocker00000000000000# mode: compile class A: def foo(self): return "A" class B(A): def foo(self): return "B" ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/pyclass.pyx0000644000175100001770000000007700000000000020612 0ustar00runnerdocker00000000000000# mode: compile class Spam: def eggs(self): pass ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/pylong.pyx0000644000175100001770000000114700000000000020443 0ustar00runnerdocker00000000000000# mode: compile cdef extern from "Python.h": ctypedef struct PyTypeObject: pass ctypedef struct PyObject: Py_ssize_t ob_refcnt PyTypeObject *ob_type cdef extern from "Python.h": """ #if PY_MAJOR_VERSION < 3 #include "longintrepr.h" #endif """ cdef struct _longobject: int ob_refcnt PyTypeObject *ob_type # int ob_size # not in Py3k unsigned int *ob_digit def test(temp = long(0)): cdef _longobject *l l = <_longobject *> temp #print sizeof(l.ob_size) # not in Py3k print sizeof(l.ob_digit[0]) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/r_pernici1.pyx0000644000175100001770000000053500000000000021166 0ustar00runnerdocker00000000000000# mode: compile __doc__ = u""" >>> main() 3.14159265358979323846 3.14159265358979323846 3.14159265358979323846 """ cdef extern from "math.h": double M_PI #cdef unsigned long int n1 #n1 = 4293858116 cdef double pi pi = 3.14159265358979323846 def main(): #print n1 print "%.18f" % M_PI print "%.18f" % ( M_PI) print "%.18f" % pi ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/signedtypes.pyx0000644000175100001770000000046100000000000021467 0ustar00runnerdocker00000000000000# mode: compile cdef struct S: char c unsigned char uc signed char sc short s unsigned short us signed short ss int i unsigned int ui signed int si long l unsigned long ul signed long sl long long ll unsigned long long ull signed long long sll ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/slicex.pyx0000644000175100001770000000012600000000000020416 0ustar00runnerdocker00000000000000# mode: compile def f(a, b, c, d, e, f, g, h, i): a = b[c:d, e:f:g, ..., h, :i:] ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/specialfloatvals.pyx0000644000175100001770000000026200000000000022464 0ustar00runnerdocker00000000000000# mode: compile DEF nan = float('nan') DEF inf = float('inf') DEF minf = -float('inf') cdef int f() except -1: cdef float x, y, z x = nan y = inf z = minf f() ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/specmethargdefault.pyx0000644000175100001770000000021300000000000022773 0ustar00runnerdocker00000000000000# mode: compile cdef class Grail: def __cinit__(self, spam = None): pass def __init__(self, parrot = 42): pass ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/specmethdocstring.pyx0000644000175100001770000000146600000000000022664 0ustar00runnerdocker00000000000000# mode: compile cdef class C: def __cinit__(self): "This is an unusable docstring." def __init__(self): "This is an unusable docstring." def __dealloc__(self): "This is an unusable docstring." def __richcmp__(self, other, int op): "This is an unusable docstring." def __nonzero__(self): "This is an unusable docstring." return False def __contains__(self, other): "This is an unusable docstring." property foo: def __get__(self): "So is this." def __set__(self, x): "And here is another one." def __div__(self, other): "usable docstring" def __iter__(self): "usable docstring" return False def __next__(self): "usable docstring" return False ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/specmethextarg.pyx0000644000175100001770000000020600000000000022151 0ustar00runnerdocker00000000000000# mode: compile cdef class Spam: cdef int eggs def __iadd__(self, Spam other): self.eggs = self.eggs + other.eggs ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/stop_async_iteration_exception_pep492.pyx0000644000175100001770000000114700000000000026554 0ustar00runnerdocker00000000000000# mode: compile # tag: pep492 # make sure async iterators also compile correctly without using 'await' cdef class AsyncIter: cdef long i cdef long aiter_calls cdef long max_iter_calls def __init__(self, long max_iter_calls=1): self.i = 0 self.aiter_calls = 0 self.max_iter_calls = max_iter_calls def __aiter__(self): self.aiter_calls += 1 return self async def __anext__(self): self.i += 1 assert self.aiter_calls <= self.max_iter_calls if self.i > 10: raise StopAsyncIteration return self.i, self.i ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/templates.h0000644000175100001770000000067400000000000020544 0ustar00runnerdocker00000000000000#ifndef _TEMPLATES_H_ #define _TEMPLATES_H_ template class TemplateTest1 { public: T value; int t; TemplateTest1() { } T getValue() { return value; } }; template class TemplateTest2 { public: T value1; U value2; TemplateTest2() { } T getValue1() { return value1; } U getValue2() { return value2; } }; template void template_function(TemplateTest1 &) { } #endif ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/traceback.pyx0000644000175100001770000000021000000000000021040 0ustar00runnerdocker00000000000000# mode: compile def spam(): raise Exception cdef int grail() except -1: raise Exception def tomato(): spam() grail() ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/tree_assertions.pyx0000644000175100001770000000123700000000000022344 0ustar00runnerdocker00000000000000# mode: compile # This is a sort of meta test - to test the functionality of "test_assert_path_exists" cimport cython @cython.test_assert_path_exists("//ReturnStatNode") def not_in_inner_compiler_directives(): # used to fail because ReturnStatNode wasn't in *this* CompilerDirectivesNode with cython.boundscheck(False): pass return 1 # should pass @cython.test_assert_path_exists("//ReturnStatNode") def in_inner_compiler_directives(): # used to fail because ReturnStatNode wasn't in *this* CompilerDirectivesNode with cython.boundscheck(False): return 1 # it's hard to come up with a corresponding test for fail_if_path_exists.. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/tryexcept.pyx0000644000175100001770000000204200000000000021155 0ustar00runnerdocker00000000000000# mode: compile def f(a, b, c, x): cdef int i a = b + c try: i = 1 raise x i = 2 except a: i = 3 try: i = 1 except a: i = 2 except b: i = 3 try: i = 1 except a, b: i = 2 try: i = 1 except a: i = 2 except: i = 3 try: i = 1 except (a, b), c[42]: i = 2 for a in b: try: c = x * 42 except: i = 17 try: i = 1 except: raise def g(a, b, c, x): cdef int i a = b + c try: i = 1 raise x i = 2 except a: i = 3 try: i = 1 except a: i = 2 except b: i = 3 try: i = 1 except a as b: i = 2 try: i = 1 except a: i = 2 except: i = 3 try: i = 1 except (a, b) as c: i = 2 except (b, a) as c: i = 3 except: i = 4 else: i = 5 ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/tryfinally.pyx0000644000175100001770000000054700000000000021333 0ustar00runnerdocker00000000000000# mode: compile def f(a, b, c, x): cdef int i a = b + c try: return raise a finally: c = a - b for a in b: try: continue break c = a * b finally: i = 42 def use_name_in_finally(name): # GH3712 try: [] finally: name() ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/typecast.pyx0000644000175100001770000000023600000000000020765 0ustar00runnerdocker00000000000000# mode: compile cdef void f(obj): cdef size_t i=0 cdef char *p p = i p = &i obj = p p = obj f(None) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/types_and_names.pxd0000644000175100001770000000021400000000000022251 0ustar00runnerdocker00000000000000cdef struct point: double x double y double z cdef foo(int, int i, list, list L, point, point p, point* ps) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/types_and_names.pyx0000644000175100001770000000126500000000000022305 0ustar00runnerdocker00000000000000# mode: compile print sizeof(point*) cdef foo(int i0, int i, list L0, list L, point p0, point p, point* ps): pass cdef class A: cdef list cdef list L # Possibly empty declarators cdef point(self, int, int i, list, list L, point, point p, point* ps): pass cdef class B(A): cdef point(self, o, int i, oo, list L, ooo, point p, point* ps): pass cdef point P cdef point *Ps cdef A a foo(2, 3, [], [], P, P, &P) a.point("something", 3, "anything", [], "an object", P, &P) # Test that internally generated names do not conflict. cdef class A_spec: pass cdef class A_members: pass cdef class A_methods: pass cdef class A_slots: pass ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/utf8bom.pyx0000644000175100001770000000023400000000000020513 0ustar00runnerdocker00000000000000# coding: utf-8 # mode: compile # this file starts with a UTF-8 encoded BOM # the only thing we test is that it properly compiles def test(): pass ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/vector_include.pyx0000644000175100001770000000104700000000000022137 0ustar00runnerdocker00000000000000# mode: compile # tag: cpp # Test that using functionality from libcpp.vector does not lead to compile # errors when wildcard imports are used as well. # Import libcpp.vector, which declares PY_SSIZE_T_MAX. from libcpp.vector cimport vector # Import any other module using a wildcard import. from spam import * # Use the imports (details don't matter). cdef extern from *: """ #include std::vector get_vector() { return std::vector(17); } """ vector[int] get_vector() my_vector = get_vector() ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/verbatiminclude_cimport.srctree0000644000175100001770000000120400000000000024666 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace ######## setup.py ######## from Cython.Build import cythonize from distutils.core import setup setup( ext_modules = cythonize("*.pyx"), ) ######## test.pyx ######## from moda cimport DEFINE_A from modb cimport DEFINE_B ######## moda.pxd ######## from verbatim cimport DEFINE_ONCE as DEFINE_A ######## modb.pxd ######## from verbatim cimport DEFINE_ONCE as DEFINE_B ######## verbatim.pxd ######## # Check that we include this only once cdef extern from *: """ #ifdef DEFINE_ONCE #error "DEFINE_ONCE already defined" #endif #define DEFINE_ONCE 1 """ int DEFINE_ONCE ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/volatile.pyx0000644000175100001770000000052600000000000020752 0ustar00runnerdocker00000000000000# mode: compile cdef volatile int x = 1 cdef const volatile char* greeting1 = "hello world" cdef volatile const char* greeting2 = "goodbye" cdef extern from "stdlib.h": volatile void* malloc(size_t) cdef volatile long* test(volatile size_t s): cdef volatile long* arr = malloc(s) return arr test(64) ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/watts2.pyx0000644000175100001770000000005300000000000020352 0ustar00runnerdocker00000000000000# mode: compile cdef int x x = 0xFFFFFFFF ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/weakref_T276.pyx0000644000175100001770000000035600000000000021302 0ustar00runnerdocker00000000000000# ticket: t276 # mode: compile __doc__ = u""" """ cdef class A: cdef __weakref__ ctypedef public class B [type B_Type, object BObject]: cdef __weakref__ cdef public class C [type C_Type, object CObject]: cdef __weakref__ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/while.pyx0000644000175100001770000000045300000000000020242 0ustar00runnerdocker00000000000000# mode: compile def f(a, b): cdef int i = 5 while a: x = 1 while a+b: x = 1 while i: x = 1 else: x = 2 while i: x = 1 break x = 2 else: x = 3 while i: x = 1 continue x = 2 ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/compile/withgil.pyx0000644000175100001770000000015300000000000020576 0ustar00runnerdocker00000000000000# mode: compile cdef void f() with gil: x = 42 cdef int g(void* x) with gil: pass f() g("test") ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/cygwin_bugs.txt0000644000175100001770000000016300000000000020017 0ustar00runnerdocker00000000000000complex_numbers_c89_T398_long_double complex_numbers_T305_long_double int_float_builtins_as_casts_T400_long_double ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.128724 Cython-3.0.8/tests/errors/0000755000175100001770000000000000000000000016252 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/break_outside_loop.pyx0000644000175100001770000000162700000000000022673 0ustar00runnerdocker00000000000000# cython: remove_unreachable=False # mode: error break class A: break cdef class B: break def test(): break try: break except: pass try: break finally: pass if bool_result(): break else: break def bool_result(): return True def break_after_loop(): for _ in range(2): pass if bool_result(): break try: if bool_result(): break except Exception: pass if bool_result(): break _ERRORS = u''' 4:0: break statement not inside loop 7:4: break statement not inside loop 10:4: break statement not inside loop 13:4: break statement not inside loop 15:5: break statement not inside loop 18:5: break statement not inside loop 22:4: break statement not inside loop 24:4: break statement not inside loop 35:8: break statement not inside loop 39:12: break statement not inside loop 44:8: break statement not inside loop ''' ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/bufaccess_noassignT444.pyx0000644000175100001770000000030200000000000023226 0ustar00runnerdocker00000000000000# ticket: t444 # mode: error def test(): cdef object[int] not_assigned_to not_assigned_to[2] = 3 _ERRORS = """ 6:5: local variable 'not_assigned_to' referenced before assignment """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/buffertypedef_T117.pyx0000644000175100001770000000027200000000000022363 0ustar00runnerdocker00000000000000# ticket: t117 # mode: error ctypedef object[float] mybuffer _ERRORS = u""" 1:0: Buffer vars not allowed in module scope 4:0: Buffer types only allowed as function local variables """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/builtin_type_inheritance.pyx0000644000175100001770000000063600000000000024101 0ustar00runnerdocker00000000000000# mode: error # current restriction: cannot inherit from PyVarObject (see ticket #152) cdef class MyTuple(tuple): pass cdef class MyBytes(bytes): pass # str is also included in this in Py2, but checked at runtime instead _ERRORS = """ 5:19: inheritance from PyVarObject types like 'tuple' is not currently supported 8:19: inheritance from PyVarObject types like 'bytes' is not currently supported """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/callargs.pyx0000644000175100001770000000102500000000000020602 0ustar00runnerdocker00000000000000# mode: error def f(*args, **kwargs): pass args = (1,2,3) kwargs = {u"test" : "toast"} def test(): # ok f(1, 2, c=3, *args, d=5, **kwargs, **kwargs) f(1, 2, c=3, *args, d=5, **kwargs, x=6) f(1, 2, **kwargs, c=3) f(1, 2, c=3, *args, *args, **kwargs) f(*args, 1, 2, 3) # errors f(**kwargs, 1, 2, c=3) f(*args, **kwargs, *args) f(1, 2, c=3, *args, **kwargs, *args) f(1=2) # too bad we don't get more errors here ... _ERRORS = u""" 17:16: Non-keyword arg following keyword arg """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/callingnonexisting_T307.pyx0000644000175100001770000000017600000000000023434 0ustar00runnerdocker00000000000000# ticket: t307 # mode: error nonexisting(3, with_kw_arg=4) _ERRORS = u""" 4:0: undeclared name not builtin: nonexisting """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cdef_class_properties_decorated.pyx0000644000175100001770000000155100000000000025372 0ustar00runnerdocker00000000000000# mode: error # ticket: t264 # tag: property, decorator from functools import wraps def wrap_func(f): @wraps(f) def wrap(*args, **kwargs): print("WRAPPED") return f(*args, **kwargs) return wrap cdef class Prop: @property @wrap_func def prop1(self): return 1 @property def prop2(self): return 2 @wrap_func @prop2.setter def prop2(self, value): pass @prop2.setter @wrap_func def prop2(self, value): pass @prop2.setter def other_name(self, value): pass _ERRORS = """ 19:4: Property methods with additional decorators are not supported 27:4: Property methods with additional decorators are not supported 33:4: Property methods with additional decorators are not supported 37:4: Mismatching property names, expected 'prop2', got 'other_name' """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cdef_func_decorators.pyx0000644000175100001770000000145500000000000023162 0ustar00runnerdocker00000000000000# mode: error # tag: decorator from functools import wraps @wraps cdef cant_be_decoratored(): pass @wraps cpdef also_cant_be_decorated(): pass cdef class C: @wraps cdef still_cant_be_decorated(self): pass @property cdef property_only_works_for_extern_classes(self): pass @wraps cpdef also_still_cant_be_decorated(self): pass @wraps @wraps cdef two_is_just_as_bad_as_one(self): pass _ERRORS = """ 6:0: Cdef functions cannot take arbitrary decorators. 10:0: Cdef functions cannot take arbitrary decorators. 15:4: Cdef functions cannot take arbitrary decorators. 19:4: Cdef functions cannot take arbitrary decorators. 23:4: Cdef functions cannot take arbitrary decorators. 27:4: Cdef functions cannot take arbitrary decorators. """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cdef_func_syntax.pyx0000644000175100001770000000057000000000000022340 0ustar00runnerdocker00000000000000# mode: error cdef inline func() -> int: pass cpdef inline func() -> int: pass _ERRORS = u""" 3:19: Return type annotation is not allowed in cdef/cpdef signatures. Please define it before the function name, as in C signatures. 6:20: Return type annotation is not allowed in cdef/cpdef signatures. Please define it before the function name, as in C signatures. """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cdef_in_pyclass.pyx0000644000175100001770000000020000000000000022131 0ustar00runnerdocker00000000000000# mode: error class Pyclass(object): cdef bad(self): pass _ERRORS = """ 4:9: cdef statement not allowed here """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cdef_members_T517.pyx0000644000175100001770000000110500000000000022144 0ustar00runnerdocker00000000000000# ticket: t517 # mode: error ctypedef void* VoidP cdef class Spam: cdef VoidP vp0 cdef readonly VoidP vp2 cdef public VoidP vp1 ctypedef struct Foo: int i cdef class Bar: cdef Foo foo0 cdef readonly Foo foo2 cdef public Foo foo1 pass _ERRORS = u""" 8:24: C attribute of type 'VoidP' cannot be accessed from Python 8:24: Cannot convert 'VoidP' to Python object 9:24: C attribute of type 'VoidP' cannot be accessed from Python 9:24: Cannot convert 'VoidP' to Python object 9:24: Cannot convert Python object to 'VoidP' """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cdef_syntax.pyx0000644000175100001770000000026700000000000021330 0ustar00runnerdocker00000000000000# mode: error cdef pass cdef void cdef nogil class test: pass _ERRORS = u""" 3: 5: Expected an identifier, found 'pass' 4: 9: Empty declarator 5:11: Expected ':', found 'class' """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cdefkwargs.pyx0000644000175100001770000000035300000000000021135 0ustar00runnerdocker00000000000000# mode: error __doc__ = u""" >>> call2() >>> call3() >>> call4() """ # the calls: def call2(): b(1,2) def call3(): b(1,2,3) def call4(): b(1,2,3,4) # the called function: cdef b(a, b, c=1, d=2): pass ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cdefoptargs.pyx0000644000175100001770000000024700000000000021320 0ustar00runnerdocker00000000000000# mode: error def call5(): b(1,2,3,4,5) cdef b(a, b, c=1, d=2): pass _ERRORS = u""" 4:5:Call with wrong number of arguments (expected at most 4, got 5) """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cdefspecial.pyx0000644000175100001770000000037300000000000021261 0ustar00runnerdocker00000000000000# mode: error cdef class Test: cdef __cinit__(self): pass cdef __len__(self): pass _ERRORS = u""" 4:9: Special methods must be declared with 'def', not 'cdef' 7:9: Special methods must be declared with 'def', not 'cdef' """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cfunc_directive_in_pyclass.pyx0000644000175100001770000000024300000000000024373 0ustar00runnerdocker00000000000000# mode: error import cython class Pyclass(object): @cython.cfunc def bad(self): pass _ERRORS = """ 5:4: cfunc directive is not allowed here """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cfuncptr.pyx0000644000175100001770000000474400000000000020651 0ustar00runnerdocker00000000000000# mode: error cdef int exceptmaybeminus2(int bad) except ?-2: if bad: raise RuntimeError else: return 0 def fail_exceptmaybeminus2(bad): cdef int (*fptr_a)(int) except -2 cdef int (*fptr_b)(int) except -1 cdef int (*fptr_c)(int) except ?-1 fptr_a = exceptmaybeminus2 fptr_b = exceptmaybeminus2 fptr_c = exceptmaybeminus2 cdef extern from *: # define this as extern since Cython converts internal "except*" to "except -1" cdef int exceptstar(int bad) except * struct mystruct: int (*func_ptr)(int param) nogil void (*func_ptr_void)(int param) nogil def fail_exceptstar(bad): cdef int (*fptr_a)(int) noexcept cdef int (*fptr_b)(int) except -1 cdef int (*fptr_c)(int) except ?-1 fptr_a = exceptstar fptr_b = exceptstar fptr_c = exceptstar cdef int cb(int param) nogil: return param cdef void cb_void(int param) except * nogil: return def fail_struct_pointer(): cdef mystruct ms = mystruct(&cb, &cb_void) _ERRORS = """ 13:13: Cannot assign type 'int (int) except? -2' to 'int (*)(int) except -2'. Exception values are incompatible. 14:13: Cannot assign type 'int (int) except? -2' to 'int (*)(int) except -1'. Exception values are incompatible. 15:13: Cannot assign type 'int (int) except? -2' to 'int (*)(int) except? -1'. Exception values are incompatible. 29:13: Cannot assign type 'int (int) except *' to 'int (*)(int) noexcept'. Exception values are incompatible. Suggest adding 'noexcept' to type 'int (int) except *'. 30:13: Cannot assign type 'int (int) except *' to 'int (*)(int) except -1'. Exception values are incompatible. 31:13: Cannot assign type 'int (int) except *' to 'int (*)(int) except? -1'. Exception values are incompatible. 40:32: Cannot assign type 'int (*)(int) except? -1 nogil' to 'int (*)(int) noexcept nogil'. Exception values are incompatible. Suggest adding 'noexcept' to type 'int (int) except? -1 nogil'. 40:32: Cannot assign type 'int (*)(int) except? -1 nogil' to 'int (*)(int) noexcept nogil'. Exception values are incompatible. Suggest adding 'noexcept' to type 'int (int) except? -1 nogil'. 40:37: Cannot assign type 'void (*)(int) except * nogil' to 'void (*)(int) noexcept nogil'. Exception values are incompatible. Suggest adding 'noexcept' to type 'void (int) except * nogil'. 40:37: Cannot assign type 'void (*)(int) except * nogil' to 'void (*)(int) noexcept nogil'. Exception values are incompatible. Suggest adding 'noexcept' to type 'void (int) except * nogil'. """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/charptr_from_temp.pyx0000644000175100001770000000447300000000000022537 0ustar00runnerdocker00000000000000# mode: error # tag: werror, charptr, conversion, temp, py_unicode_strings cdef bytes c_s = b"abc" s = b"abc" cdef char* cptr # constant => ok cptr = b"xyz" # global cdef variable => ok cptr = c_s # pyglobal => warning cptr = s # temp => error cptr = s + b"cba" # indexing => error (but not clear enough to make it a compiler error) cptr = s[0] cdef char* x = s[0] # slicing => error cptr = s[:2] cdef unicode c_u = u"abc" u = u"abc" cdef Py_UNICODE* cuptr # constant => ok cuptr = u"xyz" # global cdef variable => ok cuptr = c_u # pyglobal => warning cuptr = u # temp => error cuptr = u + u"cba" # coercion in conditional expression => ok boolval = list(u) cptr = c_s if boolval else c_s # temp in conditional expression => error cptr = s + b'x' if boolval else s + b'y' _ERRORS = """ 16:7: Obtaining 'char *' from externally modifiable global Python value 19:9: Storing unsafe C derivative of temporary Python reference #22:8: Storing unsafe C derivative of temporary Python reference #23:5: Storing unsafe C derivative of temporary Python reference #23:15: Casting temporary Python object to non-numeric non-Python type 26:8: Storing unsafe C derivative of temporary Python reference 38:8: Py_UNICODE* has been removed in Python 3.12. This conversion to a Py_UNICODE* will no longer compile in the latest Python versions. Use Python C API functions like PyUnicode_AsWideCharString if you need to obtain a wchar_t* on Windows (and free the string manually after use). 41:8: Obtaining 'Py_UNICODE *' from externally modifiable global Python value 41:8: Py_UNICODE* has been removed in Python 3.12. This conversion to a Py_UNICODE* will no longer compile in the latest Python versions. Use Python C API functions like PyUnicode_AsWideCharString if you need to obtain a wchar_t* on Windows (and free the string manually after use). 44:10: Storing unsafe C derivative of temporary Python reference 44:10: Py_UNICODE* has been removed in Python 3.12. This conversion to a Py_UNICODE* will no longer compile in the latest Python versions. Use Python C API functions like PyUnicode_AsWideCharString if you need to obtain a wchar_t* on Windows (and free the string manually after use). 52:7: Storing unsafe C derivative of temporary Python reference 52:7: Unsafe C derivative of temporary Python reference used in conditional expression """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cimport_attributes.pyx0000644000175100001770000000162300000000000022741 0ustar00runnerdocker00000000000000# mode: error # tag: cpp cimport libcpp print libcpp.no_such_attribute cimport libcpp.map print libcpp.map.no_such_attribute from libcpp cimport vector print vector.no_such_attribute from libcpp cimport vector as my_vector print my_vector.no_such_attribute from libcpp cimport vector as my_vector_with_shadow from libcpp import vector as my_vector_with_shadow print my_vector_with_shadow.python_attribute # OK (if such a module existed at runtime) # Other ordering from libcpp import map as my_map_with_shadow from libcpp cimport map as my_map_with_shadow print my_map_with_shadow.python_attribute # OK (if such a module existed at runtime) _ERRORS = u""" 6:12: cimported module has no attribute 'no_such_attribute' 9:16: cimported module has no attribute 'no_such_attribute' 12:12: cimported module has no attribute 'no_such_attribute' 15:15: cimported module has no attribute 'no_such_attribute' """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cmethbasematch.pxd0000644000175100001770000000026300000000000021740 0ustar00runnerdocker00000000000000cdef class Base(object): cdef f(self) cdef class MissingRedeclaration(Base): pass cdef class BadRedeclaration(Base): cdef f(self) cdef class NarrowerReturn(Base): pass ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cmethbasematch.pyx0000644000175100001770000000213100000000000021761 0ustar00runnerdocker00000000000000# mode: error cdef class C: cdef void f(self): pass cdef class D(C): cdef void f(self, int x): pass # These are declared in the pxd. cdef class Base(object): cdef f(self): pass cdef class MissingRedeclaration(Base): # Not declared (so assumed cdef) in the pxd. cpdef f(self): pass cdef class BadRedeclaration(Base): # Declared as cdef in the pxd. cpdef f(self): pass cdef class UnneededRedeclaration(Base): # This is OK, as it's not declared in the pxd. cpdef f(self): pass cdef class NarrowerReturn(Base): # This does not require a new vtable entry. cdef Base f(self): pass _ERRORS = u""" 8: 9: Signature not compatible with previous declaration 4: 9: Previous declaration is here # TODO(robertwb): Re-enable these errors. #18:8: Compatible but non-identical C method 'f' not redeclared in definition part of extension type 'MissingRedeclaration' #2:9: Previous declaration is here #23:8: Compatible but non-identical C method 'f' not redeclared in definition part of extension type 'BadRedeclaration' #2:9: Previous declaration is here """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/compile_time_unraisable_T370.pyx0000644000175100001770000000024200000000000024402 0ustar00runnerdocker00000000000000# ticket: t370 # mode: error cdef int raiseit(): raise IndexError try: raiseit() except: pass _ERRORS = u""" FIXME: provide a good error message here. """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/const_decl_errors.pyx0000644000175100001770000000210600000000000022524 0ustar00runnerdocker00000000000000# mode: error cdef const object o # TODO: This requires making the assignment at declaration time. # (We could fake this case by dropping the const here in the C code, # as it's not needed for agreeing with external libraries. cdef const int x = 10 cdef struct S: int member cdef func(const int a, const int* b, const (int*) c, const S s, int *const d, int **const e, int *const *f, const S *const t): a = 10 c = NULL b[0] = 100 s.member = 1000 d = NULL e[0][0] = 1 # ok e[0] = NULL # ok e = NULL # nok f[0][0] = 1 # ok f[0] = NULL # nok f = NULL # ok t = &s cdef volatile object v _ERRORS = """ 3:5: Const/volatile base type cannot be a Python object 8:5: Assignment to const 'x' 15:4: Assignment to const 'a' 16:4: Assignment to const 'c' 17:5: Assignment to const dereference 18:5: Assignment to const attribute 'member' 19:4: Assignment to const 'd' 22:4: Assignment to const 'e' 24:5: Assignment to const dereference 26:4: Assignment to const 't' 28:5: Const/volatile base type cannot be a Python object """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/continue_outside_loop.pyx0000644000175100001770000000116200000000000023425 0ustar00runnerdocker00000000000000# cython: remove_unreachable=False # mode: error continue class A: continue cdef class B: continue def test(): continue try: continue except: pass try: continue finally: pass if bool_result(): continue else: continue def bool_result(): return True _ERRORS = ''' 4:0: continue statement not inside loop 7:4: continue statement not inside loop 10:4: continue statement not inside loop 13:4: continue statement not inside loop 15:5: continue statement not inside loop 18:5: continue statement not inside loop 22:4: continue statement not inside loop 24:4: continue statement not inside loop ''' ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cpdef_syntax.pyx0000644000175100001770000000031200000000000021477 0ustar00runnerdocker00000000000000# mode: error cpdef nogil: pass cpdef nogil class test: pass _ERRORS = u""" 3: 6: cdef blocks cannot be declared cpdef 4: 6: cdef blocks cannot be declared cpdef 4:12: Expected ':', found 'class' """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cpdef_vars.pyx0000644000175100001770000000075500000000000021137 0ustar00runnerdocker00000000000000# mode: error cpdef str a = "123" cpdef b = 2 cdef class C: cpdef float c def func(): """ >>> c = func() >>> isinstance(c, C) or c True """ cpdef d = C() return d _ERRORS = """ 3:6: Variables cannot be declared with 'cpdef'. Use 'cdef' instead. 4:6: Variables cannot be declared with 'cpdef'. Use 'cdef' instead. 7:10: Variables cannot be declared with 'cpdef'. Use 'cdef' instead. 15:10: Variables cannot be declared with 'cpdef'. Use 'cdef' instead. """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cpp_bool.pyx0000644000175100001770000000034000000000000020606 0ustar00runnerdocker00000000000000# tag: cpp # mode: error from libcpp.string cimport string cdef foo(): cdef string field if field: # field cannot be coerced to bool pass _ERRORS = u""" 8:7: Type 'string' not acceptable as a boolean """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cpp_class_gil_GH1986.pyx0000644000175100001770000000060400000000000022524 0ustar00runnerdocker00000000000000# tag: cpp # mode: error cdef cppclass Base: __init__() nogil: pass cdef cppclass Sub1(Base): __init__(): # implicit requires GIL pass cdef cppclass Sub2(Sub1): __init__() nogil: pass _ERRORS = u""" 10:4: Base constructor defined here. 14:4: Constructor cannot be called without GIL unless all base constructors can also be called without GIL """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cpp_comparison.pyx0000644000175100001770000000045200000000000022031 0ustar00runnerdocker00000000000000# mode: error # tag: cpp from libcpp.vector cimport vector def vector_is_none(vector[int] iv): # TODO: this isn't strictly wrong, so it might be allowed as a 'feature' at some point if iv is None: pass _ERRORS = """ 8:10: Invalid types for 'is' (vector[int], Python object) """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cpp_enum_redeclare.pyx0000644000175100001770000000023500000000000022630 0ustar00runnerdocker00000000000000# mode: error # tag: cpp cdef enum class Spam: a cdef enum class Spam: b _ERRORS=""" 7:5: 'Spam' redeclared 4:5: Previous declaration is here """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cpp_increment.pyx0000644000175100001770000000150400000000000021642 0ustar00runnerdocker00000000000000# mode: error cimport cython cdef extern from *: cdef cppclass Foo: Foo operator++() Foo operator--() cdef cppclass Bar: Bar operator++(int) Bar operator--(int) cdef void foo(): cdef Foo f cdef Bar b cython.operator.postincrement(f) cython.operator.postincrement(b) cython.operator.postdecrement(f) cython.operator.postdecrement(b) cython.operator.preincrement(f) cython.operator.preincrement(b) cython.operator.predecrement(f) cython.operator.predecrement(b) _ERRORS = u""" 17:19: No 'operator++(int)' declared for postfix '++' (operand type is 'Foo') 19:19: No 'operator--(int)' declared for postfix '--' (operand type is 'Foo') 23:19: No match for 'operator++' (operand type is 'Bar') 25:19: No match for 'operator--' (operand type is 'Bar') """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cpp_no_auto_conversion.pyx0000644000175100001770000000121100000000000023562 0ustar00runnerdocker00000000000000# mode: error # tag: cpp # cpp will convert function arguments to a type if it has suitable constructor # we do not want that when calling from cython cdef extern from "no_such_file.cpp" nogil: cppclass wrapped_int: long long val wrapped_int() wrapped_int(long long val) wrapped_int& operator=(const wrapped_int &other) wrapped_int& operator=(const long long other) long long constructor_overload(const wrapped_int& x) long long constructor_overload(const wrapped_int x) cdef long long e = constructor_overload(17) _ERRORS = u""" 18:40: Cannot assign type 'long' to 'const wrapped_int' """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cpp_no_const_iterator_conversion.pyx0000644000175100001770000000344500000000000025664 0ustar00runnerdocker00000000000000# mode: error # tag: cpp from libcpp.deque cimport deque from libcpp.list cimport list from libcpp.map cimport map from libcpp.set cimport set from libcpp.string cimport string from libcpp.unordered_map cimport unordered_map from libcpp.unordered_set cimport unordered_set from libcpp.vector cimport vector def deque_iterator(): cdef deque[int].iterator begin cdef deque[int].const_iterator cbegin = begin begin = cbegin def list_iterator(): cdef list[int].iterator begin cdef list[int].const_iterator cbegin = begin begin = cbegin def map_iterator(): cdef map[int, int].iterator begin cdef map[int, int].const_iterator cbegin = begin begin = cbegin def set_iterator(): cdef set[int].iterator begin cdef set[int].const_iterator cbegin = begin begin = cbegin def string_iterator(): cdef string.iterator begin cdef string.const_iterator cbegin = begin begin = cbegin def map_iterator(): cdef unordered_map[int, int].iterator begin cdef unordered_map[int, int].const_iterator cbegin = begin begin = cbegin def set_iterator(): cdef unordered_set[int].iterator begin cdef unordered_set[int].const_iterator cbegin = begin begin = cbegin def vector_iterator(): cdef vector[int].iterator begin cdef vector[int].const_iterator cbegin = begin begin = cbegin _ERRORS = u""" 16:12: Cannot assign type 'const_iterator' to 'iterator' 21:12: Cannot assign type 'const_iterator' to 'iterator' 26:12: Cannot assign type 'const_iterator' to 'iterator' 31:12: Cannot assign type 'const_iterator' to 'iterator' 36:12: Cannot assign type 'const_iterator' to 'iterator' 41:12: Cannot assign type 'const_iterator' to 'iterator' 46:12: Cannot assign type 'const_iterator' to 'iterator' 51:12: Cannot assign type 'const_iterator' to 'iterator' """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cpp_no_constructor.pyx0000644000175100001770000000030400000000000022734 0ustar00runnerdocker00000000000000# tag: cpp # mode: error cdef extern from *: cdef cppclass Foo: Foo() Foo(int) new Foo(1, 2) _ERRORS = u""" 9:7: Call with wrong number of arguments (expected 1, got 2) """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cpp_object_template.pyx0000644000175100001770000000104200000000000023014 0ustar00runnerdocker00000000000000# mode: error # tag: cpp from libcpp.vector cimport vector cdef class A: pass def main(): cdef vector[object] vo vo.push_back(object()) cdef vector[A] va va.push_back(A()) def memview(): import array cdef vector[int[:]] vmv vmv.push_back(array.array("i", [1,2,3])) _ERRORS = u""" 10:15: Python object type 'Python object' cannot be used as a template argument 12:15: Python object type 'A' cannot be used as a template argument 17:15: Reference-counted type 'int[:]' cannot be used as a template argument """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cpp_rvalue_reference_support.pyx0000644000175100001770000000134300000000000024767 0ustar00runnerdocker00000000000000# mode: error # tag: werror, cpp, cpp11 # These tests check for unsupported use of rvalue-references (&&) # and should be removed or cleaned up when support is added. cdef int&& x cdef void foo(int&& x): pass cdef int&& bar(): pass cdef extern from *: """ void baz(int x, int&& y) {} template void qux(const T&& x) {} """ cdef void baz(int x, int&& y) cdef void qux[T](const T&& x) _ERRORS=""" 7:8: C++ rvalue-references cannot be declared 9:13: Rvalue-reference as function argument not supported 12:14: Rvalue-reference as function return type not supported 22:17: Rvalue-reference as function argument not supported 23:20: Rvalue-reference as function argument not supported """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cppexc_non_extern.pyx0000644000175100001770000000066500000000000022544 0ustar00runnerdocker00000000000000# mode: error # tag: warnings cdef inline void handle_exception(): pass # GH 3064 - cppfunc caused invalid code to be generated with +handle_exception # error to prevent this cdef test_func1(self) except +handle_exception: pass # warning cdef test_func2(self) except +: pass _ERRORS = """ 9:5: Only extern functions can throw C++ exceptions. """ _WARNINGS = """ 13:5: Only extern functions can throw C++ exceptions. """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/cython3_bytes.pyx0000644000175100001770000000031400000000000021607 0ustar00runnerdocker00000000000000# mode: error # -*- coding: utf-8 -*- # cython: language_level=3 escaped = b'abc\xc3\xbc\xc3\xb6\xc3\xa4' invalid = b'abcüöä' _ERRORS = """ 6:10: bytes can only contain ASCII literal characters. """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/dataclass_e1.pyx0000644000175100001770000000144600000000000021345 0ustar00runnerdocker00000000000000# mode: error # tag: warnings cimport cython @cython.dataclasses.dataclass(1, shouldnt_be_here=True, init=5, unsafe_hash=True) cdef class C: a: list = [] # mutable b: int = cython.dataclasses.field(default=5, default_factory=int) c: int def __hash__(self): pass _ERRORS = """ 6:5: Arguments passed to cython.dataclasses.dataclass must be True or False 6:5: Cannot overwrite attribute __hash__ in class C 6:5: cython.dataclasses.dataclass() got an unexpected keyword argument 'shouldnt_be_here' 6:5: cython.dataclasses.dataclass takes no positional arguments 7:14: mutable default for field a is not allowed: use default_factory 8:37: cannot specify both default and default_factory 9:4: non-default argument 'c' follows default argument in dataclass __init__ """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/dataclass_e4.pyx0000644000175100001770000000034600000000000021346 0ustar00runnerdocker00000000000000# mode: error cimport cython @cython.dataclasses.dataclass cdef class C: a: int = cython.dataclasses.field(unexpected=True) _ERRORS = """ 7:49: cython.dataclasses.field() got an unexpected keyword argument 'unexpected' """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/dataclass_e5.pyx0000644000175100001770000000112000000000000021336 0ustar00runnerdocker00000000000000# mode: error # tag: warnings cimport cython @cython.dataclasses.dataclass cdef class C: a: int b: long c: Py_ssize_t d: float e: double _WARNINGS = """ 9:7: Found Python 2.x type 'long' in a Python annotation. Did you mean to use 'cython.long'? 10:7: Found C type 'Py_ssize_t' in a Python annotation. Did you mean to use 'cython.Py_ssize_t'? 10:7: Unknown type declaration 'Py_ssize_t' in annotation, ignoring 12:7: Found C type 'double' in a Python annotation. Did you mean to use 'cython.double'? 12:7: Unknown type declaration 'double' in annotation, ignoring """ ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880488.376722 Cython-3.0.8/tests/errors/dataclass_e6.pyx0000644000175100001770000000071700000000000021352 0ustar00runnerdocker00000000000000# mode: error from cython.dataclasses cimport dataclass @dataclass cdef class BaseDataclass: a: str = "value" @dataclass cdef class MainDataclass(BaseDataclass): a: str = "new value" cdef class Intermediate(BaseDataclass): pass @dataclass cdef class AnotherDataclass(Intermediate): a: str = "ooops" _ERRORS = """ 11:4: Cannot redeclare inherited fields in Cython dataclasses 18:4: Cannot redeclare inherited fields in Cython dataclasses """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/dataclass_w1.pyx0000644000175100001770000000051300000000000021361 0ustar00runnerdocker00000000000000# mode: compile # tag: warnings from dataclass_w1_othermod cimport SomeBase from cython.dataclasses cimport dataclass @dataclass cdef class DC(SomeBase): a: str = "" _WARNINGS = """ 8:5: Cannot reliably handle Cython dataclasses with base types in external modules since it is not possible to tell what fields they have """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/dataclass_w1_othermod.pxd0000644000175100001770000000010500000000000023232 0ustar00runnerdocker00000000000000# Extern class for test "dataclass_w1" cdef class SomeBase: pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/declareafteruse_T158.pyx0000644000175100001770000000316400000000000022677 0ustar00runnerdocker00000000000000# ticket: t158 # mode: error def mult_decl_test(): print "%s" % vv print "%s" % s cdef str s, vv = "Test" def def_test(): cdef int j = 10 i[0] = j cdef int *i = NULL # pointer variables are special case cdef cdef_test(): cdef int j = 10 i[0] = j print "%d" % i[0] cdef int *i = NULL cpdef cpdef_test(): cdef int j = 10 i[0] = j print "%d" % i[0] cdef int *i = NULL s.upper() cdef str s = "Test" class Foo(object): def bar(self, x, y): cdef unsigned long w = 20 z = w + t cdef int t = 10 cdef class Foo2(object): print '%s' % r # check error inside class scope cdef str r def bar(self, x, y): cdef unsigned long w = 20 self.r = c'r' print self.r z = w + g(t) cdef int t = 10 def g(x): return x cdef int d = 20 baz[0] = d cdef int *baz print var[0][0] cdef unsigned long long[100][100] var _ERRORS = u""" 5:17: local variable 'vv' referenced before assignment 6:17: local variable 's' referenced before assignment 7:13: cdef variable 's' declared after it is used 7:16: cdef variable 'vv' declared after it is used 12:14: cdef variable 'i' declared after it is used 18:14: cdef variable 'i' declared after it is used 24:14: cdef variable 'i' declared after it is used 27:9: cdef variable 's' declared after it is used 33:17: cdef variable 't' declared after it is used 43:17: cdef variable 't' declared after it is used 50:10: cdef variable 'baz' declared after it is used 53:34: cdef variable 'var' declared after it is used """ # FIXME not detected #37:13: cdef variable 'r' declared after it is used ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/dotted.module.pxd0000644000175100001770000000004400000000000021534 0ustar00runnerdocker00000000000000cdef inline int bar(): return 5 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/dotted_filenames.pyx0000644000175100001770000000031000000000000022314 0ustar00runnerdocker00000000000000# mode: compile # tag: warnings from dotted.module cimport bar _WARNINGS = """ 3:0: Dotted filenames ('dotted.module.pxd') are deprecated. Please use the normal Python package directory layout. """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/duplicate_const.pyx0000644000175100001770000000034000000000000022171 0ustar00runnerdocker00000000000000# mode: error cdef extern from *: cdef const const int a cdef const volatile int b cdef volatile const int c cdef volatile volatile int d _ERRORS = """ 4:9: Duplicate 'const' 7:9: Duplicate 'volatile' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e2_packedstruct_T290.pyx0000644000175100001770000000016100000000000022612 0ustar00runnerdocker00000000000000# ticket: t290 # mode: error cdef packed foo: pass _ERRORS = u""" 4:12: Expected 'struct', found 'foo' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_addop.pyx0000644000175100001770000000025600000000000020412 0ustar00runnerdocker00000000000000# mode: error def f(): cdef int int1, int3 cdef int *ptr1, *ptr2, *ptr3 ptr1 = ptr2 + ptr3 # error _ERRORS = u""" 6:13: Invalid operand types for '+' (int *; int *) """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_addressof.pyx0000644000175100001770000000145100000000000021273 0ustar00runnerdocker00000000000000# mode: error cdef class Ext: cdef int a cdef object o def f(int a): cdef Ext e = Ext() x = &a # ok cdef object o = &a # pointer != object po1 = &o # pointer to Python variable po2 = &o.xyz # pointer to Python expression po3 = &e.o # pointer to Python object po4 = &e.a # ok (C attribute) po5 = &(o + 1) # pointer to non-lvalue Python expression po6 = &(a + 1) # pointer to non-lvalue C expression _ERRORS=""" 11:20: Cannot convert 'int *' to Python object 13:10: Cannot take address of Python variable 'o' 14:10: Cannot take address of Python object attribute 'xyz' 15:10: Cannot take address of Python object attribute 'o' 18:10: Taking address of non-lvalue (type Python object) 19:10: Taking address of non-lvalue (type long) """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_argdefault.pyx0000644000175100001770000000132000000000000021432 0ustar00runnerdocker00000000000000# mode: error cdef spam(int i, char *s = "blarg", float f): # can't have default value pass def swallow(x, y = 42, z): # non-default after default pass cdef class Grail: def __add__(x, y = 42): # can't have default value pass def __pow__(x, y, z=10): # default must be None pass def __rpow__(x, y=2, z=None): # z is OK, y isn't pass _ERRORS = u""" 3:9: Non-default argument follows default argument 3:36: Non-default argument following default argument 6:23: Non-default argument following default argument 11:19: This argument cannot have a default value 14:22: This argument cannot have a non-None default value 17:20: This argument cannot have a default value """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_arrayassign.pyx0000644000175100001770000000112400000000000021641 0ustar00runnerdocker00000000000000# mode: error # cython: auto_pickle=False ctypedef int[1] int_array ctypedef int[2] int_array2 cdef int_array x, y x = y # not an error cdef int_array *x_ptr = &x x_ptr[0] = y # not an error cdef class A: cdef int_array value def __init__(self): self.value = x # not an error cdef int_array2 z z = x # error x = z # error cdef enum: SIZE = 2 ctypedef int[SIZE] int_array_dyn cdef int_array_dyn d d = z # not an error _ERRORS = u""" 21:0: Assignment to slice of wrong length, expected 2, got 1 22:0: Assignment to slice of wrong length, expected 1, got 2 """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_ass.pyx0000644000175100001770000000046000000000000020106 0ustar00runnerdocker00000000000000# mode: error cdef void foo(obj): cdef int i1 cdef char *p1 cdef int *p2 i1 = p1 # error p2 = obj # error obj = p2 # error _ERRORS = u""" 7:9: Cannot assign type 'char *' to 'int' 8:9: Cannot convert Python object to 'int *' 10:10: Cannot convert 'int *' to Python object """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_assert.pyx0000644000175100001770000000111700000000000020621 0ustar00runnerdocker00000000000000# mode: error # tag: assert def nontrivial_assert_in_nogil(int a, obj): with nogil: # NOK assert obj assert a*obj assert obj, "abc" # OK assert a assert a*a assert a, "abc" assert a, u"abc" assert a, f"123{a}xyz" _ERRORS = """ 7:15: Truth-testing Python object not allowed without gil 8:15: Converting to Python object not allowed without gil 8:16: Operation not allowed without gil 8:16: Truth-testing Python object not allowed without gil 9:15: Truth-testing Python object not allowed without gil """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_assnone.pyx0000644000175100001770000000014400000000000020765 0ustar00runnerdocker00000000000000# mode: error cdef void spam(): None = 42 _ERRORS = u""" 4:1: Cannot assign to or delete this """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_autotestdict.pyx0000644000175100001770000000025500000000000022036 0ustar00runnerdocker00000000000000# mode: error cimport cython @cython.autotestdict(False) def foo(): pass _ERRORS = u""" 5:0: The autotestdict compiler directive is not allowed in function scope """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_badexcvaltype.pyx0000644000175100001770000000025700000000000022157 0ustar00runnerdocker00000000000000# mode: error cdef char *spam() except -1: pass _ERRORS = u""" 3:26: Cannot assign type 'long' to 'char *' 3:26: Exception value incompatible with function return type """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_badfuncargtype.pyx0000644000175100001770000000071500000000000022321 0ustar00runnerdocker00000000000000# mode: error cdef struct Spam cdef extern int spam(void) # function argument cannot be void cdef extern int grail(int i, void v) # function argument cannot be void cdef int tomato(Spam s): # incomplete type pass _ERRORS = u""" 5:21: Use spam() rather than spam(void) to declare a function with no arguments. 6:29: Use spam() rather than spam(void) to declare a function with no arguments. 7:16: Argument type 'Spam' is incomplete """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_badpyparam.pyx0000644000175100001770000000020300000000000021433 0ustar00runnerdocker00000000000000# mode: error cdef struct Foo def f(Foo *p): pass _ERRORS = u""" 5:6: Cannot convert Python object argument to type 'Foo *' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_badtypeuse.pyx0000644000175100001770000000263700000000000021475 0ustar00runnerdocker00000000000000# mode: error cdef struct Grail cdef extern object xobj # Python object cannot be extern cdef object aobj[42] # array element cannot be Python object cdef object *pobj # pointer base type cannot be Python object cdef int spam[] # incomplete variable type cdef Grail g # incomplete variable type cdef void nada # incomplete variable type cdef int a_spam[17][] # incomplete element type cdef Grail a_g[42] # incomplete element type cdef void a_nada[88] # incomplete element type cdef struct Eggs: int spam[] cdef f(Grail g, # incomplete argument type void v, # incomplete argument type int a[]): pass cdef NoSuchType* ptr ptr = None # This should not produce another error _ERRORS = u""" 5:19: Python object cannot be declared extern 6:16: Array element cannot be a Python object 7:12: Pointer base type cannot be a Python object 9:13: Variable type 'int []' is incomplete 10:11: Variable type 'Grail' is incomplete 11:10: Variable type 'void' is incomplete 13:15: Array element type 'int []' is incomplete 14:14: Array element type 'Grail' is incomplete 15:16: Array element type 'void' is incomplete 18:9: Variable type 'int []' is incomplete #19:1: Function argument cannot be void 21:1: Use spam() rather than spam(void) to declare a function with no arguments. 20:7: Argument type 'Grail' is incomplete 21:1: Invalid use of 'void' 25:5: 'NoSuchType' is not a type identifier """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_binop_and.pyx0000644000175100001770000000035700000000000021256 0ustar00runnerdocker00000000000000# mode: error # tag: and, binop, warnings def test_and(a, b): return a && b _WARNINGS = """ 5:13: Found the C operator '&&', did you mean the Python operator 'and'? """ _ERRORS = """ 5:13: Syntax error in simple statement list """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_binop_or.pyx0000644000175100001770000000035400000000000021131 0ustar00runnerdocker00000000000000# mode: error # tag: or, binop, warnings def test_or(a, b): return a || b _WARNINGS = """ 5:13: Found the C operator '||', did you mean the Python operator 'or'? """ _ERRORS = """ 5:13: Syntax error in simple statement list """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_bitop.pyx0000644000175100001770000000023500000000000020435 0ustar00runnerdocker00000000000000# mode: error def f(): cdef int int1, int2 cdef char *ptr int1 = int2 | ptr # error _ERRORS = u""" 6:13: Invalid operand types for '|' (int; char *) """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_boolcoerce.pyx0000644000175100001770000000202600000000000021434 0ustar00runnerdocker00000000000000# mode: error ctypedef struct struct_type_not_boolean: int i float f if struct_type_not_boolean: print("INVALID CODE") cdef struct struct_not_boolean: int i float f if struct_not_boolean: print("INVALID CODE") ctypedef union union_type_not_boolean: int i float f if union_type_not_boolean: print("INVALID CODE") cdef union union_not_boolean: int i float f if union_not_boolean: print("INVALID CODE") _ERRORS = u""" 7:3: 'struct_type_not_boolean' is not a constant, variable or function identifier 7:3: Type 'struct_type_not_boolean' not acceptable as a boolean 14:3: 'struct_not_boolean' is not a constant, variable or function identifier 14:3: Type 'struct_not_boolean' not acceptable as a boolean 21:3: 'union_type_not_boolean' is not a constant, variable or function identifier 21:3: Type 'union_type_not_boolean' not acceptable as a boolean 28:3: 'union_not_boolean' is not a constant, variable or function identifier 28:3: Type 'union_not_boolean' not acceptable as a boolean """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_bufaccess.pyx0000644000175100001770000000153300000000000021260 0ustar00runnerdocker00000000000000# mode: error cdef object[int] buf cdef class A: cdef object[int] buf def f(): cdef object[fakeoption=True] buf1 cdef object[int, -1] buf1b cdef object[ndim=-1] buf2 cdef object[int, 'a'] buf3 cdef object[int,2,3,4,5,6] buf4 cdef object[int, 2, 'foo'] buf5 cdef object[int, 2, well] buf6 cdef object[x, 1] buf0 _ERRORS = u""" 3:17: Buffer types only allowed as function local variables 5:21: Buffer types only allowed as function local variables 8:27: "fakeoption" is not a buffer option """ #TODO: #7:22: "ndim" must be non-negative #8:15: "dtype" missing #9:21: "ndim" must be an integer #10:15: Too many buffer options #11:24: Only allowed buffer modes are "full" or "strided" (as a compile-time string) #12:28: Only allowed buffer modes are "full" or "strided" (as a compile-time string) #13:17: Invalid type. #""" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_bufaccess2.pyx0000644000175100001770000000156500000000000021347 0ustar00runnerdocker00000000000000# mode: error cimport e_bufaccess_pxd # was needed to provoke a bug involving ErrorType import cython def f(): cdef object[e_bufaccess_pxd.T] buf def withnogil_access_fail(): cdef object[int] buf = None with nogil: buf[2] = 2 @cython.boundscheck(False) def withnogil_access_ok(): cdef object[int] buf = None with nogil: buf[2] = 2 # No error should be triggered here @cython.boundscheck(False) def withnogil_access_fail_2(): cdef object[object] buf = None with nogil: buf[2] = 2 # Not OK as dtype is object def withnogil_acquire(x): cdef object[int] buf with nogil: buf = x _ERRORS = u""" 3: 9: 'nothing' is not a type identifier 24:11: Cannot access buffer with object dtype without gil 24:11: Assignment of Python object not allowed without gil 29:8: Assignment of Python object not allowed without gil """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_bufaccess_pxd.pxd0000644000175100001770000000005300000000000022102 0ustar00runnerdocker00000000000000# See e_bufaccess2.pyx ctypedef nothing T ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_callnonfunction.pyx0000644000175100001770000000045000000000000022513 0ustar00runnerdocker00000000000000# mode: error cdef int i i() cdef float f f() ctypedef struct s: # FIXME: this might be worth an error ... int x s() cdef int x(): return 0 x()() _ERRORS = u""" 4:1: Calling non-function type 'int' 7:1: Calling non-function type 'float' 16:3: Calling non-function type 'int' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_callspec.pyx0000644000175100001770000000404000000000000021104 0ustar00runnerdocker00000000000000# mode: error cimport cython ctypedef int USERTYPE # Functions @cython.callspec("") cdef void h1(): pass @cython.callspec("__cdecl") cdef void __cdecl h2(): pass @cython.callspec("__stdcall") cdef void __stdcall h3(): pass @cython.callspec("__fastcall") cdef void __fastcall h4(): pass cdef USERTYPE h5(): return 0 cdef USERTYPE __cdecl h6(): return 0 cdef USERTYPE __stdcall h7(): return 0 cdef USERTYPE __fastcall h8(): return 0 @cython.callspec("__cdecl") cdef void __stdcall herr1(): pass # fail @cython.callspec("__cdecl") cdef void __fastcall herr2(): pass # fail # Pointer typedefs ctypedef void (*PT1)() ctypedef void (__cdecl *PT2)() ctypedef void (__stdcall *PT3)() ctypedef void (__fastcall *PT4)() ctypedef USERTYPE (*PT5)() ctypedef USERTYPE (__cdecl *PT6)() ctypedef USERTYPE (__stdcall *PT7)() ctypedef USERTYPE (__fastcall *PT8)() # Pointers cdef void (*p1)() cdef void (__cdecl *p2)() cdef void (__stdcall *p3)() cdef void (__fastcall *p4)() cdef USERTYPE (*p5)() cdef USERTYPE (__cdecl *p6)() cdef USERTYPE (__stdcall *p7)() cdef USERTYPE (__fastcall *p8)() cdef PT1 pt1 cdef PT2 pt2 cdef PT3 pt3 cdef PT4 pt4 cdef PT5 pt5 cdef PT6 pt6 cdef PT7 pt7 cdef PT8 pt8 # Assignments p1 = pt1 = p2 = pt2 = h1 p1 = pt1 = p2 = pt2 = h2 p3 = pt3 = h3 p4 = pt4 = h4 p5 = pt5 = p6 = pt6 = h5 p5 = pt5 = p6 = pt6 = h6 p7 = pt7 = h7 p8 = pt8 = h8 #p1 = h2 # fail #p1 = h3 # fail #p1 = h4 # fail #p2 = h1 # fail #p2 = h3 # fail #p2 = h4 # fail _ERRORS = u""" 30:25: cannot have both '__stdcall' and '__cdecl' calling conventions 33:26: cannot have both '__fastcall' and '__cdecl' calling conventions """ #31:14: Cannot assign type 'void (__cdecl )(void)' to 'void (*)(void)' #32:14: Cannot assign type 'void (__stdcall )(void)' to 'void (*)(void)' #33:14: Cannot assign type 'void (__fastcall )(void)' to 'void (*)(void)' #35:14: Cannot assign type 'void (void)' to 'void (__cdecl *)(void)' #36:14: Cannot assign type 'void (__stdcall )(void)' to 'void (__cdecl *)(void)' #37:14: Cannot assign type 'void (__fastcall )(void)' to 'void (__cdecl *)(void)' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_cdef_closure.pyx0000644000175100001770000000021500000000000021753 0ustar00runnerdocker00000000000000# mode: error cpdef cpdef_yield(): def inner(): pass _ERRORS = u""" 3:6: closures inside cpdef functions not yet supported """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_cdef_in_py.py0000644000175100001770000000020400000000000021223 0ustar00runnerdocker00000000000000# mode: error def func(): cdef int i _ERRORS = """ 4:4: The 'cdef' keyword is only allowed in Cython files (pyx/pxi/pxd) """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_cdef_keywords_T241.pyx0000644000175100001770000000452700000000000022672 0ustar00runnerdocker00000000000000# ticket: t241 # mode: error cdef some_function(x, y): pass cdef class A: cdef some_method(self, x, y=1): pass from libc.string cimport strcmp cdef extern from "string.h": char *strstr(char*, char*) # ok some_function(1, 2) some_function(1, y=2) # nok some_function(1, x=1) some_function(1, x=2, y=2) some_function(1, y=2, z=3) some_function(1, z=3) some_function(1, 2, z=3) some_function(x=1, y=2, z=3) some_function(x=1, y=2, x=1) some_function(x=1, y=2, x=1, z=3) cdef A a = A() # ok a.some_method(1) a.some_method(1, 2) a.some_method(1, y=2) a.some_method(x=1, y=2) # nok a.some_method(1, x=1) a.some_method(1, 2, x=1) a.some_method(1, 2, y=2) a.some_method(1, 2, x=1, y=2) a.some_method(1, 2, y=2, x=1) a.some_method(1, y=2, x=1) a.some_method(1, 2, z=3) a.some_method(1, y=2, z=3) a.some_method(x=1, x=1) a.some_method(x=1, x=1, y=2) a.some_method(x=1, y=2, x=1) # ok strcmp("abc", "cde") strcmp("abc", s2="cde") strcmp(s1="abc", s2="cde") strcmp(s2="cde", s1="abc") # nok strcmp("abc", s1="cde") strcmp("abc", s2="cde", s1="cde") strcmp(s1="abc", s2="cde", s1="cde") strcmp(s2="cde", s1="abc", s2="cde") # ok strstr("abc", "abcdef") # nok strstr("abc", char="abcdef") strstr("abc", "abcdef", char="xyz") _ERRORS = u""" 22:17: argument 'x' passed twice 23:17: argument 'x' passed twice 24:22: C function got unexpected keyword argument 'z' 25:17: C function got unexpected keyword argument 'z' 26:20: C function got unexpected keyword argument 'z' 27:24: C function got unexpected keyword argument 'z' 28:24: argument 'x' passed twice 29:24: argument 'x' passed twice 29:29: C function got unexpected keyword argument 'z' 39:17: argument 'x' passed twice 40:20: argument 'x' passed twice 41:20: argument 'y' passed twice 42:20: argument 'x' passed twice 42:25: argument 'y' passed twice 43:20: argument 'y' passed twice 43:25: argument 'x' passed twice 44:22: argument 'x' passed twice 45:20: C function got unexpected keyword argument 'z' 46:22: C function got unexpected keyword argument 'z' 47:19: argument 'x' passed twice 48:19: argument 'x' passed twice 49:24: argument 'x' passed twice 58:14: argument 's1' passed twice 59:24: argument 's1' passed twice 60:27: argument 's1' passed twice 61:27: argument 's2' passed twice 67:14: C function got unexpected keyword argument 'char' 68:24: C function got unexpected keyword argument 'char' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_cdef_missing_declarator.pyx0000644000175100001770000000014300000000000024150 0ustar00runnerdocker00000000000000# mode: error cdef int cdef extern from *: void f(int) _ERRORS = u""" 3:8: Empty declarator """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_cdef_yield.pyx0000644000175100001770000000024000000000000021403 0ustar00runnerdocker00000000000000# mode: error cdef cdef_yield(): yield cpdef cpdef_yield(): yield _ERRORS = u""" 4:4: 'yield' not supported here 7:4: 'yield' not supported here """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_cdefassign.pyx0000644000175100001770000000044400000000000021430 0ustar00runnerdocker00000000000000# mode: error cdef class A: cdef int value = 3 cdef extern from *: cdef struct B: int value = 3 _ERRORS = u""" 4:13: Cannot assign default value to fields in cdef classes, structs or unions 8:12: Cannot assign default value to fields in cdef classes, structs or unions """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_cdefemptysue.pyx0000644000175100001770000000126200000000000022016 0ustar00runnerdocker00000000000000# mode: error cdef struct spam: pass ctypedef union eggs: pass cdef enum ham: pass cdef struct flat_spam: pass ctypedef union flat_eggs: pass cdef enum flat_ham: pass _ERRORS = u""" 3:5: Empty struct or union definition not allowed outside a 'cdef extern from' block 6:0: Empty struct or union definition not allowed outside a 'cdef extern from' block 9:5: Empty enum definition not allowed outside a 'cdef extern from' block 13:5: Empty struct or union definition not allowed outside a 'cdef extern from' block 15:0: Empty struct or union definition not allowed outside a 'cdef extern from' block 17:5: Empty enum definition not allowed outside a 'cdef extern from' block """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_cenum.pyx0000644000175100001770000000024000000000000020423 0ustar00runnerdocker00000000000000# mode: error cdef enum Spam: a, b, c cdef void f(): global a a = 42 # assignment to non-lvalue _ERRORS = u""" 8:1: Assignment to non-lvalue 'a' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_cenum_with_type.pyx0000644000175100001770000000013700000000000022524 0ustar00runnerdocker00000000000000# mode: error cdef enum Spam(int): a, b _ERRORS = u""" 3:14: Expected ':', found '(' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_cmp.pyx0000644000175100001770000000064500000000000020104 0ustar00runnerdocker00000000000000# mode: error cdef void foo(): cdef int bool, int1 cdef char *ptr2 cdef int *ptr3 cdef object i = 5 bool = i == ptr2 # evaluated in Python space bool = ptr3 == i # error bool = int1 == ptr2 # error bool = ptr2 == ptr3 # error bool = 1 in 2 in 3 _ERRORS = u""" 10:13: Invalid types for '==' (int *, Python object) 11:13: Invalid types for '==' (int, char *) 12:13: Invalid types for '==' (char *, int *) """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_cpp_nogil.pyx0000644000175100001770000000047300000000000021276 0ustar00runnerdocker00000000000000# mode: error # tag: cpp cdef extern from *: cdef int decl_invalid() except +nogil cdef int decl2_ok() except + nogil # comment following cdef int decl_ok() except + nogil _ERRORS = """ 5:36: 'except +nogil' defines an exception handling function. Use 'except + nogil' for the 'nogil' modifier. """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_cpp_only_features.pyx0000644000175100001770000000070200000000000023040 0ustar00runnerdocker00000000000000# mode: error # tag: no-cpp, werror from cython.operator import typeid def use_typeid(): cdef int i = 0 print typeid(i) == typeid(i) cdef cppclass A: pass def use_new(): cdef A* x = new A() def use_del(): cdef A a = A() cdef A *p = &a del p _ERRORS = """ 8:10: typeid operator only allowed in c++ 8:23: typeid operator only allowed in c++ 14:16: Operation only allowed in c++ 19:4: Operation only allowed in c++ """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_cpp_references.pyx0000644000175100001770000000032600000000000022304 0ustar00runnerdocker00000000000000# mode: error # tag: cpp, cpp11 cdef foo(object& x): pass cdef bar(object&& x): pass _ERRORS=""" 4:15: Reference base type cannot be a Python object 5:15: Rvalue-reference base type cannot be a Python object """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_cstruct.pyx0000644000175100001770000000156700000000000021020 0ustar00runnerdocker00000000000000# mode: error cdef struct Spam: int i char c float[42] *p obj # error - py object #cdef struct Spam: # error - redefined (not an error in Cython, should it be?) # int j cdef struct Grail cdef void eggs(Spam s): cdef int j cdef Grail *gp j = s.k # error - undef attribute j = s.p # type error s.p = j # type error j = j.i # no error - coercion to Python object j.i = j # no error - coercion to Python object j = gp.x # error - incomplete type gp.x = j # error - incomplete type _ERRORS = u""" 7:4: C struct/union member cannot be a Python object 17:9: Object of type 'Spam' has no attribute 'k' 18:9: Cannot assign type 'float (*)[42]' to 'int' 19:10: Cannot assign type 'int' to 'float (*)[42]' 22:10: Cannot select attribute of incomplete type 'Grail' 23:6: Cannot select attribute of incomplete type 'Grail' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_ctypedefornot.pyx0000644000175100001770000000037300000000000022210 0ustar00runnerdocker00000000000000# mode: error cdef struct Foo ctypedef struct Foo: int i ctypedef struct Blarg: char c cdef struct Blarg cdef Foo f cdef Blarg b _ERRORS = u""" 5:0: 'Foo' previously declared using 'cdef' 11:5: 'Blarg' previously declared using 'ctypedef' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_cunion.pyx0000644000175100001770000000053700000000000020620 0ustar00runnerdocker00000000000000# mode: error cdef union AllCharptr: char *s1 char *s2 char *s3 def convert_ok(): cdef AllCharptr u u.s1 = b"abc" return u cdef union IllegalMix: char *s1 char *s2 int i def convert_nok(): cdef IllegalMix u u.i = 5 return u _ERRORS = """ 24:11: Cannot convert 'IllegalMix' to Python object """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_cython_parallel.pyx0000644000175100001770000001063100000000000022501 0ustar00runnerdocker00000000000000# mode: error cimport cython.parallel.parallel as p from cython.parallel cimport something import cython.parallel.parallel as p from cython.parallel import something from cython.parallel cimport prange import cython.parallel prange(1, 2, 3, schedule='dynamic') cdef int i with nogil, cython.parallel.parallel(): for i in prange(10, schedule='invalid_schedule'): pass with cython.parallel.parallel(): print "hello world!" cdef int *x = NULL with nogil, cython.parallel.parallel(): for j in prange(10): pass for x[1] in prange(10): pass for x in prange(10): pass with cython.parallel.parallel(): pass with nogil, cython.parallel.parallel: pass cdef int y for i in prange(10, nogil=True): i = y * 4 y = i for i in prange(10, nogil=True): y = i i = y * 4 y = i with nogil, cython.parallel.parallel(): i = y y = i for i in prange(10, nogil=True): y += i y *= i with nogil, cython.parallel.parallel("invalid"): pass with nogil, cython.parallel.parallel(invalid=True): pass def f(x): cdef int i with nogil, cython.parallel.parallel(): with gil: yield x for i in prange(10): with gil: yield x # Disabled nesting: for i in prange(10, nogil=True): for y in prange(10): pass with nogil, cython.parallel.parallel(): for i in prange(10): for i in prange(10): pass # Assign to private from parallel block in prange: cdef int myprivate1, myprivate2 with nogil, cython.parallel.parallel(): myprivate1 = 1 for i in prange(10): myprivate1 = 3 myprivate2 = 4 myprivate2 = 2 # Disallow parallel with block reductions: i = 0 with nogil, cython.parallel.parallel(): i += 1 # Use of privates after the parallel with block with nogil, cython.parallel.parallel(): i = 1 print i i = 2 print i # Reading of reduction variables in the prange block cdef int sum = 0 for i in prange(10, nogil=True): sum += i with gil: print sum for pyobj in prange("hello"): pass from cython import parallel with nogil, parallel.parallel(): for i in parallel.prange(10): pass cdef int[:] dst, src = object() for i in prange(10, nogil=True): dst = src for i in prange(10, nogil=True, chunksize=20): pass for i in prange(10, nogil=True, schedule='static', chunksize=-1): pass for i in prange(10, nogil=True, schedule='runtime', chunksize=10): pass cdef int chunksize(): return 10 for i in prange(10, nogil=True, schedule='static', chunksize=chunksize()): pass with nogil, cython.parallel.parallel(): with cython.parallel.parallel(): pass _ERRORS = u""" 3:8: cython.parallel.parallel is not a module 4:0: No such directive: cython.parallel.something 6:7: cython.parallel.parallel is not a module 7:0: No such directive: cython.parallel.something 13:6: prange() can only be used as part of a for loop 13:6: prange() can only be used without the GIL 18:19: Invalid schedule argument to prange: invalid_schedule 21:29: The parallel section may only be used without the GIL 27:8: target may not be a Python object as we don't have the GIL 30:9: Can only iterate over an iteration variable 33:8: Must be of numeric type, not int * 36:33: Nested parallel with blocks are disallowed 39:12: The parallel directive must be called 45:8: local variable 'y' referenced before assignment 55:8: local variable 'y' referenced before assignment 60:4: Reduction operator '*' is inconsistent with previous reduction operator '+' 62:36: cython.parallel.parallel() does not take positional arguments 65:36: Invalid keyword argument: invalid 73:12: 'yield' not allowed in parallel sections 77:16: 'yield' not allowed in parallel sections 97:8: Cannot assign to private of outer parallel block 98:8: Cannot assign to private of outer parallel block 104:4: Reductions not allowed for parallel blocks 110:6: local variable 'i' referenced before assignment 119:14: Cannot read reduction variable in loop body 121:19: prange() can only be used without the GIL 121:20: stop argument must be numeric 131:4: Memoryview slices can only be shared in parallel sections 133:42: Must provide schedule with chunksize 136:62: Chunksize must not be negative 139:62: Chunksize not valid for the schedule runtime 145:70: Calling gil-requiring function not allowed without gil 149:33: Nested parallel with blocks are disallowed """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_declarations.pyx0000644000175100001770000000065100000000000021772 0ustar00runnerdocker00000000000000# mode: error cdef extern void fa[5]() cdef extern int af()[5] cdef extern int ff()() cdef void f(): cdef void *p cdef int (*h)() h = f # this is an error h = f # this is OK _ERRORS = u""" 3:20: Template arguments must be a list of names 3:20: Template parameter not a type 5:18: Function cannot return a function 10:10: Function cannot return a function 10:5: Cannot cast to a function type """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_del.pyx0000644000175100001770000000130400000000000020062 0ustar00runnerdocker00000000000000# mode: error cdef struct S: int m def f(a): cdef int i, x[2] cdef S s global j del f() # error del i # error: deletion of non-Python object del j # error: deletion of non-Python object del x[i] # error: deletion of non-Python object del s.m # error: deletion of non-Python object def outer(a): def inner(): print a del a return inner() cdef object g del g _ERRORS = u""" 10:9: Cannot assign to or delete this 11:8: Deletion of non-Python, non-C++ object 13:9: Deletion of non-Python, non-C++ object 14:9: Deletion of non-Python, non-C++ object 19:8: can not delete variable 'a' referenced in nested scope 23:4: Deletion of global C variable """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_directives.pyx0000644000175100001770000000052300000000000021461 0ustar00runnerdocker00000000000000# mode: error # cython: nonexistent = True # cython: boundscheck = true # cython: boundscheck = 9 print 3 # Options should not be interpreted any longer: # cython: boundscheck = true _ERRORS = u""" 4:0: boundscheck directive must be set to True or False, got 'true' 5:0: boundscheck directive must be set to True or False, got '9' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_exceptclause.pyx0000644000175100001770000000034000000000000022002 0ustar00runnerdocker00000000000000# mode: error try: raise KeyError except KeyError: pass except: pass except: pass except AttributeError: pass _ERRORS = u""" 9:0: default 'except:' must be last 11:0: default 'except:' must be last """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_excvalfunctype.pyx0000644000175100001770000000072600000000000022365 0ustar00runnerdocker00000000000000# mode: error ctypedef int (*spamfunc)(int, char *) except 42 ctypedef int (*grailfunc)(int, char *) noexcept cdef grailfunc grail cdef spamfunc spam grail = spam # type mismatch spam = grail # type mismatch _ERRORS = u""" 9:8: Cannot assign type 'spamfunc' to 'grailfunc'. Exception values are incompatible. Suggest adding 'noexcept' to type 'int (int, char *) except 42'. 10:7: Cannot assign type 'grailfunc' to 'spamfunc'. Exception values are incompatible. """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_exttype_freelist.pyx0000644000175100001770000000057200000000000022723 0ustar00runnerdocker00000000000000# mode: error # tag: freelist, werror cimport cython @cython.freelist(8) cdef class ExtType: pass @cython.freelist(8) cdef class ExtTypeObject(object): pass cdef class ExtSubTypeOk(ExtType): pass @cython.freelist(8) cdef class ExtSubTypeFail(ExtType): pass _ERRORS = """ 18:5: freelists cannot be used on subtypes, only the base class can manage them """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_exttype_total_ordering.pyx0000644000175100001770000001003400000000000024114 0ustar00runnerdocker00000000000000# mode: error # tag: total_ordering, warnings cimport cython # Test all combinations with not enough methods. @cython.total_ordering cdef class ExtNoFuncs: pass @cython.total_ordering cdef class ExtGe: def __ge__(self, other): return False @cython.total_ordering cdef class ExtLe: def __le__(self, other): return False @cython.total_ordering cdef class ExtLeGe: def __le__(self, other): return False def __ge__(self, other): return False @cython.total_ordering cdef class ExtGt: def __gt__(self, other): return False @cython.total_ordering cdef class ExtGtGe: def __gt__(self, other): return False def __ge__(self, other): return False @cython.total_ordering cdef class ExtGtLe: def __gt__(self, other): return False def __le__(self, other): return False @cython.total_ordering cdef class ExtGtLeGe: def __gt__(self, other): return False def __le__(self, other): return False def __ge__(self, other): return False @cython.total_ordering cdef class ExtLt: def __lt__(self, other): return False @cython.total_ordering cdef class ExtLtGe: def __lt__(self, other): return False def __ge__(self, other): return False @cython.total_ordering cdef class ExtLtLe: def __lt__(self, other): return False def __le__(self, other): return False @cython.total_ordering cdef class ExtLtLeGe: def __lt__(self, other): return False def __le__(self, other): return False def __ge__(self, other): return False @cython.total_ordering cdef class ExtLtGt: def __lt__(self, other): return False def __gt__(self, other): return False @cython.total_ordering cdef class ExtLtGtGe: def __lt__(self, other): return False def __gt__(self, other): return False def __ge__(self, other): return False @cython.total_ordering cdef class ExtLtGtLe: def __lt__(self, other): return False def __gt__(self, other): return False def __le__(self, other): return False @cython.total_ordering cdef class ExtLtGtLeGe: def __lt__(self, other): return False def __gt__(self, other): return False def __le__(self, other): return False def __ge__(self, other): return False @cython.total_ordering cdef class ExtNe: def __ne__(self, other): return False @cython.total_ordering cdef class ExtEq: def __eq__(self, other): return False @cython.total_ordering cdef class ExtEqNe: def __eq__(self, other): return False def __ne__(self, other): return False _WARNINGS = """ 10:5: total_ordering directive used, but no comparison and equality methods defined 14:5: total_ordering directive used, but no equality method defined 19:5: total_ordering directive used, but no equality method defined 24:5: total_ordering directive used, but no equality method defined 32:5: total_ordering directive used, but no equality method defined 37:5: total_ordering directive used, but no equality method defined 45:5: total_ordering directive used, but no equality method defined 53:5: total_ordering directive used, but no equality method defined 64:5: total_ordering directive used, but no equality method defined 69:5: total_ordering directive used, but no equality method defined 77:5: total_ordering directive used, but no equality method defined 85:5: total_ordering directive used, but no equality method defined 96:5: total_ordering directive used, but no equality method defined 104:5: total_ordering directive used, but no equality method defined 115:5: total_ordering directive used, but no equality method defined 126:5: total_ordering directive used, but no equality method defined 140:5: total_ordering directive used, but no comparison methods defined 145:5: total_ordering directive used, but no comparison methods defined 150:5: total_ordering directive used, but no comparison methods defined """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_extweakref.pyx0000644000175100001770000000126200000000000021466 0ustar00runnerdocker00000000000000# mode: error cdef class C: cdef object __weakref__ cdef class D: cdef public object __weakref__ cdef class E: cdef readonly object __weakref__ cdef void f(): cdef C c = C() cdef object x x = c.__weakref__ c.__weakref__ = x _ERRORS = u""" 7:20: Illegal use of special attribute __weakref__ 7:20: Illegal use of special attribute __weakref__ 7:20: Illegal use of special attribute __weakref__ 7:20: Special attribute __weakref__ cannot be exposed to Python 10:22: Illegal use of special attribute __weakref__ 10:22: Special attribute __weakref__ cannot be exposed to Python 15:6: Illegal use of special attribute __weakref__ 16:2: Illegal use of special attribute __weakref__ """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_fstring.pyx0000644000175100001770000000103300000000000020771 0ustar00runnerdocker00000000000000# mode: error # tag: fstring def incorrect_fstrings(x): return [ f"{x}{'\\'}'{x+1}", f"""{}""", f"{}", f"{x!}", f"{", f"{{}}}", ] _ERRORS = """ 6:16: backslashes not allowed in f-strings 7:14: empty expression not allowed in f-string 8:12: empty expression not allowed in f-string 9:14: missing '}' in format string expression, found '!' 10:12: empty expression not allowed in f-string 10:12: missing '}' in format string expression 11:15: f-string: single '}' is not allowed """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_func_in_pxd.pyx0000644000175100001770000000040000000000000021606 0ustar00runnerdocker00000000000000# mode: error cimport e_func_in_pxd_support _ERRORS = u""" 1:5: function definition in pxd file must be declared 'cdef inline' 4:5: inline function definition in pxd file cannot be 'public' 7:5: inline function definition in pxd file cannot be 'api' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_func_in_pxd_support.pxd0000644000175100001770000000015000000000000023357 0ustar00runnerdocker00000000000000cdef foo(): return 1 cdef public inline foo2(): return 1 cdef api inline foo3(): return 1 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_fused_closure.pyx0000644000175100001770000000106000000000000022157 0ustar00runnerdocker00000000000000# mode: error cimport cython def closure(cython.integral i): def inner(cython.floating f): pass def closure2(cython.integral i): return lambda cython.integral i: i def closure3(cython.integral i): def inner(): return lambda cython.floating f: f def generator(cython.integral i): yield i _ERRORS = u""" e_fused_closure.pyx:6:4: Cannot nest fused functions e_fused_closure.pyx:10:11: Fused lambdas not allowed e_fused_closure.pyx:14:15: Fused lambdas not allowed e_fused_closure.pyx:16:0: Fused generators not supported """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_generators.pyx0000644000175100001770000000042500000000000021472 0ustar00runnerdocker00000000000000# mode: error def foo(): yield return 0 def bar(a): return 0 yield yield class Foo: yield _ERRORS = u""" #5:4: 'return' with argument inside generator #9:4: 'yield' outside function 11:0: 'yield' not supported here 14:4: 'yield' not supported here """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_index.pyx0000644000175100001770000000062300000000000020430 0ustar00runnerdocker00000000000000# mode: error def f(obj1, obj2): cdef int int1, int2, int3 cdef float flt1, *ptr1 cdef int array1[42] int1 = array1[flt1] # error int1 = array1[ptr1] # error int1 = int2[int3] # error obj1 = obj2[ptr1] # error _ERRORS = u""" 7:14: Invalid index type 'float' 8:14: Invalid index type 'float *' 9:12: Attempting to index non-array type 'int' 10:13: Cannot convert 'float *' to Python object """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_int_literals_py2.py0000644000175100001770000000055500000000000022420 0ustar00runnerdocker00000000000000# mode: error # cython: language_level=2 def int_literals(): a = 1L # ok b = 10000000000000L # ok c = 1UL d = 10000000000000UL e = 10000000000000LL _ERRORS = """ 7:8: illegal integer literal syntax in Python source file 8:8: illegal integer literal syntax in Python source file 9:8: illegal integer literal syntax in Python source file """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_int_literals_py3.py0000644000175100001770000000072500000000000022420 0ustar00runnerdocker00000000000000# mode: error # cython: language_level=3 def int_literals(): a = 1L b = 10000000000000L c = 1UL d = 10000000000000UL e = 10000000000000LL _ERRORS = """ 5:8: illegal integer literal syntax in Python source file 6:8: illegal integer literal syntax in Python source file 7:8: illegal integer literal syntax in Python source file 8:8: illegal integer literal syntax in Python source file 9:8: illegal integer literal syntax in Python source file """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_invalid_num_threads.pyx0000644000175100001770000000162000000000000023336 0ustar00runnerdocker00000000000000# mode: error from cython.parallel cimport parallel, prange cdef int i # valid with nogil, parallel(num_threads=None): pass # invalid with nogil, parallel(num_threads=None, num_threads=None): pass with nogil, parallel(num_threads=0): pass with nogil, parallel(num_threads=i): pass with nogil, parallel(num_threads=2, num_threads=2): pass with nogil, parallel(num_threads=2): for i in prange(10, num_threads=2): pass with nogil, parallel(): for i in prange(10, num_threads=2): pass # this one is valid for i in prange(10, nogil=True, num_threads=2): pass _ERRORS = u""" 12:20: Duplicate keyword argument found: num_threads 15:20: argument to num_threads must be greater than 0 21:20: Duplicate keyword argument found: num_threads 25:19: num_threads already declared in outer section 29:19: num_threads must be declared in the parent parallel section """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_invalid_special_cython_modules.py0000644000175100001770000000301700000000000025373 0ustar00runnerdocker00000000000000# mode: error # tag: pure, import, cimport # nok import cython.imports.libc as libc_import import cython.cimports.labc as labc_cimport from cython.imports import libc from cython.cimport.libc import math from cython.imports.libc import math from cython.cimports.labc import math import cython.paralel import cython.parrallel import cython.dataclass import cython.floating import cython.cfunc # ok from cython.cimports.libc import math from cython.cimports.libc.math import ceil def libc_math_ceil(x): """ >>> libc_math_ceil(1.5) [2, 2] """ return [int(n) for n in [ceil(x), math.ceil(x)]] _ERRORS = """ 6:7: 'cython.imports.libc' is not a valid cython.* module. Did you mean 'cython.cimports' ? 7:7: 'labc.pxd' not found 9:0: 'cython.imports' is not a valid cython.* module. Did you mean 'cython.cimports' ? 10:0: 'cython.cimport.libc' is not a valid cython.* module. Did you mean 'cython.cimports' ? 11:0: 'cython.imports.libc' is not a valid cython.* module. Did you mean 'cython.cimports' ? 12:0: 'labc/math.pxd' not found 14:7: 'cython.paralel' is not a valid cython.* module. Did you mean 'cython.parallel' ? 15:7: 'cython.parrallel' is not a valid cython.* module. Did you mean 'cython.parallel' ? 17:7: 'cython.dataclass' is not a valid cython.* module. Did you mean 'cython.dataclasses' ? 18:7: 'cython.floating' is not a valid cython.* module. Instead, use 'import cython' and then 'cython.floating'. 19:7: 'cython.cfunc' is not a valid cython.* module. Instead, use 'import cython' and then 'cython.cfunc'. """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_multass.pyx0000644000175100001770000000027500000000000021014 0ustar00runnerdocker00000000000000# mode: error def f(obj1a, obj1b): cdef int int1, int2, int3 cdef int *ptr2 int1, int3, obj1a = int2, ptr2, obj1b # error _ERRORS = u""" 6:27: Cannot assign type 'int *' to 'int' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_nargs.pyx0000644000175100001770000000111100000000000020424 0ustar00runnerdocker00000000000000# mode: error cdef extern grail(char *s, int i) cdef extern spam(char *s, int i,...) cdef f(): grail() # too few args grail("foo") # too few args grail("foo", 42, 17) # too many args spam() # too few args spam("blarg") # too few args _ERRORS = u""" 7:6: Call with wrong number of arguments (expected 2, got 0) 8:6: Call with wrong number of arguments (expected 2, got 1) 9:6: Call with wrong number of arguments (expected 2, got 3) 10:5: Call with wrong number of arguments (expected at least 2, got 0) 11:5: Call with wrong number of arguments (expected at least 2, got 1) """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_nogilcmeth.pxd0000644000175100001770000000004100000000000021417 0ustar00runnerdocker00000000000000cdef class C: cdef void f(self) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_nogilcmeth.pyx0000644000175100001770000000025600000000000021454 0ustar00runnerdocker00000000000000# mode: error cdef class C: cdef void f(self) nogil: pass _ERRORS = u""" 2:12: Previous declaration is here 4: 6: Signature not compatible with previous declaration """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_nogilfunctype.pyx0000644000175100001770000000055300000000000022211 0ustar00runnerdocker00000000000000# mode: error # tag: warnings cdef extern from *: cdef void f() cdef void (*fp)() nogil ctypedef void (*fp_t)() nogil fp = f fp = f _ERRORS = u""" 9:5: Cannot assign type 'void (void) noexcept' to 'void (*)(void) noexcept nogil' """ _WARNINGS = """ 10:5: Casting a GIL-requiring function into a nogil function circumvents GIL validation """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_nonlocal_T490.pyx0000644000175100001770000000126200000000000021646 0ustar00runnerdocker00000000000000# mode: error def test_non_existant(): nonlocal no_such_name no_such_name = 1 def redef(): x = 1 def f(): x = 2 nonlocal x global_name = 5 def ref_to_global(): nonlocal global_name global_name = 6 def global_in_class_scope(): class Test(): nonlocal global_name global_name = 6 def redef_in_class_scope(): x = 1 class Test(): x = 2 nonlocal x _ERRORS = u""" 4:4: no binding for nonlocal 'no_such_name' found 10:8: Previous declaration is here 11:8: 'x' redeclared as nonlocal 16:4: no binding for nonlocal 'global_name' found 27:8: Previous declaration is here 28:8: 'x' redeclared as nonlocal """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_nosignword.pyx0000644000175100001770000000072400000000000021514 0ustar00runnerdocker00000000000000# mode: error cdef signed float e cdef unsigned float f cdef signed double g cdef unsigned double h cdef signed long double i cdef unsigned long double j _ERRORS = u""" 3:5: Unrecognised type modifier combination 4:5: Unrecognised type modifier combination 5:5: Unrecognised type modifier combination 6:5: Unrecognised type modifier combination 7:5: Unrecognised type modifier combination 8:5: Unrecognised type modifier combination """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_notnone.pyx0000644000175100001770000000024400000000000021000 0ustar00runnerdocker00000000000000# mode: error cdef extern class Grail.Shrubbery cdef void spam(Shrubbery sh not None): pass _ERRORS = u""" 5:15: 'not None' only allowed in Python functions """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_notnone2.pyx0000644000175100001770000000027600000000000021067 0ustar00runnerdocker00000000000000# mode: error def eggs(int x not None, char* y not None): pass _ERRORS = u""" 3: 9: Only Python type arguments can have 'not None' 3:25: Only Python type arguments can have 'not None' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_numop.pyx0000644000175100001770000000023300000000000020454 0ustar00runnerdocker00000000000000# mode: error def f(): cdef int int1, int2 cdef int *ptr int1 = int2 * ptr # error _ERRORS = u""" 6:13: Invalid operand types for '*' (int; int *) """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_powop.pyx0000644000175100001770000000037600000000000020472 0ustar00runnerdocker00000000000000# mode: error def f(): cdef char *str1 cdef float flt1, flt2, flt3 flt1 = str1 ** flt3 # error flt1 = flt2 ** str1 # error _ERRORS = u""" 6:13: Invalid operand types for '**' (char *; float) 7:13: Invalid operand types for '**' (float; char *) """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_public_cdef_private_types.pyx0000644000175100001770000000226500000000000024542 0ustar00runnerdocker00000000000000# mode: error ctypedef char *string_t ctypedef public char *public_string_t ctypedef api char *api_string_t # This should all fail cdef public pub_func1(string_t x): pass cdef api api_func1(string_t x): pass cdef public string_t pub_func2(): pass cdef api string_t api_func2(): pass cdef public opt_pub_func(x = None): pass cdef api opt_api_func(x = None): pass # This should all work cdef public pub_func3(public_string_t x, api_string_t y): pass cdef api api_func3(public_string_t x, api_string_t y): pass cdef opt_func(x = None): pass _ERRORS = u""" e_public_cdef_private_types.pyx:8:22: Function declared public or api may not have private types e_public_cdef_private_types.pyx:11:19: Function declared public or api may not have private types e_public_cdef_private_types.pyx:14:5: Function declared public or api may not have private types e_public_cdef_private_types.pyx:17:5: Function declared public or api may not have private types e_public_cdef_private_types.pyx:20:24: Function with optional arguments may not be declared public or api e_public_cdef_private_types.pyx:23:21: Function with optional arguments may not be declared public or api """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_pure_cimports.pyx0000644000175100001770000000234500000000000022217 0ustar00runnerdocker00000000000000# mode: error # tag: pure, import, cimport import cython.cimportsy import cython.cimports import cython.cimports.libc import cython.cimports as cim cimport cython.cimports cimport cython.cimports.libc cimport cython.cimports as cim import cython.cimports.libc as cython # ok import cython.cimports.libc as libc from cython.cimports import libc from cython.cimports cimport libc _ERRORS = """ 4:7: 'cython.cimportsy' is not a valid cython.* module. Did you mean 'cython.cimports' ? 6:7: Cannot cimport the 'cython.cimports' package directly, only submodules. 7:7: Python cimports must use 'from cython.cimports... import ...' or 'import ... as ...', not just 'import ...' 8:7: Cannot cimport the 'cython.cimports' package directly, only submodules. 10:8: Cannot cimport the 'cython.cimports' package directly, only submodules. 11:8: Python cimports must use 'from cython.cimports... import ...' or 'import ... as ...', not just 'import ...' 12:8: Cannot cimport the 'cython.cimports' package directly, only submodules. # The following is not an accurate error message, but it's difficult to distinguish this case. And it's rare. 13:7: Python cimports must use 'from cython.cimports... import ...' or 'import ... as ...', not just 'import ...' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_pxdimpl.pyx0000644000175100001770000000041500000000000020775 0ustar00runnerdocker00000000000000# mode: error cimport e_pxdimpl_imported _ERRORS = u""" 6:4: function definition in pxd file must be declared 'cdef inline' 18:4: function definition in pxd file must be declared 'cdef inline' 23:8: function definition in pxd file must be declared 'cdef inline' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_pxdimpl_imported.pxd0000644000175100001770000000105600000000000022655 0ustar00runnerdocker00000000000000 cdef class A: cdef int test(self) # Should give error: def somefunc(self): pass # While this should *not* be an error...: def __getbuffer__(self, Py_buffer* info, int flags): pass # This neither: def __releasebuffer__(self, Py_buffer* info): pass # Terminate with an error to be sure the compiler is # not terminating prior to previous errors def terminate(self): pass cdef extern from "foo.h": cdef class pxdimpl.B [object MyB]: def otherfunc(self): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_pyobinstruct.pyx0000644000175100001770000000025400000000000022066 0ustar00runnerdocker00000000000000# mode: error cdef object x cdef struct spam: object parrot def f(): cdef spam s s.parrot = x _ERRORS = u""" 6:8: C struct/union member cannot be a Python object """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_relative_cimport.pyx0000644000175100001770000000066700000000000022701 0ustar00runnerdocker00000000000000# mode: error # tag: cimport from ..relative_cimport cimport some_name from .e_relative_cimport cimport some_name from ..cython cimport declare from . cimport e_relative_cimport _ERRORS=""" 4:0: relative cimport beyond main package is not allowed 5:0: relative cimport from non-package directory is not allowed 6:0: relative cimport beyond main package is not allowed 7:0: relative cimport from non-package directory is not allowed """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_return.pyx0000644000175100001770000000044000000000000020635 0ustar00runnerdocker00000000000000# cython: remove_unreachable=False # mode: error cdef void g(): cdef int i return i # error cdef int h(): cdef int *p return # error return p # error _ERRORS = u""" 6:8: Return with value in void function 10:1: Return value required 11:8: Cannot assign type 'int *' to 'int' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_sizeofincomplete.pyx0000644000175100001770000000021500000000000022675 0ustar00runnerdocker00000000000000# mode: error cdef struct unbekannt cdef int n n = sizeof(unbekannt) _ERRORS = u""" 5:4: Cannot take sizeof incomplete type 'unbekannt' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_slice.pyx0000644000175100001770000000111300000000000020413 0ustar00runnerdocker00000000000000# mode: error def f(obj2): cdef int *ptr1 obj1 = obj2[ptr1::] # error obj1 = obj2[:ptr1:] # error obj1 = obj2[::ptr1] # error cdef int a cdef int* int_ptr for a in int_ptr: pass for a in int_ptr[2:]: pass for a in int_ptr[2:2:a]: pass _ERRORS = u""" 5:16: Cannot convert 'int *' to Python object 6:17: Cannot convert 'int *' to Python object 7:18: Cannot convert 'int *' to Python object 12:9: C array iteration requires known end index 14:16: C array iteration requires known end index 16:21: C array iteration requires known step size and end index """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_strcoerce.pyx0000644000175100001770000000115100000000000021307 0ustar00runnerdocker00000000000000# mode: error cdef int c1 = "t" # works cdef int c2 = "te" # fails cdef int cx = "test" # fails cdef int x1 = "\xFF" # works cdef int x2 = "\u0FFF" # fails cdef Py_UNICODE u1 = u"\xFF" # works cdef int u3 = u"\xFF" # fails _ERRORS = """ 4:14: Only single-character string literals can be coerced into ints. 5:14: Only single-character string literals can be coerced into ints. 8:15: Only single-character string literals can be coerced into ints. 11:14: Unicode literals do not support coercion to C types other than Py_UNICODE/Py_UCS4 (for characters) or Py_UNICODE* (for strings). """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_subop.pyx0000644000175100001770000000036400000000000020453 0ustar00runnerdocker00000000000000# mode: error def f(): cdef int int2 cdef char *ptr1, *ptr2, *ptr3 ptr1 = int2 - ptr3 # error ptr1 = ptr2 - ptr3 # error _ERRORS = u""" 6:13: Invalid operand types for '-' (int; char *) 7:13: Cannot assign type 'ptrdiff_t' to 'char *' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_switch.pyx0000644000175100001770000000027000000000000020620 0ustar00runnerdocker00000000000000# mode: error cdef int x = 3 if x == NONEXISTING: print 2 elif x == 2: print 2342 elif x == 4: print 34 _ERRORS = u""" 5:8: undeclared name not builtin: NONEXISTING """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_switch_transform.pyx0000644000175100001770000000032400000000000022713 0ustar00runnerdocker00000000000000# cython: optimize.use_switch=True # mode: error # tag: cerror import cython cdef extern from *: enum: ONE "1" ONE_AGAIN "1+0" def is_not_one(int i): return i != ONE and i != ONE_AGAIN ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_tempcast.pyx0000644000175100001770000000043400000000000021141 0ustar00runnerdocker00000000000000# mode: error cdef object blarg def foo(obj): cdef void *p p = blarg # ok p = (obj + blarg) # error - temporary _ERRORS = u""" 8:5: Casting temporary Python object to non-numeric non-Python type 8:5: Storing unsafe C derivative of temporary Python reference """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_tuple_args_T692.py0000644000175100001770000000027200000000000022022 0ustar00runnerdocker00000000000000# ticket: t692 # mode: error def func((a, b)): return a + b _ERRORS = u""" 4:9: Missing argument name 5:11: undeclared name not builtin: a 5:15: undeclared name not builtin: b """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_typing_errors.pyx0000644000175100001770000000257300000000000022235 0ustar00runnerdocker00000000000000# mode: error import cython try: from typing import Optional, ClassVar except ImportError: pass # not OK def optional_cython_types(Optional[cython.int] i, Optional[cython.double] d, Optional[cython.float] f, Optional[cython.complex] c, Optional[cython.long] l, Optional[cython.longlong] ll): pass MyStruct = cython.struct(a=cython.int, b=cython.double) def optional_cstruct(Optional[MyStruct] x): pass def optional_pytypes(Optional[int] i, Optional[float] f, Optional[complex] c, Optional[long] l): pass cdef ClassVar[list] x # OK def optional_memoryview(double[:] d, Optional[double[:]] o): pass cdef class Cls(object): cdef ClassVar[list] x _ERRORS = """ 13:42: typing.Optional[...] cannot be applied to type int 13:66: typing.Optional[...] cannot be applied to type double 13:93: typing.Optional[...] cannot be applied to type float 14:42: typing.Optional[...] cannot be applied to type double complex 14:70: typing.Optional[...] cannot be applied to type long 14:95: typing.Optional[...] cannot be applied to type long long 24:30: typing.Optional[...] cannot be applied to type int 24:47: typing.Optional[...] cannot be applied to type float 24:87: typing.Optional[...] cannot be applied to type long 20:30: typing.Optional[...] cannot be applied to type MyStruct 28:20: Modifier 'typing.ClassVar' is not allowed here. """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_typing_optional.py0000644000175100001770000000211100000000000022342 0ustar00runnerdocker00000000000000# mode: error import cython try: from typing import Optional except ImportError: pass # not OK def optional_cython_types(i: Optional[cython.int], d: Optional[cython.double], f: Optional[cython.float], c: Optional[cython.complex], l: Optional[cython.long], ll: Optional[cython.longlong]): pass MyStruct = cython.struct(a=cython.int, b=cython.double) def optional_cstruct(x: Optional[MyStruct]): pass # OK def optional_pytypes(i: Optional[int], f: Optional[float], c: Optional[complex], l: Optional[long]): pass def optional_memoryview(d: double[:], o: Optional[double[:]]): pass _ERRORS = """ 13:44: typing.Optional[...] cannot be applied to type int 13:69: typing.Optional[...] cannot be applied to type double 13:97: typing.Optional[...] cannot be applied to type float 14:44: typing.Optional[...] cannot be applied to type double complex 14:73: typing.Optional[...] cannot be applied to type long 14:100: typing.Optional[...] cannot be applied to type long long 20:33: typing.Optional[...] cannot be applied to type MyStruct """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_undefexttype.pyx0000644000175100001770000000026200000000000022044 0ustar00runnerdocker00000000000000# mode: error cdef class Spam cdef extern class external.Eggs _ERRORS = u""" 3:5: C class 'Spam' is declared but not defined 4:5: C class 'Eggs' is declared but not defined """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_unop.pyx0000644000175100001770000000031500000000000020300 0ustar00runnerdocker00000000000000# mode: error def f(): cdef int int1 cdef char *str2 int1 = -str2 # error int1 = ~str2 # error _ERRORS = u""" 6:8: Invalid operand type for '-' (char *) 7:8: Invalid operand type for '~' (char *) """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/e_while.pyx0000644000175100001770000000031400000000000020426 0ustar00runnerdocker00000000000000# cython: remove_unreachable=False # mode: error def f(a, b): cdef int i break # error continue # error _ERRORS = u""" 6:1: break statement not inside loop 7:1: continue statement not inside loop """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/empty.pyx0000644000175100001770000000005300000000000020150 0ustar00runnerdocker00000000000000# cython: autotestdict=False # mode: error ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/encoding.pyx0000644000175100001770000000033000000000000020576 0ustar00runnerdocker00000000000000# coding=ASCII # mode: error """ Trs bien. """ _ERRORS = u""" 5:3: Decoding error, missing or incorrect coding= at top of source (cannot decode with encoding 'ascii': ordinal not in range(128)) """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/exec_errors.pyx0000644000175100001770000000215400000000000021336 0ustar00runnerdocker00000000000000# mode: error # tag: exec def test_exec_tuples(): exec() exec(1,) exec(1,2,3,4) def test_exec_tuples_with_in(d1, d2): exec(1,2) in d1 exec(1,2,3) in d1 exec(1,2) in d1, d2 exec(1,2,3) in d1, d2 exec() in d1, d2 exec(1,) in d1, d2 exec(1,2,3,4) in d1, d2 _ERRORS = """ 5:4: expected tuple of length 2 or 3, got length 0 6:4: expected tuple of length 2 or 3, got length 1 7:4: expected tuple of length 2 or 3, got length 4 10:14: tuple variant of exec does not support additional 'in' arguments 11:16: tuple variant of exec does not support additional 'in' arguments 12:14: tuple variant of exec does not support additional 'in' arguments 13:16: tuple variant of exec does not support additional 'in' arguments 14:4: expected tuple of length 2 or 3, got length 0 14:11: tuple variant of exec does not support additional 'in' arguments 15:4: expected tuple of length 2 or 3, got length 1 15:13: tuple variant of exec does not support additional 'in' arguments 16:4: expected tuple of length 2 or 3, got length 4 16:18: tuple variant of exec does not support additional 'in' arguments """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/extclassattrsetting.pyx0000644000175100001770000000051600000000000023135 0ustar00runnerdocker00000000000000# mode: error __doc__ = u""" >>> e = ExtClass() >>> e.get() 5 """ cdef class ExtClass: cdef int _attribute = 2 def get(self): return self._attribute _attribute = 5 # FIXME: this is not currently handled!!! _ERRORS = u""" 10:13: Cannot assign default value to fields in cdef classes, structs or unions """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/extended_unpacking.pyx0000644000175100001770000000154000000000000022653 0ustar00runnerdocker00000000000000# mode: error # invalid syntax (not handled by the parser) def syntax1(): a = b = c = d = e = f = g = h = i = 1 # prevent undefined names *a *1 *"abc" *a*b [*a, *b] (a, b, *c, d, e, f, *g, h, i) [a, b, *c, d, e, f, *g, h, i] {a, b, *c, d, e, f, *g, h, i} def syntax2(): list_of_sequences = [[1,2], [3,4]] for *a,*b in list_of_sequences: pass def types(l): cdef int a,b a, *b = (1,2,3,4) a, *b = l _ERRORS = u""" # syntax1() 8: 4: starred expression is not allowed here 10: 4: starred expression is not allowed here 12: 4: starred expression is not allowed here 14: 4: starred expression is not allowed here # syntax2() 26:11: more than 1 starred expression in assignment # types() 32:15: Cannot coerce list to type 'int' 33:8: starred target must have Python object (list) type """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/extended_unpacking_notuple.pyx0000644000175100001770000000040500000000000024420 0ustar00runnerdocker00000000000000# mode: error # very common mistake for new users (handled early by the parser) def no_tuple_assignment(): *a = [1] _ERRORS = u""" 6:4: a starred assignment target must be in a list or tuple - maybe you meant to use an index assignment: var[0] = ... """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/extended_unpacking_parser.pyx0000644000175100001770000000112400000000000024225 0ustar00runnerdocker00000000000000# mode: error # wrong size RHS (as handled by the parser) def length1(): a, b = [1,2,3] def length2(): a, b = [1] def length3(): a, b = [] def length4(): a, *b = [] def length5(): a, *b, c = [] a, *b, c = [1] def length_recursive(): *(a, b), c = (1,2) _ERRORS = u""" 6:4: too many values to unpack (expected 2, got 3) 9:4: need more than 1 value to unpack 12:4: need more than 0 values to unpack 15:4: need more than 0 values to unpack 18:4: need more than 0 values to unpack 19:4: need more than 1 value to unpack 22:6: need more than 1 value to unpack """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/extended_unpacking_parser2.pyx0000644000175100001770000000033200000000000024307 0ustar00runnerdocker00000000000000# mode: error # invalid syntax (as handled by the parser) def syntax(): *a, *b = 1,2,3,4,5 _ERRORS = u""" 6:4: more than 1 starred expression in assignment 6:8: more than 1 starred expression in assignment """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/final_methods.pyx0000644000175100001770000000057300000000000021635 0ustar00runnerdocker00000000000000# mode: error cimport cython cdef class BaseClass: @cython.final cdef cdef_method(self): pass @cython.final cpdef cpdef_method(self): pass cdef class SubType(BaseClass): cdef cdef_method(self): pass _ERRORS = """ 11:10: Only final types can have final Python (def/cpdef) methods 16:9: Overriding final methods is not allowed """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/fused_syntax.pyx0000644000175100001770000000016500000000000021532 0ustar00runnerdocker00000000000000# mode: error cdef fused my_fused_type: int a; char b _ERRORS = u""" fused_syntax.pyx:3:26: Expected a newline """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/fused_syntax_ctypedef.pyx0000644000175100001770000000024500000000000023414 0ustar00runnerdocker00000000000000# mode: error cimport cython ctypedef cython.fused_type(int, float) fused_t _ERRORS = u""" fused_syntax_ctypedef.pyx:5:39: Syntax error in ctypedef statement """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/fused_types.pyx0000644000175100001770000000642700000000000021357 0ustar00runnerdocker00000000000000# mode: error # ticket: 1772 cimport cython from cython import fused_type # This is all invalid # ctypedef foo(int) dtype1 # ctypedef foo.bar(float) dtype2 # ctypedef fused_type(foo) dtype3 dtype4 = cython.fused_type(int, long, kw=None) # ctypedef public cython.fused_type(int, long) dtype7 # ctypedef api cython.fused_type(int, long) dtype8 int_t = cython.fused_type(short, short, int) int2_t = cython.fused_type(int, long) dtype9 = cython.fused_type(int2_t, int) floating = cython.fused_type(float, double) cdef func(floating x, int2_t y): print x, y cdef float x = 10.0 cdef int y = 10 func[float](x, y) func[float][int](x, y) func[float, int](x) func[float, int](x, y, y) func(x, y=y) ctypedef fused memslice_dtype_t: cython.p_int # invalid dtype cython.long def f(memslice_dtype_t[:, :] a): pass lambda cython.integral i: i cdef cython.floating x cdef class Foo(object): cdef cython.floating attr def outer(cython.floating f): def inner(): cdef cython.floating g # Mixing const and non-const type makes fused type ambiguous cdef fused mix_const_t: int const int cdef cdef_func_with_mix_const_type(mix_const_t val): print(val) cdef_func_with_mix_const_type(1) # This is all valid dtype5 = fused_type(int, long, float) dtype6 = cython.fused_type(int, long) func[float, int](x, y) cdef fused fused1: int long long ctypedef fused fused2: int long long func(x, y) cdef floating return_type_unfindable1(cython.integral x): return 1.0 cpdef floating return_type_unfindable2(cython.integral x): return 1.0 cdef void contents_unfindable1(cython.integral x): z: floating = 1 # note: cdef variables also fail with an error but not by the time this test aborts sz = sizeof(floating) _ERRORS = u""" 11:15: fused_type does not take keyword arguments 16:33: Type specified multiple times 27:0: Invalid use of fused types, type cannot be specialized 27:4: Not enough types specified to specialize the function, int2_t is still fused 28:0: Invalid use of fused types, type cannot be specialized 28:4: Not enough types specified to specialize the function, int2_t is still fused 29:16: Call with wrong number of arguments (expected 2, got 1) 30:16: Call with wrong number of arguments (expected 2, got 3) 37:6: Invalid base type for memoryview slice: int * 40:0: Fused lambdas not allowed 43:5: Fused types not allowed here 43:21: cdef variable 'x' declared after it is used 46:9: Fused types not allowed here 61:0: Invalid use of fused types, type cannot be specialized 61:29: ambiguous overloaded method # Possibly duplicates the errors more often than we want 79:5: Return type is a fused type that cannot be determined from the function arguments 82:6: Return type is a fused type that cannot be determined from the function arguments 86:4: 'z' cannot be specialized since its type is not a fused argument to this function 86:4: 'z' cannot be specialized since its type is not a fused argument to this function 86:4: 'z' cannot be specialized since its type is not a fused argument to this function 87:16: Type cannot be specialized since it is not a fused argument to this function 87:16: Type cannot be specialized since it is not a fused argument to this function 87:16: Type cannot be specialized since it is not a fused argument to this function """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/futurebraces.pyx0000644000175100001770000000012400000000000021503 0ustar00runnerdocker00000000000000# mode: error from __future__ import braces _ERRORS = u""" 3:23: not a chance """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/incomplete_varadic.pyx0000644000175100001770000000017000000000000022642 0ustar00runnerdocker00000000000000# mode: error cdef error_time(bool its_fine, .): pass _ERRORS = u""" 3: 31: Expected an identifier, found '.' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3807223 Cython-3.0.8/tests/errors/incorrectly_nested_gil_blocks.pyx0000644000175100001770000000121100000000000025076 0ustar00runnerdocker00000000000000# mode: error with gil: pass with nogil: with nogil: pass cdef void without_gil() nogil: # This is not an error, as 'func' *may* be called without the GIL, but it # may also be held. with nogil: pass cdef void with_gil() with gil: # This is an error, as the GIL is acquired already with gil: pass def func(): with gil: pass _ERRORS = u''' 3:5: Trying to acquire the GIL while it is already held. 7:9: Trying to release the GIL while it was previously released. 18:9: Trying to acquire the GIL while it is already held. 22:9: Trying to acquire the GIL while it is already held. ''' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/invalid_cast.pyx0000644000175100001770000000014400000000000021453 0ustar00runnerdocker00000000000000# mode: error def f(): a = True _ERRORS = u""" 4:9: 'foao' is not a type identifier """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/invalid_hex_escape0.pyx0000644000175100001770000000010400000000000022701 0ustar00runnerdocker00000000000000# mode: error '\x' _ERRORS = ''' 3:1: Invalid hex escape '\x' ''' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/invalid_hex_escape1.pyx0000644000175100001770000000010500000000000022703 0ustar00runnerdocker00000000000000# mode: error '\x1' _ERRORS = ''' 3:1: Invalid hex escape '\x' ''' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/invalid_syntax_py.pyx0000644000175100001770000000146400000000000022565 0ustar00runnerdocker00000000000000# mode: error # tag: syntax def inline func() -> int: pass def api func() -> int: pass def nogil func() -> int: pass def func() nogil: pass def inline int* func(): pass _ERRORS = u""" 4:11: Cannot use cdef modifier 'inline' in Python function signature. Use a decorator instead. 7:8: Cannot use cdef modifier 'api' in Python function signature. Use a decorator instead. 10:10: Cannot use cdef modifier 'nogil' in Python function signature. Use a decorator instead. 13:11: Cannot use cdef modifier 'nogil' in Python function signature. Use a decorator instead. 16:11: Cannot use cdef modifier 'inline' in Python function signature. Use a decorator instead. 16:14: Expected '(', found '*'. Did you use cdef syntax in a Python declaration? Use decorators and Python type annotations instead. """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/invalid_uescape.pyx0000644000175100001770000000011400000000000022143 0ustar00runnerdocker00000000000000# mode: error u'\uXYZ' _ERRORS = ''' 3:2: Invalid unicode escape '\u' ''' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/invalid_uescape0.pyx0000644000175100001770000000011100000000000022220 0ustar00runnerdocker00000000000000# mode: error u'\u' _ERRORS = ''' 3:2: Invalid unicode escape '\u' ''' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/invalid_uescape2.pyx0000644000175100001770000000011300000000000022224 0ustar00runnerdocker00000000000000# mode: error u'\u12' _ERRORS = ''' 3:2: Invalid unicode escape '\u' ''' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/invalid_uescapeN.pyx0000644000175100001770000000014700000000000022267 0ustar00runnerdocker00000000000000# mode: error u'\N{GIBBET NICH}' _ERRORS = ''' 3:2: Unknown Unicode character name 'GIBBET NICH' ''' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/literal_lists.pyx0000644000175100001770000000030600000000000021665 0ustar00runnerdocker00000000000000# mode: error def f(): cdef int* p if false(): p = [1, 2, 3] def false(): return False _ERRORS = u""" 6:8: Literal list must be assigned to pointer at time of declaration """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/missing_baseclass_in_predecl_T262.pyx0000644000175100001770000000033400000000000025406 0ustar00runnerdocker00000000000000# ticket: t262 # mode: error cdef class Album cdef class SessionStruct: cdef Album _create_album(self, void* album, bint take_owner): pass cdef class Album(SessionStruct): pass _ERROR = u""" """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/missing_self_in_cpdef_method_T156.pyx0000644000175100001770000000020000000000000025374 0ustar00runnerdocker00000000000000# ticket: t156 # mode: error cdef class B: cpdef b(): pass _ERRORS = u""" 5:10: C method has no self argument """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/missing_self_in_cpdef_method_T165.pyx0000644000175100001770000000026100000000000025403 0ustar00runnerdocker00000000000000# ticket: t165 # mode: error cdef class A: cpdef a(int not_self): pass _ERRORS = u""" 5:10: Self argument (int) of C method 'a' does not match parent type (A) """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/mod_errors.pyx0000644000175100001770000000022400000000000021165 0ustar00runnerdocker00000000000000# mode: error def mod_complex(): x = (1.1+2.0j) % 4 return x _ERRORS = """ 4:19: mod operator not supported for type 'double complex' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/nogil.pyx0000644000175100001770000001344000000000000020126 0ustar00runnerdocker00000000000000# cython: remove_unreachable=False # mode: error cdef object f(object x) nogil: pass cdef void g(int x) nogil: cdef object z z = None cdef void h(int x) nogil: # allowed p() cdef object p() nogil: pass cdef void r() nogil: # allowed q() # allowed cdef object m(): cdef object x, y = 0, obj cdef int i, j, k global fred q() with nogil: r() # allowed to call plain C functions q() i = 42 # allowed with type inference obj = None 17L # allowed 7j help xxx = `"Hello"` import fred from fred import obj for x in obj: pass obj[i] obj[i:j] obj[i:j:k] obj.fred (x, y) [x, y] {x: y} {x, y} obj and x t(obj) f(42) x + obj -obj x = y = obj x, y = y, x obj[i] = x obj.fred = x print obj # allowed! del fred return obj raise obj # allowed! if obj: pass while obj: pass for x <= obj <= y: pass try: pass except: pass try: pass finally: pass cdef void q(): pass cdef class C: pass cdef void t(C c) nogil: pass def ticket_338(): cdef object obj with nogil: for obj from 0 <= obj < 4: pass def bare_pyvar_name(object x): with nogil: x cdef int fstrings(int x, object obj) except -1 nogil: f"" # allowed f"a" # allowed f"a"f"b" # allowed f"{x}" f"{obj}" cdef void slice_array() nogil: with gil: b = [1, 2, 3, 4] cdef int[4] a = b[:] cdef int[:] main() nogil: cdef int[4] a = [1,2,3,4] return a _ERRORS = u""" 4:5: Function with Python return type cannot be declared nogil 7:5: Function declared nogil has Python locals or temporaries 9:4: Assignment of Python object not allowed without gil 12:5: Discarding owned Python object not allowed without gil 14:5: Function with Python return type cannot be declared nogil 18:5: Calling gil-requiring function not allowed without gil 27:9: Calling gil-requiring function not allowed without gil 29:8: Assignment of Python object not allowed without gil 31:16: Constructing complex number not allowed without gil 33:8: Assignment of Python object not allowed without gil 33:14: Backquote expression not allowed without gil 34:15: Assignment of Python object not allowed without gil 34:15: Python import not allowed without gil 35:13: Python import not allowed without gil 35:25: Constructing Python list not allowed without gil 36:17: Iterating over Python object not allowed without gil 38:11: Discarding owned Python object not allowed without gil 38:11: Indexing Python object not allowed without gil 39:11: Discarding owned Python object not allowed without gil 39:11: Slicing Python object not allowed without gil 40:11: Constructing Python slice object not allowed without gil 40:11: Discarding owned Python object not allowed without gil 40:11: Indexing Python object not allowed without gil 40:12: Converting to Python object not allowed without gil 40:14: Converting to Python object not allowed without gil 40:16: Converting to Python object not allowed without gil 41:11: Accessing Python attribute not allowed without gil 41:11: Discarding owned Python object not allowed without gil 42:9: Constructing Python tuple not allowed without gil 42:9: Discarding owned Python object not allowed without gil 43:8: Constructing Python list not allowed without gil 43:8: Discarding owned Python object not allowed without gil 44:9: Constructing Python dict not allowed without gil 44:9: Discarding owned Python object not allowed without gil 45:9: Constructing Python set not allowed without gil 45:9: Discarding owned Python object not allowed without gil 46:12: Discarding owned Python object not allowed without gil 46:12: Truth-testing Python object not allowed without gil 47:10: Python type test not allowed without gil 48:9: Discarding owned Python object not allowed without gil 49:10: Discarding owned Python object not allowed without gil 49:10: Operation not allowed without gil 50:8: Discarding owned Python object not allowed without gil 50:8: Operation not allowed without gil 51:8: Assignment of Python object not allowed without gil 51:12: Assignment of Python object not allowed without gil 52:8: Assignment of Python object not allowed without gil 52:11: Assignment of Python object not allowed without gil 52:15: Creating temporary Python reference not allowed without gil 52:18: Creating temporary Python reference not allowed without gil 53:11: Assignment of Python object not allowed without gil 53:11: Indexing Python object not allowed without gil 54:11: Accessing Python attribute not allowed without gil 54:11: Assignment of Python object not allowed without gil 56:8: Deleting Python object not allowed without gil 57:8: Returning Python object not allowed without gil 59:11: Truth-testing Python object not allowed without gil 61:14: Truth-testing Python object not allowed without gil 63:8: For-loop using object bounds or target not allowed without gil 63:12: Coercion from Python not allowed without the GIL 63:24: Coercion from Python not allowed without the GIL 65:8: Try-except statement not allowed without gil 86:8: For-loop using object bounds or target not allowed without gil 97:4: Discarding owned Python object not allowed without gil 97:6: String formatting not allowed without gil 98:4: Discarding owned Python object not allowed without gil 98:6: String formatting not allowed without gil 103:21: Coercion from Python not allowed without the GIL 103:21: Slicing Python object not allowed without gil 107:11: Operation not allowed without gil """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/nogil_buffer_acquisition.pyx0000644000175100001770000000033400000000000024065 0ustar00runnerdocker00000000000000# mode: error cimport numpy as np cdef void func(np.ndarray[np.double_t, ndim=1] myarray) nogil: pass _ERRORS = u""" 5:15: Buffer may not be acquired without the GIL. Consider using memoryview slices instead. """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/nogil_conditional.pyx0000644000175100001770000000414100000000000022507 0ustar00runnerdocker00000000000000# cython: remove_unreachable=False # mode: error cdef int f_nogil(int x) nogil: cdef int y y = x + 10 return y def f_gil(x): y = 0 y = x + 100 return y def illegal_gil_usage(): cdef int res = 0 with nogil(True): res = f_gil(res) with nogil(True): res = f_gil(res) with gil(False): res = f_gil(res) with nogil(False): res = f_nogil(res) def foo(a): return a < 10 def non_constant_condition(int x) -> int: cdef int res = x with nogil(x < 10): res = f_nogil(res) with gil(foo(x)): res = f_gil(res) ctypedef fused number_or_object: float object def fused_type(number_or_object x): with nogil(number_or_object is object): res = x + 1 # This should be fine with nogil(number_or_object is float): res = x + 1 return res _ERRORS = u""" 19:14: Accessing Python global or builtin not allowed without gil 19:19: Calling gil-requiring function not allowed without gil 19:19: Coercion from Python not allowed without the GIL 19:19: Constructing Python tuple not allowed without gil 19:20: Converting to Python object not allowed without gil 21:13: Trying to release the GIL while it was previously released. 22:18: Accessing Python global or builtin not allowed without gil 22:23: Calling gil-requiring function not allowed without gil 22:23: Coercion from Python not allowed without the GIL 22:23: Constructing Python tuple not allowed without gil 22:24: Converting to Python object not allowed without gil 25:18: Accessing Python global or builtin not allowed without gil 25:23: Calling gil-requiring function not allowed without gil 25:23: Coercion from Python not allowed without the GIL 25:23: Constructing Python tuple not allowed without gil 25:24: Converting to Python object not allowed without gil 37:17: Non-constant condition in a `with nogil()` statement 40:16: Non-constant condition in a `with gil()` statement 51:8: Assignment of Python object not allowed without gil 51:16: Calling gil-requiring function not allowed without gil """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/nogilcmeth.pxd0000644000175100001770000000005200000000000021115 0ustar00runnerdocker00000000000000cdef class C: cdef void f(self) nogil ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/nogilcmeth.pyx0000644000175100001770000000026000000000000021143 0ustar00runnerdocker00000000000000# mode: error cdef class C: cdef void f(self): pass _ERRORS = u""" 2:15: Previous declaration is here 4:9: Signature not compatible with previous declaration """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/nogilfunctype.pyx0000644000175100001770000000036700000000000021710 0ustar00runnerdocker00000000000000# mode: error cdef extern from *: cdef void f() cdef void (*fp)() nogil cdef void g() nogil cdef void (*gp)() gp = g fp = f _ERRORS = u""" 12:5: Cannot assign type 'void (void) noexcept' to 'void (*)(void) noexcept nogil' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/nonconst_def.pyx0000644000175100001770000000031500000000000021472 0ustar00runnerdocker00000000000000# mode: error import os DEF ospath = os.path _ERRORS = u""" 4:13: Compile-time name 'os' not defined 4:15: Error in compile-time expression: AttributeError: 'NoneType' object has no attribute 'path' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/nonconst_def_tuple.pyx0000644000175100001770000000041700000000000022706 0ustar00runnerdocker00000000000000# mode: error DEF t = (1,2,3) DEF t_const = (1,t,2) DEF t_non_const = (1,[1,2,3],3,t[4]) x = t_non_const _ERRORS = u""" 5:32: Error in compile-time expression: IndexError: tuple index out of range 7:4: Invalid type for compile-time constant: [1, 2, 3] (type list) """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/nonconst_excval.pyx0000644000175100001770000000027400000000000022222 0ustar00runnerdocker00000000000000# mode: error import math cdef double cfunc(double x) except math.nan: return x _ERRORS = """ 5:39: Exception value must be constant 5:39: Not allowed in a constant expression """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/notcimportedT418.pyx0000644000175100001770000000022600000000000022104 0ustar00runnerdocker00000000000000# ticket: t418 # mode: error import somemod.child cdef somemod.child.something x _ERRORS = u""" 6:5: 'somemod.child' is not a cimported module """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/parsed_directive.pyx0000644000175100001770000000067000000000000022333 0ustar00runnerdocker00000000000000# mode: error cimport cython cdef class TestClass: def foo(self): with cython.c_string_encoding("ascii"): return ### FIXME: way to many errors for my taste... _ERRORS = """ 7:13: The c_string_encoding compiler directive is not allowed in with statement scope 7:19: 'c_string_encoding' not a valid cython language construct 7:19: 'c_string_encoding' not a valid cython attribute or is being used incorrectly """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pep448_syntax_1.pyx0000644000175100001770000000017000000000000021664 0ustar00runnerdocker00000000000000# mode: error # tag: pep448 def unpack_mix(): [*1, **1] _ERRORS = """ 5:9: Expected an identifier or literal """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pep448_syntax_2.pyx0000644000175100001770000000017400000000000021671 0ustar00runnerdocker00000000000000# mode: error # tag: pep448 def unpack_wrong_stars(): [**1] _ERRORS = """ 5:5: Expected an identifier or literal """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pep448_syntax_3.pyx0000644000175100001770000000020400000000000021664 0ustar00runnerdocker00000000000000# mode: error # tag: pep448 def unpack_mix_in_set(): {*1, **2} _ERRORS = """ 5:9: unexpected **item found in set literal """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pep487_exttype.pyx0000644000175100001770000000043300000000000021625 0ustar00runnerdocker00000000000000# mode: error cdef class Imp: def __init_subclass__(cls, a=None, **kwargs): super().__init_subclass__(**kwargs) print(a) cdef class ExImp1(Imp): pass class ExImp2(Imp, a=60): pass _ERRORS = u""" 4:4: '__init_subclass__' is not supported by extension class """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pep492_badsyntax_async1.pyx0000644000175100001770000000022300000000000023367 0ustar00runnerdocker00000000000000# mode: error # tag: pep492, async async def foo(): def foo(a=await list()): pass _ERRORS = """ 5:14: 'await' not supported here """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pep492_badsyntax_async4.pyx0000644000175100001770000000023300000000000023373 0ustar00runnerdocker00000000000000# mode: error # tag: pep492, async async def foo(): async def foo(): await list() _ERRORS = """ # ??? - this fails in CPython, not sure why ... """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pep492_badsyntax_async5.pyx0000644000175100001770000000017700000000000023403 0ustar00runnerdocker00000000000000# mode: error # tag: pep492, async def foo(): await list() _ERRORS = """ 5:10: Syntax error in simple statement list """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pep492_badsyntax_async7.pyx0000644000175100001770000000017700000000000023405 0ustar00runnerdocker00000000000000# mode: error # tag: pep492, async async def foo(): yield from [] _ERRORS = """ 5:4: 'yield from' not supported here """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pep492_badsyntax_async8.pyx0000644000175100001770000000020400000000000023375 0ustar00runnerdocker00000000000000# mode: error # tag: pep492, async async def foo(): await await fut _ERRORS = """ 5:10: Expected an identifier or literal """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pep492_badsyntax_async9.pyx0000644000175100001770000000017100000000000023401 0ustar00runnerdocker00000000000000# mode: error # tag: pep492, async async def foo(): await _ERRORS = """ 5:9: Expected an identifier or literal """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/posonly.pyx0000644000175100001770000000342400000000000020522 0ustar00runnerdocker00000000000000# mode: error # tag: posonly def f(a, b = 5, /, c): pass def f(a = 5, b, /, c): pass def f(a = 5, b, /): pass def f(a, /, a): pass def f(a, /, *, a): pass #def f(a, b/2, c): #D # pass #def f(*args, /): #D # pass #def f(*args, a, /): # pass #def f(**kwargs, /): # pass #def f(/, a = 1): # D # pass #def f(/, a): # pass #def f(/): # pass #def f(*, a, /): # pass #def f(*, /, a): # pass #def f(a, /, c, /): # pass #def f(a, /, c, /, d): # pass #def f(a, /, c, /, d, *, e): # pass #def f(a, *, c, /, d, e): # pass def test_invalid_syntax_lambda(self): lambda a, b = 5, /, c: None lambda a = 5, b, /, c: None lambda a = 5, b, /: None lambda a, /, a: None lambda a, /, *, a: None # lambda *args, /: None # lambda *args, a, /: None # lambda **kwargs, /: None # lambda /, a = 1: None # lambda /, a: None # lambda /: None # lambda *, a, /: None # lambda *, /, a: None async def f(a, b = 5, /, c): pass #def test_multiple_seps(a,/,b,/): # pass _ERRORS = u""" 4:19: Non-default argument following default argument 7:13: Non-default argument following default argument 7:19: Non-default argument following default argument 10:13: Non-default argument following default argument 13:6: Previous declaration is here 13:12: 'a' redeclared 16:6: Previous declaration is here 16:15: 'a' redeclared 59:24: Non-default argument following default argument 60:18: Non-default argument following default argument 60:24: Non-default argument following default argument 61:18: Non-default argument following default argument 62:11: Previous declaration is here 62:17: 'a' redeclared 63:11: Previous declaration is here 63:20: 'a' redeclared 73:25: Non-default argument following default argument """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/posonly2.pyx0000644000175100001770000000020100000000000020572 0ustar00runnerdocker00000000000000# mode: error # tag: posonly def f(a, b/2, c): pass _ERRORS = u""" 4:11: Syntax error in Python function argument list """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/posonly3.pyx0000644000175100001770000000021100000000000020574 0ustar00runnerdocker00000000000000# mode: error # tag: posonly def f(*args, /): pass def f(*args, a, /): pass _ERRORS = u""" 4:13: Expected ')', found '/' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/posonly4.pyx0000644000175100001770000000024600000000000020605 0ustar00runnerdocker00000000000000# mode: error # tag: posonly def f(/, a = 1): pass _ERRORS = u""" 4:6: Got zero positional-only arguments despite presence of positional-only specifier '/' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/posonly5.pyx0000644000175100001770000000017400000000000020606 0ustar00runnerdocker00000000000000# mode: error # tag: posonly def test_multiple_seps(a,/,b,/): pass _ERRORS = u""" 4:29: Expected ')', found '/' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pure_cclass_without_body.pxd0000644000175100001770000000003700000000000024072 0ustar00runnerdocker00000000000000# mode: error cdef class Test ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pure_cclass_without_body.py0000644000175100001770000000016000000000000023724 0ustar00runnerdocker00000000000000# mode: error class Test(object): pass _ERRORS = u""" 3:5: C class 'Test' is declared but not defined """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pure_errors.py0000644000175100001770000000356500000000000021204 0ustar00runnerdocker00000000000000# mode: error # tag: warnings import cython @cython.cfunc @cython.locals(x=cython.int) @cython.returns(cython.int) def cdef_needs_gil(x): return x + 1 @cython.cfunc @cython.nogil @cython.locals(x=cython.int) @cython.returns(cython.int) def cdef_nogil(x): return x + 1 @cython.cfunc @cython.nogil(True) @cython.locals(x=cython.int) @cython.returns(cython.int) def cdef_nogil_true(x): return x + 1 @cython.cfunc @cython.nogil(False) @cython.locals(x=cython.int) @cython.returns(cython.int) def cdef_nogil_false(x): return x + 1 @cython.locals(x=cython.int) def test_cdef_nogil(x): cdef_nogil(x) # ok cdef_nogil_false(x) # ok cdef_nogil_true(x) # ok with cython.nogil: cdef_nogil_true(x) # ok cdef_needs_gil(x) # not ok cdef_nogil_false(x) # not ok @cython.nogil def pyfunc(x): # invalid return x + 1 @cython.exceptval(-1) @cython.cfunc def test_cdef_return_object_broken(x: object) -> object: return x @cython.ccall @cython.cfunc def test_contradicting_decorators1(x: object) -> object: return x @cython.cfunc @cython.ccall def test_contradicting_decorators2(x: object) -> object: return x @cython.cfunc @cython.ufunc def add_one(x: cython.double) -> cython.double: return x+1 _ERRORS = """ 44:22: Calling gil-requiring function not allowed without gil 45:24: Calling gil-requiring function not allowed without gil 48:0: Python functions cannot be declared 'nogil' 53:0: Exception clause not allowed for function returning Python object 59:0: cfunc and ccall directives cannot be combined 65:0: cfunc and ccall directives cannot be combined 71:0: Cannot apply @cfunc to @ufunc, please reverse the decorators. """ _WARNINGS = """ 30:0: Directive does not change previous value (nogil=False) # bugs: 59:0: 'test_contradicting_decorators1' redeclared 65:0: 'test_contradicting_decorators2' redeclared """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pure_nogil_conditional.py0000644000175100001770000000450100000000000023352 0ustar00runnerdocker00000000000000# cython: remove_unreachable=False # mode: error import cython @cython.nogil @cython.cfunc def f_nogil(x: cython.int) -> cython.int: y: cython.int y = x + 10 return y def f_gil(x): y = 0 y = x + 100 return y def illegal_gil_usage(): res: cython.int = 0 with cython.nogil(True): res = f_gil(res) with cython.nogil(True): res = f_gil(res) with cython.nogil(False): res = f_nogil(res) def foo(a): return a < 10 def non_constant_condition(x: cython.int) -> cython.int: res: cython.int = x with cython.nogil(x < 10): res = f_nogil(res) number_or_object = cython.fused_type(cython.float, cython.object) def fused_type(x: number_or_object): with cython.nogil(number_or_object is object): res = x + 1 # This should be fine with cython.nogil(number_or_object is cython.float): res = x + 1 return res def nogil_multiple_arguments(x: cython.int) -> cython.int: res: cython.int = x with cython.nogil(1, 2): res = f_nogil(res) def nogil_keyworkd_arguments(x: cython.int) -> cython.int: res: cython.int = x with cython.nogil(kw=2): res = f_nogil(res) @cython.gil(True) @cython.cfunc def wrong_decorator() -> cython.int: return 0 _ERRORS = u""" 22:14: Accessing Python global or builtin not allowed without gil 22:19: Calling gil-requiring function not allowed without gil 22:19: Coercion from Python not allowed without the GIL 22:19: Constructing Python tuple not allowed without gil 22:20: Converting to Python object not allowed without gil 24:13: Trying to release the GIL while it was previously released. 25:18: Accessing Python global or builtin not allowed without gil 25:23: Calling gil-requiring function not allowed without gil 25:23: Coercion from Python not allowed without the GIL 25:23: Constructing Python tuple not allowed without gil 25:24: Converting to Python object not allowed without gil 37:24: Non-constant condition in a `with nogil()` statement 46:8: Assignment of Python object not allowed without gil 46:16: Calling gil-requiring function not allowed without gil 56:9: Compiler directive nogil accepts one positional argument. 61:9: Compiler directive nogil accepts one positional argument. 65:0: The gil compiler directive is not allowed in function scope """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pure_warnings.py0000644000175100001770000000407100000000000021511 0ustar00runnerdocker00000000000000# mode: error # tag: warnings import cython import typing from cython.cimports.libc import stdint def main(): foo1: typing.Tuple = None foo1: typing.Bar = None foo2: Bar = 1 # warning foo3: int = 1 foo4: cython.int = 1 foo5: stdint.bar = 5 # warning foo6: object = 1 foo7: cython.bar = 1 # error foo8: (1 + x).b foo9: mod.a.b foo10: func().b foo11: Bar[:, :, :] # warning foo12: cython.int[:, ::1] with cython.annotation_typing(False): foo8: Bar = 1 foo9: stdint.bar = 5 foo10: cython.bar = 1 @cython.cfunc def bar() -> cython.bar: # error pass @cython.cfunc def bar2() -> Bar: # warning pass @cython.cfunc def bar3() -> stdint.bar: # error pass def bar4(a: cython.foo[:]): # error pass _WARNINGS = """ 12:10: Unknown type declaration 'Bar' in annotation, ignoring 15:16: Unknown type declaration 'stdint.bar' in annotation, ignoring 18:17: Unknown type declaration in annotation, ignoring 19:15: Unknown type declaration in annotation, ignoring 20:17: Unknown type declaration in annotation, ignoring 21:14: Unknown type declaration in annotation, ignoring 35:14: Unknown type declaration 'Bar' in annotation, ignoring 39:20: Unknown type declaration 'stdint.bar' in annotation, ignoring # Spurious warnings from utility code - not part of the core test 25:10: 'cpdef_method' redeclared 36:10: 'cpdef_cname_method' redeclared 961:29: Ambiguous exception value, same as default return value: 0 961:29: Ambiguous exception value, same as default return value: 0 1002:46: Ambiguous exception value, same as default return value: 0 1002:46: Ambiguous exception value, same as default return value: 0 1092:29: Ambiguous exception value, same as default return value: 0 1092:29: Ambiguous exception value, same as default return value: 0 """ _ERRORS = """ 17:16: Unknown type declaration 'cython.bar' in annotation 30:13: Not a type 30:19: Unknown type declaration 'cython.bar' in annotation 35:14: Not a type 39:14: Not a type 42:18: Unknown type declaration 'cython.foo[:]' in annotation """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pxd_cdef_class_declaration_T286.pxd0000644000175100001770000000001500000000000025014 0ustar00runnerdocker00000000000000cdef class A ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pxd_cdef_class_declaration_T286.pyx0000644000175100001770000000016600000000000025050 0ustar00runnerdocker00000000000000# ticket: t286 # mode: error cdef class A: pass _ERRORS = u""" 1:5: C class 'A' is declared but not defined """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pxd_signature_mismatch.pxd0000644000175100001770000000162400000000000023533 0ustar00runnerdocker00000000000000# OK cdef int wider_exception_check(int x, int y) except? 0 cdef int no_exception_raised(int x, int y) except * cdef int any_exception_value1(int x, int y) except * cdef int any_exception_value2(int x, int y) except * cdef int any_exception_value3(int x, int y) except * cdef int any_exception_value4(int x, int y) except * cdef int optimised_exception_value(int x, int y) except? -1 # NOK cdef int wrong_args(int x, long y) cdef long wrong_return_type(int x, int y) cdef int foreign_exception_value(int x, int y) except 0 cdef int narrower_exception_check(int x, int y) except 0 cdef int wrong_exception_value(int x, int y) except 0 cdef int wrong_exception_value_check(int x, int y) except 0 cdef int wrong_exception_value_optimised_check(int x, int y) except? -2 cdef int wrong_exception_value_optimised(int x, int y) except -2 cdef int narrower_exception_check_optimised(int x, int y) except -1 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pxd_signature_mismatch.pyx0000644000175100001770000000330400000000000023555 0ustar00runnerdocker00000000000000# mode: error # tag: pxd # OK cdef int wider_exception_check(int x, int y) except 0: return 2 cdef int no_exception_raised(int x, int y): return 2 cdef int any_exception_value1(int x, int y) except *: return 2 cdef int any_exception_value2(int x, int y) except -1: return 2 cdef int any_exception_value3(int x, int y) except -2: return 2 cdef int any_exception_value4(int x, int y) except? -2: return 2 cdef int optimised_exception_value(int x, int y) except *: # => except? -1 return 2 # NOK cdef int wrong_args(int x, int y): return 2 cdef int wrong_return_type(int x, int y): return 2 cdef int foreign_exception_value(int x, int y): return 2 cdef int narrower_exception_check(int x, int y) except? 0: return 2 cdef int wrong_exception_value(int x, int y) except 1: return 2 cdef int wrong_exception_value_check(int x, int y) except? 1: return 2 cdef int wrong_exception_value_optimised_check(int x, int y) except *: return 2 cdef int wrong_exception_value_optimised(int x, int y) except *: return 2 cdef int narrower_exception_check_optimised(int x, int y) except *: return 2 _ERRORS = """ 30:5: Function signature does not match previous declaration 33:5: Function signature does not match previous declaration 36:5: Function signature does not match previous declaration 39:5: Function signature does not match previous declaration 42:5: Function signature does not match previous declaration 45:5: Function signature does not match previous declaration 48:5: Function signature does not match previous declaration 51:5: Function signature does not match previous declaration 54:5: Function signature does not match previous declaration """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/py_ucs4_type_errors.pyx0000644000175100001770000000137400000000000023044 0ustar00runnerdocker00000000000000# mode: error # -*- coding: iso-8859-1 -*- cdef Py_UCS4 char_ASCII = u'A' cdef Py_UCS4 char_KLINGON = u'\uF8D2' def char_too_long_ASCII(): cdef Py_UCS4 c = u'AB' def char_too_long_Unicode(): cdef Py_UCS4 c = u'A\uF8D2' def char_too_long_bytes(): cdef Py_UCS4 c = b'AB' def char_too_long_latin1(): cdef Py_UCS4 char_bytes_latin1 = b'\xf6' _ERRORS = """ 8:21: Only single-character Unicode string literals or surrogate pairs can be coerced into Py_UCS4/Py_UNICODE. 11:21: Only single-character Unicode string literals or surrogate pairs can be coerced into Py_UCS4/Py_UNICODE. 14:21: Only single-character string literals can be coerced into ints. 17:37: Bytes literals cannot coerce to Py_UNICODE/Py_UCS4, use a unicode literal instead. """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/py_unicode_type_errors.pyx0000644000175100001770000000141600000000000023611 0ustar00runnerdocker00000000000000# mode: error # -*- coding: iso-8859-1 -*- cdef Py_UNICODE char_ASCII = u'A' cdef Py_UNICODE char_KLINGON = u'\uF8D2' def char_too_long_ASCII(): cdef Py_UNICODE c = u'AB' def char_too_long_Unicode(): cdef Py_UNICODE c = u'A\uF8D2' def char_too_long_bytes(): cdef Py_UNICODE c = b'AB' def char_too_long_latin1(): cdef Py_UNICODE char_bytes_latin1 = b'\xf6' _ERRORS = """ 8:24: Only single-character Unicode string literals or surrogate pairs can be coerced into Py_UCS4/Py_UNICODE. 11:24: Only single-character Unicode string literals or surrogate pairs can be coerced into Py_UCS4/Py_UNICODE. 14:24: Only single-character string literals can be coerced into ints. 17:40: Bytes literals cannot coerce to Py_UNICODE/Py_UCS4, use a unicode literal instead. """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/pyobjcastdisallow_T313.pyx0000644000175100001770000000027700000000000023271 0ustar00runnerdocker00000000000000# ticket: t313 # mode: error a = 3 cdef void* allowed = a cdef double* disallowed = a _ERRORS = u""" 7:26: Python objects cannot be cast to pointers of primitive types """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/redeclaration_of_var_by_cfunc_T600.pyx0000644000175100001770000000031100000000000025540 0ustar00runnerdocker00000000000000# ticket: 600 # mode: error cdef class Bar: cdef list _operands cdef int _operands(self): return -1 _ERRORS = """ 7:9: '_operands' redeclared 5:14: Previous declaration is here """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/return_outside_function_T135.pyx0000644000175100001770000000134100000000000024507 0ustar00runnerdocker00000000000000# cython: remove_unreachable=False # ticket: t135 # mode: error def _runtime_True(): return True return 'bar' class A: return None cdef class B: return None try: return None except: pass try: return None finally: pass for i in (1,2): return None while True: return None if _runtime_True(): return None else: return None _ERRORS = u''' 8:0: Return not inside a function body 11:4: Return not inside a function body 14:4: Return not inside a function body 16:5: Return not inside a function body 19:5: Return not inside a function body 23:4: Return not inside a function body 26:4: Return not inside a function body 29:4: Return not inside a function body 31:4: Return not inside a function body ''' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/reversed_literal_pyobjs.pyx0000644000175100001770000000124600000000000023740 0ustar00runnerdocker00000000000000# mode: error # tag: reversed cdef int i, j for i in reversed(range([], j, 2)): pass for i in reversed(range([], j, -2)): pass for i in reversed(range(j, [], 2)): pass for i in reversed(range(j, [], -2)): pass # code below is no longer a compile-time error (although won't run without an exception) for i in reversed(range({}, j, 2)): pass for i in reversed(range({}, j, -2)): pass for i in reversed(range(j, {}, 2)): pass for i in reversed(range(j, {}, -2)): pass _ERRORS = """ 5:24: Cannot coerce list to type 'long' 7:24: Cannot coerce list to type 'long' 9:27: Cannot coerce list to type 'long' 11:27: Cannot coerce list to type 'long' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/se_badindent.pyx0000644000175100001770000000016700000000000021437 0ustar00runnerdocker00000000000000# mode: error def f(): a = b # space space c = d # space tab _ERRORS = u""" 5:0: Mixed use of tabs and spaces """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/se_badindent2.pyx0000644000175100001770000000021000000000000021506 0ustar00runnerdocker00000000000000# mode: error def f(): a = b c = d _ERRORS = u""" 5:0: Possible inconsistent indentation 5:0: Expected an identifier or literal """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/se_mixtabspace.pyx0000644000175100001770000000015700000000000022006 0ustar00runnerdocker00000000000000# mode: error def f(): a = b # space space c = d # tab _ERRORS = u""" 5:0: Mixed use of tabs and spaces """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/se_multass.pyx0000644000175100001770000000030400000000000021170 0ustar00runnerdocker00000000000000# mode: error def f(obj1a, obj2a, obj3a, obj1b, obj2b, obj3b, obj4b): obj1a, (obj2a, obj3a) = obj1b, (obj2b, obj3b, obj4b) _ERRORS = u""" 4:9: too many values to unpack (expected 2, got 3) """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/string_assignments.pyx0000644000175100001770000000702300000000000022737 0ustar00runnerdocker00000000000000# mode: error # coding: ASCII # tag: py_unicode_strings # ok: cdef char* c1 = "abc" cdef str s1 = "abc" cdef unicode u1 = u"abc" cdef Py_UNICODE* cu1 = u1 cdef bytes b1 = b"abc" cdef char* c2 = b"abc" cdef bytes b2 = c1 cdef char* c3 = b1 cdef basestring bs1 = "abc" cdef basestring bs2 = u"abc" cdef object o1 = "abc" cdef object o2 = b"abc" cdef object o3 = u"abc" o4 = c1 o5 = b1 o6 = s1 o7 = u1 o8 = cu1 o9 = bs1 u1 = bs1 s1 = bs1 # errors: cdef char* c_f1 = u"abc" cdef char* c_f2 = u1 cdef char* c_f3 = s1 cdef Py_UNICODE* cu_f1 = c1 cdef Py_UNICODE* cu_f2 = b1 cdef Py_UNICODE* cu_f3 = s1 cdef Py_UNICODE* cu_f4 = b"abc" cdef bytes b_f1 = u"abc" cdef bytes b_f2 = u1 cdef bytes b_f3 = s1 cdef bytes b_f4 = bs1 cdef str s_f1 = b"abc" cdef str s_f2 = b1 cdef str s_f3 = u"abc" cdef str s_f4 = u1 cdef unicode u_f1 = "abc" cdef unicode u_f2 = s1 cdef unicode u_f3 = b"abc" cdef unicode u_f4 = b1 cdef unicode u_f5 = c1 cdef basestring bs_f1 = b"abc" cdef basestring bs_f2 = b1 cdef tuple t_f1 = "abc" cdef tuple t_f2 = u"abc" cdef tuple t_f3 = b"abc" cdef list l_f1 = s1 cdef list l_f2 = b1 cdef list l_f3 = u1 print c1 print c1[1:2] print c1 print c1[1:2] _ERRORS = u""" 36:20: Unicode literals do not support coercion to C types other than Py_UNICODE/Py_UCS4 (for characters) or Py_UNICODE* (for strings). 37:20: Unicode objects only support coercion to Py_UNICODE*. 38:20: 'str' objects do not support coercion to C types (use 'bytes'?). 40:25: Cannot assign type 'char *' to 'Py_UNICODE *' 41:25: Cannot convert 'bytes' object to Py_UNICODE*, use 'unicode'. 42:25: 'str' objects do not support coercion to C types (use 'unicode'?). 43:25: Cannot convert 'bytes' object to Py_UNICODE*, use 'unicode'. 45:20: Cannot convert Unicode string to 'bytes' implicitly, encoding required. 46:20: Cannot convert Unicode string to 'bytes' implicitly, encoding required. 47:20: Cannot convert 'str' to 'bytes' implicitly. This is not portable. 48:20: Cannot convert 'basestring' object to bytes implicitly. This is not portable. 50:17: Cannot convert 'bytes' object to str implicitly. This is not portable to Py3. 51:17: Cannot convert 'bytes' object to str implicitly. This is not portable to Py3. 52:17: Cannot convert Unicode string to 'str' implicitly. This is not portable and requires explicit encoding. 53:17: Cannot convert Unicode string to 'str' implicitly. This is not portable and requires explicit encoding. 55:20: str objects do not support coercion to unicode, use a unicode string literal instead (u'') 56:20: str objects do not support coercion to unicode, use a unicode string literal instead (u'') 57:20: Cannot convert 'bytes' object to unicode implicitly, decoding required 58:20: Cannot convert 'bytes' object to unicode implicitly, decoding required 59:20: Cannot convert 'char*' to unicode implicitly, decoding required 61:24: Cannot convert 'bytes' object to basestring implicitly. This is not portable to Py3. 62:24: Cannot convert 'bytes' object to basestring implicitly. This is not portable to Py3. 64:19: Cannot assign type 'str object' to 'tuple object' 65:18: Cannot assign type 'unicode object' to 'tuple object' 66:18: Cannot assign type 'bytes object' to 'tuple object' 72:11: default encoding required for conversion from 'char *' to 'str object' 73:13: default encoding required for conversion from 'char *' to 'str object' 74:15: Cannot convert 'char*' to unicode implicitly, decoding required 75:17: default encoding required for conversion from 'char *' to 'unicode object' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/subtyping_final_class.pyx0000644000175100001770000000030300000000000023372 0ustar00runnerdocker00000000000000# mode: error cimport cython @cython.final cdef class FinalClass: pass cdef class SubType(FinalClass): pass _ERRORS = """ 9:19: Base class 'FinalClass' of type 'SubType' is final """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/syntax_warnings.pyx0000644000175100001770000000032600000000000022253 0ustar00runnerdocker00000000000000# mode: error # tag: werror cdef useless_semicolon(): cdef int i; pass; ctypedef int x; _ERRORS=""" 5:14: useless trailing semicolon 6:8: useless trailing semicolon 8:14: useless trailing semicolon """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/tree_assert.pyx0000644000175100001770000000106400000000000021335 0ustar00runnerdocker00000000000000# mode: error cimport cython @cython.test_fail_if_path_exists("//SimpleCallNode", "//NameNode") @cython.test_assert_path_exists("//ComprehensionNode", "//ComprehensionNode//FuncDefNode") def test(): object() _ERRORS = u""" 5:0: Expected path '//ComprehensionNode' not found in result tree 5:0: Expected path '//ComprehensionNode//FuncDefNode' not found in result tree 10:4: Unexpected path '//NameNode' found in result tree 10:10: Unexpected path '//SimpleCallNode' found in result tree """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/typoT304.pyx0000644000175100001770000000024000000000000020356 0ustar00runnerdocker00000000000000# ticket: t304 # mode: error def f(): print assert sizeof(int) == sizof(short) == sizeof(long) _ERRORS = u""" 5:10: Expected an identifier or literal """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/undefinedname.pyx0000644000175100001770000000041100000000000021612 0ustar00runnerdocker00000000000000# mode: error i = _this_global_name_does_not_exist_ def test(i): return _this_local_name_does_not_exist_ _ERRORS = u""" 3:4:undeclared name not builtin: _this_global_name_does_not_exist_ 6:11:undeclared name not builtin: _this_local_name_does_not_exist_ """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/unicode_identifiers_e1.pyx0000644000175100001770000000016700000000000023420 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*- # mode: error ★1 = 5 # invalid start symbol _ERRORS = u""" 4:0: Unrecognized character """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/unicode_identifiers_e2.pyx0000644000175100001770000000021500000000000023413 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*- # mode: error class MyClass₡: # invalid continue symbol pass _ERRORS = u""" 4:13: Unrecognized character """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/unicode_identifiers_e3.pyx0000644000175100001770000000034500000000000023420 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*- # mode: error def f(): a = 1 ́b = 2 # looks like an indentation error but is actually a combining accent as the first letter of column 4 c = 3 _ERRORS = u""" 6:4: Unrecognized character """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/unicode_identifiers_e4.pyx0000644000175100001770000000047400000000000023424 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*- # mode: error cdef class C: # these two symbols "\u1e69" and "\u1e9b\u0323" normalize to the same thing # so the two attributes can't coexist cdef int ṩomething cdef double ẛ̣omething _ERRORS = u""" 7:13: Previous declaration is here 8:16: 'ṩomething' redeclared """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/uninitialized_lhs.pyx0000644000175100001770000000050200000000000022527 0ustar00runnerdocker00000000000000# cython: warn.maybe_uninitialized=True # mode: error # tag: werror # ticket: t739 def index_lhs(a): cdef object idx a[idx] = 1 def slice_lhs(a): cdef object idx a[:idx] = 1 _ERRORS = """ 8:6: local variable 'idx' referenced before assignment 12:7: local variable 'idx' referenced before assignment """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/void_as_arg.pyx0000644000175100001770000000023200000000000021266 0ustar00runnerdocker00000000000000# mode: error cdef extern from *: void foo(void) _ERRORS = u""" 4:13:Use spam() rather than spam(void) to declare a function with no arguments. """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_cdef_override.pyx0000644000175100001770000000023600000000000022143 0ustar00runnerdocker00000000000000# mode: error # tag: werror cdef foo(): pass def foo(): pass _ERRORS = u""" 7:0: 'foo' redeclared 7:0: Overriding cdef method with def method. """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_numpy_arr_as_cppvec_ref.pyx0000644000175100001770000000201700000000000024235 0ustar00runnerdocker00000000000000# mode: error # tag: cpp, werror, numpy, no-cpp-locals import numpy as np cimport numpy as np from libcpp.vector cimport vector np.import_array() cdef extern from *: void cpp_function_vector1(vector[int]) void cpp_function_vector2(vector[int] &) void cpp_function_2_vec_refs(vector[int] &, vector[int] &) def main(): cdef np.ndarray[int, ndim=1, mode="c"] arr = np.zeros(10, dtype='intc') cpp_function_vector1(arr) cpp_function_vector2(arr) cpp_function_vector2(arr) cpp_function_2_vec_refs(arr, arr) cdef vector[int] vec vec.push_back(0) cpp_function_vector2(vec) _ERRORS = """ 19:25: Cannot pass Python object as C++ data structure reference (vector[int] &), will pass by copy. 20:25: Cannot pass Python object as C++ data structure reference (vector[int] &), will pass by copy. 21:28: Cannot pass Python object as C++ data structure reference (vector[int] &), will pass by copy. 21:33: Cannot pass Python object as C++ data structure reference (vector[int] &), will pass by copy. """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_python_list_as_cppset_ref.pyx0000644000175100001770000000066300000000000024620 0ustar00runnerdocker00000000000000# mode: error # tag: cpp, werror from libcpp.set cimport set cdef extern from *: void cpp_function_set1(set[int] arg) void cpp_function_set2(set[int]& arg) def pass_py_obj_as_cpp_cont_ref(): cdef list ordered_set = [0, 0, 0, 0, 0] cpp_function_set1(ordered_set) cpp_function_set2(ordered_set) _ERRORS = """ 14:22: Cannot pass Python object as C++ data structure reference (set[int] &), will pass by copy. """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_undeclared.pyx0000644000175100001770000000053000000000000021446 0ustar00runnerdocker00000000000000# cython: warn.undeclared=True # mode: error # tag: werror def foo(): a = 1 return a cdef class Bar: cdef int baz(self, a): res = 0 for i in range(3): res += i return res _ERRORS = """ 6:4: implicit declaration of 'a' 11:8: implicit declaration of 'res' 12:12: implicit declaration of 'i' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_uninitialized.pyx0000644000175100001770000000535300000000000022220 0ustar00runnerdocker00000000000000# cython: warn.maybe_uninitialized=True # mode: error # tag: werror def simple(): print a a = 0 def simple2(arg): if arg > 0: a = 1 return a def simple_pos(arg): if arg > 0: a = 1 else: a = 0 return a def ifelif(c1, c2): if c1 == 1: if c2: a = 1 else: a = 2 elif c1 == 2: a = 3 return a def nowimpossible(a): if a: b = 1 if a: print b def fromclosure(): def bar(): print a a = 1 return bar # Should work ok in both py2 and py3 def list_comp(a): return [i for i in a] def set_comp(a): return set(i for i in a) def dict_comp(a): return {i: j for i, j in a} # args and kwargs def generic_args_call(*args, **kwargs): return args, kwargs def cascaded(x): print a, b a = b = x def from_import(): print bar from foo import bar def regular_import(): print foo import foo def raise_stat(): try: raise exc, msg except: pass exc = ValueError msg = 'dummy' def defnode_decorator(): @decorator def foo(): pass def decorator(): pass def defnode_default(): def foo(arg=default()): pass def default(): pass def class_bases(): class foo(bar): pass class bar(object): pass def class_decorators(): @decorator class foo(object): pass def decorator(cls): return cls def class_py3k_metaclass(): class foo(metaclass=Meta): pass class Meta(object): pass def class_py3k_args(): class foo(*args, **kwargs): pass args = [] kwargs = {} def uninitialized_in_sizeof(): cdef int i print sizeof(i) _ERRORS = """ 6:10: local variable 'a' referenced before assignment 12:11: local variable 'a' might be referenced before assignment 29:11: local variable 'a' might be referenced before assignment 35:14: local variable 'b' might be referenced before assignment 58:10: local variable 'a' referenced before assignment 58:13: local variable 'b' referenced before assignment 62:10: local variable 'bar' referenced before assignment 66:10: local variable 'foo' referenced before assignment 71:14: local variable 'exc' referenced before assignment 71:19: local variable 'msg' referenced before assignment 78:5: local variable 'decorator' referenced before assignment 85:16: local variable 'default' referenced before assignment 91:14: local variable 'bar' referenced before assignment 97:5: local variable 'decorator' referenced before assignment 104:24: local variable 'Meta' referenced before assignment 110:15: local variable 'args' referenced before assignment 110:23: local variable 'kwargs' referenced before assignment """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_uninitialized_cpp.pyx0000644000175100001770000000032000000000000023047 0ustar00runnerdocker00000000000000# cython: warn.maybe_uninitialized=True # mode: error # tag: cpp, werror from cython.operator import typeid def uninitialized_in_typeid(): cdef int i print typeid(i) == typeid(i) _ERRORS = """ """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_uninitialized_del.pyx0000644000175100001770000000040100000000000023031 0ustar00runnerdocker00000000000000# cython: warn.maybe_uninitialized=True # mode: error # tag: werror def foo(x): a = 1 del a, b b = 2 return a, b _ERRORS = """ 7:11: local variable 'b' referenced before assignment 9:11: local variable 'a' referenced before assignment """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_uninitialized_exc.pyx0000644000175100001770000000434200000000000023054 0ustar00runnerdocker00000000000000# cython: warn.maybe_uninitialized=True # mode: error # tag: werror def exc_target(): try: {}['foo'] except KeyError, e: pass except IndexError, i: pass return e, i def exc_body(): try: a = 1 except Exception: pass return a def exc_else_pos(): try: pass except Exception, e: pass else: e = 1 return e def exc_body_pos(d): try: a = d['foo'] except KeyError: a = None return a def exc_pos(): try: a = 1 except Exception: a = 1 return a def exc_finally(): try: a = 1 finally: pass return a def exc_finally2(): try: pass finally: a = 1 return a def exc_assmt_except(a): try: x = a except: return x def exc_assmt_finaly(a): try: x = a except: return x def raise_stat(a): try: if a < 0: raise IndexError except IndexError: oops = 1 print oops def try_loop(args): try: x = 0 for i in args: if i is 0: continue elif i is None: break elif i is False: return i() except ValueError: x = 1 finally: return x def try_finally(a): try: for i in a: if i > 0: x = 1 finally: return x def try_finally_nested(m): try: try: try: f = m() except: pass finally: pass except: print f _ERRORS = """ 12:11: local variable 'e' might be referenced before assignment 12:14: local variable 'i' might be referenced before assignment 19:11: local variable 'a' might be referenced before assignment 63:15: local variable 'x' might be referenced before assignment 69:15: local variable 'x' might be referenced before assignment 77:10: local variable 'oops' might be referenced before assignment 93:15: local variable 'x' might be referenced before assignment 101:15: local variable 'x' might be referenced before assignment 113:14: local variable 'f' might be referenced before assignment """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_uninitialized_for.pyx0000644000175100001770000000343700000000000023067 0ustar00runnerdocker00000000000000# cython: warn.maybe_uninitialized=True # mode: error # tag: werror def simple_for(n): for i in n: a = 1 return a def simple_for_break(n): for i in n: a = 1 break return a def simple_for_pos(n): for i in n: a = 1 else: a = 0 return a def simple_target(n): for i in n: pass return i def simple_target_f(n): for i in n: i *= i return i def simple_for_from(n): for i from 0 <= i <= n: x = i else: return x def for_continue(l): for i in l: if i > 0: continue x = i print x def for_break(l): for i in l: if i > 0: break x = i print x def for_finally_continue(f): for i in f: try: x = i() finally: print x continue def for_finally_break(f): for i in f: try: x = i() finally: print x break def for_finally_outer(p, f): x = 1 try: for i in f: print x x = i() if x > 0: continue if x < 0: break finally: del x _ERRORS = """ 8:11: local variable 'a' might be referenced before assignment 14:11: local variable 'a' might be referenced before assignment 26:11: local variable 'i' might be referenced before assignment 31:11: local variable 'i' might be referenced before assignment 37:15: local variable 'x' might be referenced before assignment 44:10: local variable 'x' might be referenced before assignment 51:10: local variable 'x' might be referenced before assignment 58:18: local variable 'x' might be referenced before assignment 66:18: local variable 'x' might be referenced before assignment """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_uninitialized_generators.pyx0000644000175100001770000000036100000000000024443 0ustar00runnerdocker00000000000000# cython: warn.maybe_uninitialized=True # mode: error # tag: werror def unbound_inside_generator(*args): for i in args: yield x x = i + i _ERRORS = """ 7:14: local variable 'x' might be referenced before assignment """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_uninitialized_py2.pyx0000644000175100001770000000113100000000000023000 0ustar00runnerdocker00000000000000# cython: language_level=2, warn.maybe_uninitialized=True # mode: error # tag: werror def list_comp(a): r = [i for i in a] return i # dict comp is py3 feuture and don't leak here def dict_comp(a): r = {i: j for i, j in a} return i, j def dict_comp2(a): r = {i: j for i, j in a} print i, j i, j = 0, 0 _ERRORS = """ 7:11: local variable 'i' might be referenced before assignment 12:11: undeclared name not builtin: i 12:14: undeclared name not builtin: j 16:10: local variable 'i' referenced before assignment 16:13: local variable 'j' referenced before assignment """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_uninitialized_py3.pyx0000644000175100001770000000061400000000000023006 0ustar00runnerdocker00000000000000# cython: language_level=3, warn.maybe_uninitialized=True # mode: error # tag: werror def ref(obj): pass def list_comp(a): r = [i for i in a] ref(i) i = 0 return r def dict_comp(a): r = {i: j for i, j in a} ref(i) i = 0 return r _ERRORS = """ 10:8: local variable 'i' referenced before assignment 16:8: local variable 'i' referenced before assignment """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_uninitialized_while.pyx0000644000175100001770000000217400000000000023406 0ustar00runnerdocker00000000000000# cython: warn.maybe_uninitialized=True # mode: error # tag: werror def simple_while(n): while n > 0: n -= 1 a = 0 return a def simple_while_break(n): while n > 0: n -= 1 break else: a = 1 return a def simple_while_pos(n): while n > 0: n -= 1 a = 0 else: a = 1 return a def while_finally_continue(p, f): while p(): try: x = f() finally: print x continue def while_finally_break(p, f): while p(): try: x = f() finally: print x break def while_finally_outer(p, f): x = 1 try: while p(): print x x = f() if x > 0: continue if x < 0: break finally: del x _ERRORS = """ 9:11: local variable 'a' might be referenced before assignment 17:11: local variable 'a' might be referenced before assignment 32:18: local variable 'x' might be referenced before assignment 40:18: local variable 'x' might be referenced before assignment """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_uninitialized_with.pyx0000644000175100001770000000103400000000000023243 0ustar00runnerdocker00000000000000# cython: warn.maybe_uninitialized=True # mode: error # tag: werror def with_no_target(m): with m: print a a = 1 def unbound_manager(m1): with m2: pass m2 = m1 def with_target(m): with m as f: print(f) def with_mgr(m): try: with m() as f: pass except: print f _ERRORS = """ 7:14: local variable 'a' referenced before assignment 11:9: local variable 'm2' referenced before assignment 24:14: local variable 'f' might be referenced before assignment """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_unreachable.pyx0000644000175100001770000000115600000000000021616 0ustar00runnerdocker00000000000000# mode: error # tag: werror def simple_return(): return print 'Where am I?' def simple_loops(*args): for i in args: continue print 'Never be here' while True: break print 'Never be here' def conditional(a, b): if a: return 1 elif b: return 2 else: return 3 print 'oops' def try_except(): try: raise TypeError except ValueError: pass else: print 'unreachable' _ERRORS = """ 6:4: Unreachable code 11:8: Unreachable code 15:8: Unreachable code 24:4: Unreachable code 32:8: Unreachable code """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_unreachable_cf.pyx0000644000175100001770000000122200000000000022260 0ustar00runnerdocker00000000000000# mode: error # tag: werror, unreachable, control-flow def try_finally(): try: return finally: return print 'oops' def try_return(): try: return except: return print 'oops' def for_return(a): for i in a: return else: return print 'oops' def while_return(a): while a: return else: return print 'oops' def forfrom_return(a): for i from 0 <= i <= a: return else: return print 'oops' _ERRORS = """ 9:4: Unreachable code 16:4: Unreachable code 23:4: Unreachable code 30:4: Unreachable code 37:4: Unreachable code """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/w_unused.pyx0000644000175100001770000000216000000000000020644 0ustar00runnerdocker00000000000000# cython: warn.unused=True, warn.unused_arg=True, warn.unused_result=True # mode: error # tag: werror def unused_variable(): a = 1 def unused_cascade(arg): a, b = arg.split() return a def unused_arg(arg): pass def unused_result(): r = 1 + 1 r = 2 return r def unused_nested(): def _unused_one(): pass def unused_class(): class Unused: pass # this should not generate warning def used(x, y): x.y = 1 y[0] = 1 lambda x: x def unused_and_unassigned(): cdef object foo cdef int i def unused_generic(*args, **kwargs): pass def unused_in_closure(a,b,c): x = 1 def inner(): nonlocal c c = 1 y = 2 return a+b return inner() _ERRORS = """ 6:4: Unused entry 'a' 9:7: Unused entry 'b' 12:15: Unused argument 'arg' 16:4: Unused result in 'r' 21:4: Unused entry '_unused_one' 25:4: Unused entry 'Unused' 35:16: Unused entry 'foo' 36:13: Unused entry 'i' 38:20: Unused argument 'args' 38:28: Unused argument 'kwargs' 41:26: Unused argument 'c' 41:26: Unused entry 'c' 42:4: Unused entry 'x' 46:8: Unused entry 'y' """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/errors/wraparound_warnings.pyx0000644000175100001770000000406400000000000023112 0ustar00runnerdocker00000000000000# mode: error # tag: werror cimport cython s = "abc" l = [1, 2, 3] def normal_wraparound(int i, bytes B not None, list L not None): a = s[:] a = s[1:2] a = s[-2:-1] a = "abc"[-2:-1] a = "abc"[-2:i] a = B[-2:-1] a = B[:-1] a = B[-2:] b = l[1:2] b = l[:2] b = l[1:] b = l[-2:-1] b = [1, 2, 3][-2:-1] b = [1, 2, 3][-2:i] b = L[-2:-1] @cython.wraparound(False) def no_wraparound(int i, bytes B not None, list L not None): a = s[:] a = s[1:2] a = s[-2:-1] a = "abc"[-2:-1] # evaluated at compile time a = "abc"[-2:i] a = B[:] a = B[-2:-1] a = B[:-1] a = B[-2:] b = l[1:2] b = l[:2] b = l[1:] b = l[-2:-1] b = [1, 2, 3][-2:i] b = L[-2:-1] _ERRORS = """ 31:11: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined 31:14: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined 33:15: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined 35:11: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined 35:14: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined 36:12: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined 37:11: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined 42:11: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined 42:14: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined 43:19: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined 44:11: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined 44:14: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/graal_bugs.txt0000644000175100001770000000037200000000000017607 0ustar00runnerdocker00000000000000# This list is definitely not complete! cythonize_script_package # runs forever, probably multiprocessing issues callingconvention # gets stuck and runs forever different_package_names # gets stuck and runs forever duplicate_utilitycode_from_pyx ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/limited_api_bugs.txt0000644000175100001770000000032700000000000021001 0ustar00runnerdocker00000000000000# This file contains tests corresponding to unresolved bugs using CPython's # Limited API which will be skipped in the normal testing run. convolve2 dict_animal not_none queue3 test_queue memoryview memview buffer ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/macos_cpp_bugs.txt0000644000175100001770000000057200000000000020467 0ustar00runnerdocker00000000000000complex_numbers_T305 complex_numbers_c99_T398 complex_numbers_cpp complex_numbers_cxx_T398 cpdef_extern_func cpp_classes_def cpp_smart_ptr cpp_stl_conversion cpp_stl_function cpp_stl_optional cpp_stl_algo_comparison_ops cpp_stl_algo_permutation_ops cpp_stl_algo_sorted_ranges_set_ops cpp_stl_algo_sorted_ranges_other_ops cpp_stl_bit_cpp20 cpp_stl_cmath_cpp20 cpp_stl_cmath_cpp17././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.132724 Cython-3.0.8/tests/memoryview/0000755000175100001770000000000000000000000017141 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/memoryview/bufaccess.h0000644000175100001770000000016300000000000021250 0ustar00runnerdocker00000000000000/* See bufaccess.pyx */ typedef short td_h_short; typedef double td_h_double; typedef unsigned short td_h_ushort; ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/memoryview/cfunc_convert_with_memoryview.pyx0000644000175100001770000000223200000000000026056 0ustar00runnerdocker00000000000000# mode: run # tag: autowrap # cython: always_allow_keywords=True cdef void memoryview_func_a(double [:] x): x[0] = 1 cdef void memoryview_func_b(double [::1] x): x[0] = 2 cdef void memoryview_func_c(int [:] x): x[0] = 1 cdef void memoryview_func_d(int [:] x): x[0] = 2 cdef void memoryview_func_e(int [:,::1] x): x[0,0] = 4 cdef void memoryview_func_f(int [::1,:] x): x[0,0] = 4 def test_memview_wrapping(): """ We're mainly concerned that the code compiles without the names clashing >>> test_memview_wrapping() 1.0 2.0 1 2 """ cdef a = memoryview_func_a cdef b = memoryview_func_b cdef c = memoryview_func_c cdef d = memoryview_func_d cdef e = memoryview_func_e cdef f = memoryview_func_f cdef double[1] double_arr = [0] cdef int[1] int_arr = [0] a( double_arr) print(double_arr[0]) b( double_arr) print(double_arr[0]) c( int_arr) print(int_arr[0]) d( int_arr) print(int_arr[0]) # don't call e and f because it's harder without needing extra dependencies # it's mostly a compile test for them ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/memoryview/compile_declarations.pyx0000644000175100001770000000441300000000000024065 0ustar00runnerdocker00000000000000# mode: compile cimport cython # from cython.view cimport contig as foo, full as bar #, follow from cython cimport view from cython.view cimport (generic, strided, indirect, contiguous, indirect_contiguous) cdef char[:] one_dim cdef char[:,:,:] three_dim cdef unsigned int[::1, :] view1 cdef unsigned int[:, ::1] view2 cdef long long[::1, :, :, :] fort_contig cdef unsigned long[:, :, :, ::1] c_contig cdef unsigned short int[::1] c_and_fort cdef unsigned long[:, :, :, ::0x0001] c_contig0 cdef int[::generic, ::generic] a1 cdef int[::strided, ::generic] a2 cdef int[::indirect, ::generic] a3 cdef int[::generic, ::strided] a4 cdef int[::strided, ::strided] a5 cdef int[::indirect, ::strided] a6 cdef int[::generic, ::indirect] a7 cdef int[::strided, ::indirect] a8 cdef int[::indirect, ::indirect] a9 cdef int[::generic, ::contiguous] a13 cdef int[::strided, ::contiguous] a14 cdef int[::indirect, ::contiguous] a15 cdef int[::generic, ::indirect_contiguous] a16 cdef int[::strided, ::indirect_contiguous] a17 cdef int[::indirect, ::indirect_contiguous] a18 cdef int[::generic, ::] a19 cdef int[::strided, :] a20 cdef int[::indirect, :] a21 cdef int[::contiguous, :] a23 cdef int[::indirect_contiguous, :] a24 cdef int[::indirect_contiguous, ::1] a25 cdef int[::indirect_contiguous, ::1, :] a26 cdef int[::indirect_contiguous, :, ::1] a27 cdef int[::indirect_contiguous, ::1, :] a28 cdef int[::indirect_contiguous, ::view.contiguous, :] a29 cdef int[::indirect_contiguous, :, ::view.contiguous] a30 cdef int[::indirect, ::1] a31 cdef int[::indirect, ::1, :] a32 = object() cdef int[::indirect, :, ::1] a33 = object() cdef int[::indirect, ::1, :] a34 cdef int[::indirect, ::view.contiguous, :] a35 cdef int[::indirect, :, ::view.contiguous] a36 cdef int[::1, :] my_f_contig = a32[0] cdef int[:, ::1] my_c_contig = a33[0] my_f_contig = a32[0, :, :] my_c_contig = a33[0, :, :] my_f_contig = a32[0, ...] my_c_contig = a33[0, ...] # Test casting to cython.view.array cdef double[:, :] m1 = NULL cdef double[:, :] m2 = NULL cdef double[:, :] m3 = NULL cdef double[:, :, :] m4 = NULL cdef double[:, :, :] m5 = NULL cdef double[:, :, :] m6 = NULL ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/memoryview/contig_check.pyx0000644000175100001770000000326700000000000022333 0ustar00runnerdocker00000000000000# mode: run # tag: numpy, memoryview import numpy as np # Cython used to forget the "is contig" helper functions when both are used. def copy_fortran3(double[:, :, :] mat): """ >>> a = np.ones((1, 1, 1), dtype=np.float64) >>> c = copy_fortran3(a) >>> (a == c).all() True >>> a = np.ones((4, 6, 8), dtype=np.float64, order='F') >>> c = copy_fortran3(a) >>> (a == c).all() True >>> a = np.ones((4, 6, 8), dtype=np.float64, order='C') >>> c = copy_fortran3(a) >>> (a == c).all() True """ cdef int x, y, z x, y, z = np.shape(mat) if 1 == x == y == z: # C- or F- contiguous just means "contiguous". if mat.is_c_contig() or mat.is_f_contig(): return mat.base else: return np.asarray(mat.copy_fortran()) elif mat.is_f_contig(): return mat.base else: return np.asarray(mat.copy_fortran()) def copy_fortran2(double[:, :] mat): """ >>> a = np.ones((1, 1), dtype=np.float64) >>> c = copy_fortran2(a) >>> (a == c).all() True >>> a = np.ones((4, 6), dtype=np.float64, order='F') >>> c = copy_fortran2(a) >>> (a == c).all() True >>> a = np.ones((4, 6), dtype=np.float64, order='C') >>> c = copy_fortran2(a) >>> (a == c).all() True """ cdef int rows, cols rows, cols = np.shape(mat) if rows == 1 or cols == 1: # C- or F- contiguous just means "contiguous". if mat.is_c_contig() or mat.is_f_contig(): return mat.base else: return np.asarray(mat.copy_fortran()) elif mat.is_f_contig(): return mat.base else: return np.asarray(mat.copy_fortran()) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/memoryview/cythonarray.pyx0000644000175100001770000001761500000000000022260 0ustar00runnerdocker00000000000000# mode: run from __future__ import unicode_literals # these imports allow testing different ways to access [[cython.]view.]array() from cython.view cimport array from cython cimport view as v cimport cython as cy include "../testsupport/cythonarrayutil.pxi" def length(shape): """ >>> len(length((2,))) 2 >>> len(length((2,3))) 2 >>> len(length((5,3,2))) 5 """ cdef array cvarray = array(shape=shape, itemsize=sizeof(int), format="i", mode='c') assert len(cvarray) == shape[0] return cvarray def contiguity(): ''' >>> contiguity() 12 4 2 3 2 4 8 2 3 2 ''' cdef v.array cvarray = cy.view.array(shape=(2,3), itemsize=sizeof(int), format="i", mode='c') assert cvarray.len == 2*3*sizeof(int), (cvarray.len, 2*3*sizeof(int)) assert cvarray.itemsize == sizeof(int) print cvarray.strides[0], cvarray.strides[1] print cvarray.shape[0], cvarray.shape[1] print cvarray.ndim print cdef v.array farray = v.array(shape=(2,3), itemsize=sizeof(int), format="i", mode='fortran') assert farray.len == 2*3*sizeof(int) assert farray.itemsize == sizeof(int) print farray.strides[0], farray.strides[1] print farray.shape[0], farray.shape[1] print farray.ndim def acquire(): ''' >>> acquire() ''' cdef object[int, ndim=1, mode="c"] buf1d = \ array(shape=(10,), itemsize=sizeof(int), format='i', mode='c') cdef object[int, ndim=2, mode="c"] buf2d = \ array(shape=(10,10), itemsize=sizeof(int), format='i') cdef object[unsigned long, ndim=3, mode='fortran'] buf3d = \ array(shape=(1,2,3), itemsize=sizeof(unsigned long), format='L', mode='fortran') cdef object[long double, ndim=3, mode='fortran'] bufld = \ array(shape=(1,2,3), itemsize=sizeof(long double), format='g', mode='fortran') def full_or_strided(): ''' >>> full_or_strided() ''' cdef object[float, ndim=2, mode='full'] fullbuf = \ array(shape=(10,10), itemsize=sizeof(float), format='f', mode='c') cdef object[long long int, ndim=3, mode='strided'] stridedbuf = \ array(shape=(1,2,3), itemsize=sizeof(long long int), format='q', mode='fortran') def dont_allocate_buffer(): """ >>> dont_allocate_buffer() callback called """ cdef array result = array((10, 10), itemsize=sizeof(int), format='i', allocate_buffer=False) assert result.data == NULL result.callback_free_data = callback result = None def test_cython_array_getbuffer(): """ >>> test_cython_array_getbuffer() 98 61 98 61 """ cdef int[:, ::1] cslice = create_array((14, 10), 'c') cdef int[::1, :] fslice = create_array((14, 10), 'fortran') print cslice[9, 8] print cslice[6, 1] print fslice[9, 8] print fslice[6, 1] def test_cython_array_index(): """ >>> test_cython_array_index() 98 61 98 61 """ c_array = create_array((14, 10), 'c') f_array = create_array((14, 10), 'fortran') print c_array[9, 8] print c_array[6, 1] print f_array[9, 8] print f_array[6, 1] cdef int *getp(int dim1=10, int dim2=10, dim3=1) except NULL: print "getp()" cdef int *p = malloc(dim1 * dim2 * dim3 * sizeof(int)) if p == NULL: raise MemoryError for i in range(dim1 * dim2 * dim3): p[i] = i return p cdef void callback_free_data(void *p) noexcept: print 'callback free data called' free(p) def test_array_from_pointer(): """ >>> test_array_from_pointer() getp() 69 c getp() callback free data called fortran getp() 56 getp() 56 getp() 119 callback free data called """ cdef int *p = getp() cdef array c_arr = p c_arr.callback_free_data = callback_free_data print c_arr[6, 9] print c_arr.mode c_arr = ( getp()) print c_arr.mode c_arr.callback_free_data = free c_arr = getp() c_arr.callback_free_data = free cdef int[:, ::1] mslice = c_arr print mslice[5, 6] c_arr = getp(12, 10) c_arr.callback_free_data = free print c_arr[5, 6] cdef int m = 12 cdef int n = 10 c_arr = getp(m, n) c_arr.callback_free_data = callback_free_data print c_arr[m - 1, n - 1] def test_array_from_pointer_3d(): """ >>> test_array_from_pointer_3d() getp() 3 3 True True """ cdef int *p = getp(2, 2, 2) cdef array c_arr = p cdef array f_arr = p cdef int[:, :, ::1] m1 = c_arr cdef int[::1, :, :] m2 = f_arr print m1[0, 1, 1], m2[1, 1, 0] print m1.is_c_contig(), m2.is_f_contig() def test_cyarray_from_carray(): """ >>> test_cyarray_from_carray() 0 8 21 0 8 21 """ cdef int[7][8] a for i in range(7): for j in range(8): a[i][j] = i * 8 + j cdef int[:, :] mslice = a print mslice[0, 0], mslice[1, 0], mslice[2, 5] mslice = a print mslice[0, 0], mslice[1, 0], mslice[2, 5] class InheritFrom(v.array): """ Test is just to confirm it works, not to do anything meaningful with it (Be aware that itemsize isn't necessarily right) >>> inst = InheritFrom(shape=(3, 3, 3), itemsize=4, format="i") """ pass def test_char_array_in_python_api(*shape): """ >>> import sys >>> if sys.version_info[0] < 3: ... def bytes(b): return memoryview(b).tobytes() # don't call str() >>> arr1d = test_char_array_in_python_api(10) >>> print(bytes(arr1d).decode('ascii')) xxxxxxxxxx >>> len(bytes(arr1d)) 10 >>> arr2d = test_char_array_in_python_api(10, 2) >>> print(bytes(arr2d).decode('ascii')) xxxxxxxxxxxxxxxxxxxx >>> len(bytes(arr2d)) 20 # memoryview >>> len(bytes(memoryview(arr1d))) 10 >>> bytes(memoryview(arr1d)) == bytes(arr1d) True >>> len(bytes(memoryview(arr2d))) 20 >>> bytes(memoryview(arr2d)) == bytes(arr2d) True # BytesIO >>> from io import BytesIO >>> BytesIO(arr1d).read() == bytes(arr1d) True >>> BytesIO(arr2d).read() == bytes(arr2d) True >>> b = BytesIO() >>> print(b.write(arr1d)) 10 >>> b.getvalue() == bytes(arr1d) or b.getvalue() True >>> b = BytesIO() >>> print(b.write(arr2d)) 20 >>> b.getvalue() == bytes(arr2d) or b.getvalue() True # BufferedWriter (uses PyBUF_SIMPLE, see https://github.com/cython/cython/issues/3775) >>> from io import BufferedWriter >>> b = BytesIO() >>> bw = BufferedWriter(b) >>> print(bw.write(arr1d)) 10 >>> bw.flush() >>> b.getvalue() == bytes(arr1d) True >>> b = BytesIO() >>> bw = BufferedWriter(b) >>> print(bw.write(arr2d)) 20 >>> bw.flush() >>> b.getvalue() == bytes(arr2d) True """ arr = array(shape=shape, itemsize=sizeof(char), format='c', mode='c') arr[:] = b'x' return arr def test_is_Sequence(): """ >>> test_is_Sequence() 1 1 True """ import sys if sys.version_info < (3, 3): from collections import Sequence else: from collections.abc import Sequence arr = array(shape=(5,), itemsize=sizeof(char), format='c', mode='c') for i in range(arr.shape[0]): arr[i] = f'{i}'.encode('ascii') print(arr.count(b'1')) # test for presence of added collection method print(arr.index(b'1')) # test for presence of added collection method if sys.version_info >= (3, 10): # test structural pattern match in Python # (because Cython hasn't implemented it yet, and because the details # of what Python considers a sequence are important) globs = {'arr': arr} exec(""" match arr: case [*_]: res = True case _: res = False """, globs) assert globs['res'] return isinstance(arr, Sequence) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/memoryview/error_declarations.pyx0000644000175100001770000000617000000000000023570 0ustar00runnerdocker00000000000000# mode: error cimport cython from cython cimport view cdef signed short[::1, ::1] both cdef signed short[::1, :, :, ::1] both2 cdef signed char[::2] err0 cdef signed char[::-100] err1 cdef signed char[::-1] err2 cdef long long[01::1, 0x01:, '0' :, False:] fort_contig0 cdef signed char[1::] bad_start cdef unsigned long[:,:1] bad_stop cdef unsigned long[:,::1,:] neither_c_or_f cdef signed char[::1-1+1] expr_spec cdef signed char[::blargh] bad_name cdef double[::alist[0]['view'].full] expr_attribute cdef object[::1, :] unconformable1 = object() cdef object[:, ::1] unconformable2 = unconformable1 cdef int[::1, :] dtype_unconformable = object() unconformable1 = dtype_unconformable # These are INVALID cdef int[::view.contiguous, ::1] a1 #cdef int[::view.generic_contiguous, ::1] a2 #cdef int[::view.contiguous, ::view.generic_contiguous] a3 #cdef int[::view.generic_contiguous, ::view.generic_contiguous] a4 cdef int[::view.contiguous, ::view.contiguous] a5 cdef int[:, ::view.contiguous, ::view.indirect_contiguous] a6 #cdef int[::view.generic_contiguous, ::view.contiguous] a7 #cdef int[::view.contiguous, ::view.generic_contiguous] a8 ctypedef int *intp cdef intp[:, :] myarray cdef int[:] a10 = object() cdef int[:] a11 = 1 cdef struct Valid: int array[1][2][3][4][5][6][7][8] cdef struct Invalid: int array[1][2][3][4][5][6][7][8][9] cdef Valid[:] validslice cdef Invalid[:] invalidslice cdef int[:, :, :, :] four_D four_D[None, None, None, None] four_D[None, None, None, None, None] cdef int[:, :, :, :, :, :, :, :] eight_D = object() cdef double[:] m print &m # These are VALID cdef int[::view.indirect_contiguous, ::view.contiguous] a9 four_D[None, None, None] _ERRORS = u''' 11:25: Cannot specify an array that is both C and Fortran contiguous. 12:31: Cannot specify an array that is both C and Fortran contiguous. 13:19: Step must be omitted, 1, or a valid specifier. 14:20: Step must be omitted, 1, or a valid specifier. 15:20: Step must be omitted, 1, or a valid specifier. 16:15: Start must not be given. 17:17: Start must not be given. 18:22: Axis specification only allowed in the 'step' slot. 19:18: Fortran contiguous specifier must follow an indirect dimension 20:22: Invalid axis specification. 21:19: Invalid axis specification. 22:22: no expressions allowed in axis spec, only names and literals. 25:37: Memoryview 'object[::1, :]' not conformable to memoryview 'object[:, ::1]'. 28:17: Different base types for memoryviews (int, Python object) 31:8: Dimension may not be contiguous 37:8: Only one direct contiguous axis may be specified. 38:8:Only dimensions 3 and 2 may be contiguous and direct 44:9: Invalid base type for memoryview slice: intp 46:35: Can only create cython.array from pointer or array 47:24: Cannot assign type 'double' to 'Py_ssize_t' 55:12: Invalid base type for memoryview slice: Invalid 58:6: More dimensions than the maximum number of buffer dimensions were used. 59:6: More dimensions than the maximum number of buffer dimensions were used. 61:8: More dimensions than the maximum number of buffer dimensions were used. 64:13: Cannot take address of memoryview slice ''' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/memoryview/extension_type_memoryview.pyx0000644000175100001770000000120000000000000025234 0ustar00runnerdocker00000000000000# mode: run # tag: numpy cimport numpy as np import numpy as np cdef class ExtensionType(object): cdef public int dummy def __init__(self, n): self.dummy = n items = [ExtensionType(1), ExtensionType(2)] cdef ExtensionType[:] view = np.array(items, dtype=ExtensionType) def test_getitem(): """ >>> test_getitem() 1 2 """ for i in range(view.shape[0]): item = view[i] print item.dummy def test_getitem_typed(): """ >>> test_getitem_typed() 1 2 """ cdef ExtensionType item for i in range(view.shape[0]): item = view[i] print item.dummy ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/memoryview/memoryview.pxd0000644000175100001770000000013100000000000022054 0ustar00runnerdocker00000000000000ctypedef float ext_dtype cdef extern from "bufaccess.h": ctypedef float td_h_double ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/memoryview/memoryview.pyx0000644000175100001770000007746400000000000022130 0ustar00runnerdocker00000000000000# mode: run # tag: perf_hints # Test declarations, behaviour and coercions of the memoryview type itself. u''' >>> f() >>> g() >>> call() >>> assignmvs() ''' from cython.view cimport memoryview, array from cython cimport view from cpython.object cimport PyObject from cpython.ref cimport Py_INCREF, Py_DECREF cimport cython import array as pyarray from libc.stdlib cimport malloc, free cdef extern from "Python.h": cdef int PyBUF_C_CONTIGUOUS include "../buffers/mockbuffers.pxi" # ### Test for some coercions # def init_obj(): return 3 cdef passmvs(float[:,::1] mvs, object foo): mvs = array((10,10), itemsize=sizeof(float), format='f') foo = init_obj() cdef object returnobj(): cdef obj = object() return obj cdef float[::1] returnmvs_inner(): return array((10,), itemsize=sizeof(float), format='f') cdef float[::1] returnmvs(): cdef float[::1] mvs = returnmvs_inner() return mvs def f(): cdef array arr = array(shape=(10,10), itemsize=sizeof(int), format='i') cdef memoryview mv = memoryview(arr, PyBUF_C_CONTIGUOUS) def g(): cdef object obj = init_obj() cdef int[::1] mview = array((10,), itemsize=sizeof(int), format='i') obj = init_obj() mview = array((10,), itemsize=sizeof(int), format='i') cdef class ExtClass(object): cdef int[::1] mview def __init__(self): self.mview = array((10,), itemsize=sizeof(int), format='i') self.mview = array((10,), itemsize=sizeof(int), format='i') class PyClass(object): def __init__(self): self.mview = array((10,), itemsize=sizeof(long), format='l') cdef cdg(): cdef double[::1] dmv = array((10,), itemsize=sizeof(double), format='d') dmv = array((10,), itemsize=sizeof(double), format='d') cdef class TestExcClassExternalDtype(object): cdef ext_dtype[:, :] arr_float cdef td_h_double[:, :] arr_double def __init__(self): self.arr_float = array((10, 10), itemsize=sizeof(ext_dtype), format='f') self.arr_float[:] = 0.0 self.arr_float[4, 4] = 2.0 self.arr_double = array((10, 10), itemsize=sizeof(td_h_double), format='d') self.arr_double[:] = 0.0 self.arr_double[4, 4] = 2.0 def test_external_dtype(): """ >>> test_external_dtype() 2.0 2.0 """ cdef TestExcClassExternalDtype obj = TestExcClassExternalDtype() print obj.arr_float[4, 4] print obj.arr_double[4, 4] cdef class ExtClassMockedAttr(object): cdef int[:, :] arr def __init__(self): self.arr = IntMockBuffer("self.arr", range(100), (10, 8)) self.arr[:] = 0 self.arr[4, 4] = 2 cdef int[:, :] _coerce_to_temp(): cdef ExtClassMockedAttr obj = ExtClassMockedAttr() return obj.arr def test_coerce_to_temp(): """ >>> test_coerce_to_temp() acquired self.arr released self.arr acquired self.arr released self.arr acquired self.arr released self.arr 2 acquired self.arr released self.arr 2 acquired self.arr released self.arr 2 """ _coerce_to_temp()[:] = 0 print _coerce_to_temp()[...] = 0 print print _coerce_to_temp()[4, 4] print print _coerce_to_temp()[..., 4][4] print print _coerce_to_temp()[4][4] def test_extclass_attribute_dealloc(): """ >>> test_extclass_attribute_dealloc() acquired self.arr 2 released self.arr """ cdef ExtClassMockedAttr obj = ExtClassMockedAttr() print obj.arr[4, 4] cdef float[:,::1] global_mv = array((10,10), itemsize=sizeof(float), format='f') global_mv = array((10,10), itemsize=sizeof(float), format='f') cdef object global_obj def assignmvs(): cdef int[::1] mv1, mv2 cdef int[:] mv3 mv1 = array((10,), itemsize=sizeof(int), format='i') mv2 = mv1 mv1 = mv1 mv1 = mv2 mv3 = mv2 def call(): global global_mv passmvs(global_mv, global_obj) global_mv = array((3,3), itemsize=sizeof(float), format='f') cdef float[::1] getmvs = returnmvs() returnmvs() cdef object obj = returnobj() cdg() f = ExtClass() pf = PyClass() cdef ExtClass get_ext_obj(): print 'get_ext_obj called' return ExtClass.__new__(ExtClass) def test_cdef_attribute(): """ >>> test_cdef_attribute() Memoryview is not initialized local variable 'myview' referenced before assignment local variable 'myview' referenced before assignment get_ext_obj called Memoryview is not initialized """ cdef ExtClass extobj = ExtClass.__new__(ExtClass) try: print extobj.mview except AttributeError, e: print e.args[0] else: print "No AttributeError was raised" cdef int[:] myview try: print myview except UnboundLocalError, e: print e.args[0] else: print "No UnboundLocalError was raised" cdef int[:] otherview try: otherview = myview except UnboundLocalError, e: print e.args[0] try: print get_ext_obj().mview except AttributeError, e: print e.args[0] else: print "No AttributeError was raised" print ExtClass().mview @cython.boundscheck(False) def test_nogil_unbound_localerror(): """ >>> test_nogil_unbound_localerror() Traceback (most recent call last): ... UnboundLocalError: local variable 'm' referenced before assignment """ cdef int[:] m with nogil: m[0] = 10 def test_nogil_oob(): """ >>> test_nogil_oob() Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) """ cdef int[5] a cdef int[:] m = a with nogil: m[5] = 1 def basic_struct(MyStruct[:] mslice): """ See also buffmt.pyx >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)])) [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ccqii")) [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] """ cdef object buf = mslice print sorted([(k, int(v)) for k, v in buf[0].items()]) def nested_struct(NestedStruct[:] mslice): """ See also buffmt.pyx >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)])) 1 2 3 4 5 >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="T{ii}T{2i}i")) 1 2 3 4 5 """ cdef object buf = mslice d = buf[0] print d['x']['a'], d['x']['b'], d['y']['a'], d['y']['b'], d['z'] def packed_struct(PackedStruct[:] mslice): """ See also buffmt.pyx >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)])) 1 2 >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c^i}")) 1 2 >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c=i}")) 1 2 """ cdef object buf = mslice print buf[0]['a'], buf[0]['b'] def nested_packed_struct(NestedPackedStruct[:] mslice): """ See also buffmt.pyx >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)])) 1 2 3 4 5 >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ci^ci@i")) 1 2 3 4 5 >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="^c@i^ci@i")) 1 2 3 4 5 """ cdef object buf = mslice d = buf[0] print d['a'], d['b'], d['sub']['a'], d['sub']['b'], d['c'] def complex_dtype(long double complex[:] mslice): """ >>> complex_dtype(LongComplexMockBuffer(None, [(0, -1)])) -1j """ cdef object buf = mslice print buf[0] def complex_inplace(long double complex[:] mslice): """ >>> complex_inplace(LongComplexMockBuffer(None, [(0, -1)])) (1+1j) """ cdef object buf = mslice buf[0] = buf[0] + 1 + 2j print buf[0] def complex_struct_dtype(LongComplex[:] mslice): """ Note that the format string is "Zg" rather than "2g", yet a struct is accessed. >>> complex_struct_dtype(LongComplexMockBuffer(None, [(0, -1)])) 0.0 -1.0 """ cdef object buf = mslice print buf[0]['real'], buf[0]['imag'] # # Getting items and index bounds checking # def get_int_2d(int[:, :] mslice, int i, int j): """ >>> C = IntMockBuffer("C", range(6), (2,3)) >>> get_int_2d(C, 1, 1) acquired C released C 4 Check negative indexing: >>> get_int_2d(C, -1, 0) acquired C released C 3 >>> get_int_2d(C, -1, -2) acquired C released C 4 >>> get_int_2d(C, -2, -3) acquired C released C 0 Out-of-bounds errors: >>> get_int_2d(C, 2, 0) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) >>> get_int_2d(C, 0, -4) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 1) """ cdef object buf = mslice return buf[i, j] def set_int_2d(int[:, :] mslice, int i, int j, int value): """ Uses get_int_2d to read back the value afterwards. For pure unit test, one should support reading in MockBuffer instead. >>> C = IntMockBuffer("C", range(6), (2,3)) >>> set_int_2d(C, 1, 1, 10) acquired C released C >>> get_int_2d(C, 1, 1) acquired C released C 10 Check negative indexing: >>> set_int_2d(C, -1, 0, 3) acquired C released C >>> get_int_2d(C, -1, 0) acquired C released C 3 >>> set_int_2d(C, -1, -2, 8) acquired C released C >>> get_int_2d(C, -1, -2) acquired C released C 8 >>> set_int_2d(C, -2, -3, 9) acquired C released C >>> get_int_2d(C, -2, -3) acquired C released C 9 Out-of-bounds errors: >>> set_int_2d(C, 2, 0, 19) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) >>> set_int_2d(C, 0, -4, 19) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 1) """ cdef object buf = mslice buf[i, j] = value # # auto type inference # (note that for most numeric types "might_overflow" stops the type inference from working well) # def type_infer(double[:, :] arg): """ >>> type_infer(DoubleMockBuffer(None, range(6), (2,3))) double double[:] double[:] double[:, :] """ a = arg[0,0] print(cython.typeof(a)) b = arg[0] print(cython.typeof(b)) c = arg[0,:] print(cython.typeof(c)) d = arg[:,:] print(cython.typeof(d)) # # Loop optimization # @cython.test_fail_if_path_exists("//CoerceToPyTypeNode") def memview_iter(double[:, :] arg): """ >>> memview_iter(DoubleMockBuffer("C", range(6), (2,3))) acquired C released C True """ cdef double total = 0 for mview1d in arg: for val in mview1d: total += val if total == 15: return True # # Test all kinds of indexing and flags # def writable(unsigned short int[:, :, :] mslice): """ >>> R = UnsignedShortMockBuffer("R", range(27), shape=(3, 3, 3)) >>> writable(R) acquired R released R >>> [str(x) for x in R.received_flags] # Py2/3 ['FORMAT', 'ND', 'STRIDES', 'WRITABLE'] """ cdef object buf = mslice buf[2, 2, 1] = 23 def strided(int[:] mslice): """ >>> A = IntMockBuffer("A", range(4)) >>> strided(A) acquired A released A 2 Check that the suboffsets were patched back prior to release. >>> A.release_ok True """ cdef object buf = mslice return buf[2] def c_contig(int[::1] mslice): """ >>> A = IntMockBuffer(None, range(4)) >>> c_contig(A) 2 """ cdef object buf = mslice return buf[2] def c_contig_2d(int[:, ::1] mslice): """ Multi-dim has separate implementation >>> A = IntMockBuffer(None, range(12), shape=(3,4)) >>> c_contig_2d(A) 7 """ cdef object buf = mslice return buf[1, 3] def f_contig(int[::1, :] mslice): """ >>> A = IntMockBuffer(None, range(4), shape=(2, 2), strides=(1, 2)) >>> f_contig(A) 2 """ cdef object buf = mslice return buf[0, 1] def f_contig_2d(int[::1, :] mslice): """ Must set up strides manually to ensure Fortran ordering. >>> A = IntMockBuffer(None, range(12), shape=(4,3), strides=(1, 4)) >>> f_contig_2d(A) 7 """ cdef object buf = mslice return buf[3, 1] def generic(int[::view.generic, ::view.generic] mslice1, int[::view.generic, ::view.generic] mslice2): """ >>> A = IntMockBuffer("A", [[0,1,2], [3,4,5], [6,7,8]]) >>> B = IntMockBuffer("B", [[0,1,2], [3,4,5], [6,7,8]], shape=(3, 3), strides=(1, 3)) >>> generic(A, B) acquired A acquired B 4 4 10 11 released A released B """ buf1, buf2 = mslice1, mslice2 print buf1[1, 1] print buf2[1, 1] buf1[2, -1] = 10 buf2[2, -1] = 11 print buf1[2, 2] print buf2[2, 2] #def generic_contig(int[::view.generic_contiguous, :] mslice1, # int[::view.generic_contiguous, :] mslice2): # """ # >>> A = IntMockBuffer("A", [[0,1,2], [3,4,5], [6,7,8]]) # >>> B = IntMockBuffer("B", [[0,1,2], [3,4,5], [6,7,8]], shape=(3, 3), strides=(1, 3)) # >>> generic_contig(A, B) # acquired A # acquired B # 4 # 4 # 10 # 11 # released A # released B # """ # buf1, buf2 = mslice1, mslice2 # # print buf1[1, 1] # print buf2[1, 1] # # buf1[2, -1] = 10 # buf2[2, -1] = 11 # # print buf1[2, 2] # print buf2[2, 2] ctypedef int td_cy_int cdef extern from "bufaccess.h": ctypedef td_cy_int td_h_short # Defined as short, but Cython doesn't know this! ctypedef float td_h_double # Defined as double ctypedef unsigned int td_h_ushort # Defined as unsigned short ctypedef td_h_short td_h_cy_short def printbuf_td_cy_int(td_cy_int[:] mslice, shape): """ >>> printbuf_td_cy_int(IntMockBuffer(None, range(3)), (3,)) 0 1 2 END >>> printbuf_td_cy_int(ShortMockBuffer(None, range(3)), (3,)) Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'td_cy_int' but got 'short' """ cdef object buf = mslice cdef int i for i in range(shape[0]): print buf[i], print 'END' def printbuf_td_h_short(td_h_short[:] mslice, shape): """ >>> printbuf_td_h_short(ShortMockBuffer(None, range(3)), (3,)) 0 1 2 END >>> printbuf_td_h_short(IntMockBuffer(None, range(3)), (3,)) Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'td_h_short' but got 'int' """ cdef object buf = mslice cdef int i for i in range(shape[0]): print buf[i], print 'END' def printbuf_td_h_cy_short(td_h_cy_short[:] mslice, shape): """ >>> printbuf_td_h_cy_short(ShortMockBuffer(None, range(3)), (3,)) 0 1 2 END >>> printbuf_td_h_cy_short(IntMockBuffer(None, range(3)), (3,)) Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'td_h_cy_short' but got 'int' """ cdef object buf = mslice cdef int i for i in range(shape[0]): print buf[i], print 'END' def printbuf_td_h_ushort(td_h_ushort[:] mslice, shape): """ >>> printbuf_td_h_ushort(UnsignedShortMockBuffer(None, range(3)), (3,)) 0 1 2 END >>> printbuf_td_h_ushort(ShortMockBuffer(None, range(3)), (3,)) Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'td_h_ushort' but got 'short' """ cdef object buf = mslice cdef int i for i in range(shape[0]): print buf[i], print 'END' def printbuf_td_h_double(td_h_double[:] mslice, shape): """ >>> printbuf_td_h_double(DoubleMockBuffer(None, [0.25, 1, 3.125]), (3,)) 0.25 1.0 3.125 END >>> printbuf_td_h_double(FloatMockBuffer(None, [0.25, 1, 3.125]), (3,)) Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'td_h_double' but got 'float' """ cdef object buf = mslice cdef int i for i in range(shape[0]): print buf[i], print 'END' # # Object access # def addref(*args): for item in args: Py_INCREF(item) def decref(*args): for item in args: Py_DECREF(item) @cython.binding(False) @cython.always_allow_keywords(False) def get_refcount(x): return (x).ob_refcnt def printbuf_object(object[:] mslice, shape): """ Only play with unique objects, interned numbers etc. will have unpredictable refcounts. ObjectMockBuffer doesn't do anything about increfing/decrefing, we to the "buffer implementor" refcounting directly in the testcase. >>> _x = 1 >>> a, b, c = "globally_unique_string_2323412" + "3" * _x, {4:23}, [34,3] >>> get_refcount(a), get_refcount(b), get_refcount(c) (2, 2, 2) >>> A = ObjectMockBuffer(None, [a, b, c]) >>> printbuf_object(A, (3,)) 'globally_unique_string_23234123' 2 {4: 23} 2 [34, 3] 2 """ cdef object buf = mslice cdef int i for i in range(shape[0]): print repr(buf[i]), (buf[i]).ob_refcnt def assign_to_object(object[:] mslice, int idx, obj): """ See comments on printbuf_object above. >>> a, b = [1, 2, 3], [4, 5, 6] >>> get_refcount(a), get_refcount(b) (2, 2) >>> addref(a) >>> A = ObjectMockBuffer(None, [1, a]) # 1, ...,otherwise it thinks nested lists... >>> get_refcount(a), get_refcount(b) (3, 2) >>> assign_to_object(A, 1, b) >>> get_refcount(a), get_refcount(b) (2, 3) >>> decref(b) """ cdef object buf = mslice buf[idx] = obj def assign_temporary_to_object(object[:] mslice): """ See comments on printbuf_object above. >>> a, b = [1, 2, 3], {4:23} >>> get_refcount(a) 2 >>> addref(a) >>> A = ObjectMockBuffer(None, [b, a]) >>> get_refcount(a) 3 >>> assign_temporary_to_object(A) >>> get_refcount(a) 2 >>> printbuf_object(A, (2,)) {4: 23} 2 {1: 8} 2 To avoid leaking a reference in our testcase we need to replace the temporary with something we can manually decref :-) >>> assign_to_object(A, 1, a) >>> decref(a) """ cdef object buf = mslice buf[1] = {3-2: 2+(2*4)-2} def test_pyview_of_memview(int[:] ints): """ >>> A = IntMockBuffer(None, [1, 2, 3]) >>> len(test_pyview_of_memview(A)) 3 """ return ints def test_generic_slicing(arg, indirect=False): """ Test simple slicing >>> test_generic_slicing(IntMockBuffer("A", range(8 * 14 * 11), shape=(8, 14, 11))) acquired A (3, 9, 2) 308 -11 1 -1 -1 -1 released A Test direct slicing, negative slice oob in dim 2 >>> test_generic_slicing(IntMockBuffer("A", range(1 * 2 * 3), shape=(1, 2, 3))) acquired A (0, 0, 2) 12 -3 1 -1 -1 -1 released A Test indirect slicing >>> test_generic_slicing(IntMockBuffer("A", shape_5_3_4_list, shape=(5, 3, 4)), indirect=True) acquired A (2, 0, 2) 0 1 -1 released A >>> stride1 = 21 * 14 >>> stride2 = 21 >>> test_generic_slicing(IntMockBuffer("A", shape_9_14_21_list, shape=(9, 14, 21)), indirect=True) acquired A (3, 9, 2) 10 1 -1 released A """ cdef int[::view.generic, ::view.generic, :] _a = arg cdef object a = _a b = a[2:8:2, -4:1:-1, 1:3] print b.shape if indirect: print b.suboffsets[0] // sizeof(int *), print b.suboffsets[1] // sizeof(int), print b.suboffsets[2] else: print_int_offsets(b.strides[0], b.strides[1], b.strides[2]) print_int_offsets(b.suboffsets[0], b.suboffsets[1], b.suboffsets[2]) cdef int i, j, k for i in range(b.shape[0]): for j in range(b.shape[1]): for k in range(b.shape[2]): itemA = a[2 + 2 * i, -4 - j, 1 + k] itemB = b[i, j, k] assert itemA == itemB, (i, j, k, itemA, itemB) def test_indirect_slicing(arg): """ Test indirect slicing >>> test_indirect_slicing(IntMockBuffer("A", shape_5_3_4_list, shape=(5, 3, 4))) acquired A (5, 3, 2) 0 0 -1 58 56 58 58 58 58 released A >>> test_indirect_slicing(IntMockBuffer("A", shape_9_14_21_list, shape=(9, 14, 21))) acquired A (5, 14, 3) 0 16 -1 2412 2410 2412 2412 2412 2412 released A """ cdef int[::view.indirect, ::view.indirect, :] _a = arg a = _a b = a[-5:, ..., -5:100:2] print b.shape print_int_offsets(*b.suboffsets) print b[4, 2, 1] print b[..., 0][4, 2] print b[..., 1][4, 2] print b[..., 1][4][2] print b[4][2][1] print b[4, 2][1] def test_direct_slicing(arg): """ Fused types would be convenient to test this stuff! Test simple slicing >>> test_direct_slicing(IntMockBuffer("A", range(8 * 14 * 11), shape=(8, 14, 11))) acquired A (3, 9, 2) 308 -11 1 -1 -1 -1 released A Test direct slicing, negative slice oob in dim 2 >>> test_direct_slicing(IntMockBuffer("A", range(1 * 2 * 3), shape=(1, 2, 3))) acquired A (0, 0, 2) 12 -3 1 -1 -1 -1 released A """ cdef int[:, :, :] _a = arg cdef object a = _a b = a[2:8:2, -4:1:-1, 1:3] print b.shape print_int_offsets(*b.strides) print_int_offsets(*b.suboffsets) cdef int i, j, k for i in range(b.shape[0]): for j in range(b.shape[1]): for k in range(b.shape[2]): itemA = a[2 + 2 * i, -4 - j, 1 + k] itemB = b[i, j, k] assert itemA == itemB, (i, j, k, itemA, itemB) def test_slicing_and_indexing(arg): """ >>> a = IntStridedMockBuffer("A", range(10 * 3 * 5), shape=(10, 3, 5)) >>> test_slicing_and_indexing(a) acquired A (5, 2) 15 2 126 113 [111] released A """ cdef int[:, :, :] _a = arg cdef object a = _a b = a[-5:, 1, 1::2] c = b[4:1:-1, ::-1] d = c[2, 1:2] print b.shape print_int_offsets(*b.strides) cdef int i, j for i in range(b.shape[0]): for j in range(b.shape[1]): itemA = a[-5 + i, 1, 1 + 2 * j] itemB = b[i, j] assert itemA == itemB, (i, j, itemA, itemB) print c[1, 1], c[2, 0] print [d[i] for i in range(d.shape[0])] def test_oob(): """ >>> test_oob() Traceback (most recent call last): ... IndexError: Index out of bounds (axis 1) """ cdef int[:, :] a = IntMockBuffer("A", range(4 * 9), shape=(4, 9)) print a[:, 20] def test_acquire_memoryview(): """ Segfaulting in 3.2? >> test_acquire_memoryview() acquired A 22 22 22 released A """ cdef int[:, :] a = IntMockBuffer("A", range(4 * 9), shape=(4, 9)) cdef object b = a print a[2, 4] # Make sure we don't have to keep this around del a print b cdef int[:, :] c = b print b[2, 4] print c[2, 4] def test_acquire_memoryview_slice(): """ >>> test_acquire_memoryview_slice() acquired A 31 31 31 released A """ cdef int[:, :] a = IntMockBuffer("A", range(4 * 9), shape=(4, 9)) a = a[1:, :6] cdef object b = a print a[2, 4] # Make sure we don't have to keep this around del a print b cdef int[:, :] c = b print b[2, 4] print c[2, 4] cdef class TestPassMemoryviewToSetter: """ Setter has a fixed function signature and the argument needs conversion so it ends up passing through some slightly different reference counting code >>> dmb = DoubleMockBuffer("dmb", range(2), shape=(2,)) >>> TestPassMemoryviewToSetter().prop = dmb acquired dmb In prop setter released dmb >>> TestPassMemoryviewToSetter().prop_with_reassignment = dmb acquired dmb In prop_with_reassignment setter released dmb >>> dmb = DoubleMockBuffer("dmb", range(1,3), shape=(2,)) >>> TestPassMemoryviewToSetter().prop_with_reassignment = dmb acquired dmb In prop_with_reassignment setter released dmb """ @property def prop(self): return None @prop.setter def prop(self, double[:] x): print("In prop setter") @property def prop_with_reassignment(self): return None @prop_with_reassignment.setter def prop_with_reassignment(self, double[:] x): # reassignment again requires slightly different code if x[0]: x = x[1:] print("In prop_with_reassignment setter") class SingleObject(object): def __init__(self, value): self.value = value def __str__(self): return str(self.value) def __eq__(self, other): return self.value == getattr(other, 'value', None) or self.value == other def test_assign_scalar(int[:, :] m): """ >>> A = IntMockBuffer("A", [0] * 100, shape=(10, 10)) >>> test_assign_scalar(A) acquired A 1 1 1 4 1 6 1 1 1 1 2 2 2 4 2 6 2 2 2 2 3 3 3 4 3 6 3 3 3 3 1 1 1 4 1 6 1 1 1 1 5 5 5 5 5 6 5 5 5 5 1 1 1 4 1 6 1 1 1 1 released A """ m[:, :] = 1 m[1, :] = 2 m[2, :] = 3 m[:, 3] = 4 m[4, ...] = 5 m[..., 5] = 6 for i in range(6): print " ".join([str(m[i, j]) for j in range(m.shape[1])]) def test_contig_scalar_to_slice_assignment(): """ >>> test_contig_scalar_to_slice_assignment() 14 14 14 14 20 20 20 20 """ cdef int[5][10] a cdef int[:, ::1] _m = a m = _m m[...] = 14 print m[0, 0], m[-1, -1], m[3, 2], m[4, 9] m[:, :] = 20 print m[0, 0], m[-1, -1], m[3, 2], m[4, 9] def test_dtype_object_scalar_assignment(): """ >>> test_dtype_object_scalar_assignment() """ cdef object[:] m = array((10,), sizeof(PyObject *), 'O') m[:] = SingleObject(2) assert m[0] == m[4] == m[-1] == 2 ( m)[:] = SingleObject(3) assert m[0] == m[4] == m[-1] == 3 def test_assignment_in_conditional_expression(bint left): """ >>> test_assignment_in_conditional_expression(True) 1.0 2.0 1.0 2.0 >>> test_assignment_in_conditional_expression(False) 3.0 4.0 3.0 4.0 """ cdef double a[2] cdef double b[2] a[:] = [1, 2] b[:] = [3, 4] cdef double[:] A = a cdef double[:] B = b cdef double[:] C, c # assign new memoryview references C = A if left else B for i in range(C.shape[0]): print C[i] # create new memoryviews c = a if left else b for i in range(c.shape[0]): print c[i] def test_cpython_offbyone_issue_23349(): """ >>> print(test_cpython_offbyone_issue_23349()) testing """ cdef unsigned char[:] v = bytearray(b"testing") # the following returns 'estingt' without the workaround return bytearray(v).decode('ascii') @cython.test_fail_if_path_exists('//SimpleCallNode') @cython.test_assert_path_exists( '//ReturnStatNode//TupleNode', '//ReturnStatNode//TupleNode//CondExprNode', ) def min_max_tree_restructuring(): """ >>> min_max_tree_restructuring() (1, 3) """ cdef char a[5] a = [1, 2, 3, 4, 5] cdef char[:] aview = a return max(1, aview[0]), min(5, aview[2]) @cython.test_fail_if_path_exists( '//MemoryViewSliceNode', ) @cython.test_assert_path_exists( '//MemoryViewIndexNode', ) #@cython.boundscheck(False) # reduce C code clutter def optimised_index_of_slice(int[:,:,:] arr, int x, int y, int z): """ >>> arr = IntMockBuffer("A", list(range(10*10*10)), shape=(10,10,10)) >>> optimised_index_of_slice(arr, 2, 3, 4) acquired A (123, 123) (223, 223) (133, 133) (124, 124) (234, 234) (123, 123) (123, 123) (123, 123) (134, 134) (134, 134) (234, 234) (234, 234) (234, 234) released A """ print(arr[1, 2, 3], arr[1][2][3]) print(arr[x, 2, 3], arr[x][2][3]) print(arr[1, y, 3], arr[1][y][3]) print(arr[1, 2, z], arr[1][2][z]) print(arr[x, y, z], arr[x][y][z]) print(arr[1, 2, 3], arr[:, 2][1][3]) print(arr[1, 2, 3], arr[:, 2, :][1, 3]) print(arr[1, 2, 3], arr[:, 2, 3][1]) print(arr[1, y, z], arr[1, :][y][z]) print(arr[1, y, z], arr[1, :][y, z]) print(arr[x, y, z], arr[x][:][:][y][:][:][z]) print(arr[x, y, z], arr[:][x][:][y][:][:][z]) print(arr[x, y, z], arr[:, :][x][:, :][y][:][z]) def test_assign_from_byteslike(byteslike): # Once https://python3statement.org/ is accepted, should be just # >>> test_assign_from_byteslike(bytes(b'hello')) # b'hello' # ... """ >>> print(test_assign_from_byteslike(bytes(b'hello')).decode()) hello >>> print(test_assign_from_byteslike(bytearray(b'howdy')).decode()) howdy """ # fails on Python 2.7- with # TypeError: an integer is required # >>> print(test_assign_from_byteslike(pyarray.array('B', b'aloha')).decode()) # aloha # fails on Python 2.6- with # NameError: name 'memoryview' is not defined # >>> print(test_assign_from_byteslike(memoryview(b'bye!!')).decode()) # bye!! def assign(m): m[:] = byteslike cdef void *buf cdef unsigned char[:] mview buf = malloc(5) try: mview = (buf) assign(mview) return (buf)[:5] finally: free(buf) def multiple_memoryview_def(double[:] a, double[:] b): return a[0] + b[0] cpdef multiple_memoryview_cpdef(double[:] a, double[:] b): return a[0] + b[0] cdef multiple_memoryview_cdef(double[:] a, double[:] b): return a[0] + b[0] multiple_memoryview_cdef_wrapper = multiple_memoryview_cdef def test_conversion_failures(): """ What we're concerned with here is that we don't lose references if one of several memoryview arguments fails to convert. >>> test_conversion_failures() """ imb = IntMockBuffer("", range(1), shape=(1,)) dmb = DoubleMockBuffer("", range(1), shape=(1,)) for first, second in [(imb, dmb), (dmb, imb)]: for func in [multiple_memoryview_def, multiple_memoryview_cpdef, multiple_memoryview_cdef_wrapper]: # note - using python call of "multiple_memoryview_cpdef" deliberately imb_before = get_refcount(imb) dmb_before = get_refcount(dmb) try: func(first, second) except: assert get_refcount(imb) == imb_before, "before %s after %s" % (imb_before, get_refcount(imb)) assert get_refcount(dmb) == dmb_before, "before %s after %s" % (dmb_before, get_refcount(dmb)) else: assert False, "Conversion should fail!" def test_is_Sequence(double[:] a): """ >>> test_is_Sequence(DoubleMockBuffer(None, range(6), shape=(6,))) 1 1 True """ if sys.version_info < (3, 3): from collections import Sequence else: from collections.abc import Sequence for i in range(a.shape[0]): a[i] = i print(a.count(1.0)) # test for presence of added collection method print(a.index(1.0)) # test for presence of added collection method if sys.version_info >= (3, 10): # test structural pattern match in Python # (because Cython hasn't implemented it yet, and because the details # of what Python considers a sequence are important) globs = {'arr': a} exec(""" match arr: case [*_]: res = True case _: res = False """, globs) assert globs['res'] return isinstance(a, Sequence) ctypedef int aliasT def test_assignment_typedef(): """ >>> test_assignment_typedef() 1 2 """ cdef int[2] x cdef aliasT[:] y x[:] = [1, 2] y = x for v in y: print(v) def test_untyped_index(i): """ >>> test_untyped_index(2) 3 >>> test_untyped_index(0) 5 >>> test_untyped_index(-1) 0 """ cdef int[6] arr arr = [5, 4, 3, 2, 1, 0] cdef int[:] mview_arr = arr return mview_arr[i] # should generate a performance hint _PERFORMANCE_HINTS = """ 1315:21: Index should be typed for more efficient access """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/memoryview/memoryview_acq_count.srctree0000644000175100001770000000171300000000000024773 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "import counting_atomic" PYTHON -c "import counting_locked" ######## setup.py ######## from distutils.core import setup from Cython.Distutils import build_ext from Cython.Distutils.extension import Extension setup( ext_modules = [ Extension("counting_atomic", ["counting_atomic.pyx"]), Extension("counting_locked", ["counting_locked.pyx"], define_macros=[('CYTHON_ATOMICS', '0')]) ], cmdclass={'build_ext': build_ext}, ) ######## counting_atomic.pyx ######## include "counting.pxi" ######## counting_locked.pyx ######## include "counting.pxi" ######## counting.pxi ######## cimport cython from cython.parallel cimport prange cdef int[100] a cdef int[:] m = a cdef Py_ssize_t i for i in prange(1000000, nogil=True, num_threads=16): use_slice(m[::2]) cdef int use_slice(int[:] m) except -1 nogil: cdef int[:] m2 = m[1:] m = m2[:-1] del m, m2 return 0 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/memoryview/memoryview_annotation_typing.py0000644000175100001770000000707200000000000025550 0ustar00runnerdocker00000000000000# mode: run # tag: pep484, numpy, pure3.7 ##, warnings from __future__ import annotations # object[:] cannot be evaluated import cython try: import typing except ImportError: pass # Workaround for python 2.7 import numpy COMPILED = cython.compiled def one_dim(a: cython.double[:]): """ >>> a = numpy.ones((10,), numpy.double) >>> one_dim(a) (2.0, 1) """ a[0] *= 2 return a[0], a.ndim def one_dim_ccontig(a: cython.double[::1]): """ >>> a = numpy.ones((10,), numpy.double) >>> one_dim_ccontig(a) (2.0, 1) """ a[0] *= 2 return a[0], a.ndim def two_dim(a: cython.double[:,:]): """ >>> a = numpy.ones((10, 10), numpy.double) >>> two_dim(a) (3.0, 1.0, 2) """ a[0,0] *= 3 return a[0,0], a[0,1], a.ndim def variable_annotation(a): """ >>> a = numpy.ones((10,), numpy.double) >>> variable_annotation(a) 2.0 """ b: cython.double[:] b = None if cython.compiled: assert cython.typeof(b) == "double[:]", cython.typeof(b) b = a b[1] += 1 b[2] += 2 return b[1] def slice_none(m: cython.double[:]): """ >>> try: ... a = slice_none(None) ... except TypeError as exc: ... assert COMPILED ... if "Argument 'm' must not be None" not in str(exc): raise ... else: ... assert a == 1 ... assert not COMPILED """ return 1 if m is None else 2 def slice_optional(m: typing.Optional[cython.double[:]]): """ >>> slice_optional(None) 1 >>> a = numpy.ones((10,), numpy.double) >>> slice_optional(a) 2 # Make sure that we actually evaluate the type and don't just accept everything. >>> try: ... x = slice_optional(123) ... except TypeError as exc: ... if not COMPILED: raise ... else: ... assert not COMPILED """ return 1 if m is None else 2 @cython.nogil @cython.cfunc def _one_dim_nogil_cfunc(a: cython.double[:]) -> cython.double: a[0] *= 2 return a[0] def one_dim_nogil_cfunc(a: cython.double[:]): """ >>> a = numpy.ones((10,), numpy.double) >>> one_dim_nogil_cfunc(a) 2.0 """ with cython.nogil: result = _one_dim_nogil_cfunc(a) return result def generic_object_memoryview(a: object[:]): """ >>> a = numpy.ones((10,), dtype=object) >>> generic_object_memoryview(a) 10 """ sum = 0 for ai in a: sum += ai if cython.compiled: assert cython.typeof(a) == "object[:]", cython.typeof(a) return sum def generic_object_memoryview_contig(a: object[::1]): """ >>> a = numpy.ones((10,), dtype=object) >>> generic_object_memoryview_contig(a) 10 """ sum = 0 for ai in a: sum += ai if cython.compiled: assert cython.typeof(a) == "object[::1]", cython.typeof(a) return sum @cython.cclass class C: x: cython.int def __init__(self, value): self.x = value def ext_type_object_memoryview(a: C[:]): """ >>> a = numpy.array([C(i) for i in range(10)], dtype=object) >>> ext_type_object_memoryview(a) 45 """ sum = 0 for ai in a: sum += ai.x if cython.compiled: assert cython.typeof(a) == "C[:]", cython.typeof(a) return sum def ext_type_object_memoryview_contig(a: C[::1]): """ >>> a = numpy.array([C(i) for i in range(10)], dtype=object) >>> ext_type_object_memoryview_contig(a) 45 """ sum = 0 for ai in a: sum += ai.x if cython.compiled: assert cython.typeof(a) == "C[::1]", cython.typeof(a) return sum ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/memoryview/memoryview_cache_builtins.srctree0000644000175100001770000000067000000000000025774 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace ################ setup.py ##################### from distutils.core import setup from Cython.Build import cythonize from Cython.Compiler import Options Options.cache_builtins = False setup( ext_modules = cythonize("mview.pyx") ) ############### mview.pyx ################ # https://github.com/cython/cython/issues/3406 # Failure was at Cython compilation stage def f(double [::1] x): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3847222 Cython-3.0.8/tests/memoryview/memoryview_compare_type_pointers.srctree0000644000175100001770000000306300000000000027431 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "import test_compare_type_pointers" ######## setup.py ######## from Cython.Build import cythonize from distutils.core import setup setup( ext_modules = cythonize("*.pyx"), ) ######## test_compare_type_pointers.pyx ######## include "types.pxi" import other_module def test_foo_view(Foo[:] m): return m[0].f assert test_foo_view(other_module.fooview_obj) == 5.0 assert test_foo_view(other_module.otherfooview_obj) == 4.0 # Test for type comparison where the memoryview instance check succeeds cdef OtherFoo[10] otherfooarray cdef OtherFoo[:] otherfooview = otherfooarray otherfooview_obj = otherfooview otherfooview[0].f = 4.0 assert test_foo_view(otherfooview_obj) == 4.0 # Test a simple dtype now def test_double_view(double[:] m): return m[0] assert test_double_view(other_module.doubleview_obj) == 6.0 ######## other_module.pyx ######## include "types.pxi" cdef Foo[10] fooarray cdef Foo[:] fooview = fooarray fooview_obj = fooview fooview[0].f = 5.0 cdef OtherFoo[10] otherfooarray cdef OtherFoo[:] otherfooview = otherfooarray otherfooview_obj = otherfooview otherfooview[0].f = 4.0 cdef double[10] doublearray cdef double[:] doubleview = doublearray doubleview_obj = doubleview doubleview[0] = 6.0 ######## types.pxi ######## ctypedef packed struct Baz: double d ctypedef struct Bar: int i ctypedef struct Foo: float f double complex dc char c int i Bar b char s[20] ctypedef struct OtherFoo: float f double complex dc char c int i Bar b char s[20] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/memoryview/memoryview_in_subclasses.pyx0000644000175100001770000000212700000000000025025 0ustar00runnerdocker00000000000000""" Test for memory leaks when adding more memory view attributes in subtypes. """ import gc from cython.view cimport array def count_memoryviews(): gc.collect() return sum([1 if 'memoryview' in str(type(o)) else 0 for o in gc.get_objects()]) def run_test(cls, num_iters): orig_count = count_memoryviews() def f(): x = cls(1024) for i in range(num_iters): f() return count_memoryviews() - orig_count cdef class BaseType: """ >>> run_test(BaseType, 10) 0 """ cdef double[:] buffer def __cinit__(self, n): self.buffer = array((n,), sizeof(double), 'd') cdef class Subtype(BaseType): """ >>> run_test(Subtype, 10) 0 """ cdef double[:] buffer2 def __cinit__(self, n): self.buffer2 = array((n,), sizeof(double), 'd') cdef class SubtypeWithUserDealloc(BaseType): """ >>> run_test(SubtypeWithUserDealloc, 10) 0 """ cdef double[:] buffer2 def __cinit__(self, n): self.buffer2 = array((n,), sizeof(double), 'd') def __dealloc__(self): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/memoryview/memoryview_inline_pxd.srctree0000644000175100001770000000157300000000000025154 0ustar00runnerdocker00000000000000# ticket: 1415 # Utility code from an inline function in a pxd file was not # correctly included in a pyx file that cimported it. # Do not add more to this test - it is intentionally minimal # to avoid including the utility code through other means PYTHON setup.py build_ext --inplace PYTHON -c "import uses_inline; uses_inline.main()" ######## setup.py ######## from distutils.core import setup from Cython.Distutils import build_ext from Cython.Distutils.extension import Extension setup( ext_modules = [ Extension("uses_inline", ["uses_inline.pyx"]), ], cmdclass={'build_ext': build_ext}, ) ######## has_inline.pxd ######## from libc.stdlib cimport malloc cdef inline double[::1] mview(size_t size): return malloc(size * sizeof(double)) ######## uses_inline.pyx ######## from has_inline cimport mview def main(): return mview(1) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/memoryview/memoryview_inplace_division.pyx0000644000175100001770000000104400000000000025504 0ustar00runnerdocker00000000000000# mode: run # tag: memoryview, cdivision, array cimport cython from cpython.array cimport array # make Cython aware of the array type def div_memoryview(int[:] A): """ >>> from array import array >>> x = array('i', [6]) >>> div_memoryview(x) >>> x[0] 3 """ with cython.cdivision(True): A[0] /= 2 def div_buffer(object[int, ndim=1] A): """ >>> from array import array >>> x = array('i', [6]) >>> div_buffer(x) >>> x[0] 3 """ with cython.cdivision(True): A[0] /= 2 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/memoryview/memoryview_no_binding_T3613.pyx0000644000175100001770000000061100000000000025072 0ustar00runnerdocker00000000000000# mode: compile # tag: memoryview # cython: binding=False # See GH 3613 - when memoryviews were compiled with binding off they ended up in an # inconsistent state where different directives were applied at different stages # of the pipeline import cython def f(double[:] a): pass @cython.binding(False) def g(double[:] a): pass @cython.binding(True) def h(double[:] a): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/memoryview/memoryview_no_withgil_check.pyx0000644000175100001770000000046100000000000025467 0ustar00runnerdocker00000000000000# mode: compile # cython: test_fail_if_c_code_has = __Pyx_ErrOccurredWithGIL # cython-generated memoryview code shouldn't resort to # __Pyx_ErrOccurredWithGIL for error checking (because it's inefficient # inside a nogil block) def assign(double[:] a, double[:] b): with nogil: a[:] = b[:] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/memoryview/memoryview_pep484_typing.pyx0000644000175100001770000000401600000000000024605 0ustar00runnerdocker00000000000000# mode: run # tag: pep484, memoryview cimport cython include "../buffers/mockbuffers.pxi" def get_int_2d(mslice: cython.int[:, :], i: cython.int, j: cython.int) -> cython.int: """ >>> C = IntMockBuffer("C", range(6), (2,3)) >>> get_int_2d(C, 1, 1) acquired C released C 4 Check negative indexing: >>> get_int_2d(C, -1, 0) acquired C released C 3 >>> get_int_2d(C, -1, -2) acquired C released C 4 >>> get_int_2d(C, -2, -3) acquired C released C 0 Out-of-bounds errors: >>> get_int_2d(C, 2, 0) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) >>> get_int_2d(C, 0, -4) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 1) """ buf = mslice return buf[i, j] def set_int_2d(mslice: cython.int[:, :], i: cython.int, j: cython.int, value: cython.int) -> cython.int: """ Uses get_int_2d to read back the value afterwards. For pure unit test, one should support reading in MockBuffer instead. >>> C = IntMockBuffer("C", range(6), (2,3)) >>> set_int_2d(C, 1, 1, 10) acquired C released C >>> get_int_2d(C, 1, 1) acquired C released C 10 Check negative indexing: >>> set_int_2d(C, -1, 0, 3) acquired C released C >>> get_int_2d(C, -1, 0) acquired C released C 3 >>> set_int_2d(C, -1, -2, 8) acquired C released C >>> get_int_2d(C, -1, -2) acquired C released C 8 >>> set_int_2d(C, -2, -3, 9) acquired C released C >>> get_int_2d(C, -2, -3) acquired C released C 9 Out-of-bounds errors: >>> set_int_2d(C, 2, 0, 19) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) >>> set_int_2d(C, 0, -4, 19) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 1) """ buf = mslice buf[i, j] = value ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/memoryview/memoryviewattrs.pyx0000644000175100001770000002012100000000000023160 0ustar00runnerdocker00000000000000# mode: run # tag: numpy cimport cython from cython.view cimport array import numpy as np cimport numpy as np def test_shape_stride_suboffset(): u''' >>> test_shape_stride_suboffset() 5 7 11 77 11 1 -1 -1 -1 5 7 11 1 5 35 -1 -1 -1 5 7 11 77 11 1 -1 -1 -1 ''' cdef char[:,:,:] larr = array((5,7,11), 1, 'c') print larr.shape[0], larr.shape[1], larr.shape[2] print larr.strides[0], larr.strides[1], larr.strides[2] print larr.suboffsets[0], larr.suboffsets[1], larr.suboffsets[2] print larr = array((5,7,11), 1, 'c', mode='fortran') print larr.shape[0], larr.shape[1], larr.shape[2] print larr.strides[0], larr.strides[1], larr.strides[2] print larr.suboffsets[0], larr.suboffsets[1], larr.suboffsets[2] print cdef char[:,:,:] c_contig = larr.copy() print c_contig.shape[0], c_contig.shape[1], c_contig.shape[2] print c_contig.strides[0], c_contig.strides[1], c_contig.strides[2] print c_contig.suboffsets[0], c_contig.suboffsets[1], c_contig.suboffsets[2] def test_copy_to(): u''' >>> test_copy_to() 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 ''' cdef int[:, :, :] from_mvs, to_mvs from_mvs = np.arange(8, dtype=np.int32).reshape(2,2,2) cdef int *from_data = from_mvs._data print ' '.join(str(from_data[i]) for i in range(2*2*2)) to_mvs = array((2,2,2), sizeof(int), 'i') to_mvs[...] = from_mvs # TODO Mark: remove this _data attribute cdef int *to_data = to_mvs._data print ' '.join(str(from_data[i]) for i in range(2*2*2)) print ' '.join(str(to_data[i]) for i in range(2*2*2)) def test_overlapping_copy(): """ >>> test_overlapping_copy() """ cdef int i, array[10] for i in range(10): array[i] = i cdef int[:] slice = array slice[...] = slice[::-1] for i in range(10): assert slice[i] == 10 - 1 - i def test_copy_return_type(): """ >>> test_copy_return_type() 60.0 60.0 """ cdef double[:, :, :] a = np.arange(5 * 5 * 5, dtype=np.float64).reshape(5, 5, 5) cdef double[:, ::1] c_contig = a[..., 0].copy() cdef double[::1, :] f_contig = a[..., 0].copy_fortran() print(c_contig[2, 2]) print(f_contig[2, 2]) def test_partly_overlapping(): """ >>> test_partly_overlapping() """ cdef int i, array[10] for i in range(10): array[i] = i cdef int[:] slice = array cdef int[:] slice2 = slice[:5] slice2[...] = slice[4:9] for i in range(5): assert slice2[i] == i + 4 @cython.nonecheck(True) def test_nonecheck1(): u''' >>> test_nonecheck1() Traceback (most recent call last): ... UnboundLocalError: local variable 'uninitialized' referenced before assignment ''' cdef int[:,:,:] uninitialized print uninitialized.is_c_contig() @cython.nonecheck(True) def test_nonecheck2(): u''' >>> test_nonecheck2() Traceback (most recent call last): ... UnboundLocalError: local variable 'uninitialized' referenced before assignment ''' cdef int[:,:,:] uninitialized print uninitialized.is_f_contig() @cython.nonecheck(True) def test_nonecheck3(): u''' >>> test_nonecheck3() Traceback (most recent call last): ... UnboundLocalError: local variable 'uninitialized' referenced before assignment ''' cdef int[:,:,:] uninitialized uninitialized.copy() @cython.nonecheck(True) def test_nonecheck4(): u''' >>> test_nonecheck4() Traceback (most recent call last): ... UnboundLocalError: local variable 'uninitialized' referenced before assignment ''' cdef int[:,:,:] uninitialized uninitialized.copy_fortran() @cython.nonecheck(True) def test_nonecheck5(): u''' >>> test_nonecheck5() Traceback (most recent call last): ... UnboundLocalError: local variable 'uninitialized' referenced before assignment ''' cdef int[:,:,:] uninitialized uninitialized._data def test_copy_mismatch(): u''' >>> test_copy_mismatch() Traceback (most recent call last): ... ValueError: got differing extents in dimension 0 (got 2 and 3) ''' cdef int[:,:,::1] mv1 = array((2,2,3), sizeof(int), 'i') cdef int[:,:,::1] mv2 = array((3,2,3), sizeof(int), 'i') mv1[...] = mv2 def test_is_contiguous(): u""" >>> test_is_contiguous() one sized is_c/f_contig True True is_c/f_contig False True f_contig.copy().is_c/f_contig True False f_contig.copy_fortran().is_c/f_contig False True one sized strided contig True True strided False """ cdef int[::1, :, :] fort_contig = array((1,1,1), sizeof(int), 'i', mode='fortran') cdef int[:,:,:] strided = fort_contig print 'one sized is_c/f_contig', fort_contig.is_c_contig(), fort_contig.is_f_contig() fort_contig = array((2,2,2), sizeof(int), 'i', mode='fortran') print 'is_c/f_contig', fort_contig.is_c_contig(), fort_contig.is_f_contig() print 'f_contig.copy().is_c/f_contig', fort_contig.copy().is_c_contig(), \ fort_contig.copy().is_f_contig() print 'f_contig.copy_fortran().is_c/f_contig', \ fort_contig.copy_fortran().is_c_contig(), \ fort_contig.copy_fortran().is_f_contig() print 'one sized strided contig', strided.is_c_contig(), strided.is_f_contig() print 'strided', strided[::2].is_c_contig() def call(): u''' >>> call() 1000 2000 3000 1000 2000 3000 3000 1 1 1000 ''' cdef int[::1] mv1, mv2, mv3 cdef array arr = array((3,), sizeof(int), 'i') mv1 = arr cdef int *data data = arr.data data[0] = 1000 data[1] = 2000 data[2] = 3000 print (mv1._data)[0] , (mv1._data)[1] , (mv1._data)[2] mv2 = mv1.copy() print (mv2._data)[0] print (mv2._data)[1] , (mv2._data)[2] mv3 = mv2 cdef int *mv3_data = mv3._data print (mv1._data)[2] mv3_data[0] = 1 print (mv3._data)[0] , (mv2._data)[0] , (mv1._data)[0] assert len(mv1) == 3 assert len(mv2) == 3 assert len(mv3) == 3 def two_dee(): u''' >>> two_dee() 1 2 3 4 -4 -4 1 2 3 -4 1 2 3 -4 ''' cdef long[:,::1] mv1, mv2, mv3 cdef array arr = array((2,2), sizeof(long), 'l') assert len(arr) == 2 try: _ = len(mv1) except UnboundLocalError: pass else: assert False, "UnboundLocalError not raised for uninitialised memory view" cdef long *arr_data arr_data = arr.data mv1 = arr arr_data[0] = 1 arr_data[1] = 2 arr_data[2] = 3 arr_data[3] = 4 print (mv1._data)[0] , (mv1._data)[1] , (mv1._data)[2] , (mv1._data)[3] mv2 = mv1 arr_data = mv2._data arr_data[3] = -4 print (mv2._data)[3] , (mv1._data)[3] mv3 = mv2.copy() print (mv2._data)[0] , (mv2._data)[1] , (mv2._data)[2] , (mv2._data)[3] print (mv3._data)[0] , (mv3._data)[1] , (mv3._data)[2] , (mv3._data)[3] def fort_two_dee(): u''' >>> fort_two_dee() 1 2 3 4 -4 -4 1 2 3 -4 1 3 2 -4 1 2 3 -4 ''' cdef array arr = array((2,2), sizeof(long), 'l', mode='fortran') cdef long[::1,:] mv1, mv2, mv4 cdef long[:, ::1] mv3 cdef long *arr_data arr_data = arr.data mv1 = arr arr_data[0] = 1 arr_data[1] = 2 arr_data[2] = 3 arr_data[3] = 4 print (mv1._data)[0], (mv1._data)[1], (mv1._data)[2], (mv1._data)[3] mv2 = mv1 arr_data = mv2._data arr_data[3] = -4 print (mv2._data)[3], (mv1._data)[3] mv3 = mv2.copy() print (mv2._data)[0], (mv2._data)[1], (mv2._data)[2], (mv2._data)[3] print (mv3._data)[0], (mv3._data)[1], (mv3._data)[2], (mv3._data)[3] mv4 = mv3.copy_fortran() print (mv4._data)[0], (mv4._data)[1], (mv4._data)[2], (mv4._data)[3] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/memoryview/memslice.pyx0000644000175100001770000017527300000000000021520 0ustar00runnerdocker00000000000000# mode: run # Test the behaviour of memoryview slicing and indexing, contiguity, etc. # Note: see also bufaccess.pyx from __future__ import unicode_literals from cpython.object cimport PyObject from cpython.ref cimport Py_INCREF, Py_DECREF, Py_CLEAR cimport cython from cython cimport view from cython.view cimport array from cython.parallel cimport prange, parallel from functools import wraps import gc import sys if sys.version_info[0] < 3: import __builtin__ as builtins else: import builtins try: from Cython.Tests.this_module_does_not_exist import * except ImportError: # Fails, but the existence of "import *" interacted badly with some utility code pass def testcase(func): @wraps(func) def wrapper(*args, **kwargs): gc.collect() result = func(*args, **kwargs) gc.collect() return result return wrapper include "../buffers/mockbuffers.pxi" include "../testsupport/cythonarrayutil.pxi" def _print_attributes(memview): print "shape: " + " ".join(map(str, memview.shape)) print "strides: " + " ".join([str(stride // memview.itemsize) for stride in memview.strides]) print "suboffsets: " + " ".join( [str(suboffset if suboffset < 0 else suboffset // memview.itemsize) for suboffset in memview.suboffsets]) # # Buffer acquire and release tests # def nousage(): """ The challenge here is just compilation. """ cdef int[:, :] buf @testcase def acquire_release(o1, o2): """ >>> A = IntMockBuffer("A", range(6)) >>> B = IntMockBuffer("B", range(6)) >>> acquire_release(A, B) acquired A acquired B released A released B >>> acquire_release(None, B) acquired B released B """ cdef int[:] buf buf = o1 buf = o2 @testcase def acquire_raise(o): """ Apparently, doctest won't handle mixed exceptions and print stats, so need to circumvent this. >>> A = IntMockBuffer("A", range(6)) >>> A.resetlog() >>> acquire_raise(A) Traceback (most recent call last): ... Exception: on purpose >>> A.printlog() acquired A released A """ cdef int[:] buf buf = o raise Exception("on purpose") @testcase def acquire_failure1(): """ >>> acquire_failure1() acquired working 0 3 0 3 released working """ cdef int[:] buf buf = IntMockBuffer("working", range(4)) print buf[0], buf[3] try: buf = ErrorBuffer() assert False except Exception: print buf[0], buf[3] @testcase def acquire_failure2(): """ >>> acquire_failure2() acquired working 0 3 0 3 released working """ cdef int[:] buf = IntMockBuffer("working", range(4)) print buf[0], buf[3] try: buf = ErrorBuffer() assert False except Exception: print buf[0], buf[3] @testcase def acquire_failure3(): """ >>> acquire_failure3() acquired working 0 3 0 3 released working """ cdef int[:] buf buf = IntMockBuffer("working", range(4)) print buf[0], buf[3] try: buf = object() assert False except Exception: print buf[0], buf[3] @testcase def acquire_nonbuffer1(first, second=None): """ >>> acquire_nonbuffer1(3) # doctest: +ELLIPSIS Traceback (most recent call last): ... TypeError:... 'int'... >>> acquire_nonbuffer1(type) # doctest: +ELLIPSIS Traceback (most recent call last): ... TypeError:... 'type'... >>> acquire_nonbuffer1(None, 2) # doctest: +ELLIPSIS Traceback (most recent call last): ... TypeError:... 'int'... >>> acquire_nonbuffer1(4, object()) # doctest: +ELLIPSIS Traceback (most recent call last): ... TypeError:... 'int'... """ cdef int[:] buf buf = first buf = second @testcase def acquire_nonbuffer2(): """ >>> acquire_nonbuffer2() acquired working 0 3 0 3 released working """ cdef int[:] buf = IntMockBuffer("working", range(4)) print buf[0], buf[3] try: buf = ErrorBuffer assert False except Exception: print buf[0], buf[3] @testcase def as_argument(int[:] bufarg, int n): """ >>> A = IntMockBuffer("A", range(6)) >>> as_argument(A, 6) acquired A 0 1 2 3 4 5 END released A """ cdef int i for i in range(n): print bufarg[i], print 'END' @testcase def as_argument_defval(int[:] bufarg=IntMockBuffer('default', range(6)), int n=6): """ >>> as_argument_defval() 0 1 2 3 4 5 END >>> A = IntMockBuffer("A", range(6)) >>> as_argument_defval(A, 6) acquired A 0 1 2 3 4 5 END released A """ cdef int i for i in range(n): print bufarg[i], print 'END' @testcase def cdef_assignment(obj, n): """ >>> A = IntMockBuffer("A", range(6)) >>> cdef_assignment(A, 6) acquired A 0 1 2 3 4 5 END released A """ cdef int[:] buf = obj cdef int i for i in range(n): print buf[i], print 'END' @testcase def forin_assignment(objs, int pick): """ >>> A = IntMockBuffer("A", range(6)) >>> B = IntMockBuffer("B", range(6)) >>> forin_assignment([A, B, A, A], 2) acquired A 2 acquired B released A 2 acquired A released B 2 acquired A released A 2 released A """ cdef int[:] buf for buf in objs: print buf[pick] @testcase def cascaded_buffer_assignment(obj): """ >>> A = IntMockBuffer("A", range(6)) >>> cascaded_buffer_assignment(A) acquired A released A """ cdef int[:] a, b a = b = obj @testcase def tuple_buffer_assignment1(a, b): """ >>> A = IntMockBuffer("A", range(6)) # , writable=False) >>> B = IntMockBuffer("B", range(6)) # , writable=False) >>> tuple_buffer_assignment1(A, B) acquired A acquired B released A released B """ cdef int[:] x, y x, y = a, b @testcase def tuple_buffer_assignment2(tup): """ >>> A = IntMockBuffer("A", range(6)) # , writable=False) >>> B = IntMockBuffer("B", range(6)) # , writable=False) >>> tuple_buffer_assignment2((A, B)) acquired A acquired B released A released B """ cdef int[:] x, y x, y = tup @testcase def explicitly_release_buffer(): """ >>> explicitly_release_buffer() acquired A released A After release """ cdef int[:] x = IntMockBuffer("A", range(10)) # , writable=False) del x print "After release" # # Getting items and index bounds checking # @testcase def get_int_2d(int[:, :] buf, int i, int j): """ >>> C = IntMockBuffer("C", range(6), (2,3)) >>> get_int_2d(C, 1, 1) acquired C released C 4 Check negative indexing: >>> get_int_2d(C, -1, 0) acquired C released C 3 >>> get_int_2d(C, -1, -2) acquired C released C 4 >>> get_int_2d(C, -2, -3) acquired C released C 0 Out-of-bounds errors: >>> get_int_2d(C, 2, 0) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) >>> get_int_2d(C, 0, -4) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 1) """ return buf[i, j] @testcase def get_int_2d_uintindex(int[:, :] buf, unsigned int i, unsigned int j): """ Unsigned indexing: >>> C = IntMockBuffer("C", range(6), (2,3)) # , writable=False) >>> get_int_2d_uintindex(C, 0, 0) acquired C released C 0 >>> get_int_2d_uintindex(C, 1, 2) acquired C released C 5 """ # This is most interesting with regards to the C code # generated. return buf[i, j] @testcase def set_int_2d(int[:, :] buf, int i, int j, int value): """ Uses get_int_2d to read back the value afterwards. For pure unit test, one should support reading in MockBuffer instead. >>> C = IntMockBuffer("C", range(6), (2,3)) >>> set_int_2d(C, 1, 1, 10) acquired C released C >>> get_int_2d(C, 1, 1) acquired C released C 10 Check negative indexing: >>> set_int_2d(C, -1, 0, 3) acquired C released C >>> get_int_2d(C, -1, 0) acquired C released C 3 >>> set_int_2d(C, -1, -2, 8) acquired C released C >>> get_int_2d(C, -1, -2) acquired C released C 8 >>> set_int_2d(C, -2, -3, 9) acquired C released C >>> get_int_2d(C, -2, -3) acquired C released C 9 Out-of-bounds errors: >>> set_int_2d(C, 2, 0, 19) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) >>> set_int_2d(C, 0, -4, 19) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 1) >>> C = IntMockBuffer("C", range(6), (2,3), writable=False) >>> set_int_2d(C, -2, -3, 9) Traceback (most recent call last): BufferError: Writable buffer requested from read-only mock: FORMAT | ND | STRIDES | WRITABLE """ buf[i, j] = value def _read_int2d(int[:, :] buf, int i, int j): return buf[i, j] @testcase def schar_index_vars(int[:, :] buf, signed char i, signed char j, int value): """ >>> C = IntMockBuffer("C", range(300*300), (300, 300)) # > sizeof(char) >>> schar_index_vars(C, 1, 1, 5) acquired C reading writing validated released C 301 >>> _read_int2d(C, 1, 1) # validate with int indices acquired C released C 5 >>> schar_index_vars(C, -1, 1, 6) acquired C reading writing validated released C 89701 >>> _read_int2d(C, -1, 1) # validate with int indices acquired C released C 6 >>> schar_index_vars(C, -1, -2, 7) acquired C reading writing validated released C 89998 >>> _read_int2d(C, -1, -2) # validate with int indices acquired C released C 7 >>> schar_index_vars(C, -2, -3, 8) acquired C reading writing validated released C 89697 >>> _read_int2d(C, -2, -3) # validate with int indices acquired C released C 8 >>> C = IntMockBuffer("C", range(6), (2, 3)) >>> schar_index_vars(C, 5, 1, 10) Traceback (most recent call last): IndexError: Out of bounds on buffer access (axis 0) >>> schar_index_vars(C, 1, 5, 10) Traceback (most recent call last): IndexError: Out of bounds on buffer access (axis 1) >>> schar_index_vars(C, -2, 1, 10) acquired C reading writing validated released C 1 >>> schar_index_vars(C, -3, 1, 10) Traceback (most recent call last): IndexError: Out of bounds on buffer access (axis 0) >>> schar_index_vars(C, 1, -3, 10) acquired C reading writing validated released C 3 >>> schar_index_vars(C, 1, -4, 10) Traceback (most recent call last): IndexError: Out of bounds on buffer access (axis 1) """ print("reading") old_value = buf[i, j] print("writing") buf[i, j] = value if buf[i, j] == value: print("validated") return old_value @testcase def uchar_index_vars(int[:, :] buf, unsigned char i, unsigned char j, int value): """ >>> C = IntMockBuffer("C", range(300*300), (300, 300)) # > sizeof(char) >>> uchar_index_vars(C, 1, 1, 5) acquired C reading writing validated released C 301 >>> _read_int2d(C, 1, 1) # validate with int indices acquired C released C 5 >>> C = IntMockBuffer("C", range(6), (2, 3)) >>> uchar_index_vars(C, 5, 1, 10) Traceback (most recent call last): IndexError: Out of bounds on buffer access (axis 0) >>> uchar_index_vars(C, 1, 5, 10) Traceback (most recent call last): IndexError: Out of bounds on buffer access (axis 1) """ print("reading") old_value = buf[i, j] print("writing") buf[i, j] = value if buf[i, j] == value: print("validated") return old_value @testcase def char_index_vars(int[:, :] buf, char i, char j, int value): """ >>> C = IntMockBuffer("C", range(300*300), (300, 300)) # > sizeof(char) >>> char_index_vars(C, 1, 1, 5) acquired C reading writing validated released C 301 >>> _read_int2d(C, 1, 1) # validate with int indices acquired C released C 5 >>> C = IntMockBuffer("C", range(6), (2, 3)) >>> char_index_vars(C, 5, 1, 10) Traceback (most recent call last): IndexError: Out of bounds on buffer access (axis 0) >>> char_index_vars(C, 1, 5, 10) Traceback (most recent call last): IndexError: Out of bounds on buffer access (axis 1) """ print("reading") old_value = buf[i, j] print("writing") buf[i, j] = value if buf[i, j] == value: print("validated") return old_value @testcase def list_comprehension(int[:] buf, len): """ >>> list_comprehension(IntMockBuffer(None, [1,2,3]), 3) # , writable=False), 3) 1|2|3 """ cdef int i print "|".join([str(buf[i]) for i in range(len)]) @testcase @cython.wraparound(False) def wraparound_directive(int[:] buf, int pos_idx, int neg_idx): """ Again, the most interesting thing here is to inspect the C source. >>> A = IntMockBuffer(None, range(4)) # , writable=False) >>> wraparound_directive(A, 2, -1) 5 >>> wraparound_directive(A, -1, 2) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) """ cdef int byneg with cython.wraparound(True): byneg = buf[neg_idx] return buf[pos_idx] + byneg # # Test all kinds of indexing and flags # @testcase def writable(obj): """ >>> R = UnsignedShortMockBuffer("R", range(27), shape=(3, 3, 3)) >>> writable(R) acquired R released R >>> [str(x) for x in R.received_flags] # Py2/3 ['FORMAT', 'ND', 'STRIDES', 'WRITABLE'] """ cdef unsigned short int[:, :, :] buf = obj buf[2, 2, 1] = 23 @testcase def strided(const int[:] buf): """ >>> A = IntMockBuffer("A", range(4), writable=False) >>> strided(A) acquired A released A 2 >>> [str(x) for x in A.received_flags] # Py2/3 ['FORMAT', 'ND', 'STRIDES'] Check that the suboffsets were patched back prior to release. >>> A.release_ok True """ return buf[2] @testcase def c_contig(const int[::1] buf): """ >>> A = IntMockBuffer(None, range(4), writable=False) >>> c_contig(A) 2 >>> [str(x) for x in A.received_flags] ['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS'] """ return buf[2] @testcase def c_contig_2d(int[:, ::1] buf): """ Multi-dim has separate implementation >>> A = IntMockBuffer(None, range(12), shape=(3,4)) # , writable=False) >>> c_contig_2d(A) 7 >>> [str(x) for x in A.received_flags] ['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS', 'WRITABLE'] """ return buf[1, 3] @testcase def f_contig(int[::1, :] buf): """ >>> A = IntMockBuffer(None, range(4), shape=(2, 2), strides=(1, 2)) # , writable=False) >>> f_contig(A) 2 >>> [str(x) for x in A.received_flags] ['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS', 'WRITABLE'] """ return buf[0, 1] @testcase def f_contig_2d(int[::1, :] buf): """ Must set up strides manually to ensure Fortran ordering. >>> A = IntMockBuffer(None, range(12), shape=(4,3), strides=(1, 4)) # , writable=False) >>> f_contig_2d(A) 7 >>> [str(x) for x in A.received_flags] ['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS', 'WRITABLE'] """ return buf[3, 1] @testcase def generic(int[::view.generic, ::view.generic] buf1, int[::view.generic, ::view.generic] buf2): """ >>> A = IntMockBuffer("A", [[0,1,2], [3,4,5], [6,7,8]]) >>> B = IntMockBuffer("B", [[0,1,2], [3,4,5], [6,7,8]], shape=(3, 3), strides=(1, 3)) >>> generic(A, B) acquired A acquired B 4 4 10 11 released A released B >>> [str(x) for x in A.received_flags] ['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE'] >>> [str(x) for x in B.received_flags] ['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE'] """ print buf1[1, 1] print buf2[1, 1] buf1[2, -1] = 10 buf2[2, -1] = 11 print buf1[2, 2] print buf2[2, 2] # Note: disabled. generic_contiguous isn't very useful (you have to check suboffsets, # might as well multiply with strides) # def generic_contig(int[::view.generic_contiguous, :] buf1, # int[::view.generic_contiguous, :] buf2): # """ # >>> A = IntMockBuffer("A", [[0,1,2], [3,4,5], [6,7,8]]) # >>> B = IntMockBuffer("B", [[0,1,2], [3,4,5], [6,7,8]], shape=(3, 3), strides=(1, 3)) # >>> generic_contig(A, B) # acquired A # acquired B # 4 # 4 # 10 # 11 # released A # released B # >>> [str(x) for x in A.received_flags] # ['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE'] # >>> [str(x) for x in B.received_flags] # ['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE'] # """ # print buf1[1, 1] # print buf2[1, 1] # # buf1[2, -1] = 10 # buf2[2, -1] = 11 # # print buf1[2, 2] # print buf2[2, 2] @testcase def indirect_strided_and_contig( int[::view.indirect, ::view.strided] buf1, int[::view.indirect, ::view.contiguous] buf2): """ >>> A = IntMockBuffer("A", [[0,1,2], [3,4,5], [6,7,8]]) >>> B = IntMockBuffer("B", [[0,1,2], [3,4,5], [6,7,8]], shape=(3, 3), strides=(1, 3)) >>> indirect_strided_and_contig(A, B) acquired A acquired B 4 4 10 11 released A released B >>> [str(x) for x in A.received_flags] ['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE'] >>> [str(x) for x in B.received_flags] ['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE'] """ print buf1[1, 1] print buf2[1, 1] buf1[2, -1] = 10 buf2[2, -1] = 11 print buf1[2, 2] print buf2[2, 2] @testcase def indirect_contig( int[::view.indirect_contiguous, ::view.contiguous] buf1, int[::view.indirect_contiguous, ::view.generic] buf2): """ >>> A = IntMockBuffer("A", [[0,1,2], [3,4,5], [6,7,8]]) >>> B = IntMockBuffer("B", [[0,1,2], [3,4,5], [6,7,8]], shape=(3, 3), strides=(1, 3)) >>> indirect_contig(A, B) acquired A acquired B 4 4 10 11 released A released B >>> [str(x) for x in A.received_flags] ['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE'] >>> [str(x) for x in B.received_flags] ['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE'] """ print buf1[1, 1] print buf2[1, 1] buf1[2, -1] = 10 buf2[2, -1] = 11 print buf1[2, 2] print buf2[2, 2] # # Test compiler options for bounds checking. We create an array with a # safe "boundary" (memory # allocated outside of what it published) and then check whether we get back # what we stored in the memory or an error. @testcase def safe_get(int[:] buf, int idx): """ >>> A = IntMockBuffer(None, range(10), shape=(3,), offset=5) # , writable=False) Validate our testing buffer... >>> safe_get(A, 0) 5 >>> safe_get(A, 2) 7 >>> safe_get(A, -3) 5 Access outside it. This is already done above for bounds check testing but we include it to tell the story right. >>> safe_get(A, -4) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) >>> safe_get(A, 3) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) """ return buf[idx] @testcase @cython.boundscheck(False) # outer decorators should take precedence @cython.boundscheck(True) def unsafe_get(int[:] buf, int idx): """ Access outside of the area the buffer publishes. >>> A = IntMockBuffer(None, range(10), shape=(3,), offset=5) # , writable=False) >>> unsafe_get(A, -4) 4 >>> unsafe_get(A, -5) 3 >>> unsafe_get(A, 3) 8 """ return buf[idx] @testcase def mixed_get(int[:] buf, int unsafe_idx, int safe_idx): """ >>> A = IntMockBuffer(None, range(10), shape=(3,), offset=5) # , writable=False) >>> mixed_get(A, -4, 0) (4, 5) >>> mixed_get(A, 0, -4) Traceback (most recent call last): ... IndexError: Out of bounds on buffer access (axis 0) """ with cython.boundscheck(False): one = buf[unsafe_idx] with cython.boundscheck(True): two = buf[safe_idx] return (one, two) # # Testing that accessing data using various types of buffer access # all works. # def printbuf_int(int[:] buf, shape): # Utility func cdef int i for i in range(shape[0]): print buf[i], print 'END' @testcase def printbuf_int_2d(o, shape): """ Strided: >>> printbuf_int_2d(IntMockBuffer("A", range(6), (2,3), writable=False), (2,3)) acquired A 0 1 2 END 3 4 5 END released A >>> printbuf_int_2d(IntMockBuffer("A", range(100), (3,3), strides=(20,5), writable=False), (3,3)) acquired A 0 5 10 END 20 25 30 END 40 45 50 END released A Indirect: >>> printbuf_int_2d(IntMockBuffer("A", [[1,2],[3,4]], writable=False), (2,2)) acquired A 1 2 END 3 4 END released A """ # should make shape builtin cdef const int[::view.generic, ::view.generic] buf buf = o cdef int i, j for i in range(shape[0]): for j in range(shape[1]): print buf[i, j], print 'END' @testcase def printbuf_float(o, shape): """ >>> printbuf_float(FloatMockBuffer("F", [1.0, 1.25, 0.75, 1.0], writable=False), (4,)) acquired F 1.0 1.25 0.75 1.0 END released F """ # should make shape builtin cdef const float[:] buf buf = o cdef int i, j for i in range(shape[0]): print buf[i], print "END" # # Test assignments # @testcase def inplace_operators(int[:] buf): """ >>> buf = IntMockBuffer(None, [2, 2]) >>> inplace_operators(buf) >>> printbuf_int(buf, (2,)) 0 3 END """ cdef int j = 0 buf[1] += 1 buf[j] *= 2 buf[0] -= 4 # # Typedefs # # Test three layers of typedefs going through a h file for plain int, and # simply a header file typedef for floats and unsigned. ctypedef int td_cy_int cdef extern from "bufaccess.h": ctypedef td_cy_int td_h_short # Defined as short, but Cython doesn't know this! ctypedef float td_h_double # Defined as double ctypedef unsigned int td_h_ushort # Defined as unsigned short ctypedef td_h_short td_h_cy_short @testcase def printbuf_td_cy_int(td_cy_int[:] buf, shape): """ >>> printbuf_td_cy_int(IntMockBuffer(None, range(3)), (3,)) # , writable=False), (3,)) 0 1 2 END >>> printbuf_td_cy_int(ShortMockBuffer(None, range(3)), (3,)) # , writable=False), (3,)) Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'td_cy_int' but got 'short' """ cdef int i for i in range(shape[0]): print buf[i], print 'END' @testcase def printbuf_td_h_short(td_h_short[:] buf, shape): """ >>> printbuf_td_h_short(ShortMockBuffer(None, range(3)), (3,)) # , writable=False), (3,)) 0 1 2 END >>> printbuf_td_h_short(IntMockBuffer(None, range(3)), (3,)) # , writable=False), (3,)) Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'td_h_short' but got 'int' """ cdef int i for i in range(shape[0]): print buf[i], print 'END' @testcase def printbuf_td_h_cy_short(const td_h_cy_short[:] buf, shape): """ >>> printbuf_td_h_cy_short(ShortMockBuffer(None, range(3), writable=False), (3,)) 0 1 2 END >>> printbuf_td_h_cy_short(IntMockBuffer(None, range(3), writable=False), (3,)) Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'const td_h_cy_short' but got 'int' """ cdef int i for i in range(shape[0]): print buf[i], print 'END' @testcase def printbuf_td_h_ushort(const td_h_ushort[:] buf, shape): """ >>> printbuf_td_h_ushort(UnsignedShortMockBuffer(None, range(3), writable=False), (3,)) 0 1 2 END >>> printbuf_td_h_ushort(ShortMockBuffer(None, range(3), writable=False), (3,)) Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'const td_h_ushort' but got 'short' """ cdef int i for i in range(shape[0]): print buf[i], print 'END' @testcase def printbuf_td_h_double(const td_h_double[:] buf, shape): """ >>> printbuf_td_h_double(DoubleMockBuffer(None, [0.25, 1, 3.125], writable=False), (3,)) 0.25 1.0 3.125 END >>> printbuf_td_h_double(FloatMockBuffer(None, [0.25, 1, 3.125], writable=False), (3,)) Traceback (most recent call last): ... ValueError: Buffer dtype mismatch, expected 'const td_h_double' but got 'float' """ cdef int i for i in range(shape[0]): print buf[i], print 'END' # # Object access # def addref(*args): for item in args: Py_INCREF(item) def decref(*args): for item in args: Py_DECREF(item) @cython.binding(False) @cython.always_allow_keywords(False) def get_refcount(x): return (x).ob_refcnt @testcase def printbuf_object(object[:] buf, shape): """ Only play with unique objects, interned numbers etc. will have unpredictable refcounts. ObjectMockBuffer doesn't do anything about increfing/decrefing, we to the "buffer implementor" refcounting directly in the testcase. >>> _x = 1 >>> a, b, c = "globally_unique_string_2323412" + "3" * _x, {4:23}, [34,3] >>> get_refcount(a), get_refcount(b), get_refcount(c) (2, 2, 2) >>> A = ObjectMockBuffer(None, [a, b, c]) # , writable=False) >>> printbuf_object(A, (3,)) 'globally_unique_string_23234123' 2 {4: 23} 2 [34, 3] 2 """ cdef int i for i in range(shape[0]): print repr(buf[i]), (buf[i]).ob_refcnt @testcase def assign_to_object(object[:] buf, int idx, obj): """ See comments on printbuf_object above. >>> a, b = [1, 2, 3], [4, 5, 6] >>> get_refcount(a), get_refcount(b) (2, 2) >>> addref(a) >>> A = ObjectMockBuffer(None, [1, a]) # 1, ...,otherwise it thinks nested lists... >>> get_refcount(a), get_refcount(b) (3, 2) >>> assign_to_object(A, 1, b) >>> get_refcount(a), get_refcount(b) (2, 3) >>> decref(b) """ buf[idx] = obj @testcase def assign_temporary_to_object(object[:] buf): """ See comments on printbuf_object above. >>> a, b = [1, 2, 3], {4:23} >>> get_refcount(a) 2 >>> addref(a) >>> A = ObjectMockBuffer(None, [b, a]) >>> get_refcount(a) 3 >>> assign_temporary_to_object(A) >>> get_refcount(a) 2 >>> printbuf_object(A, (2,)) {4: 23} 2 {1: 8} 2 To avoid leaking a reference in our testcase we need to replace the temporary with something we can manually decref :-) >>> assign_to_object(A, 1, a) >>> decref(a) """ buf[1] = {3-2: 2+(2*4)-2} @testcase def check_object_nulled_1d(object[:] buf, int idx, obj): """ See comments on printbuf_object above. >>> a = object() >>> rc1 = get_refcount(a) >>> A = ObjectMockBuffer(None, [a, a]) >>> check_object_nulled_1d(A, 0, a) >>> check_object_nulled_1d(A, 1, a) >>> A = ObjectMockBuffer(None, [a, a, a, a], strides=(2,)) >>> check_object_nulled_1d(A, 0, a) # only 0 due to stride >>> get_refcount(a) == rc1 True """ cdef ObjectMockBuffer omb = buf.base cdef PyObject **data = (omb.buffer) Py_CLEAR(data[idx]) res = buf[idx] # takes None buf[idx] = obj return res @testcase def check_object_nulled_2d(object[:, ::1] buf, int idx1, int idx2, obj): """ See comments on printbuf_object above. >>> a = object() >>> rc1 = get_refcount(a) >>> A = ObjectMockBuffer(None, [a, a, a, a], shape=(2, 2)) >>> check_object_nulled_2d(A, 0, 0, a) >>> check_object_nulled_2d(A, 1, 1, a) >>> get_refcount(a) == rc1 True """ cdef ObjectMockBuffer omb = buf.base cdef PyObject **data = (omb.buffer) Py_CLEAR(data[idx1 + 2*idx2]) res = buf[idx1, idx2] # takes None buf[idx1, idx2] = obj return res # # Test __cythonbufferdefaults__ # @testcase def bufdefaults1(int[:] buf): """ For IntStridedMockBuffer, mode should be "strided" by defaults which should show up in the flags. >>> A = IntStridedMockBuffer("A", range(10)) # , writable=False) >>> bufdefaults1(A) acquired A released A >>> [str(x) for x in A.received_flags] ['FORMAT', 'ND', 'STRIDES', 'WRITABLE'] """ pass @testcase def basic_struct(MyStruct[:] buf): """ See also buffmt.pyx >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)])) 1 2 3 4 5 >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ccqii")) 1 2 3 4 5 """ print buf[0].a, buf[0].b, buf[0].c, buf[0].d, buf[0].e @testcase def const_struct(const MyStruct[:] buf): """ See also buffmt.pyx >>> const_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], writable=False)) 1 2 3 4 5 >>> const_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ccqii", writable=False)) 1 2 3 4 5 """ print buf[0].a, buf[0].b, buf[0].c, buf[0].d, buf[0].e @testcase def nested_struct(NestedStruct[:] buf): """ See also buffmt.pyx >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)])) 1 2 3 4 5 >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="T{ii}T{2i}i")) 1 2 3 4 5 """ print buf[0].x.a, buf[0].x.b, buf[0].y.a, buf[0].y.b, buf[0].z @testcase def const_nested_struct(const NestedStruct[:] buf): """ See also buffmt.pyx >>> const_nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], writable=False)) 1 2 3 4 5 >>> const_nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="T{ii}T{2i}i", writable=False)) 1 2 3 4 5 """ print buf[0].x.a, buf[0].x.b, buf[0].y.a, buf[0].y.b, buf[0].z @testcase def packed_struct(PackedStruct[:] buf): """ See also buffmt.pyx >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)])) 1 2 >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c^i}")) 1 2 >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c=i}")) 1 2 """ print buf[0].a, buf[0].b @testcase def const_packed_struct(const PackedStruct[:] buf): """ See also buffmt.pyx >>> const_packed_struct(PackedStructMockBuffer(None, [(1, 2)], writable=False)) 1 2 >>> const_packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c^i}", writable=False)) 1 2 >>> const_packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c=i}", writable=False)) 1 2 """ print buf[0].a, buf[0].b @testcase def nested_packed_struct(NestedPackedStruct[:] buf): """ See also buffmt.pyx >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)])) 1 2 3 4 5 >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ci^ci@i")) 1 2 3 4 5 >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="^c@i^ci@i")) 1 2 3 4 5 """ print buf[0].a, buf[0].b, buf[0].sub.a, buf[0].sub.b, buf[0].c @testcase def const_nested_packed_struct(const NestedPackedStruct[:] buf): """ See also buffmt.pyx >>> const_nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], writable=False)) 1 2 3 4 5 >>> const_nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ci^ci@i", writable=False)) 1 2 3 4 5 >>> const_nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="^c@i^ci@i", writable=False)) 1 2 3 4 5 """ print buf[0].a, buf[0].b, buf[0].sub.a, buf[0].sub.b, buf[0].c @testcase def complex_dtype(long double complex[:] buf): """ >>> complex_dtype(LongComplexMockBuffer(None, [(0, -1)])) # , writable=False)) -1j """ print buf[0] @testcase def complex_inplace(long double complex[:] buf): """ >>> complex_inplace(LongComplexMockBuffer(None, [(0, -1)])) (1+1j) """ buf[0] = buf[0] + 1 + 2j print buf[0] @testcase def complex_struct_dtype(LongComplex[:] buf): """ Note that the format string is "Zg" rather than "2g", yet a struct is accessed. >>> complex_struct_dtype(LongComplexMockBuffer(None, [(0, -1)])) # , writable=False)) 0.0 -1.0 """ print buf[0].real, buf[0].imag @testcase def complex_struct_inplace(LongComplex[:] buf): """ >>> complex_struct_inplace(LongComplexMockBuffer(None, [(0, -1)])) 1.0 1.0 """ buf[0].real += 1 buf[0].imag += 2 print buf[0].real, buf[0].imag # # Nogil # @testcase @cython.boundscheck(False) def buffer_nogil(): """ >>> buffer_nogil() (10, 10) """ cdef int[:] buf = IntMockBuffer(None, [1,2,3]) cdef int[:] buf2 = IntMockBuffer(None, [4,5,6]) with nogil: buf[1] = 10 buf2 = buf return buf[1], buf2[1] # ### Test cdef functions # class UniqueObject(object): def __init__(self, value): self.value = value def __repr__(self): return self.value objs = [[UniqueObject("spam")], [UniqueObject("ham")], [UniqueObject("eggs")]] addref(*[obj for L in objs for obj in L]) cdef cdef_function(int[:] buf1, object[::view.indirect, :] buf2 = ObjectMockBuffer(None, objs)): print 'cdef called' print buf1[6], buf2[1, 0] buf2[1, 0] = UniqueObject("eggs") @testcase def test_cdef_function(o1, o2=None): """ >>> A = IntMockBuffer("A", range(10)) >>> test_cdef_function(A) acquired A cdef called 6 ham released A acquired A cdef called 6 eggs released A >>> L = [[x] for x in range(25)] >>> addref(*[obj for mylist in L for obj in mylist]) >>> B = ObjectMockBuffer("B", L, shape=(5, 5)) >>> test_cdef_function(A, B) acquired A cdef called 6 eggs released A acquired A cdef called 6 eggs released A acquired A acquired B cdef called 6 1 released A released B """ cdef_function(o1) cdef_function(o1) if o2: cdef_function(o1, o2) cdef int[:] global_A = IntMockBuffer("Global_A", range(10)) addref(*[obj for L in objs for obj in L]) cdef object[::view.indirect, :] global_B = ObjectMockBuffer(None, objs) cdef cdef_function2(int[:] buf1, object[::view.indirect, :] buf2 = global_B): print 'cdef2 called' print buf1[6], buf2[1, 0] buf2[1, 0] = UniqueObject("eggs") @testcase def test_cdef_function2(): """ >>> test_cdef_function2() cdef2 called 6 ham eggs cdef2 called 6 eggs """ cdef int[:] A = global_A cdef object[::view.indirect, :] B = global_B cdef_function2(A, B) del A del B print global_B[1, 0] cdef_function2(global_A, global_B) @testcase def test_generic_slicing(arg, indirect=False): """ Test simple slicing >>> test_generic_slicing(IntMockBuffer("A", range(8 * 14 * 11), shape=(8, 14, 11))) # , writable=False)) acquired A 3 9 2 308 -11 1 -1 -1 -1 released A Test direct slicing, negative slice oob in dim 2 >>> test_generic_slicing(IntMockBuffer("A", range(1 * 2 * 3), shape=(1, 2, 3))) # , writable=False)) acquired A 0 0 2 12 -3 1 -1 -1 -1 released A Test indirect slicing >>> test_generic_slicing(IntMockBuffer("A", shape_5_3_4_list, shape=(5, 3, 4)), indirect=True) # , writable=False), indirect=True) acquired A 2 0 2 0 1 -1 released A >>> test_generic_slicing(IntMockBuffer("A", shape_9_14_21_list, shape=(9, 14, 21)), indirect=True) # , writable=False), indirect=True) acquired A 3 9 2 10 1 -1 released A """ cdef int[::view.generic, ::view.generic, :] a = arg cdef int[::view.generic, ::view.generic, :] b = a[2:8:2, -4:1:-1, 1:3] print b.shape[0], b.shape[1], b.shape[2] if indirect: print b.suboffsets[0] // sizeof(int *), print b.suboffsets[1] // sizeof(int), print b.suboffsets[2] else: print_int_offsets(b.strides[0], b.strides[1], b.strides[2]) print_int_offsets(b.suboffsets[0], b.suboffsets[1], b.suboffsets[2]) cdef int i, j, k for i in range(b.shape[0]): for j in range(b.shape[1]): for k in range(b.shape[2]): itemA = a[2 + 2 * i, -4 - j, 1 + k] itemB = b[i, j, k] assert itemA == itemB, (i, j, k, itemA, itemB) @testcase def test_indirect_slicing(arg): """ Test indirect slicing >>> test_indirect_slicing(IntMockBuffer("A", shape_5_3_4_list, shape=(5, 3, 4))) # , writable=False)) acquired A 5 3 2 0 0 -1 58 56 58 index away indirect 58 58 index away generic 58 58 released A >>> test_indirect_slicing(IntMockBuffer("A", shape_9_14_21_list, shape=(9, 14, 21))) # , writable=False)) acquired A 5 14 3 0 16 -1 2412 2410 2412 index away indirect 2412 2412 index away generic 2412 2412 released A """ cdef int[::view.indirect, ::view.indirect, :] a = arg cdef int[::view.indirect, ::view.indirect, :] b = a[-5:, ..., -5:100:2] cdef int[::view.generic , :: view.generic, :] generic_b = a[-5:, ..., -5:100:2] cdef int[::view.indirect, ::view.indirect] c = b[..., 0] # try indexing away leading indirect dimensions cdef int[::view.indirect, :] d = b[4] cdef int[:] e = b[4, 2] cdef int[::view.generic, :] generic_d = generic_b[4] cdef int[:] generic_e = generic_b[4, 2] print b.shape[0], b.shape[1], b.shape[2] print b.suboffsets[0] // sizeof(int *), print b.suboffsets[1] // sizeof(int), print b.suboffsets[2] print b[4, 2, 1] print c[4, 2] # test adding offset from last dimension to suboffset print b[..., 1][4, 2] print "index away indirect" print d[2, 1] print e[1] print "index away generic" print generic_d[2, 1] print generic_e[1] cdef class TestIndexSlicingDirectIndirectDims(object): "Test a int[:, ::view.indirect, :] slice" cdef Py_ssize_t[3] shape, strides, suboffsets cdef int[5] c_array cdef int *myarray[5][5] cdef bytes format def __init__(self): cdef int i self.c_array[3] = 20 self.myarray[1][2] = self.c_array for i in range(3): self.shape[i] = 5 self.strides[0] = sizeof(int *) * 5 self.strides[1] = sizeof(int *) self.strides[2] = sizeof(int) self.suboffsets[0] = -1 self.suboffsets[1] = 0 self.suboffsets[2] = -1 self.format = b"i" def __getbuffer__(self, Py_buffer *info, int flags): info.buf = self.myarray info.len = 5 * 5 * 5 info.ndim = 3 info.shape = self.shape info.strides = self.strides info.suboffsets = self.suboffsets info.itemsize = sizeof(int) info.readonly = 0 info.obj = self info.format = self.format @testcase def test_index_slicing_away_direct_indirect(): """ >>> test_index_slicing_away_direct_indirect() 20 20 20 20 20 20 20 20 All dimensions preceding dimension 1 must be indexed and not sliced """ cdef int[:, ::view.indirect, :] a = TestIndexSlicingDirectIndirectDims() cdef object a_obj = a print a[1][2][3] print a[1, 2, 3] print a[1, 2][3] print a[..., 3][1, 2] print print a_obj[1][2][3] print a_obj[1, 2, 3] print a_obj[1, 2][3] print a_obj[..., 3][1, 2] try: print a_obj[1:, 2][3] except IndexError, e: print e.args[0] @testcase def test_direct_slicing(arg): """ Fused types would be convenient to test this stuff! Test simple slicing >>> test_direct_slicing(IntMockBuffer("A", range(8 * 14 * 11), shape=(8, 14, 11))) # , writable=False)) acquired A 3 9 2 308 -11 1 -1 -1 -1 released A Test direct slicing, negative slice oob in dim 2 >>> test_direct_slicing(IntMockBuffer("A", range(1 * 2 * 3), shape=(1, 2, 3))) # , writable=False)) acquired A 0 0 2 12 -3 1 -1 -1 -1 released A """ cdef int[:, :, ::1] a = arg cdef int[:, :, :] b = a[2:8:2, -4:1:-1, 1:3] print b.shape[0], b.shape[1], b.shape[2] print_int_offsets(b.strides[0], b.strides[1], b.strides[2]) print_int_offsets(b.suboffsets[0], b.suboffsets[1], b.suboffsets[2]) cdef int i, j, k for i in range(b.shape[0]): for j in range(b.shape[1]): for k in range(b.shape[2]): itemA = a[2 + 2 * i, -4 - j, 1 + k] itemB = b[i, j, k] assert itemA == itemB, (i, j, k, itemA, itemB) @testcase def test_slicing_and_indexing(arg): """ >>> a = IntStridedMockBuffer("A", range(10 * 3 * 5), shape=(10, 3, 5)) # , writable=False) >>> test_slicing_and_indexing(a) acquired A 5 2 15 2 126 113 [111] released A """ cdef int[:, :, :] a = arg cdef int[:, :] b = a[-5:, 1, 1::2] cdef int[:, :] c = b[4:1:-1, ::-1] cdef int[:] d = c[2, 1:2] print b.shape[0], b.shape[1] print_int_offsets(b.strides[0], b.strides[1]) cdef int i, j for i in range(b.shape[0]): for j in range(b.shape[1]): itemA = a[-5 + i, 1, 1 + 2 * j] itemB = b[i, j] assert itemA == itemB, (i, j, itemA, itemB) print c[1, 1], c[2, 0] print [d[i] for i in range(d.shape[0])] @testcase def test_oob(): """ >>> test_oob() Traceback (most recent call last): ... IndexError: Index out of bounds (axis 1) """ cdef int[:, :] a = IntMockBuffer("A", range(4 * 9), shape=(4, 9)) # , writable=False) print a[:, 20] cdef int nogil_oob(int[:, :] a) except 0 nogil: a[100, 9:] return 1 @testcase def test_nogil_oob1(): """ A is acquired at the beginning of the function and released at the end. B is acquired as a temporary and as such is immediately released in the except clause. >>> test_nogil_oob1() acquired A acquired B released B Index out of bounds (axis 0) Index out of bounds (axis 0) released A """ cdef int[:, :] a = IntMockBuffer("A", range(4 * 9), shape=(4, 9)) try: nogil_oob(IntMockBuffer("B", range(4 * 9), shape=(4, 9))) except IndexError, e: print e.args[0] try: with nogil: nogil_oob(a) except IndexError, e: print e.args[0] @testcase def test_nogil_oob2(): """ >>> test_nogil_oob2() Traceback (most recent call last): ... IndexError: Index out of bounds (axis 0) """ cdef int[:, :] a = IntMockBuffer("A", range(4 * 9), shape=(4, 9)) # , writable=False) with nogil: a[100, 9:] @cython.boundscheck(False) cdef int cdef_nogil(int[:, :] a) except 0 nogil: cdef int i, j cdef int[:, :] b = a[::-1, 3:10:2] for i in range(b.shape[0]): for j in range(b.shape[1]): b[i, j] = -b[i, j] return len(a) @testcase def test_nogil(): """ >>> test_nogil() acquired A released A acquired A -25 released A """ _a = IntMockBuffer("A", range(4 * 9), shape=(4, 9)) assert cdef_nogil(_a) == 4 cdef int[:, :] a = _a print a[2, 7] cdef int length with nogil: length = cdef_nogil(a) assert length == 4 @testcase def test_convert_slicenode_to_indexnode(): """ When indexing with a[i:j] a SliceNode gets created instead of an IndexNode, which forces coercion to object and back. This would not only be inefficient, but it would also not compile in nogil mode. So instead we mutate it into an IndexNode. >>> test_convert_slicenode_to_indexnode() acquired A 2 released A """ cdef int[:] a = IntMockBuffer("A", range(10), shape=(10,)) # , writable=False) with nogil: a = a[2:4] print a[0] @testcase @cython.boundscheck(False) @cython.wraparound(False) def test_memslice_prange(arg): """ >>> test_memslice_prange(IntMockBuffer("A", range(400), shape=(20, 4, 5))) # FIXME: , writable=False)) acquired A released A >>> test_memslice_prange(IntMockBuffer("A", range(200), shape=(100, 2, 1))) # FIXME: , writable=False)) acquired A released A """ cdef int[:, :, :] src, dst src = arg dst = array(( src).shape, sizeof(int), format="i") cdef int i, j, k for i in prange(src.shape[0], nogil=True): for j in range(src.shape[1]): for k in range(src.shape[2]): dst[i, j, k] = src[i, j, k] for i in range(src.shape[0]): for j in range(src.shape[1]): for k in range(src.shape[2]): assert src[i, j, k] == dst[i, j, k], (src[i, j, k] == dst[i, j, k]) @testcase def test_clean_temps_prange(int[:, :] buf): """ Try to access a buffer out of bounds in a parallel section, and make sure any temps used by the slicing processes are correctly counted. >>> A = IntMockBuffer("A", range(100), (10, 10)) >>> test_clean_temps_prange(A) acquired A released A """ cdef int i try: for i in prange(buf.shape[0], nogil=True): buf[1:10, 20] = 0 except IndexError: pass @testcase def test_clean_temps_parallel(int[:, :] buf): """ Try to access a buffer out of bounds in a parallel section, and make sure any temps used by the slicing processes are correctly counted. >>> A = IntMockBuffer("A", range(100), (10, 10)) >>> test_clean_temps_parallel(A) acquired A released A """ cdef int i try: with nogil, parallel(): try: with gil: pass for i in prange(buf.shape[0]): buf[1:10, 20] = 0 finally: buf[1:10, 20] = 0 except IndexError: pass # Test arrays in structs cdef struct ArrayStruct: int ints[10] char chars[3] cdef packed struct PackedArrayStruct: int ints[10] char chars[3] cdef fused FusedStruct: ArrayStruct PackedArrayStruct @testcase def test_memslice_struct_with_arrays(): """ >>> test_memslice_struct_with_arrays() abc abc """ cdef ArrayStruct[10] a1 cdef PackedArrayStruct[10] a2 test_structs_with_arr(a1) test_structs_with_arr(a2) cdef test_structs_with_arr(FusedStruct array[10]): cdef FusedStruct[:] myslice1, myslice2, myslice3, myslice4 cdef int i, j myslice1 = array for i in range(10): for j in range(10): myslice1[i].ints[j] = i for j in range(3): myslice1[i].chars[j] = 97 + j if (2, 7) <= sys.version_info[:2] < (3, 3): size1 = sizeof(FusedStruct) size2 = len(builtins.memoryview(myslice1)[0]) assert size1 == size2, (size1, size2, builtins.memoryview(myslice1).format) myslice2 = builtins.memoryview(myslice1) for i in range(10): assert myslice2[i].ints[i] == myslice1[i].ints[i] assert myslice2[i].chars[i] == myslice1[i].chars[i] myslice3 = myslice1 myslice4 = myslice1 for i in range(10): for j in range(10): assert myslice3[i].ints[j] == myslice4[i].ints[j] == myslice1[i].ints[j] for j in range(3): assert myslice3[i].chars[j] == myslice4[i].chars[j] == myslice1[i].chars[j] print myslice1[0].chars[:3].decode('ascii') cdef struct TestAttrs: int int_attrib char char_attrib @testcase def test_struct_attributes_format(): """ >>> test_struct_attributes_format() T{i:int_attrib:c:char_attrib:} """ cdef TestAttrs[10] array cdef TestAttrs[:] struct_memview = array print builtins.memoryview(struct_memview).format # Test padding at the end of structs in the buffer support cdef struct PaddedAtEnd: int a[3] char b[3] cdef struct AlignedNested: PaddedAtEnd a char chars[1] cdef struct PaddedAtEndNormal: int a char b char c char d cdef struct AlignedNestedNormal: PaddedAtEndNormal a char chars # Test nested structs in a struct, make sure we compute padding each time # accordingly. If the first struct member is a struct, align on the first # member of that struct (recursively) cdef struct A: double d char c cdef struct B: char c1 A a char c2 cdef struct C: A a char c1 cdef struct D: B b C cstruct int a[2] char c cdef fused FusedPadded: ArrayStruct PackedArrayStruct AlignedNested AlignedNestedNormal A B C D @testcase def test_padded_structs(): """ >>> test_padded_structs() """ cdef ArrayStruct[10] a1 cdef PackedArrayStruct[10] a2 cdef AlignedNested[10] a3 cdef AlignedNestedNormal[10] a4 cdef A[10] a5 cdef B[10] a6 cdef C[10] a7 cdef D[10] a8 _test_padded(a1) _test_padded(a2) _test_padded(a3) _test_padded(a4) _test_padded(a5) _test_padded(a6) _test_padded(a7) # There is a pre-existing bug that doesn't parse the format for this # struct properly -- fix this #_test_padded(a8) cdef _test_padded(FusedPadded myarray[10]): # test that the buffer format parser accepts our format string... cdef FusedPadded[:] myslice = myarray obj = myslice cdef FusedPadded[:] myotherslice = obj @testcase def test_object_indices(): """ >>> test_object_indices() 0 1 2 """ cdef int[3] array cdef int[:] myslice = array cdef int j for i in range(3): myslice[i] = i for j in range(3): print myslice[j] cdef fused slice_1d: object int[:] cdef fused slice_2d: object int[:, :] @testcase def test_ellipsis_expr(): """ >>> test_ellipsis_expr() 8 8 """ cdef int[10] a cdef int[:] m = a _test_ellipsis_expr(m) _test_ellipsis_expr( m) cdef _test_ellipsis_expr(slice_1d m): m[4] = 8 m[...] = m[...] print m[4] @testcase def test_slice_assignment(): """ >>> test_slice_assignment() """ cdef int[10][100] carray cdef int i, j for i in range(10): for j in range(100): carray[i][j] = i * 100 + j cdef int[:, :] m = carray cdef int[:, :] copy = m[-6:-1, 60:65].copy() _test_slice_assignment(m, copy) _test_slice_assignment( m, copy) cdef _test_slice_assignment(slice_2d m, slice_2d copy): cdef int i, j m[...] = m[::-1, ::-1] m[:, :] = m[::-1, ::-1] m[-5:, -5:] = m[-6:-1, 60:65] for i in range(5): for j in range(5): assert copy[i, j] == m[-5 + i, -5 + j], (copy[i, j], m[-5 + i, -5 + j]) @testcase def test_slice_assignment_broadcast_leading(): """ >>> test_slice_assignment_broadcast_leading() """ cdef int[1][10] array1 cdef int[10] array2 cdef int i for i in range(10): array1[0][i] = i cdef int[:, :] a = array1 cdef int[:] b = array2 _test_slice_assignment_broadcast_leading(a, b) for i in range(10): array1[0][i] = i _test_slice_assignment_broadcast_leading( a, b) cdef _test_slice_assignment_broadcast_leading(slice_2d a, slice_1d b): cdef int i b[:] = a[:, :] b = b[::-1] a[:, :] = b[:] for i in range(10): assert a[0, i] == b[i] == 10 - 1 - i, (a[0, i], b[i], 10 - 1 - i) @testcase def test_slice_assignment_broadcast_strides(): """ >>> test_slice_assignment_broadcast_strides() """ cdef int[10] src_array cdef int[10][5] dst_array cdef int i, j for i in range(10): src_array[i] = 10 - 1 - i cdef int[:] src = src_array cdef int[:, :] dst = dst_array cdef int[:, :] dst_f = dst.copy_fortran() _test_slice_assignment_broadcast_strides(src, dst, dst_f) _test_slice_assignment_broadcast_strides( src, dst, dst_f) cdef _test_slice_assignment_broadcast_strides(slice_1d src, slice_2d dst, slice_2d dst_f): cdef int i, j dst[1:] = src[-1:-6:-1] dst_f[1:] = src[-1:-6:-1] for i in range(1, 10): for j in range(1, 5): assert dst[i, j] == dst_f[i, j] == j, (dst[i, j], dst_f[i, j], j) # test overlapping memory with broadcasting dst[:, 1:4] = dst[1, :3] dst_f[:, 1:4] = dst[1, 1:4] for i in range(10): for j in range(1, 3): assert dst[i, j] == dst_f[i, j] == j - 1, (dst[i, j], dst_f[i, j], j - 1) @testcase def test_borrowed_slice(): """ Test the difference between borrowed an non-borrowed slices. If you delete or assign to a slice in a cdef function, it is not borrowed. >>> test_borrowed_slice() 5 5 5 """ cdef int i cdef int[10] carray carray[:] = range(10) _borrowed(carray) _not_borrowed(carray) _not_borrowed2(carray) cdef _borrowed(int[:] m): print m[5] cdef _not_borrowed(int[:] m): print m[5] if object(): del m cdef _not_borrowed2(int[:] m): cdef int[10] carray print m[5] if object(): m = carray class SingleObject(object): def __init__(self, value): self.value = value def __str__(self): return str(self.value) def __eq__(self, other): return self.value == getattr(other, 'value', None) or self.value == other cdef _get_empty_object_slice(fill=None): cdef array a = array((10,), sizeof(PyObject *), 'O') assert a.dtype_is_object return a @testcase def test_object_dtype_copying(): """ >>> test_object_dtype_copying() 0 1 2 3 4 5 6 7 8 9 5 1 5 """ cdef int i unique = object() unique_refcount = get_refcount(unique) cdef object[:] m1 = _get_empty_object_slice() cdef object[:] m2 = _get_empty_object_slice() for i in range(10): m1[i] = SingleObject(i) m2[...] = m1 del m1 for i in range(10): print m2[i] obj = m2[5] refcount1 = get_refcount(obj) print obj del m2 refcount2 = get_refcount(obj) print refcount1 - refcount2, obj assert unique_refcount == get_refcount(unique), (unique_refcount, get_refcount(unique)) @testcase def test_scalar_slice_assignment(): """ >>> test_scalar_slice_assignment() 0 1 6 3 6 5 6 7 6 9 0 1 6 3 6 5 6 7 6 9 """ cdef int[10] a cdef int[:] m = a cdef int[5][10] a2 cdef int[:, ::1] m2 = a2 _test_scalar_slice_assignment(m, m2) print _test_scalar_slice_assignment( m, m2) cdef _test_scalar_slice_assignment(slice_1d m, slice_2d m2): cdef int i, j for i in range(10): m[i] = i m[-2:0:-2] = 6 for i in range(10): print m[i] for i in range(m2.shape[0]): for j in range(m2.shape[1]): m2[i, j] = i * m2.shape[1] + j cdef int x = 2, y = -2 cdef long value = 1 m2[::2, ::-1] = value m2[-2::-2, ::-1] = 2 m2[::2, -2::-2] = 0 m2[-2::-2, -2::-2] = 0 cdef int[:, :] s = m2[..., 1::2] for i in range(s.shape[0]): for j in range(s.shape[1]): assert s[i, j] == i % 2 + 1, (s[i, j], i) s = m2[::2, 1::2] for i in range(s.shape[0]): for j in range(s.shape[1]): assert s[i, j] == 1, s[i, j] s = m2[1::2, ::2] for i in range(s.shape[0]): for j in range(s.shape[1]): assert s[i, j] == 0, s[i, j] m2[...] = 3 for i in range(m2.shape[0]): for j in range(m2.shape[1]): assert m2[i, j] == 3, s[i, j] @testcase def test_contig_scalar_to_slice_assignment(): """ >>> test_contig_scalar_to_slice_assignment() 14 14 14 14 30 14 30 14 20 20 20 20 30 30 20 20 """ cdef int[5][10] a cdef int[:, ::1] m = a m[...] = 14 print m[0, 0], m[-1, -1], m[3, 2], m[4, 9] m[:, :1] = 30 print m[0, 0], m[0, 1], m[1, 0], m[1, 1] m[:, :] = 20 print m[0, 0], m[-1, -1], m[3, 2], m[4, 9] m[:1, :] = 30 print m[0, 0], m[0, 1], m[1, 0], m[1, 1] @testcase def test_dtype_object_scalar_assignment(): """ >>> test_dtype_object_scalar_assignment() """ cdef object[:] m = array((10,), sizeof(PyObject *), 'O') m[:] = SingleObject(2) assert m[0] == m[4] == m[-1] == 2 ( m)[:] = SingleObject(3) assert m[0] == m[4] == m[-1] == 3 # ### Test slices that are set to None # # for none memoryview slice attribute testing, slicing, indexing, etc, see # nonecheck.pyx @testcase def test_coerce_to_from_None(double[:] m1, double[:] m2 = None): """ >>> test_coerce_to_from_None(None) (None, None) >>> test_coerce_to_from_None(None, None) (None, None) """ return m1, m2 @testcase def test_noneslice_compare(double[:] m): """ >>> test_noneslice_compare(None) (True, True) """ with cython.nonecheck(True): result = m is None return result, m is None cdef class NoneSliceAttr(object): cdef double[:] m @testcase def test_noneslice_ext_attr(): """ >>> test_noneslice_ext_attr() AttributeError Memoryview is not initialized None """ cdef NoneSliceAttr obj = NoneSliceAttr() with cython.nonecheck(True): try: print obj.m except Exception, e: print type(e).__name__, e.args[0] obj.m = None print obj.m @testcase def test_noneslice_del(): """ >>> test_noneslice_del() Traceback (most recent call last): ... UnboundLocalError: local variable 'm' referenced before assignment """ cdef int[10] a cdef int[:] m = a with cython.nonecheck(True): m = None del m print m @testcase def test_noneslice_nogil_check_none(double[:] m): """ >>> test_noneslice_nogil_check_none(None) (True, False) """ cdef bint is_none = False cdef bint not_none = True with nogil: is_none = m is None and None is m and m == None and None == m not_none = m is not None and None is not m and m != None and None != m return is_none, not_none @testcase def test_noneslice_not_none(double[:] m not None): """ >>> test_noneslice_not_none(None) Traceback (most recent call last): TypeError: Argument 'm' must not be None """ def get_int(): return 10 @testcase def test_inplace_assignment(): """ >>> test_inplace_assignment() 10 """ cdef int[10] a cdef int[:] m = a m[0] = get_int() print m[0] @testcase def test_newaxis(int[:] one_D): """ >>> A = IntMockBuffer("A", range(6)) # , writable=False) >>> test_newaxis(A) acquired A 3 3 3 3 released A """ cdef int[:, :] two_D_1 = one_D[None] cdef int[:, :] two_D_2 = one_D[None, :] cdef int[:, :] two_D_3 = one_D[:, None] cdef int[:, :] two_D_4 = one_D[..., None] print two_D_1[0, 3] print two_D_2[0, 3] print two_D_3[3, 0] print two_D_4[3, 0] @testcase def test_newaxis2(int[:, :] two_D): """ >>> A = IntMockBuffer("A", range(6), shape=(3, 2)) # , writable=False) >>> test_newaxis2(A) acquired A shape: 3 1 1 strides: 2 0 0 suboffsets: -1 -1 -1 shape: 1 2 1 strides: 0 1 0 suboffsets: -1 -1 -1 shape: 3 1 1 1 strides: 2 0 1 0 suboffsets: -1 -1 -1 -1 shape: 1 2 2 1 strides: 0 2 1 0 suboffsets: -1 -1 -1 -1 released A """ cdef int[:, :, :] a = two_D[..., None, 1, None] cdef int[:, :, :] b = two_D[None, 1, ..., None] cdef int[:, :, :, :] c = two_D[..., None, 1:, None] cdef int[:, :, :, :] d = two_D[None, 1:, ..., None] _print_attributes(a) print _print_attributes(b) print _print_attributes(c) print _print_attributes(d) @testcase def test_const_buffer(const int[:] a): """ >>> A = IntMockBuffer("A", range(6), shape=(6,), writable=False) >>> test_const_buffer(A) acquired A 0 5 released A """ cdef const int[:] c = a print(a[0]) print(c[-1]) @testcase def test_loop(int[:] a, throw_exception): """ >>> A = IntMockBuffer("A", range(6), shape=(6,)) >>> test_loop(A, False) acquired A 15 released A >>> try: ... test_loop(A, True) ... except ValueError: ... pass acquired A released A """ cdef int sum = 0 for ai in a: sum += ai if throw_exception: raise ValueError() print(sum) @testcase def test_loop_reassign(int[:] a): """ >>> A = IntMockBuffer("A", range(6), shape=(6,)) >>> test_loop_reassign(A) acquired A 0 1 2 3 4 5 15 released A """ cdef int sum = 0 for ai in a: sum += ai print(ai) a = None # this should not mess up the loop though! print(sum) # release happens in the wrapper function @testcase def test_arg_in_closure(int [:] a): """ >>> A = IntMockBuffer("A", range(6), shape=(6,)) >>> inner = test_arg_in_closure(A) acquired A >>> inner() (0, 1) The assignment below is just to avoid printing what was collected >>> del inner; ignore_me = gc.collect() released A """ def inner(): return (a[0], a[1]) return inner cdef arg_in_closure_cdef(int [:] a): def inner(): return (a[0], a[1]) return inner def test_arg_in_closure_cdef(a): """ >>> A = IntMockBuffer("A", range(6), shape=(6,)) >>> inner = test_arg_in_closure_cdef(A) acquired A >>> inner() (0, 1) The assignment below is just to avoid printing what was collected >>> del inner; ignore_me = gc.collect() released A """ return arg_in_closure_cdef(a) @testcase def test_local_in_closure(a): """ >>> A = IntMockBuffer("A", range(6), shape=(6,)) >>> inner = test_local_in_closure(A) acquired A >>> inner() (0, 1) The assignment below is just to avoid printing what was collected >>> del inner; ignore_me = gc.collect() released A """ cdef int[:] a_view = a def inner(): return (a_view[0], a_view[1]) return inner @testcase def test_local_in_generator_expression(a, initialize, execute_now): """ >>> A1 = IntMockBuffer("A1", range(6), shape=(6,)) >>> A2 = IntMockBuffer("A2", range(6), shape=(6,)) >>> test_local_in_generator_expression(A1, initialize=False, execute_now=False) # doctest: +ELLIPSIS Traceback (most recent call last): ... UnboundLocalError... >>> test_local_in_generator_expression(A1, initialize=True, execute_now=True) acquired A1 released A1 True >>> genexp = test_local_in_generator_expression(A2, initialize=True, execute_now=False) acquired A2 >>> sum(genexp) released A2 2 """ cdef int[:] a_view if initialize: a_view = a if execute_now: return any(ai > 3 for ai in a_view) else: return (ai > 3 for ai in a_view) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/memoryview/memview_assignments.pyx0000644000175100001770000000021600000000000023766 0ustar00runnerdocker00000000000000# mode: compile # tag: memoryview cdef double[::1] contig # see if we can assign a strided value to a contiguous one contig[:] = contig[::2] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/memoryview/numpy_memoryview.pyx0000644000175100001770000004666400000000000023356 0ustar00runnerdocker00000000000000# tag: numpy # mode: run """ Test slicing for memoryviews and memoryviewslices """ import sys cimport numpy as np import numpy as np cimport cython from cython cimport view include "../testsupport/cythonarrayutil.pxi" include "../buffers/mockbuffers.pxi" ctypedef np.int32_t dtype_t IS_PYPY = hasattr(sys, 'pypy_version_info') NUMPY_VERSION = tuple(int(v) for v in np.__version__.split('.')[:2]) print(NUMPY_VERSION) def get_array(): # We need to type our array to get a __pyx_get_buffer() that typechecks # for np.ndarray and calls __getbuffer__ in numpy.pxd cdef np.ndarray[dtype_t, ndim=3] a a = np.arange(8 * 14 * 11, dtype=np.int32).reshape(8, 14, 11) return a a = get_array() def ae(*args): "assert equals" for x in args: if x != args[0]: raise AssertionError(args) def testcase_no_pypy(f, _is_pypy=hasattr(sys, "pypy_version_info")): if _is_pypy: f.__doc__ = "" # disable the tests return f def gc_collect_if_required(): if NUMPY_VERSION >= (1, 14) or IS_PYPY: import gc gc.collect() # ### Test slicing memoryview slices # def test_partial_slicing(array): """ >>> test_partial_slicing(a) """ cdef dtype_t[:, :, :] a = array obj = array[4] cdef dtype_t[:, :] b = a[4, :] cdef dtype_t[:, :] c = a[4] ae(b.shape[0], c.shape[0], obj.shape[0]) ae(b.shape[1], c.shape[1], obj.shape[1]) ae(b.strides[0], c.strides[0], obj.strides[0]) ae(b.strides[1], c.strides[1], obj.strides[1]) def test_ellipsis(array): """ >>> test_ellipsis(a) """ cdef dtype_t[:, :, :] a = array cdef dtype_t[:, :] b = a[..., 4] b_obj = array[..., 4] cdef dtype_t[:, :] c = a[4, ...] c_obj = array[4, ...] cdef dtype_t[:, :] d = a[2:8, ..., 2] d_obj = array[2:8, ..., 2] ae(tuple([b.shape[i] for i in range(2)]), b_obj.shape) ae(tuple([b.strides[i] for i in range(2)]), b_obj.strides) for i in range(b.shape[0]): for j in range(b.shape[1]): ae(b[i, j], b_obj[i, j]) ae(tuple([c.shape[i] for i in range(2)]), c_obj.shape) ae(tuple([c.strides[i] for i in range(2)]), c_obj.strides) for i in range(c.shape[0]): for j in range(c.shape[1]): ae(c[i, j], c_obj[i, j]) ae(tuple([d.shape[i] for i in range(2)]), d_obj.shape) ae(tuple([d.strides[i] for i in range(2)]), d_obj.strides) for i in range(d.shape[0]): for j in range(d.shape[1]): ae(d[i, j], d_obj[i, j]) cdef dtype_t[:] e = a[..., 5, 6] e_obj = array[..., 5, 6] ae(e.shape[0], e_obj.shape[0]) ae(e.strides[0], e_obj.strides[0]) # ### Test slicing memoryview objects # def test_partial_slicing_memoryview(array): """ >>> test_partial_slicing_memoryview(a) """ cdef dtype_t[:, :, :] _a = array a = _a obj = array[4] b = a[4, :] c = a[4] ae(b.shape[0], c.shape[0], obj.shape[0]) ae(b.shape[1], c.shape[1], obj.shape[1]) ae(b.strides[0], c.strides[0], obj.strides[0]) ae(b.strides[1], c.strides[1], obj.strides[1]) def test_ellipsis_memoryview(array): """ >>> test_ellipsis_memoryview(a) """ cdef dtype_t[:, :, :] _a = array a = _a b = a[..., 4] b_obj = array[..., 4] c = a[4, ...] c_obj = array[4, ...] d = a[2:8, ..., 2] d_obj = array[2:8, ..., 2] ae(tuple([b.shape[i] for i in range(2)]), b_obj.shape) ae(tuple([b.strides[i] for i in range(2)]), b_obj.strides) for i in range(b.shape[0]): for j in range(b.shape[1]): ae(b[i, j], b_obj[i, j]) ae(tuple([c.shape[i] for i in range(2)]), c_obj.shape) ae(tuple([c.strides[i] for i in range(2)]), c_obj.strides) for i in range(c.shape[0]): for j in range(c.shape[1]): ae(c[i, j], c_obj[i, j]) ae(tuple([d.shape[i] for i in range(2)]), d_obj.shape) ae(tuple([d.strides[i] for i in range(2)]), d_obj.strides) for i in range(d.shape[0]): for j in range(d.shape[1]): ae(d[i, j], d_obj[i, j]) e = a[..., 5, 6] e_obj = array[..., 5, 6] ae(e.shape[0], e_obj.shape[0]) ae(e.strides[0], e_obj.strides[0]) def test_transpose(): """ >>> test_transpose() 3 4 (3, 4) (3, 4) 11 11 11 11 11 11 """ cdef dtype_t[:, :] a numpy_obj = np.arange(4 * 3, dtype=np.int32).reshape(4, 3) a = numpy_obj cdef object a_obj = a cdef dtype_t[:, :] b = a.T print a.T.shape[0], a.T.shape[1] print a_obj.T.shape print tuple(map(int, numpy_obj.T.shape)) # might use longs in Py2 cdef dtype_t[:, :] c with nogil: c = a.T.T assert ( a).shape == ( c).shape assert ( a).strides == ( c).strides print a[3, 2], a.T[2, 3], a_obj[3, 2], a_obj.T[2, 3], numpy_obj[3, 2], numpy_obj.T[2, 3] def test_transpose_type(a): """ >>> a = np.zeros((5, 10), dtype=np.float64) >>> a[4, 6] = 9 >>> test_transpose_type(a) 9.0 """ cdef double[:, ::1] m = a cdef double[::1, :] m_transpose = a.T print m_transpose[6, 4] def test_numpy_like_attributes(cyarray): """ >>> cyarray = create_array(shape=(8, 5), mode="c") >>> test_numpy_like_attributes(cyarray) >>> test_numpy_like_attributes(cyarray.memview) """ numarray = np.asarray(cyarray) assert cyarray.shape == numarray.shape, (cyarray.shape, numarray.shape) assert cyarray.strides == numarray.strides, (cyarray.strides, numarray.strides) assert cyarray.ndim == numarray.ndim, (cyarray.ndim, numarray.ndim) assert cyarray.size == numarray.size, (cyarray.size, numarray.size) assert cyarray.nbytes == numarray.nbytes, (cyarray.nbytes, numarray.nbytes) cdef int[:, :] mslice = numarray assert ( mslice).base is numarray def test_copy_and_contig_attributes(a): """ >>> a = np.arange(20, dtype=np.int32).reshape(5, 4) >>> test_copy_and_contig_attributes(a) """ cdef np.int32_t[:, :] mslice = a cdef object m = mslice # object copy # Test object copy attributes assert np.all(a == np.array(m.copy())) assert a.strides == m.strides == m.copy().strides assert np.all(a == np.array(m.copy_fortran())) assert m.copy_fortran().strides == (4, 20) # Test object is_*_contig attributes assert m.is_c_contig() and m.copy().is_c_contig() assert m.copy_fortran().is_f_contig() and not m.is_f_contig() ctypedef int td_cy_int cdef extern from "bufaccess.h": ctypedef td_cy_int td_h_short # Defined as short, but Cython doesn't know this! ctypedef float td_h_double # Defined as double ctypedef unsigned int td_h_ushort # Defined as unsigned short ctypedef td_h_short td_h_cy_short cdef void dealloc_callback(void *data) noexcept: print "deallocating..." def build_numarray(array array): array.callback_free_data = dealloc_callback return np.asarray(array) def index(array array): print build_numarray(array)[3, 2] @testcase_no_pypy def test_coerce_to_numpy(): """ Test coercion to NumPy arrays, especially with automatically generated format strings. >>> test_coerce_to_numpy() [97, 98, 600, 700, 800] deallocating... (600, 700) deallocating... ((100, 200), (300, 400), 500) deallocating... (97, 900) deallocating... 99 deallocating... 111 deallocating... 222 deallocating... 333 deallocating... 11.1 deallocating... 12.2 deallocating... 13.25 deallocating... (14.4+15.5j) deallocating... (16.5+17.7j) deallocating... (18.8125+19.9375j) deallocating... 22 deallocating... 33.33 deallocating... 44 deallocating... """ # ### First set up some C arrays that will be used to hold data # cdef MyStruct[20] mystructs cdef SmallStruct[20] smallstructs cdef NestedStruct[20] nestedstructs cdef PackedStruct[20] packedstructs cdef signed char[20] chars cdef short[20] shorts cdef int[20] ints cdef long long[20] longlongs cdef td_h_short[20] externs cdef float[20] floats cdef double[20] doubles cdef long double[20] longdoubles cdef float complex[20] floatcomplex cdef double complex[20] doublecomplex cdef long double complex[20] longdoublecomplex cdef td_h_short[20] h_shorts cdef td_h_double[20] h_doubles cdef td_h_ushort[20] h_ushorts cdef Py_ssize_t idx = 17 # ### Initialize one element in each array # mystructs[idx] = { 'a': 'a', 'b': 'b', 'c': 600, 'd': 700, 'e': 800, } smallstructs[idx] = { 'a': 600, 'b': 700 } nestedstructs[idx] = { 'x': { 'a': 100, 'b': 200 }, 'y': { 'a': 300, 'b': 400 }, 'z': 500, } packedstructs[idx] = { 'a': 'a', 'b': 900 } chars[idx] = 99 shorts[idx] = 111 ints[idx] = 222 longlongs[idx] = 333 externs[idx] = 444 assert externs[idx] == 444 # avoid "set but not used" C compiler warning floats[idx] = 11.1 doubles[idx] = 12.2 longdoubles[idx] = 13.25 floatcomplex[idx] = 14.4 + 15.5j doublecomplex[idx] = 16.5 + 17.7j longdoublecomplex[idx] = 18.8125 + 19.9375j # x/64 to avoid float format rounding issues h_shorts[idx] = 22 h_doubles[idx] = 33.33 h_ushorts[idx] = 44 # ### Create a NumPy array and see if our element can be correctly retrieved # mystruct_array = build_numarray( mystructs) print [int(x) for x in mystruct_array[3, 2]] del mystruct_array index( smallstructs) index( nestedstructs) index( packedstructs) index( chars) index( shorts) index( ints) index( longlongs) index( floats) index( doubles) index( longdoubles) index( floatcomplex) index( doublecomplex) index( longdoublecomplex) index( h_shorts) index( h_doubles) index( h_ushorts) @testcase_no_pypy def test_memslice_getbuffer(): """ >>> test_memslice_getbuffer(); gc_collect_if_required() [[ 0 2 4] [10 12 14]] callback called """ cdef int[:, :] array = create_array((4, 5), mode="c", use_callback=True) print(np.asarray(array)[::2, ::2]) cdef class DeallocateMe(object): def __dealloc__(self): print "deallocated!" # Disabled! References cycles don't seem to be supported by NumPy # @testcase def acquire_release_cycle(obj): DISABLED_DOCSTRING = """ >>> a = np.arange(20, dtype=np.object) >>> a[10] = DeallocateMe() >>> acquire_release_cycle(a) deallocated! """ import gc cdef object[:] buf = obj buf[1] = buf gc.collect() del buf gc.collect() cdef packed struct StructArray: int a[4] signed char b[5] def test_memslice_structarray(data, dtype): """ >>> def b(s): return s.encode('ascii') >>> def to_byte_values(b): ... if sys.version_info[0] >= 3: return list(b) ... else: return map(ord, b) >>> data = [(range(4), b('spam\\0')), (range(4, 8), b('ham\\0\\0')), (range(8, 12), b('eggs\\0'))] >>> dtype = np.dtype([('a', '4i'), ('b', '5b')]) >>> test_memslice_structarray([(L, to_byte_values(s)) for L, s in data], dtype) 0 1 2 3 spam 4 5 6 7 ham 8 9 10 11 eggs Test the same thing with the string format specifier >>> dtype = np.dtype([('a', '4i'), ('b', 'S5')]) >>> test_memslice_structarray(data, dtype) 0 1 2 3 spam 4 5 6 7 ham 8 9 10 11 eggs """ a = np.empty((3,), dtype=dtype) a[:] = data cdef StructArray[:] myslice = a cdef int i, j for i in range(3): for j in range(4): print myslice[i].a[j] print myslice[i].b.decode('ASCII') def test_structarray_errors(StructArray[:] a): """ >>> dtype = np.dtype([('a', '4i'), ('b', '5b')]) >>> test_structarray_errors(np.empty((5,), dtype=dtype)) >>> dtype = np.dtype([('a', '6i'), ('b', '5b')]) >>> test_structarray_errors(np.empty((5,), dtype=dtype)) Traceback (most recent call last): ... ValueError: Expected a dimension of size 4, got 6 >>> dtype = np.dtype([('a', '(4,4)i'), ('b', '5b')]) >>> test_structarray_errors(np.empty((5,), dtype=dtype)) Traceback (most recent call last): ... ValueError: Expected 1 dimension(s), got 2 Test the same thing with the string format specifier >>> dtype = np.dtype([('a', '4i'), ('b', 'S5')]) >>> test_structarray_errors(np.empty((5,), dtype=dtype)) >>> dtype = np.dtype([('a', '6i'), ('b', 'S5')]) >>> test_structarray_errors(np.empty((5,), dtype=dtype)) Traceback (most recent call last): ... ValueError: Expected a dimension of size 4, got 6 >>> dtype = np.dtype([('a', '(4,4)i'), ('b', 'S5')]) >>> test_structarray_errors(np.empty((5,), dtype=dtype)) Traceback (most recent call last): ... ValueError: Expected 1 dimension(s), got 2 """ cdef struct StringStruct: signed char c[4][4] ctypedef signed char String[4][4] def stringstructtest(StringStruct[:] view): pass def stringtest(String[:] view): pass def test_string_invalid_dims(): """ >>> def b(s): return s.encode('ascii') >>> dtype = np.dtype([('a', 'S4')]) >>> data = [b('spam'), b('eggs')] >>> stringstructtest(np.array(data, dtype=dtype)) Traceback (most recent call last): ... ValueError: Expected 2 dimensions, got 1 >>> stringtest(np.array(data, dtype='S4')) Traceback (most recent call last): ... ValueError: Expected 2 dimensions, got 1 """ ctypedef struct AttributesStruct: int attrib1 float attrib2 StringStruct attrib3 def test_struct_attributes(): """ >>> test_struct_attributes() 1 2.0 c """ cdef AttributesStruct[10] a cdef AttributesStruct[:] myslice = a myslice[0].attrib1 = 1 myslice[0].attrib2 = 2.0 myslice[0].attrib3.c[0][0] = 'c' array = np.asarray(myslice) print array[0]['attrib1'] print array[0]['attrib2'] print chr(array[0]['attrib3']['c'][0][0]) # ### Test for NULL strides (C contiguous buffers) # cdef getbuffer(Buffer self, Py_buffer *info): info.buf = &self.m[0, 0] info.len = 10 * 20 info.ndim = 2 info.shape = self._shape info.strides = NULL info.suboffsets = NULL info.itemsize = 4 info.readonly = 0 self.format = b"f" info.format = self.format cdef class Buffer(object): cdef Py_ssize_t[2] _shape cdef bytes format cdef float[:, :] m cdef object shape, strides def __init__(self): a = np.arange(200, dtype=np.float32).reshape(10, 20) self.m = a self.shape = a.shape self.strides = a.strides self._shape[0] = 10 self._shape[1] = 20 def __getbuffer__(self, Py_buffer *info, int flags): getbuffer(self, info) cdef class SuboffsetsNoStridesBuffer(Buffer): def __getbuffer__(self, Py_buffer *info, int flags): getbuffer(self, info) info.suboffsets = self._shape def test_null_strides(Buffer buffer_obj): """ >>> test_null_strides(Buffer()) """ cdef float[:, :] m1 = buffer_obj cdef float[:, ::1] m2 = buffer_obj cdef float[:, ::view.contiguous] m3 = buffer_obj assert ( m1).strides == buffer_obj.strides assert ( m2).strides == buffer_obj.strides, (( m2).strides, buffer_obj.strides) assert ( m3).strides == buffer_obj.strides cdef int i, j for i in range(m1.shape[0]): for j in range(m1.shape[1]): assert m1[i, j] == buffer_obj.m[i, j] assert m2[i, j] == buffer_obj.m[i, j], (i, j, m2[i, j], buffer_obj.m[i, j]) assert m3[i, j] == buffer_obj.m[i, j] def test_null_strides_error(buffer_obj): """ >>> test_null_strides_error(Buffer()) C-contiguous buffer is not indirect in dimension 1 C-contiguous buffer is not indirect in dimension 0 C-contiguous buffer is not contiguous in dimension 0 C-contiguous buffer is not contiguous in dimension 0 >>> test_null_strides_error(SuboffsetsNoStridesBuffer()) Traceback (most recent call last): ... ValueError: Buffer exposes suboffsets but no strides """ # valid cdef float[::view.generic, ::view.generic] full_buf = buffer_obj # invalid cdef float[:, ::view.indirect] indirect_buf1 cdef float[::view.indirect, :] indirect_buf2 cdef float[::1, :] fortran_buf1 cdef float[::view.contiguous, :] fortran_buf2 try: indirect_buf1 = buffer_obj except ValueError, e: print e try: indirect_buf2 = buffer_obj except ValueError, e: print e try: fortran_buf1 = buffer_obj except ValueError, e: print e try: fortran_buf2 = buffer_obj except ValueError, e: print e def test_refcount_GH507(): """ >>> test_refcount_GH507() """ a = np.arange(12).reshape([3, 4]) cdef np.int_t[:,:] a_view = a cdef np.int_t[:,:] b = a_view[1:2,:].T @cython.boundscheck(False) @cython.wraparound(False) def test_boundscheck_and_wraparound(double[:, :] x): """ >>> import numpy as np >>> array = np.ones((2,2)) * 3.5 >>> test_boundscheck_and_wraparound(array) """ # Make sure we don't generate C compiler warnings for unused code here. cdef Py_ssize_t numrow = x.shape[0] cdef Py_ssize_t i for i in range(numrow): x[i, 0] x[i] x[i, ...] x[i, :] ctypedef struct SameTypeAfterArraysStructSimple: double a[16] double b[16] double c def same_type_after_arrays_simple(): """ >>> same_type_after_arrays_simple() """ cdef SameTypeAfterArraysStructSimple element arr = np.ones(2, np.asarray(&element).dtype) cdef SameTypeAfterArraysStructSimple[:] memview = arr ctypedef struct SameTypeAfterArraysStructComposite: int a float b[8] float c unsigned long d int e[5] int f int g double h[4] int i def same_type_after_arrays_composite(): """ >>> same_type_after_arrays_composite() if sys.version_info[:2] >= (3, 5) else None >>> same_type_after_arrays_composite() if sys.version_info[:2] == (2, 7) else None """ cdef SameTypeAfterArraysStructComposite element arr = np.ones(2, np.asarray(&element).dtype) cdef SameTypeAfterArraysStructComposite[:] memview = arr ctypedef fused np_numeric_t: np.float64_t def test_invalid_buffer_fused_memoryview(np_numeric_t[:] A): """ >>> import numpy as np >>> zz = np.zeros([5], dtype='M') >>> test_invalid_buffer_fused_memoryview(zz) Traceback (most recent call last): ... TypeError: No matching signature found """ return ctypedef fused np_numeric_object_t: np.float64_t[:] object def test_valid_buffer_fused_memoryview(np_numeric_object_t A): """ >>> import numpy as np >>> zz = np.zeros([5], dtype='M') >>> test_valid_buffer_fused_memoryview(zz) """ return ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/memoryview/numpy_memoryview_readonly.pyx0000644000175100001770000000717400000000000025244 0ustar00runnerdocker00000000000000# mode: run # tag: readonly, const, numpy # ticket: 1772 import numpy as np cimport cython def new_array(dtype='float', writeable=True): array = np.arange(10, dtype=dtype) array.setflags(write=writeable) return array ARRAY = new_array() cdef getmax(const double[:] x): """Example code, should work with both ro and rw memoryviews""" cdef double max_val = -float('inf') for val in x: if val > max_val: max_val = val return max_val cdef update_array(double [:] x): """Modifying a ro memoryview should raise an error""" x[0] = 23. cdef getconst(const double [:] x): """Should accept ro memoryviews""" return x[0] def test_mmview_rw(x): """ >>> test_mmview_rw(ARRAY) 9.0 """ return getmax(x) def test_mmview_ro(x): """ >>> test_mmview_ro(new_array()) 9.0 """ x.setflags(write=False) assert x.flags.writeable is False return getmax(x) def test_update_mmview_rw(x): """ >>> test_update_mmview_rw(new_array()) 23.0 """ update_array(x) return x[0] def test_update_mmview_ro(x): """ >>> test_update_mmview_ro(new_array()) 0.0 """ x.setflags(write=False) assert x.flags.writeable is False try: update_array(x) except ValueError: pass else: assert False, "RO error not raised!" return getconst(x) def test_rw_call_getmax(double[:] x): """ >>> test_rw_call_getmax(new_array()) 23.0 """ update_array(x) assert getconst(x) == 23 return getmax(x) def test_const_mmview_ro(x): """ >>> test_const_mmview_ro(new_array()) 0.0 """ x.setflags(write=False) assert x.flags.writeable is False return getconst(x) def test_two_views(x): """ >>> test_two_views(new_array()) 23.0 """ cdef double[:] rw = x cdef const double[:] ro = rw rw[0] = 23 return ro[0] def test_assign_ro_to_rw(x): """ >>> test_assign_ro_to_rw(new_array()) 2.0 """ cdef const double[:] ro = x cdef double[:] rw = np.empty_like(ro) rw[:] = ro return rw[2] def test_copy(): """ >>> test_copy() (1.0, 2.0, 1.0, 1.0, 1.0, 2.0) """ cdef const double[:] ro = np.ones(3) cdef const double[:] ro2 = ro.copy() cdef double[:] rw = ro.copy() cdef double[:] rw2 = ro2.copy() rw[1] = 2 rw2[2] = 2 return rw[0], rw[1], rw[2], rw2[0], rw2[1], rw2[2] cdef getmax_floating(const cython.floating[:] x): """Function with fused type, should work with both ro and rw memoryviews""" cdef cython.floating max_val = - float('inf') for val in x: if val > max_val: max_val = val return max_val def test_mmview_const_fused_cdef(): """Test cdef function with const fused type memory view as argument. >>> test_mmview_const_fused_cdef() """ cdef float[:] data_rw = new_array(dtype='float32') assert getmax_floating(data_rw) == 9 cdef const float[:] data_ro = new_array(dtype='float32', writeable=False) assert getmax_floating(data_ro) == 9 def test_mmview_const_fused_def(const cython.floating[:] x): """Test def function with const fused type memory view as argument. With read-write numpy array: >>> test_mmview_const_fused_def(new_array('float32', writeable=True)) 0.0 >>> test_mmview_const_fused_def(new_array('float64', writeable=True)) 0.0 With read-only numpy array: >>> test_mmview_const_fused_def(new_array('float32', writeable=False)) 0.0 >>> test_mmview_const_fused_def(new_array('float64', writeable=False)) 0.0 """ cdef cython.floating result = x[0] return result ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/memoryview/parallel_refcounting_stress_test.pyx0000644000175100001770000000362300000000000026550 0ustar00runnerdocker00000000000000# mode: run # tag: openmp from cython.parallel cimport prange cimport cython from random import randint, random include "../buffers/mockbuffers.pxi" # This test is designed to pick up concurrency errors in memoryview reference counting. # It won't be 100% reliable, but hopefully does enough memoryview reference counting in # parallel that we should see errors if it isn't thread-safe. # It has been verified to crash if the atomic reference counting is replaced with non-atomic counting. @cython.boundscheck(False) @cython.wraparound(False) def refcounting_stress_test(int N): """ >>> _ = refcounting_stress_test(5000) acquired a acquired b acquired c released a released b released c """ selectors = [ randint(0, 3) for _ in range(N) ] cdef int[::1] selectorsview = IntMockBuffer(None, selectors, (N,)) shape = (10, 3) size = shape[0]*shape[1] a = [ random() for _ in range(size) ] b = [ random() for _ in range(size) ] c = [ random() for _ in range(size) ] cdef double[:,:] aview = DoubleMockBuffer("a", a, shape) cdef double[:,:] bview = DoubleMockBuffer("b", b, shape) cdef double[:,:] cview = DoubleMockBuffer("c", c, shape) cdef int i cdef double total = 0.0 for i in prange(N, nogil=True): total += loopbody(aview, bview, cview, selectorsview[i]) # make "release" order predictable del aview del bview del cview return total @cython.boundscheck(False) @cython.wraparound(False) cdef double loopbody(double[:,:] a, double[:,:] b, double[:,:] c, int selector) nogil: cdef double[:,:] selected cdef double[:] subslice cdef double res = 0 if selector % 3 == 1: selected = a elif selector % 3 == 2: selected = b else: selected = c for i in range(selected.shape[0]): subslice = selected[i, :] res += subslice[0] + subslice[2] return res ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/memoryview/relaxed_strides.pyx0000644000175100001770000000460400000000000023070 0ustar00runnerdocker00000000000000# mode: run # tag: numpy """ Test accepting NumPy arrays with arbitrary strides for zero- or one-sized dimensions. Thanks to Nathaniel Smith and Sebastian Berg. See also: Mailing list threads: https://thread.gmane.org/gmane.comp.python.cython.devel/14762 https://thread.gmane.org/gmane.comp.python.cython.devel/14634 Detailed discussion of the difference between numpy/cython's current definition of "contiguity", and the correct definition: https://thread.gmane.org/gmane.comp.python.cython.devel/14634/focus=14640 The PR implementing NPY_RELAXED_STRIDES_CHECKING: https://github.com/numpy/numpy/pull/3162 Another test case: https://github.com/numpy/numpy/issues/2956 """ import numpy as np numpy_version = np.__version__.split('.')[:2] try: numpy_version = tuple(map(int, numpy_version)) except ValueError: numpy_version = (20, 0) NUMPY_HAS_RELAXED_STRIDES = ( numpy_version < (1, 8) or np.ones((10, 1), order="C").flags.f_contiguous) def test_one_sized(array): """ >>> contig = np.ascontiguousarray(np.arange(10, dtype=np.double)[::100]) >>> test_one_sized(contig)[0] 1.0 >>> a = np.arange(10, dtype=np.double)[::100] >>> if NUMPY_HAS_RELAXED_STRIDES: print(test_one_sized(a)[0]) ... else: print(1.0) 1.0 """ cdef double[::1] a = array a[0] += 1. return array def test_zero_sized(array): """ >>> contig = np.ascontiguousarray(np.arange(10, dtype=np.double)[100:200:10]) >>> _ = test_zero_sized(contig) >>> a = np.arange(10, dtype=np.double)[100:200:10] >>> if NUMPY_HAS_RELAXED_STRIDES: _ = test_zero_sized(a) """ cdef double[::1] a = array return a def test_zero_sized_multidim_ccontig(array): """ >>> contig = np.ascontiguousarray(np.zeros((4,4,4))[::2, 2:2, ::2]) >>> _ = test_zero_sized_multidim_ccontig(contig) >>> a = np.zeros((4,4,4))[::2, 2:2, ::2] >>> if NUMPY_HAS_RELAXED_STRIDES: _ = test_zero_sized_multidim_ccontig(a) """ cdef double[:, :, ::1] a = array return a def test_zero_sized_multidim_fcontig(array): """ >>> contig = np.ascontiguousarray(np.zeros((4,4,4))[::2, 2:2, ::2]) >>> _ = test_zero_sized_multidim_fcontig(contig) >>> a = np.zeros((4,4,4))[::2, 2:2, ::2] >>> if NUMPY_HAS_RELAXED_STRIDES: _ = test_zero_sized_multidim_fcontig(a) """ cdef double[::1, :, :] a = array return a ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/memoryview/transpose_refcount.pyx0000644000175100001770000000122300000000000023624 0ustar00runnerdocker00000000000000# mode: run from cython cimport view cdef bint print_upper_right(double[:, :] M): print M[0, 1] cdef class MemViewContainer: cdef double[:, :] A def __init__(self, A): self.A = A cpdef run(self): print_upper_right(self.A) print_upper_right(self.A.T) print_upper_right(self.A.T) def test_transpose_refcount(): """ >>> test_transpose_refcount() 2.0 3.0 3.0 """ cdef double[:, :] A = view.array(shape=(2, 2), itemsize=sizeof(double), format="d") A[0, 0], A[0, 1], A[1, 0], A[1, 1] = 1., 2., 3., 4. cdef MemViewContainer container = MemViewContainer(A) container.run() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/memoryview/view_return_errors.pyx0000644000175100001770000000247600000000000023661 0ustar00runnerdocker00000000000000# mode: run # tag: memoryview cdef double[:] foo(int i): if i == 1: raise AttributeError('dummy') if i == 2: raise RuntimeError('dummy') if i == 3: raise ValueError('dummy') if i == 4: raise TypeError('dummy') cdef double[:] foo_nogil(int i) nogil: if i == 1: raise AttributeError('dummy') if i == 2: raise RuntimeError('dummy') if i == 3: raise ValueError('dummy') if i == 4: raise TypeError('dummy') def propagate(i, bint nogil=False): """ >>> propagate(0) TypeError('Memoryview return value is not initialized') >>> propagate(1) AttributeError('dummy') >>> propagate(2) RuntimeError('dummy') >>> propagate(3) ValueError('dummy') >>> propagate(4) TypeError('dummy') >>> propagate(0, nogil=True) TypeError('Memoryview return value is not initialized') >>> propagate(1, nogil=True) AttributeError('dummy') >>> propagate(2, nogil=True) RuntimeError('dummy') >>> propagate(3, nogil=True) ValueError('dummy') >>> propagate(4, nogil=True) TypeError('dummy') """ try: foo_nogil(i) if nogil else foo(i) except Exception as e: print '%s(%r)' % (e.__class__.__name__, e.args[0]) else: print 'Exception subclass not raised' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/pypy2_bugs.txt0000644000175100001770000000205000000000000017577 0ustar00runnerdocker00000000000000# Specific bugs that only apply to pypy2 build.cythonize_script build.cythonize_script_package run.initial_file_path run.reduce_pickle run.final_in_pxd run.cdef_multiple_inheritance run.cdef_multiple_inheritance_nodict run.extstarargs run.cpython_capi run.isnot run.partial_circular_import # pypy 2 seems to be preferring .py files to .so files # https://foss.heptapod.net/pypy/pypy/issues/3185 run.language_level run.pure_pxd compile.pxd_mangling_names # Silly error with doctest matching slightly different string outputs rather than # an actual bug but one I can't easily resolve run.with_gil # moved from "pypy_bugs" - work on Pypy3, segfault on pypy2 broken_exception yield_from_pep380 # looks like a "when does the GC run?" issue - slightly surprised it's OK on pypy3 memoryview.numpy_memoryview # type features that are disabled in PyPy2: # (the overridden __Pyx_PyObject_GetItem requires CYTHON_USE_TYPE_SLOTS) run.test_genericclass run.test_subclassinit # TypeError: 'memoryview' does not have the buffer interface run.buffer_n_overflowcheck_T5356 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/pypy_bugs.txt0000644000175100001770000000315000000000000017517 0ustar00runnerdocker00000000000000# This file contains tests corresponding to unresolved bugs # either in PyPy, PyPy's cpyext, or Cython under PyPy, # which will be skipped in the normal testing run. bufaccess memoryview.memoryview$ # looks like a doctest issue? It's failing to match output that looks # identical to my eye #run.unicodemethods # multiphase import not supported run.unicode_imports run.tp_new run.test_fstring run.test_exceptions run.test_dictviews run.str_subclass_kwargs run.special_method_docstrings run.slice_ptr compile.min_async run.cython_includes run.test_unicode run.__getattribute__ run.__getattribute_subclasses__ run.__debug__ run.builtin_abs run.builtincomplex run.cdef_multiple_inheritance_errors run.cdivision_CEP_516 run.cyfunction run.final_cdef_class run.pyclass_special_methods run.reimport_from_package run.reimport_from_subinterpreter run.reimport_failure pkg.cimportfrom embedded TestCyCache run.ext_auto_richcmp run.coverage_cmd run.coverage_cmd_src_layout run.coverage_installed_pkg run.coverage_api run.coverage_nogil # very little coroutine-related seems to work # For PyPy3.9+, missing support for _PyErr_StackItem in PyGenObject, # PyAsyncGenObject and PyCoroObject, which prevents supporting yields # from an exception handler run.test_asyncgen run.test_coroutines_pep492 run.embedsignatures run.asyncio_generators run.py35_pep492_interop # gc issue? external_ref_reassignment run.exttype_dealloc # even if gc.collect is added, order is changed memoryview.parallel_refcounting_stress_test # bugs in cpyext: PyNumber_InPlacePower with non-None modulus is not supported run.special_methods_T561 run.special_methods_T561_py2 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/pypy_crash_bugs.txt0000644000175100001770000000037000000000000020700 0ustar00runnerdocker00000000000000# Bugs that causes hard crashes that we certainly don't # want to run because it will break the testsuite # segfault run.fastcall memslice # gc issue? memoryview_in_subclasses # """Fatal RPython error: NotImplementedError""" pep442_tp_finalize ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/pypy_implementation_detail_bugs.txt0000644000175100001770000000262300000000000024152 0ustar00runnerdocker00000000000000# PyPy "bugs" that are probably implementation differences from # CPython rather than actual bugs. Therefore they aren't targets # to be fixed (but there *may* be other details in the testfile # that should be tested on PyPy?) run.starargs # refcounting-specific tests double_dealloc_T796 run.exceptionrefcount run.capiimpl run.refcount_in_meth sequential_parallel # Ideally just disable the reference-counting tests on PyPy? run.fused_types run.generator_frame_cycle run.generators_in_refcycles run.generators_py run.parallel # "sys.getsizeof(object, default) will always return default on PyPy, and # raise a TypeError if default is not provided." buildenv # tests for things that don't exist in cpyext compile.pylong run.datetime_pxd run.datetime_cimport run.datetime_members run.extern_builtins_T258 run.line_trace run.line_profile_test run.pstats_profile_test run.longintrepr # tests probably rely on immediate GC (although maybe the tests could be tweaked so # only these bits don't run in PyPy?) buffers.buffer buffers.userbuffer memoryview.cythonarray memoryview.memoryview_pep484_typing run.cpp_classes run.cpp_classes_def # relies on cimport array (which has a different structure in PyPy) memoryview_inplace_division run.pyarray run.array_cimport # relies on deprecated unicode APIs that will be removed in python3.12 # exposing the underlying unicode buffer in PyPy is not thread-safe run.py_unicode_strings ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1704880491.132724 Cython-3.0.8/tests/pyximport/0000755000175100001770000000000000000000000017011 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/pyximport/pyximport_basic.srctree0000644000175100001770000000066700000000000023627 0ustar00runnerdocker00000000000000 PYTHON -c "import basic_test; basic_test.test()" ######## basic_test.py ######## import os.path import pyximport pyximport.DEBUG_IMPORT = True pyximport.install(build_dir=os.path.join(os.path.dirname(__file__), "TEST_TMP")) def test(): import mymodule assert mymodule.test_string == "TEST" assert not mymodule.__file__.rstrip('oc').endswith('.py'), mymodule.__file__ ######## mymodule.pyx ######## test_string = "TEST" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/pyximport/pyximport_errors.srctree0000644000175100001770000000141000000000000024045 0ustar00runnerdocker00000000000000 PYTHON -c "import pyximport_test; pyximport_test.test()" ######## pyximport_test.py ######## import os.path from contextlib import contextmanager import pyximport pyximport.DEBUG_IMPORT = True pyximport.install(build_dir=os.path.join(os.path.dirname(__file__), "TEST_TMP")) @contextmanager def fails(exc=ImportError): try: yield except exc: pass else: raise RuntimeError("NOT RAISED!") def test(): with fails(): import compiler_error with fails(): import syntax_error with fails(): import runtime_error ######## compiler_error.pyx ######## from __future__ import braces ######## syntax_error.pyx ######## def test { BRACES! } ######## runtime_error.pyx ######## raise ValueError() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/pyximport/pyximport_namespace.srctree0000644000175100001770000000072500000000000024475 0ustar00runnerdocker00000000000000 PYTHON -c "import basic_test; basic_test.test()" ######## basic_test.py ######## import os.path import pyximport pyximport.DEBUG_IMPORT = True pyximport.install(build_dir=os.path.join(os.path.dirname(__file__), "TEST_TMP")) def test(): import nsmod.mymodule assert nsmod.mymodule.test_string == "TEST" assert not nsmod.mymodule.__file__.rstrip('oc').endswith('.py'), nsmod.mymodule.__file__ ######## nsmod/mymodule.pyx ######## test_string = "TEST" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/pyximport/pyximport_pyimport.srctree0000644000175100001770000000106300000000000024420 0ustar00runnerdocker00000000000000 PYTHON -c "import pyimport_test; pyimport_test.test()" ######## pyimport_test.py ######## import os.path import pyximport # blacklist for speed import pyximport.pyxbuild, Cython.Compiler.Pipeline pyximport.DEBUG_IMPORT = True pyximport.install(pyximport=False, pyimport=True, build_dir=os.path.join(os.path.dirname(__file__), "TEST_TMP")) def test(): import mymodule assert mymodule.test_string == "TEST" assert mymodule.compiled ######## mymodule.py ######## import cython compiled = cython.compiled test_string = "TEST" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/pyximport/pyximport_pyimport_only.srctree0000644000175100001770000000075000000000000025463 0ustar00runnerdocker00000000000000 PYTHON -c "import pyimport_test; pyimport_test.test()" ######## pyimport_test.py ######## import os.path import pyximport pyximport.DEBUG_IMPORT = True pyximport.install(pyximport=False, pyimport=True, build_dir=os.path.join(os.path.dirname(__file__), "TEST_TMP")) def test(): import mymodule assert mymodule.test_string == "TEST" assert mymodule.compiled ######## mymodule.py ######## import cython compiled = cython.compiled test_string = "TEST" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/pyximport/pyximport_pyxbld.srctree0000644000175100001770000000154500000000000024044 0ustar00runnerdocker00000000000000 PYTHON -c "import basic_test; basic_test.test()" ######## basic_test.py ######## import os.path import pyximport pyximport.DEBUG_IMPORT = True pyximport.install(build_dir=os.path.join(os.path.dirname(__file__), "TEST_TMP")) def test(): import mymodule assert mymodule.test_string == "TEST" assert mymodule.header_value == 5 assert not mymodule.__file__.rstrip('oc').endswith('.py'), mymodule.__file__ ######## mymodule.pyxbld ######## def make_ext(modname, pyxfilename): from distutils.extension import Extension return Extension(name = modname, sources=[pyxfilename], include_dirs=['./headers'] ) ######## mymodule.pyx ######## cdef extern from "myheader.h": int test_value header_value = test_value test_string = "TEST" ######## headers/myheader.h ######## static int test_value = 5; ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.2367241 Cython-3.0.8/tests/run/0000755000175100001770000000000000000000000015542 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/run/__debug__.srctree0000644000175100001770000000346000000000000021020 0ustar00runnerdocker00000000000000""" PYTHON setup.py build_ext -i PYTHON debug_test.py PYTHON -O debug_test.py PYTHON -OO debug_test.py """ ######## setup.py ######## from distutils.core import setup from Cython.Build import cythonize setup(ext_modules = cythonize('*.pyx')) ######## debug_test.py ######## if __debug__: DBG = True else: DBG = False import sys try: optimised = bool(sys.flags.optimize) except AttributeError: # Py2.[45] optimised = eval('not __debug__') if DBG == optimised: raise RuntimeError( "PYTHON: unexpected debug value %s, expected %s" % ( DBG, optimised)) ASSERT_CALLED = False def sideeffect(): global ASSERT_CALLED ASSERT_CALLED = True return True assert sideeffect() if ASSERT_CALLED == optimised: raise RuntimeError("Assert called in optimised Python run") import debug_test_cython if debug_test_cython.DBG == optimised: raise RuntimeError( "CYTHON: unexpected debug value %s, expected %s" % ( debug_test_cython.DBG, optimised)) try: import plain_debug except ValueError: assert DBG except IndexError: assert not DBG else: assert False ######## plain_debug.pyx ######## if __debug__: raise ValueError("DEBUG!") else: raise IndexError("NOT DEBUG!") ######## debug_test_cython.pyx ######## if __debug__: DBG = True else: DBG = False import sys try: optimised = bool(sys.flags.optimize) except AttributeError: # Py2.[45] optimised = eval('not __debug__') ASSERT_CALLED = False def sideeffect(): global ASSERT_CALLED ASSERT_CALLED = True return True if DBG == optimised: raise RuntimeError("Unexpected debug value %s, expected %s" % ( DBG, optimised)) assert sideeffect() if ASSERT_CALLED == optimised: raise RuntimeError("Assert called in optimised Python run") ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/run/__getattribute__.pyx0000644000175100001770000000432000000000000021602 0ustar00runnerdocker00000000000000# mode: run # __getattribute__ and __getattr__ special methods for a single class. cdef class just_getattribute: """ >>> a = just_getattribute() >>> a.called 1 >>> a.called 2 >>> a.bar 'bar' >>> a.called 4 >>> try: a.invalid ... except AttributeError: pass ... else: print("NOT RAISED!") >>> a.called 6 """ cdef readonly int called def __getattribute__(self,n): self.called += 1 if n == 'bar': return n elif n == 'called': return self.called else: raise AttributeError cdef class just_getattr: """ >>> a = just_getattr() >>> a.called 0 >>> a.called 0 >>> a.foo 10 >>> a.called 0 >>> a.bar 'bar' >>> a.called 1 >>> try: a.invalid ... except AttributeError: pass ... else: print("NOT RAISED!") >>> a.called 2 """ cdef readonly int called cdef readonly int foo def __init__(self): self.foo = 10 def __getattr__(self,n): self.called += 1 if n == 'bar': return n else: raise AttributeError cdef class both: """ >>> a = both() >>> (a.called_getattr, a.called_getattribute) (0, 2) >>> a.foo 10 >>> (a.called_getattr, a.called_getattribute) (0, 5) >>> a.bar 'bar' >>> (a.called_getattr, a.called_getattribute) (1, 8) >>> try: a.invalid ... except AttributeError: pass ... else: print("NOT RAISED!") >>> (a.called_getattr, a.called_getattribute) (2, 11) """ cdef readonly int called_getattribute cdef readonly int called_getattr cdef readonly int foo def __init__(self): self.foo = 10 def __getattribute__(self,n): self.called_getattribute += 1 if n == 'foo': return self.foo elif n == 'called_getattribute': return self.called_getattribute elif n == 'called_getattr': return self.called_getattr else: raise AttributeError def __getattr__(self,n): self.called_getattr += 1 if n == 'bar': return n else: raise AttributeError ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/run/__getattribute_subclasses__.pyx0000644000175100001770000001765200000000000024045 0ustar00runnerdocker00000000000000# mode: run # __getattribute__ and __getattr__ special methods and subclasses. cdef class boring: cdef readonly int boring_member cdef readonly int getattr_called cdef int getattribute_called def __init__(self): self.boring_member = 10 cdef class getattr_boring(boring): """ getattr does not override members. >>> a = getattr_boring() >>> a.boring_member 10 >>> a.getattr_called 0 >>> print(a.resolved_by) getattr_boring >>> a.getattr_called 1 >>> try: a.no_such_member ... except AttributeError: pass ... else: print("FAILED!") >>> a.getattr_called 2 """ def __getattr__(self,n): self.getattr_called += 1 if n == 'resolved_by': return 'getattr_boring' elif n == 'getattr_boring': return True else: raise AttributeError # currently fails, see #1793 #class getattr_boring_py(getattr_boring): # __doc__ = getattr_boring.__doc__.replace( # 'getattr_boring()', 'getattr_boring_py()') cdef class getattribute_boring(boring): """ getattribute overrides members. >>> a = getattribute_boring() >>> a.getattribute_called 1 >>> try: a.boring_member ... except AttributeError: pass ... else: print("FAILED!") >>> a.getattribute_called 3 >>> print(a.resolved_by) getattribute_boring >>> a.getattribute_called 5 >>> try: a.no_such_member ... except AttributeError: pass ... else: print("FAILED!") >>> a.getattribute_called 7 """ def __getattribute__(self,n): self.getattribute_called += 1 if n == 'resolved_by': return 'getattribute_boring' elif n == 'getattribute_boring': return True elif n == 'getattribute_called': return self.getattribute_called else: raise AttributeError class getattribute_boring_py(getattribute_boring): __doc__ = getattribute_boring.__doc__.replace( 'getattribute_boring()', 'getattribute_boring_py()') cdef class _getattr: cdef readonly int getattr_called def __getattr__(self,n): self.getattr_called += 1 if n == 'resolved_by': return '_getattr' elif n == '_getattr': return True elif n == 'getattr_called': # must only get here if __getattribute__ is overwritten assert 'getattribute' in type(self).__name__ return self.getattr_called else: raise AttributeError class getattr_py(_getattr): """ getattr is inherited. >>> a = getattr_py() >>> a.getattr_called 0 >>> print(a.resolved_by) _getattr >>> a.getattr_called 1 >>> print(a._getattr) True >>> a.getattr_called 2 >>> try: a.no_such_member ... except AttributeError: pass ... else: print("FAILED!") # currently fails, see #1793 #>>> a.getattr_called #3 """ cdef class _getattribute: cdef int getattribute_called def __getattribute__(self,n): self.getattribute_called += 1 if n == 'resolved_by': return '_getattribute' elif n == '_getattribute': return True elif n == 'getattribute_called': return self.getattribute_called else: raise AttributeError class getattribute_py(_getattribute): """ getattribute is inherited. >>> a = getattribute_py() >>> a.getattribute_called 1 >>> print(a.resolved_by) _getattribute >>> a.getattribute_called 3 >>> print(a._getattribute) True >>> a.getattribute_called 5 >>> try: a.no_such_member ... except AttributeError: pass ... else: print("FAILED!") >>> a.getattribute_called 7 """ cdef class boring_getattribute(_getattribute): cdef readonly int boring_getattribute_member cdef class boring_boring_getattribute(boring_getattribute): """ getattribute is inherited. >>> a = boring_boring_getattribute() >>> a.getattribute_called 1 >>> try: a.boring_getattribute_member ... except AttributeError: pass ... else: print("FAILED!") >>> a.getattribute_called 3 >>> try: a.boring_boring_getattribute_member ... except AttributeError: pass ... else: print("FAILED!") >>> a.getattribute_called 5 >>> print(a.resolved_by) _getattribute >>> a.getattribute_called 7 >>> try: a.no_such_member ... except AttributeError: pass ... else: print("FAILED!") >>> a.getattribute_called 9 """ cdef readonly int boring_boring_getattribute_member class boring_boring_getattribute_py(boring_boring_getattribute): __doc__ = boring_boring_getattribute.__doc__.replace( 'boring_boring_getattribute()', 'boring_boring_getattribute_py()') cdef class boring_getattr(_getattr): cdef readonly int boring_getattr_member cdef class boring_boring_getattr(boring_getattr): cdef readonly int boring_boring_getattr_member cdef class getattribute_boring_boring_getattr(boring_boring_getattr): """ __getattribute__ is always tried first, then __getattr__, regardless of where in the inheritance hierarchy they came from. >>> a = getattribute_boring_boring_getattr() >>> (a.getattr_called, a.getattribute_called) (1, 2) >>> print(a.resolved_by) getattribute_boring_boring_getattr >>> (a.getattr_called, a.getattribute_called) (2, 5) >>> a.getattribute_boring_boring_getattr True >>> (a.getattr_called, a.getattribute_called) (3, 8) >>> a._getattr True >>> (a.getattr_called, a.getattribute_called) (5, 11) >>> try: a.no_such_member ... except AttributeError: pass ... else: print("FAILED!") >>> (a.getattr_called, a.getattribute_called) (7, 14) """ cdef int getattribute_called def __getattribute__(self,n): self.getattribute_called += 1 if n == 'resolved_by': return 'getattribute_boring_boring_getattr' elif n == 'getattribute_boring_boring_getattr': return True elif n == 'getattribute_called': return self.getattribute_called else: raise AttributeError # currently fails, see #1793 #class getattribute_boring_boring_getattr_py(getattribute_boring_boring_getattr): # __doc__ = getattribute_boring_boring_getattr.__doc__.replace( # 'getattribute_boring_boring_getattr()', 'getattribute_boring_boring_getattr_py()') cdef class getattr_boring_boring_getattribute(boring_boring_getattribute): """ __getattribute__ is always tried first, then __getattr__, regardless of where in the inheritance hierarchy they came from. >>> a = getattr_boring_boring_getattribute() >>> (a.getattr_called, a.getattribute_called) (1, 2) >>> print(a.resolved_by) _getattribute >>> (a.getattr_called, a.getattribute_called) (2, 5) >>> a.getattr_boring_boring_getattribute True >>> (a.getattr_called, a.getattribute_called) (4, 8) >>> a._getattribute True >>> (a.getattr_called, a.getattribute_called) (5, 11) >>> try: a.no_such_member ... except AttributeError: pass ... else: print("FAILED!") >>> (a.getattr_called, a.getattribute_called) (7, 14) """ cdef readonly int getattr_called # note: property will not be used due to __getattribute__() def __getattr__(self,n): self.getattr_called += 1 if n == 'resolved_by': return 'getattr_boring_boring_getattribute' elif n == 'getattr_boring_boring_getattribute': return True elif n == 'getattr_called': return self.getattr_called else: raise AttributeError # currently fails, see #1793 #class getattr_boring_boring_getattribute_py(getattr_boring_boring_getattribute): # __doc__ = getattr_boring_boring_getattribute.__doc__.replace( # 'getattr_boring_boring_getattribute()', 'getattr_boring_boring_getattribute_py()') ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/run/absolute_import.srctree0000644000175100001770000000263400000000000022350 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace PYTHON -c "import pkg.my_test_module" PYTHON -c "import pkg.b; pkg.b.test_reimport()" PYTHON -c "import pkg.c; pkg.c.test_reimport()" ######## setup.py ######## from Cython.Build.Dependencies import cythonize from distutils.core import setup setup( ext_modules = cythonize("**/*.pyx"), ) ######## pkg/__init__.py ######## ######## pkg/a_module.pyx ######## ######## pkg/my_test_module.pyx ######## import sys from . import a_module assert a_module in sys.modules.values(), list(sys.modules) assert sys.modules['pkg.a_module'] is a_module, list(sys.modules) ######## pkg/b.pyx ######## from __future__ import absolute_import import sys try: import my_test_module except ImportError: pass else: assert "expected ImportError on absolute import" import pkg.my_test_module assert pkg.my_test_module in sys.modules.values(), list(sys.modules) assert sys.modules['pkg.my_test_module'] is pkg.my_test_module, list(sys.modules) def test_reimport(): import pkg.my_test_module as mod assert pkg.my_test_module is mod ######## pkg/c.pyx ######## from __future__ import absolute_import import sys from pkg import my_test_module assert my_test_module in sys.modules.values(), list(sys.modules) assert sys.modules['pkg.my_test_module'] is my_test_module, list(sys.modules) def test_reimport(): from pkg import my_test_module as mod assert my_test_module is mod ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/run/addloop.pyx0000644000175100001770000000100000000000000017715 0ustar00runnerdocker00000000000000__doc__ = u""" >>> x = 1 >>> for i in range(10): ... x = x + i >>> x 46 """ def add_pyrange(max): """ >>> add_pyrange(10) 46 """ x = 1 for i in range(max): x = x + i return x def add_py(max): """ >>> add_py(10) 46 """ x = 1 for i from 0 <= i < max: x = x + i return x def add_c(max): """ >>> add_c(10) 46 """ cdef int x,i x = 1 for i from 0 <= i < max: x = x + i return x ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/run/addop.pyx0000644000175100001770000000642000000000000017375 0ustar00runnerdocker00000000000000cimport cython def bigint(x): print(str(x).rstrip('L')) def mixed_test(): """ >>> mixed_test() (30, 22) """ cdef int int1, int2, int3 cdef char *ptr1, *ptr2 = "test", *ptr3 = "toast" int2 = 10 int3 = 20 obj1 = 1 obj2 = 2 obj3 = 3 int1 = int2 + int3 ptr1 = ptr2 + int3 ptr1 = int2 + ptr3 obj1 = obj2 + int3 return int1, obj1 @cython.test_fail_if_path_exists('//AddNode') def add_x_1(x): """ >>> add_x_1(0) 1 >>> add_x_1(1) 2 >>> add_x_1(-1) 0 >>> bigint(2**50 + 1) 1125899906842625 >>> bigint(add_x_1(2**50)) 1125899906842625 >>> add_x_1(1.5) 2.5 >>> add_x_1(-1.5) -0.5 >>> try: add_x_1("abc") ... except TypeError: pass """ return x + 1 @cython.test_fail_if_path_exists('//AddNode') def add_x_1f(x): """ >>> add_x_1f(0) 1.0 >>> add_x_1f(1) 2.0 >>> add_x_1f(-1) 0.0 >>> add_x_1f(1.5) 2.5 >>> add_x_1f(-1.5) -0.5 >>> try: add_x_1f("abc") ... except TypeError: pass """ return x + 1.0 @cython.test_fail_if_path_exists('//AddNode') def add_x_large(x): """ >>> add_x_large(0) 1073741824 >>> add_x_large(1) 1073741825 >>> add_x_large(-1) 1073741823 >>> add_x_large(1.5) 1073741825.5 >>> add_x_large(-2.0**31) -1073741824.0 >>> bigint(add_x_large(2**30 + 1)) 2147483649 >>> bigint(2**50 + 1 + 2**30) 1125900980584449 >>> bigint(add_x_large(2**50 + 1)) 1125900980584449 >>> bigint(2**31 + 2**30) 3221225472 >>> bigint(add_x_large(2**31)) 3221225472 >>> bigint(2**66 + 2**30) 73786976295911948288 >>> bigint(add_x_large(2**66)) 73786976295911948288 >>> try: add_x_large("abc") ... except TypeError: pass """ return x + 2**30 @cython.test_fail_if_path_exists('//AddNode') def add_1_x(x): """ >>> add_1_x(0) 1 >>> add_1_x(1) 2 >>> add_1_x(-1) 0 >>> bigint(2**50 + 1) 1125899906842625 >>> bigint(add_1_x(2**50)) 1125899906842625 >>> add_1_x(1.5) 2.5 >>> add_1_x(-1.5) -0.5 >>> try: add_1_x("abc") ... except TypeError: pass """ return 1 + x @cython.test_fail_if_path_exists('//AddNode') def add_1f_x(x): """ >>> add_1f_x(0) 1.0 >>> add_1f_x(1) 2.0 >>> add_1f_x(-1) 0.0 >>> 1.0 + 2**52 4503599627370497.0 >>> add_1f_x(2**52) 4503599627370497.0 >>> add_1f_x(2**60) == 1.0 + 2**60 or add_1f_x(2**60) True >>> add_1f_x(1.5) 2.5 >>> add_1f_x(-1.5) -0.5 >>> try: add_1f_x("abc") ... except TypeError: pass """ return 1.0 + x @cython.test_fail_if_path_exists('//AddNode') def add_large_x(x): """ >>> add_large_x(0) 1073741824 >>> add_large_x(1) 1073741825 >>> add_large_x(-1) 1073741823 >>> add_large_x(1.5) 1073741825.5 >>> add_large_x(-2.0**30) 0.0 >>> add_large_x(-2.0**31) -1073741824.0 >>> try: add_large_x("abc") ... except TypeError: pass """ return 2**30 + x def add0(x): """ >>> add0(0) (0, 0) >>> add0(1) (1, 1) >>> add0(-1) (-1, -1) >>> a, b = add0(2**32) >>> bigint(a) 4294967296 >>> bigint(b) 4294967296 """ return x + 0, 0 + x ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/run/addressof.pyx0000644000175100001770000000020100000000000020247 0ustar00runnerdocker00000000000000def f(int a): """ >>> f(5) 5 """ cdef int i,j cdef int *p i = a p = &i j = p[0] return j ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/run/all.pyx0000644000175100001770000001215400000000000017057 0ustar00runnerdocker00000000000000# mode: run # tag: all, builtins, werror cdef class VerboseGetItem(object): cdef object sequence def __init__(self, seq): self.sequence = seq def __getitem__(self, i): print i return self.sequence[i] # may raise IndexError cimport cython @cython.test_assert_path_exists("//SimpleCallNode") @cython.test_fail_if_path_exists("//ForInStatNode") def all_item(x): """ >>> all_item([1,1,1,1,1]) True >>> all_item([1,1,1,1,0]) False >>> all_item([0,1,1,1,0]) False >>> all(VerboseGetItem([1,1,1,0,0])) 0 1 2 3 False >>> all_item(VerboseGetItem([1,1,1,0,0])) 0 1 2 3 False >>> all(VerboseGetItem([1,1,1,1,1])) 0 1 2 3 4 5 True >>> all_item(VerboseGetItem([1,1,1,1,1])) 0 1 2 3 4 5 True """ return all(x) @cython.test_assert_path_exists( "//ForInStatNode", "//InlinedGeneratorExpressionNode" ) @cython.test_fail_if_path_exists( "//SimpleCallNode", "//YieldExprNode" ) def all_in_simple_gen(seq): """ >>> all_in_simple_gen([1,1,1]) True >>> all_in_simple_gen([1,1,0]) False >>> all_in_simple_gen([1,0,1]) False >>> all_in_simple_gen(VerboseGetItem([1,1,1,1,1])) 0 1 2 3 4 5 True >>> all_in_simple_gen(VerboseGetItem([1,1,0,1,1])) 0 1 2 False """ return all(x for x in seq) @cython.test_assert_path_exists( "//ForInStatNode", "//InlinedGeneratorExpressionNode" ) @cython.test_fail_if_path_exists( "//SimpleCallNode", "//YieldExprNode" ) def all_in_simple_gen_scope(seq): """ >>> all_in_simple_gen_scope([1,1,1]) True >>> all_in_simple_gen_scope([1,1,0]) False >>> all_in_simple_gen_scope([1,0,1]) False >>> all_in_simple_gen_scope(VerboseGetItem([1,1,1,1,1])) 0 1 2 3 4 5 True >>> all_in_simple_gen_scope(VerboseGetItem([1,1,0,1,1])) 0 1 2 False """ x = 'abc' result = all(x for x in seq) assert x == 'abc' return result @cython.test_assert_path_exists( "//ForInStatNode", "//InlinedGeneratorExpressionNode" ) @cython.test_fail_if_path_exists( "//SimpleCallNode", "//YieldExprNode" ) def all_in_conditional_gen(seq): """ >>> all_in_conditional_gen([3,6,9]) False >>> all_in_conditional_gen([0,3,7]) False >>> all_in_conditional_gen([1,0,1]) True >>> all_in_conditional_gen(VerboseGetItem([1,1,1,1,1])) 0 1 2 3 4 5 True >>> all_in_conditional_gen(VerboseGetItem([1,1,0,1,1])) 0 1 2 3 4 5 True """ return all(x%3 for x in seq if x%2 == 1) mixed_ustring = u'AbcDefGhIjKlmnoP' lower_ustring = mixed_ustring.lower() upper_ustring = mixed_ustring.upper() @cython.test_assert_path_exists( '//PythonCapiCallNode', '//ForFromStatNode' ) @cython.test_fail_if_path_exists( '//SimpleCallNode', '//ForInStatNode' ) def all_lower_case_characters(unicode ustring): """ >>> all_lower_case_characters(mixed_ustring) False >>> all_lower_case_characters(upper_ustring) False >>> all_lower_case_characters(lower_ustring) True """ return all(uchar.islower() for uchar in ustring) @cython.test_assert_path_exists( "//ForInStatNode", "//InlinedGeneratorExpressionNode", "//InlinedGeneratorExpressionNode//IfStatNode" ) @cython.test_fail_if_path_exists( "//SimpleCallNode", "//YieldExprNode", # "//IfStatNode//CoerceToBooleanNode" ) def all_in_typed_gen(seq): """ >>> all_in_typed_gen([1,1,1]) True >>> all_in_typed_gen([1,0,0]) False >>> all_in_typed_gen(VerboseGetItem([1,1,1,1,1])) 0 1 2 3 4 5 True >>> all_in_typed_gen(VerboseGetItem([1,1,1,1,0])) 0 1 2 3 4 False """ cdef int x return all(x for x in seq) @cython.test_assert_path_exists( "//ForInStatNode", "//InlinedGeneratorExpressionNode", "//InlinedGeneratorExpressionNode//IfStatNode" ) @cython.test_fail_if_path_exists( "//SimpleCallNode", "//YieldExprNode", # "//IfStatNode//CoerceToBooleanNode" ) def all_in_double_gen(seq): """ >>> all(x for L in [[1,1,1],[1,1,1],[1,1,1]] for x in L) True >>> all_in_double_gen([[1,1,1],[1,1,1],[1,1,1]]) True >>> all(x for L in [[1,1,1],[1,1,1],[1,1,0]] for x in L) False >>> all_in_double_gen([[1,1,1],[1,1,1],[1,1,0]]) False >>> all(x for L in [[1,1,1],[0,1,1],[1,1,1]] for x in L) False >>> all_in_double_gen([[1,1,1],[0,1,1],[1,1,1]]) False >>> all_in_double_gen([VerboseGetItem([1,1,1]), VerboseGetItem([1,1,1,1,1])]) 0 1 2 3 0 1 2 3 4 5 True >>> all_in_double_gen([VerboseGetItem([1,1,1]),VerboseGetItem([1,1]),VerboseGetItem([1,1,0])]) 0 1 2 3 0 1 2 0 1 2 False >>> all_in_double_gen([VerboseGetItem([1,1,1]),VerboseGetItem([1,0,1]),VerboseGetItem([1,1])]) 0 1 2 3 0 1 False """ cdef int x return all(x for L in seq for x in L) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/run/altet2.pyx0000644000175100001770000000032500000000000017477 0ustar00runnerdocker00000000000000__doc__ = u""" >>> iter(C()) # doctest: +ELLIPSIS Traceback (most recent call last): TypeError: iter() returned non-iterator... """ cdef class C: def __iter__(self): "This is a doc string." ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/run/always_allow_keywords_T295.pyx0000644000175100001770000001277700000000000023472 0ustar00runnerdocker00000000000000# mode: run # ticket: t295 cimport cython import sys IS_PY2 = sys.version_info[0] == 2 def assert_typeerror_no_keywords(func, *args, **kwds): # Python 3.9 produces an slightly different error message # to previous versions, so doctest isn't matching the # traceback try: func(*args, **kwds) except TypeError as e: assert e.args[0].endswith(" takes no keyword arguments"), e.args[0] else: assert False, "call did not raise TypeError" def func0(): """ >>> func0() >>> func0(**{}) """ def func1(arg): """ >>> func1(None) >>> func1(*[None]) >>> func1(arg=None) """ return arg def func1_unused(arg): """ >>> func1_unused(None) >>> func1_unused(*[None]) >>> func1_unused(arg=None) """ @cython.always_allow_keywords(False) def func2(arg): """ >>> func2(None) >>> func2(*[None]) >>> assert_typeerror_no_keywords(func2, arg=None) """ return arg @cython.always_allow_keywords(False) def func2_unused(arg): """ >>> func2_unused(None) >>> func2_unused(*[None]) >>> assert_typeerror_no_keywords(func2_unused, arg=None) """ @cython.always_allow_keywords(True) def func3(arg): """ >>> func3(None) >>> func3(*[None]) >>> func3(arg=None) """ return arg @cython.always_allow_keywords(True) def func3_unused(arg): """ >>> func3_unused(None) >>> func3_unused(*[None]) >>> func3_unused(arg=None) """ cdef class A: """ >>> class PyA(object): ... def meth0(self): pass ... def meth1(self, arg): pass >>> PyA().meth0() >>> PyA.meth0(PyA()) >>> if not IS_PY2: PyA.meth0(self=PyA()) >>> try: PyA().meth0(self=PyA()) ... except TypeError as exc: assert 'multiple' in str(exc), "Unexpected message: %s" % exc ... else: assert False, "No TypeError when passing 'self' argument twice" >>> PyA().meth1(1) >>> PyA.meth1(PyA(), 1) >>> PyA.meth1(PyA(), arg=1) >>> if not IS_PY2: PyA.meth1(self=PyA(), arg=1) """ @cython.always_allow_keywords(False) def meth0_nokw(self): """ >>> A().meth0_nokw() >>> A().meth0_nokw(**{}) >>> try: pass #A.meth0_nokw(self=A()) ... except TypeError as exc: assert 'needs an argument' in str(exc), "Unexpected message: %s" % exc ... else: pass #assert False, "No TypeError for missing 'self' positional argument" """ @cython.always_allow_keywords(True) def meth0_kw(self): """ >>> A().meth0_kw() >>> A().meth0_kw(**{}) >>> A.meth0_kw(A()) >>> #A.meth0_kw(self=A()) >>> try: pass #A().meth0_kw(self=A()) ... except TypeError as exc: assert 'multiple' in str(exc), "Unexpected message: %s" % exc ... else: pass #assert False, "No TypeError when passing 'self' argument twice" """ @cython.always_allow_keywords(True) def meth1_kw(self, arg): """ >>> A().meth1_kw(None) >>> A().meth1_kw(*[None]) >>> A().meth1_kw(arg=None) >>> A.meth1_kw(A(), arg=None) >>> #A.meth1_kw(self=A(), arg=None) """ @cython.always_allow_keywords(False) def meth1_nokw(self, arg): """ >>> A().meth1_nokw(None) >>> A().meth1_nokw(*[None]) >>> assert_typeerror_no_keywords(A().meth1_nokw, arg=None) >>> assert_typeerror_no_keywords(A.meth1_nokw, A(), arg=None) >>> try: pass # A.meth1_nokw(self=A(), arg=None) ... except TypeError as exc: assert 'needs an argument' in str(exc), "Unexpected message: %s" % exc ... else: pass # assert False, "No TypeError for missing 'self' positional argument" """ @cython.always_allow_keywords(False) def meth2(self, arg): """ >>> A().meth2(None) >>> A().meth2(*[None]) >>> assert_typeerror_no_keywords(A().meth2, arg=None) """ @cython.always_allow_keywords(True) def meth3(self, arg): """ >>> A().meth3(None) >>> A().meth3(*[None]) >>> A().meth3(arg=None) """ class B(object): @cython.always_allow_keywords(False) def meth0_nokw(self): """ >>> B().meth0_nokw() >>> B().meth0_nokw(**{}) >>> if not IS_PY2: assert_typeerror_no_keywords(B.meth0_nokw, self=B()) """ @cython.always_allow_keywords(True) def meth0_kw(self): """ >>> B().meth0_kw() >>> B().meth0_kw(**{}) >>> B.meth0_kw(B()) >>> if not IS_PY2: B.meth0_kw(self=B()) >>> try: B().meth0_kw(self=B()) ... except TypeError as exc: assert 'multiple' in str(exc), "Unexpected message: %s" % exc ... else: assert False, "No TypeError when passing 'self' argument twice" """ @cython.always_allow_keywords(True) def meth1(self, arg): """ >>> B().meth1(None) >>> B().meth1(*[None]) >>> B().meth1(arg=None) >>> B.meth1(B(), arg=None) >>> if not IS_PY2: B.meth1(self=B(), arg=None) """ @cython.always_allow_keywords(False) def meth2(self, arg): """ >>> B().meth2(None) >>> B().meth2(*[None]) >>> B.meth2(B(), None) >>> if not IS_PY2: B.meth2(self=B(), arg=None) >>> B().meth2(arg=None) # assert_typeerror_no_keywords(B().meth2, arg=None) -> not a cdef class! """ @cython.always_allow_keywords(True) def meth3(self, arg): """ >>> B().meth3(None) >>> B().meth3(*[None]) >>> B().meth3(arg=None) """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/run/and.pyx0000644000175100001770000000255100000000000017051 0ustar00runnerdocker00000000000000a,b = 'a *','b *' # use non-interned strings def and2_assign(a,b): """ >>> a,b = 'a *','b *' # use non-interned strings >>> and2_assign(2,3) == (2 and 3) True >>> and2_assign('a', 'b') == ('a' and 'b') True >>> and2_assign(a, b) == (a and b) True """ c = a and b return c def and2(a,b): """ >>> and2(2,3) == (2 and 3) True >>> and2(0,2) == (0 and 2) True >>> and2('a', 'b') == ('a' and 'b') True >>> and2(a, b) == (a and b) True >>> and2('', 'b') == ('' and 'b') True >>> and2([], [1]) == ([] and [1]) True >>> and2([], [a]) == ([] and [a]) True """ return a and b def and3(a,b,c): """ >>> and3(0,1,2) == (0 and 1 and 2) True >>> and3([],(),[1]) == ([] and () and [1]) True """ d = a and b and c return d def and2_no_result(a,b): """ >>> and2_no_result(2,3) >>> and2_no_result(0,2) >>> and2_no_result('a','b') >>> and2_no_result(a,b) >>> a and b 'b *' """ a and b def and2_literal(): """ >>> and2_literal() 5 """ return True and 5 def c_int_results(int x): """ >>> c_int_results(7) (0, 0) >>> c_int_results(5) (1, 1) """ cdef int expr1, expr2, r1, r2 expr1 = x == 5 expr2 = 1 r1 = expr1 and expr2 r2 = (x==5) and 1 return r1, r2 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222 Cython-3.0.8/tests/run/annotate_html.pyx0000644000175100001770000000301400000000000021137 0ustar00runnerdocker00000000000000# cython: test_assert_c_code_has = Generated by Cython # cython: test_assert_c_code_has = goto __pyx_L0;\n """ >>> from codecs import open >>> import os.path as os_path >>> module_path = os_path.join(os_path.dirname(__file__), os_path.basename(__file__).split('.', 1)[0]) >>> assert module_path.endswith('annotate_html') >>> assert os_path.exists(module_path + '.c') or os_path.exists(module_path + '.cpp'), module_path >>> assert os_path.exists(module_path + '.html'), module_path >>> with open(module_path + '.html', 'r', 'utf8') as html_file: ... html = html_file.read() >>> import re >>> assert re.search('
', html)
>>> from Cython.Compiler.Annotate import AnnotationCCodeWriter
>>> assert (AnnotationCCodeWriter.COMPLETE_CODE_TITLE not in html) # per default no complete c code
"""


def mixed_test():
    """docstring
    """
    cdef int int1, int2, int3
    cdef char *ptr1, *ptr2 = "test", *ptr3 = "toast"
    int2 = 10
    int3 = 20
    obj1 = 1
    obj2 = 2
    obj3 = 3
    int1 = int2 + int3
    ptr1 = ptr2 + int3
    ptr1 = int2 + ptr3
    obj1 = obj2 + int3
    return int1, obj1


def add_x_1(int x):
    return x + 1


def add_x_1f(x):
    return x + 1.0


def add_x_large(x):
    return x + 2**30


def add_1_x(x):
    return 1 + x


def add_1f_x(double x):
    return 1.0 + x


def add_large_x(x):
    return 2**30 + x


class PythonClass(object):
    def call(self, x):
        return add_1_x(x)


cdef class ExtensionType(object):
    @classmethod
    def new(cls):
        return cls()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/annotation_typing.pyx0000644000175100001770000003021300000000000022047 0ustar00runnerdocker00000000000000# mode: run
# tag: pep484, warnings

cimport cython
from cython cimport typeof
from cpython.ref cimport PyObject

try:
    from typing import Optional
except ImportError:
    pass


def old_dict_syntax(a: list, b: "int" = 2, c: {'ctype': 'long int'} = 3, d: {'type': 'long int'} = 4) -> list:
    """
    >>> old_dict_syntax([1])
    ('list object', 'Python object', 'long', 'long')
    [1, 2, 3, 4]
    >>> old_dict_syntax([1], 3)
    ('list object', 'Python object', 'long', 'long')
    [1, 3, 3, 4]
    >>> old_dict_syntax(123)
    Traceback (most recent call last):
    TypeError: Argument 'a' has incorrect type (expected list, got int)
    >>> old_dict_syntax(None)
    Traceback (most recent call last):
    TypeError: Argument 'a' has incorrect type (expected list, got NoneType)
    """
    print(typeof(a), typeof(b), typeof(c), typeof(d))
    a.append(b)
    a.append(c)
    a.append(d)
    return a


def pytypes_def(a: list, b: int = 2, c: long = 3, d: float = 4.0, n: list = None, o: Optional[tuple] = ()) -> list:
    """
    >>> pytypes_def([1])
    ('list object', 'Python object', 'Python object', 'double', 'list object', 'tuple object')
    [1, 2, 3, 4.0, None, ()]
    >>> pytypes_def([1], 3)
    ('list object', 'Python object', 'Python object', 'double', 'list object', 'tuple object')
    [1, 3, 3, 4.0, None, ()]
    >>> pytypes_def([1], 3, 2, 1, [], None)
    ('list object', 'Python object', 'Python object', 'double', 'list object', 'tuple object')
    [1, 3, 2, 1.0, [], None]
    >>> pytypes_def(123)
    Traceback (most recent call last):
    TypeError: Argument 'a' has incorrect type (expected list, got int)
    >>> pytypes_def(None)
    Traceback (most recent call last):
    TypeError: Argument 'a' has incorrect type (expected list, got NoneType)
    """
    print(typeof(a), typeof(b), typeof(c), typeof(d), typeof(n), typeof(o))
    a.append(b)
    a.append(c)
    a.append(d)
    a.append(n)
    a.append(o)
    return a


cpdef pytypes_cpdef(a: list, b: int = 2, c: long = 3, d: float = 4.0, n: list = None, o: Optional[tuple] = ()):
    """
    >>> pytypes_cpdef([1])
    ('list object', 'Python object', 'Python object', 'double', 'list object', 'tuple object')
    [1, 2, 3, 4.0, None, ()]
    >>> pytypes_cpdef([1], 3)
    ('list object', 'Python object', 'Python object', 'double', 'list object', 'tuple object')
    [1, 3, 3, 4.0, None, ()]
    >>> pytypes_cpdef([1], 3, 2, 1, [], None)
    ('list object', 'Python object', 'Python object', 'double', 'list object', 'tuple object')
    [1, 3, 2, 1.0, [], None]
    >>> pytypes_cpdef(123)
    Traceback (most recent call last):
    TypeError: Argument 'a' has incorrect type (expected list, got int)
    >>> pytypes_cpdef(None)
    Traceback (most recent call last):
    TypeError: Argument 'a' has incorrect type (expected list, got NoneType)
    """
    print(typeof(a), typeof(b), typeof(c), typeof(d), typeof(n), typeof(o))
    a.append(b)
    a.append(c)
    a.append(d)
    a.append(n)
    a.append(o)
    return a


cdef c_pytypes_cdef(a: list, b: int = 2, c: long = 3, d: float = 4.0, n: list = None):
    print(typeof(a), typeof(b), typeof(c), typeof(d), typeof(n))
    a.append(b)
    a.append(c)
    a.append(d)
    a.append(n)
    return a


def pytypes_cdef(a, b=2, c=3, d=4):
    """
    >>> pytypes_cdef([1])
    ('list object', 'Python object', 'Python object', 'double', 'list object')
    [1, 2, 3, 4.0, None]
    >>> pytypes_cdef([1], 3)
    ('list object', 'Python object', 'Python object', 'double', 'list object')
    [1, 3, 3, 4.0, None]
    >>> pytypes_cdef(123)   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    return c_pytypes_cdef(a, b, c, d)


def pyint(a: int):
    """
    >>> large_int = eval('0x'+'F'*64)  # definitely bigger than C int64
    >>> pyint(large_int) == large_int
    True
    """
    return a


def ctypes_def(a: list, b: cython.int = 2, c: cython.long = 3, d: cython.float = 4) -> list:
    """
    >>> ctypes_def([1])
    ('list object', 'int', 'long', 'float')
    [1, 2, 3, 4.0]
    >>> ctypes_def([1], 3)
    ('list object', 'int', 'long', 'float')
    [1, 3, 3, 4.0]
    >>> ctypes_def(123)
    Traceback (most recent call last):
    TypeError: Argument 'a' has incorrect type (expected list, got int)
    """
    print(typeof(a), typeof(b), typeof(c), typeof(d))
    a.append(b)
    a.append(c)
    a.append(d)
    return a


def return_tuple_for_carray() -> tuple:
    """
    >>> return_tuple_for_carray()
    (1, 2, 3)
    """
    cdef int[3] x
    x = [1, 2, 3]
    return x


def invalid_ctuple_syntax(a: (cython.int, cython.int), b: (int, int)):
    """
    >>> invalid_ctuple_syntax([1, 2], [3, 4])
    [1, 2, 3, 4]
    """
    result: (cython.int, cython.int, cython.int, cython.int) = a + b
    return result


MyStruct = cython.struct(x=cython.int, y=cython.int, data=cython.double)


@cython.ccall
def struct_io(s : MyStruct) -> MyStruct:
    """
    >>> d = struct_io(dict(x=1, y=2, data=3))
    >>> sorted(d.items())
    [('data', 3.0), ('x', 2), ('y', 1)]
    >>> d = struct_io(None)
    Traceback (most recent call last):
    TypeError: Expected a mapping, got NoneType
    """
    t = s
    t.x, t.y = s.y, s.x
    return t


@cython.test_fail_if_path_exists(
    "//CoerceFromPyTypeNode",
    "//SimpleCallNode//CoerceToPyTypeNode",
)
@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//CoerceToPyTypeNode//SimpleCallNode",
)
def call_struct_io(s : MyStruct) -> MyStruct:
    """
    >>> d = call_struct_io(dict(x=1, y=2, data=3))
    >>> sorted(d.items())
    [('data', 3.0), ('x', 2), ('y', 1)]
    >>> d = call_struct_io(None)
    Traceback (most recent call last):
    TypeError: Expected a mapping, got NoneType
    """
    return struct_io(s)


@cython.test_assert_path_exists(
    "//CFuncDefNode",
    "//CFuncDefNode//DefNode",
    "//CFuncDefNode[@return_type]",
    "//CFuncDefNode[@return_type.is_struct_or_union = True]",
)
@cython.ccall
def struct_convert(d) -> MyStruct:
    """
    >>> d = struct_convert(dict(x=1, y=2, data=3))
    >>> sorted(d.items())
    [('data', 3.0), ('x', 1), ('y', 2)]
    >>> struct_convert({})  # make sure we can raise exceptions through struct return values
    Traceback (most recent call last):
    ValueError: No value specified for struct attribute 'x'
    """
    return d


@cython.test_assert_path_exists(
    "//CFuncDefNode",
    "//CFuncDefNode//DefNode",
    "//CFuncDefNode[@return_type]",
    "//CFuncDefNode[@return_type.is_int = True]",
)
@cython.ccall
def exception_default(raise_exc : cython.bint = False) -> cython.int:
    """
    >>> exception_default(raise_exc=False)
    10
    >>> exception_default(raise_exc=True)
    Traceback (most recent call last):
    ValueError: huhu!
    """
    if raise_exc:
        raise ValueError("huhu!")
    return 10


def call_exception_default(raise_exc=False):
    """
    >>> call_exception_default(raise_exc=False)
    10
    >>> call_exception_default(raise_exc=True)
    Traceback (most recent call last):
    ValueError: huhu!
    """
    return exception_default(raise_exc)


@cython.test_assert_path_exists(
    "//CFuncDefNode",
    "//CFuncDefNode//DefNode",
    "//CFuncDefNode[@return_type]",
    "//CFuncDefNode[@return_type.is_int = True]",
)
@cython.ccall
def exception_default_uint(raise_exc : cython.bint = False) -> cython.uint:
    """
    >>> print(exception_default_uint(raise_exc=False))
    10
    >>> exception_default_uint(raise_exc=True)
    Traceback (most recent call last):
    ValueError: huhu!
    """
    if raise_exc:
        raise ValueError("huhu!")
    return 10


def call_exception_default_uint(raise_exc=False):
    """
    >>> print(call_exception_default_uint(raise_exc=False))
    10
    >>> call_exception_default_uint(raise_exc=True)
    Traceback (most recent call last):
    ValueError: huhu!
    """
    return exception_default_uint(raise_exc)


class EarlyClass(object):
    """
    >>> a = EarlyClass(1)
    >>> a.string_forward_declaration()  # should probably raise an error at some point
    1
    >>> x = LateClass()
    >>> a = EarlyClass(x)
    >>> x2 = a.string_forward_declaration()
    >>> assert x is x2, x2
    """
    def __init__(self, x):
        self.x = x
    def string_forward_declaration(self) -> 'LateClass':
        return self.x

class LateClass(object):
    pass


def py_float_default(price : Optional[float]=None, ndigits=4):
    """
    Python default arguments should prevent C type inference.

    >>> py_float_default()
    (None, 4)
    >>> py_float_default(None)
    (None, 4)
    >>> py_float_default(2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...float...
    >>> py_float_default(2.0)
    (2.0, 4)
    >>> py_float_default(2, 3)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...float...
    """
    return price, ndigits


cdef class ClassAttribute:
    cls_attr : cython.float = 1.


@cython.cfunc
def take_ptr(obj: cython.pointer(PyObject)):
    pass

def call_take_ptr():
    """
    >>> call_take_ptr()  # really just a compile-test
    """
    python_dict = {"abc": 123}
    take_ptr(cython.cast(cython.pointer(PyObject), python_dict))

@cython.cclass
class HasPtr:
    """
    >>> HasPtr()
    HasPtr(1, 1)
    """
    a: cython.pointer(cython.int)
    b: cython.int

    def __init__(self):
        self.b = 1
        self.a = cython.address(self.b)
    def __repr__(self):
        return f"HasPtr({self.a[0]}, {self.b})"


@cython.annotation_typing(False)
def turn_off_typing(x: float, d: dict):
    """
    >>> turn_off_typing('not a float', [])  # ignore the typing
    ('Python object', 'Python object', 'not a float', [])
    """
    return typeof(x), typeof(d), x, d


@cython.annotation_typing(False)
cdef class ClassTurnOffTyping:
    x: float
    d: dict

    def get_var_types(self, arg: float):
        """
        >>> ClassTurnOffTyping().get_var_types(1.0)
        ('Python object', 'Python object', 'Python object')
        """
        return typeof(self.x), typeof(self.d), typeof(arg)

    @cython.annotation_typing(True)
    def and_turn_it_back_on_again(self, arg: float):
        """
        >>> ClassTurnOffTyping().and_turn_it_back_on_again(1.0)
        ('Python object', 'Python object', 'double')
        """
        return typeof(self.x), typeof(self.d), typeof(arg)


from cython cimport int as cy_i


def int_alias(a: cython.int, b: cy_i):
    """
    >>> int_alias(1, 2)
    int
    int
    """
    print(cython.typeof(a))
    print(cython.typeof(b))


_WARNINGS = """
14:32: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
14:47: Dicts should no longer be used as type annotations. Use 'cython.int' etc. directly.
14:56: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
14:77: Dicts should no longer be used as type annotations. Use 'cython.int' etc. directly.
14:85: Python type declaration in signature annotation does not refer to a Python type
14:85: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
36:40: Found Python 2.x type 'long' in a Python annotation. Did you mean to use 'cython.long'?
36:66: PEP-484 recommends 'typing.Optional[...]' for arguments that can be None.
63:44: Found Python 2.x type 'long' in a Python annotation. Did you mean to use 'cython.long'?
63:70: PEP-484 recommends 'typing.Optional[...]' for arguments that can be None.
90:44: Found Python 2.x type 'long' in a Python annotation. Did you mean to use 'cython.long'?
90:70: PEP-484 recommends 'typing.Optional[...]' for arguments that can be None.
152:30: Tuples cannot be declared as simple tuples of types. Use 'tuple[type1, type2, ...]'.
152:59: Tuples cannot be declared as simple tuples of types. Use 'tuple[type1, type2, ...]'.
157:13: Tuples cannot be declared as simple tuples of types. Use 'tuple[type1, type2, ...]'.
292:44: Unknown type declaration in annotation, ignoring
320:15: Annotation ignored since class-level attributes must be Python objects. Were you trying to set up an instance attribute?
# DUPLICATE:
63:44: Found Python 2.x type 'long' in a Python annotation. Did you mean to use 'cython.long'?
# BUG:
63:6: 'pytypes_cpdef' redeclared
164:0: 'struct_io' redeclared
199:0: 'struct_convert' redeclared
218:0: 'exception_default' redeclared
249:0: 'exception_default_uint' redeclared
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/anonymousenum.pyx0000644000175100001770000000014100000000000021215 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> p
42
"""

cdef enum:
    spam = 42
    grail = 17

cdef int i
i = spam

p = i
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/any.pyx0000644000175100001770000001245100000000000017076 0ustar00runnerdocker00000000000000
cdef class VerboseGetItem(object):
    cdef object sequence
    def __init__(self, seq):
        self.sequence = seq
    def __getitem__(self, i):
        print i
        return self.sequence[i] # may raise IndexError


cimport cython

@cython.test_assert_path_exists("//SimpleCallNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def any_item(x):
    """
    >>> any_item([0,0,1,0,0])
    True
    >>> any_item([0,0,0,0,1])
    True
    >>> any_item([0,0,0,0,0])
    False

    >>> any(VerboseGetItem([0,0,1,0,0]))
    0
    1
    2
    True
    >>> any_item(VerboseGetItem([0,0,1,0,0]))
    0
    1
    2
    True

    >>> any(VerboseGetItem([0,0,0,0,0]))
    0
    1
    2
    3
    4
    5
    False
    >>> any_item(VerboseGetItem([0,0,0,0,0]))
    0
    1
    2
    3
    4
    5
    False
    """
    return any(x)


@cython.test_assert_path_exists(
    "//ForInStatNode",
    "//InlinedGeneratorExpressionNode"
)
@cython.test_fail_if_path_exists(
    "//SimpleCallNode",
    "//YieldExprNode"
)
def any_in_simple_gen(seq):
    """
    >>> any_in_simple_gen([0,1,0])
    True
    >>> any_in_simple_gen([0,0,0])
    False

    >>> any_in_simple_gen(VerboseGetItem([0,0,1,0,0]))
    0
    1
    2
    True
    >>> any_in_simple_gen(VerboseGetItem([0,0,0,0,0]))
    0
    1
    2
    3
    4
    5
    False
    """
    return any(x for x in seq)


@cython.test_assert_path_exists(
    "//ForInStatNode",
    "//InlinedGeneratorExpressionNode"
)
@cython.test_fail_if_path_exists(
    "//SimpleCallNode",
    "//YieldExprNode"
)
def any_in_simple_gen_scope(seq):
    """
    >>> any_in_simple_gen_scope([0,1,0])
    True
    >>> any_in_simple_gen_scope([0,0,0])
    False

    >>> any_in_simple_gen_scope(VerboseGetItem([0,0,1,0,0]))
    0
    1
    2
    True
    >>> any_in_simple_gen_scope(VerboseGetItem([0,0,0,0,0]))
    0
    1
    2
    3
    4
    5
    False
    """
    x = 'abc'
    result = any(x for x in seq)
    assert x == 'abc'
    return result


@cython.test_assert_path_exists(
    "//ForInStatNode",
    "//InlinedGeneratorExpressionNode"
)
@cython.test_fail_if_path_exists(
    "//SimpleCallNode",
    "//YieldExprNode"
)
def any_in_conditional_gen(seq):
    """
    >>> any_in_conditional_gen([3,6,9])
    False
    >>> any_in_conditional_gen([0,3,7])
    True
    >>> any_in_conditional_gen([1,0,1])
    True

    >>> any_in_conditional_gen(VerboseGetItem([0,0,3,0,0]))
    0
    1
    2
    3
    4
    5
    False
    >>> any_in_conditional_gen(VerboseGetItem([0,3,0,1,1]))
    0
    1
    2
    3
    True
    """
    return any(x%3 for x in seq if x%2 == 1)

mixed_ustring = u'AbcDefGhIjKlmnoP'
lower_ustring = mixed_ustring.lower()
upper_ustring = mixed_ustring.upper()


@cython.test_assert_path_exists(
    '//PythonCapiCallNode',
    '//ForFromStatNode',
    "//InlinedGeneratorExpressionNode"
)
@cython.test_fail_if_path_exists(
    '//SimpleCallNode',
    '//ForInStatNode'
)
def any_lower_case_characters(unicode ustring):
    """
    >>> any_lower_case_characters(upper_ustring)
    False
    >>> any_lower_case_characters(mixed_ustring)
    True
    >>> any_lower_case_characters(lower_ustring)
    True
    """
    return any(uchar.islower() for uchar in ustring)


@cython.test_assert_path_exists(
    "//ForInStatNode",
    "//InlinedGeneratorExpressionNode",
    "//InlinedGeneratorExpressionNode//IfStatNode"
)
@cython.test_fail_if_path_exists(
    "//SimpleCallNode",
    "//YieldExprNode",
#    "//IfStatNode//CoerceToBooleanNode"
)
def any_in_typed_gen(seq):
    """
    >>> any_in_typed_gen([0,1,0])
    True
    >>> any_in_typed_gen([0,0,0])
    False

    >>> any_in_typed_gen(VerboseGetItem([0,0,1,0,0]))
    0
    1
    2
    True
    >>> any_in_typed_gen(VerboseGetItem([0,0,0,0,0]))
    0
    1
    2
    3
    4
    5
    False
    """
    cdef int x
    return any(x for x in seq)


@cython.test_assert_path_exists(
    "//ForInStatNode",
    "//InlinedGeneratorExpressionNode",
    "//InlinedGeneratorExpressionNode//IfStatNode"
)
@cython.test_fail_if_path_exists(
    "//SimpleCallNode",
    "//YieldExprNode"
)
def any_in_gen_builtin_name(seq):
    """
    >>> any_in_gen_builtin_name([0,1,0])
    True
    >>> any_in_gen_builtin_name([0,0,0])
    False

    >>> any_in_gen_builtin_name(VerboseGetItem([0,0,1,0,0]))
    0
    1
    2
    True
    >>> any_in_gen_builtin_name(VerboseGetItem([0,0,0,0,0]))
    0
    1
    2
    3
    4
    5
    False
    """
    return any(type for type in seq)


@cython.test_assert_path_exists(
    "//ForInStatNode",
    "//InlinedGeneratorExpressionNode",
    "//InlinedGeneratorExpressionNode//IfStatNode"
)
@cython.test_fail_if_path_exists(
    "//SimpleCallNode",
    "//YieldExprNode",
#    "//IfStatNode//CoerceToBooleanNode"
)
def any_in_double_gen(seq):
    """
    >>> any(x for L in [[0,0,0],[0,0,1],[0,0,0]] for x in L)
    True
    >>> any_in_double_gen([[0,0,0],[0,0,1],[0,0,0]])
    True

    >>> any(x for L in [[0,0,0],[0,0,0],[0,0,0]] for x in L)
    False
    >>> any_in_double_gen([[0,0,0],[0,0,0],[0,0,0]])
    False

    >>> any_in_double_gen([VerboseGetItem([0,0,0]), VerboseGetItem([0,0,1,0,0])])
    0
    1
    2
    3
    0
    1
    2
    True
    >>> any_in_double_gen([VerboseGetItem([0,0,0]),VerboseGetItem([0,0]),VerboseGetItem([0,0,0])])
    0
    1
    2
    3
    0
    1
    2
    0
    1
    2
    3
    False
    """
    cdef int x
    return any(x for L in seq for x in L)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/append.pyx0000644000175100001770000000457700000000000017570 0ustar00runnerdocker00000000000000cimport cython

class A:
    def append(self, x):
        print u"appending", x
        return x

class B(list):
    def append(self, *args):
        for arg in args:
            list.append(self, arg)

cdef class C:
    """
    >>> c = C(100)
    appending 100
    """
    def __init__(self, value):
        self.append(value)
    cdef append(self, value):
        print u"appending", value
        return value

def test_append(L):
    """
    >>> test_append([])
    None
    None
    None
    got error
    [1, 2, (3, 4)]
    >>> _ = test_append(A())
    appending 1
    1
    appending 2
    2
    appending (3, 4)
    (3, 4)
    got error
    >>> test_append(B())
    None
    None
    None
    None
    [1, 2, (3, 4), 5, 6]
    """
    print L.append(1)
    print L.append(2)
    print L.append((3,4))
    try:
        print L.append(5,6)
    except TypeError:
        print u"got error"
    return L


def test_append_typed(list L not None):
    """
    >>> test_append_typed([])
    None
    None
    [1, 2, (3, 4)]
    """
    print L.append(1)
    L.append(2)
    print L.append((3,4))
    return L


def append_unused_retval(L):
    """
    >>> append_unused_retval([])
    got error
    [1, 2, (3, 4)]
    >>> _ = append_unused_retval(A())
    appending 1
    appending 2
    appending (3, 4)
    got error
    >>> append_unused_retval(B())
    [1, 2, (3, 4), 5, 6]
    """
    L.append(1)
    L.append(2)
    L.append((3,4))
    try:
        L.append(5,6)
    except TypeError:
        print u"got error"
    return L


def method_name():
    """
    >>> method_name()
    'append'
    """
    return [].append.__name__

@cython.test_assert_path_exists(
    '//PythonCapiCallNode')
def append_optimized(probably_list):
    """
    >>> l = []
    >>> append_optimized(l)
    >>> l
    [1]
    """
    probably_list.append(1)

cdef class AppendBug:
    # https://github.com/cython/cython/issues/4828
    # if the attribute "append" is found it shouldn't be replaced with
    # __Pyx_PyObject_Append
    cdef object append
    def __init__(self, append):
        self.append = append

@cython.test_fail_if_path_exists(
    '//PythonCapiCallNode')
def specific_attribute(AppendBug a):
    """
    >>> def append_to_default_arg(a, arg=[]):
    ...    arg.append(a)
    ...    return arg
    >>> specific_attribute(AppendBug(append_to_default_arg))
    >>> append_to_default_arg(None)
    [1, None]
    """
    a.append(1)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/arg_incref.pyx0000644000175100001770000000027100000000000020403 0ustar00runnerdocker00000000000000def f(dict d, x=4):
    """
    >>> f({1:1, 2:2})
    [1, 2]
    """
    cdef dict d_new = {}
    l = []
    for k in d:
        d = d_new
        l.append(k)
    l.sort()
    return l
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/argdefault.pyx0000644000175100001770000000275300000000000020431 0ustar00runnerdocker00000000000000GLB0 = (1, 2)
def f0(arg=GLB0):
    """
    >>> f0()
    (1, 2)
    """
    return arg
def g0(arg=(1, 2)):
    """
    >>> g0()
    (1, 2)
    """
    return arg


GLB1 = [1, 2]
def f1(arg=GLB1):
    """
    >>> f1()
    [1, 2]
    """
    return arg
def g1(arg=[1, 2]):
    """
    >>> g1()
    [1, 2]
    """
    return arg


cdef GLB2 = {1: 2}
def f2(arg=GLB2):
    """
    >>> f2()
    {1: 2}
    """
    return arg
def g2(arg={1: 2}):
    """
    >>> g2()
    {1: 2}
    """
    return arg


class Foo(object):
    pass
cdef GLB3 = Foo()
def f3(arg=GLB3):
    """
    >>> f3() #doctest: +ELLIPSIS
    
    """
    return arg
def g3(arg=Foo()):
    """
    >>> g3() #doctest: +ELLIPSIS
    
    """
    return arg


cdef class Bar:
    pass
cdef Bar GLB4 = Bar()
def f4(arg=GLB4):
    """
    >>> f4() #doctest: +ELLIPSIS
    
    """
    return arg
def g4(arg=Bar()):
    """
    >>> g4() #doctest: +ELLIPSIS
    
    """
    return arg


cdef class Bla:
    pass
cdef Bla GLB5 = Bla()
def f5(Bla arg=GLB5):
    """
    >>> f5() #doctest: +ELLIPSIS
    
    """
    return arg
def g5(Bla arg=Bla()):
    """
    >>> g5() #doctest: +ELLIPSIS
    
    """
    return arg


cdef int GLB6 = 7
def f6(int arg=GLB6):
    """
    >>> f6()
    7
    """
    return arg
def g6(int arg=7):
    """
    >>> g6()
    7
    """
    return arg
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/argerrors.py0000644000175100001770000000504200000000000020123 0ustar00runnerdocker00000000000000# mode: run
# tag: kwargs, argument unpacking

# This test validates the error handling in the different specialised
# code paths of the argument unpacking code.  The have-kwargs and
# no-kwargs branches take different paths, so we always test with and
# without a keyword dict (even if it's empty).

def test_single_arg(a):
    """
    >>> test_single_arg(1)
    1
    >>> test_single_arg(1, **{})
    1
    >>> test_single_arg()                  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> test_single_arg(1,2)               # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> test_single_arg(1,2, **{})         # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> test_single_arg(**{})              # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> test_single_arg(*(), **{})         # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> test_single_arg(**{'b':2})         # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> test_single_arg(**{'a':1, 'b':2})  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    return a

def test_two_args(a,b):
    """
    >>> test_two_args(1,2)
    (1, 2)
    >>> test_two_args(1,2, **{})
    (1, 2)
    >>> test_two_args(1,**{'b':2})
    (1, 2)
    >>> test_two_args(**{'a':1, 'b':2})
    (1, 2)
    >>> test_two_args()                 # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> test_two_args(1)                # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> test_two_args(1, **{})          # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> test_two_args(1,2,3)            # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> test_two_args(1,2,3, **{})      # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> test_two_args(**{})             # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> test_two_args(*(), **{})        # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> test_two_args(**{'a':1})        # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> test_two_args(**{'a':1, 'b':2, 'c':3})  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    return a,b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/args_unpacking_in_closure_T658.pyx0000644000175100001770000000053400000000000024251 0ustar00runnerdocker00000000000000# mode: run
# tag: closures
# ticket: t658

def outer(int x, *args, **kwargs):
    """
    >>> inner = outer(1, 2, a=3)
    >>> inner()
    (1, (2,), {'a': 3})

    >>> inner = outer('abc', 2, a=3)
    Traceback (most recent call last):
    TypeError: an integer is required
    """
    def inner():
        return x, args, kwargs
    return inner
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/argument_unpacking_closure_T736.py0000644000175100001770000000102700000000000024254 0ustar00runnerdocker00000000000000# mode: run
# ticket: t736
# tag: default arguments, closure

def default_args_for_closure(a=1, b=2):
    """
    >>> default_args_for_closure()()
    (1, 2)
    >>> default_args_for_closure(1, 2)()
    (1, 2)
    >>> default_args_for_closure(2)()
    (2, 2)
    >>> default_args_for_closure(8,9)()
    (8, 9)
    >>> default_args_for_closure(7, b=6)()
    (7, 6)
    >>> default_args_for_closure(a=5, b=4)()
    (5, 4)
    >>> default_args_for_closure(b=5, a=6)()
    (6, 5)
    """
    def func():
        return a,b
    return func
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/arithmetic_analyse_types.pyx0000644000175100001770000000272700000000000023405 0ustar00runnerdocker00000000000000# ticket: t676
# tag: cpp

from cython cimport typeof

cdef extern from "arithmetic_analyse_types_helper.h":
    cdef struct short_return:
        char *msg
    cdef struct int_return:
        char *msg
    cdef struct longlong_return:
        char *msg
    cdef short_return f(short)
    cdef int_return f(int)
    cdef longlong_return f(long long)

def short_binop(short val):
    """
    Arithmetic in C is always done with at least int precision.
    
    >>> print(short_binop(3))
    int called
    """
    assert typeof(val + val) == "int", typeof(val + val)
    assert typeof(val - val) == "int", typeof(val - val)
    assert typeof(val & val) == "int", typeof(val & val)
    cdef int_return x = f(val + val)
    return x.msg.decode('ASCII')

def short_unnop(short val):
    """
    Arithmetic in C is always done with at least int precision.
    
    >>> print(short_unnop(3))
    int called
    """
    cdef int_return x = f(-val)
    return x.msg.decode('ASCII')

def longlong_binop(long long val):
    """
    >>> print(longlong_binop(3))
    long long called
    """
    cdef longlong_return x = f(val * val)
    return x.msg.decode('ASCII')

def longlong_unnop(long long val):
    """
    >>> print(longlong_unnop(3))
    long long called
    """
    cdef longlong_return x = f(~val)
    return x.msg.decode('ASCII')


def test_bint(bint a):
    """
    >>> test_bint(True)
    """
    assert typeof(a + a) == "int", typeof(a + a)
    assert typeof(a & a) == "bint", typeof(a & a)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/arithmetic_analyse_types_helper.h0000644000175100001770000000105600000000000024345 0ustar00runnerdocker00000000000000/* A set of mutually incompatible return types. */

struct short_return { char *msg; };
struct int_return { char *msg; };
struct longlong_return { char *msg; };

/* A set of overloaded methods. */

short_return f(short arg) {
    short_return val;
    arg++;
    val.msg = (char*)"short called";
    return val;
}

int_return f(int arg) {
    int_return val;
    arg++;
    val.msg = (char*)"int called";
    return val;
}

longlong_return f(long long arg) {
    longlong_return val;
    arg++;
    val.msg = (char*)"long long called";
    return val;
}
 
 
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/array_address.pyx0000644000175100001770000000043500000000000021131 0ustar00runnerdocker00000000000000ctypedef int five_ints[5]

def test_array_address(int ix, int x):
    """
    >>> test_array_address(0, 100)
    100
    >>> test_array_address(2, 200)
    200
    """
    cdef five_ints a
    a[:] = [1, 2, 3, 4, 5]
    cdef five_ints *a_ptr = &a
    a_ptr[0][ix] = x
    return a[ix]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/array_cimport.srctree0000644000175100001770000000116200000000000022006 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import ttt"

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup

setup(
  ext_modules = cythonize("*.pyx"),
)


######## tt.pxd ########

from cpython.array cimport array

cdef class Foo:
    cdef array obj

######## tt.pyx ########

cdef class Foo:
    def __init__(self, data):
        self.obj = data

######## ttt.pyx ########

from array import array
from cpython.array cimport array
from tt cimport Foo

cdef array a = array('i', [1,2,3])
cdef Foo x
print(a.data.as_ints[0])
x = Foo(a)
print(x.obj.data.as_ints[0])
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/arrayassign.pyx0000644000175100001770000002247600000000000020642 0ustar00runnerdocker00000000000000# mode: run

cimport cython

def test_literal_list():
    """
    >>> test_literal_list()
    (1, 2, 3, 4, 5)
    """
    cdef int a[5]
    a = [1,2,3,4,5]
    return (a[0], a[1], a[2], a[3], a[4])

def test_literal_list_multiplied():
    """
    >>> test_literal_list_multiplied()
    (1, 2, 1, 2, 1, 2)
    """
    cdef int a[6]
    a = [1,2] * 3
    return (a[0], a[1], a[2], a[3], a[4], a[5])

def test_literal_list_slice_all():
    """
    >>> test_literal_list_slice_all()
    (1, 2, 3, 4, 5)
    """
    cdef int a[5] # = [5,4,3,2,1]
    a[:] = [1,2,3,4,5]
    return (a[0], a[1], a[2], a[3], a[4])

def test_literal_list_slice_start():
    """
    >>> test_literal_list_slice_start()
    (1, 2, 3, 4, 5)
    """
    cdef int a[7] # = [7,6,5,4,3,2,1]
    a[2:] = [1,2,3,4,5]
    return (a[2], a[3], a[4], a[5], a[6])

def test_literal_list_slice_end():
    """
    >>> test_literal_list_slice_end()
    (1, 2, 3, 4, 5)
    """
    cdef int a[7] # = [7,6,5,4,3,2,1]
    a[:5] = [1,2,3,4,5]
    return (a[0], a[1], a[2], a[3], a[4])

def test_literal_list_slice_start_end():
    """
    >>> test_literal_list_slice_start_end()
    (1, 2, 3, 4, 5)
    """
    cdef int a[9] # = [9,8,7,6,5,4,3,2,1]
    a[2:7] = [1,2,3,4,5]
    return (a[2], a[3], a[4], a[5], a[6])

def test_literal_list_slice_start_param(s):
    """
    >>> test_literal_list_slice_start_param(4)
    (1, 2, 3, 4, 5)
    >>> test_literal_list_slice_start_param(3)
    Traceback (most recent call last):
    ValueError: Assignment to slice of wrong length, expected 5, got 6
    >>> test_literal_list_slice_start_param(5)
    Traceback (most recent call last):
    ValueError: Assignment to slice of wrong length, expected 5, got 4
    """
    cdef int a[9] # = [9,8,7,6,5,4,3,2,1]
    a[s:] = [1,2,3,4,5]
    return (a[4], a[5], a[6], a[7], a[8])
#    return a[s:]

def test_literal_list_slice_end_param(e):
    """
    >>> test_literal_list_slice_end_param(5)
    (1, 2, 3, 4, 5)
    >>> test_literal_list_slice_end_param(4)
    Traceback (most recent call last):
    ValueError: Assignment to slice of wrong length, expected 5, got 4
    >>> test_literal_list_slice_end_param(6)
    Traceback (most recent call last):
    ValueError: Assignment to slice of wrong length, expected 5, got 6
    """
    cdef int a[9] # = [9,8,7,6,5,4,3,2,1]
    a[:e] = [1,2,3,4,5]
    return (a[0], a[1], a[2], a[3], a[4])
#    return a[:e]

def test_literal_list_slice_start_end_param(s,e):
    """
    >>> test_literal_list_slice_start_end_param(2,7)
    (1, 2, 3, 4, 5)
    >>> test_literal_list_slice_start_end_param(3,7)
    Traceback (most recent call last):
    ValueError: Assignment to slice of wrong length, expected 5, got 4
    >>> test_literal_list_slice_start_end_param(1,7)
    Traceback (most recent call last):
    ValueError: Assignment to slice of wrong length, expected 5, got 6
    >>> test_literal_list_slice_start_end_param(2,6)
    Traceback (most recent call last):
    ValueError: Assignment to slice of wrong length, expected 5, got 4
    >>> test_literal_list_slice_start_end_param(2,8)
    Traceback (most recent call last):
    ValueError: Assignment to slice of wrong length, expected 5, got 6
    >>> test_literal_list_slice_start_end_param(3,6)
    Traceback (most recent call last):
    ValueError: Assignment to slice of wrong length, expected 5, got 3
    >>> test_literal_list_slice_start_end_param(1,8)
    Traceback (most recent call last):
    ValueError: Assignment to slice of wrong length, expected 5, got 7
    """
    cdef int a[9] # = [9,8,7,6,5,4,3,2,1]
    a[s:e] = [1,2,3,4,5]
    return (a[2], a[3], a[4], a[5], a[6])
#    return a[s:e]

def test_ptr_literal_list_slice_all():
    """
    >>> test_ptr_literal_list_slice_all()
    (1, 2, 3, 4, 5)
    """
    cdef int *a = [6,5,4,3,2]
    a[:] = [1,2,3,4,5]
    return (a[0], a[1], a[2], a[3], a[4])

def test_ptr_literal_list_slice_start():
    """
    >>> test_ptr_literal_list_slice_start()
    (1, 2, 3, 4, 5)
    """
    cdef int *a = [6,5,4,3,2,1]
    a[1:] = [1,2,3,4,5]
    return (a[1], a[2], a[3], a[4], a[5])

def test_ptr_literal_list_slice_end():
    """
    >>> test_ptr_literal_list_slice_end()
    (1, 2, 3, 4, 5)
    """
    cdef int *a = [6,5,4,3,2,1]
    a[:5] = [1,2,3,4,5]
    return (a[0], a[1], a[2], a[3], a[4])


@cython.test_assert_path_exists(
    '//ReturnStatNode//CoerceToPyTypeNode'
)
def test_starred_from_array():
    """
    >>> test_starred_from_array()
    (1, [2, 3, 4], 5)
    """
    cdef int[5] a
    a[0] = 1
    a[1] = 2
    a[2] = 3
    a[3] = 4
    a[4] = 5
    x, *y, z = a
    return x, y, z


@cython.test_fail_if_path_exists(
    '//ParallelAssignmentNode//CoerceToPyTypeNode',
    '//ParallelAssignmentNode//CoerceFromPyTypeNode',
)
@cython.test_assert_path_exists(
    '//ParallelAssignmentNode',
    '//ReturnStatNode//CoerceToPyTypeNode'
)
def test_multiple_from_array():
    """
    >>> test_multiple_from_array()
    (1, 2, 3)
    """
    cdef int[3] a
    a[0] = 1
    a[1] = 2
    a[2] = 3
    x, y, z = a
    return x, y, z


@cython.test_fail_if_path_exists(
    '//ParallelAssignmentNode//CoerceToPyTypeNode'
)
@cython.test_assert_path_exists(
    '//ParallelAssignmentNode',
    '//ReturnStatNode//CoerceToPyTypeNode'
)
def test_multiple_from_array_full_slice():
    """
    >>> test_multiple_from_array_full_slice()
    (1, 2, 3)
    """
    cdef int[3] a
    a[0] = 1
    a[1] = 2
    a[2] = 3
    x, y, z = a[:]
    return x, y, z


@cython.test_fail_if_path_exists(
    '//ParallelAssignmentNode//CoerceToPyTypeNode'
)
@cython.test_assert_path_exists(
    '//ParallelAssignmentNode',
    '//ReturnStatNode//CoerceToPyTypeNode'
)
def test_multiple_from_slice():
    """
    >>> test_multiple_from_slice()
    (5, 4, 3)
    """
    cdef int *a = [6,5,4,3,2,1]
    x, y, z = a[1:4]
    return x, y, z


def test_slice_from_multiple():
    """
    >>> test_slice_from_multiple()
    (6, -1, -2, -3, 2, 1)
    """
    cdef int *a = [6,5,4,3,2,1]
    a[1:4] = -1, -2, -3
    return a[0], a[1], a[2], a[3], a[4], a[5]

def test_literal_tuple():
    """
    >>> test_literal_tuple()
    (1, 2, 3, 4, 5)
    """
    cdef int a[5]
    a = (1,2,3,4,5)
    return (a[0], a[1], a[2], a[3], a[4])

def test_list(list l):
    """
    >>> test_list([1, 2, 3, 4, 5])
    (1, 2, 3, 4, 5)
    """
    cdef int a[5]
    a[:] = l
    return (a[0], a[1], a[2], a[3], a[4])


def assign_all_from_pointer():
    """
    >>> assign_all_from_pointer()
    (1, 2, 3, 4, 5)
    """
    cdef int *v = [1, 2, 3, 4, 5]
    cdef int[5] a
    a = v
    return (a[0], a[1], a[2], a[3], a[4])


def assign_full_from_pointer():
    """
    >>> assign_full_from_pointer()
    (1, 2, 3, 4, 5)
    """
    cdef int *v = [1, 2, 3, 4, 5]
    cdef int[5] a
    a[:] = v
    return (a[0], a[1], a[2], a[3], a[4])


def assign_slice_end_from_pointer():
    """
    >>> assign_slice_end_from_pointer()
    (1, 2, 3, 4, 123)
    """
    cdef int *v = [1, 2, 3, 4, 5]
    cdef int[5] a
    a[4] = 123
    a[:4] = v
    return (a[0], a[1], a[2], a[3], a[4])


def assign_slice_start_from_pointer():
    """
    >>> assign_slice_start_from_pointer()
    (123, 234, 1, 2, 3)
    """
    cdef int *v = [1, 2, 3, 4, 5]
    cdef int[5] a
    a[0] = 123
    a[1] = 234
    a[2:] = v
    return (a[0], a[1], a[2], a[3], a[4])


def assign_slice_start_end_from_pointer():
    """
    >>> assign_slice_start_end_from_pointer()
    (123, 234, 1, 2, 345)
    """
    cdef int *v = [1, 2, 3, 4, 5]
    cdef int[5] a
    a[0] = 123
    a[1] = 234
    a[4] = 345
    a[2:4] = v
    return (a[0], a[1], a[2], a[3], a[4])


'''
# FIXME: make this work:
def assign_slice_start_end_from_sliced_pointer():
    """
    >>> assign_slice_start_end_from_sliced_pointer()
    (123, 234, 3, 4, 345)
    """
    cdef int *v = [1, 2, 3, 4, 5]
    cdef int[5] a
    a[0] = 123
    a[1] = 234
    a[4] = 345
    a[2:4] = v[2:4]
    return (a[0], a[1], a[2], a[3], a[4])


def assign_from_longer_array_slice():
    """
    >>> assign_from_longer_array_slice()
    [3, 4, 5]
    """
    cdef int[5] a
    cdef int[3] b
    a[0] = 1
    a[1] = 2
    a[2] = 3
    a[3] = 4
    a[4] = 5
    b[0] = 11
    b[1] = 12
    b[2] = 13
    b = a[2:]
    return b
'''


def assign_slice_from_shorter_array():
    """
    >>> assign_slice_from_shorter_array()
    [1, 11, 12, 13, 5]
    """
    cdef int[5] a
    cdef int[3] b
    a[0] = 1
    a[1] = 2
    a[2] = 3
    a[3] = 4
    a[4] = 5
    b[0] = 11
    b[1] = 12
    b[2] = 13
    a[1:4] = b
    return a


cdef enum:
    SIZE = 2

ctypedef int[SIZE] int_array_dyn


def assign_ptr_to_unknown_csize():
    """
    >>> assign_ptr_to_unknown_csize()
    [1, 2]
    """
    cdef int* v = [1, 2, 3, 4, 5]
    cdef int_array_dyn d
    d = v
    return d


def assign_to_wrong_csize():
    """
    >>> assign_to_wrong_csize()
    Traceback (most recent call last):
    ValueError: Assignment to slice of wrong length, expected 3, got 2
    """
    cdef int_array_dyn d
    cdef int v[3]
    v[0] = 1
    v[1] = 2
    v[2] = 3
    d = v
    return d


def assign_full_array_slice_to_array():
    """
    >>> assign_full_array_slice_to_array()
    [1, 2, 3]
    """
    cdef int[3] x, y
    x[0] = 1
    x[1] = 2
    x[2] = 3
    y = x[:]
    return y


cdef class ArrayOwner:
    cdef readonly int[3] array

    def __init__(self, a, b, c):
        self.array = (a, b, c)


def assign_from_array_attribute():
    """
    >>> assign_from_array_attribute()
    [1, 2, 3]
    """
    cdef int[3] v
    a = ArrayOwner(1, 2, 3)
    v = a.array[:]
    return v
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/ass2cglobal.pyx0000644000175100001770000000033300000000000020477 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> what()
0 5
>>> f(5)
>>> what()
42 5
>>> f(6)
>>> what()
42 6
>>> f("spam")
>>> what()
42 spam
"""

cdef int i = 0
cdef x = 5

def f(a):
    global i, x
    i = 42
    x = a

def what():
    print i,x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/ass2global.py0000644000175100001770000000113300000000000020143 0ustar00runnerdocker00000000000000# mode: run
# tag: pyglobal

"""
>>> getg()
5
>>> getg()
5
>>> getg()
5
>>> setg(42)
>>> getg()
42
>>> getg()
42
>>> getg()
42
"""

g = 5


def setg(a):
    global g
    g = a


def getg():
    return g


class Test(object):
    """
    >>> global_in_class
    9
    >>> Test.global_in_class
    Traceback (most recent call last):
    AttributeError: type object 'Test' has no attribute 'global_in_class'
    >>> Test().global_in_class
    Traceback (most recent call last):
    AttributeError: 'Test' object has no attribute 'global_in_class'
    """
    global global_in_class
    global_in_class = 9
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/ass2local.pyx0000644000175100001770000000010400000000000020162 0ustar00runnerdocker00000000000000def f():
    """
    >>> f()
    42
    """
    a = 42
    return a
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/assert.pyx0000644000175100001770000000374400000000000017615 0ustar00runnerdocker00000000000000# mode: run

cimport cython

@cython.test_assert_path_exists(
    '//AssertStatNode',
    '//AssertStatNode//RaiseStatNode',
)
def f(a, b, int i):
    """
    >>> f(1, 2, 1)
    >>> f(0, 2, 1)
    Traceback (most recent call last):
    AssertionError
    >>> f(1, -1, 1)
    Traceback (most recent call last):
    AssertionError
    >>> f(1, 2, 0)
    Traceback (most recent call last):
    AssertionError
    """
    assert a
    assert a+b
    assert i


@cython.test_assert_path_exists(
    '//AssertStatNode',
    '//AssertStatNode//RaiseStatNode',
    '//AssertStatNode//RaiseStatNode//TupleNode',
)
def g(a, b):
    """
    >>> g(1, "works")
    >>> g(0, "fails")
    Traceback (most recent call last):
    AssertionError: fails
    >>> g(0, (1, 2))
    Traceback (most recent call last):
    AssertionError: (1, 2)
    """
    assert a, b


@cython.test_assert_path_exists(
    '//AssertStatNode',
    '//AssertStatNode//RaiseStatNode',
    '//AssertStatNode//RaiseStatNode//TupleNode',
)
def g(a, b):
    """
    >>> g(1, "works")
    >>> g(0, "fails")
    Traceback (most recent call last):
    AssertionError: fails
    >>> g(0, (1, 2))
    Traceback (most recent call last):
    AssertionError: (1, 2)
    """
    assert a, b


@cython.test_assert_path_exists(
    '//AssertStatNode',
    '//AssertStatNode//RaiseStatNode',
    '//AssertStatNode//RaiseStatNode//TupleNode',
    '//AssertStatNode//RaiseStatNode//TupleNode//TupleNode',)
def assert_with_tuple_arg(a):
    """
    >>> assert_with_tuple_arg(True)
    >>> assert_with_tuple_arg(False)
    Traceback (most recent call last):
    AssertionError: (1, 2)
    """
    assert a, (1, 2)


@cython.test_assert_path_exists(
    '//AssertStatNode',
    '//AssertStatNode//RaiseStatNode',
)
@cython.test_fail_if_path_exists(
    '//AssertStatNode//TupleNode',
)
def assert_with_str_arg(a):
    """
    >>> assert_with_str_arg(True)
    >>> assert_with_str_arg(False)
    Traceback (most recent call last):
    AssertionError: abc
    """
    assert a, 'abc'
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/assigned_builtin_methods.pyx0000644000175100001770000000320600000000000023353 0ustar00runnerdocker00000000000000# mode: run
# tag: builtins

cimport cython

@cython.test_assert_path_exists(
    '//ReturnStatNode//PythonCapiCallNode')
def unbound_dict_get(d):
    """
    >>> unbound_dict_get({})
    >>> unbound_dict_get({1:2})
    2
    """
    get = dict.get
    return get(d, 1)


@cython.test_assert_path_exists(
    '//ReturnStatNode//PythonCapiCallNode')
def bound_dict_get(dict d):
    """
    >>> bound_dict_get({})
    >>> bound_dict_get({1:2})
    2
    """
    get = d.get
    return get(1)


@cython.test_fail_if_path_exists(
    '//ReturnStatNode//PythonCapiCallNode')
@cython.test_assert_path_exists(
    '//ReturnStatNode//PyMethodCallNode')
def bound_dict_get_reassign(dict d):
    """
    >>> bound_dict_get_reassign({})
    >>> bound_dict_get_reassign({1:2})
    2
    """
    get = d.get
    d = {1: 3}
    return get(1)


@cython.test_assert_path_exists(
    '//PythonCapiCallNode//NameNode[@name="l"]')
def unbound_list_sort(list l):
    """
    >>> unbound_list_sort([1, 3, 2])
    [1, 2, 3]
    >>> unbound_list_sort([1, 3, 2])
    [1, 2, 3]
    """
    sort = list.sort
    sort(l)
    return l


@cython.test_assert_path_exists(
    '//PythonCapiCallNode//NameNode[@name="l"]')
def bound_list_sort(list l):
    """
    >>> bound_list_sort([1, 3, 2])
    [1, 2, 3]
    >>> bound_list_sort([1, 3, 2])
    [1, 2, 3]
    """
    sort = l.sort
    sort()
    return l


@cython.test_fail_if_path_exists(
    '//PythonCapiCallNode')
def bound_list_sort_reassign(list l):
    """
    >>> bound_list_sort_reassign([1, 3, 2])
    [3, 2, 1]
    >>> bound_list_sort_reassign([1, 3, 2])
    [3, 2, 1]
    """
    sort = l.sort
    l = [3, 2, 1]
    sort()
    return l
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/async_def.pyx0000644000175100001770000000531200000000000020240 0ustar00runnerdocker00000000000000# cython: language_level=3str, binding=True
# mode: run
# tag: pep492, await, gh3337

"""
Cython specific tests in addition to "test_coroutines_pep492.pyx"
(which is copied from CPython).
"""

import sys


def run_async(coro, assert_type=True, send_value=None):
    if assert_type:
        #assert coro.__class__ is types.GeneratorType
        assert coro.__class__.__name__ in ('coroutine', '_GeneratorWrapper'), coro.__class__.__name__

    buffer = []
    result = None
    while True:
        try:
            buffer.append(coro.send(send_value))
        except StopIteration as ex:
            result = ex.value if sys.version_info >= (3, 5) else ex.args[0] if ex.args else None
            break
    return buffer, result


async def test_async_temp_gh3337(x, y):
    """
    >>> run_async(test_async_temp_gh3337(2, 3))
    ([], -1)
    >>> run_async(test_async_temp_gh3337(3, 2))
    ([], 0)
    """
    return min(x - y, 0)


async def outer_with_nested(called):
    """
    >>> called = []
    >>> _, inner = run_async(outer_with_nested(called))
    >>> called  # after outer_with_nested()
    ['outer', 'make inner', 'deco', 'return inner']
    >>> _ = run_async(inner())
    >>> called  # after inner()
    ['outer', 'make inner', 'deco', 'return inner', 'inner']
    """
    called.append('outer')

    def deco(f):
        called.append('deco')
        return f

    called.append('make inner')

    @deco
    async def inner():
        called.append('inner')
        return 1

    called.append('return inner')
    return inner

# used in "await_in_genexpr_iterator"
async def h(arg):
    return [arg, arg+1]

async def await_in_genexpr_iterator():
    """
    >>> _, x = run_async(await_in_genexpr_iterator())
    >>> x
    [4, 6]
    """
    lst = list  # obfuscate from any optimizations cython might try
    return lst(x*2 for x in await h(2))

def yield_in_genexpr_iterator():
    """
    Same test as await_in_genexpr_iterator but with yield.
    (Possibly in the wrong place, but grouped with related tests)

    >>> g = yield_in_genexpr_iterator()
    >>> g.send(None)
    >>> _, x = run_async(g, assert_type=False, send_value=[2, 3])
    >>> x
    [4, 6]
    """
    lst = list  # obfuscate from any optimizations cython might try
    return lst(x*2 for x in (yield))

def h_yield_from(arg):
    yield
    return [arg, arg+1]

def yield_from_in_genexpr_iterator():
    """
    Same test as await_in_genexpr_iterator but with "yield from".
    (Possibly in the wrong place, but grouped with related tests)

    >>> _, x = run_async(yield_from_in_genexpr_iterator(), assert_type=False)
    >>> x
    [4, 6]
    """
    lst = list  # obfuscate from any optimizations cython might try
    return lst(x*2 for x in (yield from h_yield_from(2)))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/async_globals.pyx0000644000175100001770000000056300000000000021130 0ustar00runnerdocker00000000000000# mode: run
# tag: pep492, asyncfor, await, gh2613

# Using C-globals in coroutines.


cdef object py_retval


async def test():
    """
    >>> t = test()
    >>> try: t.send(None)
    ... except StopIteration as ex:
    ...     print(ex.args[0] if ex.args else None)
    ... else: print("NOT STOPPED!")
    None
    """
    global py_retval
    py_retval = {'foo': 42}
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/async_iter_pep492.pyx0000644000175100001770000001527400000000000021560 0ustar00runnerdocker00000000000000# mode: run
# tag: pep492, asyncfor, await

import sys

if sys.version_info >= (3, 5, 0, 'beta'):
    # pass Cython implemented AsyncIter() into a Python async-for loop
    __doc__ = u"""
>>> def test_py35(AsyncIterClass):
...     buffer = []
...     async def coro():
...         async for i1, i2 in AsyncIterClass(1):
...             buffer.append(i1 + i2)
...     return coro, buffer

>>> testfunc, buffer = test_py35(AsyncIterOld if sys.version_info < (3, 5, 2) else AsyncIter)
>>> buffer
[]

>>> yielded, _ = run_async(testfunc(), check_type=False)
>>> yielded == [i * 100 for i in range(1, 11)] or yielded
True
>>> buffer == [i*2 for i in range(1, 101)] or buffer
True
"""


cdef class AsyncYieldFrom:
    cdef object obj
    def __init__(self, obj):
        self.obj = obj

    def __await__(self):
        yield from self.obj


cdef class AsyncYield:
    cdef object value
    def __init__(self, value):
        self.value = value

    def __await__(self):
        yield self.value


def run_async(coro, check_type='coroutine'):
    if check_type:
        assert coro.__class__.__name__ == check_type, \
            'type(%s) != %s' % (coro.__class__, check_type)

    buffer = []
    result = None
    while True:
        try:
            buffer.append(coro.send(None))
        except StopIteration as ex:
            result = ex.args[0] if ex.args else None
            break
    return buffer, result


cdef class AsyncIter:
    cdef long i
    cdef long aiter_calls
    cdef long max_iter_calls

    def __init__(self, long max_iter_calls=1):
        self.i = 0
        self.aiter_calls = 0
        self.max_iter_calls = max_iter_calls

    def __aiter__(self):
        self.aiter_calls += 1
        return self

    async def __anext__(self):
        self.i += 1
        assert self.aiter_calls <= self.max_iter_calls

        if not (self.i % 10):
            await AsyncYield(self.i * 10)

        if self.i > 100:
            raise StopAsyncIteration

        return self.i, self.i


cdef class AsyncIterOld(AsyncIter):
    """
    Same as AsyncIter, but with the old async-def interface for __aiter__().
    """
    async def __aiter__(self):
        self.aiter_calls += 1
        return self


def test_for_1():
    """
    >>> testfunc, buffer = test_for_1()
    >>> buffer
    []
    >>> yielded, _ = run_async(testfunc())
    >>> yielded == [i * 100 for i in range(1, 11)] or yielded
    True
    >>> buffer == [i*2 for i in range(1, 101)] or buffer
    True
    """
    buffer = []
    async def test1():
        async for i1, i2 in AsyncIter(1):
            buffer.append(i1 + i2)
    return test1, buffer


def test_for_2():
    """
    >>> testfunc, buffer = test_for_2()
    >>> buffer
    []
    >>> yielded, _ = run_async(testfunc())
    >>> yielded == [100, 200] or yielded
    True
    >>> buffer == [i for i in range(1, 21)] + ['end'] or buffer
    True
    """
    buffer = []
    async def test2():
        nonlocal buffer
        async for i in AsyncIter(2):
            buffer.append(i[0])
            if i[0] == 20:
                break
        else:
            buffer.append('what?')
        buffer.append('end')
    return test2, buffer



def test_for_3():
    """
    >>> testfunc, buffer = test_for_3()
    >>> buffer
    []
    >>> yielded, _ = run_async(testfunc())
    >>> yielded == [i * 100 for i in range(1, 11)] or yielded
    True
    >>> buffer == [i for i in range(1, 21)] + ['what?', 'end'] or buffer
    True
    """
    buffer = []
    async def test3():
        nonlocal buffer
        async for i in AsyncIter(3):
            if i[0] > 20:
                continue
            buffer.append(i[0])
        else:
            buffer.append('what?')
        buffer.append('end')
    return test3, buffer


cdef class NonAwaitableFromAnext:
    def __aiter__(self):
        return self

    def __anext__(self):
        return 123


def test_broken_anext():
    """
    >>> testfunc = test_broken_anext()
    >>> try: run_async(testfunc())
    ... except TypeError as exc:
    ...     assert ' int' in str(exc)
    ... else:
    ...     print("NOT RAISED!")
    """
    async def foo():
        async for i in NonAwaitableFromAnext():
            print('never going to happen')
    return foo


cdef class Manager:
    cdef readonly list counter
    def __init__(self, counter):
        self.counter = counter

    async def __aenter__(self):
        self.counter[0] += 10000

    async def __aexit__(self, *args):
        self.counter[0] += 100000


cdef class Iterable:
    cdef long i
    def __init__(self):
        self.i = 0

    def __aiter__(self):
        return self

    async def __anext__(self):
        if self.i > 10:
            raise StopAsyncIteration
        self.i += 1
        return self.i

def has_getrefcount():
    import sys
    return hasattr(sys, "getrefcount")

def test_with_for():
    """
    >>> test_with_for()
    111011
    333033
    20555255
    """
    I = [0]

    manager = Manager(I)
    iterable = Iterable()
    if has_getrefcount():
        mrefs_before = sys.getrefcount(manager)
        irefs_before = sys.getrefcount(iterable)

    async def main():
        async with manager:
            async for i in iterable:
                I[0] += 1
        I[0] += 1000

    run_async(main())
    print(I[0])

    if has_getrefcount():
        assert sys.getrefcount(manager) == mrefs_before
        assert sys.getrefcount(iterable) == irefs_before

    ##############

    async def main():
        nonlocal I

        async with Manager(I):
            async for i in Iterable():
                I[0] += 1
        I[0] += 1000

        async with Manager(I):
            async for i in Iterable():
                I[0] += 1
        I[0] += 1000

    run_async(main())
    print(I[0])

    ##############

    async def main():
        async with Manager(I):
            I[0] += 100
            async for i in Iterable():
                I[0] += 1
            else:
                I[0] += 10000000
        I[0] += 1000

        async with Manager(I):
            I[0] += 100
            async for i in Iterable():
                I[0] += 1
            else:
                I[0] += 10000000
        I[0] += 1000

    run_async(main())
    print(I[0])


# old-style pre-3.5.2 AIter protocol - no longer supported
#cdef class AI_old:
#    async def __aiter__(self):
#        1/0


cdef class AI_new:
    def __aiter__(self):
        1/0


def test_aiter_raises(AI):
    """
    #>>> test_aiter_raises(AI_old)
    #RAISED
    #0
    >>> test_aiter_raises(AI_new)
    RAISED
    0
    """
    CNT = 0

    async def foo():
        nonlocal CNT
        async for i in AI():
            CNT += 1
        CNT += 10

    try:
        run_async(foo())
    except ZeroDivisionError:
        print("RAISED")
    else:
        print("NOT RAISED")
    return CNT
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/asyncio_generators.srctree0000644000175100001770000001361100000000000023033 0ustar00runnerdocker00000000000000# mode: run
# tag: asyncio, pep492

"""
PYTHON setup.py build_ext -i
PYTHON test_from_import.py
PYTHON test_import.py
PYTHON test_async_def.py
PYTHON test_async_def_future.py
PYTHON test_all.py
"""

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup

setup(
  ext_modules = cythonize("*.pyx"),
)


######## test_from_import.py ########

import from_asyncio_import
import asyncio
import sys
from contextlib import closing
new_event_loop = asyncio.new_event_loop if sys.version_info >= (3, 5) else asyncio.get_event_loop

def runloop(task):
    with closing(new_event_loop()) as loop:
        result = loop.run_until_complete(task())
        assert 3 == result, result

if sys.version_info < (3, 7):
    runloop(from_asyncio_import.wait3)


######## test_import.py ########

import import_asyncio
import asyncio
import sys
from contextlib import closing
new_event_loop = asyncio.new_event_loop if sys.version_info >= (3, 5) else asyncio.get_event_loop

def runloop(task):
    with closing(new_event_loop()) as loop:
        result = loop.run_until_complete(task())
        assert 3 == result, result

if sys.version_info < (3, 7):
    runloop(import_asyncio.wait3)


######## test_async_def.py ########

import sys

ASYNCIO_SUPPORTS_COROUTINE = sys.version_info[:2] >= (3, 5)

if ASYNCIO_SUPPORTS_COROUTINE:
    import async_def
    import asyncio
    from contextlib import closing

    def runloop(task):
        with closing(asyncio.new_event_loop()) as loop:
            result = loop.run_until_complete(task())
            assert 3 == result, result

    runloop(async_def.wait3)


######## test_async_def_future.py ########

import sys

ASYNCIO_SUPPORTS_COROUTINE = sys.version_info[:2] >= (3, 5)

if ASYNCIO_SUPPORTS_COROUTINE:
    from async_def_future import await_future
    import asyncio
    from contextlib import closing

    def runloop():
        with closing(asyncio.new_event_loop()) as loop:
            task, events, expected = await_future(loop)
            result = loop.run_until_complete(task())
            assert events == expected, 'expected %s, got %s' % (expected, events)

    runloop()


######## test_all.py ########

import sys
import asyncio
from contextlib import closing, contextmanager
new_event_loop = asyncio.new_event_loop if sys.version_info >= (3, 5) else asyncio.get_event_loop
if sys.version_info < (3, 5):
    # don't close loop on Py 3.4
    @contextmanager
    def closing(o):
        yield o


ASYNCIO_SUPPORTS_COROUTINE = sys.version_info[:2] >= (3, 5)
ASYNCIO_SUPPORTS_YIELD_FROM = sys.version_info[:2] < (3, 7)

def runloop(task):
    with closing(new_event_loop()) as loop:
        result = loop.run_until_complete(task())
        assert 3 == result, result

import import_asyncio
if ASYNCIO_SUPPORTS_YIELD_FROM:
    runloop(import_asyncio.wait3)       # 1a)
import from_asyncio_import
if ASYNCIO_SUPPORTS_YIELD_FROM:
    runloop(from_asyncio_import.wait3)  # 1b)

import async_def
if ASYNCIO_SUPPORTS_COROUTINE:
    runloop(async_def.wait3)            # 1c)

if ASYNCIO_SUPPORTS_YIELD_FROM:
    runloop(from_asyncio_import.wait3)  # 2a)
    runloop(import_asyncio.wait3)       # 2b)
if ASYNCIO_SUPPORTS_COROUTINE:
    runloop(async_def.wait3)            # 2c)

import sys
if ASYNCIO_SUPPORTS_YIELD_FROM:
    runloop(from_asyncio_import.wait3)  # 3a)
    runloop(import_asyncio.wait3)       # 3b)
if ASYNCIO_SUPPORTS_COROUTINE:
    runloop(async_def.wait3)            # 3c)

try:
    from collections.abc import Generator
except ImportError:
    try:
        from collections import Generator
    except ImportError:
        assert sys.version_info < (3, 5), "Python 3.5+ should have collections.abc.Generator"
        Generator = object  # easy win :)

assert isinstance(from_asyncio_import.wait3(), Generator)
assert isinstance(import_asyncio.wait3(), Generator)
assert isinstance((lambda:(yield))(), Generator)

try:
    from collections.abc import Awaitable
except ImportError:
    try:
        from collections import Awaitable
    except ImportError:
        assert sys.version_info < (3, 5), "Python 3.5+ should have collections.abc.Awaitable"
        Awaitable = object  # easy win :)

assert isinstance(async_def.wait3(), Awaitable)

try:
    from collections.abc import Coroutine
except ImportError:
    try:
        from collections import Coroutine
    except ImportError:
        assert sys.version_info < (3, 5), "Python 3.5+ should have collections.abc.Coroutine"
        Coroutine = object  # easy win :)

assert isinstance(async_def.wait3(), Coroutine)


######## import_asyncio.pyx ########
# cython: binding=True

try:
    from types import coroutine as types_coroutine
except ImportError:
    types_coroutine = lambda f:f

import asyncio

@types_coroutine
def wait3():
    counter = 0
    for i in range(3):
        print(counter)
        yield from asyncio.sleep(0.01)
        counter += 1
    return counter


######## from_asyncio_import.pyx ########
# cython: binding=True

try:
    from types import coroutine as types_coroutine
except ImportError:
    types_coroutine = lambda f:f

from asyncio import sleep

@types_coroutine
def wait3():
    counter = 0
    for i in range(3):
        print(counter)
        yield from sleep(0.01)
        counter += 1
    return counter


######## async_def.pyx ########
# cython: binding=True

import asyncio

async def wait3():
    counter = 0
    for i in range(3):
        print(counter)
        await asyncio.sleep(0.01)
        counter += 1
    return counter


######## async_def_future.pyx ########
# cython: binding=True

import asyncio

def await_future(loop):
    events = []
    async def worker():
        fut = asyncio.Future()

        def setval():
            events.append('setval')
            fut.set_result(123)

        events.append('setup')
        loop.call_later(0.2, setval)
        events.append(await fut)

    async def test():
        await worker()

    expected = ['setup', 'setval', 123]
    return test, events, expected
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/attr.pyx0000644000175100001770000000226600000000000017264 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> class Test(object):
    ...     def __init__(self, i):
    ...         self.i = i
    >>> b = Test(1)
    >>> b.spam = Test(2)
    >>> b.spam.eggs = Test(3)
    >>> b.spam.eggs.spam = Test(4)
    >>> b.spam.eggs.spam.eggs = Test(5)

    >>> a = f(b)
    >>> a.i
    2
    >>> b.i
    1
    >>> a.spam.i
    1
    >>> b.spam.i
    2
    >>> a.spam.eggs.i
    Traceback (most recent call last):
    AttributeError: 'Test' object has no attribute 'eggs'
    >>> b.spam.eggs.i
    3
    >>> a.spam.spam.i
    2
    >>> b.spam.spam.i
    1
    >>> a.spam.eggs.spam.i
    Traceback (most recent call last):
    AttributeError: 'Test' object has no attribute 'eggs'
    >>> b.spam.eggs.spam.i
    4

    >>> a = g(b)
    >>> a.i
    3
    >>> b.i
    1
    >>> a.spam.i
    4
    >>> b.spam.i
    2
    >>> a.spam.eggs.i
    1
    >>> b.spam.eggs.i
    3
    >>> a.spam.spam.i
    Traceback (most recent call last):
    AttributeError: 'Test' object has no attribute 'spam'
    >>> b.spam.spam.i
    1
    >>> a.spam.eggs.spam.i
    2
    >>> b.spam.eggs.spam.i
    4
"""

def f(b):
    a = b.spam
    a.spam = b
    return a

def g(b):
    a = b.spam.eggs
    a.spam.eggs = b
    return a
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/attribute_and_lambda.pyx0000644000175100001770000000035400000000000022433 0ustar00runnerdocker00000000000000# mode: run
# tag: lambda, attribute, regression

class TestClass(object):
    bar = 123


def test_attribute_and_lambda(f):
    """
    >>> test_attribute_and_lambda(lambda _: TestClass())
    123
    """
    return f(lambda x: x).bar
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/auto_cpdef.py0000644000175100001770000000243200000000000020226 0ustar00runnerdocker00000000000000# cython: auto_cpdef=True
# mode:run
# tag: directive,auto_cpdef

import cython

def str(arg):
    """
    This is a bit evil - str gets mapped to a C-API function and is
    being redefined here.

    >>> print(str('TEST'))
    STR
    """
    return 'STR'

@cython.test_assert_path_exists('//SimpleCallNode[@function.type.is_cfunction = True]')
@cython.test_fail_if_path_exists('//SimpleCallNode[@function.type.is_builtin_type = True]')
def call_str(arg):
    """
    >>> print(call_str('TEST'))
    STR
    """
    return str(arg)


def stararg_func(*args):
    """
    >>> stararg_func(1, 2)
    (1, 2)
    """
    return args

def starstararg_func(**kwargs):
    """
    >>> starstararg_func(a=1)
    1
    """
    return kwargs['a']

l = lambda x: 1

def test_lambda():
    """
    >>> l(1)
    1
    """


# test classical import fallbacks
try:
    from math import fabs
except ImportError:
    def fabs(x):
        if x < 0:
            return -x
        else:
            return x

try:
    from math import no_such_function
except ImportError:
    def no_such_function(x):
        return x + 1.0


def test_import_fallback():
    """
    >>> fabs(1.0)
    1.0
    >>> no_such_function(1.0)
    2.0
    >>> test_import_fallback()
    (1.0, 2.0)
    """
    return fabs(1.0), no_such_function(1.0)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/auto_cpdef_closures.py0000644000175100001770000000050000000000000022137 0ustar00runnerdocker00000000000000# cython: auto_cpdef=True
# mode:run
# tag: directive,auto_cpdef,closures

def closure_func(x):
    """
    >>> c = closure_func(2)
    >>> c()
    2
    """
    def c():
        return x
    return c

def generator_func():
    """
    >>> for i in generator_func(): print(i)
    1
    2
    """
    yield 1
    yield 2
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/autotestdict.pxd0000644000175100001770000000001700000000000020771 0ustar00runnerdocker00000000000000# I just exist
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/autotestdict.pyx0000644000175100001770000000613400000000000021024 0ustar00runnerdocker00000000000000# cython: autotestdict=True
# Directive defaults to True, but not when testing in Py3.4
"""
Tests autotestdict compiler directive.

Both module test and individual tests are run; finally,
all_tests_run() is executed which does final validation.

>>> items = list(__test__.items())
>>> items.sort()
>>> for key, value in items:
...     print('%s ; %s' % (key, value))
MyCdefClass.cpdef_method (line 77) ; >>> add_log("cpdef class method")
MyCdefClass.method (line 74) ; >>> add_log("cdef class method")
MyClass.method (line 63) ; >>> add_log("class method")
mycpdeffunc (line 50) ; >>> add_log("cpdef")
myfunc (line 40) ; >>> add_log("def")
"""

import sys
log = []

cdef cdeffunc():
    """
    >>> True
    False
    """
cdeffunc() # make sure it's being used

def all_tests_run():
    assert sorted(log) == sorted([u'cdef class', u'class'] + (
        (1 if sys.version_info < (3, 4) else 2) * [u'cdef class method', u'class method', u'cpdef', u'cpdef class method', u'def'])), sorted(log)

def add_log(s):
    log.append(unicode(s))
    if len(log) == len(__test__) + (2 if sys.version_info < (3, 4) else 7):
        # Final per-function doctest executed
        all_tests_run()

def myfunc():
    """>>> add_log("def")"""
    x = lambda a:1 # no docstring here ...

def doc_without_test():
    """Some docs"""

def nodocstring():
    pass

cpdef mycpdeffunc():
    """>>> add_log("cpdef")"""


class MyClass:
    """
    Needs no hack

    >>> add_log("class")
    >>> True
    True
    """

    def method(self):
        """>>> add_log("class method")"""

cdef class MyCdefClass:
    """
    Needs no hack

    >>> add_log("cdef class")
    >>> True
    True
    """
    def method(self):
        """>>> add_log("cdef class method")"""

    cpdef cpdef_method(self):
        """>>> add_log("cpdef class method")"""

    cdef cdef_method(self):
        """>>> add_log("cdef class cmethod")"""

    def __cinit__(self):
        """
        Should not be included, as it can't be looked up with getattr

        >>> True
        False
        """

    def __dealloc__(self):
        """
        Should not be included, as it can't be looked up with getattr

        >>> True
        False
        """

    def __richcmp__(self, other, int op):
        """
        Should not be included, as it can't be looked up with getattr in Py 2

        >>> True
        False
        """

    def __nonzero__(self):
        """
        Should not be included, as it can't be looked up with getattr in Py 3.1

        >>> True
        False
        """

    def __len__(self):
        """
        Should not be included, as it can't be looked up with getattr in Py 3.1

        >>> sys.version_info < (3, 4)
        False
        """

    def __contains__(self, value):
        """
        Should not be included, as it can't be looked up with getattr in Py 3.1

        >>> sys.version_info < (3, 4)
        False
        """

cdef class MyOtherCdefClass:
    """
    Needs no hack

    >>> True
    True
    """

    def __bool__(self):
        """
        Should not be included, as it can't be looked up with getattr in Py 2

        >>> True
        False
        """
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/autotestdict_all.pyx0000644000175100001770000000627200000000000021657 0ustar00runnerdocker00000000000000# cython: autotestdict=True, autotestdict.all=True

"""
Tests autotestdict compiler directive.

Both module test and individual tests are run; finally,
all_tests_run() is executed which does final validation.

>>> items = list(__test__.items())
>>> items.sort()
>>> for key, value in items:
...     print('%s ; %s' % (key, value))
MyCdefClass.cdef_method (line 79) ; >>> add_log("cdef class cmethod")
MyCdefClass.cpdef_method (line 76) ; >>> add_log("cpdef class method")
MyCdefClass.method (line 73) ; >>> add_log("cdef class method")
MyClass.method (line 62) ; >>> add_log("class method")
cdeffunc (line 26) ; >>> add_log("cdef")
doc_without_test (line 43) ; Some docs
mycpdeffunc (line 49) ; >>> add_log("cpdef")
myfunc (line 40) ; >>> add_log("def")
"""

import sys
log = []

cdef cdeffunc():
    """>>> add_log("cdef")"""
cdeffunc() # make sure it's being used

def all_tests_run():
    assert sorted(log) == sorted([u'cdef', u'cdef class', u'class', u'cdef class cmethod'] + (
        (1 if sys.version_info < (3, 4) else 2) * [u'cdef class method', u'class method', u'cpdef', u'cpdef class method', u'def'])), sorted(log)

def add_log(s):
    log.append(unicode(s))
    if len(log) == len(__test__) + (1 if sys.version_info < (3, 4) else 6):
        # Final per-function doctest executed
        all_tests_run()

def myfunc():
    """>>> add_log("def")"""

def doc_without_test():
    """Some docs"""

def nodocstring():
    pass

cpdef mycpdeffunc():
    """>>> add_log("cpdef")"""


class MyClass:
    """
    Needs no hack

    >>> add_log("class")
    >>> True
    True
    """

    def method(self):
        """>>> add_log("class method")"""

cdef class MyCdefClass:
    """
    Needs no hack

    >>> add_log("cdef class")
    >>> True
    True
    """
    def method(self):
        """>>> add_log("cdef class method")"""

    cpdef cpdef_method(self):
        """>>> add_log("cpdef class method")"""

    cdef cdef_method(self):
        """>>> add_log("cdef class cmethod")"""

    def __cinit__(self):
        """
        Should not be included, as it can't be looked up with getattr

        >>> True
        False
        """

    def __dealloc__(self):
        """
        Should not be included, as it can't be looked up with getattr

        >>> True
        False
        """

    def __richcmp__(self, other, int op):
        """
        Should not be included, as it can't be looked up with getattr in Py 2

        >>> True
        False
        """

    def __nonzero__(self):
        """
        Should not be included, as it can't be looked up with getattr in Py 3.1

        >>> True
        False
        """

    def __len__(self):
        """
        Should not be included, as it can't be looked up with getattr in Py 3.1

        >>> sys.version_info < (3, 4)
        False
        """

    def __contains__(self, value):
        """
        Should not be included, as it can't be looked up with getattr in Py 3.1

        >>> sys.version_info < (3, 4)
        False
        """

cdef class MyOtherCdefClass:
    """
    Needs no hack

    >>> True
    True
    """

    def __bool__(self):
        """
        Should not be included, as it can't be looked up with getattr in Py 2

        >>> True
        False
        """
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/autotestdict_cdef.pyx0000644000175100001770000000622600000000000022007 0ustar00runnerdocker00000000000000# cython: autotestdict=True, autotestdict.cdef=True

"""
Tests autotestdict compiler directive.

Both module test and individual tests are run; finally,
all_tests_run() is executed which does final validation.

>>> items = list(__test__.items())
>>> items.sort()
>>> for key, value in items:
...     print('%s ; %s' % (key, value))
MyCdefClass.cdef_method (line 78) ; >>> add_log("cdef class cmethod")
MyCdefClass.cpdef_method (line 75) ; >>> add_log("cpdef class method")
MyCdefClass.method (line 72) ; >>> add_log("cdef class method")
MyClass.method (line 61) ; >>> add_log("class method")
cdeffunc (line 25) ; >>> add_log("cdef")
mycpdeffunc (line 48) ; >>> add_log("cpdef")
myfunc (line 39) ; >>> add_log("def")
"""

import sys
log = []

cdef cdeffunc():
    """>>> add_log("cdef")"""
cdeffunc() # make sure it's being used

def all_tests_run():
    assert sorted(log) == sorted([u'cdef', u'cdef class', u'cdef class cmethod', u'class'] + (
        ((1 if sys.version_info < (3, 4) else 2) * [u'cdef class method', u'class method', u'cpdef', u'cpdef class method', u'def']))), sorted(log)

def add_log(s):
    log.append(unicode(s))
    if len(log) == len(__test__) + (2 if sys.version_info < (3, 4) else 7):
        # Final per-function doctest executed
        all_tests_run()

def myfunc():
    """>>> add_log("def")"""

def doc_without_test():
    """Some docs"""

def nodocstring():
    pass

cpdef mycpdeffunc():
    """>>> add_log("cpdef")"""


class MyClass:
    """
    Needs no hack

    >>> add_log("class")
    >>> True
    True
    """

    def method(self):
        """>>> add_log("class method")"""

cdef class MyCdefClass:
    """
    Needs no hack

    >>> add_log("cdef class")
    >>> True
    True
    """
    def method(self):
        """>>> add_log("cdef class method")"""

    cpdef cpdef_method(self):
        """>>> add_log("cpdef class method")"""

    cdef cdef_method(self):
        """>>> add_log("cdef class cmethod")"""

    def __cinit__(self):
        """
        Should not be included, as it can't be looked up with getattr

        >>> True
        False
        """

    def __dealloc__(self):
        """
        Should not be included, as it can't be looked up with getattr

        >>> True
        False
        """

    def __richcmp__(self, other, int op):
        """
        Should not be included, as it can't be looked up with getattr in Py 2

        >>> True
        False
        """

    def __nonzero__(self):
        """
        Should not be included, as it can't be looked up with getattr in Py 3.1

        >>> True
        False
        """

    def __len__(self):
        """
        Should not be included, as it can't be looked up with getattr in Py 3.1

        >>> sys.version_info < (3, 4)
        False
        """

    def __contains__(self, value):
        """
        Should not be included, as it can't be looked up with getattr in Py 3.1

        >>> sys.version_info < (3, 4)
        False
        """

cdef class MyOtherCdefClass:
    """
    Needs no hack

    >>> True
    True
    """

    def __bool__(self):
        """
        Should not be included, as it can't be looked up with getattr in Py 2

        >>> True
        False
        """
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/autotestdict_skip.pyx0000644000175100001770000000051700000000000022051 0ustar00runnerdocker00000000000000#cython: autotestdict=True

"""
Tests that autotestdict doesn't come into effect when
a __test__ is defined manually.

If this doesn't work, then the function doctest should fail.

>>> True
True
"""

import sys

def func():
    """
    >>> sys.version_info < (3, 4)
    False
    """

__test__ = {
    u"one" : """
>>> True
True
"""
}
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/baas3.pyx0000644000175100001770000000025100000000000017273 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> m = MyClass()
    >>> m is foo(m)
    True
"""

cdef class MyClass:
    pass

def foo(MyClass c):
    cdef MyClass res
    res = c
    return res
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/backquote.pyx0000644000175100001770000000030400000000000020257 0ustar00runnerdocker00000000000000def f(obj2):
    """
    >>> f(20)
    '20'
    >>> f('test')
    "'test'"
    """
    obj1 = `obj2`
    return obj1

def g():
    """
    >>> g()
    '42'
    """
    obj1 = `42`
    return obj1
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/bad_c_struct_T252.pyx0000644000175100001770000000151500000000000021456 0ustar00runnerdocker00000000000000# ticket: t252

cdef cf(default=None):
    return default

cpdef cpf(default=100):
    """
    >>> cpf()
    100
    >>> cpf(1)
    1
    >>> cpf(default=2)
    2
    """
    default = cf(default)
    return default

def pf(default=100):
    """
    >>> pf()
    100
    >>> pf(1)
    1
    >>> pf(default=2)
    2
    """
    return default


cdef struct foo:
    int void
    int default

def test_struct():
    """
    >>> test_struct()
    (1, 2)
    """
    cdef foo foo_struct
    foo_struct.void = 1
    foo_struct.default = 2
    return foo_struct.void, foo_struct.default


cdef class Foo:
    cdef int void
    cdef int default

def test_class():
    """
    >>> test_class()
    (1, 2)
    """
    cdef Foo foo_instance = Foo()
    foo_instance.void = 1
    foo_instance.default = 2
    return foo_instance.void, foo_instance.default
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/behnel1.pyx0000644000175100001770000000026100000000000017621 0ustar00runnerdocker00000000000000cdef class Spam:
    cdef eggs(self, a):
        return a

cdef Spam spam():
    return Spam()

def viking(a):
    """
    >>> viking(5)
    5
    """
    return spam().eggs(a)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/behnel2.pyx0000644000175100001770000000014000000000000017616 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> y
    1
    >>> y and {}
    {}
    >>> x
    {}
"""

y = 1
x = y and {}
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/behnel3.pyx0000644000175100001770000000013300000000000017621 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> y
    >>> y or {}
    {}
    >>> x
    {}
"""

y = None
x = y or {}
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/big_indices.pyx0000644000175100001770000000060200000000000020541 0ustar00runnerdocker00000000000000def test():
    """
    >>> test()
    neg False
    pos True
    neg
    pos
    neg
    pos
    """
    cdef object D
    cdef long neg = -1
    cdef unsigned long pos = -2 # will be a large positive number

    print u"neg", neg > 0
    print u"pos", pos > 0

    D = { neg: u'neg', pos: u'pos' }

    print D[neg]
    print D[pos]

    print D[neg]
    print D[pos]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/binop_reverse_methods_GH2056.pyx0000644000175100001770000001731500000000000023573 0ustar00runnerdocker00000000000000cimport cython

import sys
IS_PYTHON2 = sys.version_info[0] == 2

__doc__ = ""


@cython.c_api_binop_methods(False)
@cython.cclass
class Base(object):
    """
    >>> Base() + 2
    'Base.__add__(Base(), 2)'
    >>> 2 + Base()
    'Base.__radd__(Base(), 2)'

    >>> Base(implemented=False) + 2  #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: unsupported operand type...
    >>> 2 + Base(implemented=False)  #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: unsupported operand type...

    >>> Base() ** 2
    'Base.__pow__(Base(), 2, None)'
    >>> 2 ** Base()
    'Base.__rpow__(Base(), 2, None)'
    >>> pow(Base(), 2, 100)
    'Base.__pow__(Base(), 2, 100)'
    >>> Base() // 1
    True
    >>> set() // Base()
    True

    # version dependent tests for @ and / are external
    """
    implemented: cython.bint

    def __init__(self, *, implemented=True):
        self.implemented = implemented

    def __add__(self, other):
        assert cython.typeof(self) == "Base"
        if self.implemented:
            return "Base.__add__(%s, %s)" % (self, other)
        else:
            return NotImplemented

    def __radd__(self, other):
        assert cython.typeof(self) == "Base"
        if self.implemented:
            return "Base.__radd__(%s, %s)" % (self, other)
        else:
            return NotImplemented

    def __pow__(self, other, mod):
        assert cython.typeof(self) == "Base"
        if self.implemented:
            return "Base.__pow__(%s, %s, %s)" % (self, other, mod)
        else:
            return NotImplemented

    def __rpow__(self, other, mod):
        assert cython.typeof(self) == "Base"
        if self.implemented:
            return "Base.__rpow__(%s, %s, %s)" % (self, other, mod)
        else:
            return NotImplemented

    def __repr__(self):
        return "%s()" % (self.__class__.__name__)

    # The following methods were missed from the initial implementation
    # that typed 'self'. These tests are a quick test to confirm that
    # but not the full binop behaviour
    def __matmul__(self, other):
        return cython.typeof(self) == 'Base'

    def __rmatmul__(self, other):
        return cython.typeof(self) == 'Base'

    def __truediv__(self, other):
        return cython.typeof(self) == 'Base'

    def __rtruediv__(self, other):
        return cython.typeof(self) == 'Base'

    def __floordiv__(self, other):
        return cython.typeof(self) == 'Base'

    def __rfloordiv__(self, other):
        return cython.typeof(self) == 'Base'


if sys.version_info >= (3, 5):
    __doc__ += """
    >>> Base() @ 1
    True
    >>> set() @ Base()
    True
    """

if sys.version_info >= (3, 0):
    __doc__ += """
    >>> Base() / 1
    True
    >>> set() / Base()
    True
    """


@cython.c_api_binop_methods(False)
@cython.cclass
class OverloadLeft(Base):
    """
    >>> OverloadLeft() + 2
    'OverloadLeft.__add__(OverloadLeft(), 2)'
    >>> 2 + OverloadLeft()
    'Base.__radd__(OverloadLeft(), 2)'

    >>> OverloadLeft() + Base()
    'OverloadLeft.__add__(OverloadLeft(), Base())'
    >>> Base() + OverloadLeft()
    'Base.__add__(Base(), OverloadLeft())'

    >>> OverloadLeft(implemented=False) + Base(implemented=False)  #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: unsupported operand type...
    >>> Base(implemented=False) + OverloadLeft(implemented=False)  #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: unsupported operand type...
    """
    derived_implemented: cython.bint

    def __init__(self, *, implemented=True):
        super().__init__(implemented=implemented)
        self.derived_implemented = implemented

    def __add__(self, other):
        assert cython.typeof(self) == "OverloadLeft"
        if self.derived_implemented:
            return "OverloadLeft.__add__(%s, %s)" % (self, other)
        else:
            return NotImplemented


@cython.c_api_binop_methods(False)
@cython.cclass
class OverloadRight(Base):
    """
    >>> OverloadRight() + 2
    'Base.__add__(OverloadRight(), 2)'
    >>> 2 + OverloadRight()
    'OverloadRight.__radd__(OverloadRight(), 2)'

    >>> OverloadRight() + Base()
    'Base.__add__(OverloadRight(), Base())'
    >>> Base() + OverloadRight()
    'OverloadRight.__radd__(OverloadRight(), Base())'

    >>> OverloadRight(implemented=False) + Base(implemented=False)  #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: unsupported operand type...
    >>> Base(implemented=False) + OverloadRight(implemented=False)  #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: unsupported operand type...
    """
    derived_implemented: cython.bint

    def __init__(self, *, implemented=True):
        super().__init__(implemented=implemented)
        self.derived_implemented = implemented

    def __radd__(self, other):
        assert cython.typeof(self) == "OverloadRight"
        if self.derived_implemented:
            return "OverloadRight.__radd__(%s, %s)" % (self, other)
        else:
            return NotImplemented


@cython.c_api_binop_methods(True)
@cython.cclass
class OverloadCApi(Base):
    """
    >>> OverloadCApi() + 2
    'OverloadCApi.__add__(OverloadCApi(), 2)'
    >>> 2 + OverloadCApi()
    'OverloadCApi.__add__(2, OverloadCApi())'

    >>> OverloadCApi() + Base()
    'OverloadCApi.__add__(OverloadCApi(), Base())'
    >>> Base() + OverloadCApi()
    'OverloadCApi.__add__(Base(), OverloadCApi())'

    >>> OverloadCApi(derived_implemented=False) + 2 #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: unsupported operand type...
    >>> 2 + OverloadCApi(derived_implemented=False) #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: unsupported operand type...
    """
    derived_implemented: cython.bint

    def __init__(self, *, derived_implemented=True):
        super().__init__(implemented=True)
        self.derived_implemented = derived_implemented

    def __add__(self, other):
        assert cython.typeof(self) != "OverloadCApi"  # should be untyped
        if isinstance(self, OverloadCApi):
            derived_implemented = (self).derived_implemented
        else:
            derived_implemented = (other).derived_implemented
        if derived_implemented:
            return "OverloadCApi.__add__(%s, %s)" % (self, other)
        else:
            return NotImplemented


if sys.version_info >= (3, 5):
    __doc__ += """
    >>> d = PyVersionDependent()
    >>> d @ 2
    9
    >>> 2 @ d
    99
    >>> i = d
    >>> i @= 2
    >>> i
    999
"""


@cython.c_api_binop_methods(False)
@cython.cclass
class PyVersionDependent:
    """
    >>> d = PyVersionDependent()
    >>> d / 2
    5
    >>> 2 / d
    2
    >>> d // 2
    55
    >>> 2 // d
    22
    >>> i = d
    >>> i /= 2
    >>> i
    4
    >>> i = d
    >>> i //= 2
    >>> i
    44
    """
    def __div__(self, other):
        assert IS_PYTHON2
        return 5

    def __rdiv__(self, other):
        assert IS_PYTHON2
        return 2

    def __idiv__(self, other):
        assert IS_PYTHON2
        return 4

    def __truediv__(self, other):
        assert not IS_PYTHON2
        return 5

    def __rtruediv__(self, other):
        assert not IS_PYTHON2
        return 2

    def __itruediv__(self, other):
        assert not IS_PYTHON2
        return 4

    def __floordiv__(self, other):
        return 55

    def __rfloordiv__(self, other):
        return 22

    def __ifloordiv__(self, other):
        return 44

    def __matmul__(self, other):
        return 9

    def __rmatmul__(self, other):
        return 99

    def __imatmul__(self, other):
        return 999


# TODO: Test a class that only defines the `__r...__()` methods.
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/bint.pyx0000644000175100001770000000114600000000000017242 0ustar00runnerdocker00000000000000from cython cimport typeof

def test(bint value):
    """
    >>> test(True)
    True
    >>> test(False)
    False
    >>> test(None)
    False

    >>> test(0)
    False
    >>> test(1)
    True
    >>> test(-1)
    True
    >>> test(100)
    True

    >>> test(0.0)
    False
    >>> test(0.1)
    True

    >>> test([])
    False
    >>> test([1, 2, 3])
    True
    """
    return value

def test_types(bint a):
    """
    >>> test_types(None)
    """
    cdef bint b = a
    assert typeof(a) == 'bint', typeof(a)
    assert typeof(b) == 'bint', typeof(b)
    c = b
    assert typeof(c) == 'bint', typeof(c)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/bint_binop_T145.pyx0000644000175100001770000000451000000000000021144 0ustar00runnerdocker00000000000000# ticket: t145

cimport cython

@cython.test_fail_if_path_exists('//BoolBinopNode')
def or_literal_bint():
    """
    >>> True or 5
    True
    >>> or_literal_bint()
    True
    """
    return True or 5

@cython.test_fail_if_path_exists('//BoolBinopNode')
def and_literal_bint():
    """
    >>> 5 and True
    True
    >>> and_literal_bint()
    True
    """
    return 5 and True

@cython.test_fail_if_path_exists('//BoolBinopNode')
def False_and_True_or_0():
    """
    >>> False and True or 0
    0
    >>> False_and_True_or_0()
    0
    """
    return False and True or 0

@cython.test_fail_if_path_exists('//BoolBinopNode')
def True_and_True_or_0():
    """
    >>> True and True or 0
    True
    >>> True_and_True_or_0()
    True
    """
    return True and True or 0

def x_and_True_or_False(x):
    """
    >>> x_and_True_or_False(0)
    False
    >>> x_and_True_or_False(1)
    True
    >>> x_and_True_or_False('abc')
    True
    >>> x_and_True_or_False([])
    False
    """
    return x and True or False

def x_and_True_or_0(x):
    """
    >>> 0 and True or 0
    0
    >>> x_and_True_or_0(0)
    0

    >>> 1 and True or 0
    True
    >>> x_and_True_or_0(1)
    True

    >>> x_and_True_or_0('abc')
    True
    >>> x_and_True_or_0([])
    0
    """
    return x and True or 0

def x_and_True_or_1(x):
    """
    >>> 0 and True or 1
    1
    >>> x_and_True_or_1(0)
    1

    >>> 1 and True or 1
    True
    >>> x_and_True_or_1(1)
    True

    >>> x_and_True_or_1('abc')
    True
    >>> x_and_True_or_1([])
    1
    """
    return x and True or 1

def x_and_1_or_False(x):
    """
    >>> 0 and 1 or False
    False
    >>> x_and_1_or_False(0)
    False

    >>> 1 and 1 or False
    1
    >>> x_and_1_or_False(1)
    1

    >>> x_and_1_or_False('abc')
    1
    >>> x_and_1_or_False([])
    False
    """
    return x and 1 or False

def test_large_int(unsigned long x):
    """
    >>> try: test_large_int(1 << 127)
    ... except OverflowError: print(True)
    True
    >>> try: test_large_int(1 << 63)
    ... except OverflowError: print(True)
    True
    >>> try: test_large_int(1 << 48)
    ... except OverflowError: print(True)
    True
    >>> try: test_large_int(1 << 31)
    ... except OverflowError: print(True)
    True
    >>> test_large_int(0)
    False
    """
    if True and x:
        return True
    else:
        return False
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/bint_property_T354.pyx0000644000175100001770000000051100000000000021720 0ustar00runnerdocker00000000000000# ticket: t354

cdef class Test:
    """
    >>> t = Test(True)
    >>> t.some_ro_bool
    True
    >>> t.some_public_bool
    True
    """
    cdef public bint some_public_bool
    cdef readonly bint some_ro_bool

    def __init__(self, bint boolval):
        self.some_ro_bool = boolval
        self.some_public_bool = boolval
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/bishop1.pyx0000644000175100001770000000050700000000000017653 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> m = fmatrix()
    >>> m[1] = True
    >>> m.getfoo()
    1
    >>> m[0] = True
    >>> m.getfoo()
    0
"""

cdef class fmatrix:
  cdef int foo

  def __setitem__(self, int key, int value):
    if key:
      self.foo = value
      return
    self.foo = not value

  def getfoo(self):
    return self.foo
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/bishop2.pyx0000644000175100001770000000022500000000000017651 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> f = foo()
    >>> 'a' in f
    True
    >>> 1 in f
    True
"""

cdef class foo:

  def __contains__(self, key):
    return 1
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/boolean_context.pyx0000644000175100001770000000034000000000000021464 0ustar00runnerdocker00000000000000
def test():
    """
    >>> test()
    True
    """
    cdef int x = 5
    return bool(x)

def test_bool_and_int():
    """
    >>> test_bool_and_int()
    1
    """
    cdef int x = 5
    cdef int b = bool(x)
    return b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/boolop.pyx0000644000175100001770000000314700000000000017603 0ustar00runnerdocker00000000000000
def simple_values(obj1, obj2, obj3, obj4):
    """
    >>> simple_values(True, False, 23, 'test')
    (0.0, 1.0, False, False)
    """
    cdef int bool1, bool2
    cdef float bool3, bool4
    cdef char *ptr1, *ptr2, *ptr0
    cdef float f
    bool1 = 1
    bool2 = 0
    ptr1 = ptr2 = NULL
    f = 0.0

    bool3 = bool1 and bool2
    bool3 = bool1 or bool2
    bool3 = obj1 and obj2
    ptr0 = ptr1 and ptr2
    bool3 = bool1 and f
    bool4 = bool1 and bool2 and bool3
    bool4 = bool1 or bool2 and bool3
    obj4 = obj1 and obj2 and obj3
    obj5 = (obj1 + obj2 + obj3) and obj4
    return bool3, bool4, obj4, obj5


def non_simple_values(obj1, obj2, obj3, obj4):
    """
    >>> non_simple_values(1, 2, 3, 4)
    (7, 3, 7, 3, 7, 7, 5, 5)
    >>> non_simple_values(0, 0, 3, 4)
    (0, 7, 4, 4, 4, 4, 4, 4)
    >>> non_simple_values(0, 0, 1, -1)
    (0, 0, -1, 0, -1, -1, 0, 0)
    >>> non_simple_values(1, -1, 1, -1)
    (0, 0, 0, 0, 0, 0, 0, 0)
    >>> non_simple_values(1, 2, 1, -1)
    (0, 3, 0, 3, 0, 0, 1, 1)
    >>> non_simple_values(2, 1, 1, -1)
    (0, 3, 1, 3, 0, 0, 1, 1)
    """
    and1 = obj1 + obj2 and obj3 + obj4
    or1 = obj1 + obj2 or obj3 + obj4
    and_or = obj1 + obj2 and obj3 + obj4 or obj1 + obj4
    or_and = obj1 + obj2 or obj3 + obj4 and obj1 + obj4
    and_or_and = obj1 + obj2 and obj3 + obj4 or obj1 + obj4 and obj2 + obj4
    and1_or_and = (and1 or (obj1 + obj4 and obj2 + obj4))
    or_and_or = (obj1 + obj2 or obj3 + obj4) and (obj1 + obj4 or obj2 + obj4)
    or1_and_or = (or1 and (obj1 + obj4 or obj2 + obj4))
    return (and1, or1, and_or, or_and, and_or_and, and1_or_and, or_and_or, or1_and_or)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/boolop_py.py0000644000175100001770000000177100000000000020124 0ustar00runnerdocker00000000000000
def non_simple_values(obj1, obj2, obj3, obj4):
    """
    >>> non_simple_values(1, 2, 3, 4)
    (7, 3, 7, 3, 7, 7, 5, 5)
    >>> non_simple_values(0, 0, 3, 4)
    (0, 7, 4, 4, 4, 4, 4, 4)
    >>> non_simple_values(0, 0, 1, -1)
    (0, 0, -1, 0, -1, -1, 0, 0)
    >>> non_simple_values(1, -1, 1, -1)
    (0, 0, 0, 0, 0, 0, 0, 0)
    >>> non_simple_values(1, 2, 1, -1)
    (0, 3, 0, 3, 0, 0, 1, 1)
    >>> non_simple_values(2, 1, 1, -1)
    (0, 3, 1, 3, 0, 0, 1, 1)
    """
    and1 = obj1 + obj2 and obj3 + obj4
    or1 = obj1 + obj2 or obj3 + obj4
    and_or = obj1 + obj2 and obj3 + obj4 or obj1 + obj4
    or_and = obj1 + obj2 or obj3 + obj4 and obj1 + obj4
    and_or_and = obj1 + obj2 and obj3 + obj4 or obj1 + obj4 and obj2 + obj4
    and1_or_and = (and1 or (obj1 + obj4 and obj2 + obj4))
    or_and_or = (obj1 + obj2 or obj3 + obj4) and (obj1 + obj4 or obj2 + obj4)
    or1_and_or = (or1 and (obj1 + obj4 or obj2 + obj4))
    return (and1, or1, and_or, or_and, and_or_and, and1_or_and, or_and_or, or1_and_or)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/bound_builtin_methods_T589.pyx0000644000175100001770000000370100000000000023416 0ustar00runnerdocker00000000000000# ticket: t589

cimport cython

_set = set # CPython may not define it (in Py2.3), but Cython does :)


def test_set_clear_bound():
    """
    >>> type(test_set_clear_bound()) is _set
    True
    >>> list(test_set_clear_bound())
    []
    """
    cdef set s1 = set([1])
    clear = s1.clear
    clear()
    return s1

text = u'ab jd  sdflk as sa  sadas asdas fsdf '
pipe_sep = u'|'


@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
)
def test_unicode_join_bound(unicode sep, l):
    """
    >>> l = text.split()
    >>> len(l)
    8
    >>> print( pipe_sep.join(l) )
    ab|jd|sdflk|as|sa|sadas|asdas|fsdf
    >>> print( test_unicode_join_bound(pipe_sep, l) )
    ab|jd|sdflk|as|sa|sadas|asdas|fsdf
    """
    join = sep.join
    return join(l)


def test_unicode_join_bound_no_assignment(unicode sep):
    """
    >>> test_unicode_join_bound_no_assignment(text)
    """
    sep.join


def test_dict_items_bound_no_assignment(dict d):
    """
    >>> test_dict_items_bound_no_assignment({1:2})
    """
    d.items


def list_pop(list l):
    """
    >>> list_pop([1,2,3])
    (2, [1, 3])
    """
    pop = l.pop
    r = pop(1)
    return r, l


def list_pop_literal():
    """
    >>> list_pop_literal()
    (2, [1, 3])
    """
    l = [1,2,3]
    pop = l.pop
    r = pop(1)
    return r, l


def list_pop_reassign():
    """
    >>> list_pop_reassign()
    2
    """
    l = [1,2,3]
    pop = l.pop
    l = None
    r = pop(1)
    return r


def list_insert(list l):
    """
    >>> list_insert([1,2,3])
    (None, [1, 4, 2, 3])
    """
    insert = l.insert
    r = insert(1, 4)
    return r, l


def list_insert_literal():
    """
    >>> list_insert_literal()
    (None, [1, 4, 2, 3])
    """
    l = [1,2,3]
    insert = l.insert
    r = insert(1, 4)
    return r, l


def list_insert_reassign():
    """
    >>> list_insert_reassign()
    (None, [1, 4, 2, 3])
    """
    l = [1,2,3]
    insert = l.insert
    m, l = l, None
    r = insert(1, 4)
    return r, m
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/broken_exception.pyx0000644000175100001770000000065200000000000021645 0ustar00runnerdocker00000000000000
import sys

def exception_creates_invalid_instance():
    """
    >>> print( exception_creates_invalid_instance() )
    OK
    """
    class MyException(Exception):
        def __new__(cls, *args):
            return object()

    if sys.version_info[0] >= 3:
        expected_error = TypeError
    else:
        expected_error = MyException

    try:
        raise MyException
    except expected_error:
        return "OK"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/buffer_n_overflowcheck_T5356.pyx0000644000175100001770000000052200000000000023620 0ustar00runnerdocker00000000000000# mode: run
# ticket: t5356

cimport cython


@cython.overflowcheck(True)
cdef size_t _mul_checked(size_t a, size_t b) except? -1:
    return a * b


def f(unsigned char[:] a, unsigned char[:] b):
    """
    >>> f(memoryview(bytearray(b"12")), memoryview(bytearray(b"345")))
    6
    """
    return _mul_checked(a.shape[0], b.shape[0])
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/builtin_abs.pyx0000644000175100001770000002107700000000000020606 0ustar00runnerdocker00000000000000# mode: run
# ticket: t698
# distutils: extra_compile_args=-fwrapv

cdef extern from *:
    int INT_MAX
    long LONG_MAX

max_int = INT_MAX
max_long = LONG_MAX
max_long_long = (2) ** (sizeof(long long) * 8 - 1) - 1


cimport cython

def abs_as_name():
    """
    >>> _abs = abs_as_name()
    >>> _abs(-5)
    5
    """
    x = abs
    return x

def py_abs(a):
    """
    >>> py_abs(-5)
    5
    >>> py_abs(-5.5)
    5.5
    """
    return abs(a)

@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
                                "//ReturnStatNode//NameNode[@entry.cname = 'abs']")
def sub_abs(int a):
    """
    >>> sub_abs(5)
    (-5, 95)
    >>> sub_abs(105)
    (-105, -5)
    """
    return -abs(a), 100 - abs(a)

@cython.overflowcheck(True)
@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
                                "//ReturnStatNode//NameNode[@entry.cname = 'abs']")
def int_abs(int a):
    """
    >>> int_abs(-5) == 5
    True
    >>> int_abs(-5.1) == 5
    True
    >>> int_abs(-max_int-1)     #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    OverflowError: ...
    >>> int_abs(max_int) == abs(max_int)         or (max_int, int_abs(max_int), abs(max_int))
    True
    """
    return abs(a)

@cython.overflowcheck(True)
@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
                                "//ReturnStatNode//NameNode[@entry.cname = 'abs']")
cdef int c_int_abs(int a) except * nogil:
    return abs(a)

def test_c_int_abs(int a):
    """
    >>> test_c_int_abs(-5) == 5
    True
    >>> test_c_int_abs(-5.1) == 5
    True
    >>> test_c_int_abs(-max_int-1)     #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    OverflowError: ...
    >>> test_c_int_abs(max_int) == abs(max_int)  or (max_int, test_c_int_abs(max_int), abs(max_int))
    True
    """
    return c_int_abs(a)

@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']")
@cython.test_fail_if_path_exists("//ReturnStatNode//NameNode[@entry.cname = 'abs']",
                                 "//ReturnStatNode//NameNode[@entry.cname = 'labs']")
def uint_abs(unsigned int a):
    """
    >>> uint_abs(max_int) == abs(max_int)         or (max_int, uint_abs(max_int), abs(max_int))
    True
    """
    return abs(a)

@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']")
@cython.test_fail_if_path_exists("//ReturnStatNode//NameNode[@entry.cname = 'abs']",
                                 "//ReturnStatNode//NameNode[@entry.cname = 'labs']")
cdef unsigned int c_uint_abs(unsigned int a) nogil:
    return abs(a)

def test_c_uint_abs(unsigned int a):
    """
    >>> test_c_uint_abs(max_int) == abs(max_int)  or (max_int, test_c_uint_abs(max_int), abs(max_int))
    True
    """
    return c_uint_abs(a)

@cython.overflowcheck(True)
@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
                                "//ReturnStatNode//NameNode[@entry.cname = 'labs']")
def long_abs(long a):
    """
    >>> long_abs(-5) == 5
    True
    >>> long_abs(-5.1) == 5
    True
    >>> long_abs(-max_long-1)     #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    OverflowError: ...
    >>> long_abs(max_long) == abs(max_long)         or (max_long, long_abs(max_long), abs(max_long))
    True
    """
    return abs(a)

@cython.overflowcheck(True)
@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
                                "//ReturnStatNode//NameNode[@entry.cname = 'labs']")
cdef long c_long_abs(long a) except * nogil:
    return abs(a)

def test_c_long_abs(long a):
    """
    >>> test_c_long_abs(-5) == 5
    True
    >>> test_c_long_abs(-5.1) == 5
    True
    >>> test_c_long_abs(-max_long-1)     #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    OverflowError: ...
    >>> test_c_long_abs(max_long) == abs(max_long)  or (max_long, test_c_long_abs(max_long), abs(max_long))
    True
    """
    return c_long_abs(a)

@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']")
@cython.test_fail_if_path_exists("//ReturnStatNode//NameNode[@entry.cname = 'abs']",
                                 "//ReturnStatNode//NameNode[@entry.cname = 'labs']")
def ulong_abs(unsigned long a):
    """
    >>> ulong_abs(max_long) == abs(max_long)         or (max_int, ulong_abs(max_long), abs(max_long))
    True
    >>> ulong_abs(max_long + 5) == abs(max_long + 5)         or (max_long + 5, ulong_abs(max_long + 5), abs(max_long + 5))
    True
    """
    return abs(a)

@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']")
@cython.test_fail_if_path_exists("//ReturnStatNode//NameNode[@entry.cname = 'abs']",
                                 "//ReturnStatNode//NameNode[@entry.cname = 'labs']")
cdef unsigned long c_ulong_abs(unsigned long a) nogil:
    return abs(a)

def test_c_ulong_abs(unsigned long a):
    """
    >>> test_c_ulong_abs(max_long) == abs(max_long)  or (max_int, test_c_ulong_abs(max_long), abs(max_long))
    True
    >>> test_c_ulong_abs(max_long + 5) == abs(max_long + 5)  or (max_long + 5, test_c_ulong_abs(max_long + 5), abs(max_long + 5))
    True
    """
    return c_ulong_abs(a)

@cython.overflowcheck(True)
@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
                                "//ReturnStatNode//NameNode[@entry.cname = '__Pyx_abs_longlong']")
def long_long_abs(long long a):
    """
    >>> long_long_abs(-(2**33)) == 2**33
    True
    >>> long_long_abs(-max_long_long-1)     #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    OverflowError: ...
    >>> long_long_abs(max_long_long) == abs(max_long_long)        or (max_long_long, long_long_abs(max_long_long), abs(max_long_long))
    True
    """
    return abs(a)

@cython.overflowcheck(True)
@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
                                "//ReturnStatNode//NameNode[@entry.cname = '__Pyx_abs_longlong']")
cdef long long c_long_long_abs(long long a) except * nogil:
    return abs(a)

def test_c_long_long_abs(long long a):
    """
    >>> test_c_long_long_abs(-(2**33)) == 2**33
    True
    >>> test_c_long_long_abs(-max_long_long-1)     #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    OverflowError: ...
    >>> test_c_long_long_abs(max_long_long) == abs(max_long_long) or (max_long_long, test_c_long_long_abs(max_long_long), abs(max_long_long))
    True
    """
    return c_long_long_abs(a)

@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
                                "//ReturnStatNode//NameNode[@entry.cname = 'fabs']")
def double_abs(double a):
    """
    >>> double_abs(-5)
    5.0
    >>> double_abs(-5.5)
    5.5
    """
    return abs(a)

@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
                                "//ReturnStatNode//NameNode[@entry.cname = 'fabs']")
cdef double c_double_abs(double a) nogil:
    return abs(a)

def test_c_double_abs(double a):
    """
    >>> test_c_double_abs(-5)
    5.0
    >>> test_c_double_abs(-5.5)
    5.5
    """
    return c_double_abs(a)

@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
                                "//ReturnStatNode//NameNode[@entry.cname = 'fabsf']")
def float_abs(float a):
    """
    >>> float_abs(-5)
    5.0
    >>> float_abs(-5.5)
    5.5
    """
    return abs(a)

@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
                                "//ReturnStatNode//NameNode[@entry.cname = 'fabsf']")
cdef float c_float_abs(float a) nogil:
    return abs(a)

def test_c_float_abs(float a):
    """
    >>> test_c_float_abs(-5)
    5.0
    >>> test_c_float_abs(-5.5)
    5.5
    """
    return c_float_abs(a)

@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
                                "//ReturnStatNode//NameNode[@entry.cname = '__Pyx_c_abs_double']")
def complex_abs(complex a):
    """
    >>> complex_abs(-5j)
    5.0
    >>> complex_abs(-5.5j)
    5.5
    """
    return abs(a)

@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
                                "//ReturnStatNode//NameNode[@entry.cname = '__Pyx_c_abs_double']")
cdef double c_complex_abs(complex a) nogil:
    return abs(a)

def test_c_complex_abs(complex a):
    """
    >>> test_c_complex_abs(-5j)
    5.0
    >>> test_c_complex_abs(-5.5j)
    5.5
    """
    return c_complex_abs(a)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/builtin_basestring.pyx0000644000175100001770000000521600000000000022177 0ustar00runnerdocker00000000000000
cimport cython

import sys
IS_PY3 = sys.version_info[0] >= 3

ustring = u'abcdef'
sstring =  'abcdef'
bstring = b'abcdef'


def isinstance_basestring(obj):
    """
    >>> isinstance_basestring(ustring)
    True
    >>> isinstance_basestring(sstring)
    True
    >>> if IS_PY3: print(not isinstance_basestring(bstring))
    ... else: print(isinstance_basestring(bstring))
    True
    """
    return isinstance(obj, basestring)


def basestring_is_unicode_in_py3():
    """
    >>> basestring_is_unicode_in_py3()
    True
    """
    if IS_PY3:
        return basestring is unicode
    else:
        return basestring is not unicode


def unicode_subtypes_basestring():
    """
    >>> unicode_subtypes_basestring()
    True
    """
    return issubclass(unicode, basestring)


def basestring_typed_variable(obj):
    """
    >>> basestring_typed_variable(None) is None
    True
    >>> basestring_typed_variable(ustring) is ustring
    True
    >>> basestring_typed_variable(sstring) is sstring
    True
    >>> if IS_PY3: print(True)
    ... else: print(basestring_typed_variable(bstring) is bstring)
    True
    >>> class S(str): pass
    >>> basestring_typed_variable(S())   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...got S...
    """
    cdef basestring s
    s = u'abc'
    assert s
    s = 'abc'
    assert s
    # make sure coercion also works in conditional expressions
    s = u'abc' if obj else 'abc'
    assert s
    s = obj
    return s


def basestring_typed_argument(basestring obj):
    """
    >>> basestring_typed_argument(None) is None
    True
    >>> basestring_typed_argument(ustring) is ustring
    True
    >>> basestring_typed_argument(sstring) is sstring
    True
    >>> if IS_PY3: print(True)
    ... else: print(basestring_typed_argument(bstring) is bstring)
    True
    >>> class S(str): pass
    >>> basestring_typed_argument(S())   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...got S...
    """
    return obj


@cython.test_assert_path_exists(
    "//SimpleCallNode",
    "//SimpleCallNode//NoneCheckNode",
    "//SimpleCallNode//AttributeNode[@is_py_attr = false]")
def basestring_join(basestring s, *values):
    """
    >>> print(basestring_join(ustring, 'a', 'b', 'c'))
    aabcdefbabcdefc
    >>> print(basestring_join(sstring, 'a', 'b', 'c'))
    aabcdefbabcdefc
    >>> if IS_PY3: print('abcdefabcdefabcdef')
    ... else: print(basestring_join(bstring, bstring, bstring).decode('utf8'))
    abcdefabcdefabcdef
    >>> basestring_join(None, 'a', 'b', 'c')
    Traceback (most recent call last):
    AttributeError: 'NoneType' object has no attribute 'join'
    """
    return s.join(values)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/builtin_callable.pyx0000644000175100001770000000071200000000000021571 0ustar00runnerdocker00000000000000# mode: run
# tag: builtin, callable

cimport cython

@cython.test_assert_path_exists("//SimpleCallNode[@type.is_pyobject = False]")
def test_callable(x):
    """
    >>> test_callable(None)
    False
    >>> test_callable('ABC')
    False

    >>> class C: pass
    >>> test_callable(C)
    True
    >>> test_callable(C())
    False

    >>> test_callable(int)
    True
    >>> test_callable(test_callable)
    True
    """
    b = callable(x)
    return b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/builtin_float.py0000644000175100001770000001773700000000000020766 0ustar00runnerdocker00000000000000# mode: run
# tag: pure3.0

import cython
import sys

def fix_underscores(s):
    if sys.version_info < (3, 6) or getattr(sys, 'pypy_version_info', (9, 9)) < (3, 7, 4):
        # Py2 float() does not support PEP-515 underscore literals
        if isinstance(s, bytes):
            if not cython.compiled and b'_' in s:
                return s.replace(b'_', b'')
        elif '_' in s:
            return s.replace('_', '')
    return s


def empty_float():
    """
    >>> float()
    0.0
    >>> empty_float()
    0.0
    """
    x = float()
    return x


def float_conjugate():
    """
    >>> float_call_conjugate()
    1.5
    """
    x = 1.5 .conjugate()
    return x


def float_call_conjugate():
    """
    >>> float_call_conjugate()
    1.5
    """
    x = float(1.5).conjugate()
    return x


def from_int(i):
    """
    >>> from_int(0)
    0.0
    >>> from_int(1)
    1.0
    >>> from_int(-1)
    -1.0
    >>> from_int(99)
    99.0
    >>> from_int(-99)
    -99.0

    >>> for exp in (14, 15, 16, 30, 31, 32, 52, 53, 54, 60, 61, 62, 63, 64):
    ...     for sign in (1, 0, -1):
    ...         value = (sign or 1) * 2**exp + sign
    ...         float_value = from_int(value)
    ...         assert float_value == float(value), "expected %s2**%s+%s == %r, got %r, difference %r" % (
    ...             '-' if sign < 0 else '', exp, sign, float(value), float_value, float_value - float(value))
    """
    return float(i)


@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//CoerceToPyTypeNode//PythonCapiCallNode",
)
def from_bytes(s: bytes):
    """
    >>> from_bytes(b"123")
    123.0
    >>> from_bytes(b"123.25")
    123.25
    >>> from_bytes(fix_underscores(b"98_5_6.2_1"))
    9856.21
    >>> from_bytes(fix_underscores(b"12_4_131_123123_1893798127398123_19238712_128937198237.8222113_519879812387"))
    1.2413112312318938e+47
    >>> from_bytes(b"123E100")
    1.23e+102
    >>> from_bytes(b"12__._3")  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...12__._3...
    >>> from_bytes(b"_12.3")  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ..._12.3...
    >>> from_bytes(b"12.3_")  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...12.3_...
    >>> from_bytes(b"na_n")  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...na_n...
    >>> from_bytes(None)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError...
    """
    return float(s)


@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//CoerceToPyTypeNode//PythonCapiCallNode",
)
def from_bytes_literals():
    """
    >>> from_bytes_literals()
    (123.0, 123.23, 123.76, 1e+100)
    """
    return float(b"123"), float(b"123.23"), float(fix_underscores(b"12_3.7_6")), float(b"1e100")


@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//CoerceToPyTypeNode//PythonCapiCallNode",
)
def from_bytearray(s: bytearray):
    """
    >>> from_bytearray(bytearray(b"123"))
    123.0
    >>> from_bytearray(bytearray(b"123.25"))
    123.25
    >>> from_bytearray(bytearray(fix_underscores(b"98_5_6.2_1")))
    9856.21
    >>> from_bytearray(bytearray(fix_underscores(b"12_4_131_123123_1893798127398123_19238712_128937198237.8222113_519879812387")))
    1.2413112312318938e+47
    >>> from_bytearray(bytearray(b"123E100"))
    1.23e+102
    >>> from_bytearray(bytearray(b"12__._3"))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...12__._3...
    >>> from_bytearray(bytearray(b"_12.3"))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ..._12.3...
    >>> from_bytearray(bytearray(b"12.3_"))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...12.3_...
    >>> from_bytearray(bytearray(b"in_f"))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...in_f...
    >>> from_bytearray(None)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError...
    """
    return float(s)


@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//CoerceToPyTypeNode//PythonCapiCallNode",
)
def from_str(s: 'str'):
    """
    >>> from_str("123")
    123.0
    >>> from_str("123.25")
    123.25
    >>> from_str(fix_underscores("3_21.2_5"))
    321.25
    >>> from_str(fix_underscores("12_4_131_123123_1893798127398123_19238712_128937198237.8222113_519879812387"))
    1.2413112312318938e+47
    >>> from_str("123E100")
    1.23e+102
    >>> from_str("12__._3")  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...12__._3...
    >>> from_str("_12.3")  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ..._12.3...
    >>> from_str("12.3_")  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...12.3_...
    >>> from_str("n_an")  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...n_an...
    >>> from_str(None)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError...
    """
    return float(s)


@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//CoerceToPyTypeNode//PythonCapiCallNode",
)
def from_str_literals():
    """
    >>> from_str_literals()
    (123.0, 123.23, 124.23, 1e+100)
    """
    return float("123"), float("123.23"), float(fix_underscores("1_2_4.2_3")), float("1e100")


@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//CoerceToPyTypeNode//PythonCapiCallNode",
)
def from_unicode(s: 'unicode'):
    """
    >>> from_unicode(u"123")
    123.0
    >>> from_unicode(u"123.25")
    123.25
    >>> from_unicode(fix_underscores(u"12_4.8_5"))
    124.85
    >>> from_unicode(fix_underscores(u"12_4_131_123123_1893798127398123_19238712_128937198237.8222113_519879812387"))
    1.2413112312318938e+47
    >>> from_unicode(u"123E100")
    1.23e+102
    >>> from_unicode(u"123.23\\N{PUNCTUATION SPACE}")
    123.23
    >>> from_unicode(u"\\N{PUNCTUATION SPACE} 123.23 \\N{PUNCTUATION SPACE}")
    123.23
    >>> from_unicode(fix_underscores(u"\\N{PUNCTUATION SPACE} 12_3.2_3 \\N{PUNCTUATION SPACE}"))
    123.23
    >>> from_unicode(u"\\N{PUNCTUATION SPACE} " * 25 + u"123.54 " + u"\\N{PUNCTUATION SPACE} " * 22)  # >= 40 chars
    123.54
    >>> from_unicode(fix_underscores(u"\\N{PUNCTUATION SPACE} " * 25 + u"1_23.5_4 " + u"\\N{PUNCTUATION SPACE} " * 22))
    123.54
    >>> from_unicode(u"\\N{PUNCTUATION SPACE} " + u"123.54 " * 2 + u"\\N{PUNCTUATION SPACE}")  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...123.54 123.54...
    >>> from_unicode(u"\\N{PUNCTUATION SPACE} " * 25 + u"123.54 " * 2 + u"\\N{PUNCTUATION SPACE} " * 22)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...123.54 123.54...
    >>> from_unicode(u"_12__._3")  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ..._12__._3...
    >>> from_unicode(u"_12.3")  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ..._12.3...
    >>> from_unicode(u"12.3_")  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...12.3_...
    >>> from_unicode(u"i_nf")  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...i_nf...
    >>> from_unicode(None)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError...
    """
    return float(s)


@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//CoerceToPyTypeNode//PythonCapiCallNode",
)
def from_unicode_literals():
    """
    >>> from_unicode_literals()
    (123.0, 123.23, 123.45, 1e+100, 123.23)
    """
    return float(u"123"), float(u"123.23"), float(fix_underscores(u"12_3.4_5")), float(u"1e100"), float(u"123.23\N{PUNCTUATION SPACE}")


def catch_valueerror(val):
    """
    >>> catch_valueerror("foo")
    False
    >>> catch_valueerror(u"foo")
    False
    >>> catch_valueerror(b"foo")
    False
    >>> catch_valueerror(bytearray(b"foo"))
    False
    >>> catch_valueerror("-1")
    -1.0
    """
    try:
        return float(val)
    except ValueError:
        return False
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/builtin_globals.py0000644000175100001770000000033500000000000021266 0ustar00runnerdocker00000000000000# mode: run
# tag: allow_unknown_names

assert "NEW" not in globals()

globals().update(NEW=True)

assert "NEW" in globals()


def default_args(value=NEW):
    """
    >>> default_args()
    True
    """
    return value
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/builtin_len.pyx0000644000175100001770000000547400000000000020622 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*-

cimport cython

unicode_str = u'ab jd  üöä ôñ ÄÖ'
bytes_str   = b'ab jd  sdflk as sa  sadas asdas fsdf '

_frozenset = frozenset
_set = set

@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//PythonCapiCallNode")
def len_unicode(unicode s):
    """
    >>> len(unicode_str)
    16
    >>> len_unicode(unicode_str)
    16
    >>> len_unicode(None)
    Traceback (most recent call last):
    TypeError: object of type 'NoneType' has no len()
    """
    return len(s)

@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//PythonCapiCallNode")
def len_bytes(bytes s):
    """
    >>> len(bytes_str)
    37
    >>> len_bytes(bytes_str)
    37
    >>> len_bytes(None)
    Traceback (most recent call last):
    TypeError: object of type 'NoneType' has no len()
    """
    return len(s)

#@cython.test_assert_path_exists(
#    "//CoerceToPyTypeNode",
#    "//PythonCapiCallNode")
def len_str(str s):
    """
    >>> len('abcdefg')
    7
    >>> len_str('abcdefg')
    7
    >>> len_unicode(None)
    Traceback (most recent call last):
    TypeError: object of type 'NoneType' has no len()
    """
    return len(s)

@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//PythonCapiCallNode")
def len_list(list s):
    """
    >>> l = [1,2,3,4]
    >>> len(l)
    4
    >>> len_list(l)
    4
    >>> len_list(None)
    Traceback (most recent call last):
    TypeError: object of type 'NoneType' has no len()
    """
    return len(s)

@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//PythonCapiCallNode")
def len_tuple(tuple s):
    """
    >>> t = (1,2,3,4)
    >>> len(t)
    4
    >>> len_tuple(t)
    4
    >>> len_tuple(None)
    Traceback (most recent call last):
    TypeError: object of type 'NoneType' has no len()
    """
    return len(s)

@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//PythonCapiCallNode")
def len_dict(dict s):
    """
    >>> d = dict(a=1, b=2, c=3, d=4)
    >>> len(d)
    4
    >>> len_dict(d)
    4
    >>> len_dict(None)
    Traceback (most recent call last):
    TypeError: object of type 'NoneType' has no len()
    """
    return len(s)

@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//PythonCapiCallNode")
def len_set(set s):
    """
    >>> s = _set((1,2,3,4))
    >>> len(s)
    4
    >>> len_set(s)
    4
    >>> len_set(None)
    Traceback (most recent call last):
    TypeError: object of type 'NoneType' has no len()
    """
    return len(s)

@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//PythonCapiCallNode")
def len_frozenset(frozenset s):
    """
    >>> s = _frozenset((1,2,3,4))
    >>> len(s)
    4
    >>> len_frozenset(s)
    4
    >>> len_set(None)
    Traceback (most recent call last):
    TypeError: object of type 'NoneType' has no len()
    """
    return len(s)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/builtin_memory_view.pyx0000644000175100001770000000324300000000000022376 0ustar00runnerdocker00000000000000# mode: run

# Tests Python's builtin memoryview.

from __future__ import print_function

import sys

cimport cython
#from cpython.memoryview cimport PyMemoryView_GET_BUFFER

@cython.test_fail_if_path_exists("//SimpleCallNode")
def test_convert_from_obj(o):
    """
    >>> abc = b'abc'
    >>> all(x == y for x, y in zip(test_convert_from_obj(abc), abc))
    True
    """
    return memoryview(o)

# TODO - this currently doesn't work because the buffer fails a
# "can coerce to python object" test earlier. But it'd be nice to support
'''
def test_create_from_buffer():
    """
    memoryview from Py_buffer exists and is special-cased
    >>> mview = test_create_from_buffer()
    >>> >>> all(x == y for x, y in zip(mview, b'argh!'))
    True
    """
    other_view = memoryview(b'argh!')
    cdef Py_buffer *buf = PyMemoryView_GET_BUFFER(other_view)
    return memoryview(buf)
'''

@cython.test_fail_if_path_exists("//AttributeNode")
def test_optimized_attributes(memoryview view):
    """
    >>> test_optimized_attributes(memoryview(b'zzzzz'))
    1 1 True
    """
    print(view.itemsize, view.ndim, view.readonly)

def test_isinstance(x):
    """
    >>> test_isinstance(b"abc")
    False
    >>> test_isinstance(memoryview(b"abc"))
    True
    """
    return isinstance(x, memoryview)

def test_in_with(x):
    """
    This is really just a compile test. An optimization was being
    applied in a way that generated invalid code
    >>> test_in_with(b"abc")
    98
    """
    if sys.version_info[0] < 3:
        # Python 2 doesn't support memoryviews as context-managers
        # so just skip the test
        print(98)
        return
    with memoryview(x) as xv:
        print(xv[1])
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/builtin_methods_return_values.pyx0000644000175100001770000000343000000000000024453 0ustar00runnerdocker00000000000000# mode: run
# tag: list, set, builtins
# ticket: t688

_set = set

class TestObj(object):
    pass

def _setattr(obj):
    """
    >>> t = TestObj()
    >>> _setattr(t) is None
    True
    >>> t.test is None
    True
    """
    setattr(obj, 'test', None)
    return setattr(obj, 'test', None)

def _delattr(obj):
    """
    >>> t = TestObj()
    >>> t.test1 = t.test2 = True
    >>> _delattr(t) is None
    True
    >>> hasattr(t, 'test1')
    False
    >>> hasattr(t, 'test2')
    False
    """
    delattr(obj, 'test1')
    return delattr(obj, 'test2')

def list_sort(list l):
    """
    >>> list_sort([1,2,3]) is None
    True
    """
    l.sort()
    return l.sort()

def list_reverse(list l):
    """
    >>> list_reverse([1,2,3]) is None
    True
    """
    l.reverse()
    return l.reverse()

def list_insert(list l):
    """
    >>> list_insert([1,2,3]) is None
    True
    """
    l.insert(1, 2)
    return l.insert(1, 2)

def list_append(list l):
    """
    >>> list_append([1,2,3]) is None
    True
    """
    l.append(1)
    return l.append(2)

def set_clear(set s):
    """
    >>> set_clear(_set([1,2,3])) is None
    True
    >>> set_clear(None)
    Traceback (most recent call last):
    AttributeError: 'NoneType' object has no attribute 'clear'
    """
    s.clear()
    return s.clear()

def set_discard(set s):
    """
    >>> set_discard(_set([1,2,3])) is None
    True
    """
    s.discard(1)
    return s.discard(2)

def set_add(set s):
    """
    >>> set_add(_set([1,2,3])) is None
    True
    """
    s.add(1)
    return s.add(2)

def dict_clear(dict d):
    """
    >>> dict_clear({1:2,3:4}) is None
    True
    >>> dict_clear(None)
    Traceback (most recent call last):
    AttributeError: 'NoneType' object has no attribute 'clear'
    """
    d.clear()
    return d.clear()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/builtin_min_max.pyx0000644000175100001770000001546700000000000021477 0ustar00runnerdocker00000000000000# mode: run
# tag: optimisation

cimport cython


class loud_list(list):
    def __len__(self):
        print "calling __len__"
        return super(loud_list, self).__len__()


# min()

@cython.test_assert_path_exists("//CondExprNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def min3(a,b,c):
    """
    >>> min3(1,2,3)
    1
    >>> min3(2,3,1)
    1
    >>> min3(2,1,3)
    1
    >>> min3(3,1,2)
    1
    >>> min3(3,2,1)
    1
    """
    return min(a,b,c)


@cython.test_assert_path_exists("//CondExprNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def min3_list(a,b,c):
    """
    >>> min3_list(1,2,3)
    1
    >>> min3_list(2,3,1)
    1
    >>> min3_list(2,1,3)
    1
    >>> min3_list(3,1,2)
    1
    >>> min3_list(3,2,1)
    1
    """
    return min([a,b,c])


@cython.test_assert_path_exists("//CondExprNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def min3_tuple(a,b,c):
    """
    >>> min3_tuple(1,2,3)
    1
    >>> min3_tuple(2,3,1)
    1
    >>> min3_tuple(2,1,3)
    1
    >>> min3_tuple(3,1,2)
    1
    >>> min3_tuple(3,2,1)
    1
    """
    return min((a,b,c))


@cython.test_assert_path_exists("//CondExprNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def min3_typed(int a, int b, int c):
    """
    >>> min3_typed(1,2,3)
    1
    >>> min3_typed(2,3,1)
    1
    >>> min3_typed(2,1,3)
    1
    >>> min3_typed(3,1,2)
    1
    >>> min3_typed(3,2,1)
    1
    """
    return min(a,b,c)


@cython.test_assert_path_exists("//CondExprNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def literal_min3():
    """
    >>> literal_min3()
    (1, 1, 1, 1, 1)
    """
    return min(1,2,3), min(2,1,3), min(2,3,1), min(3,1,2), min(3,2,1)


@cython.test_assert_path_exists(
    '//PrintStatNode//CondExprNode')
@cython.test_fail_if_path_exists(
    '//PrintStatNode//SimpleCallNode//CoerceToPyTypeNode',
    '//PrintStatNode//SimpleCallNode//ConstNode')
def test_min2():
    """
    >>> test_min2()
    1
    1
    1
    1
    1
    calling __len__
    1
    calling __len__
    1
    """
    cdef int my_int = 1
    cdef object my_pyint = 2
    cdef object my_list = loud_list([1,2,3])

    print min(1, 2)
    print min(2, my_int)
    print min(my_int, 2)

    print min(my_int, my_pyint)
    print min(my_pyint, my_int)

    print min(my_int, len(my_list))
    print min(len(my_list), my_int)


@cython.test_assert_path_exists(
    '//PrintStatNode//CondExprNode')
@cython.test_fail_if_path_exists(
    '//PrintStatNode//SimpleCallNode//CoerceToPyTypeNode',
    '//PrintStatNode//SimpleCallNode//ConstNode')
def test_min3():
    """
    >>> test_min3()
    calling __len__
    1
    calling __len__
    calling __len__
    2
    """
    cdef int my_int = 1
    cdef object my_pyint = 2
    cdef object my_list = loud_list([1,2,3])

    print min(my_int, my_pyint, len(my_list))
    print min(my_pyint, my_list.__len__(), len(my_list))


@cython.test_assert_path_exists(
    '//PrintStatNode//CondExprNode')
@cython.test_fail_if_path_exists(
    '//PrintStatNode//SimpleCallNode//CoerceToPyTypeNode',
    '//PrintStatNode//SimpleCallNode//ConstNode')
def test_minN():
    """
    >>> test_minN()
    calling __len__
    0
    calling __len__
    0
    calling __len__
    0
    """
    cdef int my_int = 1
    cdef object my_pyint = 2
    cdef object my_list = loud_list([1,2,3])

    print min(my_int, 2, my_int, 0, my_pyint, my_int, len(my_list))
    print min(my_int, my_int, 0, my_pyint, my_int, len(my_list))
    print min(my_int, my_int, 2, my_int, 0, my_pyint, my_int, len(my_list))


# max()

@cython.test_assert_path_exists("//CondExprNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def max3(a,b,c):
    """
    >>> max3(1,2,3)
    3
    >>> max3(2,3,1)
    3
    >>> max3(2,1,3)
    3
    >>> max3(3,1,2)
    3
    >>> max3(3,2,1)
    3
    """
    return max(a,b,c)


@cython.test_assert_path_exists("//CondExprNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def max3_typed(int a, int b, int c):
    """
    >>> max3_typed(1,2,3)
    3
    >>> max3_typed(2,3,1)
    3
    >>> max3_typed(2,1,3)
    3
    >>> max3_typed(3,1,2)
    3
    >>> max3_typed(3,2,1)
    3
    """
    return max(a,b,c)


@cython.test_assert_path_exists("//CondExprNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def literal_max3():
    """
    >>> literal_max3()
    (3, 3, 3, 3, 3)
    """
    return max(1,2,3), max(2,1,3), max(2,3,1), max(3,1,2), max(3,2,1)


def max1(x):
    """
    >>> max1([1, 2, 3])
    3
    >>> max1([2])
    2
    """
    return max(x)


@cython.test_assert_path_exists(
    '//PrintStatNode//CondExprNode')
@cython.test_fail_if_path_exists(
    '//PrintStatNode//SimpleCallNode//CoerceToPyTypeNode',
    '//PrintStatNode//SimpleCallNode//ConstNode')
def test_max2():
    """
    >>> test_max2()
    2
    2
    2
    2
    2
    calling __len__
    3
    calling __len__
    3
    """
    cdef int my_int = 1
    cdef object my_pyint = 2
    cdef object my_list = loud_list([1,2,3])

    print max(1, 2)
    print max(2, my_int)
    print max(my_int, 2)

    print max(my_int, my_pyint)
    print max(my_pyint, my_int)

    print max(my_int, len(my_list))
    print max(len(my_list), my_int)


@cython.test_assert_path_exists(
    '//PrintStatNode//CondExprNode')
@cython.test_fail_if_path_exists(
    '//PrintStatNode//SimpleCallNode//CoerceToPyTypeNode',
    '//PrintStatNode//SimpleCallNode//ConstNode')
def test_max3():
    """
    >>> test_max3()
    calling __len__
    3
    calling __len__
    calling __len__
    3
    """
    cdef int my_int = 1
    cdef object my_pyint = 2
    cdef object my_list = loud_list([1,2,3])

    print max(my_int, my_pyint, len(my_list))
    print max(my_pyint, my_list.__len__(), len(my_list))


@cython.test_assert_path_exists(
    '//PrintStatNode//CondExprNode')
@cython.test_fail_if_path_exists(
    '//PrintStatNode//SimpleCallNode//CoerceToPyTypeNode',
    '//PrintStatNode//SimpleCallNode//ConstNode')
def test_maxN():
    """
    >>> test_maxN()
    calling __len__
    3
    calling __len__
    3
    calling __len__
    3
    """
    cdef int my_int = 1
    cdef object my_pyint = 2
    cdef object my_list = loud_list([1,2,3])

    print max(my_int, 2, my_int, 0, my_pyint, my_int, len(my_list))
    print max(my_int, my_int, 0, my_pyint, my_int, len(my_list))
    print max(my_int, my_int, 2, my_int, 0, my_pyint, my_int, len(my_list))


'''
# ticket 772
# FIXME: signed vs. unsigned fails to safely handle intermediate results

@cython.test_assert_path_exists("//CondExprNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def max3_typed_signed_unsigned(int a, unsigned int b, int c):
    """
    >>> max3_typed_signed_unsigned(1,2,-3)
    2
    >>> max3_typed_signed_unsigned(-2,3,1)
    3
    >>> max3_typed_signed_unsigned(-2,1,-3)
    1
    >>> max3_typed_signed_unsigned(3,-1,2)
    3
    >>> max3_typed_signed_unsigned(-3,2,1)
    2
    """
    return max(a,b,c)
'''
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/builtin_next.pyx0000644000175100001770000000317500000000000021016 0ustar00runnerdocker00000000000000
import sys
IS_PY3 = sys.version_info[0] >= 3

__doc__ = """
>>> it = iter([1,2,3])
>>> if not IS_PY3:
...     next = type(it).next
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3

>>> next(it)
Traceback (most recent call last):
StopIteration

>>> next(it)
Traceback (most recent call last):
StopIteration

>>> if IS_PY3: next(it, 123)
... else: print(123)
123
"""

if IS_PY3:
    __doc__ += """
>>> next(123)      # doctest: +ELLIPSIS
Traceback (most recent call last):
TypeError: ...int... object is not an iterator
"""

def test_next_not_iterable(it):
    """
    >>> test_next_not_iterable(123)
    Traceback (most recent call last):
    TypeError: int object is not an iterator
    """
    return next(it)

def test_single_next(it):
    """
    >>> it = iter([1,2,3])
    >>> test_single_next(it)
    1
    >>> test_single_next(it)
    2
    >>> test_single_next(it)
    3
    >>> test_single_next(it)
    Traceback (most recent call last):
    StopIteration
    >>> test_single_next(it)
    Traceback (most recent call last):
    StopIteration
    """
    return next(it)

def test_default_next(it, default):
    """
    >>> it = iter([1,2,3])
    >>> test_default_next(it, 99)
    1
    >>> test_default_next(it, 99)
    2
    >>> test_default_next(it, 99)
    3
    >>> test_default_next(it, 99)
    99
    >>> test_default_next(it, 99)
    99
    """
    return next(it, default)

def test_next_override(it):
    """
    >>> it = iter([1,2,3])
    >>> test_next_override(it)
    1
    >>> test_next_override(it)
    1
    >>> test_next_override(it)
    1
    >>> test_next_override(it)
    1
    """
    def next(it):
        return 1
    return next(it)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3887222
Cython-3.0.8/tests/run/builtin_ord.pyx0000644000175100001770000000351500000000000020622 0ustar00runnerdocker00000000000000
cimport cython

import sys

uspace = u' '
ustring_with_a = u'abcdefg'
ustring_without_a = u'bcdefg'


@cython.test_assert_path_exists(
    # ord() should receive and return a C value
    '//ReturnStatNode//CoerceToPyTypeNode//SimpleCallNode')
@cython.test_fail_if_path_exists(
    '//ReturnStatNode//SimpleCallNode//CoerceToPyTypeNode')
def ord_Py_UNICODE(unicode s):
    """
    >>> ord_Py_UNICODE(uspace)
    32
    """
    cdef Py_UNICODE u
    u = s[0]
    return ord(u)


@cython.test_assert_path_exists('//TupleNode//IntNode')
@cython.test_fail_if_path_exists('//SimpleCallNode')
def ord_const():
    """
    >>> ord(b' ')
    32
    >>> ord(' ')
    32
    >>> ord_const()
    (32, 32, 32, 255, 255, 4660, 0)
    """
    return ord(u' '), ord(b' '), ord(' '), ord('\xff'), ord(b'\xff'), ord(u'\u1234'), ord('\0')


@cython.test_assert_path_exists('//PrimaryCmpNode//IntNode')
#@cython.test_fail_if_path_exists('//SimpleCallNode')
def unicode_for_loop_ord(unicode s):
    """
    >>> unicode_for_loop_ord(ustring_with_a)
    True
    >>> unicode_for_loop_ord(ustring_without_a)
    False
    """
    for c in s:
        if ord(c) == ord(u'a'):
            return True
    return False


def compare_to_char(s):
    """
    >>> compare_to_char(uspace)
    False
    >>> compare_to_char(b'a')
    False
    >>> compare_to_char(b'x')
    True
    >>> compare_to_char('x')
    True
    """
    cdef char c = b'x'
    return ord(s) == c


def ord_object(s):
    """
    >>> try: ord_object('abc')
    ... except ValueError: assert sys.version_info[0] >= 3
    ... except TypeError: assert sys.version_info[0] < 3
    >>> ord_object('a')
    97
    >>> ord_object(b'a')
    97
    """
    return ord(s)


def non_builtin_ord(s):
    """
    >>> non_builtin_ord('x')
    (123, 123)
    """
    def _ord(s):
        return 123

    ord = _ord
    return ord(s), _ord(s)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/builtin_pow.pyx0000644000175100001770000000075500000000000020646 0ustar00runnerdocker00000000000000
def pow3(a,b,c):
    """
    >>> pow3(2,3,5)
    3
    >>> pow3(3,3,5)
    2
    """
    return pow(a,b,c)

def pow3_const():
    """
    >>> pow3_const()
    3
    """
    return pow(2,3,5)

def pow2(a,b):
    """
    >>> pow2(2,3)
    8
    >>> pow2(3,3)
    27
    """
    return pow(a,b)

def pow2_const():
    """
    >>> pow2_const()
    8
    """
    return pow(2,3)

def pow_args(*args):
    """
    >>> pow_args(2,3)
    8
    >>> pow_args(2,3,5)
    3
    """
    return pow(*args)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/builtin_py3.pyx0000644000175100001770000000133100000000000020543 0ustar00runnerdocker00000000000000# tag: py3

__doc__ = u"""
>>> test_xrange()
0
1
2
>>> test_range()
0
1
2

>>> test_long() == 12
True
>>> test_int() == 12
True
"""

# the builtins 'xrange' and 'long' are not available in Py3, but they
# can safely be replaced by 'range' and 'int' on that platform

import sys

IS_PY3 = sys.version_info[0] >= 3

def test_xrange():
    r = xrange(3)
    assert type(r) is xrange
    for i in r:
        print i

def test_range():
    r = range(3)
    assert (type(r) is range) if IS_PY3 else (type(r) is list)
    for i in r:
        print i

def test_long():
    long_val = long(12)
    assert type(long_val) is long
    return long_val

def test_int():
    int_val = int(12)
    assert type(int_val) is int
    return int_val
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/builtin_slice.pyx0000644000175100001770000000251200000000000021131 0ustar00runnerdocker00000000000000# mode: run

def slice1(stop):
    """
    >>> list(range(8))
    [0, 1, 2, 3, 4, 5, 6, 7]
    >>> list(range(10))[slice1(8)]
    [0, 1, 2, 3, 4, 5, 6, 7]
    >>> slice1(1)
    slice(None, 1, None)
    >>> slice1(10)
    slice(None, 10, None)
    >>> slice1(None)
    slice(None, None, None)
    >>> slice1(1) == slice(1)
    True
    >>> slice1(None) == slice(None)
    True
    """
    return slice(stop)


def slice1_const():
    """
    >>> slice1_const() == slice(12)
    True
    """
    return slice(12)


def slice2(start, stop):
    """
    >>> list(range(2, 8))
    [2, 3, 4, 5, 6, 7]
    >>> list(range(10))[slice2(2, 8)]
    [2, 3, 4, 5, 6, 7]
    >>> slice2(1, 10)
    slice(1, 10, None)
    >>> slice2(None, 10)
    slice(None, 10, None)
    >>> slice2(4, None)
    slice(4, None, None)
    """
    return slice(start, stop)


def slice2_const():
    """
    >>> slice2_const() == slice(None, 12)
    True
    """
    return slice(None, 12)


def slice3(start, stop, step):
    """
    >>> list(range(2, 8, 3))
    [2, 5]
    >>> list(range(10))[slice3(2, 8, 3)]
    [2, 5]
    >>> slice3(2, None, 3)
    slice(2, None, 3)
    >>> slice3(None, 3, 2)
    slice(None, 3, 2)
    """
    return slice(start, stop, step)


def slice3_const():
    """
    >>> slice3_const() == slice(12, None, 34)
    True
    """
    return slice(12, None, 34)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/builtin_sorted.pyx0000644000175100001770000000404700000000000021337 0ustar00runnerdocker00000000000000cimport cython


def generator():
    yield 2
    yield 1
    yield 3


def returns_set():
    return {"foo", "bar", "baz"}


def returns_tuple():
    return (1, 2, 3, 0)


@cython.test_fail_if_path_exists("//SimpleCallNode")
def sorted_arg(x):
    """
    >>> a = [3, 2, 1]
    >>> sorted_arg(a)
    [1, 2, 3]
    >>> a
    [3, 2, 1]
    >>> sorted(generator())
    [1, 2, 3]
    >>> sorted(returns_set())
    ['bar', 'baz', 'foo']
    >>> sorted(returns_tuple())
    [0, 1, 2, 3]
    >>> sorted(object())
    Traceback (most recent call last):
    TypeError: 'object' object is not iterable
    """
    return sorted(x)


@cython.test_assert_path_exists("//GeneralCallNode")
def sorted_arg_with_key(x):
    """
    >>> a = [3, 2, 1]
    >>> sorted_arg_with_key(a)
    [3, 2, 1]
    >>> a
    [3, 2, 1]
    >>> sorted_arg_with_key(generator())
    [3, 2, 1]
    >>> sorted_arg_with_key(returns_tuple())
    [3, 2, 1, 0]
    >>> sorted_arg_with_key(object())
    Traceback (most recent call last):
    TypeError: 'object' object is not iterable
    """
    return sorted(x, key=lambda x: -x)


@cython.test_fail_if_path_exists("//YieldExprNode",
                                 "//NoneCheckNode")
@cython.test_assert_path_exists("//InlinedGeneratorExpressionNode")
def sorted_genexp():
    """
    >>> sorted_genexp()
    [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
    """
    return sorted(i*i for i in range(10,0,-1))


@cython.test_fail_if_path_exists("//SimpleCallNode//SimpleCallNode")
@cython.test_assert_path_exists("//SimpleCallNode/NameNode[@name = 'range']")
def sorted_list_of_range():
    """
    >>> sorted_list_of_range()
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    """
    return sorted(list(range(10,0,-1)))


@cython.test_fail_if_path_exists("//SimpleCallNode")
def sorted_list_literal():
    """
    >>> sorted_list_literal()
    [1, 1, 2, 2, 3, 3]
    """
    return sorted([3, 1, 2] * 2)


@cython.test_fail_if_path_exists("//SimpleCallNode")
def sorted_tuple_literal():
    """
    >>> sorted_tuple_literal()
    [1, 1, 2, 2, 3, 3]
    """
    return sorted((1, 3, 2) * 2)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/builtin_subtype_methods_T653.pyx0000644000175100001770000001256100000000000023776 0ustar00runnerdocker00000000000000#cython: language_level=2
# mode: run
# ticket: t653

cimport cython

# The "contains" tests relate to GH-4785 - replacing the method
# call with PySequence_Contains was causing infinite recursion
# for some classes

cdef class MyList(list):
    """
    >>> l = MyList()
    >>> l.__contains__(1)
    MyList.__contains__
    False
    >>> l.append(1)
    >>> l.__contains__(1)
    MyList.__contains__
    True
    """
    def test_append(self, x):
        """
        >>> l = MyList()
        >>> type(l) is MyList
        True
        >>> list(l)
        []
        >>> l.test_append(5)
        >>> list(l)
        [5]
        """
        self.append(x)

    def __contains__(self, value):
        print "MyList.__contains__"
        return list.__contains__(self, value)  # probably optimized

cdef class MyDict(dict):
    # tests for __contains__ are in the global __doc__ to version-check a PyPy bug

    @cython.test_assert_path_exists("//ComprehensionNode//AttributeNode",
                                    "//ComprehensionNode//AttributeNode[@attribute='items']")
    @cython.test_fail_if_path_exists("//ComprehensionNode//CMethodSelfCloneNode")
    def test_items(self):
        """
        >>> MyDict(a=1, b=2).test_items()
        [('a', 1), ('b', 2)]
        """
        l = [ (key, value) for key, value in self.items() ]
        l.sort()
        return l

    def test_values(self):
        """
        >>> MyDict(a=1, b=2).test_values()
        [1, 2]
        """
        l = [ v for v in self.values() ]
        l.sort()
        return l

    def __contains__(self, key):
        print "MyDict.__contains__"
        return dict.__contains__(self, key)

import sys
pypy_version = getattr(sys, 'pypy_version_info', None)
if not (pypy_version and pypy_version < (7, 3, 10)):
    __doc__ = """
    >>> MyDict(a=1).__contains__("a")
    MyDict.__contains__
    True
    """

@cython.final
cdef class MyDictFinal(dict):
    @cython.test_assert_path_exists("//ComprehensionNode//CMethodSelfCloneNode")
    def test_items(self):
        """
        >>> MyDictFinal(a=1, b=2).test_items()
        [('a', 1), ('b', 2)]
        """
        l = [ (key, value) for key, value in self.items() ]
        l.sort()
        return l

    def test_values(self):
        """
        >>> MyDictFinal(a=1, b=2).test_values()
        [1, 2]
        """
        l = [ v for v in self.values() ]
        l.sort()
        return l

cdef class MyDict2(MyDict):
    @cython.test_assert_path_exists("//ComprehensionNode//AttributeNode",
                                    "//ComprehensionNode//AttributeNode[@attribute='items']")
    @cython.test_fail_if_path_exists("//ComprehensionNode//CMethodSelfCloneNode")
    def test_items(self):
        """
        >>> MyDict2(a=1, b=2).test_items()
        [('a', 1), ('b', 2)]
        """
        l = [ (key, value) for key, value in self.items() ]
        l.sort()
        return l

    def test_values(self):
        """
        >>> MyDict2(a=1, b=2).test_values()
        [1, 2]
        """
        l = [ v for v in self.values() ]
        l.sort()
        return l

@cython.final
cdef class MyDict2Final(MyDict):
    @cython.test_assert_path_exists("//ComprehensionNode//CMethodSelfCloneNode")
    def test_items(self):
        """
        >>> MyDict2Final(a=1, b=2).test_items()
        [('a', 1), ('b', 2)]
        """
        l = [ (key, value) for key, value in self.items() ]
        l.sort()
        return l

    def test_values(self):
        """
        >>> MyDict2Final(a=1, b=2).test_values()
        [1, 2]
        """
        l = [ v for v in self.values() ]
        l.sort()
        return l

@cython.final
cdef class MyDictOverride(dict):
    def items(self):
        return [(1,2), (3,4)]

    @cython.test_assert_path_exists("//ComprehensionNode//AttributeNode",
                                    "//ComprehensionNode//AttributeNode[@attribute='items']")
    @cython.test_fail_if_path_exists("//ComprehensionNode//CMethodSelfCloneNode")
    def test_items(self):
        """
        >>> MyDictOverride(a=1, b=2).test_items()
        [(1, 2), (3, 4)]
        """
        l = [ (key, value) for key, value in self.items() ]
        l.sort()
        return l

    def test_values(self):
        """
        >>> MyDictOverride(a=1, b=2).test_values()
        [1, 2]
        """
        l = [ v for v in self.values() ]
        l.sort()
        return l

@cython.final
cdef class MyDictOverride2(MyDict):
    def items(self):
        return [(1,2), (3,4)]

    @cython.test_assert_path_exists("//ComprehensionNode//AttributeNode",
                                    "//ComprehensionNode//AttributeNode[@attribute='items']")
    @cython.test_fail_if_path_exists("//ComprehensionNode//CMethodSelfCloneNode")
    def test_items(self):
        """
        >>> MyDictOverride2(a=1, b=2).test_items()
        [(1, 2), (3, 4)]
        """
        l = [ (key, value) for key, value in self.items() ]
        l.sort()
        return l

    def test_values(self):
        """
        >>> MyDictOverride2(a=1, b=2).test_values()
        [1, 2]
        """
        l = [ v for v in self.values() ]
        l.sort()
        return l

class MyBytes(bytes):
    """
    >>> mb = MyBytes(b"abc")
    >>> mb.__contains__(b"a")
    MyBytes.__contains__
    True
    >>> mb.__contains__(b"z")
    MyBytes.__contains__
    False
    """
    def __contains__(self, value):
        print "MyBytes.__contains__"
        return bytes.__contains__(self, value)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/builtin_subtype_methods_cy3.pyx0000644000175100001770000000214200000000000024025 0ustar00runnerdocker00000000000000# cython: language_level=3
# mode: run
# ticket: t653


class DictPySubtype(dict):
    def keys(self):
        """
        >>> d = DictPySubtype(one=42, two=17, three=0)
        >>> for v in sorted(d.keys()):
        ...     print(v)
        three
        two
        """
        for key in dict.keys(self):
            if key != 'one':
                yield key

    def values(self):
        """
        >>> d = DictPySubtype(one=42, two=17, three=0)
        >>> for v in sorted(d.values()):
        ...     print(v)
        17
        42
        """
        for value in dict.values(self):
            if value:
                yield value

    def items(self):
        """
        >>> d = DictPySubtype(one=42, two=17, three=0)
        >>> for v in sorted(d.items()):
        ...     print(v)
        one
        two
        """
        for key, value in dict.items(self):
            if value:
                yield key


class ListPySubtype(list):
    """
    >>> lst = ListPySubtype([1,2,3])
    >>> lst.append(4)
    >>> lst
    [1, 2, 3, 5]
    """
    def append(self, value):
        list.append(self, value+1)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/builtin_type.pyx0000644000175100001770000000243200000000000021014 0ustar00runnerdocker00000000000000cimport cython

@cython.test_assert_path_exists(
    '//PythonCapiCallNode/PythonCapiFunctionNode[@cname="Py_TYPE"]')
def get_type_of(a):
    """
    >>> get_type_of(object()) is object
    True
    """
    return type(a)

@cython.test_assert_path_exists(
    '//PythonCapiCallNode/PythonCapiFunctionNode[@cname="Py_TYPE"]')
def get_type_through_local(a):
    """
    >>> get_type_of(object()) is object
    True
    """
    t = type(a)
    return t

@cython.test_assert_path_exists(
    '//PythonCapiCallNode/PythonCapiFunctionNode[@cname="Py_TYPE"]')
@cython.test_fail_if_path_exists(
    '//PythonCapiCallNode/PythonCapiFunctionNode[@cname="__Pyx_Type"]',
    '//NameNode[@name="type"]')
def test_type(a, t):
    """
    >>> test_type(object(), object)
    True
    """
    return type(a) and type(a) is t and type(a) == t

@cython.test_assert_path_exists('//NameNode[@name="type"]')
def type_type():
    """
    >>> type_type()(object()) is object
    True
    """
    return type

cpdef type pass_type(type x):
    """
    >>> pass_type(int) == int
    True
    >>> class MyType(object): pass
    >>> pass_type(MyType) == MyType
    True
    >>> pass_type(object())
    Traceback (most recent call last):
    TypeError: Argument 'x' has incorrect type (expected type, got object)
    """
    return x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/builtin_type_inheritance_T608.pyx0000644000175100001770000000471400000000000024113 0ustar00runnerdocker00000000000000# ticket: t608

# see "builtin_type_inheritance_T608_py2only.pyx" for inheritance from int

cdef class MyFloat(float):
    """
    >>> MyFloat(1.0)== 1.0
    True
    >>> MyFloat(1.0).attr is None
    True
    """
    cdef readonly object attr

ustring = u'abc'

cdef class MyUnicode(unicode):
    """
    >>> MyUnicode(ustring) == ustring
    True
    >>> MyUnicode(ustring + ustring) == ustring
    False
    >>> MyUnicode(ustring).attr is None
    True
    """
    cdef readonly object attr

cdef class MyList(list):
    """
    >>> MyList([1,2,3]) == [1,2,3]
    True
    >>> MyList([1,2,3]).attr is None
    True
    """
    cdef readonly object attr

cdef class MyListOverride(list):
    """
    >>> MyListOverride([1,2,3]) == [1,2,3]
    True
    >>> l = MyListOverride([1,2,3])
    >>> l.reverse()
    >>> l
    [1, 2, 3, 5]
    >>> l._reverse()
    >>> l
    [1, 2, 3, 5, 5]
    """
    # not doctested:
    """
    >>> l = MyListOverride([1,2,3])
    >>> l.append(8)
    >>> l
    [1, 2, 3, 0, 8]
    >>> l._append(9)
    >>> l
    [1, 2, 3, 0, 8, 0, 9]
    """
    def reverse(self):
        self[:] = self + [5]

    def _reverse(self):
        self.reverse()

    ## FIXME: this doesn't currently work:

    ## cdef int append(self, value) except -1:
    ##     self[:] = self + [0] + [value]
    ##     return 0

    ## def _append(self, value):
    ##     self.append(value)

cdef class MyDict(dict):
    """
    >>> MyDict({1:2, 3:4}) == {1:2, 3:4}
    True
    >>> MyDict({1:2, 3:4}).attr is None
    True
    """
    cdef readonly object attr

cdef class MyException(Exception):
    """
    >>> raise MyException(3) # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    ...
    MyException: 3
    """
    cdef readonly int value
    def __cinit__(self, value):
        self.value = value

def test_exception_isinstance(maybe_exn):
    """
    >>> test_exception_isinstance(Exception())
    True
    >>> test_exception_isinstance(MyException(3))
    True
    >>> test_exception_isinstance(3)
    False
    """
    return isinstance(maybe_exn, Exception)

def test_exception_type_cast(Exception maybe_exn):
    """
    >>> test_exception_type_cast(Exception())
    >>> test_exception_type_cast(MyException(3))
    >>> test_exception_type_cast(3)   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: Argument 'maybe_exn' has incorrect type (expected ...Exception, got int)
    """
    cdef object o = maybe_exn
    cdef Exception e = o
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/builtin_type_inheritance_T608_py2only.pyx0000644000175100001770000000141400000000000025601 0ustar00runnerdocker00000000000000# ticket: t608

# This only works reliably in Python2. In Python3 ints are variable-sized.
# You get away with it for small ints but it's a bad idea

cdef class MyInt(int):
    """
    >>> MyInt(2) == 2
    True
    >>> MyInt(2).attr is None
    True
    """
    cdef readonly object attr

cdef class MyInt2(int):
    """
    >>> MyInt2(2) == 2
    True
    >>> MyInt2(2).attr is None
    True
    >>> MyInt2(2).test(3)
    5
    """
    cdef readonly object attr

    def test(self, arg):
        return self._test(arg)

    cdef _test(self, arg):
        return self + arg

cdef class MyInt3(MyInt2):
    """
    >>> MyInt3(2) == 2
    True
    >>> MyInt3(2).attr is None
    True
    >>> MyInt3(2).test(3)
    6
    """
    cdef _test(self, arg):
        return self + arg + 1
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/builtin_types_class.py0000644000175100001770000000204700000000000022176 0ustar00runnerdocker00000000000000# mode: run

from __future__ import print_function

import cython

# https://github.com/cython/cython/issues/3954
# calls to the __class__ attributes of builtin types were optimized to something invalid

@cython.locals(d=dict)
def test_dict(d):
    """
    >>> test_dict({})
    dict
    {}
    """
    print(d.__class__.__name__)
    print(d.__class__())

@cython.locals(i=int)
def test_int(i):
    """
    >>> test_int(0)
    int
    0
    """
    print(i.__class__.__name__)
    print(i.__class__())

@cython.cclass
class C:
    def __str__(self):
        return "I'm a C object"

@cython.locals(c=C)
def test_cdef_class(c):
    """
    # This wasn't actually broken but is worth testing anyway
    >>> test_cdef_class(C())
    C
    I'm a C object
    """
    print(c.__class__.__name__)
    print(c.__class__())

@cython.locals(d=object)
def test_object(o):
    """
    >>> test_object({})
    dict
    {}
    >>> test_object(1)
    int
    0
    >>> test_object(C())
    C
    I'm a C object
    """
    print(o.__class__.__name__)
    print(o.__class__())
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/builtin_types_none_T166.pyx0000644000175100001770000000055600000000000022743 0ustar00runnerdocker00000000000000# ticket: t166

__doc__ = u"""
>>> l = None
>>> l.append(2)
Traceback (most recent call last):
AttributeError: 'NoneType' object has no attribute 'append'

"""

def append_to_none():
    """
    >>> append_to_none()
    Traceback (most recent call last):
    AttributeError: 'NoneType' object has no attribute 'append'
    """
    cdef list l = None
    l.append(2)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/builtincomplex.pyx0000644000175100001770000000236400000000000021347 0ustar00runnerdocker00000000000000
from cpython.complex cimport complex

def complex_attributes():
    """
    >>> complex_attributes()
    (1.0, 2.0)
    """
    cdef complex c = 1+2j
    return (c.real, c.imag)

def complex_attributes_assign():
    """
    >>> complex_attributes_assign()
    (10.0, 20.0)
    """
    cdef complex c = 1+2j
    c.cval.real, c.cval.imag = 10, 20
    return (c.real, c.imag)

def complex_cstruct_assign():
    """
    >>> complex_cstruct_assign()
    (10.0, 20.0)
    """
    cdef complex c = 1+2j
    cval = &c.cval
    cval.real, cval.imag = 10, 20
    return (c.real, c.imag)

def complex_coercion():
    """
    >>> complex_coercion()
    (1.0, 2.0, 1.0, 2.0)
    """
    cdef complex py_c = 1+2j
    cdef double complex c_c = py_c
    cdef object py = c_c
    return (c_c.real, c_c.imag, py.real, py.imag)

def complex_arg(complex c):
    """
    >>> complex_arg(1+2j)
    (1.0, 2.0)
    """
    return (c.real, c.imag)

def complex_conjugate_nonsimple_float():
    """
    >>> complex_conjugate_nonsimple_float()
    1.0
    """
    x = float(1.0).conjugate()
    return x

cdef double float_result():
    return 1.0

def complex_conjugate_nonsimple():
    """
    >>> complex_conjugate_nonsimple()
    1.0
    """
    x = float_result().conjugate()
    return x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/builtinnames.pyx0000644000175100001770000000265100000000000021002 0ustar00runnerdocker00000000000000cimport cython

def test_file_py(file):
    assert isinstance(file, (str, unicode)), \
        u"not a string, found '%s' instead" % file.__class__.__name__
    return file

cdef test_file_c(file):
    assert isinstance(file, (str, unicode)), \
        u"not a string, found '%s' instead" % file.__class__.__name__
    return u'file' + file


def range(arg):
    return u'range' + arg

def len(arg):
    return u'len' + arg

cdef type(arg):
    return u'type' + arg


@cython.test_fail_if_path_exists(
    '//PyMethodCallNode/NameNode[@name="type" and @entry.is_cfunction=False]',
    '//SimpleCallNode/NameNode[@name="type" and @entry.is_cfunction=False]',
    '//SimpleCallNode/NameNode[@name="len" and @entry.is_cfunction=True]',
    )
@cython.test_assert_path_exists(
    '//SimpleCallNode/NameNode[@name="type"]',
    '//SimpleCallNode/NameNode[@name="type" and @entry.is_cfunction=True]',
    '//PyMethodCallNode/NameNode[@name="len"]',
    )
def test_c(arg):
    """
    >>> test_c('abc')
    fileabc
    lenabc
    typeabc
    >>> print(test_file_py('abc'))
    abc
    >>> print(range('abc'))
    rangeabc
    >>> print(len('abc'))
    lenabc
    """
    print test_file_c(arg)
    print len(arg)
    print type(arg)

def test_for_in_range(arg):
    """
    >>> print(str(test_for_in_range('abc')).replace("u'", "'"))
    ['r', 'a', 'n', 'g', 'e', 'a', 'b', 'c']
    """
    l = []
    for c in range(arg):
        l.append(c)
    return l
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/builtins_truth_test.pyx0000644000175100001770000001061600000000000022426 0ustar00runnerdocker00000000000000
def bool_list(list obj):
    """
    >>> bool_list( [] )
    False
    >>> bool_list( [1] )
    True
    >>> bool_list(None)
    False
    """
    return bool(obj)


def if_list(list obj):
    """
    >>> if_list( [] )
    False
    >>> if_list( [1] )
    True
    >>> if_list(None)
    False
    """
    if obj:
        return True
    else:
        return False


def if_list_nogil(list obj):
    """
    >>> if_list_nogil( [] )
    False
    >>> if_list_nogil( [1] )
    True
    >>> if_list_nogil(None)
    False
    """
    cdef bint result
    with nogil:
        if obj:
            result = True
        else:
            result = False
    return result


def if_list_literal(t):
    """
    >>> if_list_literal(True)
    True
    >>> if_list_literal(False)
    False
    """
    if t:
        if [1,2,3]:
            return True
        else:
            return False
    else:
        if []:
            return True
        else:
            return False


def bool_tuple(tuple obj):
    """
    >>> bool_tuple( () )
    False
    >>> bool_tuple( (1,) )
    True
    >>> bool_tuple(None)
    False
    """
    return bool(obj)


def if_tuple(tuple obj):
    """
    >>> if_tuple( () )
    False
    >>> if_tuple( (1,) )
    True
    >>> if_tuple(None)
    False
    """
    if obj:
        return True
    else:
        return False


def if_tuple_literal(t):
    """
    >>> if_tuple_literal(True)
    True
    >>> if_tuple_literal(False)
    False
    """
    if t:
        if (1,2,3):
            return True
        else:
            return False
    else:
        if ():
            return True
        else:
            return False


def bool_set(set obj):
    """
    >>> bool_set( set() )
    False
    >>> bool_set( set([1]) )
    True
    >>> bool_set(None)
    False
    """
    return bool(obj)


def if_set(set obj):
    """
    >>> if_set( set() )
    False
    >>> if_set( set([1]) )
    True
    >>> if_set(None)
    False
    """
    if obj:
        return True
    else:
        return False


def if_set_nogil(set obj):
    """
    >>> if_set_nogil( set() )
    False
    >>> if_set_nogil( set([1]) )
    True
    >>> if_set_nogil(None)
    False
    """
    cdef bint result
    with nogil:
        if obj:
            result = True
        else:
            result = False
    return result


def if_set_literal(t):
    """
    >>> if_set_literal(True)
    True
    >>> if_set_literal(False)
    False
    """
    if t:
        if {1,2,3}:
            return True
        else:
            return False
    else:
        if set():
            return True
        else:
            return False


def bool_frozenset(frozenset obj):
    """
    >>> bool_frozenset( frozenset() )
    False
    >>> bool_frozenset( frozenset([1]) )
    True
    >>> bool_frozenset(None)
    False
    """
    return bool(obj)


def if_frozenset(frozenset obj):
    """
    >>> if_frozenset( frozenset() )
    False
    >>> if_frozenset( frozenset([1]) )
    True
    >>> if_frozenset(None)
    False
    """
    if obj:
        return True
    else:
        return False


b0 = b''
b1 = b'abc'

def bool_bytes(bytes obj):
    """
    >>> bool_bytes(b0)
    False
    >>> bool_bytes(b1)
    True
    >>> bool_bytes(None)
    False
    """
    return bool(obj)

def if_bytes(bytes obj):
    """
    >>> if_bytes(b0)
    False
    >>> if_bytes(b1)
    True
    >>> if_bytes(None)
    False
    """
    if obj:
        return True
    else:
        return False

def if_bytes_literal(t):
    """
    >>> if_bytes_literal(True)
    True
    >>> if_bytes_literal(False)
    False
    """
    if t:
        if b'abc':
            return True
        else:
            return False
    else:
        if b'':
            return True
        else:
            return False


u0 = u''
u1 = u'abc'

def bool_unicode(unicode obj):
    """
    >>> bool_unicode(u0)
    False
    >>> bool_unicode(u1)
    True
    >>> bool_unicode(None)
    False
    """
    return bool(obj)

def if_unicode(unicode obj):
    """
    >>> if_unicode(u0)
    False
    >>> if_unicode(u1)
    True
    >>> if_unicode(None)
    False
    """
    if obj:
        return True
    else:
        return False

def if_unicode_literal(t):
    """
    >>> if_unicode_literal(True)
    True
    >>> if_unicode_literal(False)
    False
    """
    if t:
        if u'abc':
            return True
        else:
            return False
    else:
        if u'':
            return True
        else:
            return False
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/builtinslice.pyx0000644000175100001770000000161400000000000020774 0ustar00runnerdocker00000000000000cimport cython

def unbound_method_lookup():
    """
    >>> unbound_method_lookup()
    """
    ignore = slice.indices

@cython.test_assert_path_exists('//SingleAssignmentNode//AttributeNode[@is_py_attr = False]')
@cython.test_fail_if_path_exists('//SingleAssignmentNode//AttributeNode[@is_py_attr = True]')
def typed_slice():
    """
    >>> typed_slice()
    (1, 2, 3)
    """
    cdef slice s
    cdef object z
    cdef Py_ssize_t a,b,c

    z = slice
    s = slice(1, 2, 3)
    s.indices

    a = s.start
    b = s.stop
    c = s.step

    return (a,b,c)

@cython.test_fail_if_path_exists('//SingleAssignmentNode//AttributeNode[@is_py_attr = False]')
def plain_object_slice():
    """
    >>> plain_object_slice()
    (1, 2, 3)
    """
    cdef object s
    cdef object z
    cdef Py_ssize_t a,b,c

    s = slice(1, 2, 3)
    s.indices

    a = s.start
    b = s.stop
    c = s.step

    return (a,b,c)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/bytearray_ascii_auto_encoding.pyx0000644000175100001770000000044300000000000024355 0ustar00runnerdocker00000000000000#cython: c_string_type = bytearray
#cython: c_string_encoding = ascii

"End of first directives"

include "unicode_ascii_auto_encoding.pyx"

auto_string_type = bytearray

def check_auto_string_type():
    """
    >>> check_auto_string_type()
    """
    assert auto_string_type is bytearray
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/bytearray_coercion.pyx0000644000175100001770000001054200000000000022171 0ustar00runnerdocker00000000000000# mode: run

# NOTE: Py2.6+ only


cimport cython

cpdef bytearray coerce_to_charptr(char* b):
    """
    >>> b = bytearray(b'abc')
    >>> coerced = coerce_to_charptr(b)
    >>> coerced == b or (coerced, b)
    True
    >>> isinstance(coerced, bytearray) or type(coerced)
    True
    """
    return b

def coerce_to_charptrs(bytearray b):
    """
    >>> b = bytearray(b'abc')
    >>> coerce_to_charptrs(b)
    True
    """
    cdef char* cs = b
    cdef unsigned char* ucs = b
    cdef signed char* scs = b
    return b == cs ==  ucs == scs

cpdef bytearray coerce_charptr_slice(char* b):
    """
    >>> b = bytearray(b'abc')
    >>> coerced = coerce_charptr_slice(b)
    >>> coerced == b[:2] or (coerced, b)
    True
    >>> isinstance(coerced, bytearray) or type(coerced)
    True
    """
    return b[:2]


def infer_concatenation_types(bytearray b):
    """
    >>> b = bytearray(b'a\\xFEc')
    >>> b2, c, d, e, tb, tc, td, te = infer_concatenation_types(b)
    >>> tb, tc, td, te
    ('bytearray object', 'bytearray object', 'bytearray object', 'bytearray object')
    >>> b2, c, d, e
    (bytearray(b'a\\xfec'), bytearray(b'a\\xfeca\\xfec'), bytearray(b'a\\xfeca\\xfec'), bytearray(b'a\\xfeca\\xfec'))
    """
    c = b[:]
    c += b[:]

    d = b[:]
    d *= 2

    e = b + b

    return b, c, d, e, cython.typeof(b), cython.typeof(c), cython.typeof(d), cython.typeof(e)


def infer_index_types(bytearray b):
    """
    >>> b = bytearray(b'a\\xFEc')
    >>> print(infer_index_types(b))
    (254, 254, 254, 'unsigned char', 'unsigned char', 'unsigned char', 'int')
    """
    c = b[1]
    with cython.wraparound(False):
        d = b[1]
    with cython.boundscheck(False):
        e = b[1]
    return c, d, e, cython.typeof(c), cython.typeof(d), cython.typeof(e), cython.typeof(b[1])


def infer_slice_types(bytearray b):
    """
    >>> b = bytearray(b'abc')
    >>> print(infer_slice_types(b))
    (bytearray(b'bc'), bytearray(b'bc'), bytearray(b'bc'), 'bytearray object', 'bytearray object', 'bytearray object', 'bytearray object')
    """
    c = b[1:]
    with cython.boundscheck(False):
        d = b[1:]
    with cython.boundscheck(False), cython.wraparound(False):
        e = b[1:]
    return c, d, e, cython.typeof(c), cython.typeof(d), cython.typeof(e), cython.typeof(b[1:])


def assign_to_index(bytearray b, value):
    """
    >>> b = bytearray(b'0abcdefg')
    >>> assign_to_index(b, 1)
    bytearray(b'xyzee\\x01h')
    >>> b
    bytearray(b'xyzee\\x01h')

    >>> assign_to_index(bytearray(b'0ABCDEFG'), 40)
    bytearray(b'xyzEE(o')

    >>> assign_to_index(bytearray(b'0abcdefg'), -1)
    Traceback (most recent call last):
    OverflowError: can't convert negative value to unsigned char

    >>> assign_to_index(bytearray(b'0abcdef\\x00'), 255)
    bytearray(b'xyzee\\xff\\xff')
    >>> assign_to_index(bytearray(b'0abcdef\\x01'), 255)
    Traceback (most recent call last):
    OverflowError: value too large to convert to unsigned char
    >>> assign_to_index(bytearray(b'0abcdef\\x00'), 256)
    Traceback (most recent call last):
    OverflowError: value too large to convert to unsigned char
    """
    b[1] = 'x'
    b[2] = b'y'
    b[3] = c'z'
    b[4] += 1
    b[5] |= 1
    b[6] = value
    b[7] += value
    del b[0]

    try:
        b[7] = 1
    except IndexError:
        pass
    else:
        assert False, "IndexError not raised"

    try:
        b[int(str(len(b)))] = 1   # test non-int-index assignment
    except IndexError:
        pass
    else:
        assert False, "IndexError not raised"

    return b


def check_bounds(int cvalue):
    """
    >>> check_bounds(0)
    0
    >>> check_bounds(255)
    255
    >>> check_bounds(256)
    Traceback (most recent call last):
    ValueError: byte must be in range(0, 256)
    >>> check_bounds(-1)
    Traceback (most recent call last):
    ValueError: byte must be in range(0, 256)
    """
    b = bytearray(b'x')

    try:
        b[0] = 256
    except ValueError:
        pass
    else:
        assert False, "ValueError not raised"

    try:
        b[0] = -1
    except ValueError:
        pass
    else:
        assert False, "ValueError not raised"

    b[0] = cvalue
    return b[0]


def nogil_assignment(bytearray x, int value):
    """
    >>> b = bytearray(b'abc')
    >>> nogil_assignment(b, ord('y'))
    >>> b
    bytearray(b'xyc')
    """
    with nogil:
        x[0] = 'x'
        x[1] = value
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/bytearray_default_auto_encoding.pyx0000644000175100001770000000077500000000000024721 0ustar00runnerdocker00000000000000# cython: c_string_type = bytearray
# cython: c_string_encoding = default

import sys
if sys.version_info[0] >= 3:
    __doc__ = r"""
        >>> isinstance(as_objects("ab\xff"), bytearray)
        True
        >>> as_objects("ab\xff") == bytearray("ab\xff".encode())
        True
        >>> isinstance(slice_as_objects("ab\xff", 1, 4), bytearray)
        True
        >>> slice_as_objects("ab\xffd", 1, 4) == bytearray("b\xff".encode())
        True
        """

include "bytearray_ascii_auto_encoding.pyx"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/bytearray_iter.py0000644000175100001770000000423200000000000021142 0ustar00runnerdocker00000000000000# mode: run
# tag: pure3, pure2

import cython

@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
@cython.locals(x=bytearray)
def basic_bytearray_iter(x):
    """
    >>> basic_bytearray_iter(bytearray(b"hello"))
    h
    e
    l
    l
    o
    """
    for a in x:
        print(chr(a))

@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
@cython.locals(x=bytearray)
def reversed_bytearray_iter(x):
    """
    >>> reversed_bytearray_iter(bytearray(b"hello"))
    o
    l
    l
    e
    h
    """
    for a in reversed(x):
        print(chr(a))

@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
@cython.locals(x=bytearray)
def modifying_bytearray_iter1(x):
    """
    >>> modifying_bytearray_iter1(bytearray(b"abcdef"))
    a
    b
    c
    3
    """
    count = 0
    for a in x:
        print(chr(a))
        del x[-1]
        count += 1
    print(count)

@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
@cython.locals(x=bytearray)
def modifying_bytearray_iter2(x):
    """
    >>> modifying_bytearray_iter2(bytearray(b"abcdef"))
    a
    c
    e
    3
    """
    count = 0
    for a in x:
        print(chr(a))
        del x[0]
        count += 1
    print(count)

@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
@cython.locals(x=bytearray)
def modifying_reversed_bytearray_iter(x):
    """
    NOTE - I'm not 100% sure how well-defined this behaviour is in Python.
    However, for the moment Python and Cython seem to do the same thing.
    Testing that it doesn't crash is probably more important than the exact output!
    >>> modifying_reversed_bytearray_iter(bytearray(b"abcdef"))
    f
    f
    f
    f
    f
    f
    """
    for a in reversed(x):
        print(chr(a))
        del x[0]

# ticket: 3473

def test_bytearray_iteration(src):
    """
    >>> src = b'123'
    >>> test_bytearray_iteration(src)
    49
    50
    51
    """

    data = bytearray(src)
    for elem in data:
        print(elem)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/bytearraymethods.pyx0000644000175100001770000002047600000000000021703 0ustar00runnerdocker00000000000000
import sys
IS_PY3 = sys.version_info[0] >= 3

cimport cython

b_a = bytearray(b'a')
b_b = bytearray(b'b')


'''   # disabled for now, enable when we consider it worth the code overhead

@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
@cython.test_fail_if_path_exists(
    "//SimpleCallNode")
def bytearray_startswith(bytearray s, sub, start=None, stop=None):
    """
    >>> bytearray_startswith(b_a, b_a)
    True
    >>> bytearray_startswith(b_a+b_b, b_a)
    True
    >>> bytearray_startswith(b_a, b_b)
    False
    >>> bytearray_startswith(b_a+b_b, b_b)
    False
    >>> bytearray_startswith(b_a, (b_a, b_b))
    True
    >>> bytearray_startswith(b_a, b_a, 1)
    False
    >>> bytearray_startswith(b_a, b_a, 0, 0)
    False
    """

    if start is None:
      return s.startswith(sub)
    elif stop is None:
      return s.startswith(sub, start)
    else:
      return s.startswith(sub, start, stop)


@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
@cython.test_fail_if_path_exists(
    "//SimpleCallNode")
def bytearray_endswith(bytearray s, sub, start=None, stop=None):
    """
    >>> bytearray_endswith(b_a, b_a)
    True
    >>> bytearray_endswith(b_b+b_a, b_a)
    True
    >>> bytearray_endswith(b_a, b_b)
    False
    >>> bytearray_endswith(b_b+b_a, b_b)
    False
    >>> bytearray_endswith(b_a, (b_a, b_b))
    True
    >>> bytearray_endswith(b_a, b_a, 1)
    False
    >>> bytearray_endswith(b_a, b_a, 0, 0)
    False
    """

    if start is None:
      return s.endswith(sub)
    elif stop is None:
      return s.endswith(sub, start)
    else:
      return s.endswith(sub, start, stop)
'''


@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
@cython.test_fail_if_path_exists(
    "//SimpleCallNode")
def bytearray_decode(bytearray s, start=None, stop=None):
    """
    >>> s = b_a+b_b+b_a+b_a+b_b
    >>> print(bytearray_decode(s))
    abaab

    >>> print(bytearray_decode(s, 2))
    aab
    >>> print(bytearray_decode(s, -3))
    aab

    >>> print(bytearray_decode(s, None, 4))
    abaa
    >>> print(bytearray_decode(s, None, 400))
    abaab
    >>> print(bytearray_decode(s, None, -2))
    aba
    >>> print(bytearray_decode(s, None, -4))
    a
    >>> print(bytearray_decode(s, None, -5))
    
    >>> print(bytearray_decode(s, None, -200))
    

    >>> print(bytearray_decode(s, 2, 5))
    aab
    >>> print(bytearray_decode(s, 2, 500))
    aab
    >>> print(bytearray_decode(s, 2, -1))
    aa
    >>> print(bytearray_decode(s, 2, -3))
    
    >>> print(bytearray_decode(s, 2, -300))
    
    >>> print(bytearray_decode(s, -3, -1))
    aa
    >>> print(bytearray_decode(s, -300, 300))
    abaab
    >>> print(bytearray_decode(s, -300, -4))
    a
    >>> print(bytearray_decode(s, -300, -5))
    
    >>> print(bytearray_decode(s, -300, -6))
    
    >>> print(bytearray_decode(s, -300, -500))
    

    >>> s[:'test']                       # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError:...
    >>> print(bytearray_decode(s, 'test'))   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError:...
    >>> print(bytearray_decode(s, None, 'test'))    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError:...
    >>> print(bytearray_decode(s, 'test', 'test'))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError:...

    >>> print(bytearray_decode(None))
    Traceback (most recent call last):
    AttributeError: 'NoneType' object has no attribute 'decode'
    >>> print(bytearray_decode(None, 1))
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not subscriptable
    >>> print(bytearray_decode(None, None, 1))
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not subscriptable
    >>> print(bytearray_decode(None, 0, 1))
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not subscriptable
    """
    if start is None:
        if stop is None:
            return s.decode('utf8')
        else:
            return s[:stop].decode('utf8')
    elif stop is None:
        return s[start:].decode('utf8')
    else:
        return s[start:stop].decode('utf8')


@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
@cython.test_fail_if_path_exists(
    "//SimpleCallNode")
def bytearray_decode_unbound_method(bytearray s, start=None, stop=None):
    """
    >>> s = b_a+b_b+b_a+b_a+b_b
    >>> print(bytearray_decode_unbound_method(s))
    abaab
    >>> print(bytearray_decode_unbound_method(s, 1))
    baab
    >>> print(bytearray_decode_unbound_method(s, None, 3))
    aba
    >>> print(bytearray_decode_unbound_method(s, 1, 4))
    baa

    >>> print(bytearray_decode_unbound_method(None))
    Traceback (most recent call last):
    TypeError: descriptor 'decode' requires a 'bytearray' object but received a 'NoneType'
    >>> print(bytearray_decode_unbound_method(None, 1))
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not subscriptable
    >>> print(bytearray_decode_unbound_method(None, None, 1))
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not subscriptable
    >>> print(bytearray_decode_unbound_method(None, 0, 1))
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not subscriptable
    """
    if start is None:
        if stop is None:
            return bytearray.decode(s, 'utf8')
        else:
            return bytearray.decode(s[:stop], 'utf8')
    elif stop is None:
        return bytearray.decode(s[start:], 'utf8')
    else:
        return bytearray.decode(s[start:stop], 'utf8')

@cython.test_fail_if_path_exists('//SimpleCallNode')
@cython.test_assert_path_exists('//PythonCapiCallNode')
def bytearray_append(bytearray b, signed char c, int i, object o):
    """
    >>> b = bytearray(b'abc')
    >>> b = bytearray_append(b, ord('x'), ord('y'), ord('z'))
    >>> print(b.decode('ascii'))
    abcX@xyz

    >>> b = bytearray(b'abc')
    >>> b = bytearray_append(b, ord('x'), ord('y'), 0)
    >>> print(b.decode('ascii')[:-1])
    abcX@xy
    >>> b[-1]
    0

    >>> b = bytearray(b'abc')
    >>> b = bytearray_append(b, ord('x'), ord('y'), ord('z') if IS_PY3 else b'z')
    >>> print(b.decode('ascii'))
    abcX@xyz

    >>> b = bytearray(b'abc')
    >>> b = bytearray_append(b, ord('x'), ord('y'), ord('\\xc3') if IS_PY3 else b'\\xc3')
    >>> print(b[:-1].decode('ascii'))
    abcX@xy
    >>> print('%x' % b[-1])
    c3

    >>> b = bytearray(b'abc')
    >>> try:
    ...     b = bytearray_append(b, ord('x'), ord('y'), b'zz')
    ... except (TypeError, ValueError): pass  # (Py3, Py2)
    ... else: print("FAIL")
    >>> print(b.decode('ascii'))
    abcX@xy

    >>> b = bytearray(b'abc')
    >>> b = bytearray_append(b, -1, ord('y'), ord('z'))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...
    >>> print(b.decode('ascii'))
    abcX@

    >>> b = bytearray(b'abc')
    >>> b = bytearray_append(b, ord('x'), -1, ord('z'))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...
    >>> print(b.decode('ascii'))
    abcX@x

    >>> b = bytearray(b'abc')
    >>> b = bytearray_append(b, ord('x'), 256, ord('z'))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...
    >>> print(b.decode('ascii'))
    abcX@x

    >>> b = bytearray(b'abc')
    >>> b = bytearray_append(b, ord('x'), ord('y'), -1)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...
    >>> print(b.decode('ascii'))
    abcX@xy

    >>> b = bytearray(b'abc')
    >>> b = bytearray_append(b, ord('x'), ord('y'), 256)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...
    >>> print(b.decode('ascii'))
    abcX@xy
    """
    assert b.append('X') is None
    b.append(64)
    b.append(c)
    b.append(i)
    b.append(o)
    return b


cdef class BytearraySubtype(bytearray):
    """
    >>> b = BytearraySubtype(b'abc')
    >>> b._append(ord('x'))
    >>> b.append(ord('y'))
    >>> print(b.decode('ascii'))
    abcxy
    """
    def _append(self, x):
        self.append(x)

def fromhex(bytearray b):
    """
    https://github.com/cython/cython/issues/5051
    Optimization of bound method calls was breaking classmethods
    >>> fromhex(bytearray(b""))
    """
    if IS_PY3:
        assert b.fromhex('2Ef0 F1f2  ') == b'.\xf0\xf1\xf2'
    # method doesn't exist on Py2!
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/bytes_char_coercion.pyx0000644000175100001770000001120200000000000022304 0ustar00runnerdocker00000000000000
cimport cython

def coerce_char_default(char c):
    """
    Default char -> int coercion

    >>> coerce_char_default(ord('A')) == ord('A')
    True
    """
    return c


def coerce_uchar_default(unsigned char c):
    """
    Default char -> int coercion

    >>> coerce_uchar_default(ord('A')) == ord('A')
    True
    """
    return c


@cython.test_assert_path_exists("//CoerceIntToBytesNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def coerce_char_bytes_cast(char c):
    """
    Explicit char -> bytes coercion

    >>> coerce_char_bytes_cast(ord('A')) == 'A'.encode('ASCII')
    True
    """
    return c


@cython.test_assert_path_exists("//CoerceIntToBytesNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def coerce_uchar_bytes_cast(unsigned char c):
    """
    Explicit uchar -> bytes coercion

    >>> coerce_uchar_bytes_cast(ord('A')) == 'A'.encode('ASCII')
    True
    >>> b = coerce_uchar_bytes_cast(ord('\\xff'))
    >>> b == '\\xff' or b == '\\xff'.encode('ISO-8859-1') # Py2 or Py3
    True
    """
    return c


@cython.test_assert_path_exists("//CoerceIntToBytesNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def coerce_int_bytes_cast(int c):
    """
    Explicit int -> bytes coercion

    >>> coerce_int_bytes_cast(ord('A')) == 'A'.encode('ASCII')
    True
    >>> coerce_int_bytes_cast(ord('A') + 0x100)
    Traceback (most recent call last):
    OverflowError: value too large to pack into a byte
    >>> coerce_int_bytes_cast(ord('A') - 0x100)
    Traceback (most recent call last):
    OverflowError: value too large to pack into a byte
    """
    return c


@cython.test_assert_path_exists("//CoerceIntToBytesNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def coerce_uint_bytes_cast(unsigned int c):
    """
    Explicit uint -> bytes coercion

    >>> coerce_uint_bytes_cast(ord('A')) == 'A'.encode('ASCII')
    True
    >>> b = coerce_uint_bytes_cast(ord('\\xff'))
    >>> b == '\\xff' or b == '\\xff'.encode('ISO-8859-1') # Py2 or Py3
    True

    >>> coerce_uint_bytes_cast(ord('A') + 0x100)
    Traceback (most recent call last):
    OverflowError: value too large to pack into a byte
    """
    return c


@cython.test_assert_path_exists("//CoerceIntToBytesNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def coerce_char_bytes_assign(char c):
    """
    Implicit char -> bytes coercion in assignments

    >>> coerce_char_bytes_assign(ord('A')) == 'A'.encode('ASCII')
    True
    """
    cdef bytes s = c
    return s


@cython.test_assert_path_exists("//CoerceIntToBytesNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def coerce_uchar_bytes_assign(unsigned char c):
    """
    Implicit uchar -> bytes coercion in assignments

    >>> coerce_uchar_bytes_assign(ord('A')) == 'A'.encode('ASCII')
    True
    >>> b = coerce_uchar_bytes_assign(ord('\\xff'))
    >>> b == '\\xff' or b == '\\xff'.encode('ISO-8859-1') # Py2 or Py3
    True
    """
    cdef bytes s = c
    return s


@cython.test_assert_path_exists("//CoerceIntToBytesNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def coerce_int_bytes_assign(int c):
    """
    Implicit int -> bytes coercion in assignments

    >>> coerce_int_bytes_assign(ord('A')) == 'A'.encode('ASCII')
    True

    >>> coerce_int_bytes_assign(ord('A') + 0x100)
    Traceback (most recent call last):
    OverflowError: value too large to pack into a byte
    >>> coerce_int_bytes_assign(ord('A') - 0x100)
    Traceback (most recent call last):
    OverflowError: value too large to pack into a byte
    """
    cdef bytes s = c
    return s


@cython.test_assert_path_exists("//CoerceIntToBytesNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def coerce_uint_bytes_assign(unsigned int c):
    """
    Implicit uint -> bytes coercion in assignments

    >>> coerce_uint_bytes_assign(ord('A')) == 'A'.encode('ASCII')
    True
    >>> b = coerce_uint_bytes_assign(ord('\\xff'))
    >>> b == '\\xff' or b == '\\xff'.encode('ISO-8859-1') # Py2 or Py3
    True

    >>> coerce_uint_bytes_assign(ord('A') + 0x100)
    Traceback (most recent call last):
    OverflowError: value too large to pack into a byte
    """
    cdef bytes s = c
    return s


def inplace_ops_use_arithmetic():
    """
    >>> print(inplace_ops_use_arithmetic().decode('ascii'))
    bc
    """
    cdef char* s = 'abc'
    cdef object x = 1
    s += 1
    s += 2*x
    s -= 1
    s -= x
    return s


@cython.test_fail_if_path_exists('//CoerceFromPyTypeNode')
def indexing_to_char(bytes s):
    """
    >>> ord('b')
    98
    >>> indexing_to_char('abc'.encode('ascii'))
    98
    """
    cdef unsigned char c = s[1]
    return c
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/bytes_formatting.pyx0000644000175100001770000000123400000000000021664 0ustar00runnerdocker00000000000000# mode: run
# tag: stringformat, bytesformat


import sys
IS_PY2 = sys.version_info[0] < 3


if IS_PY2:
    __doc__ = """
>>> print(format_bytes_with_str(u'abc'))
1 12170405abc6A
"""


def format_bytes():
    """
    >>> print(format_bytes())
    1 121704056A
    """
    cdef bytes result = b'%d%3i%x%02X%02.0f%g%c' % (
        1, 12, 23, 4, 5, 6, 65)
    assert type(result) is bytes
    return result.decode('ascii')


def format_bytes_with_str(s):
    """
    >>> print(format_bytes_with_str(b'abc'))
    1 12170405abc6A
    """
    result = b'%d%3i%x%02X%02.0f%s%g%c' % (
        1, 12, 23, 4, 5, s, 6, 65)
    return result if IS_PY2 else result.decode('ascii')
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/bytes_indexing.pyx0000644000175100001770000001221600000000000021321 0ustar00runnerdocker00000000000000
cimport cython

cdef bytes b12345 = b'12345'

def index_literal(int i):
    """
    Python 3 returns integer values on indexing, Py2 returns byte
    string literals...

    >>> index_literal(0) in (ord('1'), '1')
    True
    >>> index_literal(-5) in (ord('1'), '1')
    True
    >>> index_literal(2) in (ord('3'), '3')
    True
    >>> index_literal(4) in (ord('5'), '5')
    True
    """
    return b"12345"[i]


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
                                 "//CoerceFromPyTypeNode")
def index_literal_char_cast(int i):
    """
    >>> index_literal_char_cast(0) == ord('1')
    True
    >>> index_literal_char_cast(-5) == ord('1')
    True
    >>> index_literal_char_cast(2) == ord('3')
    True
    >>> index_literal_char_cast(4) == ord('5')
    True
    >>> index_literal_char_cast(6)
    Traceback (most recent call last):
    IndexError: string index out of range
    """
    return (b"12345"[i])


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
                                 "//CoerceFromPyTypeNode")
def index_nonliteral_char_cast(int i):
    """
    >>> index_nonliteral_char_cast(0) == ord('1')
    True
    >>> index_nonliteral_char_cast(-5) == ord('1')
    True
    >>> index_nonliteral_char_cast(2) == ord('3')
    True
    >>> index_nonliteral_char_cast(4) == ord('5')
    True
    >>> index_nonliteral_char_cast(6)
    Traceback (most recent call last):
    IndexError: string index out of range
    """
    return (b12345[i])


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
                                 "//CoerceFromPyTypeNode")
def index_literal_uchar_cast(int i):
    """
    >>> index_literal_uchar_cast(0) == ord('1')
    True
    >>> index_literal_uchar_cast(-5) == ord('1')
    True
    >>> index_literal_uchar_cast(2) == ord('3')
    True
    >>> index_literal_uchar_cast(4) == ord('5')
    True
    >>> index_literal_uchar_cast(6)
    Traceback (most recent call last):
    IndexError: string index out of range
    """
    return (b"12345"[i])


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
                                 "//CoerceFromPyTypeNode")
def index_nonliteral_uchar_cast(int i):
    """
    >>> index_nonliteral_uchar_cast(0) == ord('1')
    True
    >>> index_nonliteral_uchar_cast(-5) == ord('1')
    True
    >>> index_nonliteral_uchar_cast(2) == ord('3')
    True
    >>> index_nonliteral_uchar_cast(4) == ord('5')
    True
    >>> index_nonliteral_uchar_cast(6)
    Traceback (most recent call last):
    IndexError: string index out of range
    """
    return (b12345[i])


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
                                 "//CoerceFromPyTypeNode")
def index_literal_char_coerce(int i):
    """
    >>> index_literal_char_coerce(0) == ord('1')
    True
    >>> index_literal_char_coerce(-5) == ord('1')
    True
    >>> index_literal_char_coerce(2) == ord('3')
    True
    >>> index_literal_char_coerce(4) == ord('5')
    True
    >>> index_literal_char_coerce(6)
    Traceback (most recent call last):
    IndexError: string index out of range
    """
    cdef char result = b"12345"[i]
    return result


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
                                 "//CoerceFromPyTypeNode")
def index_nonliteral_char_coerce(int i):
    """
    >>> index_nonliteral_char_coerce(0) == ord('1')
    True
    >>> index_nonliteral_char_coerce(-5) == ord('1')
    True
    >>> index_nonliteral_char_coerce(2) == ord('3')
    True
    >>> index_nonliteral_char_coerce(4) == ord('5')
    True
    >>> index_nonliteral_char_coerce(6)
    Traceback (most recent call last):
    IndexError: string index out of range
    """
    cdef char result = b12345[i]
    return result


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
                                 "//CoerceFromPyTypeNode")
@cython.boundscheck(False)
def index_literal_char_coerce_no_check(int i):
    """
    >>> index_literal_char_coerce_no_check(0) == ord('1')
    True
    >>> index_literal_char_coerce_no_check(-5) == ord('1')
    True
    >>> index_literal_char_coerce_no_check(2) == ord('3')
    True
    >>> index_literal_char_coerce_no_check(4) == ord('5')
    True
    """
    cdef char result = b"12345"[i]
    return result


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
                                 "//CoerceFromPyTypeNode")
@cython.boundscheck(False)
def index_nonliteral_char_coerce_no_check(int i):
    """
    >>> index_nonliteral_char_coerce_no_check(0) == ord('1')
    True
    >>> index_nonliteral_char_coerce_no_check(-5) == ord('1')
    True
    >>> index_nonliteral_char_coerce_no_check(2) == ord('3')
    True
    >>> index_nonliteral_char_coerce_no_check(4) == ord('5')
    True
    """
    cdef char result = b12345[i]
    return result
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/bytesmethods.pyx0000644000175100001770000001723400000000000021025 0ustar00runnerdocker00000000000000cimport cython

cdef extern from *:
    const Py_ssize_t PY_SSIZE_T_MIN
    const Py_ssize_t PY_SSIZE_T_MAX

SSIZE_T_MAX = PY_SSIZE_T_MAX
SSIZE_T_MIN = PY_SSIZE_T_MIN


b_a = b'a'
b_b = b'b'

import sys


@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
@cython.test_fail_if_path_exists(
    "//SimpleCallNode")
def bytes_startswith(bytes s, sub, start=None, stop=None):
    """
    >>> bytes_startswith(b_a, b_a)
    True
    >>> bytes_startswith(b_a+b_b, b_a)
    True
    >>> bytes_startswith(b_a, b_b)
    False
    >>> bytes_startswith(b_a+b_b, b_b)
    False
    >>> bytes_startswith(b_a, (b_a, b_b))
    True
    >>> bytes_startswith(b_a, b_a, 1)
    False
    >>> bytes_startswith(b_a, b_a, 0, 0)
    False
    """

    if start is None:
      return s.startswith(sub)
    elif stop is None:
      return s.startswith(sub, start)
    else:
      return s.startswith(sub, start, stop)


@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
@cython.test_fail_if_path_exists(
    "//SimpleCallNode")
def bytes_endswith(bytes s, sub, start=None, stop=None):
    """
    >>> bytes_endswith(b_a, b_a)
    True
    >>> bytes_endswith(b_b+b_a, b_a)
    True
    >>> bytes_endswith(b_a, b_b)
    False
    >>> bytes_endswith(b_b+b_a, b_b)
    False
    >>> bytes_endswith(b_a, (b_a, b_b))
    True
    >>> bytes_endswith(b_a, b_a, 1)
    False
    >>> bytes_endswith(b_a, b_a, 0, 0)
    False
    """

    if start is None:
      return s.endswith(sub)
    elif stop is None:
      return s.endswith(sub, start)
    else:
      return s.endswith(sub, start, stop)


@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
@cython.test_fail_if_path_exists(
    "//SimpleCallNode")
def bytes_decode(bytes s, start=None, stop=None):
    """
    >>> s = b_a+b_b+b_a+b_a+b_b
    >>> print(bytes_decode(s))
    abaab

    >>> print(bytes_decode(s, 2))
    aab
    >>> print(bytes_decode(s, -3))
    aab

    >>> print(bytes_decode(s, None, 4))
    abaa
    >>> print(bytes_decode(s, None, 400))
    abaab
    >>> print(bytes_decode(s, None, -2))
    aba
    >>> print(bytes_decode(s, None, -4))
    a
    >>> print(bytes_decode(s, None, -5))
    
    >>> print(bytes_decode(s, None, -200))
    

    >>> print(bytes_decode(s, 2, 5))
    aab
    >>> print(bytes_decode(s, 2, 500))
    aab
    >>> print(bytes_decode(s, 2, -1))
    aa
    >>> print(bytes_decode(s, 2, -3))
    
    >>> print(bytes_decode(s, 2, -300))
    
    >>> print(bytes_decode(s, -3, -1))
    aa
    >>> print(bytes_decode(s, -300, 300))
    abaab
    >>> print(bytes_decode(s, -300, -4))
    a
    >>> print(bytes_decode(s, -300, -5))
    
    >>> print(bytes_decode(s, -300, -6))
    
    >>> print(bytes_decode(s, -300, -500))
    
    >>> print(bytes_decode(s, SSIZE_T_MIN, SSIZE_T_MIN))
    
    >>> print(bytes_decode(s, SSIZE_T_MIN, SSIZE_T_MAX))
    abaab
    >>> print(bytes_decode(s, SSIZE_T_MAX, SSIZE_T_MIN))
    
    >>> print(bytes_decode(s, SSIZE_T_MAX, SSIZE_T_MAX))
    

    >>> s[:'test']                       # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError:...
    >>> print(bytes_decode(s, 'test'))   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError:...
    >>> print(bytes_decode(s, None, 'test'))    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError:...
    >>> print(bytes_decode(s, 'test', 'test'))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError:...

    >>> print(bytes_decode(None))
    Traceback (most recent call last):
    AttributeError: 'NoneType' object has no attribute 'decode'
    >>> print(bytes_decode(None, 1))
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not subscriptable
    >>> print(bytes_decode(None, None, 1))
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not subscriptable
    >>> print(bytes_decode(None, 0, 1))
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not subscriptable
    """
    if start is None:
        if stop is None:
            return s.decode('utf8')
        else:
            return s[:stop].decode('utf8')
    elif stop is None:
        return s[start:].decode('utf8')
    else:
        return s[start:stop].decode('utf8')


@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
@cython.test_fail_if_path_exists(
    "//SimpleCallNode")
def bytes_decode_utf16(bytes s):
    """
    >>> s = 'abc'.encode('UTF-16')
    >>> print(bytes_decode_utf16(s))
    abc
    """
    return s.decode('utf16')


@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
@cython.test_fail_if_path_exists(
    "//SimpleCallNode")
def bytes_decode_utf16_le(bytes s):
    """
    >>> s = 'abc'.encode('UTF-16LE')
    >>> assert s != 'abc'.encode('UTF-16BE')
    >>> print(bytes_decode_utf16_le(s))
    abc
    """
    return s.decode('utf_16_le')


@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
@cython.test_fail_if_path_exists(
    "//SimpleCallNode")
def bytes_decode_utf16_be(bytes s):
    """
    >>> s = 'abc'.encode('UTF-16BE')
    >>> assert s != 'abc'.encode('UTF-16LE')
    >>> print(bytes_decode_utf16_be(s))
    abc
    """
    return s.decode('utf_16_be')


@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
@cython.test_fail_if_path_exists(
    "//SimpleCallNode")
def bytes_decode_unbound_method(bytes s, start=None, stop=None):
    """
    >>> s = b_a+b_b+b_a+b_a+b_b
    >>> print(bytes_decode_unbound_method(s))
    abaab
    >>> print(bytes_decode_unbound_method(s, 1))
    baab
    >>> print(bytes_decode_unbound_method(s, None, 3))
    aba
    >>> print(bytes_decode_unbound_method(s, 1, 4))
    baa

    >>> print(bytes_decode_unbound_method(None))
    Traceback (most recent call last):
    TypeError: descriptor 'decode' requires a 'bytes' object but received a 'NoneType'
    >>> print(bytes_decode_unbound_method(None, 1))
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not subscriptable
    >>> print(bytes_decode_unbound_method(None, None, 1))
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not subscriptable
    >>> print(bytes_decode_unbound_method(None, 0, 1))
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not subscriptable
    """
    if start is None:
        if stop is None:
            return bytes.decode(s, 'utf8')
        else:
            return bytes.decode(s[:stop], 'utf8')
    elif stop is None:
        return bytes.decode(s[start:], 'utf8')
    else:
        return bytes.decode(s[start:stop], 'utf8')


@cython.test_assert_path_exists(
    "//SimpleCallNode",
    "//SimpleCallNode//NoneCheckNode",
    "//SimpleCallNode//AttributeNode[@is_py_attr = false]")
def bytes_join(bytes s, *args):
    """
    >>> print(bytes_join(b_a, b_b, b_b, b_b).decode('utf8'))
    babab
    """
    result = s.join(args)
    assert cython.typeof(result) == 'Python object', cython.typeof(result)
    return result


@cython.test_fail_if_path_exists(
    "//SimpleCallNode//NoneCheckNode",
)
@cython.test_assert_path_exists(
    "//SimpleCallNode",
    "//SimpleCallNode//AttributeNode[@is_py_attr = false]")
def literal_join(*args):
    """
    >>> print(literal_join(b_b, b_b, b_b, b_b).decode('utf8'))
    b|b|b|b
    """
    result = b'|'.join(args)
    assert cython.typeof(result) == 'Python object', cython.typeof(result)
    return result

def fromhex(bytes b):
    """
    https://github.com/cython/cython/issues/5051
    Optimization of bound method calls was breaking classmethods
    >>> fromhex(b"")
    """
    if sys.version_info[0] > 2:
        assert b.fromhex('2Ef0 F1f2  ') == b'.\xf0\xf1\xf2'
    # method doesn't exist on Py2!
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/c_file_validation.srctree0000644000175100001770000000453200000000000022572 0ustar00runnerdocker00000000000000"""
PYTHON run_test.py
"""

######## run_test.py ########

import os
from collections import defaultdict
from os.path import basename, splitext

from Cython.Compiler.Options import CompilationOptions
from Cython.Compiler.Main import compile as cython_compile
from Cython.Compiler.Options import default_options


def validate_file(filename):
    module_name = basename(filename)
    c_file = splitext(filename)[0] + '.c'

    options = CompilationOptions(
        default_options,
        language_level="3",
        evaluate_tree_assertions=True,
    )
    result = cython_compile(filename, options=options)
    return result.num_errors


error_counts = defaultdict(int)
failed = False

for filename in sorted(os.listdir(".")):
    if "run_test" in filename:
        continue

    print("Testing '%s'" % filename)
    num_errors = validate_file(filename)
    print(num_errors, filename)
    error_counts[num_errors] += 1

    if '_ok' in filename:
        if num_errors > 0:
            failed = True
            print("ERROR: Compilation failed: %s (%s errors)" % (filename, num_errors))
    else:
        if num_errors == 0:
            failed = True
            print("ERROR: Expected failure, but compilation succeeded: %s" % filename)

assert error_counts == {0: 3, 1: 6}, error_counts
assert not failed


######## assert_ok.py ########

# cython: test_assert_c_code_has = Generated by Cython
# cython: test_assert_c_code_has = CYTHON_HEX_VERSION


######## assert_missing.py ########

# cython: test_assert_c_code_has = Generated by Python


######## assert_start_end_ok.py ########

# cython: test_assert_c_code_has = :/#include "Python.h"/ Generated by Cython
# cython: test_assert_c_code_has = /Generated by Cython/:/Code section/ #include "Python.h"


######## assert_start_missing.py ########

# cython: test_assert_c_code_has = /xx[^x]xx/: Generated by Cython


######## assert_end_missing.py ########

# cython: test_assert_c_code_has = :/xx[^x]xx/ Generated by Cython


######## fail_if_ok.py ########

# cython: test_fail_if_c_code_has = Generated by Python


######## fail_if_found.py ########

# cython: test_fail_if_c_code_has = Generated by Cython


######## fail_if_start_missing.py ########

# cython: test_fail_if_c_code_has = /xx[^x]xx/: Generated by Python


######## fail_if_end_missing.py ########

# cython: test_fail_if_c_code_has = :/xx[^x]xx/ Generated by Python
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/c_int_types_T255.pyx0000644000175100001770000004702400000000000021352 0ustar00runnerdocker00000000000000# ticket: t255

__doc__ = u""

# -------------------------------------------------------------------

SCHAR_MAX = ((-1)>>1)
SCHAR_MIN = (-SCHAR_MAX-1)

def test_schar(signed char x):
   u"""
   >>> test_schar(-129) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_schar(-128)
   -128
   >>> test_schar(0)
   0
   >>> test_schar(127)
   127
   >>> test_schar(128) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to signed char
   """
   return x

def test_add_schar(x, y):
   u"""
   >>> test_add_schar(SCHAR_MIN, -1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_add_schar(SCHAR_MIN, 0) == SCHAR_MIN
   True
   >>> test_add_schar(SCHAR_MIN, 1) == SCHAR_MIN+1
   True
   >>> test_add_schar(SCHAR_MAX, -1) == SCHAR_MAX-1
   True
   >>> test_add_schar(SCHAR_MAX, 0) == SCHAR_MAX
   True
   >>> test_add_schar(SCHAR_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to signed char
   """
   cdef signed char r = x + y
   return r

UCHAR_MAX = ((-1))

def test_uchar(unsigned char x):
   u"""
   >>> test_uchar(-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: can't convert negative value to unsigned char
   >>> test_uchar(0)
   0
   >>> test_uchar(1)
   1
   >>> test_uchar(UCHAR_MAX) == UCHAR_MAX
   True
   >>> test_uchar(UCHAR_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to unsigned char
   """
   return x

def test_add_uchar(x, y):
   u"""
   >>> test_add_uchar(UCHAR_MAX, 0) == UCHAR_MAX
   True
   >>> test_add_uchar(UCHAR_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to unsigned char
   """
   cdef unsigned char r = x + y
   return r

# chars may be signed or unsigned
if (-1) < 0:
    CHAR_MAX = SCHAR_MAX
    CHAR_MIN = SCHAR_MIN
else:
    CHAR_MAX = UCHAR_MAX
    CHAR_MIN = 0

def test_char(char x):
   u"""
   >>> test_char(CHAR_MIN-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> if CHAR_MIN < 0:
   ...     assert test_char(-1) == -1
   >>> test_char(CHAR_MIN) == CHAR_MIN
   True
   >>> test_char(0)
   0
   >>> test_char(1)
   1
   >>> test_char(CHAR_MAX) == CHAR_MAX
   True
   >>> test_char(CHAR_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to char
   """
   return x

def test_add_char(x, y):
   u"""
   >>> test_add_char(CHAR_MIN, -1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_add_char(CHAR_MIN, 0) == CHAR_MIN
   True
   >>> test_add_char(CHAR_MIN, 1) == CHAR_MIN+1
   True
   >>> test_add_char(CHAR_MAX, -1) == CHAR_MAX-1
   True
   >>> test_add_char(CHAR_MAX, 0) == CHAR_MAX
   True
   >>> test_add_char(CHAR_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to char
   """
   cdef char r = x + y
   return r

# -------------------------------------------------------------------

SHORT_MAX = ((-1)>>1)
SHORT_MIN = (-SHORT_MAX-1)

def test_short(short x):
   u"""
   >>> test_short(SHORT_MIN-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to short
   >>> test_short(SHORT_MIN) == SHORT_MIN
   True
   >>> test_short(-1)
   -1
   >>> test_short(0)
   0
   >>> test_short(1)
   1
   >>> test_short(SHORT_MAX) == SHORT_MAX
   True
   >>> test_short(SHORT_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to short
   """
   return x

def test_add_short(x, y):
   u"""
   >>> test_add_short(SHORT_MIN, -1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to short
   >>> test_add_short(SHORT_MIN, 0) == SHORT_MIN
   True
   >>> test_add_short(SHORT_MIN, 1) == SHORT_MIN+1
   True
   >>> test_add_short(SHORT_MAX, -1) == SHORT_MAX-1
   True
   >>> test_add_short(SHORT_MAX, 0) == SHORT_MAX
   True
   >>> test_add_short(SHORT_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to short
   """
   cdef short r = x + y
   return r

SSHORT_MAX = ((-1)>>1)
SSHORT_MIN = (-SSHORT_MAX-1)

def test_sshort(signed short x):
   u"""
   >>> test_sshort(SSHORT_MIN-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to short
   >>> test_sshort(SSHORT_MIN) == SSHORT_MIN
   True
   >>> test_sshort(-1)
   -1
   >>> test_sshort(0)
   0
   >>> test_sshort(1)
   1
   >>> test_sshort(SSHORT_MAX) == SSHORT_MAX
   True
   >>> test_short(SSHORT_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to short
   """
   return x

def test_add_sshort(x, y):
   u"""
   >>> test_add_sshort(SSHORT_MIN, -1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to short
   >>> test_add_sshort(SSHORT_MIN, 0) == SSHORT_MIN
   True
   >>> test_add_sshort(SSHORT_MIN, 1) == SSHORT_MIN+1
   True
   >>> test_add_sshort(SSHORT_MAX, -1) == SSHORT_MAX-1
   True
   >>> test_add_sshort(SSHORT_MAX, 0) == SSHORT_MAX
   True
   >>> test_add_sshort(SSHORT_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to short
   """
   cdef signed short r = x + y
   return r

USHORT_MAX = ((-1))

def test_ushort(unsigned short x):
   u"""
   >>> test_ushort(-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: can't convert negative value to unsigned short
   >>> test_ushort(0)
   0
   >>> test_ushort(1)
   1
   >>> test_ushort(USHORT_MAX) == USHORT_MAX
   True
   >>> test_ushort(USHORT_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_ushort(x, y):
   u"""
   >>> test_add_ushort(USHORT_MAX, 0) == USHORT_MAX
   True
   >>> test_add_ushort(USHORT_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to unsigned short
   """
   cdef unsigned short r = x + y
   return r

# -------------------------------------------------------------------

INT_MAX = ((-1)>>1)
INT_MIN = (-INT_MAX-1)

def test_int(int x):
   u"""
   >>> test_int(INT_MIN-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_int(INT_MIN) == INT_MIN
   True
   >>> test_int(-1)
   -1
   >>> test_int(0)
   0
   >>> test_int(1)
   1
   >>> test_int(INT_MAX) == INT_MAX
   True
   >>> test_int(INT_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_int(x, y):
   u"""
   >>> test_add_int(INT_MIN, -1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_add_int(INT_MIN, 0) == INT_MIN
   True
   >>> test_add_int(INT_MIN, 1) == INT_MIN+1
   True
   >>> test_add_int(INT_MAX, -1) == INT_MAX-1
   True
   >>> test_add_int(INT_MAX, 0) == INT_MAX
   True
   >>> test_add_int(INT_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   cdef int r = x + y
   return r

SINT_MAX = ((-1)>>1)
SINT_MIN = (-SINT_MAX-1)

def test_sint(signed int x):
   u"""
   >>> test_sint(SINT_MIN-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_sint(SINT_MIN) == SINT_MIN
   True
   >>> test_sint(-1)
   -1
   >>> test_sint(0)
   0
   >>> test_sint(1)
   1
   >>> test_sint(SINT_MAX) == SINT_MAX
   True
   >>> test_sint(SINT_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_sint(x, y):
   u"""
   >>> test_add_sint(SINT_MIN, -1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_add_sint(SINT_MIN, 0) == SINT_MIN
   True
   >>> test_add_sint(SINT_MIN, 1) == SINT_MIN+1
   True
   >>> test_add_sint(SINT_MAX, -1) == SINT_MAX-1
   True
   >>> test_add_sint(SINT_MAX, 0) == SINT_MAX
   True
   >>> test_add_sint(SINT_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   cdef signed int r = x + y
   return r

UINT_MAX = (-1)

def test_uint(unsigned int x):
   u"""
   >>> test_uint(-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: can't convert negative value to unsigned int
   >>> print(test_uint(0))
   0
   >>> print(test_uint(1))
   1
   >>> test_uint(UINT_MAX) == UINT_MAX
   True
   >>> test_uint(UINT_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_uint(x, y):
   u"""
   >>> test_add_uint(UINT_MAX, 0) == UINT_MAX
   True
   >>> test_add_uint(UINT_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   cdef unsigned int r = x + y
   return r

# -------------------------------------------------------------------

LONG_MAX = ((-1)>>1)
LONG_MIN = (-LONG_MAX-1)

def test_long(long x):
   u"""
   >>> test_long(LONG_MIN-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_long(LONG_MIN) == LONG_MIN
   True
   >>> test_long(-1)
   -1
   >>> test_long(0)
   0
   >>> test_long(1)
   1
   >>> test_long(LONG_MAX) == LONG_MAX
   True
   >>> test_long(LONG_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_long(x, y):
   u"""
   >>> test_add_long(LONG_MIN, -1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_add_long(LONG_MIN, 0) == LONG_MIN
   True
   >>> test_add_long(LONG_MIN, 1) == LONG_MIN+1
   True
   >>> test_add_long(LONG_MAX, -1) == LONG_MAX-1
   True
   >>> test_add_long(LONG_MAX, 0) == LONG_MAX
   True
   >>> test_add_long(LONG_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   cdef long r = x + y
   return r

SLONG_MAX = ((-1)>>1)
SLONG_MIN = (-SLONG_MAX-1)

def test_slong(signed long x):
   u"""
   >>> test_slong(SLONG_MIN-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_slong(SLONG_MIN) == SLONG_MIN
   True
   >>> test_slong(-1)
   -1
   >>> test_slong(0)
   0
   >>> test_slong(1)
   1
   >>> test_slong(SLONG_MAX) == SLONG_MAX
   True
   >>> test_slong(SLONG_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_slong(x, y):
   u"""
   >>> test_add_slong(SLONG_MIN, -1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_add_slong(SLONG_MIN, 0) == SLONG_MIN
   True
   >>> test_add_slong(SLONG_MIN, 1) == SLONG_MIN+1
   True
   >>> test_add_slong(SLONG_MAX, -1) == SLONG_MAX-1
   True
   >>> test_add_slong(SLONG_MAX, 0) == SLONG_MAX
   True
   >>> test_add_slong(SLONG_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   cdef signed long r = x + y
   return r

ULONG_MAX = (-1)

def test_ulong(unsigned long x):
   u"""
   >>> test_ulong(-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: can't convert negative value to unsigned long
   >>> print(test_ulong(0))
   0
   >>> print(test_ulong(1))
   1
   >>> test_ulong(ULONG_MAX) == ULONG_MAX
   True
   >>> test_ulong(ULONG_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_ulong(x, y):
   u"""
   >>> test_add_ulong(ULONG_MAX, 0) == ULONG_MAX
   True
   >>> test_add_ulong(ULONG_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   cdef unsigned long r = x + y
   return r

# -------------------------------------------------------------------

LONGLONG_MAX = ((-1)>>1)
LONGLONG_MIN = (-LONGLONG_MAX-1)

def test_longlong(long long x):
   u"""
   >>> test_longlong(LONGLONG_MIN-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_longlong(LONGLONG_MIN) == LONGLONG_MIN
   True
   >>> print(test_longlong(-1))
   -1
   >>> print(test_longlong(0))
   0
   >>> print(test_longlong(1))
   1
   >>> test_longlong(LONGLONG_MAX) == LONGLONG_MAX
   True
   >>> test_longlong(LONGLONG_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_longlong(x, y):
   u"""
   >>> test_add_longlong(LONGLONG_MIN, -1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_add_longlong(LONGLONG_MIN, 0) == LONGLONG_MIN
   True
   >>> test_add_longlong(LONGLONG_MIN, 1) == LONGLONG_MIN+1
   True
   >>> test_add_longlong(LONGLONG_MAX, -1) == LONGLONG_MAX-1
   True
   >>> test_add_longlong(LONGLONG_MAX, 0) == LONGLONG_MAX
   True
   >>> test_add_longlong(LONGLONG_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   cdef long long r = x + y
   return r

SLONGLONG_MAX = ((-1)>>1)
SLONGLONG_MIN = (-SLONGLONG_MAX-1)

def test_slonglong(long long x):
   u"""
   >>> test_slonglong(SLONGLONG_MIN-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_slonglong(SLONGLONG_MIN) == SLONGLONG_MIN
   True
   >>> print(test_slonglong(-1))
   -1
   >>> print(test_slonglong(0))
   0
   >>> print(test_slonglong(1))
   1
   >>> test_slonglong(SLONGLONG_MAX) == SLONGLONG_MAX
   True
   >>> test_slonglong(SLONGLONG_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_slonglong(x, y):
   u"""
   >>> test_add_slonglong(SLONGLONG_MIN, -1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_add_slonglong(SLONGLONG_MIN, 0) == SLONGLONG_MIN
   True
   >>> test_add_slonglong(SLONGLONG_MIN, 1) == SLONGLONG_MIN+1
   True
   >>> test_add_slonglong(SLONGLONG_MAX, -1) == SLONGLONG_MAX-1
   True
   >>> test_add_slonglong(SLONGLONG_MAX, 0) == SLONGLONG_MAX
   True
   >>> test_add_slonglong(SLONGLONG_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   cdef signed long long r = x + y
   return r

ULONGLONG_MAX = (-1)

def test_ulonglong(unsigned long long x):
   u"""
   >>> test_ulonglong(-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: can't convert negative value to unsigned PY_LONG_LONG
   >>> print(test_ulonglong(0))
   0
   >>> print(test_ulonglong(1))
   1
   >>> test_ulonglong(ULONGLONG_MAX) == ULONGLONG_MAX
   True
   >>> test_ulonglong(ULONGLONG_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_ulonglong(x, y):
   u"""
   >>> test_add_ulonglong(ULONGLONG_MAX, 0) == ULONGLONG_MAX
   True
   >>> test_add_ulonglong(ULONGLONG_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   cdef unsigned long long r = x + y
   return r

# -------------------------------------------------------------------
import sys

class MyInt(object):
   def __init__(self, value):
      self.value = value
   def __int__(self):
      print(u"MyInt.__int__()")
      return self.value

class MyBadInt(MyInt):
   def __int__(self):
      return u"%s" % self.value

class MyInt2:
   def __init__(self, value):
      self.value = value
   def __int__(self):
      print(u"MyInt.__int__()")
      return self.value

class MyBadInt2(MyInt2):
   def __int__(self):
      return u"%s" % self.value

def test_convert_pyint(x):
   u"""
   >>> test_convert_pyint(None)  # doctest: +ELLIPSIS
   Traceback (most recent call last):
   TypeError:... int...
   >>> test_convert_pyint("123")  # doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   TypeError:... int...
   >>> test_convert_pyint(MyBadInt(0)) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   TypeError: ... returned non-... (type ...)

   >>> test_convert_pyint(False) == 0
   True
   >>> test_convert_pyint(True) == 1
   True
   >>> test_convert_pyint(3.14) == 3
   True

   >>> test_convert_pyint(MyInt(LONG_MIN)) == LONG_MIN
   MyInt.__int__()
   True
   >>> test_convert_pyint(MyInt(0)) == 0
   MyInt.__int__()
   True
   >>> test_convert_pyint(MyInt(LONG_MAX)) == LONG_MAX
   MyInt.__int__()
   True
   """
   cdef long r = x
   return r

class MyLong(object):
   def __init__(self, value):
      self.value = value
   def __int__(self): # Python 3
      return self.__long__()
   def __long__(self):
      print(u"MyInt.__long__()")
      return self.value

class MyBadLong(MyLong):
   def __long__(self):
      return u"%s" % self.value

def test_convert_pylong(x):
   u"""
   >>> test_convert_pylong(None)  # doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   TypeError:... int...
   >>> test_convert_pylong("123")  # doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   TypeError:... int...
   >>> test_convert_pylong(MyBadLong(0)) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   TypeError: ... returned non-... (type ...)

   >>> test_convert_pylong(False) == 0
   True
   >>> test_convert_pylong(True) == 1
   True
   >>> test_convert_pylong(3.14) == 3
   True

   >>> test_convert_pylong(MyLong(LONGLONG_MIN)) == LONGLONG_MIN
   MyInt.__long__()
   True
   >>> test_convert_pylong(MyLong(0)) == 0
   MyInt.__long__()
   True
   >>> test_convert_pylong(MyLong(LONGLONG_MAX)) == LONGLONG_MAX
   MyInt.__long__()
   True
   """
   cdef long long r = x
   return r


cdef enum:
   ANONYMOUS_ENUM_MEMBER = 1

def test_anonymous_enum():
   """
   The main point here is that the from-py conversion function shouldn't
   conflict with the function for int
   >>> test_anonymous_enum()
   1
   """
   return ANONYMOUS_ENUM_MEMBER


# -------------------------------------------------------------------

__doc__ = u"".join([
      f.__doc__ for f in (
         #
         test_char,  test_add_char,
         test_schar, test_add_schar,
         test_uchar, test_add_uchar,
         #
         test_short,  test_add_short,
         test_sshort, test_add_sshort,
         test_ushort, test_add_ushort,
         #
         test_int,  test_add_int,
         test_sint, test_add_sint,
         test_uint, test_add_uint,
         #
         test_long,  test_add_long,
         test_slong, test_add_slong,
         test_ulong, test_add_ulong,
         #
         test_longlong,  test_add_longlong,
         test_slonglong, test_add_slonglong,
         test_ulonglong, test_add_ulonglong,
         #
         test_convert_pyint,
         test_convert_pylong,
         )
    ])

# -------------------------------------------------------------------
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/c_type_methods_T236.pyx0000644000175100001770000000146300000000000022034 0ustar00runnerdocker00000000000000# ticket: t236

import sys

__doc__ = '''
>>> float_is_integer(1.0)
True
>>> float_is_integer(1.1)
False
'''
if sys.version_info >= (3,1):
    __doc__ += '''
>>> int_bit_length(1) == (1).bit_length()
True
>>> int_bit_length(1234) == (1234).bit_length()
True
'''

def float_is_integer(float f):
    return f.is_integer()

def int_bit_length(int i):
    # requires Python 3.x
    return i.bit_length()


def float__add__(float f):
    """
    >>> float__add__(5.0)
    7.0
    """
    return f.__add__(2)


def float_const__add__(float f):
    """
    >>> float_const__add__(5.0)
    7.0
    """
    return 2. .__add__(f)


def int__add__(int i):
    """
    >>> int__add__(5)
    7
    """
    return i.__add__(2)


def int_const__add__(int i):
    """
    >>> int_const__add__(5)
    7
    """
    return 2 .__add__(i)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/call_crash.pyx0000644000175100001770000000064700000000000020406 0ustar00runnerdocker00000000000000cdef class A:
    """
    >>> A().test(3)
    9
    """

    cdef int (*func_ptr)(int)

    def __init__(self):
        self.func_ptr = &func

    cdef int do_it(self, int s):
        cdef int r = first_call(self).func_ptr(s) # the temp for first_call(self) not properly freed
        return r

    def test(self, s):
        return self.do_it(s)

cdef A first_call(A x):
    return x

cdef int func(int s):
    return s*s
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/call_py_cy.pyx0000644000175100001770000001542600000000000020432 0ustar00runnerdocker00000000000000# mode: run
# tag: cyfunction,call,python
# cython: binding=True

#######
# Test that Cython and Python functions can call each other in various signature combinations.
#######

py_call_noargs = eval("lambda: 'noargs'")
py_call_onearg = eval("lambda arg: arg")
py_call_twoargs = eval("lambda arg, arg2: (arg, arg2)")
py_call_starargs = eval("lambda *args: args")
py_call_pos_and_starargs = eval("lambda arg, *args: (arg, args)")
py_call_starstarargs = eval("lambda **kw: sorted(kw.items())")
py_call_args_and_starstarargs = eval("lambda *args, **kw: (args, sorted(kw.items()))")


def cy_call_noargs():
    """
    >>> cy_call_noargs()
    'noargs'
    """
    return py_call_noargs()


def cy_call_onearg(f):
    """
    >>> cy_call_onearg(py_call_onearg)
    'onearg'
    >>> try: cy_call_onearg(py_call_noargs)
    ... except TypeError: pass
    ... else: print("FAILED!")
    >>> try: cy_call_onearg(py_call_twoargs)
    ... except TypeError: pass
    ... else: print("FAILED!")

    >>> class Class(object):
    ...     def method(self, arg): return arg

    >>> cy_call_onearg(Class().method)
    'onearg'
    """
    return f('onearg')


def cy_call_twoargs(f, arg):
    """
    >>> cy_call_twoargs(py_call_twoargs, 132)
    (132, 'twoargs')

    >>> class Class2(object):
    ...     def method(self, arg, arg2): return arg, arg2
    >>> cy_call_twoargs(Class2().method, 123)
    (123, 'twoargs')

    >>> class Class1(object):
    ...     def method(self, arg): return arg
    >>> cy_call_twoargs(Class1.method, Class1())
    'twoargs'
    """
    return f(arg, 'twoargs')


def cy_call_two_kwargs(f, arg):
    """
    >>> cy_call_two_kwargs(py_call_twoargs, arg=132)
    (132, 'two-kwargs')
    >>> cy_call_two_kwargs(f=py_call_twoargs, arg=132)
    (132, 'two-kwargs')
    >>> cy_call_two_kwargs(arg=132, f=py_call_twoargs)
    (132, 'two-kwargs')

    >>> class Class(object):
    ...     def method(self, arg, arg2): return arg, arg2

    >>> cy_call_two_kwargs(Class().method, 123)
    (123, 'two-kwargs')
    """
    return f(arg2='two-kwargs', arg=arg)


def cy_call_starargs(*args):
    """
    >>> cy_call_starargs()
    ()
    >>> cy_call_starargs(1)
    (1,)
    >>> cy_call_starargs(1, 2)
    (1, 2)
    >>> cy_call_starargs(1, 2, 3)
    (1, 2, 3)
    """
    return py_call_starargs(*args)


def cy_call_pos_and_starargs(f, *args):
    """
    >>> cy_call_pos_and_starargs(py_call_onearg)
    'no-arg'
    >>> cy_call_pos_and_starargs(py_call_onearg, 123)
    123
    >>> cy_call_pos_and_starargs(py_call_twoargs, 123, 321)
    (123, 321)
    >>> cy_call_pos_and_starargs(py_call_starargs)
    ('no-arg',)
    >>> cy_call_pos_and_starargs(py_call_starargs, 123)
    (123,)
    >>> cy_call_pos_and_starargs(py_call_starargs, 123, 321)
    (123, 321)
    >>> cy_call_pos_and_starargs(py_call_pos_and_starargs)
    ('no-arg', ())
    >>> cy_call_pos_and_starargs(py_call_pos_and_starargs, 123)
    (123, ())
    >>> cy_call_pos_and_starargs(py_call_pos_and_starargs, 123, 321)
    (123, (321,))
    >>> cy_call_pos_and_starargs(py_call_pos_and_starargs, 123, 321, 234)
    (123, (321, 234))

    >>> class Class(object):
    ...     def method(self, arg, arg2): return arg, arg2

    >>> cy_call_pos_and_starargs(Class().method, 123, 321)
    (123, 321)
    >>> cy_call_pos_and_starargs(Class.method, Class(), 123, 321)
    (123, 321)
    """
    return f(args[0] if args else 'no-arg', *args[1:])


def cy_call_starstarargs(**kw):
    """
    >>> kw = {}
    >>> cy_call_starstarargs(**kw)
    []
    >>> kw = {'a': 123}
    >>> cy_call_starstarargs(**kw)
    [('a', 123)]
    >>> kw = {'a': 123, 'b': 321}
    >>> cy_call_starstarargs(**kw)
    [('a', 123), ('b', 321)]
    """
    return py_call_starstarargs(**kw)


def cy_call_kw_and_starstarargs(f=None, arg1=None, **kw):
    """
    >>> kw = {}
    >>> cy_call_kw_and_starstarargs(**kw)
    [('arg', None)]
    >>> try: cy_call_kw_and_starstarargs(py_call_noargs, **kw)
    ... except TypeError: pass
    >>> try: cy_call_kw_and_starstarargs(py_call_twoargs, **kw)
    ... except TypeError: pass
    ... else: print("FAILED!")
    >>> cy_call_kw_and_starstarargs(py_call_onearg, **kw)
    >>> cy_call_kw_and_starstarargs(f=py_call_onearg, **kw)
    >>> cy_call_kw_and_starstarargs(py_call_pos_and_starargs, **kw)
    (None, ())

    >>> kw = {'arg1': 123}
    >>> cy_call_kw_and_starstarargs(**kw)
    [('arg', 123)]
    >>> cy_call_kw_and_starstarargs(py_call_onearg, **kw)
    123
    >>> cy_call_kw_and_starstarargs(f=py_call_onearg, **kw)
    123
    >>> cy_call_kw_and_starstarargs(py_call_twoargs, arg2=321, **kw)
    (123, 321)
    >>> cy_call_kw_and_starstarargs(f=py_call_twoargs, arg2=321, **kw)
    (123, 321)
    >>> try: cy_call_kw_and_starstarargs(py_call_twoargs, **kw)
    ... except TypeError: pass
    ... else: print("FAILED!")
    >>> try: cy_call_kw_and_starstarargs(py_call_twoargs, arg2=321, other=234, **kw)
    ... except TypeError: pass
    ... else: print("FAILED!")
    >>> cy_call_kw_and_starstarargs(py_call_pos_and_starargs, **kw)
    (123, ())

    >>> try: cy_call_kw_and_starstarargs(arg=321, **kw)   # duplicate kw in Python call
    ... except TypeError: pass
    ... else: print("FAILED!")

    >>> kw = {'a': 123}
    >>> cy_call_kw_and_starstarargs(**kw)
    [('a', 123), ('arg', None)]
    >>> cy_call_kw_and_starstarargs(arg1=321, **kw)
    [('a', 123), ('arg', 321)]

    >>> kw = {'a': 123, 'b': 321}
    >>> cy_call_kw_and_starstarargs(**kw)
    [('a', 123), ('arg', None), ('b', 321)]
    >>> cy_call_kw_and_starstarargs(arg1=234, **kw)
    [('a', 123), ('arg', 234), ('b', 321)]

    >>> class Class2(object):
    ...     def method(self, arg, arg2): return arg, arg2

    >>> cy_call_kw_and_starstarargs(Class2().method, arg1=123, arg2=321)
    (123, 321)
    """
    return (f or py_call_starstarargs)(arg=arg1, **kw)


def cy_call_pos_and_starstarargs(f=None, arg1=None, **kw):
    """
    >>> cy_call_pos_and_starstarargs(arg=123)
    ((None,), [('arg', 123)])
    >>> cy_call_pos_and_starstarargs(arg1=123)
    ((123,), [])
    >>> cy_call_pos_and_starstarargs(arg=123, arg2=321)
    ((None,), [('arg', 123), ('arg2', 321)])
    >>> cy_call_pos_and_starstarargs(arg1=123, arg2=321)
    ((123,), [('arg2', 321)])

    >>> class Class2(object):
    ...     def method(self, arg, arg2=None): return arg, arg2

    >>> cy_call_pos_and_starstarargs(Class2().method, 123)
    (123, None)
    >>> cy_call_pos_and_starstarargs(Class2().method, 123, arg2=321)
    (123, 321)
    >>> cy_call_pos_and_starstarargs(Class2().method, arg1=123, arg2=321)
    (123, 321)
    >>> cy_call_pos_and_starstarargs(Class2.method, Class2(), arg=123)
    (123, None)
    >>> cy_call_pos_and_starstarargs(Class2.method, Class2(), arg=123, arg2=321)
    (123, 321)
    >>> cy_call_pos_and_starstarargs(Class2.method, arg1=Class2(), arg=123, arg2=321)
    (123, 321)
    """
    return (f or py_call_args_and_starstarargs)(arg1, **kw)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/callargs.pyx0000644000175100001770000001155300000000000020101 0ustar00runnerdocker00000000000000# mode: run
# tag: call


def func0():
    """
    >>> func0()
    """


def onearg(arg):
    """
    >>> onearg(None)
    None
    """
    print(arg)


def onearg_unused(arg):
    """
    >>> onearg_unused(None)
    """


def c(a=10, b=20, **kwds):
    """
    >>> c()
    10 20 0
    >>> c(1)
    1 20 0
    >>> c(1,2)
    1 2 0
    >>> c(key=None)
    10 20 1
    >>> c(1, key=None)
    1 20 1
    >>> c(1,2, key=None)
    1 2 1
    """
    print a, b, len(kwds)

def d(a, b=1, *args, **kwds):
    """
    >>> d()
    Traceback (most recent call last):
    TypeError: d() takes at least 1 positional argument (0 given)
    >>> d(1)
    1 1 0 0
    >>> d(1,2)
    1 2 0 0
    >>> d(1,2,3)
    1 2 1 0
    >>> d(key=None)
    Traceback (most recent call last):
    TypeError: d() takes at least 1 positional argument (0 given)
    >>> d(1, key=None)
    1 1 0 1
    >>> d(1,2, key=None)
    1 2 0 1
    >>> d(1,2,3, key=None)
    1 2 1 1
    """
    print a, b, len(args), len(kwds)


def e(*args, **kwargs):
    """
    >>> e()
    0 0
    >>> e(1)
    1 0
    >>> e(1,2)
    2 0
    >>> e(1,2)
    2 0
    >>> e(a=4)
    0 1
    >>> e(a=4, b=5)
    0 2
    >>> e(1,2, x=5)
    2 1
    """
    print len(args), len(kwargs)


def args_kwargs_unused(*args, **kwargs):
    """
    >>> args_kwargs_unused()
    >>> args_kwargs_unused(1, 2, 3)
    >>> args_kwargs_unused(x=5)
    >>> args_kwargs_unused(1, 2, 3, x=5)
    """


def args_kwargs_unused_args(*args, **kwargs):
    """
    >>> args_kwargs_unused_args()
    0
    >>> args_kwargs_unused_args(1, 2, 3)
    0
    >>> args_kwargs_unused_args(x=5)
    1
    >>> args_kwargs_unused_args(1, 2, 3, x=5)
    1
    >>> args_kwargs_unused_args(1, 2, 3, x=5, y=4)
    2
    """
    return len(kwargs)


def args_kwargs_unused_kwargs(*args, **kwargs):
    """
    >>> args_kwargs_unused_kwargs()
    0
    >>> args_kwargs_unused_kwargs(1, 2, 3)
    3
    >>> args_kwargs_unused_kwargs(x=5)
    0
    >>> args_kwargs_unused_kwargs(1, 2, 3, x=5)
    3
    """
    return len(args)


def f(*args):
    """
    >>> f(1,2, d=5)
    Traceback (most recent call last):
    TypeError: f() got an unexpected keyword argument 'd'
    >>> f(1, d=5)
    Traceback (most recent call last):
    TypeError: f() got an unexpected keyword argument 'd'
    >>> f(d=5)
    Traceback (most recent call last):
    TypeError: f() got an unexpected keyword argument 'd'
    """
    print len(args)

def g(**kwargs):
    """
    >>> g(1,2, d=5)
    Traceback (most recent call last):
    TypeError: g() takes exactly 0 positional arguments (2 given)
    >>> g(1,2)
    Traceback (most recent call last):
    TypeError: g() takes exactly 0 positional arguments (2 given)
    >>> g(1)
    Traceback (most recent call last):
    TypeError: g() takes exactly 0 positional arguments (1 given)
    """
    print len(kwargs)

def h(a, b, c, *args, **kwargs):
    """
    >>> h(1,2, d=5)
    Traceback (most recent call last):
    TypeError: h() takes at least 3 positional arguments (2 given)
    """
    print a, b, c, u'*', len(args), len(kwargs)

args = (9,8,7)

import sys
if sys.version_info[0] >= 3:
    kwargs = {u"test" : u"toast"}
else:
    kwargs = {"test" : u"toast"}

def test_kw_args(f):
    """
    >>> test_kw_args(h)
    1 2 3 * 0 0
    1 2 9 * 2 1
    1 2 7 * 2 1
    1 2 9 * 2 2
    1 2 9 * 2 2
    1 2 9 * 2 3
    >>> test_kw_args(e)
    2 1
    5 1
    5 1
    5 2
    5 2
    5 3
    """
    f(1,2, c=3)
    f(1,2, d=3, *args)
    f(1,2, d=3, *(7,8,9))
    f(1,2, d=3, *args, **kwargs)
    f(1,2, d=3, *args, e=5)
    f(1,2, d=3, *args, e=5, **kwargs)

def test_pos_args(f):
    """
    >>> test_pos_args(h)
    1 2 3 * 0 0
    1 2 9 * 2 0
    1 2 7 * 2 0
    9 8 7 * 0 0
    7 8 9 * 0 0
    >>> test_pos_args(f)
    3
    5
    5
    3
    3
    """
    f(1,2,3)
    f(1,2, *args)
    f(1,2, *(7,8,9))
    f(*args)
    f(*(7,8,9))

def test_kw(f):
    """
    >>> test_kw(e)
    0 1
    0 2
    0 2
    0 1
    >>> test_kw(g)
    1
    2
    2
    1
    """
    f(c=3)
    f(d=3, e=5)
    f(d=3, **kwargs)
    f(**kwargs)

def test_noargs(f):
    """
    >>> test_noargs(e)
    0 0
    >>> test_noargs(f)
    0
    >>> test_noargs(g)
    0

    # and some errors:
    >>> test_noargs(h)
    Traceback (most recent call last):
    TypeError: h() takes at least 3 positional arguments (0 given)
    """
    f()

def test_int_kwargs(f):
    """
    >>> test_int_kwargs(e)     # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...keywords must be strings...
    >>> test_int_kwargs(f)     # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...keywords must be strings...
    >>> test_int_kwargs(g)     # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...keywords must be strings...
    >>> test_int_kwargs(h)     # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...keywords must be strings...
    """
    f(a=1,b=2,c=3, **{10:20,30:40})
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/capiimpl.pyx0000644000175100001770000000156700000000000020113 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> import sys
>>> sys.getrefcount(Foo.__pyx_vtable__)
2
>>> sys.getrefcount(__pyx_capi__['bar'])
2
>>> sys.getrefcount(__pyx_capi__['spam'])
2
>>> sys.getrefcount(__pyx_capi__['ten'])
2
>>> sys.getrefcount(__pyx_capi__['pi'])
2
>>> sys.getrefcount(__pyx_capi__['obj'])
2
>>> sys.getrefcount(__pyx_capi__['dct'])
2
>>> sys.getrefcount(__pyx_capi__['tpl'])
2
>>> sys.getrefcount(__pyx_capi__['one'])
2
>>> sys.getrefcount(__pyx_capi__['two'])
Traceback (most recent call last):
  ...
KeyError: 'two'
"""

cdef public api class Foo [type FooType, object FooObject]:
    cdef void bar(self):
        pass

cdef public api void bar():
    pass
cdef api void spam():
    pass

cdef api int    ten = 10
cdef api double pi = 3.14
cdef api object obj = object()
cdef api dict   dct = {}

cdef public api tuple tpl = ()
cdef public api float one = 1
cdef public     float two = 2

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/carray_coercion.pyx0000644000175100001770000002566100000000000021460 0ustar00runnerdocker00000000000000# mode: run

import sys
IS_PY3 = sys.version_info[0] >= 3
IS_32BIT_PY2 = not IS_PY3 and sys.maxint < 2**32


from libc cimport stdint
from libc.stdint cimport int16_t as my_int16_t


def unlongify(v):
    # on 32bit Py2.x platforms, 'unsigned int' coerces to a Python long => fix doctest output here.
    s = repr(v)
    if IS_32BIT_PY2:
        assert s.count('L') == s.count(',') + 1, s
        s = s.replace('L', '')
    return s


def from_int_array():
    """
    >>> from_int_array()
    [1, 2, 3]
    """
    cdef int[3] v
    v[0] = 1
    v[1] = 2
    v[2] = 3
    return v


cpdef tuple tuple_from_int_array():
    """
    >>> tuple_from_int_array()
    (1, 2, 3)
    """
    cdef int[3] v
    v[0] = 1
    v[1] = 2
    v[2] = 3
    assert isinstance(v, tuple)
    return v


cdef extern from "stdint.h":
    ctypedef unsigned long uint32_t


def from_typedef_int_array():
    """
    >>> unlongify(from_typedef_int_array())
    '[1, 2, 3]'
    """
    cdef uint32_t[3] v
    v[0] = 1
    v[1] = 2
    v[2] = 3
    return v


cpdef tuple tuple_from_typedef_int_array():
    """
    >>> unlongify(tuple_from_typedef_int_array())
    '(1, 2, 3)'
    """
    cdef uint32_t[3] v
    v[0] = 1
    v[1] = 2
    v[2] = 3
    return v


def from_cimported_int_array():
    """
    >>> from_cimported_int_array()
    [1, 2, 3]
    """
    cdef stdint.int32_t[3] v
    v[0] = 1
    v[1] = 2
    v[2] = 3
    return v


def from_cimported_as_int_array():
    """
    >>> from_cimported_as_int_array()
    [1, 2, 3]
    """
    cdef my_int16_t[3] v
    v[0] = 1
    v[1] = 2
    v[2] = 3
    return v


def from_int_array_array():
    """
    >>> from_int_array_array()
    [[11, 12, 13], [21, 22, 23]]
    """
    cdef int[2][3] v
    v[0][0] = 11
    v[0][1] = 12
    v[0][2] = 13
    v[1][0] = 21
    v[1][1] = 22
    v[1][2] = 23
    return v


def assign_int_array_array():
    """
    >>> assign_int_array_array()
    [[11, 12, 13], [21, 22, 23]]
    """
    cdef int[2][3] v = [[11, 12, 13], [21, 22, 23]]
    return v


def assign_int_array_array_from_tuples():
    """
    >>> assign_int_array_array_from_tuples()
    [[11, 12, 13], [21, 22, 23]]
    """
    cdef int[2][3] v = ([11, 12, 13], [21, 22, 23])
    return v


''' FIXME: this currently crashes:
def assign_int_array_array_from_tuples():
    """
    >>> assign_int_array_array_from_tuples()
    [[11, 12, 13], [21, 22, 23]]
    """
    cdef int[2][3] v = ((11, 12, 13), (21, 22, 23))
    return v
'''


def build_from_list_of_arrays():
    """
    >>> build_from_list_of_arrays()
    [[11, 12, 13], [21, 22, 23]]
    """
    cdef int[3] x = [11, 12, 13]
    cdef int[3] y = [21, 22, 23]
    cdef int[2][3] v = [x, y]
    return v


def build_from_tuple_of_arrays():
    """
    >>> build_from_tuple_of_arrays()
    [[11, 12, 13], [21, 22, 23]]
    """
    cdef int[3] x = [11, 12, 13]
    cdef int[3] y = [21, 22, 23]
    cdef int[2][3] v = (x, y)
    return v


ctypedef struct MyStructType:
    int x
    double y


cdef struct MyStruct:
    int x
    double y


def from_struct_array():
    """
    >>> a, b = from_struct_array()
    >>> a['x'], a['y']
    (1, 2.0)
    >>> b['x'], b['y']
    (3, 4.0)
    """
    cdef MyStructType[2] v
    cdef MyStruct[2] w
    v[0] = MyStructType(1, 2)
    v[1] = MyStructType(3, 4)
    assert isinstance(v, tuple)
    assert isinstance(v, list)

    w[0] = MyStruct(1, 2)
    w[1] = MyStruct(3, 4)
    assert (w) == v
    assert w == (v)

    return v


def to_int_array(x):
    """
    >>> to_int_array([1, 2, 3])
    (1, 2, 3)
    >>> to_int_array([1, 2])
    Traceback (most recent call last):
    IndexError: not enough values found during array assignment, expected 3, got 2
    >>> to_int_array([1, 2, 3, 4])
    Traceback (most recent call last):
    IndexError: too many values found during array assignment, expected 3
    """
    cdef int[3] v = x
    return v[0], v[1], v[2]


def to_int_array_array(x):
    """
    >>> to_int_array_array([[1, 2, 3], [4, 5, 6]])
    (1, 2, 3, 4, 5, 6)
    >>> to_int_array_array(iter([[1, 2, 3], [4, 5, 6]]))
    (1, 2, 3, 4, 5, 6)

    >>> to_int_array_array([[1, 2, 3]])
    Traceback (most recent call last):
    IndexError: not enough values found during array assignment, expected 2, got 1
    >>> to_int_array_array(iter([[1, 2, 3]]))
    Traceback (most recent call last):
    IndexError: not enough values found during array assignment, expected 2, got 1

    >>> to_int_array_array([[1, 2, 3], [4, 5]])
    Traceback (most recent call last):
    IndexError: not enough values found during array assignment, expected 3, got 2
    >>> to_int_array_array(iter([[1, 2, 3], [4, 5]]))
    Traceback (most recent call last):
    IndexError: not enough values found during array assignment, expected 3, got 2

    >>> to_int_array_array([[1, 2, 3, 4], [5, 6, 7]])
    Traceback (most recent call last):
    IndexError: too many values found during array assignment, expected 3
    >>> to_int_array_array(iter([[1, 2, 3, 4], [5, 6, 7]]))
    Traceback (most recent call last):
    IndexError: too many values found during array assignment, expected 3
    """
    cdef int[2][3] v = x
    return v[0][0], v[0][1], v[0][2], v[1][0], v[1][1], v[1][2]


'''
# FIXME: this isn't currently allowed
cdef enum:
    SIZE_A = 2
    SIZE_B = 3

def to_int_array_array_enumsize(x):
    """
    >>> to_int_array_array([[1, 2, 3], [4, 5, 6]])
    (1, 2, 3, 4, 5, 6)
    >>> to_int_array_array(iter([[1, 2, 3], [4, 5, 6]]))
    (1, 2, 3, 4, 5, 6)
    >>> to_int_array([1, 2])
    Traceback (most recent call last):
    IndexError: not enough values found during array assignment, expected 3, got 2
    >>> to_int_array([1, 2, 3, 4])
    Traceback (most recent call last):
    IndexError: too many values found during array assignment, expected 3
    """
    cdef int[SIZE_A][SIZE_B] v = x
    return v[0][0], v[0][1], v[0][2], v[1][0], v[1][1], v[1][2]
'''


'''
# FIXME: this isn't currently supported
def array_as_argument(int[2] x):
    """
    >>> array_as_argument([1, 2])
    (1, 2)
    """
    return x[0], x[1]
'''


def to_int_array_slice(x):
    """
    >>> to_int_array_slice([1, 2, 3])
    (1, 2, 3)
    >>> to_int_array_slice([1, 2])
    Traceback (most recent call last):
    IndexError: not enough values found during array assignment, expected 3, got 2
    >>> to_int_array_slice([1, 2, 3, 4])
    Traceback (most recent call last):
    IndexError: too many values found during array assignment, expected 3
    """
    cdef int[3] v
    v[:] = x[:3]
    assert v[0] == x[0]
    assert v[1] == x[1]
    assert v[2] == x[2]
    v[:3] = [0, 0, 0]
    assert v[0] == 0
    assert v[1] == 0
    assert v[2] == 0
    v[:] = x
    return v[0], v[1], v[2]


def iterable_to_int_array(x):
    """
    >>> iterable_to_int_array(iter([1, 2, 3]))
    (1, 2, 3)
    >>> iterable_to_int_array(iter([1, 2]))
    Traceback (most recent call last):
    IndexError: not enough values found during array assignment, expected 3, got 2
    >>> iterable_to_int_array(iter([1, 2, 3, 4]))
    Traceback (most recent call last):
    IndexError: too many values found during array assignment, expected 3
    """
    cdef int[3] v
    v[:] = x
    return v[0], v[1], v[2]


def to_struct_array(x):
    """
    >>> a, b = to_struct_array(({'x': 1, 'y': 2}, {'x': 3, 'y': 4}))
    >>> a['x'], a['y']
    (1, 2.0)
    >>> b['x'], b['y']
    (3, 4.0)
    """
    cdef MyStructType[2] v
    v[:] = x

    cdef MyStruct[2] w
    w[:] = x

    assert w[0].x == v[0].x
    assert w[0].y == v[0].y
    assert w[1].x == v[1].x
    assert w[1].y == v[1].y

    return v[0], w[1]


def to_struct_array_array(x):
    """
    >>> (a1, a2, a3), (b1, b2, b3) = to_struct_array_array([
    ...     ({'x': 11, 'y': 12}, {'x': 13, 'y': 14}, {'x': 15, 'y': 16}),
    ...     ({'x': 21, 'y': 22}, {'x': 23, 'y': 24}, {'x': 25, 'y': 26}),
    ... ])
    >>> a1['x'], a1['y']
    (11, 12.0)
    >>> b3['x'], b3['y']
    (25, 26.0)
    """
    cdef MyStructType[2][3] v = x
    return v[0], v[1]


cdef struct StructWithArray:
    int a
    MyStruct[2] b


def to_struct_with_array(x):
    """
    >>> x, y = to_struct_with_array([
    ...     {'a': 11, 'b': [{'x': 12, 'y': 13}, {'x': 14, 'y': 15}]},
    ...     {'a': 21, 'b': [{'x': 22, 'y': 23}, {'x': 24, 'y': 25}]},
    ... ])
    >>> x['a'], y['a']
    (11, 21)
    >>> sorted(sorted(v.items()) for v in x['b'])
    [[('x', 12), ('y', 13.0)], [('x', 14), ('y', 15.0)]]
    >>> sorted(sorted(v.items()) for v in y['b'])
    [[('x', 22), ('y', 23.0)], [('x', 24), ('y', 25.0)]]

    >>> x, y = to_struct_with_array(iter([
    ...     {'a': 11, 'b': iter([{'x': 12, 'y': 13}, {'x': 14, 'y': 15}])},
    ...     {'a': 21, 'b': iter([{'x': 22, 'y': 23}, {'x': 24, 'y': 25}])},
    ... ]))
    >>> x['a'], y['a']
    (11, 21)
    >>> sorted(sorted(v.items()) for v in x['b'])
    [[('x', 12), ('y', 13.0)], [('x', 14), ('y', 15.0)]]
    >>> sorted(sorted(v.items()) for v in y['b'])
    [[('x', 22), ('y', 23.0)], [('x', 24), ('y', 25.0)]]
    """
    cdef StructWithArray[2] v
    v = x
    return v


def to_struct_with_array_slice(x):
    """
    >>> x, y = to_struct_with_array_slice([
    ...     {'a': 11, 'b': [{'x': 12, 'y': 13}, {'x': 14, 'y': 15}]},
    ...     {'a': 21, 'b': [{'x': 22, 'y': 23}, {'x': 24, 'y': 25}]},
    ... ])
    >>> x['a'], y['a']
    (11, 21)
    >>> sorted(sorted(v.items()) for v in x['b'])
    [[('x', 12), ('y', 13.0)], [('x', 14), ('y', 15.0)]]
    >>> sorted(sorted(v.items()) for v in y['b'])
    [[('x', 22), ('y', 23.0)], [('x', 24), ('y', 25.0)]]

    >>> x, y = to_struct_with_array_slice(iter([
    ...     {'a': 11, 'b': iter([{'x': 12, 'y': 13}, {'x': 14, 'y': 15}])},
    ...     {'a': 21, 'b': iter([{'x': 22, 'y': 23}, {'x': 24, 'y': 25}])},
    ... ]))
    >>> x['a'], y['a']
    (11, 21)
    >>> sorted(sorted(v.items()) for v in x['b'])
    [[('x', 12), ('y', 13.0)], [('x', 14), ('y', 15.0)]]
    >>> sorted(sorted(v.items()) for v in y['b'])
    [[('x', 22), ('y', 23.0)], [('x', 24), ('y', 25.0)]]
    """
    cdef StructWithArray[2] v
    v[:] = x
    return v


'''
# FIXME: this isn't currently allowed
def to_struct_with_array_slice_end(x):
    """
    >>> to_struct_with_array_slice_end([
    ...     {'a': 11, 'b': [{'x': 12, 'y': 13}, {'x': 14, 'y': 15}]},
    ... ])
    [{'a': 11, 'b': [{'y': 13.0, 'x': 12}, {'y': 15.0, 'x': 14}]}]
    >>> to_struct_with_array_slice_end(iter([
    ...     {'a': 11, 'b': iter([{'x': 12, 'y': 13}, {'x': 14, 'y': 15}])},
    ... ]))
    [{'a': 11, 'b': [{'y': 13.0, 'x': 12}, {'y': 15.0, 'x': 14}]}]
    >>> to_struct_with_array_slice_end(iter([
    ...     {'a': 11, 'b': iter([{'x': 12, 'y': 13}, {'x': 14, 'y': 15}])},
    ...     {'a': 21, 'b': iter([{'x': 22, 'y': 23}, {'x': 24, 'y': 25}])},
    ... ]))
    Traceback (most recent call last):
    IndexError: too many values found during array assignment, expected 1
    """
    cdef StructWithArray[2] v
    v[:1] = x
    return v


def to_int_array_slice_start_end(x):
    """
    >>> to_int_array_slice_start_end([1, 2, 3])
    (1, 2, 3, 2, 3)
    """
    cdef int[5] v
    v[2:] = x
    v[:3] = x
    return v[0], v[1], v[2], v[3], v[4]
'''
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/carray_slicing.pyx0000644000175100001770000002224400000000000021301 0ustar00runnerdocker00000000000000
cimport cython

############################################################
# tests for char* slicing

cdef char* cstring = "abcABCqtp"

def slice_charptr_end():
    """
    >>> print(str(slice_charptr_end()).replace("b'", "'"))
    ('a', 'abc', 'abcABCqtp')
    """
    return cstring[:1], cstring[:3], cstring[:9]

#### BROKEN: this test assumes that the result of a char* iteration
#### becomes a bytes object, which is not the case when applying
#### carray iteration.  Contradiction.
##
## @cython.test_assert_path_exists("//ForFromStatNode",
##                                 "//ForFromStatNode//SliceIndexNode")
## @cython.test_fail_if_path_exists("//ForInStatNode")
## def slice_charptr_for_loop_py():
##     """
##     >>> slice_charptr_for_loop_py()
##     ['a', 'b', 'c']
##     ['b', 'c', 'A', 'B']
##     ['B', 'C', 'q', 't', 'p']
##     """
##     print str([ c for c in cstring[:3] ]).replace(" b'", " '").replace("[b'", "['")
##     print str([ c for c in cstring[1:5] ]).replace(" b'", " '").replace("[b'", "['")
##     print str([ c for c in cstring[4:9] ]).replace(" b'", " '").replace("[b'", "['")

@cython.test_assert_path_exists("//ForFromStatNode",
                                "//ForFromStatNode//IndexNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def slice_charptr_for_loop_c():
    """
    >>> slice_charptr_for_loop_c()
    ['a', 'b', 'c']
    ['a', 'b', 'c']
    ['b', 'c', 'A', 'B']
    ['B', 'C', 'q', 't', 'p']
    """
    cdef char c
    print [ chr(c) for c in cstring[:3] ]
    print [ chr(c) for c in cstring[None:3] ]
    print [ chr(c) for c in cstring[1:5] ]
    print [ chr(c) for c in cstring[4:9] ]

#@cython.test_assert_path_exists("//ForFromStatNode",
#                                "//ForFromStatNode//IndexNode")
#@cython.test_fail_if_path_exists("//ForInStatNode")
def slice_charptr_for_loop_c_to_bytes():
    """
    >>> slice_charptr_for_loop_c_to_bytes()
    ['a', 'b', 'c']
    ['a', 'b', 'c']
    ['b', 'c', 'A', 'B']
    ['B', 'C', 'q', 't', 'p']
    """
    cdef bytes b
    print str([ b for b in cstring[:3] ]).replace(" b'", " '").replace("[b'", "['")
    print str([ b for b in cstring[None:3] ]).replace(" b'", " '").replace("[b'", "['")
    print str([ b for b in cstring[1:5] ]).replace(" b'", " '").replace("[b'", "['")
    print str([ b for b in cstring[4:9] ]).replace(" b'", " '").replace("[b'", "['")

@cython.test_assert_path_exists("//ForFromStatNode",
                                "//ForFromStatNode//IndexNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def slice_charptr_for_loop_c_step():
    """
    >>> slice_charptr_for_loop_c_step()
    Acba ['A', 'c', 'b', 'a']
    Acba ['A', 'c', 'b', 'a']
    bA ['b', 'A']
    acB ['a', 'c', 'B']
    acB ['a', 'c', 'B']
     []
    ptqC ['p', 't', 'q', 'C']
    pq ['p', 'q']
    """
    cdef object ustring = cstring.decode('ASCII')
    cdef char c
    print ustring[3::-1],     [ chr(c) for c in cstring[3::-1] ]
    print ustring[3:None:-1], [ chr(c) for c in cstring[3:None:-1] ]
    print ustring[1:5:2],     [ chr(c) for c in cstring[1:5:2] ]
    print ustring[:5:2],      [ chr(c) for c in cstring[:5:2] ]
    print ustring[None:5:2],  [ chr(c) for c in cstring[None:5:2] ]
    print ustring[4:9:-1],    [ chr(c) for c in cstring[4:9:-1] ]
    print ustring[8:4:-1],    [ chr(c) for c in cstring[8:4:-1] ]
    print ustring[8:4:-2],    [ chr(c) for c in cstring[8:4:-2] ]

@cython.test_assert_path_exists("//ForFromStatNode",
                                "//ForFromStatNode//IndexNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def slice_charptr_for_loop_c_dynamic_bounds():
    """
    >>> slice_charptr_for_loop_c_dynamic_bounds()
    ['a', 'b', 'c']
    ['a', 'b', 'c']
    ['b', 'c', 'A', 'B']
    ['B', 'C', 'q', 't', 'p']
    """
    cdef char c
    print [ chr(c) for c in cstring[0:return3()] ]
    print [ chr(c) for c in cstring[None:return3()] ]
    print [ chr(c) for c in cstring[return1():return5()] ]
    print [ chr(c) for c in cstring[return4():return9()] ]

cdef return1(): return 1
cdef return3(): return 3
cdef return4(): return 4
cdef return5(): return 5
cdef return9(): return 9

#### BROKEN: this test assumes that the result of a char* iteration
#### becomes a bytes object, which is not the case when applying
#### carray iteration.  Contradiction.
##
## @cython.test_assert_path_exists("//ForFromStatNode",
##                                 "//ForFromStatNode//SliceIndexNode")
## @cython.test_fail_if_path_exists("//ForInStatNode")
## def slice_charptr_for_loop_py_enumerate():
##     """
##     >>> slice_charptr_for_loop_py_enumerate()
##     [(0, 'a'), (1, 'b'), (2, 'c')]
##     [(0, 'b'), (1, 'c'), (2, 'A'), (3, 'B')]
##     [(0, 'B'), (1, 'C'), (2, 'q'), (3, 't'), (4, 'p')]
##     """
##     print str([ (i,c) for i,c in enumerate(cstring[:3]) ]).replace(" b'", " '")
##     print str([ (i,c) for i,c in enumerate(cstring[1:5]) ]).replace(" b'", " '")
##     print str([ (i,c) for i,c in enumerate(cstring[4:9]) ]).replace(" b'", " '")

@cython.test_assert_path_exists("//ForFromStatNode",
                                "//ForFromStatNode//IndexNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def slice_charptr_for_loop_c_enumerate():
    """
    >>> slice_charptr_for_loop_c_enumerate()
    [(0, 97), (1, 98), (2, 99)]
    [(0, 97), (1, 98), (2, 99)]
    [(0, 98), (1, 99), (2, 65), (3, 66)]
    [(0, 66), (1, 67), (2, 113), (3, 116), (4, 112)]
    """
    cdef int c,i
    print [ (i,c) for i,c in enumerate(cstring[:3]) ]
    print [ (i,c) for i,c in enumerate(cstring[None:3]) ]
    print [ (i,c) for i,c in enumerate(cstring[1:5]) ]
    print [ (i,c) for i,c in enumerate(cstring[4:9]) ]


############################################################
# tests for int* slicing

cdef int[6] cints
for i in range(6):
    cints[i] = i

@cython.test_assert_path_exists("//ForFromStatNode",
                                "//ForFromStatNode//IndexNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def slice_intarray_for_loop_c():
    """
    >>> slice_intarray_for_loop_c()
    [0, 1, 2]
    [0, 1, 2]
    [1, 2, 3, 4]
    [4, 5]
    """
    cdef int i
    print [ i for i in cints[:3] ]
    print [ i for i in cints[None:3] ]
    print [ i for i in cints[1:5] ]
    print [ i for i in cints[4:6] ]

@cython.test_assert_path_exists("//ForFromStatNode",
                                "//ForFromStatNode//IndexNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def iter_intarray_for_loop_c():
    """
    >>> iter_intarray_for_loop_c()
    [0, 1, 2, 3, 4, 5]
    """
    cdef int i
    print [ i for i in cints ]

@cython.test_assert_path_exists("//ForFromStatNode",
                                "//ForFromStatNode//IndexNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def slice_intptr_for_loop_c():
    """
    >>> slice_intptr_for_loop_c()
    [0, 1, 2]
    [0, 1, 2]
    [1, 2, 3, 4]
    [4, 5]
    """
    cdef int* nums = cints
    cdef int i
    print [ i for i in nums[:3] ]
    print [ i for i in nums[None:3] ]
    print [ i for i in nums[1:5] ]
    print [ i for i in nums[4:6] ]


############################################################
# tests for slicing other arrays

cdef double[6] cdoubles
for i in range(6):
    cdoubles[i] = i + 0.5

cdef double* cdoubles_ptr = cdoubles

@cython.test_assert_path_exists("//ForFromStatNode",
                                "//ForFromStatNode//IndexNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def slice_doublptr_for_loop_c():
    """
    >>> slice_doublptr_for_loop_c()
    [0.5, 1.5, 2.5]
    [0.5, 1.5, 2.5]
    [1.5, 2.5, 3.5, 4.5]
    [4.5, 5.5]
    """
    cdef double d
    print [ d for d in cdoubles_ptr[:3] ]
    print [ d for d in cdoubles_ptr[None:3] ]
    print [ d for d in cdoubles_ptr[1:5] ]
    print [ d for d in cdoubles_ptr[4:6] ]

## @cython.test_assert_path_exists("//ForFromStatNode",
##                                 "//ForFromStatNode//IndexNode")
## @cython.test_fail_if_path_exists("//ForInStatNode")
## def slice_doublptr_for_loop_c_step():
##     """
##     >>> slice_doublptr_for_loop_c_step()
##     """
##     cdef double d
##     print [ d for d in cdoubles_ptr[:3:1] ]
##     print [ d for d in cdoubles_ptr[5:1:-1] ]
##     print [ d for d in cdoubles_ptr[:2:-2] ]
##     print [ d for d in cdoubles_ptr[4:6:2] ]
##     print [ d for d in cdoubles_ptr[4:6:-2] ]

@cython.test_assert_path_exists("//ForFromStatNode",
                                "//ForFromStatNode//IndexNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def iter_doublearray_for_loop_c():
    """
    >>> iter_doublearray_for_loop_c()
    [0.5, 1.5, 2.5, 3.5, 4.5, 5.5]
    """
    cdef double d
    print [ d for d in cdoubles ]


cdef struct MyStruct:
    int i

@cython.test_assert_path_exists("//ForFromStatNode",
                                "//ForFromStatNode//IndexNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def struct_ptr_iter():
    """
    >>> struct_ptr_iter()
    ([0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4])
    """
    cdef MyStruct[5] my_structs
    for i in range(5):
        my_structs[i].i = i
    cdef MyStruct value
    cdef MyStruct *ptr
    return ([ value.i for value in my_structs[:5] ],
            [ ptr.i for ptr in my_structs[:5] ],
            [ inferred.i for inferred in my_structs[:5] ])
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/carrays.pyx0000644000175100001770000000176200000000000017756 0ustar00runnerdocker00000000000000def test1():
    """
    >>> test1()
    2
    """
    cdef int[2][2] x
    x[0][0] = 1
    x[0][1] = 2
    x[1][0] = 3
    x[1][1] = 4
    return f(x)[1]

cdef int* f(int x[2][2]):
    return x[0]


def assign_index_in_loop():
    """
    >>> assign_index_in_loop()
    2
    """
    cdef int i = 0
    cdef int[1] a
    cdef int[1] b
    for a[0], b[0] in enumerate(range(3)):
        assert a[0] == b[0]
        assert a[0] == i
        i += 1

    assert a[0] == b[0]
    return b[0]


def test2():
    """
    >>> test2()
    0
    """
    cdef int[5] a1
    cdef int a2[2+3]
    return sizeof(a1) - sizeof(a2)

cdef enum:
    MY_SIZE_A = 2
    MY_SIZE_B = 3

def test3():
    """
    >>> test3()
    (2, 3)
    """
    cdef int a[MY_SIZE_A]
    cdef int b[MY_SIZE_B]
    return sizeof(a)/sizeof(int), sizeof(b)/sizeof(int)


from libc cimport limits

def test_cimported_attribute():
    """
    >>> test_cimported_attribute()
    True
    """
    cdef char a[limits.CHAR_MAX]
    return sizeof(a) >= 127
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cascaded_list_unpacking_T467.pyx0000644000175100001770000000436400000000000023660 0ustar00runnerdocker00000000000000# ticket: t467

def simple_parallel_assignment_from_call():
    """
    >>> simple_parallel_assignment_from_call()
    (2, 1, 2, 1, 2, 1, 2, [1, 2], [1, 2])
    """
    cdef int ai, bi
    cdef long al, bl
    cdef object ao, bo
    reset()
    ai, bi = al, bl = ao, bo = c = d = [intval(1), intval(2)]
    return call_count, ao, bo, ai, bi, al, bl, c, d

def recursive_parallel_assignment_from_call_left():
    """
    >>> recursive_parallel_assignment_from_call_left()
    (3, 1, 2, 3, 1, 2, 3, (1, 2), 3, [(1, 2), 3])
    """
    cdef int ai, bi, ci
    cdef object ao, bo, co
    reset()
    (ai, bi), ci = (ao, bo), co = t,o = d = [(intval(1), intval(2)), intval(3)]
    return call_count, ao, bo, co, ai, bi, ci, t, o, d

def recursive_parallel_assignment_from_call_right():
    """
    >>> recursive_parallel_assignment_from_call_right()
    (3, 1, 2, 3, 1, 2, 3, 1, (2, 3), [1, (2, 3)])
    """
    cdef int ai, bi, ci
    cdef object ao, bo, co
    reset()
    ai, (bi, ci) = ao, (bo, co) = o,t = d = [intval(1), (intval(2), intval(3))]
    return call_count, ao, bo, co, ai, bi, ci, o, t, d

def recursive_parallel_assignment_from_call_left_reversed():
    """
    >>> recursive_parallel_assignment_from_call_left_reversed()
    (3, 1, 2, 3, 1, 2, 3, (1, 2), 3, [(1, 2), 3])
    """
    cdef int ai, bi, ci
    cdef object ao, bo, co
    reset()
    d = t,o = (ao, bo), co = (ai, bi), ci = [(intval(1), intval(2)), intval(3)]
    return call_count, ao, bo, co, ai, bi, ci, t, o, d

def recursive_parallel_assignment_from_call_right_reversed():
    """
    >>> recursive_parallel_assignment_from_call_right_reversed()
    (3, 1, 2, 3, 1, 2, 3, 1, (2, 3), [1, (2, 3)])
    """
    cdef int ai, bi, ci
    cdef object ao, bo, co
    reset()
    d = o,t = ao, (bo, co) = ai, (bi, ci) = [intval(1), (intval(2), intval(3))]
    return call_count, ao, bo, co, ai, bi, ci, o, t, d

cdef int call_count = 0
cdef int next_expected_arg = 1

cdef reset():
    global call_count, next_expected_arg
    call_count = 0
    next_expected_arg = 1

cdef int intval(int x) except -1:
    global call_count, next_expected_arg
    call_count += 1
    assert next_expected_arg == x, "calls not in source code order: expected %d, found %d" % (next_expected_arg, x)
    next_expected_arg += 1
    return x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cascaded_typed_assignments_T466.pyx0000644000175100001770000000461600000000000024405 0ustar00runnerdocker00000000000000# mode: run
# ticket: t466
# extension to T409

cimport cython

def simple_parallel_typed():
    """
    >>> simple_parallel_typed()
    (1, 2, [1, 2], [1, 2])
    """
    cdef int a,c
    a, c = d = e = [1,2]
    return a, c, d, e

def simple_parallel_int_mix():
    """
    >>> simple_parallel_int_mix()
    (1, 2, 1, 2, 1, 2, [1, 2], [1, 2])
    """
    cdef int ai,bi
    cdef long al,bl
    cdef object ao, bo
    ai, bi = al, bl = ao, bo = c = d = [1,2]
    return ao, bo, ai, bi, al, bl, c, d

def simple_parallel_int_mix_recursive():
    """
    >>> simple_parallel_int_mix_recursive()
    (1, 2, 3, 1, [2, 3], 1, 2, 3, 1, 2, 3, [1, [2, 3]], [1, [2, 3]])
    """
    cdef int ai, bi, ci
    cdef long al, bl, cl
    cdef object ao, bo, co
    cdef object xo, yo
    ai, [bi, ci] = al, [bl, cl] = xo, yo = ao, [bo, co] = c = d = [1, [2, 3]]
    return ao, bo, co, xo, yo, ai, bi, ci, al, bl, cl, c, d

cdef int called = 0

cdef char* get_string():
    global called
    called += 1
    return "abcdefg"

def non_simple_rhs():
    """
    >>> non_simple_rhs()
    1
    """
    cdef char *a, *b
    cdef int orig_called = called
    a = b = get_string()
    assert a is b
    return called - orig_called

from libc.stdlib cimport malloc, free

def non_simple_rhs_malloc():
    """
    >>> non_simple_rhs_malloc()
    """
    cdef char *a, *b, **c

    c = &b
    c[0] = a = malloc(2)
    a[0] = c'X'
    b[1] = c'\0'

    # copy from different pointers to make sure they all point to the
    # same memory
    cdef char[2] x
    x[0] = b[0]
    x[1] = a[1]

    # clean up
    free(a)
    if b is not a: # shouldn't happen
        free(b)

    # check copied values
    assert x[0] == c'X'
    assert x[1] == c'\0'

@cython.test_assert_path_exists(
    '//CascadedAssignmentNode',
    '//CascadedAssignmentNode//CoerceToTempNode',
    '//CascadedAssignmentNode//CoerceToTempNode[@type.is_ptr]')
def assign_carray():
    """
    assign_carray()
    (1, 2, 3)
    """
    cdef int *b, *c
    cdef int[3] a
    a[0] = 1
    a[1] = 2
    a[2] = 3

    b = c = a+1
    assert b[0] == 2
    assert c[1] == 3
    return a[0], b[0], c[1]


def pyobject_from_cvalue(table, key):
    """
    >>> table = {'X':0, 'Y':1}
    >>> pyobject_from_cvalue(table, 'Z')
    2
    >>> pyobject_from_cvalue(table, 'X')
    0
    """
    cdef int num
    num = table.get(key, -1)
    if num < 0:
        num = table[key] = len(table)
    return num
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cascadedassignment.pyx0000644000175100001770000000306100000000000022124 0ustar00runnerdocker00000000000000import cython

@cython.test_fail_if_path_exists(
    '//CascadedAssignmentNode//CoerceFromPyTypeNode',
    '//CascadedAssignmentNode//CoerceToPyTypeNode',
)
@cython.test_assert_path_exists('//CascadedAssignmentNode')
def test_cascaded_assignment_simple():
    """
    >>> test_cascaded_assignment_simple()
    5
    """
    a = b = c = 5
    return a

@cython.test_fail_if_path_exists(
    '//CascadedAssignmentNode//CoerceFromPyTypeNode',
    '//CascadedAssignmentNode//CoerceToPyTypeNode',
)
@cython.test_assert_path_exists('//CascadedAssignmentNode')
def test_cascaded_assignment_typed():
    """
    >>> test_cascaded_assignment_typed()
    int Python object double
    (5, 5, 5.0)
    """
    cdef int a
    cdef object b
    cdef double c

    a = b = c = 5

    print cython.typeof(a), cython.typeof(b), cython.typeof(c)
    return a, b, c

def test_cascaded_assignment_builtin_expr():
    """
    This test is useful as previously the rhs expr node got replaced resulting
    in CloneNode generating None in the C source.

    >>> test_cascaded_assignment_builtin_expr()
    (10.0, 10.0, 10.0)
    """
    a = b = c = float(10)
    return a, b, c

def expr():
    print "expr called"
    return 10

def test_cascaded_assignment_evaluate_expr():
    """
    >>> test_cascaded_assignment_evaluate_expr()
    expr called
    (10.0, 10.0, 10.0)
    """
    a = b = c = float(expr())
    return a, b, c


def test_overwrite():
    """
    >>> test_overwrite()
    {0: {1: {2: {}}}}
    """
    x = a = {}
    for i in range(3):
        a[i] = a = {}
    assert a == {}
    return x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cascmp.pyx0000644000175100001770000000457600000000000017566 0ustar00runnerdocker00000000000000# mode: run
# tag: cascade, compare

def ints_and_objects():
    """
    >>> ints_and_objects()
    (0, 1, 0, 1, 1, 0)
    """
    cdef int int1=0, int2=0, int3=0, int4=0
    cdef int r1, r2, r3, r4, r5, r6
    cdef object obj1, obj2, obj3, obj4
    obj1 = 1
    obj2 = 2
    obj3 = 3
    obj4 = 4
    r1 = int1 < int2 < int3
    r2 = obj1 < obj2 < obj3
    r3 = int1 < int2 < obj3
    r4 = obj1 < 2 < 3
    r5 = obj1 < 2 < 3 < 4
    r6 = int1 < (int2 == int3) < int4
    return r1, r2, r3, r4, r5, r6


def const_cascade(x):
    """
    >>> const_cascade(2)
    (True, False, True, False, False, True, False)
    """
    return (
        0 <= 1,
        1 <= 0,
        1 <= 1 <= 2,
        1 <= 0 < 1,
        1 <= 1 <= 0,
        1 <= 1 <= x <= 2 <= 3 > x <= 2 <= 2,
        1 <= 1 <= x <= 1 <= 1 <= x <= 2,
    )

def eq_if_statement(a, b, c):
    """
    >>> eq_if_statement(1, 2, 3)
    False
    >>> eq_if_statement(2, 3, 4)
    False
    >>> eq_if_statement(1, 1, 2)
    False
    >>> eq_if_statement(1, "not an int", 2)
    False
    >>> eq_if_statement(2, 1, 1)
    False
    >>> eq_if_statement(1, 1, 1)
    True
    """
    if 1 == a == b == c:
        return True
    else:
        return False

def eq_if_statement_semi_optimized(a, int b, int c):
    """
    Some but not all of the cascade ends up optimized
    (probably not as much as should be). The test is mostly
    that it keeps the types consistent throughout

    >>> eq_if_statement_semi_optimized(1, 2, 3)
    False
    >>> eq_if_statement_semi_optimized(2, 3, 4)
    False
    >>> eq_if_statement_semi_optimized(1, 1, 2)
    False
    >>> eq_if_statement_semi_optimized("not an int", 1, 2)
    False
    >>> eq_if_statement_semi_optimized(2, 1, 1)
    False
    >>> eq_if_statement_semi_optimized(1, 1, 1)
    True
    """
    if 1 == a == b == c == 1:
        return True
    else:
        return False

def eq_if_statement_semi_optimized2(a, b, c):
    """
    Here only "b==c" fails to optimize

    >>> eq_if_statement_semi_optimized2(1, 2, 3)
    False
    >>> eq_if_statement_semi_optimized2(2, 3, 4)
    False
    >>> eq_if_statement_semi_optimized2(1, 1, 2)
    False
    >>> eq_if_statement_semi_optimized2(1, "not an int", 2)
    False
    >>> eq_if_statement_semi_optimized2(2, 1, 1)
    False
    >>> eq_if_statement_semi_optimized2(1, 1, 1)
    True
    """
    if 1 == a == 1 == b == c:
        return True
    else:
        return False
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cclass_assign_attr_GH3100.pyx0000644000175100001770000000305000000000000023032 0ustar00runnerdocker00000000000000cdef extern from *:
    """
    #ifdef CYTHON_USE_TYPE_SPECS
    #define TYPESPECS 1
    #else
    #define TYPESPECS 0
    #endif
    """
    int TYPESPECS

cdef class Foo:
    """
    >>> D = Foo.__dict__
    >>> D["meth"] is D["meth2"]
    True
    >>> D["classmeth"] is D["classmeth2"]
    True
    >>> D["staticmeth"] is D["staticmeth2"]
    True
    """
    def meth(self): pass
    @classmethod
    def classmeth(cls): pass
    @staticmethod
    def staticmeth(): pass

    meth2 = meth
    classmeth2 = classmeth
    staticmeth2 = staticmeth

cdef class ChangeName:
    # the class seems to need some contents for changing the
    # name to cause a problem
    cdef public str attr1
    cdef public int attr2

if TYPESPECS:
    __doc__ = """
    For typespecs, cdef classes are mutable on some Python versions
    (and it's easiest to leave them that way). Therefore the test
    is just that reassigning the name doesn't cause a crash

    >>> try:
    ...     ChangeName.__name__ = "SomethingElse"
    ... except TypeError:
    ...     pass  # either type error or changing the name is fine
    """
else:
    __doc__ = """
    GH-5079
    Assigning to the cdef class name shouldn't cause a crash.
    The important bit of this test is the not crashing - it's
    possible that typespec/limited-API defined classes will be
    naturally mutable and that isn't a huge problem

    >>> ChangeName.__name__ = "SomethingElse"  # doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    TypeError: ...
    >>> ChangeName.__name__
    'ChangeName'
    """

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_bool_T227.pyx0000644000175100001770000000101300000000000020731 0ustar00runnerdocker00000000000000# ticket: t227

from cpython.bool cimport bool

def foo(bool a):
    """
    >>> foo(True)
    True
    >>> foo(False)
    False
    >>> foo('abc') # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    return a == True

def call_cfoo(a):
    """
    >>> call_cfoo(True)
    True
    >>> call_cfoo(False)
    False
    >>> call_cfoo('abc') # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    return cfoo(a)

cdef cfoo(bool a):
    return a == True
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_class_dataclass.pyx0000644000175100001770000001764700000000000022430 0ustar00runnerdocker00000000000000# mode: run
# tag: dataclass

from cython cimport dataclasses
from cython.dataclasses cimport dataclass, field
try:
    import typing
    from typing import ClassVar
    from dataclasses import InitVar
    import dataclasses as py_dataclasses
except ImportError:
    pass
import cython
from libc.stdlib cimport malloc, free

include "../testsupport/cythonarrayutil.pxi"

cdef class NotADataclass:
    cdef cython.int a
    b: float

    def __repr__(self):
        return "NADC"

    def __str__(self):
        return "string of NotADataclass"  # should not be called - repr is called instead!

    def __eq__(self, other):
        return type(self) == type(other)

    def __hash__(self):
        return 1

@dataclass(unsafe_hash=True)
cdef class BasicDataclass:
    """
    >>> sorted(list(BasicDataclass.__dataclass_fields__.keys()))
    ['a', 'b', 'c', 'd']

    # Check the field type attribute - this is currently a string since
    # it's taken from the annotation, but if we drop PEP563 in future
    # then it may change
    >>> BasicDataclass.__dataclass_fields__["a"].type
    'float'
    >>> BasicDataclass.__dataclass_fields__["b"].type
    'NotADataclass'
    >>> BasicDataclass.__dataclass_fields__["c"].type
    'object'
    >>> BasicDataclass.__dataclass_fields__["d"].type
    'list'

    >>> inst1 = BasicDataclass() # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: __init__() takes at least 1 ...
    >>> inst1 = BasicDataclass(2.0)

    # The error at-least demonstrates that the hash function has been created
    >>> hash(inst1) # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...unhashable...
    >>> inst2 = BasicDataclass(2.0)
    >>> inst1 == inst2
    True
    >>> inst2 = BasicDataclass(2.0, NotADataclass(), [])
    >>> inst1 == inst2
    False
    >>> inst2 = BasicDataclass(2.0, NotADataclass(), [], [1,2,3])
    >>> inst2
    BasicDataclass(a=2.0, b=NADC, c=[], d=[1, 2, 3])
    >>> inst2.c = "Some string"
    >>> inst2
    BasicDataclass(a=2.0, b=NADC, c='Some string', d=[1, 2, 3])
    """
    a: float
    b: NotADataclass = field(default_factory=NotADataclass)
    c: object = field(default=0)
    d: list = dataclasses.field(default_factory=list)

@dataclasses.dataclass
cdef class InheritsFromDataclass(BasicDataclass):
    """
    >>> sorted(list(InheritsFromDataclass.__dataclass_fields__.keys()))
    ['a', 'b', 'c', 'd', 'e']
    >>> InheritsFromDataclass(a=1.0, e=5)
    In __post_init__
    InheritsFromDataclass(a=1.0, b=NADC, c=0, d=[], e=5)
    """
    e: cython.int = 0

    def __post_init__(self):
        print "In __post_init__"

@cython.dataclasses.dataclass
cdef class InheritsFromNotADataclass(NotADataclass):
    """
    >>> sorted(list(InheritsFromNotADataclass.__dataclass_fields__.keys()))
    ['c']
    >>> InheritsFromNotADataclass()
    InheritsFromNotADataclass(c=1)
    >>> InheritsFromNotADataclass(5)
    InheritsFromNotADataclass(c=5)
    """

    c: cython.int = 1

cdef struct S:
    int a

ctypedef S* S_ptr

cdef S_ptr malloc_a_struct():
    return malloc(sizeof(S))

@dataclass
cdef class ContainsNonPyFields:
    """
    >>> ContainsNonPyFields()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: __init__() takes ... 1 positional ...
    >>> ContainsNonPyFields(mystruct={'a': 1 })  # doctest: +ELLIPSIS
    ContainsNonPyFields(mystruct={'a': 1}, memview=)
    >>> ContainsNonPyFields(mystruct={'a': 1 }, memview=create_array((2,2), "c"))  # doctest: +ELLIPSIS
    ContainsNonPyFields(mystruct={'a': 1}, memview=)
    >>> ContainsNonPyFields(mystruct={'a': 1 }, mystruct_ptr=0)
    Traceback (most recent call last):
    TypeError: __init__() got an unexpected keyword argument 'mystruct_ptr'
    """
    mystruct: S = cython.dataclasses.field(compare=False)
    mystruct_ptr: S_ptr = field(init=False, repr=False, default_factory=malloc_a_struct)
    memview: cython.int[:, ::1] = field(default=create_array((3,1), "c"),  # mutable so not great but OK for a test
                                        compare=False)

    def __dealloc__(self):
        free(self.mystruct_ptr)

@dataclass
cdef class InitClassVars:
    """
    Private (i.e. defined with "cdef") members deliberately don't appear
    TODO - ideally c1 and c2 should also be listed here
    >>> sorted(list(InitClassVars.__dataclass_fields__.keys()))
    ['a', 'b1', 'b2']
    >>> InitClassVars.c1
    2.0
    >>> InitClassVars.e1
    []
    >>> inst1 = InitClassVars()
    In __post_init__
    >>> inst1  # init vars don't appear in string
    InitClassVars(a=0)
    >>> inst2 = InitClassVars(b1=5, d2=100)
    In __post_init__
    >>> inst1 == inst2  # comparison ignores the initvar
    True
    """
    a: cython.int = 0
    b1: InitVar[cython.double] = 1.0
    b2: py_dataclasses.InitVar[cython.double] = 1.0
    c1: ClassVar[float] = 2.0
    c2: typing.ClassVar[float] = 2.0
    cdef InitVar[cython.int] d1
    cdef py_dataclasses.InitVar[cython.int] d2
    d1 = 5
    d2 = 5
    cdef ClassVar[list] e1
    cdef typing.ClassVar[list] e2
    e1 = []
    e2 = []

    def __post_init__(self, b1, b2, d1, d2):
         # Check that the initvars haven't been assigned yet
        assert self.b1==0, self.b1
        assert self.b2==0, self.b2
        assert self.d1==0, self.d1
        assert self.d2==0, self.d2
        self.b1 = b1
        self.b2 = b2
        self.d1 = d1
        self.d2 = d2
        print "In __post_init__"

@dataclass
cdef class TestVisibility:
    """
    >>> inst = TestVisibility()
    >>> "a" in TestVisibility.__dataclass_fields__
    False
    >>> hasattr(inst, "a")
    False
    >>> "b" in TestVisibility.__dataclass_fields__
    True
    >>> hasattr(inst, "b")
    True
    >>> "c" in TestVisibility.__dataclass_fields__
    True
    >>> TestVisibility.__dataclass_fields__["c"].type
    'double'
    >>> hasattr(inst, "c")
    True
    >>> "d" in TestVisibility.__dataclass_fields__
    True
    >>> TestVisibility.__dataclass_fields__["d"].type
    'object'
    >>> hasattr(inst, "d")
    True
    """
    cdef double a
    a = 1.0
    b: cython.double = 2.0
    cdef public double c
    c = 3.0
    cdef public object d
    d = object()

@dataclass(frozen=True)
cdef class TestFrozen:
    """
    >>> inst = TestFrozen(a=5)
    >>> inst.a
    5.0
    >>> inst.a = 2.  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    AttributeError: attribute 'a' of '...TestFrozen' objects is not writable
    """
    a: cython.double = 2.0

def get_dataclass_initvar():
    return py_dataclasses.InitVar

  
@dataclass(kw_only=True)
cdef class TestKwOnly:
    """
    >>> inst = TestKwOnly(a=3, b=2)
    >>> inst.a
    3.0
    >>> inst.b
    2
    >>> inst = TestKwOnly(b=2)
    >>> inst.a
    2.0
    >>> inst.b
    2
    >>> fail = TestKwOnly(3, 2)
    Traceback (most recent call last):
    TypeError: __init__() takes exactly 0 positional arguments (2 given)
    >>> fail = TestKwOnly(a=3)
    Traceback (most recent call last):
    TypeError: __init__() needs keyword-only argument b
    >>> fail = TestKwOnly()
    Traceback (most recent call last):
    TypeError: __init__() needs keyword-only argument b
    """

    a: cython.double = 2.0
    b: cython.long


import sys
if sys.version_info >= (3, 7):
    __doc__ = """
    >>> from dataclasses import Field, is_dataclass, fields, InitVar

    # It uses the types from the standard library where available
    >>> all(isinstance(v, Field) for v in BasicDataclass.__dataclass_fields__.values())
    True

    # check out Cython dataclasses are close enough to convince it
    >>> is_dataclass(BasicDataclass)
    True
    >>> is_dataclass(BasicDataclass(1.5))
    True
    >>> is_dataclass(InheritsFromDataclass)
    True
    >>> is_dataclass(NotADataclass)
    False
    >>> is_dataclass(InheritsFromNotADataclass)
    True
    >>> [ f.name for f in fields(BasicDataclass)]
    ['a', 'b', 'c', 'd']
    >>> [ f.name for f in fields(InitClassVars)]
    ['a']
    >>> get_dataclass_initvar() == InitVar
    True
    """
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_class_field.pyx0000644000175100001770000000036000000000000021534 0ustar00runnerdocker00000000000000# mode: run
# tag: exttype
# ticket: t677

"""
>>> str(Foo(4))
'4'
>>> x
3
"""

x = 3
cdef int y

cdef class Foo:
    cdef int x
    cdef int y
    def __init__(self, x):
        self.x = x
    def __str__(self):
        return str(self.x)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_class_order.pyx0000644000175100001770000000120000000000000021556 0ustar00runnerdocker00000000000000cimport cython

cdef class B

cdef class A(object):
    cdef list dealloc1

cdef class Y(X): pass
cdef class X(C): pass
cdef class C: pass

cdef class B(A):
    cdef list dealloc2

cdef class Z(A): pass


def test():
    """
    >>> test()
    A
    B
    C
    X
    Y
    Z
    """
    A(), B(), C(), X(), Y(), Z()
    import sys
    py_version = sys.version_info[:2]
    if py_version >= (3, 7): # built-in dict is insertion-ordered
        global_values = list(globals().values())
    else:
        global_values = [A, B, C, X, Y, Z]
    for value in global_values:
        if isinstance(value, type):
            print(value.__name__)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_class_property_decorator_T264.pyx0000644000175100001770000000235300000000000025122 0ustar00runnerdocker00000000000000# mode: run
# ticket: t264
# tag: property, decorator

my_property = property

cdef class Prop:
    """
    >>> p = Prop()
    >>> p.prop
    GETTING 'None'
    >>> p.prop = 1
    SETTING '1' (previously: 'None')
    >>> p.prop
    GETTING '1'
    1
    >>> p.prop = 2
    SETTING '2' (previously: '1')
    >>> p.prop
    GETTING '2'
    2
    >>> p.my_prop
    GETTING '2' via my_prop
    2
    >>> del p.prop
    DELETING '2'
    >>> p.prop
    GETTING 'None'
    >>> list(p.generator_prop)
    [42]
    """
    cdef _value
    def __init__(self):
        self._value = None

    @property
    def prop(self):
        print("FAIL")
        return 0

    @prop.getter
    def prop(self):
        print("FAIL")

    @property
    def prop(self):
        print("GETTING '%s'" % self._value)
        return self._value

    @prop.setter
    def prop(self, value):
        print("SETTING '%s' (previously: '%s')" % (value, self._value))
        self._value = value

    @prop.deleter
    def prop(self):
        print("DELETING '%s'" % self._value)
        self._value = None

    @my_property
    def my_prop(self):
        print("GETTING '%s' via my_prop" % self._value)
        return self._value

    @property
    def generator_prop(self):
        yield 42
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_classmethod.pyx0000644000175100001770000000336000000000000021575 0ustar00runnerdocker00000000000000
cimport cython

cdef class cclass:

    @classmethod
    def test0(cls):
        """
        >>> cclass.test0()
        'type object'
        """
        return cython.typeof(cls)

    @classmethod
    def test0_args(*args):
        """
        >>> cclass.test0_args(1,2,3)
        ('Python object', (1, 2, 3))
        """
        return cython.typeof(args[0]), args[1:]

    @classmethod
    def test1(cls, arg):
        """
        >>> cclass.test1(1)
        ('type object', 1)
        """
        return cython.typeof(cls), arg

    @classmethod
    def test2(cls, arg1, arg2):
        """
        >>> cclass.test2(1,2)
        ('type object', 1, 2)
        """
        return cython.typeof(cls), arg1, arg2

    @classmethod
    def test1_args(cls, *args):
        """
        >>> cclass.test1_args(1,2,3)
        ('type object', (1, 2, 3))
        """
        return cython.typeof(cls), args

    @classmethod
    def test2_args(cls, arg, *args):
        """
        >>> cclass.test2_args(1,2,3)
        ('type object', 1, (2, 3))
        """
        return cython.typeof(cls), arg, args

    @classmethod
    def test0_args_kwargs(*args, **kwargs):
        """
        >>> cclass.test0_args_kwargs(1,2,3)
        ('Python object', (1, 2, 3), {})
        """
        return cython.typeof(args[0]), args[1:], kwargs

    @classmethod
    def test1_args_kwargs(cls, *args, **kwargs):
        """
        >>> cclass.test1_args_kwargs(1,2,3)
        ('type object', (1, 2, 3), {})
        """
        return cython.typeof(cls), args, kwargs

    @classmethod
    def test2_args_kwargs(cls, arg, *args, **kwargs):
        """
        >>> cclass.test2_args_kwargs(1,2,3)
        ('type object', 1, (2, 3), {})
        """
        return cython.typeof(cls), arg, args, kwargs
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_cpdef_override_GH543.srctree0000644000175100001770000000170600000000000023712 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON test.py

######## setup.py ########
from Cython.Build import cythonize
from distutils.core import setup

setup(
  ext_modules = cythonize("*.pyx"),
)

######## test.py ########
from base import A, B
from derived import C

assert B().foo() == 'B.foo'
assert C().foo() == 'B.foo'

assert A().foo1() == 'A.foo'
assert B().foo1() == 'B.foo'
assert C().foo1() == 'B.foo'

assert B().foo2() == 'B.foo'
assert C().foo2() == 'B.foo'

assert C().bar() == 'C.bar'

######## base.pxd ########
cdef class A(object):
    cdef foo(self)

cdef class B(A):
    cpdef foo(self)

######## base.pyx ########
cdef class A(object):
    cdef foo(self):
        return "A.foo"

    def foo1(self):
        return self.foo()

cdef class B(A):
    cpdef foo(self):
        return "B.foo"

    def foo2(self):
        return self.foo()

######## derived.pyx ########
from base cimport B

cdef class C(B):
    cpdef bar(self):
        return "C.bar"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_decorator_directives_T183.pyx0000644000175100001770000000045200000000000024210 0ustar00runnerdocker00000000000000# ticket: t183

cimport cython

@cython.cdivision(True)
cpdef cdiv_decorator(int a, int b):
    """
    >>> cdiv_decorator(-12, 5)
    -2
    """
    return a / b

@cython.cdivision(False)
cpdef pydiv_decorator(int a, int b):
    """
    >>> pydiv_decorator(-12, 5)
    -3
    """
    return a / b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_function_kwargs.pyx0000644000175100001770000002106600000000000022475 0ustar00runnerdocker00000000000000cimport cython

from libc.string cimport strstr

cdef cfunc(a,b,c,d):
    return (a,b,c,d)

cpdef cpfunc(a,b,c,d):
    return (a,b,c,d)

cdef optargs(a, b=2, c=3):
    return (a,b,c)

ctypedef int (*cfuncptr_type)(int a, int b)
cdef int cfuncptr(int a, int b):
    print a, b

cdef cfuncptr_type get_cfuncptr():
    return cfuncptr


sideeffect = []
cdef side_effect(x):
    sideeffect.append(x)
    return x


@cython.test_fail_if_path_exists('//GeneralCallNode')
@cython.test_assert_path_exists('//SimpleCallNode')
def cfunc_all_keywords():
    """
    >>> cfunc_all_keywords()
    (1, 2, 3, 4)
    """
    return cfunc(a=1, b=2, c=3, d=4)


@cython.test_fail_if_path_exists('//GeneralCallNode')
@cython.test_assert_path_exists('//SimpleCallNode')
def cfunc_some_keywords():
    """
    >>> cfunc_some_keywords()
    (1, 2, 3, 4)
    """
    return cfunc(1, 2, c=3, d=4)


@cython.test_fail_if_path_exists('//GeneralCallNode')
@cython.test_assert_path_exists('//SimpleCallNode')
def cfunc_some_keywords_unordered():
    """
    >>> cfunc_some_keywords_unordered()
    (1, 2, 3, 4)
    """
    return cfunc(1, 2, d=4, c=3)


@cython.test_fail_if_path_exists('//GeneralCallNode')
@cython.test_assert_path_exists('//SimpleCallNode')
def cfunc_some_keywords_unordered_sideeffect():
    """
    >>> del sideeffect[:]
    >>> cfunc_some_keywords_unordered_sideeffect()
    (1, 2, 3, 4)
    >>> sideeffect
    [4, 3]
    """
    return cfunc(1, 2, d=side_effect(4), c=side_effect(3))


@cython.test_fail_if_path_exists('//GeneralCallNode')
@cython.test_assert_path_exists('//SimpleCallNode')
def cpfunc_all_keywords():
    """
    >>> cpfunc_all_keywords()
    (1, 2, 3, 4)
    """
    return cpfunc(a=1, b=2, c=3, d=4)


@cython.test_fail_if_path_exists('//GeneralCallNode')
@cython.test_assert_path_exists('//SimpleCallNode')
def cpfunc_some_keywords():
    """
    >>> cpfunc_some_keywords()
    (1, 2, 3, 4)
    """
    return cpfunc(1, 2, c=3, d=4)


@cython.test_fail_if_path_exists('//GeneralCallNode')
@cython.test_assert_path_exists('//SimpleCallNode')
def cpfunc_some_keywords_unordered():
    """
    >>> cpfunc_some_keywords_unordered()
    (1, 2, 3, 4)
    """
    return cpfunc(1, 2, d=4, c=3)


@cython.test_fail_if_path_exists('//GeneralCallNode')
@cython.test_assert_path_exists('//SimpleCallNode')
def cpfunc_some_keywords_unordered_sideeffect():
    """
    >>> del sideeffect[:]
    >>> cpfunc_some_keywords_unordered_sideeffect()
    (1, 2, 3, 4)
    >>> sideeffect
    [4, 3]
    """
    return cpfunc(1, 2, d=side_effect(4), c=side_effect(3))


@cython.test_fail_if_path_exists('//GeneralCallNode')
@cython.test_assert_path_exists('//SimpleCallNode')
def libc_strstr():
    """
    >>> libc_strstr()
    (True, True, True, True, True)
    """
    return (
        strstr("xabcy", "abc") is not NULL,
        strstr("abc", "xabcy") is NULL,
        strstr(needle="abc", haystack="xabcz") is not NULL,
        strstr(needle="xabcz", haystack="abc") is NULL,
        strstr(haystack="abc", needle="xabcz") is NULL,
        )


@cython.test_fail_if_path_exists('//GeneralCallNode')
@cython.test_assert_path_exists('//SimpleCallNode')
def cdef_optargs():
    """
    >>> cdef_optargs()
    (11, 2, 3)
    (11, 2, 3)
    (11, 12, 3)
    (11, 12, 3)
    (11, 12, 3)
    (11, 12, 3)
    (11, 12, 3)
    (11, 12, 13)
    (11, 12, 13)
    (11, 12, 13)
    (11, 12, 13)
    (11, 12, 13)
    (11, 12, 13)
    (11, 12, 13)
    """
    print(optargs(11))
    print(optargs(a=11))

    print(optargs(11,   12))
    print(optargs(11,   b=12))
    print(optargs(a=11, b=12))
    print(optargs(b=12, a=11))
    print(optargs(a=11, b=12))

    print(optargs(11,   12,   13))
    print(optargs(11,   12,   c=13))
    print(optargs(11,   c=13, b=12))
    print(optargs(a=11, b=12, c=13))
    print(optargs(b=12, a=11, c=13))
    print(optargs(b=12, c=13, a=11))
    print(optargs(c=13, a=11, b=12))


@cython.test_fail_if_path_exists('//GeneralCallNode')
@cython.test_assert_path_exists('//SimpleCallNode')
def cdef_funcptr():
    """
    >>> cdef_funcptr()
    1 2
    1 2
    1 2
    1 2
    """
    cdef cfuncptr_type cfunc_ptr = get_cfuncptr()
    cfunc_ptr(1, 2)
    cfunc_ptr(1, b=2)
    cfunc_ptr(a=1, b=2)
    cfunc_ptr(b=2, a=1)


'''
# This works but currently brings up C compiler warnings
# because the format string is not a literal C string.

from libc.stdio cimport snprintf

@cython.test_fail_if_path_exists('//GeneralCallNode')
@cython.test_assert_path_exists('//SimpleCallNode')
def varargs():
    """
    >>> print(varargs())
    abc
    """
    cdef char[10] buffer
    retval = snprintf(buffer, template="abc", size=10)
    if retval < 0:
        raise MemoryError()
    return buffer[:retval].decode('ascii')
'''


cdef class ExtType:
    cdef cmeth(self, a, b, c, d):
        return (a,b,c,d)

    @cython.test_fail_if_path_exists('//GeneralCallNode')
    @cython.test_assert_path_exists('//SimpleCallNode')
    def call_cmeth(self, ExtType ext):
        """
        >>> x = ExtType()
        >>> x.call_cmeth(x)
        (1, 2, 3, 4)
        (1, 2, 3, 4)
        (1, 2, 3, 4)
        EXT
        (1, 2, 3, 4)
        (1, 2, 3, 4)
        (1, 2, 3, 4)
        """
        print self.cmeth(1,2,3,4)
        print self.cmeth(1,2,c=3,d=4)
        print self.cmeth(a=1,b=2,c=3,d=4)
        print "EXT"
        print ext.cmeth(1,2,3,4)
        print ext.cmeth(1,2,c=3,d=4)
        print ext.cmeth(a=1,b=2,c=3,d=4)

    cpdef cpmeth(self, a, b, c, d):
        return (a,b,c,d)

    @cython.test_fail_if_path_exists('//GeneralCallNode')
    @cython.test_assert_path_exists('//SimpleCallNode')
    def call_cpmeth(self, ExtType ext):
        """
        >>> x = ExtType()
        >>> x.call_cpmeth(x)
        (1, 2, 3, 4)
        (1, 2, 3, 4)
        (1, 2, 3, 4)
        EXT
        (1, 2, 3, 4)
        (1, 2, 3, 4)
        (1, 2, 3, 4)
        """
        print self.cpmeth(1,2,3,4)
        print self.cpmeth(1,2,c=3,d=4)
        print self.cpmeth(a=1,b=2,c=3,d=4)
        print "EXT"
        print ext.cpmeth(1,2,3,4)
        print ext.cpmeth(1,2,c=3,d=4)
        print ext.cpmeth(a=1,b=2,c=3,d=4)

    cdef optargs(self, a=1, b=2):
        return (a,b)

    @cython.test_fail_if_path_exists('//GeneralCallNode')
    @cython.test_assert_path_exists('//SimpleCallNode')
    def call_optargs(self, ExtType ext):
        """
        >>> x = ExtType()
        >>> x.call_optargs(x)
        (3, 4)
        (3, 4)
        (3, 4)
        (1, 2)
        (3, 2)
        (3, 2)
        EXT
        (3, 4)
        (3, 4)
        (3, 4)
        (1, 2)
        (3, 2)
        (3, 2)
        """
        print self.optargs(3,4)
        print self.optargs(3,b=4)
        print self.optargs(a=3,b=4)
        print self.optargs()
        print self.optargs(3)
        print self.optargs(a=3)
        #print self.optargs(b=4)
        print "EXT"
        print ext.optargs(3,4)
        print ext.optargs(3,b=4)
        print ext.optargs(a=3,b=4)
        print ext.optargs()
        print ext.optargs(3)
        print ext.optargs(a=3)
        #print ext.optargs(b=4)

    cpdef cpmeth_optargs(self, a=1, b=2):
        return (a,b)

    @cython.test_fail_if_path_exists('//GeneralCallNode')
    @cython.test_assert_path_exists('//SimpleCallNode')
    def call_cpmeth_optargs(self, ExtType ext):
        """
        >>> x = ExtType()
        >>> x.call_cpmeth_optargs(x)
        (3, 4)
        (3, 4)
        (3, 4)
        (1, 2)
        (3, 2)
        (3, 2)
        EXT
        (3, 4)
        (3, 4)
        (3, 4)
        (1, 2)
        (3, 2)
        (3, 2)
        """
        print self.cpmeth_optargs(3,4)
        print self.cpmeth_optargs(3,b=4)
        print self.cpmeth_optargs(a=3,b=4)
        print self.cpmeth_optargs()
        print self.cpmeth_optargs(3)
        print self.cpmeth_optargs(a=3)
        #print self.cpmeth_optargs(b=4)
        print "EXT"
        print ext.cpmeth_optargs(3,4)
        print ext.cpmeth_optargs(3,b=4)
        print ext.cpmeth_optargs(a=3,b=4)
        print ext.cpmeth_optargs()
        print ext.cpmeth_optargs(3)
        print ext.cpmeth_optargs(a=3)
        #print ext.cpmeth_optargs(b=4)

    cpdef cpmeth_optargs1(self, a=1):
        return a

    @cython.test_fail_if_path_exists('//GeneralCallNode')
    @cython.test_assert_path_exists('//SimpleCallNode')
    def call_cpmeth_optargs1(self, ExtType ext):
        """
        >>> x = ExtType()
        >>> x.call_cpmeth_optargs1(x)
        1
        3
        3
        EXT
        1
        3
        3
        """
        print self.cpmeth_optargs1()
        print self.cpmeth_optargs1(3)
        print self.cpmeth_optargs1(a=3)
        print "EXT"
        print ext.cpmeth_optargs1()
        print ext.cpmeth_optargs1(3)
        print ext.cpmeth_optargs1(a=3)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_locals_decorator_T477.pyx0000644000175100001770000000072000000000000023330 0ustar00runnerdocker00000000000000# ticket: t477

import cython
@cython.locals(x=double)
cdef func(x):
    return x**2

@cython.locals(x=double)
cdef func_defval(x=0):
    return x**2

def test():
    """
    >>> isinstance(test(), float)
    True
    """
    return func(2)

def test_defval(x=None):
    """
    >>> test_defval()
    0.0
    >>> test_defval(1)
    1.0
    >>> test_defval(2.0)
    4.0
    """
    if x is None:
        return func_defval()
    else:
        return func_defval(x)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_members_T517.pyx0000644000175100001770000000541700000000000021446 0ustar00runnerdocker00000000000000# ticket: t517
#cython: embedsignature=True

__doc__ = u"""
>>> a = A()
>>> a.h = 7
>>> a.i = 127
>>> a.l = 255
>>> a.q = 255
>>> a.f = 1.0/2.0
>>> a.d = 1/2.0 + 1/4.0
>>> a.g = 1/2.0 + 1/4.0 + 1/8.0
>>> a.Zf = 1+2j
>>> a.Zd = 3+4j
>>> a.Zg = 5+6j

>>> a.h, a.i, a.l
(7, 127, 255)
>>> a.ro_h, a.ro_i, a.ro_l
(7, 127, 255)
>>> a.f, a.d, a.g
(0.5, 0.75, 0.875)
>>> a.ro_f, a.ro_d, a.ro_g
(0.5, 0.75, 0.875)
>>> a.Zf, a.Zd, a.Zg
((1+2j), (3+4j), (5+6j))
>>> a.ro_Zf, a.ro_Zd, a.ro_Zg
((1+2j), (3+4j), (5+6j))

>>> b = B()
>>> b.a0 #doctest: +ELLIPSIS
Traceback (most recent call last):
AttributeError: ...

>>> b.b0 #doctest: +ELLIPSIS
Traceback (most recent call last):
AttributeError: ...

>>> b.c0 #doctest: +ELLIPSIS
Traceback (most recent call last):
AttributeError: ...

>>> isinstance(b.a1, type(None))
True
>>> isinstance(b.a2, type(None))
True
>>> isinstance(b.b1, list)
True
>>> isinstance(b.b2, list)
True
>>> isinstance(b.c1, A)
True
>>> isinstance(b.c2, A)
True

>>> b.a1 = a
>>> b.a1 is not b.a2
True

TYPE_FIXES_REQUIRED:

>>> try: b.b1 = 1
... except (TypeError, AttributeError): pass

>>> try: b.c1 = 1
... except (TypeError, AttributeError): pass

>>> try: b.a2 = None
... except (TypeError, AttributeError): pass

>>> try: b.b2 = []
... except (TypeError, AttributeError): pass

>>> try: b.c2 = A()
... except (TypeError, AttributeError): pass
"""

import sys
if sys.version_info < (2,5):
    __doc__ = (__doc__.split('TYPE_FIXES_REQUIRED')[0] +
               __doc__.split('TYPE_FIXES_REQUIRED')[1].replace('\nAttributeError: ...', '\nTypeError: ...'))


cdef class A:

    cdef public short h
    cdef public int i
    cdef public long l
    cdef public long long q
    cdef public float f
    cdef public double d
    cdef public long double g
    cdef public float complex Zf
    cdef public double complex Zd
    cdef public long double complex Zg

    cdef readonly short ro_h
    cdef readonly int ro_i
    cdef readonly long ro_l
    cdef readonly long long ro_q
    cdef readonly float ro_f
    cdef readonly double ro_d
    cdef readonly long double ro_g
    cdef readonly float complex ro_Zf
    cdef readonly double complex ro_Zd
    cdef readonly long double complex ro_Zg

    def __cinit__(self):
        self.ro_h = 7
        self.ro_i = 127
        self.ro_l = 255
        self.ro_q = 255
        self.ro_f = 1.0/2.0
        self.ro_d = 1/2.0 + 1/4.0
        self.ro_g = 1/2.0 + 1/4.0 + 1/8.0
        self.ro_Zf = 1+2j
        self.ro_Zd = 3+4j
        self.ro_Zg = 5+6j


cdef class B:

    cdef object a0
    cdef public object a1
    cdef readonly object a2

    cdef list b0
    cdef public list b1
    cdef readonly list b2

    cdef A c0
    cdef public A c1
    cdef readonly A c2

    def __cinit__(self):
        self.b0 = self.b1 = self.b2 = []
        self.c0 = self.c1 = self.c2 = A()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_members_binding_properties.pyx0000644000175100001770000000552600000000000024675 0ustar00runnerdocker00000000000000# cython: embedsignature=True, binding=True
# mode: run

# same test as "cdef_members_T517.pyx" but "binding=True"

__doc__ = u"""
>>> a = A()
>>> a.h = 7
>>> a.i = 127
>>> a.l = 255
>>> a.q = 255
>>> a.f = 1.0/2.0
>>> a.d = 1/2.0 + 1/4.0
>>> a.g = 1/2.0 + 1/4.0 + 1/8.0
>>> a.Zf = 1+2j
>>> a.Zd = 3+4j
>>> a.Zg = 5+6j

>>> a.h, a.i, a.l
(7, 127, 255)
>>> a.ro_h, a.ro_i, a.ro_l
(7, 127, 255)
>>> a.f, a.d, a.g
(0.5, 0.75, 0.875)
>>> a.ro_f, a.ro_d, a.ro_g
(0.5, 0.75, 0.875)
>>> a.Zf, a.Zd, a.Zg
((1+2j), (3+4j), (5+6j))
>>> a.ro_Zf, a.ro_Zd, a.ro_Zg
((1+2j), (3+4j), (5+6j))

>>> b = B()
>>> b.a0 #doctest: +ELLIPSIS
Traceback (most recent call last):
AttributeError: ...

>>> b.b0 #doctest: +ELLIPSIS
Traceback (most recent call last):
AttributeError: ...

>>> b.c0 #doctest: +ELLIPSIS
Traceback (most recent call last):
AttributeError: ...

>>> isinstance(b.a1, type(None))
True
>>> isinstance(b.a2, type(None))
True
>>> isinstance(b.b1, list)
True
>>> isinstance(b.b2, list)
True
>>> isinstance(b.c1, A)
True
>>> isinstance(b.c2, A)
True

>>> b.a1 = a
>>> b.a1 is not b.a2
True

TYPE_FIXES_REQUIRED:

>>> try: b.b1 = 1
... except (TypeError, AttributeError): pass

>>> try: b.c1 = 1
... except (TypeError, AttributeError): pass

>>> try: b.a2 = None
... except (TypeError, AttributeError): pass

>>> try: b.b2 = []
... except (TypeError, AttributeError): pass

>>> try: b.c2 = A()
... except (TypeError, AttributeError): pass
"""

import sys
if sys.version_info < (2,5):
    __doc__ = (__doc__.split('TYPE_FIXES_REQUIRED')[0] +
               __doc__.split('TYPE_FIXES_REQUIRED')[1].replace('\nAttributeError: ...', '\nTypeError: ...'))


cdef class A:

    cdef public short h
    cdef public int i
    cdef public long l
    cdef public long long q
    cdef public float f
    cdef public double d
    cdef public long double g
    cdef public float complex Zf
    cdef public double complex Zd
    cdef public long double complex Zg

    cdef readonly short ro_h
    cdef readonly int ro_i
    cdef readonly long ro_l
    cdef readonly long long ro_q
    cdef readonly float ro_f
    cdef readonly double ro_d
    cdef readonly long double ro_g
    cdef readonly float complex ro_Zf
    cdef readonly double complex ro_Zd
    cdef readonly long double complex ro_Zg

    def __cinit__(self):
        self.ro_h = 7
        self.ro_i = 127
        self.ro_l = 255
        self.ro_q = 255
        self.ro_f = 1.0/2.0
        self.ro_d = 1/2.0 + 1/4.0
        self.ro_g = 1/2.0 + 1/4.0 + 1/8.0
        self.ro_Zf = 1+2j
        self.ro_Zd = 3+4j
        self.ro_Zg = 5+6j


cdef class B:

    cdef object a0
    cdef public object a1
    cdef readonly object a2

    cdef list b0
    cdef public list b1
    cdef readonly list b2

    cdef A c0
    cdef public A c1
    cdef readonly A c2

    def __cinit__(self):
        self.b0 = self.b1 = self.b2 = []
        self.c0 = self.c1 = self.c2 = A()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_methods_T462.pyx0000644000175100001770000000161700000000000021454 0ustar00runnerdocker00000000000000# ticket: t462

cimport cython

cdef class cclass:
    def test_self(self):
        """
        >>> cclass().test_self()
        'cclass'
        """
        return cython.typeof(self)

    def test_self_1(self, arg):
        """
        >>> cclass().test_self_1(1)
        ('cclass', 1)
        """
        return cython.typeof(self), arg

    def test_self_args(self, *args):
        """
        >>> cclass().test_self_args(1,2,3)
        ('cclass', (1, 2, 3))
        """
        return cython.typeof(self), args

    def test_args(*args):
        """
        >>> cclass().test_args(1,2,3)
        ('Python object', (1, 2, 3))
        """
        return cython.typeof(args[0]), args[1:]

    def test_args_kwargs(*args, **kwargs):
        """
        >>> cclass().test_args_kwargs(1,2,3, a=4)
        ('Python object', (1, 2, 3), {'a': 4})
        """
        return cython.typeof(args[0]), args[1:], kwargs
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_multiple_inheritance.pyx0000644000175100001770000000246300000000000023476 0ustar00runnerdocker00000000000000cimport cython

cdef class CBase(object):
    cdef int a
    cdef c_method(self):
        return "CBase"
    cpdef cpdef_method(self):
        return "CBase"

class PyBase(object):
    def py_method(self):
        return "PyBase"

@cython.binding(True)
cdef class BothBound(CBase, PyBase):
    cdef dict __dict__
    """
    >>> b = Both()
    >>> b.py_method()
    'PyBase'
    >>> b.cp_method()
    'Both'
    >>> b.call_c_method()
    'Both'

    >>> isinstance(b, CBase)
    True
    >>> isinstance(b, PyBase)
    True
    """
    cdef c_method(self):
        return "Both"
    cpdef cp_method(self):
        return "Both"
    def call_c_method(self):
        return self.c_method()

cdef class BothSub(BothBound):
    """
    >>> b = BothSub()
    >>> b.py_method()
    'PyBase'
    >>> b.cp_method()
    'Both'
    >>> b.call_c_method()
    'Both'
    """
    pass

@cython.binding(False)
cdef class BothUnbound(CBase, PyBase):
    cdef dict __dict__
    """
    >>> b = Both()
    >>> b.py_method()
    'PyBase'
    >>> b.cp_method()
    'Both'
    >>> b.call_c_method()
    'Both'

    >>> isinstance(b, CBase)
    True
    >>> isinstance(b, PyBase)
    True
    """
    cdef c_method(self):
        return "Both"
    cpdef cp_method(self):
        return "Both"
    def call_c_method(self):
        return self.c_method()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_multiple_inheritance_cimport.srctree0000644000175100001770000000117600000000000026062 0ustar00runnerdocker00000000000000# Test for https://github.com/cython/cython/issues/4106

PYTHON setup.py build_ext --inplace
PYTHON -c "import sub"

######## setup.py ########

from Cython.Build import cythonize
from distutils.core import setup

setup(
  ext_modules = cythonize("*.pyx"),
)

######## base.pxd ########

cdef class A:
  cdef dict __dict__
  cdef int a(self)

cdef class B(A):
  cdef int b(self)

######## base.pyx ########

cdef class A:
  cdef int a(self):
    return 1

class PyA:
  pass

cdef class B(A, PyA):
  cdef int b(self):
    return 2

######## sub.pyx ########

from base cimport B
print(B)

cdef class C(B):
  cdef int c(self):
    return 3
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_multiple_inheritance_errors.srctree0000644000175100001770000000345100000000000025717 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import runner"

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup

setup(ext_modules=cythonize("*.pyx"))

######## notheaptype.pyx ########

cdef class Base:
    pass

Obj = type(object())

cdef class Foo(Base, Obj):
    pass

######## wrongbase.pyx ########

cdef class Base:
    pass

Str = type("")

cdef class X(Base, Str):
    pass

######## badmro.pyx ########

class Py(object):
    pass

cdef class X(object, Py):
    pass

######## nodict.pyx ########

cdef class Base:
    pass

class Py(object):
    pass

cdef class X(Base, Py):
    pass

######## oldstyle.pyx ########
# cython: language_level=2

cdef class Base:
    cdef dict __dict__

class OldStyle:
    pass

cdef class Foo(Base, OldStyle):
    pass

######## runner.py ########

import sys

try:
    import notheaptype
    assert False, "notheaptype"
except TypeError as msg:
    assert str(msg) == "base class 'object' is not a heap type"

try:
    import wrongbase
    assert False, "wrongbase"
except TypeError as msg:
    assert str(msg) == "best base 'str' must be equal to first base 'wrongbase.Base'"

try:
    import badmro
    assert False, "badmro"
except TypeError as msg:
    assert str(msg).startswith("Cannot create a consistent method resolution")

try:
    import nodict
    assert False, "nodict"
except TypeError as msg:
    assert str(msg) == "extension type 'nodict.X' has no __dict__ slot, but base type 'Py' has: either add 'cdef dict __dict__' to the extension type or add '__slots__ = [...]' to the base type"

try:
    # This should work on Python 3 but fail on Python 2
    import oldstyle
    assert sys.version_info[0] >= 3, "oldstyle"
except TypeError as msg:
    assert str(msg) == "base class 'OldStyle' is an old-style class"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_multiple_inheritance_nodict.pyx0000644000175100001770000000161200000000000025031 0ustar00runnerdocker00000000000000# Copied from cdef_multiple_inheritance.pyx
# but with __slots__ and without __dict__

cdef class CBase(object):
    cdef int a
    cdef c_method(self):
        return "CBase"
    cpdef cpdef_method(self):
        return "CBase"

class PyBase(object):
    __slots__ = []
    def py_method(self):
        return "PyBase"

cdef class Both(CBase, PyBase):
    """
    >>> b = Both()
    >>> b.py_method()
    'PyBase'
    >>> b.cp_method()
    'Both'
    >>> b.call_c_method()
    'Both'

    >>> isinstance(b, CBase)
    True
    >>> isinstance(b, PyBase)
    True
    """
    cdef c_method(self):
        return "Both"
    cpdef cp_method(self):
        return "Both"
    def call_c_method(self):
        return self.c_method()

cdef class BothSub(Both):
    """
    >>> b = BothSub()
    >>> b.py_method()
    'PyBase'
    >>> b.cp_method()
    'Both'
    >>> b.call_c_method()
    'Both'
    """
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_opt.pxd0000644000175100001770000000006100000000000020037 0ustar00runnerdocker00000000000000cdef class A:
    cpdef foo(self, bint a=*, b=*)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_opt.pyx0000644000175100001770000000104500000000000020067 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> a = A()
    >>> a.foo()
    (True, 'yo')
    >>> a.foo(False)
    (False, 'yo')
    >>> a.foo(10, 'yes')
    (True, 'yes')

"""

cdef class A:
    cpdef foo(self, bint a=True, b="yo"):
        return a, b

def call0():
    """
    >>> call0()
    (True, 'yo')
    """
    cdef A a = A()
    return a.foo()

def call1():
    """
    >>> call1()
    (False, 'yo')
    """
    cdef A a = A()
    return a.foo(False)

def call2():
    """
    >>> call2()
    (False, 'go')
    """
    cdef A a = A()
    return a.foo(False, "go")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdef_setitem_T284.pyx0000644000175100001770000000166000000000000021463 0ustar00runnerdocker00000000000000# ticket: t284

def no_cdef():
    """
    >>> no_cdef()
    """
    cdef object lst = list(range(11))
    ob = 10L
    lst[ob] = -10
    cdef object dd = {}
    dd[ob] = -10

def with_cdef():
    """
    >>> with_cdef()
    """
    cdef list lst = list(range(11))
    ob = 10L
    lst[ob] = -10
    cdef dict dd = {}
    dd[ob] = -10

def with_external_list(list L):
    """
    >>> with_external_list([1,2,3])
    [1, -10, 3]
    >>> with_external_list(None)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: 'NoneType' object ...
    """
    ob = 1L
    L[ob] = -10
    return L

def test_list(list L, object i, object a):
    """
    >>> test_list(list(range(11)), -2, None)
    [0, 1, 2, 3, 4, 5, 6, 7, 8, None, 10]
    >>> test_list(list(range(11)), "invalid index", None) #doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: list ... must be ...integer...
    """
    L[i] = a
    return L
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdefassign.pyx0000644000175100001770000000047100000000000020414 0ustar00runnerdocker00000000000000cdef int g = 7

def test(x, int y):
    """
    >>> test(1, 2)
    4 1 2 2 0 7 8
    """
    if True:
        before = 0
    cdef int a = 4, b = x, c = y
    cdef int *p = &y
    cdef object o = int(8)
    print a, b, c, p[0], before, g, o

# Also test that pruning cdefs doesn't hurt
def empty():
    cdef int i
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdefoptargs.pyx0000644000175100001770000000177100000000000020613 0ustar00runnerdocker00000000000000from cython cimport typeof

def call2():
    """
    >>> call2()
    """
    b(1,2)

def call3():
    """
    >>> call3()
    """
    b(1,2,3)

def call4():
    """
    >>> call4()
    """
    b(1,2,3,4)

# the called function:

cdef b(a, b, c=1, d=2):
    pass


cdef int foo(int a, int b=1, int c=1):
    return a+b*c

def test_foo():
    """
    >>> test_foo()
    2
    3
    7
    26
    """
    print foo(1)
    print foo(1, 2)
    print foo(1, 2, 3)
    print foo(1, foo(2, 3), foo(4))

cdef class A:
    cpdef method(self):
        """
        >>> A().method()
        'A'
        """
        return typeof(self)

cdef class B(A):
    cpdef method(self, int x = 0):
        """
        >>> B().method()
        ('B', 0)
        >>> B().method(100)
        ('B', 100)
        """
        return typeof(self), x

cdef class C(B):
    cpdef method(self, int x = 10):
        """
        >>> C().method()
        ('C', 10)
        >>> C().method(100)
        ('C', 100)
        """
        return typeof(self), x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cdivision_CEP_516.pyx0000644000175100001770000001143100000000000021355 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> v = [(17, 10), (-17, 10), (-17, -10), (17, -10)]
>>> standard = [(a % b) for a, b in v]
>>> standard
[7, 3, -7, -3]
>>> [mod_int_py(a, b) for a, b in v] == standard
True
>>> [mod_short_py(a, b) for a, b in v] == standard
True
>>> [mod_float_py(a, b) for a, b in v] == standard
True
>>> [mod_double_py(a, b) for a, b in v] == standard
True

>>> [mod_int_c(a, b) for a, b in v]
[7, -7, -7, 7]
>>> [mod_float_c(a, b) for a, b in v]
[7.0, -7.0, -7.0, 7.0]
>>> [mod_double_c(a, b) for a, b in v]
[7.0, -7.0, -7.0, 7.0]

>>> [div_int_py(a, b) for a, b in v]
[1, -2, 1, -2]
>>> [div_int_c(a, b) for a, b in v]
[1, -1, 1, -1]

>>> [test_cdiv_cmod(a, b) for a, b in v]
[(1, 7), (-1, -7), (1, -7), (-1, 7)]

>>> [test_cdiv_cmod(a, b) for a, b in [(4, -4), (4, -2), (4, -1)]]
[(-1, 0), (-2, 0), (-4, 0)]

>>> all([mod_int_py(a,b) == a % b for a in range(-10, 10) for b in range(-10, 10) if b != 0])
True
>>> all([div_int_py(a,b) == a // b for a in range(-10, 10) for b in range(-10, 10) if b != 0])
True
"""

import warnings
orig_showwarning = warnings.showwarning

true_py_functions = {}
exec "def simple_warn(msg, *args): print(msg)" in true_py_functions
simple_warn = true_py_functions['simple_warn']
del true_py_functions


def _all(seq):
    for x in seq:
        if not x:
            return False
    return True

try:
    all
except NameError:
    all = _all


cimport cython

@cython.cdivision(False)
def mod_int_py(int a, int b):
    return a % b

@cython.cdivision(False)
def mod_short_py(short a, short b):
    return a % b

@cython.cdivision(False)
def mod_double_py(double a, double b):
    return a % b

@cython.cdivision(False)
def mod_float_py(float a, float b):
    return a % b

@cython.cdivision(True)
def mod_int_c(int a, int b):
    return a % b

@cython.cdivision(True)
def mod_float_c(float a, float b):
    return a % b

@cython.cdivision(True)
def mod_double_c(double a, double b):
    return a % b


@cython.cdivision(False)
def div_int_py(int a, int b):
    return a // b

@cython.cdivision(True)
def div_int_c(int a, int b):
    return a // b


@cython.cdivision(False)
def test_cdiv_cmod(short a, short b):
    cdef short q = cython.cdiv(a, b)
    cdef short r = cython.cmod(a, b)
    return q, r

@cython.cdivision(True)
@cython.cdivision_warnings(True)
def mod_int_c_warn(int a, int b):
    """
    >>> warnings.showwarning = simple_warn
    >>> mod_int_c_warn(-17, 10)
    division with oppositely signed operands, C and Python semantics differ
    -7
    >>> warnings.showwarning = orig_showwarning
    """
    return a % b

@cython.cdivision(True)
@cython.cdivision_warnings(True)
def div_int_c_warn(int a, int b):
    """
    >>> warnings.showwarning = simple_warn
    >>> div_int_c_warn(-17, 10)
    division with oppositely signed operands, C and Python semantics differ
    -1
    >>> warnings.showwarning = orig_showwarning
    """
    return a // b

@cython.cdivision(False)
@cython.cdivision_warnings(True)
def complex_expression(int a, int b, int c, int d):
    """
    >>> warnings.showwarning = simple_warn
    >>> complex_expression(-150, 20, 19, -7)
    verbose_call(20)
    division with oppositely signed operands, C and Python semantics differ
    verbose_call(19)
    division with oppositely signed operands, C and Python semantics differ
    -2
    >>> warnings.showwarning = orig_showwarning
    """
    return (a // verbose_call(b)) % (verbose_call(c) // d)

cdef int verbose_call(int x):
    print u"verbose_call(%s)" % x
    return x


# These may segfault with cdivision

@cython.cdivision(False)
def mod_div_zero_int(int a, int b, int c):
    """
    >>> mod_div_zero_int(25, 10, 2)
    verbose_call(5)
    2
    >>> print(mod_div_zero_int(25, 10, 0))
    verbose_call(5)
    integer division or modulo by zero
    >>> print(mod_div_zero_int(25, 0, 0))
    integer division or modulo by zero
    """
    try:
        return verbose_call(a % b) / c
    except ZeroDivisionError, ex:
        return unicode(ex)

@cython.cdivision(False)
def mod_div_zero_float(float a, float b, float c):
    """
    >>> mod_div_zero_float(25, 10, 2)
    2.5
    >>> print(mod_div_zero_float(25, 10, 0))
    float division
    >>> print(mod_div_zero_float(25, 0, 0))
    float divmod()
    """
    try:
        return (a % b) / c
    except ZeroDivisionError, ex:
        return unicode(ex)

@cython.cdivision(False)
def py_div_long(long a, long b):
    """
    >>> py_div_long(-5, -1)
    5
    >>> import sys
    >>> maxint = getattr(sys, ((sys.version_info[0] >= 3) and 'maxsize' or 'maxint'))
    >>> py_div_long(-maxint-1, -1) # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: ...
    """
    return a / b

def c_div_const_test(a, b):
    """
    >>> c_div_const_test(5, 3)
    1
    """
    return c_div_const(a, b)

cdef long c_div_const(const long a, int b):
    cdef long c = a / b
    return c
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cf_none.pyx0000644000175100001770000000451100000000000017714 0ustar00runnerdocker00000000000000
cimport cython

@cython.test_fail_if_path_exists('//NoneCheckNode')
def none_checks(a):
    """
    >>> none_checks(1)
    22
    >>> none_checks(None)
    True
    """
    c = None
    d = {11:22}
    if a is c:
        return True
    else:
        return d.get(11)

@cython.test_assert_path_exists('//NoneCheckNode')
def dict_arg(dict a):
    """
    >>> dict_arg({})
    >>> dict_arg({1:2})
    2
    """
    return a.get(1)

@cython.test_fail_if_path_exists('//NoneCheckNode')
def dict_arg_not_none(dict a not None):
    """
    >>> dict_arg_not_none({})
    >>> dict_arg_not_none({1:2})
    2
    """
    return a.get(1)

@cython.test_assert_path_exists('//NoneCheckNode')
def reassignment(dict d):
    """
    >>> reassignment({})
    (None, 2)
    >>> reassignment({1:3})
    (3, 2)
    """
    a = d.get(1)
    d = {1:2}
    b = d.get(1)
    return a, b

@cython.test_fail_if_path_exists('//NoneCheckNode')
def conditional(a):
    """
    >>> conditional(True)
    2
    >>> conditional(False)
    3
    """
    if a:
        d = {1:2}
    else:
        d = {1:3}
    return d.get(1)

@cython.test_assert_path_exists('//NoneCheckNode')
def conditional_arg(a, dict d):
    """
    >>> conditional_arg(True,  {1:2})
    >>> conditional_arg(False, {1:2})
    2
    """
    if a:
        d = {}
    return d.get(1)

@cython.test_fail_if_path_exists('//NoneCheckNode')
def conditional_not_none(a, dict d not None):
    """
    >>> conditional_not_none(True,  {1:2})
    >>> conditional_not_none(False, {1:2})
    2
    """
    if a:
        d = {}
    return d.get(1)

@cython.test_fail_if_path_exists('//NoneCheckNode')
def self_dependency(int x):
    """
    >>> self_dependency(1)
    (1, 2)
    >>> self_dependency(2)
    (None, None)
    """
    cdef dict a, b
    a = {1:2}
    b = {2:1}
    for i in range(x):
        a,b = b,a
    return a.get(2), b.get(1)

@cython.test_assert_path_exists('//NoneCheckNode')
def self_dependency_none(int x):
    """
    >>> self_dependency_none(False)
    1
    >>> self_dependency_none(True)
    Traceback (most recent call last):
    AttributeError: 'NoneType' object has no attribute 'get'
    """
    cdef dict a, b
    a = None
    b = {2:1}
    if x:
        a,b = b,a
    return b.get(2)

@cython.test_fail_if_path_exists('//NoneCheckNode')
def in_place_op():
    vals = [0]
    vals += [1]
    for x in vals:
        pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cfunc_call_tuple_args_T408.pyx0000644000175100001770000000056100000000000023343 0ustar00runnerdocker00000000000000# ticket: t408

__doc__ = """
>>> call_with_tuple(1, 1.2, 'test', [1,2,3])
(1, 1.2, 'test', [1, 2, 3])

>>> call_with_list(1, 1.2, None, None)
(1, 1.2, None, None)
"""

cdef c_function(int a, float b, c, list d):
    return a,b,c,d

def call_with_tuple(*args):
    return c_function(*args)

def call_with_list(*args):
    args = list(args)
    return c_function(*args)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cfunc_convert.pyx0000644000175100001770000001371400000000000021150 0ustar00runnerdocker00000000000000# mode: run
# tag: autowrap
# cython: always_allow_keywords=True

cimport cython

from libc.math cimport sqrt

cdef void empty_cfunc():
    print "here"

# same signature
cdef void another_empty_cfunc():
    print "there"

def call_empty_cfunc():
    """
    >>> call_empty_cfunc()
    here
    there
    """
    cdef object py_func = empty_cfunc
    py_func()
    cdef object another_py_func = another_empty_cfunc
    another_py_func()


cdef double square_c(double x):
    return x * x

def call_square_c(x):
    """
    >>> call_square_c(2)
    4.0
    >>> call_square_c(-7)
    49.0
    """
    cdef object py_func = square_c
    return py_func(x)


def return_square_c():
    """
    >>> square_c = return_square_c()
    >>> square_c(5)
    25.0
    >>> square_c(x=4)
    16.0
    >>> square_c.__doc__   # FIXME: try to make original C function name available
    'wrap(x: float) -> float'
    """
    return square_c


def return_libc_sqrt():
    """
    >>> sqrt = return_libc_sqrt()
    >>> sqrt(9)
    3.0
    >>> sqrt(x=9)
    3.0
    >>> sqrt.__doc__
    'wrap(x: float) -> float'
    """
    return sqrt


global_csqrt = sqrt

def test_global():
    """
    >>> global_csqrt(9)
    3.0
    >>> global_csqrt.__doc__
    'wrap(x: float) -> float'
    >>> test_global()
    double (double) noexcept nogil
    Python object
    """
    print cython.typeof(sqrt)
    print cython.typeof(global_csqrt)


cdef long long rad(long long x):
    cdef long long rad = 1
    for p in range(2, sqrt(x) + 1):  # MSVC++ fails without the input cast
        if x % p == 0:
            rad *= p
            while x % p == 0:
                x //= p
        if x == 1:
            break
    return rad

cdef bint abc(long long a, long long b, long long c) except -1:
    if a + b != c:
        raise ValueError("Not a valid abc candidate: (%s, %s, %s)" % (a, b, c))
    return rad(a*b*c) < c

def call_abc(a, b, c):
    """
    >>> call_abc(2, 3, 5)
    False
    >>> call_abc(1, 63, 64)
    True
    >>> call_abc(2, 3**10 * 109, 23**5)
    True
    >>> call_abc(a=2, b=3**10 * 109, c=23**5)
    True
    >>> call_abc(1, 1, 1)
    Traceback (most recent call last):
    ...
    ValueError: Not a valid abc candidate: (1, 1, 1)
    """
    cdef object py_func = abc
    return py_func(a, b, c)

def return_abc():
    """
    >>> abc = return_abc()
    >>> abc(2, 3, 5)
    False
    >>> abc.__doc__
    "wrap(a: 'long long', b: 'long long', c: 'long long') -> bool"
    """
    return abc


ctypedef double foo
cdef foo test_typedef_cfunc(foo x):
    return x

def test_typedef(x):
    """
    >>> test_typedef(100)
    100.0
    """
    return (test_typedef_cfunc)(x)


cdef union my_union:
    int a
    double b

cdef struct my_struct:
    int which
    my_union y

cdef my_struct c_struct_builder(int which, int a, double b):
    cdef my_struct value
    value.which = which
    if which:
        value.y.a = a
    else:
        value.y.b = b
    return value

def return_struct_builder():
    """
    >>> make = return_struct_builder()
    >>> d = make(0, 1, 2)
    >>> d['which']
    0
    >>> d['y']['b']
    2.0
    >>> d = make(1, 1, 2)
    >>> d['which']
    1
    >>> d['y']['a']
    1
    >>> make.__doc__
    "wrap(which: 'int', a: 'int', b: float) -> 'my_struct'"
    """
    return c_struct_builder


cdef object test_object_params_cfunc(a, b):
    return a, b

def test_object_params(a, b):
    """
    >>> test_object_params(1, 'a')
    (1, 'a')
    """
    return (test_object_params_cfunc)(a, b)


cdef tuple test_builtin_params_cfunc(list a, dict b):
    return a, b

def test_builtin_params(a, b):
    """
    >>> test_builtin_params([], {})
    ([], {})
    >>> test_builtin_params(1, 2)
    Traceback (most recent call last):
    ...
    TypeError: Argument 'a' has incorrect type (expected list, got int)
    """
    return (test_builtin_params_cfunc)(a, b)

def return_builtin_params_cfunc():
    """
    >>> cfunc = return_builtin_params_cfunc()
    >>> cfunc([1, 2], {'a': 3})
    ([1, 2], {'a': 3})
    >>> cfunc.__doc__
    'wrap(a: list, b: dict) -> tuple'
    """
    return test_builtin_params_cfunc


cdef class A:
    def __repr__(self):
        return self.__class__.__name__

cdef class B(A):
    pass

cdef A test_cdef_class_params_cfunc(A a, B b):
    return b

def test_cdef_class_params(a, b):
    """
    >>> test_cdef_class_params(A(), B())
    B
    >>> test_cdef_class_params(B(), A())
    Traceback (most recent call last):
    ...
    TypeError: Argument 'b' has incorrect type (expected cfunc_convert.B, got cfunc_convert.A)
    """
    return (test_cdef_class_params_cfunc)(a, b)

# There were a few cases where duplicate utility code definitions (i.e. with the same name)
# could be generated, causing C compile errors. This file tests them.

cdef cfunc_dup_f1(x, r):
    return "f1"

cdef cfunc_dup_f2(x1, r):
    return "f2"

def make_map():
    """
    https://github.com/cython/cython/issues/3716
    This is testing the generation of wrappers for f1 and f2
    >>> for k, f in make_map().items():
    ...    print(k == f(0, 0))  # in both cases the functions should just return their name
    True
    True

    # Test passing of keyword arguments
    >>> print(make_map()['f1'](x=1, r=2))
    f1
    >>> make_map()['f1'](x1=1, r=2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> print(make_map()['f2'](x1=1, r=2))
    f2
    >>> make_map()['f2'](x=1, r=2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    cdef map = {
        "f1": cfunc_dup_f1,
        "f2": cfunc_dup_f2,
    }
    return map


cdef class HasCdefFunc:
    cdef int x
    def __init__(self, x):
        self.x = x

    cdef int func(self, int y):
        return self.x + y

def test_unbound_methods():
    """
    >>> f = test_unbound_methods()
    >>> f(HasCdefFunc(1), 2)
    3
    """
    return HasCdefFunc.func

def test_bound_methods():
    """
    >>> f = test_bound_methods()
    >>> f(2)
    3
    """
    return HasCdefFunc(1).func
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cfuncdef.pyx0000644000175100001770000000042500000000000020062 0ustar00runnerdocker00000000000000cdef void ftang():
    cdef int x
    x = 0

cdef int foo(int i, char c):
    cdef float f, g
    f = 0
    g = 0

cdef spam(int i, obj, object object):
    cdef char c
    c = 0

def test():
    """
    >>> test()
    """
    ftang()
    foo(0, c'f')
    spam(25, None, None)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cfuncptr.pyx0000644000175100001770000000364000000000000020133 0ustar00runnerdocker00000000000000# mode: run


cdef int grail():
    cdef int (*spam)()
    spam = &grail
    spam = grail
    assert spam is grail
    assert spam == grail
    assert spam == &grail


ctypedef int funcptr_t()

cdef funcptr_t* get_grail():
    return &grail


def test_assignments():
    """
    >>> test_assignments()
    """
    grail()


def test_return_value():
    """
    >>> test_return_value()
    True
    """
    g = get_grail()
    return g == &grail


def call_cfuncptr():
    """
    >>> call_cfuncptr()
    """
    cdef int (*spam)()
    spam = grail
    spam()

cdef int exceptminus2(int bad) except -2:
    if bad:
        raise RuntimeError
    else:
        return 0

def call_exceptminus2_through_exceptstar_pointer(bad):
    """
    >>> call_exceptminus2_through_exceptstar_pointer(True)
    Traceback (most recent call last):
    ...
    RuntimeError
    >>> call_exceptminus2_through_exceptstar_pointer(False)
    0
    """
    cdef int (*fptr)(int) except *  # GH4770 - should not be treated as except? -1
    fptr = exceptminus2
    return fptr(bad)

def call_exceptminus2_through_exceptmaybeminus2_pointer(bad):
    """
    >>> call_exceptminus2_through_exceptmaybeminus2_pointer(True)
    Traceback (most recent call last):
    ...
    RuntimeError
    >>> call_exceptminus2_through_exceptmaybeminus2_pointer(False)
    0
    """
    cdef int (*fptr)(int) except ?-2  # exceptions should be compatible
    fptr = exceptminus2
    return fptr(bad)

cdef int noexcept_func():  # noexcept
    return 0

def call_noexcept_func_except_star():
    """
    >>> call_noexcept_func_except_star()
    0
    """
    cdef int (*fptr)() except *
    fptr = noexcept_func  # exception specifications are compatible
    return fptr()

def call_noexcept_func_except_check():
    """
    >>> call_noexcept_func_except_check()
    0
    """
    cdef int (*fptr)() except ?-1
    fptr = noexcept_func  # exception specifications are compatible
    return fptr()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/char_constants_T99.pyx0000644000175100001770000000057700000000000021773 0ustar00runnerdocker00000000000000# ticket: t99

cdef char c = 'c'
cdef char* s = 'abcdef'

def global_c_and_s():
    """
    >>> global_c_and_s()
    99
    abcdef
    """
    pys = s
    print c
    print (pys.decode(u'ASCII'))

def local_c_and_s():
    """
    >>> local_c_and_s()
    98
    bcdefg
    """
    cdef char c = 'b'
    cdef char* s = 'bcdefg'
    pys = s
    print c
    print (pys.decode(u'ASCII'))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/charcomparisonT412.pyx0000644000175100001770000000022300000000000021664 0ustar00runnerdocker00000000000000# ticket: t412

def f():
    """
    >>> f()
    True
    True
    """

    cdef char a
    a = 62
    print (a == '>')
    print (a == '>')
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/charencoding.pyx0000644000175100001770000000230400000000000020727 0ustar00runnerdocker00000000000000# coding: ASCII

import sys
if sys.version_info[0] < 3:
    __doc__ = u"""
>>> expected = ''.join([chr(i) for i in range(0x10,0xFF,0x11)] + [chr(0xFF)])

>>> s = test_assign()
>>> assert s == expected, repr(s)

>>> s = test_array()
>>> assert s == expected, repr(s)
"""
else:
    __doc__ = u"""
>>> expected = bytes(list(range(0x10,0xFF,0x11)) + [0xFF])

>>> s = test_assign()
>>> assert s == expected, repr(s)

>>> s = test_array()
>>> assert s == expected, repr(s)
"""

def test_assign():
    cdef char[17] s

    s[ 0] = c'\x10'
    s[ 1] = c'\x21'
    s[ 2] = c'\x32'
    s[ 3] = c'\x43'
    s[ 4] = c'\x54'
    s[ 5] = c'\x65'
    s[ 6] = c'\x76'
    s[ 7] = c'\x87'
    s[ 8] = c'\x98'
    s[ 9] = c'\xA9'
    s[10] = c'\xBA'
    s[11] = c'\xCB'
    s[12] = c'\xDC'
    s[13] = c'\xED'
    s[14] = c'\xFE'
    s[15] = c'\xFF'

    s[16] = c'\x00'

    return s

def test_array():
    cdef char* s = [
        c'\x10',
        c'\x21',
        c'\x32',
        c'\x43',
        c'\x54',
        c'\x65',
        c'\x76',
        c'\x87',
        c'\x98',
        c'\xA9',
        c'\xBA',
        c'\xCB',
        c'\xDC',
        c'\xED',
        c'\xFE',
        c'\xFF',
        c'\x00',
        ]

    return s
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/charescape.pyx0000644000175100001770000000245700000000000020412 0ustar00runnerdocker00000000000000import sys
if sys.version_info[0] < 3:
    __doc__ = u"""
>>> s = test()
>>> assert s == ''.join(map(chr, range(1,49))), repr(s)
"""
else:
    __doc__ = u"""
>>> s = test()
>>> assert s == bytes(range(1,49)), repr(s)
"""

def test():
    cdef char[50] s

    s[ 0] = c'\0'
    s[ 1] = c'\x01'
    s[ 2] = c'\x02'
    s[ 3] = c'\x03'
    s[ 4] = c'\x04'
    s[ 5] = c'\x05'
    s[ 6] = c'\x06'
    s[ 7] = c'\x07'
    s[ 8] = c'\x08'
    s[ 9] = c'\x09'
    s[10] = c'\x0A'
    s[11] = c'\x0B'
    s[12] = c'\x0C'
    s[13] = c'\x0D'
    s[14] = c'\x0E'
    s[15] = c'\x0F'
    s[16] = c'\x10'
    s[17] = c'\x11'
    s[18] = c'\x12'
    s[19] = c'\x13'
    s[20] = c'\x14'
    s[21] = c'\x15'
    s[22] = c'\x16'
    s[23] = c'\x17'
    s[24] = c'\x18'
    s[25] = c'\x19'
    s[26] = c'\x1A'
    s[27] = c'\x1B'
    s[28] = c'\x1C'
    s[29] = c'\x1D'
    s[30] = c'\x1E'
    s[31] = c'\x1F'
    s[32] = c'\x20'
    s[33] = c'\x21'
    s[34] = c'\x22'
    s[35] = c'\x23'
    s[36] = c'\x24'
    s[37] = c'\x25'
    s[38] = c'\x26'
    s[39] = c'\x27'
    s[40] = c'\x28'
    s[41] = c'\x29'
    s[42] = c'\x2A'
    s[43] = c'\x2B'
    s[44] = c'\x2C'
    s[45] = c'\x2D'
    s[46] = c'\x2E'
    s[47] = c'\x2F'
    s[48] = c'\x30'

    s[49] = c'\x00'

    assert s[ 0] == c'\x00'
    assert s[49] == c'\0'

    return &s[1]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/charptr_comparison_T582.pyx0000644000175100001770000000761300000000000022732 0ustar00runnerdocker00000000000000# ticket: t582

cimport cython

################################################################################
## plain char*

@cython.test_assert_path_exists('//SingleAssignmentNode')
#@cython.test_fail_if_path_exists('//SingleAssignmentNode//CoerceFromPyTypeNode')
def charptr_equals_literal(char* s):
    """
    >>> charptr_equals_literal('abc'.encode('ASCII'))
    True
    >>> charptr_equals_literal('aabc'.encode('ASCII'))
    False
    >>> charptr_equals_literal('abcx'.encode('ASCII'))
    False
    >>> charptr_equals_literal('bcx'.encode('ASCII'))
    False
    """
    cdef bint result = (s == b"abc")
    return result

def charptr_gt_literal(char* s):
    """
    >>> charptr_gt_literal('abc'.encode('ASCII'))
    False
    >>> charptr_gt_literal('aabc'.encode('ASCII'))
    False
    >>> charptr_gt_literal('abcx'.encode('ASCII'))
    True
    >>> charptr_gt_literal('bcx'.encode('ASCII'))
    True
    """
    cdef bint result = (s > b"abc")
    return result

def charptr_lt_literal(char* s):
    """
    >>> charptr_lt_literal('abc'.encode('ASCII'))
    False
    >>> charptr_lt_literal('aabc'.encode('ASCII'))
    True
    >>> charptr_lt_literal('abcx'.encode('ASCII'))
    False
    >>> charptr_lt_literal('bcx'.encode('ASCII'))
    False
    """
    cdef bint result = (s < b"abc")
    return result

def charptr_ge_literal(char* s):
    """
    >>> charptr_ge_literal('abc'.encode('ASCII'))
    True
    >>> charptr_ge_literal('aabc'.encode('ASCII'))
    False
    >>> charptr_ge_literal('abcx'.encode('ASCII'))
    True
    >>> charptr_ge_literal('bcx'.encode('ASCII'))
    True
    """
    cdef bint result = (s >= b"abc")
    return result

def charptr_le_literal(char* s):
    """
    >>> charptr_le_literal('abc'.encode('ASCII'))
    True
    >>> charptr_le_literal('aabc'.encode('ASCII'))
    True
    >>> charptr_le_literal('abcx'.encode('ASCII'))
    False
    >>> charptr_le_literal('bcx'.encode('ASCII'))
    False
    """
    cdef bint result = (s <= b"abc")
    return result


################################################################################
## slices

@cython.test_assert_path_exists('//SingleAssignmentNode')
#FIXME: optimise me!
#@cython.test_fail_if_path_exists('//SingleAssignmentNode//CoerceFromPyTypeNode')
def slice_equals_literal(char* s):
    """
    >>> slice_equals_literal('abc'.encode('ASCII'))
    True
    >>> slice_equals_literal('aabc'.encode('ASCII'))
    False
    >>> slice_equals_literal('abcx'.encode('ASCII'))
    True
    >>> slice_equals_literal('bcx'.encode('ASCII'))
    False
    """
    cdef bint result = (s[:3] == b"abc")
    return result

def slice_gt_literal(char* s):
    """
    >>> slice_gt_literal('abc'.encode('ASCII'))
    False
    >>> slice_gt_literal('aabc'.encode('ASCII'))
    False
    >>> slice_gt_literal('abcx'.encode('ASCII'))
    False
    >>> slice_gt_literal('bcx'.encode('ASCII'))
    True
    """
    cdef bint result = (s[:3] > b"abc")
    return result

def slice_lt_literal(char* s):
    """
    >>> slice_lt_literal('abc'.encode('ASCII'))
    False
    >>> slice_lt_literal('aabc'.encode('ASCII'))
    True
    >>> slice_lt_literal('abcx'.encode('ASCII'))
    False
    >>> slice_lt_literal('bcx'.encode('ASCII'))
    False
    """
    cdef bint result = (s[:3] < b"abc")
    return result

def slice_ge_literal(char* s):
    """
    >>> slice_ge_literal('abc'.encode('ASCII'))
    True
    >>> slice_ge_literal('aabc'.encode('ASCII'))
    False
    >>> slice_ge_literal('abcx'.encode('ASCII'))
    True
    >>> slice_ge_literal('bcx'.encode('ASCII'))
    True
    """
    cdef bint result = (s[:3] >= b"abc")
    return result

def slice_le_literal(char* s):
    """
    >>> slice_le_literal('abc'.encode('ASCII'))
    True
    >>> slice_le_literal('aabc'.encode('ASCII'))
    True
    >>> slice_le_literal('abcx'.encode('ASCII'))
    True
    >>> slice_le_literal('bcx'.encode('ASCII'))
    False
    """
    cdef bint result = (s[:3] <= b"abc")
    return result
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/charptr_decode.pyx0000644000175100001770000001202700000000000021254 0ustar00runnerdocker00000000000000
cimport cython

cdef extern from *:
    const Py_ssize_t PY_SSIZE_T_MIN
    const Py_ssize_t PY_SSIZE_T_MAX


############################################################
# tests for char* slicing

cdef const char* cstring = "abcABCqtp"

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def slice_charptr_decode():
    """
    >>> print(str(slice_charptr_decode()).replace("u'", "'"))
    ('a', 'abc', 'abcABCqtp')
    """
    return (cstring[:1].decode('UTF-8'),
            cstring[:3].decode('UTF-8'),
            cstring[:9].decode('UTF-8'))

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def slice_charptr_decode_platform_encoding():
    """
    >>> print(str(slice_charptr_decode()).replace("u'", "'"))
    ('a', 'abc', 'abcABCqtp')
    """
    cdef bytes s = u'abcABCqtp'.encode()
    cdef char* cstr = s
    return (cstr[:1].decode(),
            cstr[:3].decode(),
            cstr[:9].decode())

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def slice_charptr_decode_unknown_encoding():
    """
    >>> print(str(slice_charptr_decode_unknown_encoding()).replace("u'", "'"))
    ('abcABCqtp', 'abcABCqtp', 'abc', 'abcABCqt')
    """
    cdef const char* enc = 'UTF-8'
    cdef const char* error_handling = 'strict'
    return (cstring.decode(enc),
            cstring.decode(enc, error_handling),
            cstring[:3].decode(enc),
            cstring[:8].decode(enc, error_handling))

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def slice_charptr_decode_slice2():
    """
    >>> print(str(slice_charptr_decode_slice2()).replace("u'", "'"))
    ('a', 'bc', 'tp')
    """
    return (cstring[0:1].decode('UTF-8'),
            cstring[1:3].decode('UTF-8'),
            cstring[7:9].decode('UTF-8'))

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def slice_charptr_decode_strlen():
    """
    >>> print(str(slice_charptr_decode_strlen()).replace("u'", "'"))
    ('abcABCqtp', 'bcABCqtp', '', 'BCq', 'abcA', '')
    """
    return (cstring.decode('UTF-8'),
            cstring[1:].decode('UTF-8'),
            cstring[9:].decode('UTF-8'),
            cstring[-5:-2].decode('UTF-8'),
            cstring[:-5].decode('UTF-8'),
            cstring[:-9].decode('UTF-8'))

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def slice_charptr_decode_unbound():
    """
    >>> print(str(slice_charptr_decode_unbound()).replace("u'", "'"))
    ('a', 'abc', 'abcABCqtp')
    """
    return (bytes.decode(cstring[:1], 'UTF-8'),
            bytes.decode(cstring[:3], 'UTF-8', 'replace'),
            bytes.decode(cstring[:9], 'UTF-8'))

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def slice_charptr_decode_errormode():
    """
    >>> print(str(slice_charptr_decode_errormode()).replace("u'", "'"))
    ('a', 'abc', 'abcABCqtp')
    """
    return (cstring[:1].decode('UTF-8', 'strict'),
            cstring[:3].decode('UTF-8', 'replace'),
            cstring[:9].decode('UTF-8', 'unicode_escape'))

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def slice_charptr_dynamic_bounds():
    """
    >>> print(str(slice_charptr_dynamic_bounds()).replace("u'", "'"))
    ('abc', 'abc', 'bcAB', 'BCqtp')
    """
    return (cstring[:return3()].decode('UTF-8'),
            cstring[0:return3()].decode('UTF-8'),
            cstring[return1():return5()].decode('UTF-8'),
            cstring[return4():return9()].decode('UTF-8'))

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def slice_charptr_dynamic_bounds_non_name():
    """
    >>> print(str(slice_charptr_dynamic_bounds_non_name()).replace("u'", "'"))
    ('bcA', 'bcA', 'BCqtp', 'ABCqtp', 'bcABCqtp', 'bcABCqtp', 'cABC')
    """
    return ((cstring+1)[:return3()].decode('UTF-8'),
            (cstring+1)[0:return3()].decode('UTF-8'),
            (cstring+1)[return3():].decode('UTF-8'),
            (cstring+1)[2:].decode('UTF-8'),
            (cstring+1)[0:].decode('UTF-8'),
            (cstring+1)[:].decode('UTF-8'),
            (cstring+1)[return1():return5()].decode('UTF-8'))

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def slice_charptr_decode_large_bounds():
    """
    >>> print(str(slice_charptr_decode_large_bounds()).replace("u'", "'"))
    ('abcABCqtp', '', '', '')
    """
    return (cstring[PY_SSIZE_T_MIN:9].decode('UTF-8'),
            cstring[PY_SSIZE_T_MAX:PY_SSIZE_T_MIN].decode('UTF-8'),
            cstring[PY_SSIZE_T_MIN:PY_SSIZE_T_MIN].decode('UTF-8'),
            cstring[PY_SSIZE_T_MAX:PY_SSIZE_T_MAX].decode('UTF-8'))


cdef return1(): return 1
cdef return3(): return 3
cdef return4(): return 4
cdef return5(): return 5
cdef return9(): return 9
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/charptr_from_temp.pyx0000644000175100001770000000356400000000000022027 0ustar00runnerdocker00000000000000# mode: run

from cpython.version cimport PY_MAJOR_VERSION

cdef bint IS_PY2 = PY_MAJOR_VERSION == 2


cdef cfunc1(char* s):
    if IS_PY2:
        return s
    else:
        return s.decode('ASCII')


cdef cfunc3(int x, char* s, object y):
    return cfunc1(s)


def test_one_arg_indexing(s):
    """
    >>> test_one_arg_indexing(b'xyz')
    'y'
    """
    cfunc1(s[0]) if IS_PY2 else cfunc1(s[:1])
    z = cfunc1(s[2]) if IS_PY2 else cfunc1(s[2:])
    assert z == 'z', repr(z)
    return cfunc1(s[1]) if IS_PY2 else cfunc1(s[1:2])


def test_more_args_indexing(s):
    """
    >>> test_more_args_indexing(b'xyz')
    'y'
    """
    cfunc3(1, s[0 if IS_PY2 else slice(0,1)], 6.5)
    z = cfunc3(2, s[2 if IS_PY2 else slice(2,None)], 'abc' * 2)
    assert z == 'z', repr(z)
    return cfunc3(3, s[1 if IS_PY2 else slice(1,2)], 1)


def test_one_arg_slicing(s):
    """
    >>> test_one_arg_slicing(b'xyz')
    'y'
    """
    cfunc1(s[:2])
    z = cfunc1(s[2:])
    assert z == 'z', repr(z)
    return cfunc1(s[1:2])


def test_more_args_slicing(s):
    """
    >>> test_more_args_slicing(b'xyz')
    'y'
    """
    cfunc3(1, s[:2], 'abc')
    z = cfunc3(123, s[2:], 5)
    assert z == 'z', repr(z)
    return cfunc3(2, s[1:2], 1.4)


def test_one_arg_adding(s):
    """
    >>> test_one_arg_adding(b'xyz')
    'abxyzqr'
    """
    return cfunc1(b"a" + b"b" + s + b"q" + b"r")


def test_more_args_adding(s):
    """
    >>> test_more_args_adding(b'xyz')
    'abxyzqr'
    """
    return cfunc3(1, b"a" + b"b" + s + b"q" + b"r", 'xyz%d' % 3)


cdef char* ret_charptr(char* s):
    return s


def test_charptr_and_charptr_func(char* s):
    """
    >>> test_charptr_and_charptr_func(b'abc') == b'abc'
    True
    """
    return s and ret_charptr(s)


def test_charptr_and_ucharptr(char* s):
    """
    >>> test_charptr_and_ucharptr(b'abc') == b'abc'
    True
    """
    return s and s
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/charptr_len.pyx0000644000175100001770000000335400000000000020612 0ustar00runnerdocker00000000000000cimport cython

cdef char* s = b"abcdefg"
cdef const char* cs = b"abcdefg"
cdef unsigned char* us = b"abcdefg"
cdef const unsigned char* cus = b"abcdefg"
cdef bytes pystr =  b"abcdefg"


@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
    )
def lentest_char():
    """
    >>> lentest_char()
    7
    """
    return len(s)


@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
    )
def lentest_const_char():
    """
    >>> lentest_const_char()
    7
    """
    return len(cs)


@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
    )
def lentest_char_c():
    """
    >>> lentest_char_c()
    7
    """
    cdef Py_ssize_t l = len(s)
    return l


@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
    )
def lentest_char_c_short():
    """
    >>> lentest_char_c_short()
    7
    """
    cdef short l = len(s)
    return l


@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
    )
def lentest_char_c_float():
    """
    >>> lentest_char_c_float()
    7.0
    """
    cdef float l = len(s)
    return l


@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
    )
def lentest_uchar():
    """
    >>> lentest_uchar()
    7
    """
    return len(us)


@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
    )
def lentest_const_uchar():
    """
    >>> lentest_const_uchar()
    7
    """
    return len(cus)


@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
    )
def lentest_uchar_c():
    """
    >>> lentest_uchar_c()
    7
    """
    cdef Py_ssize_t l = len(us)
    return l


def lentest_py():
    """
    >>> lentest_py()
    7
    """
    return len(pystr)


def lentest_py_c():
    """
    >>> lentest_py_c()
    7
    """
    cdef Py_ssize_t l = len(pystr)
    return l
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/check_fused_types.pyx0000644000175100001770000001005500000000000021774 0ustar00runnerdocker00000000000000cimport cython
cimport check_fused_types_pxd

import math

ctypedef char *string_t

fused_t = cython.fused_type(int, long, float, string_t)
other_t = cython.fused_type(int, long)
base_t = cython.fused_type(short, int)

# complex_t = cython.fused_type(cython.floatcomplex, cython.doublecomplex)
cdef fused complex_t:
    float complex
    double complex

ctypedef base_t **base_t_p_p

# ctypedef cython.fused_type(char, base_t_p_p, fused_t, complex_t) composed_t
cdef fused composed_t:
    char
    int
    float
    string_t
    cython.pp_int
    float complex
    double complex
    int complex
    long complex


cdef func(fused_t a, other_t b):
    cdef int int_a
    cdef string_t string_a
    cdef other_t other_a

    if fused_t is other_t:
        print 'fused_t is other_t'
        other_a = a

    if fused_t is int:
        print 'fused_t is int'
        int_a = a

    if fused_t is string_t:
        print 'fused_t is string_t'
        string_a = a

    if fused_t in check_fused_types_pxd.unresolved_t:
        print 'fused_t in unresolved_t'

    if int in check_fused_types_pxd.unresolved_t:
        print 'int in unresolved_t'

    if string_t in check_fused_types_pxd.unresolved_t:
        print 'string_t in unresolved_t'


def test_int_int():
    """
    >>> test_int_int()
    fused_t is other_t
    fused_t is int
    fused_t in unresolved_t
    int in unresolved_t
    """
    cdef int x = 1
    cdef int y = 2

    func(x, y)

def test_int_long():
    """
    >>> test_int_long()
    fused_t is int
    fused_t in unresolved_t
    int in unresolved_t
    """
    cdef int x = 1
    cdef long y = 2

    func(x, y)

def test_float_int():
    """
    >>> test_float_int()
    fused_t in unresolved_t
    int in unresolved_t
    """
    cdef float x = 1
    cdef int y = 2

    func(x, y)

def test_string_int():
    """
    >>> test_string_int()
    fused_t is string_t
    int in unresolved_t
    """
    cdef string_t x = b"spam"
    cdef int y = 2

    func(x, y)


cdef if_then_else(fused_t a, other_t b):
    cdef other_t other_a
    cdef string_t string_a
    cdef fused_t specific_a

    if fused_t is other_t:
        print 'fused_t is other_t'
        other_a = a
    elif fused_t is string_t:
        print 'fused_t is string_t'
        string_a = a
    else:
        print 'none of the above'
        specific_a = a

def test_if_then_else_long_long():
    """
    >>> test_if_then_else_long_long()
    fused_t is other_t
    """
    cdef long x = 0, y = 0
    if_then_else(x, y)

def test_if_then_else_string_int():
    """
    >>> test_if_then_else_string_int()
    fused_t is string_t
    """
    cdef string_t x = b"spam"
    cdef int y = 0
    if_then_else(x, y)

def test_if_then_else_float_int():
    """
    >>> test_if_then_else_float_int()
    none of the above
    """
    cdef float x = 0.0
    cdef int y = 1
    if_then_else(x, y)


cdef composed_t composed(composed_t x, composed_t y):
    if composed_t in base_t_p_p or composed_t is string_t:
        if string_t == composed_t:
            print x.decode('ascii'), y.decode('ascii')
        else:
            print x[0][0], y[0][0]

        return x
    elif composed_t == string_t:
        print 'this is never executed'
    elif list():
        print 'neither is this one'
    else:
        if composed_t not in complex_t:
            print 'not a complex number'
            print  x,  y
        else:
            print 'it is a complex number'
            print x.real, x.imag

        return x + y

def test_composed_types():
    """
    >>> test_composed_types()
    it is a complex number
    0.5 0.6
    9 4
    
    not a complex number
    7 8
    15
    
    7 8
    
    spam eggs
    spam
    """
    cdef double complex a = 0.5 + 0.6j, b = 0.4 -0.2j, result
    cdef int c = 7, d = 8
    cdef int *cp = &c, *dp = &d
    cdef string_t e = "spam", f = "eggs"

    result = composed(a, b)
    print int(math.ceil(result.real * 10)), int(math.ceil(result.imag * 10))
    print

    print composed(c, d)
    print

    composed(&cp, &dp)
    print

    print composed(e, f).decode('ascii')

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/check_fused_types_pxd.pxd0000644000175100001770000000007500000000000022623 0ustar00runnerdocker00000000000000cimport cython

unresolved_t = cython.fused_type(int, float)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/check_size.srctree0000644000175100001770000001177000000000000021250 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import runner"

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from Cython.Compiler.Errors import CompileError
from distutils.core import setup

# force the build order
setup(ext_modules= cythonize("check_size.pyx"))

setup(ext_modules = cythonize("_check_size*.pyx"))

try:
    setup(ext_modules= cythonize("check_size_invalid.pyx"))
    assert False
except CompileError as e:
    pass

######## check_size_nominal.h ########

#include 

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
    PyObject_HEAD
    int f0;
    int f1;
    int f2;
} FooStructNominal;

#ifdef __cplusplus
}
#endif

######## check_size_bigger.h ########

#include 

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
    PyObject_HEAD
    int f0;
    int f1;
    int f2;
    int f3;
    int f4;
} FooStructBig;

#ifdef __cplusplus
}
#endif

######## check_size_smaller.h ########

#include 

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
    PyObject_HEAD
    int f9;
} FooStructSmall;

#ifdef __cplusplus
}
#endif


######## check_size.pyx ########

cdef class Foo:
    cdef public int field0, field1, field2;

    def __init__(self, f0, f1, f2):
        self.field0 = f0
        self.field1 = f1
        self.field2 = f2

######## _check_size_exact.pyx ########

cdef extern from "check_size_nominal.h":

    ctypedef class check_size.Foo [object FooStructNominal]:
        cdef:
            int f0
            int f1


cpdef public int testme(Foo f) except -1:
    return f.f0 + f.f1

######## _check_size_too_small.pyx ########

cdef extern from "check_size_bigger.h":

    ctypedef class check_size.Foo [object FooStructBig]:
        cdef:
            int f0
            int f1
            int f2


cpdef public int testme(Foo f, int f2) except -1:
    f.f2 = f2
    return f.f0 + f.f1 + f.f2

######## _check_size_default.pyx ########

cdef extern from "check_size_smaller.h":

    ctypedef class check_size.Foo [object FooStructSmall]:
        cdef:
            int f9


cpdef public int testme(Foo f) except -1:
    return f.f9

######## _check_size_warn.pyx ########

cdef extern from "check_size_smaller.h":

    # make sure missing check_size is equivalent to warn
    ctypedef class check_size.Foo [object FooStructSmall, check_size warn]:
        cdef:
            int f9


cpdef public int testme(Foo f) except -1:
    return f.f9

######## _check_size_ignore.pyx ########

cdef extern from "check_size_smaller.h":

    # Allow size to be larger
    ctypedef class check_size.Foo [object FooStructSmall, check_size ignore]:
        cdef:
            int f9


cpdef public int testme(Foo f) except -1:
    return f.f9

######## _check_size_error.pyx ########

cdef extern from "check_size_smaller.h":

    # Strict checking, will raise an error
    ctypedef class check_size.Foo [object FooStructSmall, check_size error]:
        cdef:
            int f9


cpdef public int testme(Foo f) except -1:
    return f.f9

######## check_size_invalid.pyx ########

cdef extern from "check_size_smaller.h":

    # Raise CompileError when using bad value
    ctypedef class check_size.Foo [object FooStructSmall, check_size hihi]:
        cdef:
            int f9


cpdef public int testme(Foo f) except -1:
    return f.f9

######## runner.py ########

import check_size, _check_size_exact, warnings

foo = check_size.Foo(23, 123, 1023)

assert foo.field0 == 23
assert foo.field1 == 123

ret =  _check_size_exact.testme(foo)
assert ret == 23 + 123

# ValueError since check_size.Foo's tp_basicsize is smaller than what is needed
# for FooStructBig. Messing with f2 will access memory outside the struct!
try:
    import _check_size_too_small
    assert False
except ValueError as e:
    assert str(e).startswith('check_size.Foo size changed')

# Warning since check_size.Foo's tp_basicsize is larger than what is needed
# for FooStructSmall. There is "spare", accessing FooStructSmall's fields will
# never access invalid memory. This can happen, for instance, when using old
# headers with a newer runtime, or when using an old _check_size{2,3} with a newer
# check_size, where the developers of check_size are careful to be backward
# compatible.

with warnings.catch_warnings(record=True) as w:
    warnings.simplefilter("always")
    import _check_size_default
    import _check_size_warn
    assert len(w) == 2, 'expected two warnings, got %d' % len(w)
    assert str(w[0].message).startswith('check_size.Foo size changed')
    assert str(w[1].message).startswith('check_size.Foo size changed')

ret = _check_size_default.testme(foo)
assert ret == 23
ret = _check_size_warn.testme(foo)
assert ret == 23

with warnings.catch_warnings(record=True) as w:
    # No warning, runtime vendor must provide backward compatibility
    import _check_size_ignore
    assert len(w) == 0

ret = _check_size_ignore.testme(foo)
assert ret == 23

try:
    # Enforce strict checking
    import _check_size_error
    assert False
except ValueError as e:
    assert str(e).startswith('check_size.Foo size changed')
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cimport.srctree0000644000175100001770000000176200000000000020616 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import a"

######## setup.py ########


from Cython.Build import cythonize
from distutils.core import setup

setup(
  ext_modules = cythonize("*.pyx"),
)

######## other.pxd ########

cdef class A:
    pass

cdef int foo(int)

######## other.pyx ########

cdef class A:
    pass

cdef int foo(int a):
     return a**2

######## pkg/__init__.py ########


######## pkg/sub.pxd ########

ctypedef int my_int

######## pkg/subpkg/__init__.py ########

######## pkg/subpkg/submod.pxd ########

ctypedef int my_int

######## a.pyx ########

from other cimport (
    A,
    foo,
)
print(A, foo(10))

cimport other

cdef call_fooptr(int (*fptr)(int)):
    return fptr(10)

def call_other_foo():
    x = other.foo  # GH4000 - failed because other was untyped
    return call_fooptr(x) # check that x is correctly resolved as a function pointer

print(other.A, other.foo(10), call_other_foo())

from pkg cimport sub
cdef sub.my_int a = 100

from pkg.subpkg cimport submod
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cimport_alias_subclass.pyx0000644000175100001770000000034100000000000023027 0ustar00runnerdocker00000000000000# mode: compile


cimport cimport_alias_subclass_helper as cash

cdef class Derived(cash.Base):
    cdef bint foo(self):
        print "Hello"

def run():
    """
    >>> run()
    Hello
    """
    d = Derived()
    d.foo()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cimport_alias_subclass_helper.pxd0000644000175100001770000000005100000000000024337 0ustar00runnerdocker00000000000000cdef class Base:
    cdef bint foo(self)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cimport_cython_T505.pyx0000644000175100001770000000040700000000000022063 0ustar00runnerdocker00000000000000# ticket: t505

cimport cython

cdef extern from "Python.h":
    cdef cython.unicode PyUnicode_DecodeUTF8(char* s, Py_ssize_t size, char* errors)

def test_capi():
    """
    >>> print(test_capi())
    abc
    """
    return PyUnicode_DecodeUTF8("abc", 3, NULL)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cimport_from_pyx.srctree0000644000175100001770000000412300000000000022533 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import a"

######## setup.py ########

from Cython.Build.Dependencies import cythonize
import Cython.Compiler.Options
Cython.Compiler.Options.cimport_from_pyx = True

from distutils.core import setup

setup(
  ext_modules = cythonize("*.pyx"),
)

######## a.pyx ########

from b cimport (Bclass, Bfunc, Bstruct, Benum, Benum_value, Btypedef, Py_EQ, Py_NE,
                DecoratedClass, cfuncOutside)
cdef Bclass b = Bclass(5)
assert Bfunc(&b.value) == b.value
assert b.anotherValue == 6, b.anotherValue
assert b.asStruct().value == b.value
cdef Btypedef b_type = &b.value
cdef Benum b_enum = Benum_value
cdef int tmp = Py_EQ

cdef DecoratedClass dc = DecoratedClass()
assert dc.cfuncInClass().value == 5
assert dc.cpdefInClass() == 1.0

assert cfuncOutside().value == 2

#from c cimport ClassC
#cdef ClassC c = ClassC()
#print c.value

######## b.pyx ########

from cpython.object cimport Py_EQ, Py_NE

cimport cython

cdef enum Benum:
    Benum_value

cdef struct Bstruct:
    int value

ctypedef long *Btypedef

cdef class Bclass:
    cdef long value
    anotherValue: cython.double
    def __init__(self, value):
        self.value = value
        self.anotherValue = value + 1
    cdef Bstruct asStruct(self):
        return Bstruct(value=self.value)
    cdef double getOtherValue(self):
        return self.anotherValue

cdef long Bfunc(Btypedef x):
    return x[0]

@cython.cclass
class DecoratedClass:
    @cython.cfunc
    @cython.returns(Bstruct)
    def cfuncInClass(self):
        return Bstruct(value=5)
    @cython.ccall
    @cython.returns(cython.double)
    def cpdefInClass(self):
        return 1.0

@cython.cfunc
@cython.returns(Bstruct)
def cfuncOutside():
    return Bstruct(value=2)

######## c.pxd ########

cdef class ClassC:
    cdef int value

######## d.pyx ########

ctypedef fused fused_type:
    long
    double

cdef fused_checker(fused_type i):
    if fused_type is long:
        return True
    else:
        return False

cpdef fused_cpdef(fused_type i):
    return not fused_checker(i)

def test():
    return fused_checker(0) and fused_cpdef(1.0)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cimport_from_sys_path.srctree0000644000175100001770000000120600000000000023544 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import a"

######## setup.py ########

from Cython.Build import cythonize
from distutils.core import setup

# Add ./site-packages to sys.path
from os.path import realpath
import sys
sys.path.append(realpath('site-packages'))

setup(
  ext_modules = cythonize("*.pyx"),
)

######## site-packages/b/__init__.py ########

######## site-packages/b/other.pxd ########

cdef extern from "foo.c":
    int foo(int)

######## site-packages/b/foo.c ########

static int foo(int a)
{
    return a * a;
}

######## a.pyx ########

from b.other cimport foo
print(foo(10))

cimport b.other
print(b.other.foo(10))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/cintop.pyx0000644000175100001770000000213500000000000017601 0ustar00runnerdocker00000000000000# mode: run

__doc__ = u"""
    >>> int2 = 42
    >>> int3 = 7
    >>> char1 = ord('C')

    >>> int1 = int2 | int3
    >>> int1 |= int2 ^ int3
    >>> int1 ^= int2 & int3
    >>> int1 ^= int2 << int3
    >>> int1 ^= int2 >> int3
    >>> int1 ^= int2 << int3 | int2 >> int3
    >>> long1 = char1 | int1
    >>> (int1, long1) == f()
    True

"""

def f():
    """
    >>> f()
    (45, 111)
    """
    cdef int int1, int2, int3
    cdef char char1
    cdef long long1, long2
    int2 = 42
    int3 = 7
    char1 = c'C'

    int1 = int2 | int3
    int1 |= int2 ^ int3
    int1 ^= int2 & int3
    int1 ^= int2 << int3
    int1 ^= int2 >> int3
    int1 ^= int2 << int3 | int2 >> int3
    long1 = char1 | int1
    return int1, long1


def long_int_shift():
    """
    >>> long_int_shift()
    80082
    10010
    10010
    10010
    10010
    """
    value = 80082 # int using more than 2 bytes == long
    print(value)
    shiftedby3 = value >> 3
    dividedby8 = value // 8
    print(shiftedby3)
    print(dividedby8)
    shiftedby3 = 80082 >> 3
    dividedby8 = 80082 // 8
    print(shiftedby3)
    print(dividedby8)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/class_attribute_init_values_T18.pyx0000644000175100001770000000136300000000000024535 0ustar00runnerdocker00000000000000# ticket: t18

__doc__ = u"""
>>> f = PyFoo()
>>> print(f.bar)
5
>>> print(f.baz)
someval

>>> f = MyPyFoo()
>>> print(f.bar)
7
>>> print(f.baz)
anotherval

>>> f = CyFoo()
>>> print(f.bar)
5
>>> print(f.baz)
anotherval

>>> f = MyCyFoo()
>>> print(f.bar)
7
>>> print(f.baz)
anotherval

>>> f = AnotherFoo()
>>> print(f.bar)
8
>>> print(f.baz)
yetanotherval
"""

# this works:

class PyFoo(object):
   bar = 5
   baz = u"someval"

class MyPyFoo(PyFoo):
   bar = 7
   baz = u"anotherval"

# this doesn't:

cdef class CyFoo:
    cdef public int bar = 5
    cdef public object baz = u"someval"

cdef class MyCyFoo(CyFoo):
    cdef public int bar = 7
    cdef public object baz = u"anotherval"

class AnotherFoo(CyFoo):
    bar = 8
    baz = u"yetanotherval"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/class_func_in_control_structures_T87.pyx0000644000175100001770000000201500000000000025615 0ustar00runnerdocker00000000000000# ticket: t87

__doc__ = u"""
>>> d = Defined()
>>> n = NotDefined()         # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'NotDefined' is not defined
"""

if True:
    class Defined(object):
        """
        >>> isinstance(Defined(), Defined)
        True
        """

if False:
    class NotDefined(object):
        """
        >>> NotDefined() # fails when defined
        """

def test_class_cond(x):
    """
    >>> Test, test = test_class_cond(True)
    >>> test.A
    1
    >>> Test().A
    1
    >>> Test, test = test_class_cond(False)
    >>> test.A
    2
    >>> Test().A
    2
    """
    if x:
        class Test(object):
            A = 1
    else:
        class Test(object):
            A = 2
    return Test, Test()

def test_func_cond(x):
    """
    >>> func = test_func_cond(True)
    >>> func()
    1
    >>> func = test_func_cond(False)
    >>> func()
    2
    """
    if x:
        def func():
            return 1
    else:
        def func():
            return 2
    return func
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/class_redefine.py0000644000175100001770000000041600000000000021063 0ustar00runnerdocker00000000000000
class set(object):
    def __init__(self, x):
        self.x = x

SET = set([1])

class set(object):
    def __init__(self, x):
        self.X = x

def test_class_redef(x):
    """
    >>> SET.x
    [1]
    >>> test_class_redef(2).X
    [2]
    """
    return set([x])
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/class_scope.py0000644000175100001770000000027400000000000020415 0ustar00runnerdocker00000000000000# mode:run
# tag: class, scope

class MethodRedef(object):
    """
    >>> MethodRedef().a(5)
    7
    """

    def a(self, i):
        return i+1

    def a(self, i):
        return i+2
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3927221
Cython-3.0.8/tests/run/class_scope_del_T684.py0000644000175100001770000000042500000000000021764 0ustar00runnerdocker00000000000000# mode:run
# tag: class, scope, del
# ticket: t684

class DelInClass(object):
    """
    >>> DelInClass.y
    5
    >>> DelInClass.x
    Traceback (most recent call last):
    AttributeError: type object 'DelInClass' has no attribute 'x'
    """
    x = 5
    y = x
    del x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/classbody_exec.pyx0000644000175100001770000000037000000000000021273 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> print(D)
    {u'answer': (42, 42)}
"""

import sys
if sys.version_info[0] >= 3:
    __doc__ = __doc__.replace(u"u'", u"'")

D = {}

def foo(x):
    return x, x

cdef class Spam:
    answer = 42
    D[u'answer'] = foo(answer)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/classdecorators_T336.pyx0000644000175100001770000000151500000000000022220 0ustar00runnerdocker00000000000000# ticket: t336

__doc__ = u"""
>>> print('\\n'.join(calls))
Py-Honk PyTestClass
PyTestClass
Py-Hello PyTestClass
PyTestClass
Py-Done PyTestClass

>>> c = PyTestClass()
Ho, Ho, Ho!
"""

calls = []

class print_msg(object):
    def __init__(self, message):
        self.msg = message
    def __call__(self, c):
        calls.append( self.msg + c.__name__ )
        return c

def print_name(c):
    calls.append( c.__name__ )
    return c

@print_msg(u"Py-Done ")
@print_name
@print_msg(u"Py-Hello ")
@print_name
@print_msg(u"Py-Honk ")
class PyTestClass(object):
    def __init__(self):
        print u"Ho, Ho, Ho!"

# not currently working:
#
## @print_msg("Cy-Done ")
## @print_name
## @print_msg("Cy-Hello ")
## @print_name
## @print_msg("Cy-Honk ")
## cdef class CyTestClass(object):
##     def __init__(self):
##         print u"Ho, Ho, Ho!"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/classkwonlyargs.pyx0000644000175100001770000000555300000000000021542 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> spam = Spam()
    >>> b,c,d,e,f,g,h,k = spam.b,spam.c,spam.d,spam.e,spam.f,spam.g,spam.h,spam.k

    >>> b(1,2,3)
    >>> b(1,2,3,4)
    Traceback (most recent call last):
    TypeError: b() takes exactly 4 positional arguments (5 given)

    >>> c(1,2)
    >>> c(1,2,3)
    >>> c(1,2,3,4)
    Traceback (most recent call last):
    TypeError: c() takes at most 4 positional arguments (5 given)

    >>> d(1,2)
    >>> d(1,2, c=1)

    >>> d(1,2,3)
    Traceback (most recent call last):
    TypeError: d() takes exactly 3 positional arguments (4 given)
    >>> d(1,2, d=1)
    Traceback (most recent call last):
    TypeError: d() got an unexpected keyword argument 'd'

    >>> e(1,2)
    >>> e(1,2, c=1)
    >>> e(1,2, d=1)
    >>> e(1,2, c=1, d=2, e=3)
    >>> e(1,2,3)
    >>> e(1,2,3,4)
    Traceback (most recent call last):
    TypeError: e() takes at most 4 positional arguments (5 given)

    >>> f(1,2, c=1)
    >>> f(1,2, c=1, d=2)

    >>> f(1,2,3)
    Traceback (most recent call last):
    TypeError: f() takes exactly 3 positional arguments (4 given)
    >>> f(1,2)
    Traceback (most recent call last):
    TypeError: f() needs keyword-only argument c
    >>> f(1,2, c=1, e=2)
    Traceback (most recent call last):
    TypeError: f() got an unexpected keyword argument 'e'

    >>> g(1,2, c=1, f=2)
    >>> g(1,2, c=1, e=0, f=2, d=11)
    >>> g(1,2, c=1, f=2, e=0, x=25)

    >>> g(1,2,3)
    Traceback (most recent call last):
    TypeError: g() takes exactly 3 positional arguments (4 given)
    >>> g(1,2)
    Traceback (most recent call last):
    TypeError: g() needs keyword-only argument c
    >>> g(1,2, c=1)
    Traceback (most recent call last):
    TypeError: g() needs keyword-only argument f

    >>> h(1,2, c=1, f=2)
    >>> h(1,2, c=1, f=2, e=3)
    >>> h(1,2,3,4,5,6, c=1, f=2)
    >>> h(1,2,3,4,5,6, c=1, f=2, e=3, x=25, y=11)

    >>> h(1,2,3)
    Traceback (most recent call last):
    TypeError: h() needs keyword-only argument c
    >>> h(1,2, d=1)
    Traceback (most recent call last):
    TypeError: h() needs keyword-only argument c

    >>> k(1,2, c=1, f=2)
    >>> k(1,2, c=1, f=2, e=3)
    >>> k(1,2,3,4,5,6, d=1, f=2)
    >>> k(1,2,3,4,5,6, d=1, f=2, e=3, x=25, y=11)

    >>> k(1,2,3)
    Traceback (most recent call last):
    TypeError: k() needs keyword-only argument f
    >>> k(1,2, d=1)
    Traceback (most recent call last):
    TypeError: k() needs keyword-only argument f
"""

class Spam:
    def b(self, a, b, c):
        pass

    def c(self, a, b, c=1):
        pass

    def d(self, a, b, *, c = 88):
        pass

    def e(self, a, b, c = 88, **kwds):
        pass

    def f(self, a, b, *, c, d = 42):
        pass

    def g(self, a, b, *, c, d = 42, e = 17, f, **kwds):
        pass

    def h(self, a, b, *args, c, d = 42, e = 17, f, **kwds):
        pass

    def k(self, a, b, c=1, *args, d = 42, e = 17, f, **kwds):
        pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/classmethod.pyx0000644000175100001770000000270000000000000020611 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> class1.plus(1)
6
>>> class1.view()
class1
>>> class1().view()
class1
>>> class1.bview()
class1
>>> class1().bview()
class1
>>> class1().cview()
class1
>>> class1().cview("XX")
class1XX

>>> class2.view()
class2
>>> class2.plus(1)
7

>>> class3.view()
class3
>>> class3.bview()
class3
>>> class3().bview()
class3
>>> class3.plus(1)
8

>>> class4.view()
class4
>>> class5.view()
class5
"""

cimport cython

def f_plus(cls, a):
    return cls.a + a

def second_decorator(f):
    # note - a class, not a function (didn't pass Cython's test in __Pyx_Method_ClassMethod)
    class C:
        def __call__(self, *args):
            return f(*args)
    return C()

class class1:
    a = 5
    plus = classmethod(f_plus)
    def view(cls):
        print cls.__name__
    view = classmethod(view)

    @classmethod
    @cython.binding(True)
    def bview(cls):
        print cls.__name__

    @classmethod
    @second_decorator
    def cview(cls, s=""):
        print cls.__name__+s


class class2(object):
    a = 6
    plus = classmethod(f_plus)
    def view(cls):
        print cls.__name__
    view = classmethod(view)


cdef class class3:
    a = 7
    plus = classmethod(f_plus)
    def view(cls):
        print cls.__name__
    view = classmethod(view)

    @classmethod
    @cython.binding(True)
    def bview(cls):
        print cls.__name__


class class4:
    @classmethod
    def view(cls):
        print cls.__name__


class class5(class4):
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/classpass.pyx0000644000175100001770000000026500000000000020303 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> s = Spam()
    >>> s.__class__.__name__
    'Spam'

    >>> s = SpamT()
    >>> type(s).__name__
    'SpamT'
"""

class Spam: pass

class SpamT(object): pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/clear_to_null.pyx0000644000175100001770000000351600000000000021133 0ustar00runnerdocker00000000000000"""
Check that Cython generates a tp_clear function that actually clears object
references to NULL instead of None.

Discussed here: https://article.gmane.org/gmane.comp.python.cython.devel/14833
"""

from cpython.ref cimport PyObject, Py_TYPE

cdef class ExtensionType:
    """
    Just a type which is handled by a specific C type (instead of PyObject)
    to check that tp_clear works when the C pointer is of a type different
    from PyObject *.
    """


# Pull tp_clear for PyTypeObject as I did not find another way to access it
# from Cython code.

cdef extern from "Python.h":
    ctypedef struct PyTypeObject:
        void (*tp_clear)(object)


cdef class TpClearFixture:
    """
    An extension type that has a tp_clear method generated to test that it
    actually clears the references to NULL.

    >>> fixture = TpClearFixture()
    >>> isinstance(fixture.extension_type, ExtensionType)
    True
    >>> isinstance(fixture.any_object, str)
    True
    >>> fixture.call_tp_clear()
    >>> fixture.check_any_object_status()
    'NULL'
    >>> fixture.check_extension_type_status()
    'NULL'
    """
    
    cdef readonly object any_object
    cdef readonly ExtensionType extension_type

    def __cinit__(self):
        self.any_object = "Hello World"
        self.extension_type = ExtensionType()

    def call_tp_clear(self):
        cdef PyTypeObject *pto = Py_TYPE(self)
        pto.tp_clear(self)

    def check_any_object_status(self):
        if (self.any_object) == NULL:
            return 'NULL'
        elif self.any_object is None:
            return 'None' 
        else:
            return 'not cleared'

    def check_extension_type_status(self):
        if (self.any_object) == NULL:
            return 'NULL'
        elif self.any_object is None:
            return 'None' 
        else:
            return 'not cleared'
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/clone_type.pyx0000644000175100001770000000047200000000000020450 0ustar00runnerdocker00000000000000cdef class MyType:
    def dup(self):
        """
        >>> x1 = MyType()
        >>> isinstance(x1, MyType)
        True
        >>> x2 = x1.dup()
        >>> isinstance(x2, MyType)
        True
        >>> x1 != x2
        True
        """
        cdef MyType clone = type(self)()
        return clone
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/closure_arg_type_error.pyx0000644000175100001770000000205600000000000023066 0ustar00runnerdocker00000000000000# mode: run
# tag: closures

# The arguments in f() are put into the closure one after the other,
# so the reference of 'o' is filled in before the type errors are
# found.  This leaves a reference in the closure instance on error
# return, which must be properly ref-counted to facilitate generic
# closure deallocation.  In the case of an argument type error, it's
# actually best to just Py_CLEAR() the already handled references, as
# this frees them as early as possible.

# This test doesn't really check the ref-counting itself, it just
# reproduces the problem.


def func_with_typed_args(object o, int i, tuple t, double d):
    """
    >>> g = func_with_typed_args(1, 2, (), 3.0)
    >>> g()
    (1, 2, (), 3.0)

    >>> g = func_with_typed_args(1, 'x', (), 3.0)
    Traceback (most recent call last):
    TypeError: an integer is required

    >>> g = func_with_typed_args(1, 2, 3, 3.0)
    Traceback (most recent call last):
    TypeError: Argument 't' has incorrect type (expected tuple, got int)
    """
    def g():
        return o, i, t, d
    return g
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/closure_class_T596.pyx0000644000175100001770000000210200000000000021667 0ustar00runnerdocker00000000000000# mode: run
# tag: closures
# ticket: t596

def simple(a, b):
    """
    >>> kls = simple(1, 2)
    >>> kls().result()
    3
    """
    class Foo:
        def result(self):
            return a + b
    return Foo

def nested_classes(a, b):
    """
    >>> kls = nested_classes(1, 2)
    >>> kls().result(-3)
    0
    """
    class Foo:
        class Bar:
            def result(self, c):
                return a + b + c
    return Foo.Bar

def staff(a, b):
    """
    >>> kls = staff(1, 2)
    >>> kls.static()
    (1, 2)
    >>> kls.klass()
    ('Foo', 1, 2)
    >>> obj = kls()
    >>> obj.member()
    (1, 2)
    """
    class Foo:
        def member(self):
            return a, b
        @staticmethod
        def static():
            return a, b
        @classmethod
        def klass(cls):
            return cls.__name__, a, b
    return Foo

def nested2(a):
    """
    >>> obj = nested2(1)
    >>> f = obj.run(2)
    >>> f()
    3
    """
    class Foo:
        def run(self, b):
            def calc():
                return a + b
            return calc
    return Foo()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/closure_decorators_T478.pyx0000644000175100001770000000206600000000000022737 0ustar00runnerdocker00000000000000# mode: run
# tag: closures
# ticket: t478

__doc__ = """
    >>> Num(13).is_prime()
    args (Num(13),) kwds {}
    True
    >>> Num(13).is_prime(True)
    args (Num(13), True) kwds {}
    True
    >>> Num(15).is_prime(print_factors=True)
    args (Num(15),) kwds {'print_factors': True}
    3 5
    False
"""

def print_args(func):
    def f(*args, **kwds):
        print "args", args, "kwds", kwds
        return func(*args, **kwds)
    return f


cdef class Num:

    cdef int n

    def __init__(self, n):
        self.n = n

    def __repr__(self):
        return "Num(%s)" % self.n

    @print_args
    def is_prime(self, bint print_factors=False):
        if self.n == 2:
            return True
        elif self.n < 2:
            return False
        elif self.n % 2 == 0:
            if print_factors:
                print 2, self.n // 2
        cdef int i = 3
        while i*i <= self.n:
            if self.n % i == 0:
                if print_factors:
                    print i, self.n // i
                return False
            i += 2
        return True
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/closure_in_derived_class_T2967.pyx0000644000175100001770000000054500000000000024154 0ustar00runnerdocker00000000000000# mode: run
# tag: closures
# ticket: 2967

cdef class BaseClass:
    cdef func(self):
        pass
cdef class ClosureInsideExtensionClass(BaseClass):
    """
    >>> y = ClosureInsideExtensionClass(42)
    >>> y.test(42)
    43
    """
    cdef func(self):
        a = 1
        return (lambda x : x+a)
    def test(self, b):
        return self.func()(b)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/closure_inlining.pyx0000644000175100001770000000754500000000000021662 0ustar00runnerdocker00000000000000# cython: optimize.inline_defnode_calls=True
# mode: run
cimport cython

@cython.test_fail_if_path_exists('//SimpleCallNode')
@cython.test_assert_path_exists('//InlinedDefNodeCallNode')
def simple_noargs():
    """
    >>> simple_noargs()
    123
    """
    def inner():
        return 123
    return inner()


@cython.test_fail_if_path_exists('//SimpleCallNode')
@cython.test_assert_path_exists('//InlinedDefNodeCallNode')
def test_coerce(a, int b):
    """
    >>> test_coerce(2, 2)
    4
    """
    def inner(int a, b):
        return a * b
    return inner(a, b)


cdef class Foo(object):
    def __repr__(self):
        return ''


@cython.test_fail_if_path_exists('//SimpleCallNode')
@cython.test_assert_path_exists('//InlinedDefNodeCallNode')
def test_func_signature(a):
    """
    >>> test_func_signature(Foo())
    
    >>> test_func_signature(123)
    Traceback (most recent call last):
    TypeError: Cannot convert int to closure_inlining.Foo
    """

    def inner(Foo a):
        return a
    return inner(a)

@cython.test_fail_if_path_exists('//SimpleCallNode')
@cython.test_assert_path_exists('//InlinedDefNodeCallNode')
def test_func_signature2(a, b):
    """
    >>> test_func_signature2(Foo(), 123)
    (, 123)
    >>> test_func_signature2(321, 123)
    Traceback (most recent call last):
    TypeError: Cannot convert int to closure_inlining.Foo
    """

    def inner(Foo a, b):
        return a, b
    return inner(a, b)

# Starred args and default values are not yet supported for inlining
@cython.test_assert_path_exists('//SimpleCallNode')
def test_defaults(a, b):
    """
    >>> test_defaults(1, 2)
    (1, 2, 123)
    """
    def inner(a, b=b, c=123):
        return a, b, c
    return inner(a)

@cython.test_assert_path_exists('//SimpleCallNode')
def test_kwonly_args(a, b):
    """
    >>> test_kwonly_args(1, 2)
    (1, 2, 123)
    """
    def inner(a, b=b, *, c=123):
        return a, b, c
    return inner(a)

@cython.test_assert_path_exists('//SimpleCallNode')
def test_kwonly_args_missing(a, b):
    """
    >>> test_kwonly_args_missing(1, 2)
    Traceback (most recent call last):
    TypeError: inner() needs keyword-only argument c
    """
    def inner(a, b=b, *, c):
        return a, b, c
    return inner(a)

@cython.test_assert_path_exists('//SimpleCallNode')
def test_starred(a):
    """
    >>> test_starred(123)
    (123, (), {})
    """
    def inner(a, *args, **kwargs):
        return a, args, kwargs
    return inner(a)


def test_global_calls_still_work():
    """
    >>> global_call_result
    123
    """
    return 123

global_call_result = test_global_calls_still_work()


@cython.test_fail_if_path_exists(
    '//InlinedDefNodeCallNode//SimpleCallNode')
@cython.test_assert_path_exists(
    '//InlinedDefNodeCallNode',
    '//InlinedDefNodeCallNode[@function_name.name = "call"]',
    '//InlinedDefNodeCallNode//InlinedDefNodeCallNode')
def test_sideeffect_call_order():
    """
    >>> test_sideeffect_call_order()
    [2, 4, 5]
    """
    L = []
    def sideeffect(x):
        L.append(x)
        return x
    def call(x1, x2, x3, x4, x5):
        pass
    call(1, sideeffect(2), 3, sideeffect(4), sideeffect(5))
    return L


def test_redef(redefine):
    """
    >>> test_redef(False)
    1
    >>> test_redef(True)
    2
    """
    def inner():
        return 1
    def inner2():
        return 2
    def redef():
        nonlocal inner
        inner = inner2
    if redefine:
        redef()
        assert inner == inner2
    else:
        assert inner != inner2
    return inner()


def test_with_statement():
    """
    >>> test_with_statement()
    enter
    running
    exit
    """
    def make_context_manager():
        class CM(object):
            def __enter__(self):
                print "enter"
            def __exit__(self, *args):
                print "exit"
        return CM()

    with make_context_manager():
        print "running"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/closure_inside_cdef_T554.pyx0000644000175100001770000000134300000000000023016 0ustar00runnerdocker00000000000000# mode: run
# tag: closures
# ticket: t554

def call_f(x):
    """
    >>> call_f(2)
    4
    """
    return f(x)


cdef f(x):                # def  here => works fine
   def g(y): return y*x   # cdef here => compile error
   return g(x)            # faults@ INCREF(.*cur_scope->.*v_x


def closure_in_void():
    """
    >>> genex = closure_in_void()
    >>> list(genex)
    ['a', 'b', 'c']
    """
    l = []
    add_gen(l)
    return l[0]


cdef void add_gen(l):
    x = "abc"
    l.append((c for c in x))


def closure_in_int():
    """
    >>> genex = closure_in_int()
    >>> list(genex)
    ['a', 'b', 'c']
    """
    l = []
    add_gen_int(l)
    return l[0]


cdef int add_gen_int(l):
    x = "abc"
    l.append((c for c in x))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/closure_leak_1.pyx0000644000175100001770000000032700000000000021176 0ustar00runnerdocker00000000000000# mode: run
# tag: closure

def reassign_args(x, *args):
    """
    >>> reassign_args(1, [1,2,3,4])
    """
    a,args = args[0], args[1:]
    b = False
    if b:
        c = x.map_coefficients(lambda c: c(*args))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/closure_name_mangling_T537.pyx0000644000175100001770000000055700000000000023365 0ustar00runnerdocker00000000000000# mode: run
# tag: closures
# ticket: t537

__doc__ = u"""
>>> f1 = nested1()
>>> f2 = nested2()
>>> f1 == f2      # inner functions (f)
False
>>> f1() == f2()  # inner-inner functions (g)
False
"""

def nested1():
   def f():
      def g():
         pass
      return g
   return f

def nested2():
   def f():
      def g():
         pass
      return g
   return f
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/closure_names.pyx0000644000175100001770000000404000000000000021141 0ustar00runnerdocker00000000000000# mode: run
# tag: closures
# ticket: 1797


def func():
    """
    >>> funcs = func()
    >>> [f(1) for f in funcs]  # doctest: +NORMALIZE_WHITESPACE
    ['eq',
     'str',
     'weakref',
     'new',
     'getitem',
     'setitem',
     'delitem',
     'getslice',
     'setslice',
     'delslice_',
     'getattr',
     'getattribute',
     'setattr',
     'delattr',
     'get',
     'set',
     'delete',
     'dict',
     'dealloc',
     'cinit']
    """
    def __eq__(a):
        return 'eq'

    def __str__(a):
        return 'str'

    def __weakref__(a):
        return 'weakref'

    def __new__(a):
        return 'new'

    def __getitem__(a):
        return 'getitem'

    def __setitem__(a):
        return 'setitem'

    def __delitem__(a):
        return 'delitem'

    def __getslice__(a):
        return 'getslice'

    def __setslice__(a):
        return 'setslice'

    def __delslice__(a):
        return 'delslice_'

    def __getattr__(a):
        return 'getattr'

    def __getattribute__(a):
        return 'getattribute'

    def __setattr__(a):
        return 'setattr'

    def __delattr__(a):
        return 'delattr'

    def __get__(a):
        return 'get'

    def __set__(a):
        return 'set'

    def __delete__(a):
        return 'delete'

    def __dict__(a):
        return 'dict'

    def __dealloc__(a):
        return 'dealloc'

    def __cinit__(a):
        return 'cinit'

    def list_from_gen(g):
        return list(g)

    # move into closure by using inside of generator expression
    return list_from_gen([
            __eq__,
            __str__,
            __weakref__,
            __new__,
            __getitem__,
            __setitem__,
            __delitem__,
            __getslice__,
            __setslice__,
            __delslice__,
            __getattr__,
            __getattribute__,
            __setattr__,
            __delattr__,
            __get__,
            __set__,
            __delete__,
            __dict__,
            __dealloc__,
            __cinit__,
        ][i] for i in range(20))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/closure_self.pyx0000644000175100001770000000225600000000000020776 0ustar00runnerdocker00000000000000# mode: run
# tag: closures
cdef class Test:
    cdef int x

cdef class SelfInClosure(object):
    cdef Test _t
    cdef int x

    def plain(self):
        """
        >>> o = SelfInClosure()
        >>> o.plain()
        1
        """
        self.x = 1
        return self.x

    def closure_method(self):
        """
        >>> o = SelfInClosure()
        >>> o.closure_method()() == o
        True
        """
        def nested():
            return self
        return nested

    def closure_method_cdef_attr(self, Test t):
        """
        >>> o = SelfInClosure()
        >>> o.closure_method_cdef_attr(Test())()
        (1, 2)
        """
        t.x = 2
        self._t = t
        self.x = 1
        def nested():
            return self.x, t.x
        return nested

    def call_closure_method_cdef_attr_c(self, Test t):
        """
        >>> o = SelfInClosure()
        >>> o.call_closure_method_cdef_attr_c(Test())()
        (1, 2)
        """
        return self.closure_method_cdef_attr_c(t)

    cdef closure_method_cdef_attr_c(self, Test t):
        t.x = 2
        self._t = t
        self.x = 1
        def nested():
            return self.x, t.x
        return nested
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/closure_tests_1.pyx0000644000175100001770000001552300000000000021430 0ustar00runnerdocker00000000000000# mode: run
# tag: closures
# preparse: id
# preparse: def_to_cdef
#
# closure_tests_1.pyx
#
# Battery of tests for closures in Cython. Based on the collection of
# compiler tests from P423/B629 at Indiana University, Spring 1999 and
# Fall 2000. Special thanks to R. Kent Dybvig, Dan Friedman, Kevin
# Millikin, and everyone else who helped to generate the original
# tests. Converted into a collection of Python/Cython tests by Craig
# Citro.
#
# Note: This set of tests is split (somewhat randomly) into several
# files, simply because putting all the tests in a single file causes
# gcc and g++ to buckle under the load.
#

def g1425():
    """
    >>> g1425()
    142
    """
    if (True):
      def g1424():
        if (True):
          return 122
      return (20)+(g1424())
    else:
      return 10000


def g1432():
    """
    >>> g1432()
    [0, []]
    """
    def g1431():
      return [0,[]]
    x_1056 = g1431()
    if (x_1056):
      def g1430():
        def g1429():
          return (x_1056[0])
        def g1428():
          return (x_1056[0])
        return (g1429())+(g1428())
      x_1056[0] = g1430()
    return x_1056


def g1435():
    """
    >>> g1435()
    4000
    """
    def g1434():
      def g1433(y_1057):
        return y_1057
      return g1433
    return g1434()(4000)


def g1438():
    """
    >>> g1438()
    1
    """
    def g1437():
      def g1436(x_1058):
        return x_1058
      return g1436
    f_1059 = g1437()
    return (f_1059(0)+1)


def g1441():
    """
    >>> g1441()
    4
    """
    def g1440():
      def g1439(y_1060):
        return y_1060
      return g1439
    f_1061 = g1440()
    return f_1061(f_1061(4))


def g1446():
    """
    >>> g1446()
    4
    """
    def g1445():
      def g1444(f_1063):
        return f_1063(f_1063(4))
      return g1444
    def g1443():
      def g1442(y_1062):
        return y_1062
      return g1442
    return g1445()(g1443())


def g1449():
    """
    >>> g1449()
    9000
    """
    def g1448():
      a_1064 = 4000
      def g1447(b_1065):
        return (a_1064)+(b_1065)
      return g1447
    return g1448()(5000)


def g1454():
    """
    >>> g1454()
    9000
    """
    def g1453():
      def g1452():
        def g1450(a_1066):
          def g1451(b_1067):
            return (a_1066)+(b_1067)
          return g1451
        return g1450
      return g1452()(4000)
    return g1453()(5000)


def g1459():
    """
    >>> g1459()
    2
    """
    def g1458():
      def g1457(f_1069):
        return f_1069(f_1069(0))
      return g1457
    def g1456():
      def g1455(x_1068):
        return (x_1068+1)
      return g1455
    return g1458()(g1456())


def g1462():
    """
    >>> g1462()
    0
    """
    x_1072 = 0
    def g1461():
      def g1460(x_1070):
        return x_1070
      return g1460
    f_1071 = g1461()
    a_1075 = f_1071(x_1072)
    b_1074 = f_1071(x_1072)
    c_1073 = f_1071(x_1072)
    return ((a_1075)+(b_1074))+(c_1073)


def g1465():
    """
    >>> g1465()
    3
    """
    x_1080 = 0
    y_1079 = 1
    z_1078 = 2
    def g1464():
      def g1463(x_1076):
        return x_1076
      return g1463
    f_1077 = g1464()
    a_1083 = f_1077(x_1080)
    b_1082 = f_1077(y_1079)
    c_1081 = f_1077(z_1078)
    return ((a_1083)+(b_1082))+(c_1081)


def g1468():
    """
    >>> g1468()
    0
    """
    def g1467():
      def g1466(x_1085, y_1084):
        return x_1085
      return g1466
    f_1086 = g1467()
    a_1087 = f_1086(0, 1)
    return f_1086(a_1087, a_1087)


def g1471():
    """
    >>> g1471()
    0
    """
    x_1094 = 0
    y_1093 = 1
    z_1092 = 2
    def g1470():
      def g1469(x_1090, y_1089, z_1088):
        return x_1090
      return g1469
    f_1091 = g1470()
    a_1097 = f_1091(x_1094, y_1093, z_1092)
    b_1096 = y_1093
    c_1095 = z_1092
    return f_1091(a_1097, b_1096, c_1095)


def g1474():
    """
    >>> g1474()
    3
    """
    def g1473():
      def g1472(a_1101, b_1100, c_1099, d_1098):
        return (a_1101)+(d_1098)
      return g1472
    f_1102 = g1473()
    return f_1102(0, 1, 2, 3)


def g1478():
    """
    >>> g1478()
    3
    """
    def g1477():
      def g1476(x_1103):
        return x_1103
      return g1476
    f_1104 = g1477()
    def g1475():
      a_1107 = 0
      b_1106 = 1
      c_1105 = 2
      return (f_1104(a_1107))+((f_1104(b_1106))+(f_1104(c_1105)))
    return (f_1104(0))+(g1475())


def g1483():
    """
    >>> g1483()
    """
    a_1108 = 0
    def g1482():
      def g1481():
        return 0
      return g1481
    a_1110 = g1482()
    def g1480():
      def g1479():
        return 11
      return g1479
    b_1109 = g1480()
    a_1110 = 11


def g1486():
    """
    >>> g1486()
    """
    a_1111 = 0
    def g1485():
      def g1484():
        a_1113 = 0
      return g1484
    a_1113 = g1485()
    b_1112 = 11
    return a_1113()


def g1491():
    """
    >>> g1491()
    0
    """
    def g1490():
      def g1489():
        return 0
      return g1489
    a_1115 = g1490()
    def g1488():
      def g1487():
        return 11
      return g1487
    b_1114 = g1488()
    return a_1115()


def g1494():
    """
    >>> g1494()
    2
    """
    def g1493():
      x_1116 = 1
      def g1492(y_1117):
        return (x_1116)+(y_1117)
      return g1492
    f_1118 = g1493()
    x_1119 = 0
    return f_1118(f_1118(x_1119))


def g1501():
    """
    >>> g1501()
    3050
    """
    def g1500():
      def g1499():
        def g1498(x_1121):
          return (x_1121)+(50)
        return g1498
      t_1122 = g1499()
      def g1497(f_1123):
        return t_1122(f_1123(1000))
      return g1497
    def g1496():
      def g1495(y_1120):
        return (y_1120)+(2000)
      return g1495
    return g1500()(g1496())


def g1508():
    """
    >>> g1508()
    60
    """
    def g1507():
      def g1506():
        def g1505():
          def g1502(a_1124):
            def g1503(b_1125):
              def g1504(c_1126):
                return (a_1124)+((b_1125)+(c_1126))
              return g1504
            return g1503
          return g1502
        return g1505()(10)
      return g1506()(20)
    return g1507()(30)


def g1513():
    """
    >>> g1513()
    5
    """
    def g1512():
      def g1509(b_1127):
        def g1511():
          def g1510(a_1128):
            return (b_1127)+(a_1128)
          return g1510
        return g1511()(2)
      return g1509
    return g1512()(3)


def g1518():
    """
    >>> g1518()
    5
    """
    def g1517():
      def g1516(f_1130):
        return f_1130(f_1130(5))
      return g1516
    def g1515():
      def g1514(x_1129):
        return x_1129
      return g1514
    return g1517()(g1515())


def g1523():
    """
    >>> g1523()
    8000
    """
    def g1522():
      def g1521():
        def g1520(x_1131):
          return (x_1131)+(3000)
        return g1520
      f_1132 = g1521()
      def g1519(y_1133):
        return f_1132(f_1132(y_1133))
      return g1519
    return g1522()(2000)

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/closure_tests_2.pyx0000644000175100001770000002204500000000000021426 0ustar00runnerdocker00000000000000# mode: run
# tag: closures
# preparse: id
# preparse: def_to_cdef
#
# closure_tests_2.pyx
#
# Battery of tests for closures in Cython. Based on the collection of
# compiler tests from P423/B629 at Indiana University, Spring 1999 and
# Fall 2000. Special thanks to R. Kent Dybvig, Dan Friedman, Kevin
# Millikin, and everyone else who helped to generate the original
# tests. Converted into a collection of Python/Cython tests by Craig
# Citro.
#
# Note: This set of tests is split (somewhat randomly) into several
# files, simply because putting all the tests in a single file causes
# gcc and g++ to buckle under the load.
#


def g1526():
    """
    >>> g1526()
    2
    """
    x_1134 = 0
    def g1525():
      x_1136 = 1
      z_1135 = x_1134
      def g1524(y_1137):
        return (x_1136)+((z_1135)+(y_1137))
      return g1524
    f_1138 = g1525()
    return f_1138(f_1138(x_1134))


def g1535():
    """
    >>> g1535()
    3050
    """
    def g1534():
      def g1533():
        def g1531(t_1141):
          def g1532(f_1142):
            return t_1141(f_1142(1000))
          return g1532
        return g1531
      def g1530():
        def g1529(x_1140):
          return (x_1140)+(50)
        return g1529
      return g1533()(g1530())
    def g1528():
      def g1527(y_1139):
        return (y_1139)+(2000)
      return g1527
    return g1534()(g1528())


def g1540():
    """
    >>> g1540()
    2050
    """
    def g1539():
      t_1143 = 50
      def g1538(f_1144):
        return (t_1143)+(f_1144())
      return g1538
    def g1537():
      def g1536():
        return 2000
      return g1536
    return g1539()(g1537())


def g1547():
    """
    >>> g1547()
    2050
    """
    def g1546():
      def g1545():
        def g1543(t_1145):
          def g1544(f_1146):
            return (t_1145)+(f_1146())
          return g1544
        return g1543
      return g1545()(50)
    def g1542():
      def g1541():
        return 2000
      return g1541
    return g1546()(g1542())


def g1550():
    """
    >>> g1550()
    700
    """
    def g1549():
      x_1147 = 300
      def g1548(y_1148):
        return (x_1147)+(y_1148)
      return g1548
    return g1549()(400)


def g1553():
    """
    >>> g1553()
    0
    """
    x_1152 = 3
    def g1552():
      def g1551(x_1150, y_1149):
        return x_1150
      return g1551
    f_1151 = g1552()
    if (f_1151(0, 0)):
      return f_1151(f_1151(0, 0), x_1152)
    else:
      return 0


def g1562():
    """
    >>> g1562()
    False
    """
    def g1561():
      def g1556(x_1153):
        def g1560():
          def g1559():
            return isinstance(x_1153, list)
          if (g1559()):
            def g1558():
              def g1557():
                return (x_1153[0])
              return (g1557() == 0)
            return (not g1558())
          else:
            return False
        if (g1560()):
          return x_1153
        else:
          return False
      return g1556
    f_1154 = g1561()
    def g1555():
      def g1554():
        return [0,[]]
      return [0,g1554()]
    return f_1154(g1555())


def g1570():
    """
    >>> g1570()
    False
    """
    def g1569():
      def g1563(x_1155):
        def g1568():
          if (x_1155):
            def g1567():
              def g1566():
                return isinstance(x_1155, list)
              if (g1566()):
                def g1565():
                  def g1564():
                    return (x_1155[0])
                  return (g1564() == 0)
                return (not g1565())
              else:
                return False
            return (not g1567())
          else:
            return False
        if (g1568()):
          return x_1155
        else:
          return False
      return g1563
    f_1156 = g1569()
    return f_1156(0)


def g1575():
    """
    >>> g1575()
    []
    """
    def g1574():
      def g1571(x_1157):
        def g1573():
          def g1572():
            return isinstance(x_1157, list)
          if (g1572()):
            return True
          else:
            return (x_1157 == [])
        if (g1573()):
          return x_1157
        else:
          return []
      return g1571
    f_1158 = g1574()
    return f_1158(0)


def g1578():
    """
    >>> g1578()
    4
    """
    y_1159 = 4
    def g1577():
      def g1576(y_1160):
        return y_1160
      return g1576
    f_1161 = g1577()
    return f_1161(f_1161(y_1159))


def g1581():
    """
    >>> g1581()
    0
    """
    y_1162 = 4
    def g1580():
      def g1579(x_1164, y_1163):
        return 0
      return g1579
    f_1165 = g1580()
    return f_1165(f_1165(y_1162, y_1162), f_1165(y_1162, y_1162))


def g1584():
    """
    >>> g1584()
    0
    """
    y_1166 = 4
    def g1583():
      def g1582(x_1168, y_1167):
        return 0
      return g1582
    f_1169 = g1583()
    return f_1169(f_1169(y_1166, y_1166), f_1169(y_1166, f_1169(y_1166, y_1166)))


def g1587():
    """
    >>> g1587()
    0
    """
    y_1170 = 4
    def g1586():
      def g1585(x_1172, y_1171):
        return 0
      return g1585
    f_1173 = g1586()
    return f_1173(f_1173(y_1170, f_1173(y_1170, y_1170)), f_1173(y_1170, f_1173(y_1170, y_1170)))


def g1594():
    """
    >>> g1594()
    4
    """
    def g1593():
      def g1588(y_1174):
        def g1592():
          def g1591(f_1176):
            return f_1176(f_1176(y_1174))
          return g1591
        def g1590():
          def g1589(y_1175):
            return y_1175
          return g1589
        return g1592()(g1590())
      return g1588
    return g1593()(4)


def g1598():
    """
    >>> g1598()
    23
    """
    def g1597():
      def g1596(x_1177):
        return x_1177
      return g1596
    f_1178 = g1597()
    def g1595():
      if (False):
        return 1
      else:
        return f_1178(22)
    return (g1595()+1)


def g1603():
    """
    >>> g1603()
    22
    """
    def g1602():
      def g1601(x_1179):
        return x_1179
      return g1601
    f_1180 = g1602()
    def g1600():
      def g1599():
        return 23 == 0
      return f_1180(g1599())
    if (g1600()):
      return 1
    else:
      return 22


def g1611():
    """
    >>> g1611()
    5061
    """
    def g1610():
      def g1609(x_1182):
        if (x_1182):
          return (not x_1182)
        else:
          return x_1182
      return g1609
    f_1185 = g1610()
    def g1608():
      def g1607(x_1181):
        return (10)*(x_1181)
      return g1607
    f2_1184 = g1608()
    x_1183 = 23
    def g1606():
      def g1605():
        def g1604():
          return x_1183 == 0
        return f_1185(g1604())
      if (g1605()):
        return 1
      else:
        return (x_1183)*(f2_1184((x_1183-1)))
    return (g1606()+1)


def g1614():
    """
    >>> g1614()
    1
    """
    def g1613():
      def g1612():
        return 0
      return g1612
    f_1186 = g1613()
    x_1187 = f_1186()
    return 1


def g1617():
    """
    >>> g1617()
    1
    """
    def g1616():
      def g1615():
        return 0
      return g1615
    f_1188 = g1616()
    f_1188()
    return 1


def g1620():
    """
    >>> g1620()
    4
    """
    def g1619():
      def g1618(x_1189):
        return x_1189
      return g1618
    f_1190 = g1619()
    if (True):
      f_1190(3)
      return 4
    else:
      return 5


def g1623():
    """
    >>> g1623()
    6
    """
    def g1622():
      def g1621(x_1191):
        return x_1191
      return g1621
    f_1192 = g1622()
    (f_1192(4)) if (True) else (5)
    return 6


def g1627():
    """
    >>> g1627()
    120
    """
    def g1626():
      def g1624(fact_1195, n_1194, acc_1193):
        def g1625():
          return n_1194 == 0
        if (g1625()):
          return acc_1193
        else:
          return fact_1195(fact_1195, (n_1194-1), (n_1194)*(acc_1193))
      return g1624
    fact_1196 = g1626()
    return fact_1196(fact_1196, 5, 1)


def g1632():
    """
    >>> g1632()
    144
    """
    def g1631():
      def g1628(b_1199, c_1198, a_1197):
        b_1203 = (b_1199)+(a_1197)
        def g1630():
          def g1629():
            a_1201 = (b_1199)+(b_1199)
            c_1200 = (c_1198)+(c_1198)
            return (a_1201)+(a_1201)
          return (a_1197)+(g1629())
        a_1202 = g1630()
        return (a_1202)*(a_1202)
      return g1628
    return g1631()(2, 3, 4)


def g1639():
    """
    >>> g1639()
    3
    """
    def g1638():
      def g1636(x_1204):
        def g1637():
          return x_1204()
        return g1637
      return g1636
    f_1205 = g1638()
    def g1635():
      def g1634():
        def g1633():
          return 3
        return g1633
      return f_1205(g1634())
    return g1635()()


def g1646():
    """
    >>> g1646()
    3628800
    """
    def g1645():
      def g1643(x_1207):
        def g1644():
          return x_1207 == 0
        if (g1644()):
          return 1
        else:
          return (x_1207)*(f_1206((x_1207)-(1)))
      return g1643
    f_1206 = g1645()
    q_1208 = 17
    def g1642():
      def g1640(a_1209):
        q_1208 = 10
        def g1641():
          return a_1209(q_1208)
        return g1641
      return g1640
    g_1210 = g1642()
    return g_1210(f_1206)()

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/closure_tests_3.pyx0000644000175100001770000003366000000000000021434 0ustar00runnerdocker00000000000000# mode: run
# tag: closures
# preparse: id
# preparse: def_to_cdef
#
# closure_tests_3.pyx
#
# Battery of tests for closures in Cython. Based on the collection of
# compiler tests from P423/B629 at Indiana University, Spring 1999 and
# Fall 2000. Special thanks to R. Kent Dybvig, Dan Friedman, Kevin
# Millikin, and everyone else who helped to generate the original
# tests. Converted into a collection of Python/Cython tests by Craig
# Citro.
#
# Note: This set of tests is split (somewhat randomly) into several
# files, simply because putting all the tests in a single file causes
# gcc and g++ to buckle under the load.
#


def g1649():
    """
    >>> g1649()
    6
    """
    def g1648():
      def g1647(x_1211):
        return x_1211
      return g1647
    f_1212 = g1648()
    if (f_1212(True)):
      f_1212(3)
      f_1212(4)
    else:
      f_1212(5)
    return f_1212(6)


def g1653():
    """
    >>> g1653()
    5
    """
    def g1652():
      def g1651(x_1213):
        return (x_1213+1)
      return g1651
    f_1214 = g1652()
    def g1650():
      f_1215 = 3
      return (f_1215)+(1)
    return f_1214(g1650())


def g1662():
    """
    >>> g1662()
    51
    """
    x_1223 = 15
    def g1661():
      def g1660(h_1219, v_1218):
        return (h_1219)*(v_1218)
      return g1660
    f_1222 = g1661()
    def g1659():
      def g1658(x_1217):
        return (x_1217)+(5)
      return g1658
    k_1221 = g1659()
    def g1657():
      def g1656(x_1216):
        return (x_1216+1)
      return g1656
    g_1220 = g1657()
    def g1655():
      def g1654():
        g_1224 = 3
        return f_1222(g_1224, x_1223)
      return g_1220(g1654())
    return k_1221(g1655())


def g1665():
    """
    >>> g1665()
    5
    """
    x_1225 = 4
    def g1664():
      def g1663():
        return x_1225
      return g1663
    f_1226 = g1664()
    x_1225 = 5
    return f_1226()


def g1670():
    """
    >>> g1670()
    5
    """
    def g1669():
      def g1668():
        def g1667():
          def g1666():
            return 4
          return g1666
        y_1227 = g1667()
        return y_1227()
      return (g1668()+1)
    x_1228 = g1669()
    return x_1228


def g1674():
    """
    >>> g1674()
    1
    """
    def g1673():
      def g1671(n_1230):
        def g1672():
          return n_1230 == 0
        if (g1672()):
          return 1
        else:
          return one_1229((n_1230-1))
      return g1671
    one_1229 = g1673()
    return one_1229(13)


def g1681():
    """
    >>> g1681()
    True
    """
    def g1680():
      def g1678(x_1234):
        def g1679():
          return x_1234 == 0
        if (g1679()):
          return True
        else:
          return odd_1231((x_1234-1))
      return g1678
    even_1232 = g1680()
    def g1677():
      def g1675(x_1233):
        def g1676():
          return x_1233 == 0
        if (g1676()):
          return False
        else:
          return even_1232((x_1233-1))
      return g1675
    odd_1231 = g1677()
    return odd_1231(13)


def g1688():
    """
    >>> g1688()
    True
    """
    t_1236 = True
    f_1235 = False
    def g1687():
      def g1685(x_1240):
        def g1686():
          return x_1240 == 0
        if (g1686()):
          return t_1236
        else:
          return odd_1237((x_1240-1))
      return g1685
    even_1238 = g1687()
    def g1684():
      def g1682(x_1239):
        def g1683():
          return x_1239 == 0
        if (g1683()):
          return f_1235
        else:
          return even_1238((x_1239-1))
      return g1682
    odd_1237 = g1684()
    return odd_1237(13)


def g1698():
    """
    >>> g1698()
    True
    """
    def g1697():
      def g1696(x_1241):
        return x_1241
      return g1696
    even_1242 = g1697()
    def g1695():
      def g1694():
        def g1692(x_1246):
          def g1693():
            return x_1246 == 0
          if (g1693()):
            return True
          else:
            return odd_1243((x_1246-1))
        return g1692
      even_1244 = g1694()
      def g1691():
        def g1689(x_1245):
          def g1690():
            return x_1245 == 0
          if (g1690()):
            return False
          else:
            return even_1244((x_1245-1))
        return g1689
      odd_1243 = g1691()
      return odd_1243(13)
    return even_1242(g1695())


def g1702():
    """
    >>> g1702()
    120
    """
    def g1701():
      def g1699(n_1248):
        def g1700():
          return n_1248 == 0
        if (g1700()):
          return 1
        else:
          return (n_1248)*(fact_1247((n_1248-1)))
      return g1699
    fact_1247 = g1701()
    return fact_1247(5)


def g1716():
    """
    >>> g1716()
    10
    """
    x_1249 = 5
    def g1715():
      def g1713(u_1263, v_1262, w_1261):
        def g1714():
          return u_1263 == 0
        if (g1714()):
          return b_1251(v_1262, w_1261)
        else:
          return a_1252((u_1263)-(1), v_1262, w_1261)
      return g1713
    a_1252 = g1715()
    def g1712():
      def g1705(q_1255, r_1254):
        p_1256 = (q_1255)*(r_1254)
        def g1711():
          def g1709(n_1260):
            def g1710():
              return n_1260 == 0
            if (g1710()):
              return c_1250(p_1256)
            else:
              return o_1257((n_1260)-(1))
          return g1709
        e_1258 = g1711()
        def g1708():
          def g1706(n_1259):
            def g1707():
              return n_1259 == 0
            if (g1707()):
              return c_1250(x_1249)
            else:
              return e_1258((n_1259)-(1))
          return g1706
        o_1257 = g1708()
        return e_1258((q_1255)*(r_1254))
      return g1705
    b_1251 = g1712()
    def g1704():
      def g1703(x_1253):
        return (5)*(x_1253)
      return g1703
    c_1250 = g1704()
    return a_1252(3, 2, 1)


def g1729():
    """
    >>> g1729()
    537516
    """
    def g1728():
      def g1727(x_1269):
        return (x_1269+1)
      return g1727
    f_1276 = g1728()
    def g1726():
      def g1725(x_1268):
        return (x_1268-1)
      return g1725
    g_1275 = g1726()
    def g1724():
      def g1723(x_1267):
        return (x_1267+1)
      return g1723
    t_1274 = g1724()
    def g1722():
      def g1721(x_1266):
        return (x_1266+1)
      return g1721
    j_1273 = g1722()
    def g1720():
      def g1719(x_1265):
        return (x_1265+1)
      return g1719
    i_1272 = g1720()
    def g1718():
      def g1717(x_1264):
        return (x_1264+1)
      return g1717
    h_1271 = g1718()
    x_1270 = 80
    a_1279 = f_1276(x_1270)
    b_1278 = g_1275(x_1270)
    c_1277 = h_1271(i_1272(j_1273(t_1274(x_1270))))
    return (a_1279)*((b_1278)*((c_1277)+(0)))


def g1733():
    """
    >>> g1733()
    120
    """
    def g1732():
      def g1730(fact_1281, n_1280):
        def g1731():
          return n_1280 == 0
        if (g1731()):
          return 1
        else:
          return (fact_1281(fact_1281, (n_1280-1)))*(n_1280)
      return g1730
    fact_1282 = g1732()
    return fact_1282(fact_1282, 5)


def g1737():
    """
    >>> g1737()
    10000
    """
    def g1736():
      def g1735(x_1283):
        return (x_1283)+(1000)
      return g1735
    f_1284 = g1736()
    def g1734():
      return f_1284(-2) == 0
    if (g1734()):
      return f_1284(6000)
    else:
      return f_1284(f_1284(8000))


def g1741():
    """
    >>> g1741()
    10000
    """
    def g1740():
      def g1739(x_1285):
        return (x_1285)+(1000)
      return g1739
    f_1286 = g1740()
    def g1738():
      return f_1286(-1) == 0
    if (g1738()):
      return f_1286(6000)
    else:
      return f_1286(f_1286(8000))


def g1747():
    """
    >>> g1747()
    8000
    """
    def g1746():
      def g1745(x_1288, y_1287):
        return (x_1288)+(1000)
      return g1745
    f_1289 = g1746()
    def g1744():
      def g1743():
        def g1742():
          return 0
        return f_1289(3000, g1742())
      if (g1743()):
        return f_1289(f_1289(4000, 0), 0)
      else:
        return 8000
    return (g1744())+(2000)


def g1754():
    """
    >>> g1754()
    24
    """
    def g1753():
      def g1752():
        def g1751():
          def g1748(x_1290):
            def g1749(y_1291):
              def g1750(z_1292):
                return (x_1290)+((y_1291)+((z_1292)+(y_1291)))
              return g1750
            return g1749
          return g1748
        return g1751()(5)
      return g1752()(6)
    return g1753()(7)


def g1765():
    """
    >>> g1765()
    35
    """
    def g1764():
      def g1763():
        def g1762():
          def g1761():
            def g1760():
              def g1755(x_1293):
                def g1756(y_1294):
                  def g1757(z_1295):
                    def g1758(w_1296):
                      def g1759(u_1297):
                        return (x_1293)+((y_1294)+((z_1295)+((w_1296)+(u_1297))))
                      return g1759
                    return g1758
                  return g1757
                return g1756
              return g1755
            return g1760()(5)
          return g1761()(6)
        return g1762()(7)
      return g1763()(8)
    return g1764()(9)


def g1769():
    """
    >>> g1769()
    True
    """
    def g1768():
      def g1767(x_1298):
        return x_1298
      return g1767
    f_1299 = g1768()
    def g1766():
      return hasattr(f_1299, '__call__')
    if (g1766()):
      return True
    else:
      return False


def g1779():
    """
    >>> g1779()
    6
    """
    def g1778():
      def g1773(sum_1301, ls_1300):
        def g1777():
          return (ls_1300 == [])
        if (g1777()):
          return 0
        else:
          def g1776():
            return (ls_1300[0])
          def g1775():
            def g1774():
              return (ls_1300[1])
            return sum_1301(sum_1301, g1774())
          return (g1776())+(g1775())
      return g1773
    sum_1302 = g1778()
    def g1772():
      def g1771():
        def g1770():
          return [3,[]]
        return [2,g1770()]
      return [1,g1771()]
    return sum_1302(sum_1302, g1772())


def g1785():
    """
    >>> g1785()
    1500
    """
    def g1784():
      def g1783():
        def g1780(a_1303):
          def g1781():
            def g1782():
              if (True):
                return 200
            (a_1303)+(g1782())
            return 1500
          return g1781
        return g1780
      return g1783()(1000)
    return g1784()()


def g1791():
    """
    >>> g1791()
    102
    """
    def g1790():
      def g1789():
        def g1786(b_1304):
          def g1787(a_1305):
            def g1788():
              if (1):
                return 2
            a_1305 = g1788()
            return (a_1305)+(b_1304)
          return g1787
        return g1786
      return g1789()(100)
    return g1790()(200)


def g1800():
    """
    >>> g1800()
    2600
    """
    def g1799():
      def g1798():
        def g1797():
          def g1792(a_1306):
            def g1793(b_1307):
              def g1794():
                if (b_1307):
                  return 200
              a_1306 = g1794()
              def g1795(c_1308):
                def g1796():
                  if (300):
                    return 400
                c_1308 = g1796()
                return (a_1306)+((b_1307)+(c_1308))
              return g1795
            return g1793
          return g1792
        return g1797()(1000)
      return g1798()(2000)
    return g1799()(3000)


def g1807():
    """
    >>> g1807()
    3628800
    """
    def g1806():
      def g1804(x_1310):
        def g1805():
          return x_1310 == 0
        if (g1805()):
          return 1
        else:
          return (x_1310)*(f_1309((x_1310)-(1)))
      return g1804
    f_1309 = g1806()
    def g1803():
      def g1801(a_1311):
        def g1802(b_1312):
          return a_1311(b_1312)
        return g1802
      return g1801
    g_1313 = g1803()
    return g_1313(f_1309)(10)


def g1828():
    """
    >>> g1828()
    [52, [44, [17, [44, [52, 17]]]]]
    """
    def g1827():
      def g1826():
        return (a_1316)+(b_1315)
      return g1826
    f_1318 = g1827()
    def g1825():
      def g1822(y_1320):
        def g1824():
          def g1823(y_1321):
            return y_1321
          return g1823
        g_1317 = g1824()
        return (y_1320)+(y_1320)
      return g1822
    g_1317 = g1825()
    a_1316 = 17
    b_1315 = 35
    def g1821():
      def g1820():
        def g1819():
          return a_1316
        return g1819
      def g1818():
        def g1817(v_1319):
          a_1316 = v_1319
        return g1817
      return [g1820(),g1818()]
    h_1314 = g1821()
    x1_1324 = f_1318()
    x2_1323 = g_1317(22)
    def g1816():
      def g1815():
        return (h_1314[0])
      return g1815()()
    x3_1322 = g1816()
    x4_1325 = g_1317(22)
    def g1814():
      return (h_1314[1])
    g1814()(3)
    x5_1327 = f_1318()
    def g1813():
      def g1812():
        return (h_1314[0])
      return g1812()()
    x6_1326 = g1813()
    def g1811():
      def g1810():
        def g1809():
          def g1808():
            return [x5_1327,x6_1326]
          return [x4_1325,g1808()]
        return [x3_1322,g1809()]
      return [x2_1323,g1810()]
    return [x1_1324,g1811()]


def g1843():
    """
    >>> g1843()
    [52, [17, [35, [17, 35]]]]
    """
    def g1842():
      def g1841():
        return (a_1330)+(b_1329)
      return g1841
    f_1331 = g1842()
    a_1330 = 17
    b_1329 = 35
    def g1840():
      def g1839():
        def g1838():
          return a_1330
        return g1838
      def g1837():
        def g1836():
          return b_1329
        return g1836
      return [g1839(),g1837()]
    h_1328 = g1840()
    def g1835():
      def g1834():
        def g1833():
          def g1832():
            def g1831():
              return (h_1328[0])
            return g1831()()
          def g1830():
            def g1829():
              return (h_1328[1])
            return g1829()()
          return [g1832(),g1830()]
        return [b_1329,g1833()]
      return [a_1330,g1834()]
    return [f_1331(),g1835()]

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/closure_tests_4.pyx0000644000175100001770000004353300000000000021435 0ustar00runnerdocker00000000000000# mode: run
# tag: closures
# preparse: id
# preparse: def_to_cdef
#
# closure_tests_4.pyx
#
# Battery of tests for closures in Cython. Based on the collection of
# compiler tests from P423/B629 at Indiana University, Spring 1999 and
# Fall 2000. Special thanks to R. Kent Dybvig, Dan Friedman, Kevin
# Millikin, and everyone else who helped to generate the original
# tests. Converted into a collection of Python/Cython tests by Craig
# Citro.
#
# Note: This set of tests is split (somewhat randomly) into several
# files, simply because putting all the tests in a single file causes
# gcc and g++ to buckle under the load.
#


def g1852():
    """
    >>> g1852()
    [3, 42]
    """
    def g1851():
      def g1850(x_1333):
        x_1334 = 3
        return 3
      return g1850
    f_1332 = g1851()
    def g1848():
      def g1847(x_1336):
        y_1337 = 14
        y_1337 = 7
        return y_1337
      return g1847
    g_1335 = g1848()
    def g1849():
      return [g_1335,3]
    g_1335 = g1849()
    def g1846():
      def g1845(x_1340):
        return x_1340
      return g1845
    h_1339 = g1846()
    z_1338 = 42
    def g1844():
      return (g_1335[1])
    return [g1844(),h_1339(z_1338)]


def g1864():
    """
    >>> g1864()
    True
    """
    t_1342 = True
    f_1341 = False
    def g1863():
      return [t_1342,f_1341]
    bools_1345 = g1863()
    def g1862():
      def g1861(x_1343):
        if ((not x_1343)):
          return f_1341
        else:
          return t_1342
      return g1861
    id_1344 = g1862()
    def g1860():
      def g1857(x_1349):
        def g1859():
          return x_1349 == 0
        if (g1859()):
          def g1858():
            return (bools_1345[0])
          return id_1344(g1858())
        else:
          return odd_1346((x_1349)-(1))
      return g1857
    even_1347 = g1860()
    def g1856():
      def g1853(y_1348):
        def g1855():
          return y_1348 == 0
        if (g1855()):
          def g1854():
            return (bools_1345[1])
          return id_1344(g1854())
        else:
          return even_1347((y_1348)-(1))
      return g1853
    odd_1346 = g1856()
    return odd_1346(5)


def g1872():
    """
    >>> g1872()
    35
    """
    a_1350 = 5
    def g1871():
      return [a_1350,6]
    b_1351 = g1871()
    def g1870():
      def g1869(x_1352):
        return (x_1352)*(a_1350)
      return g1869
    f_1353 = g1870()
    def g1867():
      def g1866():
        return (b_1351[0])
      return (f_1353(a_1350))-(g1866())
    if (g1867()):
      def g1868():
        if ((not a_1350)):
          return (2)*(a_1350)
        else:
          return (2)+(a_1350)
      b_1351[0] = g1868()
      f_1353(a_1350)
    else:
      if ((not (not (f_1353(a_1350) < b_1351)))): (f_1353(a_1350))
    def g1865():
      return (b_1351[0])
    return f_1353(g1865())


def g1885():
    """
    >>> g1885()
    9
    """
    def g1884():
      def g1883(x_1368, y_1367):
        if ((not x_1368)):
          return g_1355((x_1368+1), (y_1367+1))
        else:
          return h_1354((x_1368)+(y_1367))
      return g1883
    f_1356 = g1884()
    def g1882():
      def g1875(u_1359, v_1358):
        a_1361 = (u_1359)+(v_1358)
        b_1360 = (u_1359)*(v_1358)
        def g1881():
          def g1876(d_1363):
            def g1880():
              return [a_1361,b_1360]
            p_1365 = g1880()
            def g1879():
              def g1877(m_1366):
                if ((m_1366 < u_1359)):
                  return f_1356(m_1366, d_1363)
                else:
                  def g1878():
                    return (p_1365[0])
                  return h_1354(g1878())
              return g1877
            q_1364 = g1879()
            return q_1364(f_1356(a_1361, b_1360))
          return g1876
        e_1362 = g1881()
        return e_1362(u_1359)
      return g1875
    g_1355 = g1882()
    def g1874():
      def g1873(w_1357):
        return w_1357
      return g1873
    h_1354 = g1874()
    return f_1356(4, 5)


def g1897():
    """
    >>> g1897()
    22
    """
    def g1896():
      def g1890(x_1373):
        def g1895():
          def g1894():
            def g1893():
              def g1891(y_1374):
                def g1892(z_1375):
                  return (y_1374)+(z_1375)
                return g1892
              return g1891
            return g1893()(6)
          return g1894()(7)
        return (x_1373)+(g1895())
      return g1890
    f_1370 = g1896()
    def g1889():
      def g1888():
        def g1887():
          def g1886(w_1372, u_1371):
            return (w_1372)+(u_1371)
          return g1886
        return g1887()(8, 9)
      return (5)+(g1888())
    g_1369 = g1889()
    return g_1369


def g1923():
    """
    >>> g1923()
    True
    """
    y_1377 = []
    z_1376 = 10
    def g1911():
      return [5,y_1377]
    test_ls_1378 = g1911()
    def g1922():
      def g1913(f_1379):
        def g1921():
          def g1918(g_1382):
            def g1920():
              def g1919(x_1383):
                return g_1382(g_1382)(x_1383)
              return g1919
            return f_1379(g1920())
          return g1918
        def g1917():
          def g1914(g_1380):
            def g1916():
              def g1915(x_1381):
                return g_1380(g_1380)(x_1381)
              return g1915
            return f_1379(g1916())
          return g1914
        return g1921()(g1917())
      return g1913
    y_1377 = g1922()
    def g1912():
      return [z_1376,test_ls_1378]
    test_ls_1378 = g1912()
    def g1910():
      def g1906(ls_1385):
        def g1909():
          return (ls_1385 == [])
        if (g1909()):
          return 0
        else:
          def g1908():
            def g1907():
              return (ls_1385[1])
            return length_1384(g1907())
          return (1)+(g1908())
      return g1906
    length_1384 = g1910()
    len_1386 = length_1384(test_ls_1378)
    def g1905():
      def g1904():
        def g1903():
          def g1898(len_1387):
            def g1899(ls_1388):
              def g1902():
                return (ls_1388 == [])
              if (g1902()):
                return 0
              else:
                def g1901():
                  def g1900():
                    return (ls_1388[1])
                  return len_1387(g1900())
                return (1)+(g1901())
            return g1899
          return g1898
        return y_1377(g1903())
      length_1384 = g1904()
      return length_1384(test_ls_1378)
    return (g1905() == len_1386)


def g1927():
    """
    >>> g1927()
    0
    """
    def g1926():
      def g1924():
        def g1925():
          return loop_1389()
        return g1925
      return g1924
    loop_1389 = g1926()
    loop_1389()
    return 0


def g1935():
    """
    >>> g1935()
    668
    """
    def g1934():
      def g1928():
        def g1933():
          def g1931(link_1392):
            def g1932():
              return link_1392()
            return g1932
          return g1931
        loop_1391 = g1933()
        def g1930():
          def g1929():
            return 668
          return g1929
        return loop_1391(g1930())
      return g1928
    f_1390 = g1934()
    return f_1390()()


def g1946():
    """
    >>> g1946()
    14629
    """
    def g1945():
      def g1944():
        return 1
      return g1944
    if (g1945()):
      a_1393 = 2
      def g1943():
        def g1942():
          def g1941():
            def g1938(x_1394):
              def g1940():
                def g1939():
                  a_1393 = 1
                a_1393 = g1939()
              x_1395 = g1940()
              return x_1395
            return g1938
          return g1941()(1)
        if (g1942()):
          def g1937():
            def g1936():
              return None
            return (a_1393 == g1936())
          if (g1937()):
            return True
          else:
            return False
        else:
          return False
      if (g1943()):
        return 778477
      else:
        return 14629


def g1949():
    """
    >>> g1949()
    2
    """
    def g1948():
      def g1947(x_1396):
        return x_1396
      return g1947
    f_1397 = g1948()
    a_1398 = 1
    return ((f_1397(a_1398))+(a_1398))*(a_1398)


def g1952():
    """
    >>> g1952()
    17
    """
    def g1951():
      def g1950(x_1400, y_1399):
        return x_1400
      return g1950
    k_1401 = g1951()
    b_1402 = 17
    return k_1401(k_1401(k_1401, 37), 37)(b_1402, (b_1402)*(b_1402))


def g1956():
    """
    >>> g1956()
    False
    """
    def g1955():
      def g1953():
        n_1403 = 256
        def g1954():
          return ([0]*n_1403)
        v_1404 = g1954()
        v_1404[32] = n_1403
        return v_1404[32]
      return g1953
    f_1405 = g1955()
    return isinstance(f_1405(), list)


def g1959():
    """
    >>> g1959()
    60
    """
    w_1409 = 4
    x_1408 = 8
    y_1407 = 16
    z_1406 = 32
    def g1958():
      def g1957():
        return (w_1409)+((x_1408)+((y_1407)+(z_1406)))
      return g1957
    f_1410 = g1958()
    return f_1410()


def g1965():
    """
    >>> g1965()
    37
    """
    def g1964():
      def g1962(g_1412, u_1411):
        def g1963():
          if (u_1411):
            return g_1412(37)
          else:
            return u_1411
        return g_1412(g1963())
      return g1962
    f_1413 = g1964()
    def g1961():
      def g1960(x_1414):
        return x_1414
      return g1960
    return f_1413(g1961(), 75)


def g1971():
    """
    >>> g1971()
    4687
    """
    def g1970():
      def g1968(h_1416, u_1415):
        def g1969():
          if (u_1415):
            return h_1416((u_1415)+(37))
          else:
            return u_1415
        return h_1416(g1969())
      return g1968
    f_1418 = g1970()
    w_1417 = 62
    def g1967():
      def g1966(x_1419):
        return (w_1417)-(x_1419)
      return g1966
    return f_1418(g1967(), (75)*(w_1417))


def g1983():
    """
    >>> g1983()
    True
    """
    t_1421 = True
    f_1420 = False
    def g1982():
      return [t_1421,f_1420]
    bools_1424 = g1982()
    def g1981():
      def g1980(x_1422):
        if ((not x_1422)):
          return f_1420
        else:
          return t_1421
      return g1980
    id_1423 = g1981()
    def g1979():
      def g1976(x_1428):
        def g1978():
          def g1977():
            return x_1428 == 0
          return id_1423(g1977())
        if (g1978()):
          return (bools_1424[0])
        else:
          return odd_1425((x_1428)-(1))
      return g1976
    even_1426 = g1979()
    def g1975():
      def g1972(y_1427):
        def g1974():
          return y_1427 == 0
        if (g1974()):
          def g1973():
            return (bools_1424[1])
          return id_1423(g1973())
        else:
          return even_1426((y_1427)-(1))
      return g1972
    odd_1425 = g1975()
    return odd_1425(5)


def g1990():
    """
    >>> g1990()
    48
    """
    def g1989():
      def g1984(x_1431, y_1430, z_1429):
        def g1988():
          def g1987(u_1435, v_1434):
            x_1431 = u_1435
            return (x_1431)+(v_1434)
          return g1987
        f_1437 = g1988()
        def g1986():
          def g1985(r_1433, s_1432):
            y_1430 = (z_1429)+(s_1432)
            return y_1430
          return g1985
        g_1436 = g1986()
        return (f_1437(1, 2))*(g_1436(3, 4))
      return g1984
    return g1989()(10, 11, 12)


def g1997():
    """
    >>> g1997()
    176
    """
    def g1996():
      def g1991(x_1440, y_1439, z_1438):
        f_1444 = False
        def g1995():
          def g1994(r_1442, s_1441):
            y_1439 = (z_1438)+(s_1441)
            return y_1439
          return g1994
        g_1443 = g1995()
        def g1993():
          def g1992(u_1446, v_1445):
            v_1445 = u_1446
            return (x_1440)+(v_1445)
          return g1992
        f_1444 = g1993()
        return (f_1444(1, 2))*(g_1443(3, 4))
      return g1991
    return g1996()(10, 11, 12)


def g2002():
    """
    >>> g2002()
    5
    """
    def g2001():
      def g2000(x_1450):
        return (x_1450)+(1)
      return g2000
    f_1448 = g2001()
    def g1999():
      def g1998(y_1449):
        return f_1448(f_1448(y_1449))
      return g1998
    g_1447 = g1999()
    return (f_1448(1))+(g_1447(1))


def g2010():
    """
    >>> g2010()
    1521
    """
    y_1451 = 3
    def g2009():
      def g2007(x_1457):
        def g2008():
          return x_1457 == 0
        if (g2008()):
          return g_1453((x_1457)+(1))
        else:
          return f_1454((x_1457)-(y_1451))
      return g2007
    f_1454 = g2009()
    def g2006():
      def g2005(x_1456):
        return h_1452((x_1456)*(x_1456))
      return g2005
    g_1453 = g2006()
    def g2004():
      def g2003(x_1455):
        return x_1455
      return g2003
    h_1452 = g2004()
    return g_1453(39)


def g2017():
    """
    >>> g2017()
    -1
    """
    def g2014():
      def g2013(x_1461):
        return (x_1461)+(1)
      return g2013
    f_1459 = g2014()
    def g2012():
      def g2011(y_1460):
        return f_1459(f_1459(y_1460))
      return g2011
    g_1458 = g2012()
    def g2016():
      def g2015(x_1462):
        return (x_1462)-(1)
      return g2015
    f_1459 = g2016()
    return (f_1459(1))+(g_1458(1))


def g2032():
    """
    >>> g2032()
    [52, [17, [35, [17, 35]]]]
    """
    def g2031():
      def g2030():
        return (a_1465)+(b_1464)
      return g2030
    f_1466 = g2031()
    a_1465 = 17
    b_1464 = 35
    def g2029():
      def g2028():
        def g2027():
          return a_1465
        return g2027
      def g2026():
        def g2025():
          return b_1464
        return g2025
      return [g2028(),g2026()]
    h_1463 = g2029()
    def g2024():
      def g2023():
        def g2022():
          def g2021():
            def g2020():
              return (h_1463[0])
            return g2020()()
          def g2019():
            def g2018():
              return (h_1463[1])
            return g2018()()
          return [g2021(),g2019()]
        return [b_1464,g2022()]
      return [a_1465,g2023()]
    return [f_1466(),g2024()]


def g2038():
    """
    >>> g2038()
    120
    """
    x_1469 = 5
    def g2037():
      a_1467 = 1
      def g2036():
        return a_1467
      return g2036
    th_1468 = g2037()
    def g2035():
      def g2033(n_1472, th_1471):
        def g2034():
          return n_1472 == 0
        if (g2034()):
          return th_1471()
        else:
          return (n_1472)*(fact_1470((n_1472)-(1), th_1471))
      return g2033
    fact_1470 = g2035()
    return fact_1470(x_1469, th_1468)


def g2046():
    """
    >>> g2046()
    [120, -120]
    """
    def g2045():
      def g2044(n_1473):
        return (n_1473 < 0)
      return g2044
    negative_1474 = g2045()
    def g2043():
      def g2041(n_1478):
        def g2042():
          return n_1478 == 0
        if (g2042()):
          return 1
        else:
          return (n_1478)*(fact_1476((n_1478)-(1)))
      return g2041
    fact_1476 = g2043()
    def g2040():
      def g2039(n_1477):
        if ((not negative_1474(n_1477))):
          return fact_1476(n_1477)
        else:
          return (0)-(fact_1476((0)-(n_1477)))
      return g2039
    call_fact_1475 = g2040()
    return [call_fact_1475(5),call_fact_1475(-5)]


def g2050():
    """
    >>> g2050()
    [0, 1, 2, 3]
    """
    def g2049():
      def g2048(v_1482, i_1481, n_1480):
        if ((not (i_1481 == n_1480))):
          v_1482[i_1481] = i_1481
          return iota_fill_1479(v_1482, (i_1481)+(1), n_1480)
      return g2048
    iota_fill_1479 = g2049()
    n_1483 = 4
    def g2047():
      return ([0]*n_1483)
    v_1484 = g2047()
    iota_fill_1479(v_1484, 0, n_1483)
    return v_1484


def g2061():
    """
    >>> g2061()
    [[33, 55], [77, 99]]
    """
    def g2060():
      def g2059():
        def g2058():
          def g2057():
            def g2051(a_1485):
              def g2052(b_1486):
                def g2053(c_1487):
                  def g2054(d_1488):
                    def g2056():
                      return [a_1485,b_1486]
                    def g2055():
                      return [c_1487,d_1488]
                    return [g2056(),g2055()]
                  return g2054
                return g2053
              return g2052
            return g2051
          return g2057()(33)
        return g2058()(55)
      return g2059()(77)
    return g2060()(99)


def g2075():
    """
    >>> g2075()
    [[[3, [21, [18, []]]], [4, [28, [24, []]]]], [[[0, [0, [0, []]]], [1, [7, [6, []]]]], [[408, 408], []]]]
    """
    a_1489 = 17
    def g2074():
      def g2064(x_1490):
        x1_1492 = (x_1490)+(1)
        x2_1491 = (x_1490)+(2)
        y1_1494 = (x1_1492)*(7)
        y2_1493 = (x2_1491)*(7)
        z1_1496 = (y1_1494)-(x1_1492)
        z2_1495 = (y2_1493)-(x2_1491)
        w1_1498 = (z1_1496)*(a_1489)
        w2_1497 = (z2_1495)*(a_1489)
        def g2073():
          def g2068(b_1500):
            if ((b_1500 == a_1489)):
              def g2072():
                def g2071():
                  return [z1_1496,[]]
                return [y1_1494,g2071()]
              return [x1_1492,g2072()]
            else:
              def g2070():
                def g2069():
                  return [z2_1495,[]]
                return [y2_1493,g2069()]
              return [x2_1491,g2070()]
          return g2068
        g_1502 = g2073()
        def g2067():
          def g2066(c_1499):
            if ((c_1499 == x_1490)):
              return w1_1498
            else:
              return w2_1497
          return g2066
        h_1501 = g2067()
        def g2065():
          if (((x_1490)*(x_1490) == (x_1490)+(x_1490))):
            return True
          else:
            return (x_1490 < 0)
        if (g2065()):
          return [g_1502(17),g_1502(16)]
        else:
          return [h_1501(x_1490),h_1501((x_1490)-(0))]
      return g2064
    f_1503 = g2074()
    def g2063():
      def g2062():
        return [f_1503(3),[]]
      return [f_1503(-1),g2062()]
    return [f_1503(2),g2063()]

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/closures_T82.pyx0000644000175100001770000001056100000000000020603 0ustar00runnerdocker00000000000000# mode: run
# tag: closures
# ticket: t82
# preparse: id
# preparse: def_to_cdef

cimport cython

def add_n(int n):
    """
    >>> f = add_n(3)
    >>> f(2)
    5

    >>> f = add_n(1000000)
    >>> f(1000000), f(-1000000)
    (2000000, 0)
    """
    def f(int x):
        return x+n
    return f

def a(int x):
    """
    >>> a(5)()
    8
    """
    def b():
        def c():
            return 3+x
        return c()
    return b

def local_x(int arg_x):
    """
    >>> local_x(1)(2)(4)
    4 2 1
    15
    """
    cdef int local_x = arg_x
    def y(arg_y):
        y = arg_y
        def z(long arg_z):
            cdef long z = arg_z
            print z, y, local_x
            return 8+z+y+local_x
        return z
    return y

def x(int x):
    """
    >>> x(1)(2)(4)
    15
    """
    def y(y):
        def z(long z):
            return 8+z+y+x
        return z
    return y

def x2(int x2):
    """
    >>> x2(1)(2)(4)
    4 2 1
    15
    """
    def y2(y2):
        def z2(long z2):
            print z2, y2, x2
            return 8+z2+y2+x2
        return z2
    return y2


def inner_override(a,b):
    """
    >>> inner_override(2,4)()
    5
    """
    def f():
        a = 1
        return a+b
    return f


def reassign(x):
    """
    >>> reassign(4)(2)
    3
    """
    def f(a):
        return a+x
    x = 1
    return f

def reassign_int(x):
    """
    >>> reassign_int(4)(2)
    3
    """
    def f(int a):
        return a+x
    x = 1
    return f

def reassign_int_int(int x):
    """
    >>> reassign_int_int(4)(2)
    3
    """
    def f(int a):
        return a+x
    x = 1
    return f


def cy_twofuncs(x):
    """
    >>> def py_twofuncs(x):
    ...    def f(a):
    ...        return g(x) + a
    ...    def g(b):
    ...        return x + b
    ...    return f

    >>> py_twofuncs(1)(2) == cy_twofuncs(1)(2)
    True
    >>> py_twofuncs(3)(5) == cy_twofuncs(3)(5)
    True
    """
    def f(a):
        return g(x) + a
    def g(b):
        return x + b
    return f

def switch_funcs(a, b, int ix):
    """
    >>> switch_funcs([1,2,3], [4,5,6], 0)([10])
    [1, 2, 3, 10]
    >>> switch_funcs([1,2,3], [4,5,6], 1)([10])
    [4, 5, 6, 10]
    >>> switch_funcs([1,2,3], [4,5,6], 2) is None
    True
    """
    def f(x):
        return a + x
    def g(x):
        return b + x
    if ix == 0:
        return f
    elif ix == 1:
        return g
    else:
        return None

def ignore_func(x):
    def f():
        return x
    return None

def call_ignore_func():
    """
    >>> call_ignore_func()
    """
    ignore_func((1,2,3))

def more_inner_funcs(x):
    """
    >>> inner_funcs = more_inner_funcs(1)(2,4,8)
    >>> inner_funcs[0](16), inner_funcs[1](32), inner_funcs[2](64)
    (19, 37, 73)
    """
    # called with x==1
    def f(a):
        def g(b):
            # called with 16
            return a+b+x
        return g
    def g(b):
        def f(a):
            # called with 32
            return a+b+x
        return f
    def h(b):
        def f(a):
            # called with 64
            return a+b+x
        return f
    def resolve(a_f, b_g, b_h):
        # called with (2,4,8)
        return f(a_f), g(b_g), h(b_h)
    return resolve


@cython.test_assert_path_exists("//DefNode//DefNode//DefNode//DefNode",
                                "//DefNode[@needs_outer_scope = False]", # deep_inner()
                                "//DefNode//DefNode//DefNode//DefNode[@needs_closure = False]", # h()
                                )
@cython.test_fail_if_path_exists("//DefNode//DefNode[@needs_outer_scope = False]")
def deep_inner():
    """
    >>> deep_inner()()
    2
    """
    cdef int x = 1
    def f():
        def g():
            def h():
                return x+1
            return h
        return g()
    return f()


@cython.test_assert_path_exists("//DefNode//DefNode//DefNode",
                                "//DefNode//DefNode//DefNode[@needs_outer_scope = False]",  # a()
                                "//DefNode//DefNode//DefNode[@needs_closure = False]", # a(), g(), h()
                                )
@cython.test_fail_if_path_exists("//DefNode//DefNode//DefNode[@needs_closure = True]") # a(), g(), h()
def deep_inner_sibling():
    """
    >>> deep_inner_sibling()()
    2
    """
    cdef int x = 1
    def f():
        def a():
            return 1
        def g():
            return x+a()
        def h():
            return g()
        return h
    return f()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cmethod_inline_T474.pxd0000644000175100001770000000014400000000000021761 0ustar00runnerdocker00000000000000cdef class TestInlineMethod(object):
    cdef inline int cdef_inline_method(self):
        return 0
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cmethod_inline_T474.pyx0000644000175100001770000000135600000000000022014 0ustar00runnerdocker00000000000000# mode: run
# ticket: t474
cimport cython


cdef class TestInlineMethod(object):
    """
    >>> test = TestInlineMethod()
    >>> test.test_cdef_method()
    0
    """

    @cython.test_assert_path_exists(
        "//AttributeNode[@entry.is_inline_cmethod=True]",
        "//AttributeNode[@entry.is_final_cmethod=True]")
    def test_cdef_method(self):
        return self.cdef_inline_method()


cdef class Subtyping(TestInlineMethod):
    """
    >>> test = Subtyping()
    >>> test.test_cdef_subtyping()
    0
    """

    @cython.test_assert_path_exists(
        "//AttributeNode[@entry.is_inline_cmethod=True]",
        "//AttributeNode[@entry.is_final_cmethod=True]")
    def test_cdef_subtyping(self):
        return self.cdef_inline_method()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cmp.pyx0000644000175100001770000000326300000000000017067 0ustar00runnerdocker00000000000000def single_py(a, b):
    """
    >>> single_py(1, 2)
    True
    >>> single_py(2, 1)
    False
    """
    return a < b

def cascaded_py(a, b, c):
    """
    >>> cascaded_py(1, 2, 3)
    True
    >>> cascaded_py(1, 2, -1)
    False
    >>> cascaded_py(10, 2, 3)
    False
    """
    return a < b < c

def single_c(int a, int b):
    """
    >>> single_c(1, 2)
    True
    >>> single_c(2, 1)
    False
    """
    return a < b

def cascaded_c(double a, double b, double c):
    """
    >>> cascaded_c(1, 2, 3)
    True
    >>> cascaded_c(1, 2, -1)
    False
    >>> cascaded_c(10, 2, 3)
    False
    """
    return a < b < c

def cascaded_mix_pyleft(a, double b, double c):
    """
    >>> cascaded_mix_pyleft(1, 2, 3)
    True
    >>> cascaded_mix_pyleft(1, 2, -1)
    False
    >>> cascaded_mix_pyleft(10, 2, 3)
    False
    """
    return a < b < c

def cascaded_mix_pyright(double a, double b, c):
    """
    >>> cascaded_mix_pyright(1, 2, 3)
    True
    >>> cascaded_mix_pyright(1, 2, -1)
    False
    >>> cascaded_mix_pyright(10, 2, 3)
    False
    """
    return a < b < c

def typed_cmp(list L):
    """
    >>> typed_cmp([1,2,3])
    False
    False
    False
    False
    """
    print L is Ellipsis
    print Ellipsis is L
    print 1 == L
    print L == 1.5

def pointer_cmp():
    """
    >>> pointer_cmp()
    True
    False
    True
    """
    cdef int* a = NULL
    cdef double* b = NULL
    cdef double** c = NULL
    print a is NULL
    print b is not NULL
    print c == NULL

def c_cmp(double a, int b, long c):
    """
    >>> c_cmp(1, 2, 3)
    True
    >>> c_cmp(1.5, 2, 2)
    True
    >>> c_cmp(1.5, 2, 0)
    False
    >>> c_cmp(1, 1, 3)
    False
    """
    return a < b <= c
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/code_object_cache.pyx0000644000175100001770000001017000000000000021666 0ustar00runnerdocker00000000000000# mode: run
# tag: except

# test the code object cache that is being used in exception raising

### low level tests

cimport cython

cdef extern from *:
    # evil hack to access the internal utility function
    ctypedef struct PyCodeObject
    ctypedef struct __Pyx_CodeObjectCacheEntry:
        int code_line
        PyCodeObject* code_object
    int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line)

def test_lowlevel_bisect2(*indices):
    """
    >>> test_lowlevel_bisect2(1, 2, 3, 4, 5, 6)
    [0, 0, 1, 1, 2, 2]
    """
    cdef __Pyx_CodeObjectCacheEntry* cache = [
        __Pyx_CodeObjectCacheEntry(2, NULL),
        __Pyx_CodeObjectCacheEntry(4, NULL),
        ]
    return [ __pyx_bisect_code_objects(cache, 2, i)
             for i in indices ]

def test_lowlevel_bisect5(*indices):
    """
    >>> test_lowlevel_bisect5(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
    [0, 1, 2, 2, 2, 3, 3, 3, 4, 5, 5]
    """
    cdef __Pyx_CodeObjectCacheEntry* cache = [
        __Pyx_CodeObjectCacheEntry(1, NULL),
        __Pyx_CodeObjectCacheEntry(2, NULL),
        __Pyx_CodeObjectCacheEntry(5, NULL),
        __Pyx_CodeObjectCacheEntry(8, NULL),
        __Pyx_CodeObjectCacheEntry(9, NULL),
        ]
    return [ __pyx_bisect_code_objects(cache, 5, i)
             for i in indices ]

def test_lowlevel_bisect6(*indices):
    """
    >>> test_lowlevel_bisect6(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)
    [0, 0, 1, 2, 2, 2, 3, 3, 4, 5, 5, 5, 6]
    """
    cdef __Pyx_CodeObjectCacheEntry* cache = [
        __Pyx_CodeObjectCacheEntry(2, NULL),
        __Pyx_CodeObjectCacheEntry(3, NULL),
        __Pyx_CodeObjectCacheEntry(6, NULL),
        __Pyx_CodeObjectCacheEntry(8, NULL),
        __Pyx_CodeObjectCacheEntry(9, NULL),
        __Pyx_CodeObjectCacheEntry(12, NULL),
        ]
    return [ __pyx_bisect_code_objects(cache, 6, i)
             for i in indices ]

### Python level tests

import sys

def tb():
    return sys.exc_info()[-1]

def raise_keyerror():
    raise KeyError

def check_code_object_identity_recursively(tb1, tb2):
    if tb1 is None or tb2 is None:
        return
    code1, code2 = tb1.tb_frame.f_code, tb2.tb_frame.f_code
    if code1 is not code2:
        print('%s != %s' % (code1, code2))
    check_code_object_identity_recursively(tb1.tb_next, tb2.tb_next)

def assert_simple_code_object_reuse():
    """
    >>> try: assert_simple_code_object_reuse()
    ... except KeyError: t1 = tb()
    >>> try: assert_simple_code_object_reuse()
    ... except KeyError: t2 = tb()
    >>> check_code_object_identity_recursively(t1.tb_next, t2.tb_next)
    """
    raise KeyError

def assert_multi_step_code_object_reuse(recursions=0):
    """
    >>> for depth in range(5):
    ...     try: assert_multi_step_code_object_reuse(depth)
    ...     except KeyError: t1 = tb()
    ...     try: assert_multi_step_code_object_reuse(depth)
    ...     except KeyError: t2 = tb()
    ...     check_code_object_identity_recursively(t1.tb_next, t2.tb_next)
    """
    if recursions:
        assert_multi_step_code_object_reuse(recursions-1)
    else:
        raise_keyerror()

def assert_simple_code_object_reuse_fused(cython.floating dummy):
    """
    DISABLED: searching for code objects based on C lineno breaks for specializations

    >> try: assert_simple_code_object_reuse_fused["float"](1.0)
    ... except KeyError: t1 = tb()
    >> try: assert_simple_code_object_reuse_fused["double"](1.0)
    ... except KeyError: t2 = tb()
    >> check_code_object_identity_recursively(t1.tb_next, t2.tb_next)
    """
    raise KeyError

def assert_multi_step_code_object_reuse_fused(recursions=0, cython.floating dummy = 2.0):
    """
    DISABLED: searching for code objects based on C lineno breaks for specializations

    >> for depth in range(5):
    ...     try: assert_multi_step_code_object_reuse_fused(depth, 1.0)
    ...     except KeyError: t1 = tb()
    ...     try: assert_multi_step_code_object_reuse_fused(depth, 1.0)
    ...     except KeyError: t2 = tb()
    ...     check_code_object_identity_recursively(t1.tb_next, t2.tb_next)
    """
    if recursions:
        assert_multi_step_code_object_reuse(recursions-1)
    else:
        raise_keyerror()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/coercearraytoptr.pyx0000644000175100001770000000067100000000000021700 0ustar00runnerdocker00000000000000cdef char* cstring = "abcdefg"

cdef void spam(char *target):
    cdef char* s = cstring
    while s[0]:
        target[0] = s[0]
        s += 1
        target += 1
    target[0] = c'\0'

cdef struct Grail:
    char silly[42]

def eggs():
    """
    >>> print(str(eggs()).replace("b'", "'"))
    ('abcdefg', 'abcdefg')
    """
    cdef char[42] silly
    cdef Grail grail
    spam(silly)
    spam(grail.silly)
    return silly, grail.silly
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/common_utility_types.srctree0000644000175100001770000000225300000000000023434 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import runner"

######## setup.py ########

from Cython.Build.Dependencies import cythonize

from distutils.core import setup

setup(
  ext_modules = cythonize("*.pyx"),
)

######## a.pyx ########

# cython: binding=True

def funcA():
    return

######## b.pyx ########

# cython: binding=True

def funcB():
    return

######## runner.py ########

print("importing...")
import a, b
print(type(a.funcA))

assert type(a.funcA).__name__.endswith('cython_function_or_method')
assert type(a.funcA) is type(b.funcB)

assert a.funcA.func_globals is a.__dict__
assert b.funcB.func_globals is b.__dict__

# Test that it's possible to look up the name of the class
from sys import modules
cy_modules = [ mod for n, mod in modules.items() if n.startswith("_cython_") ]
# In principle it's possible to have "_cython_" internal modules for multiple
# different versions of Cython. However, since this is run in an end-to-end test
# with a very short list of imports it should not happen here.
assert(len(cy_modules)==1)
mod = cy_modules[0]

assert '.' not in type(a.funcA).__name__
func_t = getattr(mod, type(a.funcA).__name__)
assert func_t is type(a.funcA)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/compare_binary_pyversions.pyx0000644000175100001770000000563700000000000023612 0ustar00runnerdocker00000000000000# mode: run
# tag: internal

cdef extern from *:
    int check_binary_version "__Pyx_check_binary_version" (unsigned long ct_version, unsigned long rt_version, int allow_newer) except -1
    unsigned long get_runtime_version "__Pyx_get_runtime_version" ()
    unsigned long PY_VERSION_HEX


def test_get_runtime_version():
    """
    >>> test_get_runtime_version()
    True
    """
    cdef unsigned long rt_version = get_runtime_version()
    return PY_VERSION_HEX & ~0xFF == rt_version or  (hex(PY_VERSION_HEX), hex(rt_version))


def iter_hex_versions():
    cdef long major, minor, dot
    for major in range(0, 20):
        for minor in range(0, 20, 3):
            for dot in range(0, 20, 3):
                yield ((major * 16 + minor) * 16 + dot) * 16


def test_compare_binary_versions_exact():
    """
    >>> import warnings
    >>> warnings.simplefilter("error")
    >>> test_compare_binary_versions_exact()
    >>> warnings.resetwarnings()
    """
    cdef long major_and_minor = 0xFFFF0000
    cdef long rt_version, ct_version

    versions = list(iter_hex_versions())
    for ct_version in versions:
        for rt_version in versions:
            if rt_version & major_and_minor == ct_version & major_and_minor:
                assert check_binary_version(ct_version, rt_version, 0) == 0, (hex(rt_version), hex(ct_version))
            else:
                try:
                    check_binary_version(ct_version, rt_version, 0)
                except Warning as exc:
                    assert "does not match runtime version" in str(exc), exc
                else:
                    assert not "raised", (hex(rt_version), hex(ct_version))


def test_compare_binary_versions_minimum():
    """
    >>> import warnings
    >>> warnings.simplefilter("error")
    >>> test_compare_binary_versions_minimum()
    >>> warnings.resetwarnings()
    """
    cdef long major_and_minor = 0xFFFF0000
    cdef long rt_version, ct_version

    versions = list(iter_hex_versions())
    for ct_version in versions:
        for rt_version in versions:
            if rt_version & major_and_minor >= ct_version & major_and_minor:
                result = check_binary_version(ct_version, rt_version, 1)
                if rt_version & major_and_minor > ct_version & major_and_minor:
                    assert result == 1, (hex(rt_version), hex(ct_version))
                else:
                    assert result == 0, (hex(rt_version), hex(ct_version))
            else:
                try:
                    check_binary_version(ct_version, rt_version, 1)
                except Warning as exc:
                    if rt_version & major_and_minor < ct_version & major_and_minor:
                        assert "was newer than runtime version" in str(exc), exc
                    else:
                        assert "does not match runtime version" in str(exc), exc
                else:
                    assert not "raised", (hex(rt_version), hex(ct_version))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/compiledef.pyx0000644000175100001770000000051100000000000020410 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> t
    True
    >>> f
    False
    >>> boolexpr
    True
    >>> num6
    6
    >>> intexpr
    10
"""

DEF c_t = True
DEF c_f = False
DEF c_boolexpr = c_t and True and not (c_f or False)

DEF c_num6 = 2*3
DEF c_intexpr = c_num6 + 4

t = c_t
f = c_f
boolexpr = c_boolexpr
num6 = c_num6
intexpr = c_intexpr
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/complex_cast_T445.pyx0000644000175100001770000000230200000000000021502 0ustar00runnerdocker00000000000000# ticket: t445

def complex_double_cast(double x, double complex z):
    """
    >>> complex_double_cast(1, 4-3j)
    ((1+0j), (4-3j))
    """
    cdef double complex xx = x
    cdef double complex zz = z
    xx = x
    return xx, zz

def complex_double_int_cast(int x, int complex z):
    """
    >>> complex_double_int_cast(2, 2 + 3j)
    ((2+0j), (3+3j))
    """
    cdef double complex xx = x
    cdef double complex zz = (z+1)
    return xx, zz

def complex_int_double_cast(double x, double complex z):
    """
    >>> complex_int_double_cast(2.5, 2.5 + 3.5j)
    ((2+0j), (2+3j))
    """
    cdef int complex xx = x
    cdef int complex zz = z
    return xx, zz

cdef int side_effect_counter = 0

cdef double complex side_effect(double complex z):
    global side_effect_counter
    side_effect_counter += 1
    print "side effect", side_effect_counter, z
    return z

def test_side_effect(int complex z):
    """
    >>> test_side_effect(5)
    side effect 1 (5+0j)
    (5+0j)
    >>> test_side_effect(3-4j)
    side effect 2 (3-4j)
    (3-4j)
    """
    cdef int complex zz = side_effect(z)
    return zz
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/complex_coercion_sideeffects_T693.pyx0000644000175100001770000000052500000000000024727 0ustar00runnerdocker00000000000000# mode: run
# ticket: t693

cdef double complex func(double complex x):                                                  
    print "hello"
    return x

def test_coercion():
    """
    >>> c = test_coercion()
    hello
    >>> c.real == 0.5
    True
    >>> c.imag == 1.5
    True
    """
    cdef object x = func(0.5 + 1.5j)
    return x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/complex_extern_GH1433.pyx0000644000175100001770000000046100000000000022232 0ustar00runnerdocker00000000000000# tag: numpy

cimport numpy as np

def divide(np.float64_t x, np.complex128_t y):
    """
    >>> divide(2, 1+1j)
    (1-1j)
    """
    return x / y

def pow(np.complex128_t x, np.complex128_t y):
    """
    >>> pow(1 + 1j, 2j)  # doctest: +ELLIPSIS
    (0.1599...+0.1328...j)
    """
    return x ** y
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/complex_int_T446.pyx0000644000175100001770000000246100000000000021351 0ustar00runnerdocker00000000000000# ticket: t446

import cython

cdef extern from *:
    """
    #if defined _MSC_VER && defined __cplusplus
    #define CYTHON_CCOMPLEX 0
    #endif
    """


def test_arith(int complex a, int complex b):
    """
    >>> test_arith(4, 2)
    ((-4+0j), (6+0j), (2+0j), (8+0j))
    >>> test_arith(6+9j, 3j)
    ((-6-9j), (6+12j), (6+6j), (-27+18j))
    >>> test_arith(29+11j, 5+7j)
    ((-29-11j), (34+18j), (24+4j), (68+258j))
    """
    return -a, a+b, a-b, a*b

@cython.cdivision(False)
def test_div_by_zero(long complex z):
    """
    >>> test_div_by_zero(4j)
    -25j
    >>> test_div_by_zero(0)
    Traceback (most recent call last):
    ...
    ZeroDivisionError: float division
    """
    return 100/z

def test_coercion(int a, long b, int complex c):
    """
    >>> test_coercion(1, -2, 3-3j)
    (1+0j)
    (-2+0j)
    (3-3j)
    (5-6j)
    """
    cdef double complex z
    z = a; print z
    z = b; print z
    z = c; print z
    return z + a + b + c


def test_conjugate(long complex z):
    """
    >>> test_conjugate(2+3j)
    (2-3j)
    """
    return z.conjugate()

def test_conjugate2(short complex z):
    """
    >>> test_conjugate2(2+3j)
    (2-3j)
    """
    return z.conjugate()

def test_conjugate3(long long complex z):
    """
    >>> test_conjugate3(2+3j)
    (2-3j)
    """
    return z.conjugate()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/complex_numbers_T305.pyx0000644000175100001770000002243500000000000022227 0ustar00runnerdocker00000000000000# ticket: t305

from cpython.object cimport Py_EQ, Py_NE

cimport cython

DEF C21 = 2-1j


cdef class Complex3j:
    """
    >>> Complex3j() == 3j
    True
    >>> Complex3j() == Complex3j()
    True
    >>> Complex3j() != 3j
    False
    >>> Complex3j() != 3
    True
    >>> Complex3j() != Complex3j()
    False
    """
    def __richcmp__(a, b, int op):
        if op == Py_EQ or op == Py_NE:
            if isinstance(a, Complex3j):
                eq = isinstance(b, Complex3j) or b == 3j
            else:
                eq = isinstance(b, Complex3j) and a == 3j
            return eq if op == Py_EQ else not eq
        return NotImplemented


def test_object_conversion(o):
    """
    >>> test_object_conversion(2)
    ((2+0j), (2+0j))
    >>> test_object_conversion(2j - 0.5)
    ((-0.5+2j), (-0.5+2j))
    """
    cdef float complex a = o
    cdef double complex b = o
    return (a, b)


def test_arithmetic(double complex z, double complex w):
    """
    >>> test_arithmetic(2j, 4j)
    (2j, -2j, 6j, -2j, (-8+0j), (0.5+0j))
    >>> test_arithmetic(6+12j, 3j)
    ((6+12j), (-6-12j), (6+15j), (6+9j), (-36+18j), (4-2j))
    >>> test_arithmetic(5-10j, 3+4j)
    ((5-10j), (-5+10j), (8-6j), (2-14j), (55-10j), (-1-2j))
    """
    return +z, -z+0, z+w, z-w, z*w, z/w


def test_div(double complex a, double complex b, expected):
    """
    >>> big = 2.0**1023
    >>> test_div(1 + 1j, 1 + big*1j, 1/big - 1j/big)
    >>> test_div(1 + 1j, 1/big + 1j/big, big)
    """
    # Can't count on good c99 complex division :(
    if '_c99_' not in __name__:
        assert a / b == expected, (a / b, expected)


def test_pow(double complex z, double complex w, tol=None):
    """
    Various implementations produce slightly different results...

    >>> a = complex(3, 1)
    >>> test_pow(a, 1, 1e-15)
    True
    >>> test_pow(a, 2, 1e-15)
    True
    >>> test_pow(a, a, 1e-15)
    True
    >>> test_pow(complex(0.5, -.25), complex(3, 4), 1e-15)
    True
    >>> test_pow(-0.5, 1j, tol=1e-15)
    True
    >>> test_pow(-1, 0.5, tol=1e-15)
    True
    """
    if tol is None:
        return z**w
    else:
        return abs(z**w / z ** w - 1) < tol


def test_int_pow(double complex z, int n, tol=None):
    """
    >>> [test_int_pow(complex(0, 1), k, 1e-15) for k in range(-4, 5)]
    [True, True, True, True, True, True, True, True, True]
    >>> [test_int_pow(complex(0, 2), k, 1e-15) for k in range(-4, 5)]
    [True, True, True, True, True, True, True, True, True]
    >>> [test_int_pow(complex(2, 0.5), k, 1e-14) for k in range(0, 10)]
    [True, True, True, True, True, True, True, True, True, True]
    >>> test_int_pow(-0.5, 5, tol=1e-15)
    True
    """
    if tol is None:
        return z**n + 0 # add zero to normalize zero sign
    else:
        return abs(z**n / z ** n - 1) < tol


@cython.cdivision(False)
def test_div_by_zero(double complex z):
    """
    >>> test_div_by_zero(4j)
    -0.25j
    >>> test_div_by_zero(0)
    Traceback (most recent call last):
    ...
    ZeroDivisionError: float division
    """
    return 1/z


def test_coercion(int a, float b, double c, float complex d, double complex e):
    """
    >>> test_coercion(1, 1.5, 2.5, 4+1j, 10j)
    (1+0j)
    (1.5+0j)
    (2.5+0j)
    (4+1j)
    10j
    (9+21j)
    """
    cdef double complex z
    z = a; print z
    z = b; print z
    z = c; print z
    z = d; print z
    z = e; print z
    return z + a + b + c + d + e


def test_compare(double complex a, double complex b):
    """
    >>> test_compare(3, 3)
    (True, False, False, False, False, True, False)
    >>> test_compare(3j, 3j)
    (True, False, True, True, True, False, False)
    >>> test_compare(3j, 4j)
    (False, True, True, False, True, True, False)
    >>> test_compare(3, 4)
    (False, True, False, False, False, True, False)
    >>> test_compare(2-1j, 4)
    (False, True, False, False, False, True, True)
    """
    return a == b, a != b, a == 3j, 3j == b, a == Complex3j(), Complex3j() != b, a == C21


def test_compare_coerce(double complex a, int b):
    """
    >>> test_compare_coerce(3, 4)
    (False, True, False, False, False, True)
    >>> test_compare_coerce(4+1j, 4)
    (False, True, False, True, False, True)
    >>> test_compare_coerce(4, 4)
    (True, False, False, False, False, True)
    >>> test_compare_coerce(3j, 4)
    (False, True, True, False, True, False)
    """
    return a == b, a != b, a == 3j, 4+1j == a, a == Complex3j(), Complex3j() != a


def test_literal():
    """
    >>> test_literal()
    (5j, (1-2.5j), (2-1j))
    """
    return 5j, 1-2.5j, C21


def test_real_imag(double complex z):
    """
    >>> test_real_imag(1-3j)
    (1.0, -3.0)
    >>> test_real_imag(5)
    (5.0, 0.0)
    >>> test_real_imag(1.5j)
    (0.0, 1.5)
    """
    return z.real, z.imag

def test_real_imag_assignment(object a, double b):
    """
    >>> test_real_imag_assignment(1, 2)
    (1+2j)
    >>> test_real_imag_assignment(1.5, -3.5)
    (1.5-3.5j)
    """
    cdef double complex z
    z.real = a
    z.imag = b
    return z

def test_conjugate(float complex z):
    """
    >>> test_conjugate(2+3j)
    (2-3j)
    """
    return z.conjugate()

def test_conjugate_double(double complex z):
    """
    >>> test_conjugate_double(2+3j)
    (2-3j)
    """
    return z.conjugate()

ctypedef double complex cdouble
def test_conjugate_typedef(cdouble z):
    """
    >>> test_conjugate_typedef(2+3j)
    (2-3j)
    """
    return z.conjugate()

cdef cdouble test_conjugate_nogil(cdouble z) nogil:
    # Really just a compile test.
    return z.conjugate()
test_conjugate_nogil(0) # use it

## cdef extern from "complex_numbers_T305.h":
##     ctypedef double double_really_float "myfloat"
##     ctypedef float float_really_double "mydouble"
##     ctypedef float real_float "myfloat"
##     ctypedef double real_double "mydouble"

## def test_conjugate_nosizeassumptions(double_really_float x,
##                                      float_really_double y,
##                                      real_float z, real_double w):
##     """
##     >>> test_conjugate_nosizeassumptions(1, 1, 1, 1)
##     (-1j, -1j, -1j, -1j)
##     >>> ["%.2f" % x.imag for x in test_conjugate_nosizeassumptions(2e300, 2e300, 2e300, 2e300)]
##     ['-inf', '-2e+300', '-inf', '-2e+300']
##     """
##     cdef double complex I = 1j
##     return ((x*I).conjugate(), (y*I).conjugate(), (z*I).conjugate(), (w*I).conjugate())

ctypedef double mydouble
def test_coerce_typedef_multiply(mydouble x, double complex z):
    """
    >>> test_coerce_typedef_multiply(3, 1+1j)
    (3+3j)
    """
    return x * z

ctypedef int myint
def test_coerce_typedef_multiply_int(myint x, double complex z):
    """
    >>> test_coerce_typedef_multiply_int(3, 1+1j)
    (3+3j)
    """
    return x * z

cpdef double complex complex_retval():
    """
    >>> complex_retval()
    1j
    """
    return 1j

def stress_test():
    """
    Run the main operations on 1000 pseudo-random numbers to
    try to spot anything accidentally missed from the test cases
    (doesn't cover inf and NaN as inputs though)
    >>> stress_test()
    """
    cdef double complex x
    cdef double complex y

    from random import Random
    from math import ldexp
    r = Random()
    r.seed("I'm a seed")  # try to make the test somewhat reproducible

    # copied from https://docs.python.org/3/library/random.html#recipes
    # gets evenly distributed random numbers
    def full_random():
        mantissa = 0x10_0000_0000_0000 | r.getrandbits(52)
        exponent = -53
        x = 0
        while not x:
            x = r.getrandbits(32)
            exponent += x.bit_length() - 32
        return ldexp(mantissa, exponent)

    for n in range(1, 1001):
        if n % 50 == 0:
            # strategical insert some 0 values
            a = 0
        else:
            a = full_random()
        if n % 51 == 0:
            b = 0
        else:
            b = full_random()
        if n % 52 == 0:
            c = 0
        else:
            c = full_random()
        if n % 53 == 0:
            d = 0
        else:
            d = full_random()

        x= a+1j*b
        y = c+1j*d
        py_dict = dict(x=x, y=y)

        sum_ = x+y
        sum_py = eval("x+y", py_dict)
        delta_sum = abs(sum_/sum_py - 1)
        assert delta_sum < 1e-15, f"{x} {y} {sum_} {sum_py} {delta_sum}"

        minus = x-y
        minus_py = eval("x-y", py_dict)
        delta_minus = abs(minus/minus_py - 1)
        assert delta_minus < 1e-15, f"{x} {y} {minus} {minus_py} {delta_minus}"

        times = x*y
        times_py = eval("x*y", py_dict)
        delta_times = abs(times/times_py - 1)
        assert delta_times < 1e-15, f"{x} {y} {times} {times_py} {delta_times}"

        divide = x/y
        divide_py = eval("x/y", py_dict)
        delta_divide = abs(divide/divide_py - 1)
        assert delta_divide < 1e-15, f"{x} {y} {divide} {divide_py} {delta_divide}"

        divide2 = y/x
        divide2_py = eval("y/x", py_dict)
        delta_divide2 = abs(divide2/divide2_py - 1)
        assert delta_divide2 < 1e-15, f"{x} {y} {divide2} {divide2_py} {delta_divide2}"

        pow_ = x**y
        pow_py = eval("x**y", py_dict)
        delta_pow = abs(pow_/pow_py - 1)
        assert delta_pow < 1e-15, f"{x} {y} {pow_} {pow_py} {delta_pow}"

        pow2 = y**x
        pow2_py = eval("y**x", py_dict)
        delta_pow2 = abs(pow2/pow2_py - 1)
        assert delta_pow2 < 1e-15, f"{x} {y} {pow2} {pow2_py} {delta_pow2}"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/complex_numbers_T305_long_double.pyx0000644000175100001770000000034300000000000024572 0ustar00runnerdocker00000000000000# ticket: t305

cimport cython

def test_object_conversion(o):
    """
    >>> test_object_conversion(2)
    (2+0j)
    >>> test_object_conversion(2j - 0.5)
    (-0.5+2j)
    """
    cdef long double complex a = o
    return a
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/complex_numbers_c89_T398.h0000644000175100001770000000003200000000000022322 0ustar00runnerdocker00000000000000#define CYTHON_CCOMPLEX 0
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/complex_numbers_c89_T398.pyx0000644000175100001770000000014700000000000022722 0ustar00runnerdocker00000000000000# ticket: t398

cdef extern from "complex_numbers_c89_T398.h": pass
include "complex_numbers_T305.pyx"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/complex_numbers_c89_T398_long_double.pyx0000644000175100001770000000016300000000000025271 0ustar00runnerdocker00000000000000# ticket: t398

cdef extern from "complex_numbers_c89_T398.h": pass
include "complex_numbers_T305_long_double.pyx"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/complex_numbers_c99_T398.h0000644000175100001770000000123600000000000022332 0ustar00runnerdocker00000000000000#if !defined(__cplusplus)
#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) \
  || defined(__GNUC__)						 \
  || defined(__INTEL_COMPILER)					 \
  || defined(__IBMC__)						 \

#include 
#if !defined(_Complex_I)
#error The "complex.h" header does not define the '_Complex_I' macro.
#error Please report this to Cython developers 
#endif

#elif defined(_MSC_VER)
/* Although the MSVC compilers implementation of complex isn't
   compatible with Cython, it shouldn't cause Cython to define
   CYTHON_CCOMPLEX. Instead Cython should use it's own complex
   implementation.
 */
#include 
#endif
#endif
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/complex_numbers_c99_T398.pyx0000644000175100001770000000014700000000000022723 0ustar00runnerdocker00000000000000# ticket: t398

cdef extern from "complex_numbers_c99_T398.h": pass
include "complex_numbers_T305.pyx"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/complex_numbers_cmath_T2891.pyx0000644000175100001770000000047500000000000023477 0ustar00runnerdocker00000000000000# ticket: 2891
# tag: c, no-cpp

cdef extern from "complex_numbers_c99_T398.h": pass

from libc.complex cimport cimag, creal, cabs, carg


def test_decomposing(double complex z):
    """
    >>> test_decomposing(3+4j)
    (3.0, 4.0, 5.0, 0.9272952180016122)
    """

    return (creal(z), cimag(z), cabs(z), carg(z))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/complex_numbers_cpp.pyx0000644000175100001770000000057400000000000022356 0ustar00runnerdocker00000000000000# tag: cpp

from libcpp.complex cimport complex as complex_class

def double_complex(complex_class[double] a):
    """
    >>> double_complex(1 + 2j)
    (1+2j)
    >>> double_complex(1.5 + 2.5j)
    (1.5+2.5j)
    """
    return a

def double_int(complex_class[int] a):
    """
    >>> double_int(1 + 2j)
    (1+2j)
    >>> double_int(1.5 + 2.5j)
    (1+2j)
    """
    return a
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/complex_numbers_cxx_T398.h0000644000175100001770000000013200000000000022522 0ustar00runnerdocker00000000000000#if defined(__cplusplus)
#define CYTHON_CCOMPLEX 1
#else
#define CYTHON_CCOMPLEX 0
#endif
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/complex_numbers_cxx_T398.pyx0000644000175100001770000000014700000000000023121 0ustar00runnerdocker00000000000000# ticket: t398

cdef extern from "complex_numbers_cxx_T398.h": pass
include "complex_numbers_T305.pyx"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/concatcstrings.pyx0000644000175100001770000000030600000000000021327 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> spam == u'C string 1' + u'C string 2'
    True
"""

import sys
if sys.version_info[0] >= 3:
    __doc__ = __doc__.replace(u" u'", u" '")

spam = u"C string 1" + u"C string 2"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/constant_folding.py0000644000175100001770000002605000000000000021452 0ustar00runnerdocker00000000000000# coding=utf8
# mode: run
# tag: constant_folding

import cython


import sys
IS_PY2 = sys.version_info < (3, 0)


def print_big_ints(t):
    s = repr(t)
    if IS_PY2:
        s = s.replace('L', '')
    print(s)


@cython.test_fail_if_path_exists(
    "//UnaryMinusNode",
    "//UnaryPlusNode",
)
def unop_floats():
    """
    >>> unop_floats()
    (False, 2.0, -2.0, False, 2.0, -2.0, -2.0)
    """
    not1   = not 2.0
    plus1  = + 2.0
    minus1 = - 2.0
    not3   = not not not 2.0
    plus3  = +++ 2.0
    minus3 = --- 2.0
    mix    = +-++-- 2.0
    return not1, plus1, minus1, not3, plus3, minus3, mix


@cython.test_fail_if_path_exists(
    "//UnaryMinusNode",
    "//UnaryPlusNode",
    "//CoerceToPyTypeNode",
)
def unop_py_floats_tuple():
    """
    >>> unop_floats()
    (False, 2.0, -2.0, False, 2.0, -2.0, -2.0)
    """
    return (
        not 2.0,
        + 2.0,
        - 2.0,
        not not not 2.0,
        +++ 2.0,
        --- 2.0,
        +-++-- 2.0)


@cython.test_fail_if_path_exists(
    "//UnaryMinusNode",
    "//UnaryPlusNode",
)
def unop_ints():
    """
    >>> unop_ints()
    (False, 2, -2, False, 2, -2, -2)
    """
    not1   = not 2
    plus1  = + 2
    minus1 = - 2
    not3   = not not not 2
    plus3  = +++ 2
    minus3 = --- 2
    mix    = +-++-- 2
    return not1, plus1, minus1, not3, plus3, minus3, mix


@cython.test_fail_if_path_exists(
    "//UnaryMinusNode",
    "//UnaryPlusNode",
    "//NotNode",
)
def unop_bool():
    """
    >>> unop_bool()
    (False, 1, -1, False, 1, -1, -1)
    """
    not1   = not True
    plus1  = + True
    minus1 = - True
    not3   = not not not True
    plus3  = +++ True
    minus3 = --- True
    mix    = +-++-- True
    return not1, plus1, minus1, not3, plus3, minus3, mix


@cython.test_fail_if_path_exists(
    "//AddNode",
    "//SubNode",
)
def binop_bool():
    """
    >>> binop_bool()
    (2, 1, 0, True, True, 1, False, 2, 2, -2, False, True, 1, False)
    """
    plus1  = True + True
    pmix1  = True + 0
    minus1 = True - True
    and1   = True & True
    or1    = True | True
    ormix1 = True | 0
    xor1   = True ^ True
    plus3  = False + True + False + True
    pmix3  = False + True + 0 + True
    minus3 = False - True - False - True
    and3   = False & True & False & True
    or3    = False | True | False | True
    ormix3 = False | 0 | False | True
    xor3   = False ^ True ^ False ^ True
    return plus1, pmix1, minus1, and1, or1, ormix1, xor1, plus3, pmix3, minus3, and3, or3, ormix3, xor3


@cython.test_fail_if_path_exists(
    "//MulNode",
    "//PowNode",
)
def binop_mul_pow():
    """
    >>> print_big_ints(binop_mul_pow())
    (800, 12193263111263526900, 248832, 12467572902176589255564000298710470656)
    """
    mul_int = 20 * 40
    mul_large_int = 1234567890 * 9876543210
    pow_int = 12 ** 5
    pow_large_int = 1234 ** 12
    return (mul_int, mul_large_int, pow_int, pow_large_int)


def binop_pow_negative():
    """
    >>> print_big_ints(binop_pow_negative())
    (4.018775720164609e-06, 8.020807320287816e-38, 0.1)
    """
    pow_int = 12 ** -5
    pow_large_int = 1234 ** -12
    pow_expression_int = 10 ** (1-2)
    return (pow_int, pow_large_int, pow_expression_int)


@cython.test_fail_if_path_exists(
    "//SliceIndexNode",
)
def slicing2():
    """
    >>> slicing2()
    ([1, 2, 3, 4], [3, 4], [1, 2, 3, 4], [3, 4], (1, 2, 3, 4), (3, 4), (1, 2, 3, 4), (3, 4))
    """
    lst0 = [1, 2, 3, 4][:]
    lst1 = [1, 2, 3, 4][2:]
    lst2 = [1, 2, 3, 4][:4]
    lst3 = [1, 2, 3, 4][2:4]

    tpl0 = (1, 2, 3, 4)[:]
    tpl1 = (1, 2, 3, 4)[2:]
    tpl2 = (1, 2, 3, 4)[:4]
    tpl3 = (1, 2, 3, 4)[2:4]

    return lst0, lst1, lst2, lst3, tpl0, tpl1, tpl2, tpl3


@cython.test_fail_if_path_exists(
    "//SliceIndexNode",
)
def str_slicing2():
    """
    >>> a,b,c,d = str_slicing2()
    >>> a == 'abc\\xE9def'[:]
    True
    >>> b == 'abc\\xE9def'[2:]
    True
    >>> c == 'abc\\xE9def'[:4]
    True
    >>> d == 'abc\\xE9def'[2:4]
    True
    """
    str0 = 'abc\xE9def'[:]
    str1 = 'abc\xE9def'[2:]
    str2 = 'abc\xE9def'[:4]
    str3 = 'abc\xE9def'[2:4]

    return str0, str1, str2, str3


@cython.test_fail_if_path_exists(
    "//IfStatNode",
)
def str_in_and_not_in():
    """
    >>> str_in_and_not_in()
    True
    """
    if 'a' in 'abc' and 'b' in 'abc' and 'c' in 'abc' and 'd' not in 'abc': return True
    else: return False


@cython.test_fail_if_path_exists(
    "//WhileStatNode",
)
def while_false():
    """
    >>> while_false()
    """
    while 1 == 0:
        return False


@cython.test_fail_if_path_exists(
    "//WhileStatNode",
    )
def while_false_else():
    """
    >>> while_false_else()
    True
    """
    while 1 == 0:
        return False
    else:
        return True


@cython.test_fail_if_path_exists(
    "//WhileStatNode//PrintStatNode",
    "//WhileStatNode//PrimaryCmpNode",
    "//WhileStatNode/BoolNode",
    "//WhileStatNode/IntNode",
)
@cython.test_assert_path_exists(
    "//WhileStatNode",
)
def while_true():
    """
    >>> while_true()
    True
    """
    while 1 == 1:
        return True
    else:
        print("FAIL")


@cython.test_fail_if_path_exists(
    "//ForInStatNode",
)
def for_in_empty():
    """
    >>> for_in_empty()
    """
    for i in []:
        print("LOOP")


@cython.test_fail_if_path_exists(
    "//ForInStatNode",
)
def for_in_empty_else():
    """
    >>> for_in_empty_else()
    True
    """
    for i in []:
        print("LOOP")
    else:
        return True


@cython.test_fail_if_path_exists(
    "//ComprehensionNode",
    "//ForInStatNode",
)
@cython.test_assert_path_exists(
    "//ListNode",
)
def for_in_empty_listcomp():
    """
    >>> for_in_empty_listcomp()
    []
    """
    return [i for i in []]


@cython.test_fail_if_path_exists(
    "//ComprehensionNode",
    "//ForInStatNode",
)
@cython.test_assert_path_exists(
    "//ListNode",
)
def for_in_empty_nested_listcomp():
    """
    >>> for_in_empty_nested_listcomp()
    []
    """
    return [x for _ in [] for x in [1, 2, 3]]


@cython.test_fail_if_path_exists(
    "//ForInStatNode//ForInStatNode",
)
@cython.test_assert_path_exists(
    "//ForInStatNode",
    "//ComprehensionNode",
)
def for_in_nested_listcomp():
    """
    >>> for_in_nested_listcomp()
    []
    """
    return [x for x in [1, 2, 3] for _ in []]


@cython.test_fail_if_path_exists(
    "//MulNode",
)
def mult_empty_list():
    """
    >>> mult_empty_list()
    []
    """
    return 5 * [] * 100


@cython.test_fail_if_path_exists(
    "//MulNode",
)
def mult_list_int_int():
    """
    >>> mult_list_int_int()
    [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
    """
    return [1, 2] * 2 * 3


@cython.test_fail_if_path_exists(
    "//MulNode",
)
def mult_int_list_int():
    """
    >>> mult_int_list_int()
    [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
    """
    return 3 * [1, 2] * 2


@cython.test_fail_if_path_exists(
    "//MulNode",
    "//ListNode//IntNode",
)
def neg_mult_list():
    """
    >>> neg_mult_list()
    []
    """
    return -5 * [1, 2] * -100


@cython.test_fail_if_path_exists(
    "//MulNode",
    "//ListNode//IntNode",
)
def zero_mult_list():
    """
    >>> zero_mult_list()
    []
    """
    return 0 * [1, 2] * 0


@cython.test_assert_path_exists(
    "//BoolNode",
)
@cython.test_fail_if_path_exists(
    "//PrimaryCmpNode",
    "//MulNode",
    "//ListNode//IntNode",
)
def in_mult_list():
    """
    >>> in_mult_list()
    False
    """
    return 5 in 100 * [1, 2] * 0


@cython.test_assert_path_exists(
    "//BoolNode",
)
@cython.test_fail_if_path_exists(
    "//PrimaryCmpNode",
    "//MulNode",
    "//ListNode//IntNode",
)
def not_in_mult_list():
    """
    >>> not_in_mult_list()
    True
    """
    return 5 not in 100 * [1, 2] * 0


@cython.test_assert_path_exists(
    "//BoolNode",
)
@cython.test_fail_if_path_exists(
    "//PrimaryCmpNode",
    "//MulNode",
    "//ListNode//IntNode",
)
def combined():
    """
    >>> combined()
    True
    """
    return 5 in 100 * [1, 2] * 0  or  5 not in 100 * [] * 10


@cython.test_assert_path_exists(
    '//IntNode[@base_10_value = "2"]',
    '//IntNode[@base_10_value = "4"]',
    '//IntNode[@base_10_value = "5"]',
    '//IntNode[@base_10_value = "7"]',
    '//BoolBinopNode//PrimaryCmpNode',
    '//BoolBinopNode[.//PrimaryCmpNode//IntNode[@base_10_value = "4"] and .//PrimaryCmpNode//IntNode[@base_10_value = "5"]]',
    '//PrimaryCmpNode[.//IntNode[@base_10_value = "2"] and .//IntNode[@base_10_value = "4"]]',
    '//PrimaryCmpNode[.//IntNode[@base_10_value = "5"] and .//IntNode[@base_10_value = "7"]]',
)
@cython.test_fail_if_path_exists(
    '//IntNode[@base_10_value = "1"]',
    '//IntNode[@base_10_value = "8"]',
    '//PrimaryCmpNode[.//IntNode[@base_10_value = "4"] and .//IntNode[@base_10_value = "5"]]',
    '//PrimaryCmpNode[.//IntNode[@base_10_value = "2"] and .//IntNode[@base_10_value = "7"]]',
    '//BoolNode',
)
def cascaded_cmp_with_partial_constants(a, b):
    """
    >>> cascaded_cmp_with_partial_constants(3, 6)
    True
    >>> cascaded_cmp_with_partial_constants(1, 6)
    False
    >>> cascaded_cmp_with_partial_constants(4, 6)
    False
    >>> cascaded_cmp_with_partial_constants(3, 7)
    False
    >>> cascaded_cmp_with_partial_constants(3, 6)
    True
    """
    return 1 < 2 < a < 4 < 5 < b < 7 < 8


@cython.test_assert_path_exists(
    '//IntNode[@base_10_value = "2"]',
    '//IntNode[@base_10_value = "4"]',
    '//IntNode[@base_10_value = "5"]',
    '//IntNode[@base_10_value = "7"]',
    '//BoolBinopNode',
    '//SingleAssignmentNode//BoolBinopNode',
    '//SingleAssignmentNode//BoolBinopNode//NameNode[@name = "a"]',
    '//SingleAssignmentNode//BoolBinopNode//NameNode[@name = "b"]',
    '//BoolBinopNode[.//PrimaryCmpNode//IntNode[@base_10_value = "4"] and .//PrimaryCmpNode//IntNode[@base_10_value = "5"]]',
    '//BoolNode[@value = False]',
)
@cython.test_fail_if_path_exists(
    '//SingleAssignmentNode//NameNode[@name = "c"]',
    '//IntNode[@base_10_value = "1"]',
    '//PrimaryCmpNode[.//IntNode[@base_10_value = "4"] and .//IntNode[@base_10_value = "5"]]',
    '//PrimaryCmpNode[.//IntNode[@base_10_value = "2"] and .//IntNode[@base_10_value = "7"]]',
    '//BoolNode[@value = True]',
)
def cascaded_cmp_with_partial_constants_and_false_end(a, b, c):
    """
    >>> cascaded_cmp_with_partial_constants_and_false_end(3, 6, 8)
    False
    >>> cascaded_cmp_with_partial_constants_and_false_end(1, 6, 8)
    False
    >>> cascaded_cmp_with_partial_constants_and_false_end(4, 6, 8)
    False
    >>> cascaded_cmp_with_partial_constants_and_false_end(3, 7, 8)
    False
    """
    x = 1 < 2 < a < 4 < 5 < b < 7 < 7 < c
    return x


@cython.test_assert_path_exists(
    '//PrimaryCmpNode',
    '//PrimaryCmpNode//IntNode',
    '//PrimaryCmpNode//IntNode[@base_10_value = "0"]',
    '//PrimaryCmpNode//IntNode[@base_10_value = "4294967296"]',
)
@cython.test_fail_if_path_exists(
    '//PrimaryCmpNode//IntBinopNode',
    '//PrimaryCmpNode//IntNode[@base_10_value = "1"]',
    '//PrimaryCmpNode//IntNode[@base_10_value = "32"]',
)
def const_in_binop(v):
    """
    >>> const_in_binop(-1)
    1
    >>> const_in_binop(0)
    0
    >>> const_in_binop(1 << 32)
    1
    >>> const_in_binop(1 << 32 - 1)
    0
    """
    if v < 0 or v >= (1 << 32):
        return 1
    else:
        return 0
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/constant_folding_cy.pyx0000644000175100001770000000444400000000000022340 0ustar00runnerdocker00000000000000# coding=utf8
# mode: run
# tag: constant_folding

cimport cython


bstring = b'abc\xE9def'
ustring = u'abc\xE9def'
surrogates_ustring = u'abc\U00010000def'


@cython.test_fail_if_path_exists(
    "//SliceIndexNode",
    )
def bytes_slicing2():
    """
    >>> a,b,c,d = bytes_slicing2()
    >>> a == bstring[:]
    True
    >>> b == bstring[2:]
    True
    >>> c == bstring[:4]
    True
    >>> d == bstring[2:4]
    True
    """
    str0 = b'abc\xE9def'[:]
    str1 = b'abc\xE9def'[2:]
    str2 = b'abc\xE9def'[:4]
    str3 = b'abc\xE9def'[2:4]

    return str0, str1, str2, str3


@cython.test_fail_if_path_exists(
    "//SliceIndexNode",
    )
def unicode_slicing2():
    """
    >>> a,b,c,d = unicode_slicing2()
    >>> a == ustring[:]
    True
    >>> b == ustring[2:]
    True
    >>> c == ustring[:4]
    True
    >>> d == ustring[2:4]
    True
    """
    str0 = u'abc\xE9def'[:]
    str1 = u'abc\xE9def'[2:]
    str2 = u'abc\xE9def'[:4]
    str3 = u'abc\xE9def'[2:4]

    return str0, str1, str2, str3


@cython.test_assert_path_exists(
    "//SliceIndexNode",
    )
def unicode_slicing_unsafe_surrogates2():
    """
    >>> unicode_slicing_unsafe_surrogates2() == surrogates_ustring[2:]
    True
    """
    ustring = u'abc\U00010000def'[2:]
    return ustring


@cython.test_fail_if_path_exists(
    "//SliceIndexNode",
    )
def unicode_slicing_safe_surrogates2():
    """
    >>> unicode_slicing_safe_surrogates2() == surrogates_ustring[:2]
    True
    >>> print(unicode_slicing_safe_surrogates2())
    ab
    """
    ustring = u'abc\U00010000def'[:2]
    return ustring


@cython.test_fail_if_path_exists(
    "//ComprehensionNode",
    "//ForInStatNode",
)
@cython.test_assert_path_exists(
    "//SetNode",
)
def for_in_empty_setcomp():
    """
    >>> s = for_in_empty_setcomp()
    >>> isinstance(s, set)
    True
    >>> len(s)
    0
    """
    return {i for i in []}


@cython.test_fail_if_path_exists(
    "//ReturnStatNode//AddNode",
)
@cython.test_assert_path_exists(
    "//ListNode//AddNode",
)
def add_strings():
    """
    >>> u, b, rest = add_strings()
    >>> u == 'abcdef' or u
    True
    >>> b == b'abcdef' or b
    True
    >>> rest
    1
    """
    a = ["abc" + "def"]  # not currently optimised
    # FIXME: test encodings and unicode escapes
    return u"abc" + u"def", b"abc" + b"def", a[0] and 1
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/constants.pyx0000644000175100001770000001476000000000000020330 0ustar00runnerdocker00000000000000import sys
IS_PY3 = sys.version_info[0] >= 3

cimport cython

DEF INT_VAL = 1

def _func(a,b,c):
    return a+b+c

@cython.test_fail_if_path_exists("//AddNode")
def add():
    """
    >>> add() == 1+2+3+4
    True
    """
    return 1+2+3+4

#@cython.test_fail_if_path_exists("//AddNode")
def add_var(a):
    """
    >>> add_var(10) == 1+2+10+3+4
    True
    """
    return 1+2 +a+ 3+4

@cython.test_fail_if_path_exists("//AddNode", "//SubNode")
def neg():
    """
    >>> neg() == -1 -2 - (-3+4)
    True
    """
    return -1 -2 - (-3+4)

@cython.test_fail_if_path_exists("//AddNode", "//MulNode", "//DivNode")
def long_int_mix():
    """
    >>> long_int_mix() == 1 + (2 * 3) // 2
    True
    >>> if IS_PY3: type(long_int_mix()) is int  or type(long_int_mix())
    ... else:      type(long_int_mix()) is long or type(long_int_mix())
    True
    """
    return 1L + (2 * 3L) // 2

@cython.test_fail_if_path_exists("//AddNode", "//MulNode", "//DivNode")
def char_int_mix():
    """
    >>> char_int_mix() == 1 + (ord(' ') * 3) // 2 + ord('A')
    True
    """
    return 1L + (c' ' * 3L) // 2 + c'A'

@cython.test_fail_if_path_exists("//AddNode", "//MulNode")
def int_cast():
    """
    >>> int_cast() == 1 + 2 * 6000
    True
    """
    return (1 + 2 * 6000)

@cython.test_fail_if_path_exists("//MulNode")
def mul():
    """
    >>> mul() == 1*60*1000
    True
    """
    return 1*60*1000

@cython.test_fail_if_path_exists("//AddNode", "//MulNode")
def arithm():
    """
    >>> arithm() == 9*2+3*8//6-10
    True
    """
    return 9*2+3*8//6-10

@cython.test_fail_if_path_exists("//AddNode", "//MulNode")
def parameters():
    """
    >>> parameters() == _func(-1 -2, - (-3+4), 1*2*3)
    True
    """
    return _func(-1 -2, - (-3+4), 1*2*3)

#@cython.test_fail_if_path_exists("//AddNode")
def lists():
    """
    >>> lists() == [1,2,3] + [4,5,6]
    True
    """
    return [1,2,3] + [4,5,6]

@cython.test_fail_if_path_exists("//MulNode")
def multiplied_lists_right_len1():
    """
    >>> multiplied_lists_right_len1() == [1] * 5
    True
    """
    return [1] * 5

@cython.test_fail_if_path_exists("//MulNode")
def multiplied_lists_right():
    """
    >>> multiplied_lists_right() == [1,2,3] * 5
    True
    """
    return [1,2,3] * 5

@cython.test_fail_if_path_exists("//MulNode")
def multiplied_lists_left():
    """
    >>> multiplied_lists_left() == [1,2,3] * 5
    True
    """
    return 5 * [1,2,3]

@cython.test_fail_if_path_exists("//MulNode")
def multiplied_lists_neg():
    """
    >>> multiplied_lists_neg() == [1,2,3] * -5
    True
    """
    return [1,2,3] * -5

@cython.test_fail_if_path_exists("//MulNode")
def multiplied_lists_nonconst(x):
    """
    >>> multiplied_lists_nonconst(5) == [1,2,3] * 5
    True
    >>> multiplied_lists_nonconst(-5) == [1,2,3] * -5
    True
    >>> multiplied_lists_nonconst(0) == [1,2,3] * 0
    True

    >>> try: [1,2,3] * 'abc'
    ... except TypeError: pass
    >>> try: multiplied_nonconst_tuple_arg('abc')
    ... except TypeError: pass
    >>> try: [1,2,3] * 1.0
    ... except TypeError: pass
    >>> try: multiplied_nonconst_tuple_arg(1.0)
    ... except TypeError: pass
    """
    return [1,2,3] * x

@cython.test_assert_path_exists("//MulNode")
def multiplied_lists_nonconst_left(x):
    """
    >>> multiplied_lists_nonconst_left(5) == 5 * [1,2,3]
    True
    >>> multiplied_lists_nonconst_left(-5) == -5 * [1,2,3]
    True
    >>> multiplied_lists_nonconst_left(0) == 0 * [1,2,3]
    True
    """
    return x * [1,2,3]


@cython.test_fail_if_path_exists("//MulNode")
def multiplied_nonconst_list_const_int(x):
    """
    >>> multiplied_nonconst_list_const_int(2)
    [1, 2, 3, 1, 2, 3]
    """
    return [1,x,3] * 2


@cython.test_fail_if_path_exists("//MulNode//ListNode")
def multiplied_lists_nonconst_expression(x):
    """
    >>> multiplied_lists_nonconst_expression(5) == [1,2,3] * (5 * 2)
    True
    >>> multiplied_lists_nonconst_expression(-5) == [1,2,3] * (-5 * 2)
    True
    >>> multiplied_lists_nonconst_expression(0) == [1,2,3] * (0 * 2)
    True
    """
    return [1,2,3] * (x*2)

cdef side_effect(int x):
    print x
    return x

@cython.test_fail_if_path_exists("//MulNode")
def multiplied_lists_with_side_effects():
    """
    >>> multiplied_lists_with_side_effects() == [1,2,3] * 5
    1
    2
    3
    True
    """
    return [side_effect(1), side_effect(2), side_effect(3)] * 5

@cython.test_fail_if_path_exists("//MulNode")
def multiplied_lists_nonconst_with_side_effects(x):
    """
    >>> multiplied_lists_nonconst_with_side_effects(5) == [1,2,3] * 5
    1
    2
    3
    True
    """
    return [side_effect(1), side_effect(2), side_effect(3)] * x

@cython.test_fail_if_path_exists("//MulNode")
def multiplied_nonconst_tuple_arg(x):
    """
    >>> multiplied_nonconst_tuple_arg(5) == (1,2) * 5
    True
    >>> multiplied_nonconst_tuple_arg(-5) == (1,2) * -5
    True
    >>> multiplied_nonconst_tuple_arg(0) == (1,2) * 0
    True

    >>> try: (1,2) * 'abc'
    ... except TypeError: pass
    >>> try: multiplied_nonconst_tuple_arg('abc')
    ... except TypeError: pass
    >>> try: (1,2) * 1.0
    ... except TypeError: pass
    >>> try: multiplied_nonconst_tuple_arg(1.0)
    ... except TypeError: pass
    """
    return (1,2) * x

@cython.test_fail_if_path_exists("//MulNode")
def multiplied_nonconst_tuple_int_arg(int x):
    """
    >>> multiplied_nonconst_tuple_int_arg(5) == (1,2) * 5
    True
    """
    return (1,2) * x

@cython.test_fail_if_path_exists("//MulNode")
def multiplied_nonconst_tuple(x):
    """
    >>> multiplied_nonconst_tuple(5) == (1,2) * (5+1)
    True
    """
    return (1,2) * (x + 1)

MULT = 5

@cython.test_fail_if_path_exists("//MulNode")
def multiplied_global_nonconst_tuple():
    """
    >>> multiplied_global_nonconst_tuple() == (1,2,3) * 5
    1
    2
    3
    True
    """
    return (side_effect(1), side_effect(2), side_effect(3)) * MULT

@cython.test_fail_if_path_exists("//MulNode")
def multiplied_const_tuple():
    """
    >>> multiplied_const_tuple() == (1,2) * 5
    True
    """
    return (1,2) * 5

@cython.test_fail_if_path_exists("//MulNode")
def multiplied_const_tuple_len1():
    """
    >>> multiplied_const_tuple_len1() == (1,) * 5
    True
    """
    return (1,) * 5

@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def compile_time_DEF():
    """
    >>> compile_time_DEF()
    (1, False, True, True, False)
    """
    return INT_VAL, INT_VAL == 0, INT_VAL != 0, INT_VAL == 1, INT_VAL != 1

@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def cascaded_compare():
    """
    >>> cascaded_compare()
    True
    """
    return 1 < 2 < 3 < 4
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/contains_T455.pyx0000644000175100001770000000370200000000000020645 0ustar00runnerdocker00000000000000# ticket: t455

def in_sequence(x, seq):
    """
    >>> in_sequence(1, [])
    False
    >>> in_sequence(1, ())
    False
    >>> in_sequence(1, {})
    False
    >>> in_sequence(1, [1])
    True
    >>> in_sequence(1, (1,))
    True
    >>> in_sequence(1, {1:None})
    True

    >>> in_sequence(1, None)    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...iterable...

    >>> in_sequence(1, 1)       # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...iterable...
    """
    return x in seq

def not_in_sequence(x, seq):
    """
    >>> not_in_sequence(1, [])
    True
    >>> not_in_sequence(1, ())
    True
    >>> not_in_sequence(1, {})
    True
    >>> not_in_sequence(1, [1])
    False
    >>> not_in_sequence(1, (1,))
    False
    >>> not_in_sequence(1, {1:None})
    False

    >>> not_in_sequence(1, None)    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...iterable...

    >>> not_in_sequence(1, 1)       # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...iterable...
    """
    return x not in seq


def in_dict(k, dict dct):
    """
    >>> in_dict(1, {})
    False
    >>> in_dict(1, {1:None})
    True

    >>> in_dict(1, None)
    Traceback (most recent call last):
    ...
    TypeError: 'NoneType' object is not iterable
    """
    return k in dct

def not_in_dict(k, dict dct):
    """
    >>> not_in_dict(1, {})
    True
    >>> not_in_dict(1, {1:None})
    False

    >>> not_in_dict(1, None)
    Traceback (most recent call last):
    ...
    TypeError: 'NoneType' object is not iterable
    """
    return k not in dct

def cascaded(a, b, c):
    """
    >>> cascaded(1, 2, 3)    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: ...iterable...
    >>> cascaded(-1, (1,2), (1,3))
    True
    >>> cascaded(1, (1,2), (1,3))
    False
    >>> cascaded(-1, (1,2), (1,0))
    False
    """
    return a not in b < c
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/control_flow_except_T725.pyx0000644000175100001770000000044300000000000023105 0ustar00runnerdocker00000000000000def unused_except_capture():
    """
    >>> unused_except_capture()
    """
    try:
        try:
            raise ValueError
        except TypeError, s:
            raise TypeError
        except ValueError, s:
            raise ValueError # segfault
    except ValueError:
        pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/control_flow_loop.pyx0000644000175100001770000000207400000000000022047 0ustar00runnerdocker00000000000000# mode: run
# tag: forin, control-flow, werror

def for_in_break(LL, p=bool):
    """
    >>> for_in_break([[1,2,3], [4,5,6]])
    True
    >>> for_in_break([[1,2,3], [4,5,0]])
    False
    >>> for_in_break([[1,2,3], [0,4,5]])
    False
    >>> for_in_break([[1,2,3], [0,4,5], [6,7,8]])
    False

    >>> def collect(x):
    ...     v.append(x)
    ...     return x

    >>> v = []
    >>> for_in_break([[1,2,3], [4,5,6]], p=collect)
    True
    >>> v
    [1, 2, 3, 4, 5, 6]

    >>> v = []
    >>> for_in_break([[1,2,3], [4,5,0]], p=collect)
    False
    >>> v
    [1, 2, 3, 4, 5, 0]

    >>> v = []
    >>> for_in_break([[1,2,3], [0,4,5]], p=collect)
    False
    >>> v
    [1, 2, 3, 0]

    >>> v = []
    >>> for_in_break([[1,2,3], [0,4,5], [6,7,8]], p=collect)
    False
    >>> v
    [1, 2, 3, 0]
    """
    result = 'NOK'
    # implements the builtin all()
    for L in LL:
        for x in L:
            if not p(x):
                result = False
                break
        else:
            continue
        break
    else:
        result = True
    return result
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/control_flow_stack_allocation.pyx0000644000175100001770000000143000000000000024403 0ustar00runnerdocker00000000000000# mode: run
# tag: werror, control-flow
# cython: warn.unused=True, warn.unused_arg=True, warn.unused_result=True

cdef struct S:
    int x
    float y


cdef stack_alloc_test(int[2] array_arg, S struct_arg):
    cdef int[2] array_var
    cdef S struct_var, struct_var_by_value

    for i in range(2):
        array_var[i] = array_arg[i]
    struct_var.x, struct_var.y = struct_arg.x, struct_arg.y
    struct_var_by_value = struct_var

    return [ i for i in array_var ], struct_var_by_value


def test():
    """
    >>> a,d = test()
    >>> a
    [0, 1]
    >>> sorted(d.items())
    [('x', 1), ('y', 2.0)]
    """
    cdef int[2] array_var
    cdef S struct_var
    for i in range(2):
        array_var[i] = i
    struct_var = [1, 2.0]

    return stack_alloc_test(array_var, struct_var)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/coroutines.py0000644000175100001770000000253700000000000020315 0ustar00runnerdocker00000000000000# cython: language_level=3
# mode: run
# tag: pep492, pure3.5, gh1462, async, await


async def test_coroutine_frame(awaitable):
    """
    >>> class Awaitable(object):
    ...     def __await__(self):
    ...         return iter([2])

    >>> coro = test_coroutine_frame(Awaitable())
    >>> import types
    >>> isinstance(coro.cr_frame, types.FrameType) or coro.cr_frame
    True
    >>> coro.cr_frame is coro.cr_frame  # assert that it's cached
    True
    >>> coro.cr_frame.f_code is not None
    True
    >>> code_obj = coro.cr_frame.f_code
    >>> code_obj.co_argcount
    1
    >>> code_obj.co_varnames
    ('awaitable', 'b')

    >>> next(coro.__await__())  # avoid "not awaited" warning
    2
    """
    b = await awaitable
    return b


# gh1462: Using decorators on coroutines.

def pass_through(func):
    return func


@pass_through
async def test_pass_through():
    """
    >>> t = test_pass_through()
    >>> try: t.send(None)
    ... except StopIteration as ex:
    ...     print(ex.args[0] if ex.args else None)
    ... else: print("NOT STOPPED!")
    None
    """


@pass_through(pass_through)
async def test_pass_through_with_args():
    """
    >>> t = test_pass_through_with_args()
    >>> try: t.send(None)
    ... except StopIteration as ex:
    ...     print(ex.args[0] if ex.args else None)
    ... else: print("NOT STOPPED!")
    None
    """
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/coverage_api.srctree0000644000175100001770000001262600000000000021566 0ustar00runnerdocker00000000000000# mode: run
# tag: coverage,trace

"""
PYTHON -c "import shutil; shutil.copy('pkg/coverage_test_pyx.pyx', 'pkg/coverage_test_pyx.pxi')"
PYTHON setup.py build_ext -i
PYTHON coverage_test.py
"""

######## setup.py ########

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize([
    'coverage_test_*.py*',
    'pkg/coverage_test_*.py*',
    'Package2/CoverageTest_*.py*'
]))


######## .coveragerc ########
[run]
plugins = Cython.Coverage


######## pkg/__init__.py ########

######## pkg/coverage_test_py.py ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1

def func1(a, b):
    x = 1               #  5
    c = func2(a) + b    #  6
    return x + c        #  7


def func2(a):
    return a * 2        # 11


######## pkg/coverage_test_pyx.pyx ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1

def func1(int a, int b):
    cdef int x = 1      #  5
    c = func2(a) + b    #  6
    return x + c        #  7


def func2(int a):
    return a * 2        # 11


######## coverage_test_include_pyx.pyx ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1

cdef int x = 5                                   #  4

cdef int cfunc1(int x):                          #  6
    return x * 3                                 #  7

include "pkg/coverage_test_pyx.pxi"              #  9

def main_func(int x):                            # 11
    return cfunc1(x) + func1(x, 4) + func2(x)    # 12


######## Package2/__init__.py ########
# Add MixedCase package and filenames to test if the files are found

######## Package2/CoverageTest_py.py ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1

def func1(a, b):
    x = 1               #  5
    c = func2(a) + b    #  6
    return x + c        #  7


def func2(a):
    return a * 2        # 11


######## Package2/CoverageTest_pyx.pyx ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1

def func1(int a, int b):
    cdef int x = 1      #  5
    c = func2(a) + b    #  6
    return x + c        #  7


def func2(int a):
    return a * 2        # 11


######## coverage_test_include_pyx.pyx ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1

cdef int x = 5                                   #  4

cdef int cfunc1(int x):                          #  6
    return x * 3                                 #  7

include "pkg/coverage_test_pyx.pxi"              #  9

def main_func(int x):                            # 11
    return cfunc1(x) + func1(x, 4) + func2(x)    # 12


######## coverage_test.py ########

import re
import os.path
try:
    # io.StringIO in Py2.x cannot handle str ...
    from StringIO import StringIO
except ImportError:
    from io import StringIO

from coverage import coverage

from pkg import coverage_test_py
from pkg import coverage_test_pyx
import coverage_test_include_pyx

# test the MixedCase Files and packages
from Package2 import CoverageTest_py
from Package2 import CoverageTest_pyx

for module in [coverage_test_py, coverage_test_pyx, coverage_test_include_pyx,
               CoverageTest_py, CoverageTest_pyx]:
    assert not any(module.__file__.endswith(ext) for ext in '.py .pyc .pyo .pyw .pyx .pxi'.split()), \
        module.__file__


def source_file_for(module):
    module_name = module.__name__
    path, ext = os.path.splitext(module.__file__)
    if ext == '.so':
        # Linux/Unix/Mac extension module
        platform_suffix = re.search(r'[.](?:cpython|pypy)-[0-9]+[-_a-z0-9]*$', path, re.I)
        if platform_suffix:
            path = path[:platform_suffix.start()]
    elif ext == '.pyd':
        # Windows extension module
        platform_suffix = re.search(r'[.]cp[0-9]+-win[_a-z0-9]*$', path, re.I)
        if platform_suffix:
            path = path[:platform_suffix.start()]
    source_filepath = path + '.' + module_name.rsplit('_', 1)[-1]
    return source_filepath


def run_coverage(module):
    module_name = module.__name__
    module_path = module_name.replace('.', os.path.sep) + '.' + module_name.rsplit('_', 1)[-1]

    cov = coverage()
    cov.start()
    assert module.func1(1, 2) == (1 * 2) + 2 + 1
    assert module.func2(2) == 2 * 2
    if '_include_' in module_name:
        assert module.main_func(2) == (2 * 3) + ((2 * 2) + 4 + 1) + (2 * 2)
    cov.stop()

    out = StringIO()
    cov.report(file=out)
    #cov.report([module], file=out)
    lines = out.getvalue().splitlines()
    assert any(module_path in line for line in lines), "'%s' not found in coverage report:\n\n%s" % (
        module_path, out.getvalue())

    mod_file, exec_lines, excl_lines, missing_lines, _ = cov.analysis2(source_file_for(module))
    assert module_path in mod_file

    if '_include_' in module_name:
        executed = set(exec_lines) - set(missing_lines)
        assert all(line in executed for line in [7, 12]), '%s / %s' % (exec_lines, missing_lines)

        # rest of test if for include file
        mod_file, exec_lines, excl_lines, missing_lines, _ = cov.analysis2(
            os.path.join(os.path.dirname(module.__file__), "pkg", "coverage_test_pyx.pxi"))

    executed = set(exec_lines) - set(missing_lines)
    assert all(line in executed for line in [5, 6, 7, 11]), '%s / %s' % (exec_lines, missing_lines)


if __name__ == '__main__':
    run_coverage(coverage_test_py)
    run_coverage(coverage_test_pyx)
    run_coverage(coverage_test_include_pyx)
    run_coverage(CoverageTest_py)
    run_coverage(CoverageTest_pyx)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/coverage_cmd.srctree0000644000175100001770000001707500000000000021563 0ustar00runnerdocker00000000000000# mode: run
# tag: coverage,trace

"""
PYTHON -c "import shutil; shutil.copy('pkg/coverage_test_pyx.pyx', 'pkg/coverage_test_pyx.pxi')"
PYTHON setup.py build_ext -i
PYTHON -m coverage run coverage_test.py
PYTHON collect_coverage.py
"""

######## setup.py ########

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize([
    'coverage_test_*.py*',
    'pkg/coverage_test_*.py*'
]))


######## .coveragerc ########
[run]
plugins = Cython.Coverage


######## pkg/__init__.py ########

######## pkg/coverage_test_py.py ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1
import cython


def func1(a, b):
    x = 1               #  7
    c = func2(a) + b    #  8
    return x + c        #  9


def func2(a):
    return a * 2        # 13


def func3(a):
    x = 1               # 17
    a *= 2              #     # pragma: no cover
    a += x              #
    return a * 42       # 20  # pragma: no cover


@cython.cclass
class A:
    def meth(self):
        return 1        # 26


######## pkg/coverage_test_pyx.pyx ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1



def func1(int a, int b):
    cdef int x = 1      #  7
    c = func2(a) + b    #  8
    return x + c        #  9


def func2(int a):
    return a * 2        # 13


def func3(int a):
    cdef int x = 1      # 17
    a *= 2              #     # pragma: no cover
    a += x              #
    return a * 42       # 20  # pragma: no cover



cdef class A:
    def meth(self):
        return 1        # 26


######## coverage_test_include_pyx.pyx ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1

cdef int x = 5                                   #  4

cdef int cfunc1(int x):                          #  6
    return x * 3                                 #  7

include "pkg/coverage_test_pyx.pxi"              #  9

def main_func(int x):                            # 11
    return cfunc1(x) + func1(x, 4) + func2(x)    # 12


######## coverage_test.py ########

import os.path
try:
    # io.StringIO in Py2.x cannot handle str ...
    from StringIO import StringIO
except ImportError:
    from io import StringIO

from pkg import coverage_test_py
from pkg import coverage_test_pyx
import coverage_test_include_pyx


for module in [coverage_test_py, coverage_test_pyx, coverage_test_include_pyx]:
    assert not any(module.__file__.endswith(ext) for ext in '.py .pyc .pyo .pyw .pyx .pxi'.split()), \
        module.__file__


def run_coverage(module):
    module_name = module.__name__
    module_path = module_name.replace('.', os.path.sep) + '.' + module_name.rsplit('_', 1)[-1]

    assert module.func1(1, 2) == (1 * 2) + 2 + 1
    assert module.func2(2) == 2 * 2
    if '_include_' in module_name:
        assert module.main_func(2) == (2 * 3) + ((2 * 2) + 4 + 1) + (2 * 2)
    assert module.A().meth() == 1




if __name__ == '__main__':
    run_coverage(coverage_test_py)
    run_coverage(coverage_test_pyx)
    run_coverage(coverage_test_include_pyx)


######## collect_coverage.py ########

import re
import sys
import os
import os.path
import subprocess
from glob import iglob


def run_coverage_command(*command):
    env = dict(os.environ, LANG='', LC_ALL='C')
    process = subprocess.Popen(
        [sys.executable, '-m', 'coverage'] + list(command),
        stdout=subprocess.PIPE, env=env)
    stdout, _ = process.communicate()
    return stdout


def run_report():
    stdout = run_coverage_command('report', '--show-missing')
    stdout = stdout.decode('iso8859-1')  # 'safe' decoding
    lines = stdout.splitlines()
    print(stdout)

    # FIXME:  'coverage_test_pyx.pxi' may not be found if coverage.py requests it before the .pyx file
    for module_path in ('coverage_test_py.py', 'coverage_test_pyx.pyx', 'coverage_test_include_pyx.pyx'):
        assert any(module_path in line for line in lines), "'%s' not found in coverage report:\n\n%s" % (
            module_path, stdout)

    files = {}
    line_iter = iter(lines)
    for line in line_iter:
        if line.startswith('---'):
            break
    extend = [''] * 2
    for line in line_iter:
        if not line or line.startswith('---'):
            continue
        name, statements, missed, covered, _missing = (line.split(None, 4) + extend)[:5]
        missing = []
        for start, end in re.findall('([0-9]+)(?:-([0-9]+))?', _missing):
            if end:
                missing.extend(range(int(start), int(end)+1))
            else:
                missing.append(int(start))
        files[os.path.basename(name)] = (statements, missed, covered, missing)

    report = files['coverage_test_pyx.pyx']
    assert  7 not in report[-1], report
    assert 12 not in report[-1], report


def run_xml_report():
    stdout = run_coverage_command('xml', '-o', '-')
    print(stdout)

    import xml.etree.ElementTree as etree
    data = etree.fromstring(stdout)

    files = {}
    for module in data.iterfind('.//class'):
        files[module.get('filename').replace('\\', '/')] = dict(
            (int(line.get('number')), int(line.get('hits')))
            for line in module.findall('lines/line')
        )

    report = files['pkg/coverage_test_pyx.pyx']
    assert report[7] > 0, report
    assert report[8] > 0, report
    assert report[9] > 0, report
    assert report[26] > 0, report


def run_json_report():
    import coverage
    if coverage.version_info < (5, 0):
        # JSON output comes in coverage 5.0
        return

    stdout = run_coverage_command('json', '-o', '-')

    import json
    files = json.loads(stdout.decode("ascii"))['files']

    for filename in [
        'pkg/coverage_test_py.py',
        'pkg/coverage_test_pyx.pyx',
    ]:
        report = files[filename.replace('/', os.sep)]
        summary = report['summary']
        assert summary['missing_lines'] == 2, summary
        assert summary['excluded_lines'] == 2, summary
        assert report['missing_lines'] == [17, 19], report
        assert report['excluded_lines'] == [18, 20], report

        assert not frozenset(
            report['missing_lines'] + report['excluded_lines']
        ).intersection(report['executed_lines'])


def run_html_report():
    from collections import defaultdict

    stdout = run_coverage_command('html', '-d', 'html')
    # coverage 6.1+ changed the order of the attributes => need to parse them separately
    _parse_id = re.compile(r'id=["\'][^0-9"\']*(?P[0-9]+)[^0-9"\']*["\']').search
    _parse_state = re.compile(r'class=["\'][^"\']*(?Pmis|run|exc)[^"\']*["\']').search

    files = {}
    for file_path in iglob('html/*.html'):
        with open(file_path) as f:
            page = f.read()
        report = defaultdict(set)
        for line in re.split(r'id=["\']source["\']', page)[-1].splitlines():
            lineno = _parse_id(line)
            state = _parse_state(line)
            if not lineno or not state:
                continue
            report[state.group('state')].add(int(lineno.group('id')))
        files[file_path] = report

    for filename, report in files.items():
        if "coverage_test_pyx" not in filename:
            continue
        executed = report["run"]
        missing = report["mis"]
        excluded = report["exc"]
        assert executed, (filename, report)
        assert 7 in executed, executed
        assert 8 in executed, executed
        assert 9 in executed, executed
        assert 26 in executed, executed
        assert 17 in missing, missing
        assert 18 in excluded, excluded
        assert 19 in missing, missing
        assert 20 in excluded, excluded


if __name__ == '__main__':
    run_report()
    run_xml_report()
    run_json_report()
    run_html_report()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/coverage_cmd_src_layout.srctree0000644000175100001770000001104100000000000024012 0ustar00runnerdocker00000000000000# mode: run
# tag: coverage,trace

"""
PYTHON setup.py build_ext -i
PYTHON -m coverage run --source=src coverage_test.py
PYTHON collect_coverage.py
"""

######## setup.py ########

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize([
    'src/trivial_module.pyx',
]))


######## .coveragerc ########
[run]
plugins = Cython.Coverage


######## src/trivial_module.pyx ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1

def func1(int a, int b):
    cdef int x = 1      #  5
    c = func2(a) + b    #  6
    return x + c        #  7


def func2(int a):
    return a * 2        # 11


######## coverage_test.py ########

import os.path
import trivial_module


assert not any(
    trivial_module.__file__.endswith(ext)
    for ext in '.py .pyc .pyo .pyw .pyx .pxi'.split()
), module.__file__


def run_coverage(module):
    assert module.func1(1, 2) == (1 * 2) + 2 + 1
    assert module.func2(2) == 2 * 2


if __name__ == '__main__':
    run_coverage(trivial_module)


######## collect_coverage.py ########

import re
import sys
import os
import os.path
import subprocess
from glob import iglob


def run_coverage_command(*command):
    env = dict(os.environ, LANG='', LC_ALL='C')
    process = subprocess.Popen(
        [sys.executable, '-m', 'coverage'] + list(command),
        stdout=subprocess.PIPE, env=env)
    stdout, _ = process.communicate()
    return stdout


def run_report():
    stdout = run_coverage_command('report', '--show-missing')
    stdout = stdout.decode('iso8859-1')  # 'safe' decoding
    lines = stdout.splitlines()
    print(stdout)

    module_path = 'trivial_module.pyx'
    assert any(module_path in line for line in lines), (
        "'%s' not found in coverage report:\n\n%s" % (module_path, stdout))

    files = {}
    line_iter = iter(lines)
    for line in line_iter:
        if line.startswith('---'):
            break
    extend = [''] * 2
    for line in line_iter:
        if not line or line.startswith('---'):
            continue
        name, statements, missed, covered, _missing = (line.split(None, 4) + extend)[:5]
        missing = []
        for start, end in re.findall('([0-9]+)(?:-([0-9]+))?', _missing):
            if end:
                missing.extend(range(int(start), int(end)+1))
            else:
                missing.append(int(start))
        files[os.path.basename(name)] = (statements, missed, covered, missing)

    assert  5 not in files[module_path][-1], files[module_path]
    assert  6 not in files[module_path][-1], files[module_path]
    assert  7 not in files[module_path][-1], files[module_path]
    assert 11 not in files[module_path][-1], files[module_path]


def run_xml_report():
    stdout = run_coverage_command('xml', '-o', '-')
    print(stdout)

    import xml.etree.ElementTree as etree
    data = etree.fromstring(stdout)

    files = {}
    for module in data.iterfind('.//class'):
        files[module.get('filename').replace('\\', '/')] = dict(
            (int(line.get('number')), int(line.get('hits')))
            for line in module.findall('lines/line')
        )

    module_path = 'src/trivial_module.pyx'

    assert files[module_path][5] > 0, files[module_path]
    assert files[module_path][6] > 0, files[module_path]
    assert files[module_path][7] > 0, files[module_path]
    assert files[module_path][11] > 0, files[module_path]


def run_html_report():
    from collections import defaultdict

    stdout = run_coverage_command('html', '-d', 'html')
    # coverage 6.1+ changed the order of the attributes => need to parse them separately
    _parse_id = re.compile(r'id=["\'][^0-9"\']*(?P[0-9]+)[^0-9"\']*["\']').search
    _parse_state = re.compile(r'class=["\'][^"\']*(?Pmis|run|exc)[^"\']*["\']').search

    files = {}
    for file_path in iglob('html/*.html'):
        with open(file_path) as f:
            page = f.read()
        report = defaultdict(set)
        for line in re.split(r'id=["\']source["\']', page)[-1].splitlines():
            lineno = _parse_id(line)
            state = _parse_state(line)
            if not lineno or not state:
                continue
            report[state.group('state')].add(int(lineno.group('id')))
        files[file_path] = (report['run'], report['mis'])

    executed, missing = [data for path, data in files.items() if 'trivial_module' in path][0]
    assert executed
    assert 5 in executed, executed
    assert 6 in executed, executed
    assert 7 in executed, executed
    assert 11 in executed, executed


if __name__ == '__main__':
    run_report()
    run_xml_report()
    run_html_report()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/coverage_cmd_src_pkg_layout.srctree0000644000175100001770000001151500000000000024661 0ustar00runnerdocker00000000000000# mode: run
# tag: coverage,trace

"""
PYTHON -m pip install .
PYTHON setup.py build_ext --inplace
PYTHON -m coverage run --source=pkg coverage_test.py
PYTHON collect_coverage.py
"""

######## setup.py ########

from setuptools import Extension, find_packages, setup
from Cython.Build import cythonize

MODULES = [
        Extension("pkg.module1", ["src/pkg/module1.pyx"]),
        ]

setup(
    name="pkg",
    zip_safe=False,
    packages=find_packages('src'),
    package_data={'pkg': ['*.pxd', '*.pyx']},
    package_dir={'': 'src'},
    ext_modules= cythonize(MODULES)
    )


######## .coveragerc ########
[run]
plugins = Cython.Coverage

######## src/pkg/__init__.py ########

######## src/pkg/module1.pyx ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1

def func1(int a, int b):
    cdef int x = 1      #  5
    c = func2(a) + b    #  6
    return x + c        #  7


def func2(int a):
    return a * 2       # 11

######## coverage_test.py ########

import os.path
from pkg import module1


assert not any(
    module1.__file__.endswith(ext)
    for ext in '.py .pyc .pyo .pyw .pyx .pxi'.split()
), module.__file__


def run_coverage(module):
    assert module.func1(1, 2) == (1 * 2) + 2 + 1
    assert module.func2(2) == 2 * 2


if __name__ == '__main__':
    run_coverage(module1)


######## collect_coverage.py ########

import re
import sys
import os
import os.path
import subprocess
from glob import iglob


def run_coverage_command(*command):
    env = dict(os.environ, LANG='', LC_ALL='C')
    process = subprocess.Popen(
        [sys.executable, '-m', 'coverage'] + list(command),
        stdout=subprocess.PIPE, env=env)
    stdout, _ = process.communicate()
    return stdout


def run_report():
    stdout = run_coverage_command('report', '--show-missing')
    stdout = stdout.decode('iso8859-1')  # 'safe' decoding
    lines = stdout.splitlines()
    print(stdout)

    module_path = 'module1.pyx'
    assert any(module_path in line for line in lines), (
        "'%s' not found in coverage report:\n\n%s" % (module_path, stdout))

    files = {}
    line_iter = iter(lines)
    for line in line_iter:
        if line.startswith('---'):
            break
    extend = [''] * 2
    for line in line_iter:
        if not line or line.startswith('---'):
            continue
        name, statements, missed, covered, _missing = (line.split(None, 4) + extend)[:5]
        missing = []
        for start, end in re.findall('([0-9]+)(?:-([0-9]+))?', _missing):
            if end:
                missing.extend(range(int(start), int(end)+1))
            else:
                missing.append(int(start))
        files[os.path.basename(name)] = (statements, missed, covered, missing)
    assert  5 not in files[module_path][-1], files[module_path]
    assert  6 not in files[module_path][-1], files[module_path]
    assert  7 not in files[module_path][-1], files[module_path]
    assert 11 not in files[module_path][-1], files[module_path]


def run_xml_report():
    stdout = run_coverage_command('xml', '-o', '-')
    print(stdout)

    import xml.etree.ElementTree as etree
    data = etree.fromstring(stdout)

    files = {}
    for module in data.iterfind('.//class'):
        files[module.get('filename').replace('\\', '/')] = dict(
            (int(line.get('number')), int(line.get('hits')))
            for line in module.findall('lines/line')
        )

    module_path = 'src/pkg/module1.pyx'

    assert files[module_path][5] > 0, files[module_path]
    assert files[module_path][6] > 0, files[module_path]
    assert files[module_path][7] > 0, files[module_path]
    assert files[module_path][11] > 0, files[module_path]


def run_html_report():
    from collections import defaultdict

    stdout = run_coverage_command('html', '-d', 'html')
    # coverage 6.1+ changed the order of the attributes => need to parse them separately
    _parse_id = re.compile(r'id=["\'][^0-9"\']*(?P[0-9]+)[^0-9"\']*["\']').search
    _parse_state = re.compile(r'class=["\'][^"\']*(?Pmis|run|exc)[^"\']*["\']').search

    files = {}
    for file_path in iglob('html/*.html'):
        with open(file_path) as f:
            page = f.read()
        report = defaultdict(set)
        for line in re.split(r'id=["\']source["\']', page)[-1].splitlines():
            lineno = _parse_id(line)
            state = _parse_state(line)
            if not lineno or not state:
                continue
            report[state.group('state')].add(int(lineno.group('id')))
        files[file_path] = report

    file_report = [data for path, data in files.items() if 'module1' in path][0]
    executed, missing = file_report["run"], file_report["mis"]
    assert executed
    assert 5 in executed, executed
    assert 6 in executed, executed
    assert 7 in executed, executed
    assert 11 in executed, executed


if __name__ == '__main__':
    run_report()
    run_xml_report()
    run_html_report()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/coverage_installed_pkg.srctree0000644000175100001770000000227600000000000023635 0ustar00runnerdocker00000000000000# mode: run
# tag: coverage,trace

"""
PYTHON setup.py build_ext -i
PYTHON -c "import shutil; shutil.move('ext_src/ext_pkg', 'ext_pkg')"
PYTHON -m coverage run coverage_test.py
PYTHON -m coverage report
"""

######## setup.py ########
from distutils.core import setup, Extension
from Cython.Build import cythonize

setup(ext_modules = cythonize([
    'pkg/*.pyx',
]))

setup(
    name='ext_pkg',
    package_dir={'': 'ext_src'},
    ext_modules = cythonize([
        Extension('ext_pkg._mul', ['ext_src/ext_pkg/mul.py'])
    ]),
)


######## .coveragerc ########
[run]
plugins = Cython.Coverage


######## pkg/__init__.py ########
from .test_ext_import import test_add


######## pkg/test_ext_import.pyx ########
# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE=1

import ext_pkg


cpdef test_add(int a, int b):
    return a + ext_pkg.test_mul(b, 2)


######## ext_src/ext_pkg/__init__.py ########
from .mul import test_mul


######## ext_src/ext_pkg/mul.py ########
from __future__ import absolute_import


def test_mul(a, b):
     return a * b


try:
    from ._mul import *
except ImportError:
    pass


######## coverage_test.py ########

from pkg import test_add


assert 5 == test_add(1, 2)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/coverage_nogil.srctree0000644000175100001770000000565500000000000022131 0ustar00runnerdocker00000000000000# mode: run
# tag: coverage,trace,nogil,fastgil

"""
PYTHON setup.py build_ext -i
PYTHON coverage_test.py
"""

######## setup.py ########

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize([
    'coverage_test_*.pyx',
]))


######## .coveragerc ########
[run]
plugins = Cython.Coverage


######## coverage_test_nogil_fastgil.pyx ########
# cython: linetrace=True,fast_gil=True
# distutils: define_macros=CYTHON_TRACE=1 CYTHON_TRACE_NOGIL=1
include "_coverage_test_nogil.pxi"


######## coverage_test_nogil_nofastgil.pyx ########
# cython: linetrace=True,fast_gil=False
# distutils: define_macros=CYTHON_TRACE=1 CYTHON_TRACE_NOGIL=1
include "_coverage_test_nogil.pxi"


######## _coverage_test_nogil.pxi ########
#  1
#  2
#  3
cdef int func1(int a, int b) nogil:  #  4
    cdef int x                       #  5
    with gil:                        #  6
        x = 1                        #  7
    cdef int c = func2(a) + b        #  8
    return x + c                     #  9
# 10
# 11
cdef int func2(int a) with gil:  # 12
    return a * 2                 # 13
# 14
# 15
def call(int a, int b):          # 16
    a, b = b, a                  # 17
    with nogil:                  # 18
        result = func1(b, a)     # 19
    return result                # 20


######## coverage_test.py ########

import os.path
try:
    # io.StringIO in Py2.x cannot handle str ...
    from StringIO import StringIO
except ImportError:
    from io import StringIO

from coverage import coverage


def run_coverage(module_name):
    print("Testing module %s" % module_name)
    cov = coverage()
    cov.start()

    module = __import__(module_name)
    module_name = module.__name__
    module_path = module_name + '.pyx'
    assert not any(module.__file__.endswith(ext)
                   for ext in '.py .pyc .pyo .pyw .pyx .pxi'.split()), \
        module.__file__
    assert module.call(1, 2) == (1 * 2) + 2 + 1

    cov.stop()
    out = StringIO()
    cov.report(file=out)
    #cov.report([module], file=out)
    lines = out.getvalue().splitlines()
    assert any(module_path in line for line in lines), \
        "'%s' not found in coverage report:\n\n%s" % (module_path, out.getvalue())

    module_pxi = "_coverage_test_nogil.pxi"
    mod_file, exec_lines, excl_lines, missing_lines, _ = cov.analysis2(os.path.abspath(module_pxi))
    assert module_pxi in mod_file

    executed = set(exec_lines) - set(missing_lines)
    # check that everything that runs with the gil owned was executed (missing due to pxi: 4, 12, 16)
    assert all(line in executed for line in [13, 17, 18, 20]), '%s / %s' % (exec_lines, missing_lines)
    # check that everything that runs in nogil sections was executed
    assert all(line in executed for line in [6, 7, 8, 9]), '%s / %s' % (exec_lines, missing_lines)


if __name__ == '__main__':
    for module_name in ["coverage_test_nogil_fastgil", "coverage_test_nogil_nofastgil"]:
        run_coverage(module_name)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_enums.pxd0000644000175100001770000000074100000000000020551 0ustar00runnerdocker00000000000000cdef extern from *:
    cpdef enum: # ExternPxd
        FOUR "4"
        EIGHT "8"

    cdef enum: # ExternSecretPxd
        SIXTEEN "16"

cpdef enum PxdEnum:
    RANK_0 = 11
    RANK_1 = 37
    RANK_2 = 389

cpdef enum cpdefPxdDocEnum:
    """Home is where...
    """
    RANK_6 = 159

cpdef enum cpdefPxdDocLineEnum:
    """Home is where..."""
    RANK_7 = 889

cdef enum PxdSecretEnum:
    RANK_8 = 5077

cdef enum cdefPxdDocEnum:
    """the heart is.
    """
    RANK_9 = 2458
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_enums.pyx0000644000175100001770000001336600000000000020605 0ustar00runnerdocker00000000000000"""
>>> import sys

>>> ONE, TEN, HUNDRED
(1, 10, 100)
>>> THOUSAND        # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'THOUSAND' is not defined

>>> TWO == 2 or TWO
True
>>> THREE == 3 or THREE
True
>>> FIVE == 5 or FIVE
True
>>> ELEVEN == 11 or ELEVEN
True
>>> SEVEN           # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'SEVEN' is not defined

>>> FOUR == 4 or FOUR
True
>>> EIGHT == 8 or EIGHT
True
>>> SIXTEEN        # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'SIXTEEN' is not defined

>>> RANK_0 == 11 or RANK_0
True
>>> RANK_1 == 37 or RANK_1
True
>>> RANK_2 == 389 or RANK_2
True
>>> RANK_6 == 159 or RANK_6
True
>>> RANK_7 == 889 or RANK_7
True
>>> RANK_3         # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'RANK_3' is not defined

>>> set(PyxEnum) == {TWO, THREE, FIVE}
True
>>> str(PyxEnum.TWO).split(".")[-1]  if sys.version_info < (3,11) else  "TWO" # Py3.10/11 changed the output here
'TWO'
>>> str(PyxEnum.TWO)  if sys.version_info >= (3,11) else  "2" # Py3.10/11 changed the output here
'2'
>>> PyxEnum.TWO + PyxEnum.THREE == PyxEnum.FIVE
True
>>> PyxEnum(2) is PyxEnum["TWO"] is PyxEnum.TWO
True

# not leaking into module namespace
>>> IntEnum        # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'IntEnum' is not defined
"""

cdef extern from *:
    cpdef enum: # ExternPyx
        ONE "1"
        TEN "10"
        HUNDRED "100"

    cdef enum: # ExternSecretPyx
        THOUSAND "1000"

cpdef enum PyxEnum:
    TWO = 2
    THREE = 3
    FIVE = 5

cpdef enum cpdefPyxDocEnum:
    """Home is where...
    """
    ELEVEN = 11

cpdef enum cpdefPyxDocLineEnum:
    """Home is where..."""
    FOURTEEN = 14

cdef enum SecretPyxEnum:
    SEVEN = 7

cdef enum cdefPyxDocEnum:
    """the heart is.
    """
    FIVE_AND_SEVEN = 5077

cdef extern from *:
    """
    enum ExternHasDuplicates {
        EX_DUP_A,
        EX_DUP_B=EX_DUP_A,
        EX_DUP_C=EX_DUP_A
    };
    """
    # Cython doesn't know about the duplicates though
    cpdef enum ExternHasDuplicates:
        EX_DUP_A
        EX_DUP_B
        EX_DUP_C


cpdef enum CyDefinedHasDuplicates1:
    CY_DUP1_A
    CY_DUP1_B = 0x00000000


cpdef enum CyDefinedHasDuplicates2:
    CY_DUP2_A
    CY_DUP2_B = CY_DUP2_A

cpdef enum CyDefinedHasDuplicates3:
    CY_DUP3_A = 1
    CY_DUP3_B = 0
    CY_DUP3_C  # = 1


def test_as_variable_from_cython():
    """
    >>> test_as_variable_from_cython()
    """
    assert list(PyxEnum) == [TWO, THREE, FIVE], list(PyxEnum)
    assert list(PxdEnum) == [RANK_0, RANK_1, RANK_2], list(PxdEnum)

cdef int verify_pure_c() nogil:
    cdef int x = TWO
    cdef int y = PyxEnum.THREE
    cdef int z = SecretPyxEnum.SEVEN
    return x + y + z

# Use it to suppress warning.
verify_pure_c()

def verify_resolution_GH1533():
    """
    >>> verify_resolution_GH1533()
    3
    """
    THREE = 100
    return int(PyxEnum.THREE)


def check_docs():
    """
    >>> PxdEnum.__doc__ not in ("Home is where...\\n    ", "Home is where...")
    True
    >>> PyxEnum.__doc__ not in ("Home is where...\\n    ", "Home is where...")
    True
    >>> cpdefPyxDocEnum.__doc__ == "Home is where...\\n    "
    True
    >>> cpdefPxdDocEnum.__doc__ == "Home is where...\\n    "
    True
    >>> cpdefPyxDocLineEnum.__doc__
    'Home is where...'
    >>> cpdefPxdDocLineEnum.__doc__
    'Home is where...'
    """
    pass


def to_from_py_conversion(PxdEnum val):
    """
    >>> to_from_py_conversion(RANK_1) is PxdEnum.RANK_1
    True

    C enums are commonly enough used as flags that it seems reasonable
    to allow it in Cython
    >>> to_from_py_conversion(RANK_1 | RANK_2) == (RANK_1 | RANK_2)
    True
    """
    return val


def to_from_py_conversion_with_duplicates1(ExternHasDuplicates val):
    """
    Mainly a compile-time test - we can't optimize to a switch here
    >>> to_from_py_conversion_with_duplicates1(EX_DUP_A) == ExternHasDuplicates.EX_DUP_A
    True
    """
    return val


def to_from_py_conversion_with_duplicates2(CyDefinedHasDuplicates1 val):
    """
    Mainly a compile-time test - we can't optimize to a switch here
    >>> to_from_py_conversion_with_duplicates2(CY_DUP1_A) == CyDefinedHasDuplicates1.CY_DUP1_A
    True
    """
    return val


def to_from_py_conversion_with_duplicates3(CyDefinedHasDuplicates2 val):
    """
    Mainly a compile-time test - we can't optimize to a switch here
    >>> to_from_py_conversion_with_duplicates3(CY_DUP2_A) == CyDefinedHasDuplicates2.CY_DUP2_A
    True
    """
    return val


def to_from_py_conversion_with_duplicates4(CyDefinedHasDuplicates3 val):
    """
    Mainly a compile-time test - we can't optimize to a switch here
    >>> import sys
    >>> True if sys.version_info < (3, 6, 0) else to_from_py_conversion_with_duplicates4(CY_DUP3_C) == CyDefinedHasDuplicates3.CY_DUP3_C
    True
    """
    return val


def test_pickle():
    """
    >>> from pickle import loads, dumps
    >>> import sys

    Pickling enums won't work without the enum module, so disable the test in Py<3.6.
    (requires 3.6 for IntFlag)
    Python 3.11.4 has a bug that breaks pickling: https://github.com/python/cpython/issues/105332

    >>> if sys.version_info < (3, 6) or sys.version_info[:3] == (3,11,4):
    ...     loads = dumps = lambda x: x

    >>> loads(dumps(PyxEnum.TWO)) == PyxEnum.TWO
    True
    >>> loads(dumps(PxdEnum.RANK_2)) == PxdEnum.RANK_2
    True
    """
    pass

def test_as_default_value(PxdEnum val=PxdEnum.RANK_1):
    """
    In order to work, this requires the utility code to be evaluated
    before the function definition
    >>> test_as_default_value()
    True
    >>> test_as_default_value(PxdEnum.RANK_2)
    False
    >>> test_as_default_value.__defaults__[0] == PxdEnum.RANK_1
    True
    """
    return val == PxdEnum.RANK_1
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_enums_import.srctree0000644000175100001770000000363500000000000023024 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import import_enums_test"

######## setup.py ########

from Cython.Build.Dependencies import cythonize

from distutils.core import setup

setup(
  ext_modules = cythonize(["enums.pyx", "enums_same_name.pyx", "no_enums.pyx"]),
)

######## enums.pyx ########

cpdef enum:
    BAR

cpdef foo(): pass

######## enums.pxd ########

cpdef enum:
    FOO

cpdef enum NamedEnumType:
    NamedEnumValue = 389

cpdef foo()

######## enums_same_name.pyx ############

######## enums_same_name.pxd ############

# Note - same name as enums.pxd but shouldn't conflict
cpdef enum NamedEnumType:
    Value = 1

######## enums_without_pyx.pxd #####

cpdef enum EnumTypeNotInPyx:
    AnotherEnumValue = 500

######## no_enums.pyx ########

from enums cimport *
from enums_without_pyx cimport *
cimport enums_same_name

def get_named_enum_value():
    return NamedEnumType.NamedEnumValue

def get_from_enums_same_name():
    # This should not generate conflicting "to py" functions with the other
    # identically named enum from a different pxd file.
    return enums_same_name.NamedEnumType.Value

def get_named_without_pyx():
    # This'll generate a warning but return a c int
    return EnumTypeNotInPyx.AnotherEnumValue

######## import_enums_test.py ########

# We can import enums with a star import.
from enums import *
import enums_same_name

print(dir())
assert 'BAR' in dir() and 'FOO' in dir()
assert 'NamedEnumType' in dir()

# enums not generated in the wrong module
import no_enums
print(dir(no_enums))
assert 'FOO' not in dir(no_enums)
assert 'foo' not in dir(no_enums)

assert no_enums.get_named_enum_value() == NamedEnumType.NamedEnumValue
# In this case the enum isn't accessible from Python (by design)
# but the conversion to Python goes through a reasonable fallback
assert no_enums.get_named_without_pyx() == 500

assert no_enums.get_from_enums_same_name() == enums_same_name.NamedEnumType.Value
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_extern_func.pxd0000644000175100001770000000020300000000000021733 0ustar00runnerdocker00000000000000# cython: c_string_type=str
# cython: c_string_encoding=ascii

cdef extern from "math.h":
    cpdef double pxd_sqrt "sqrt"(double)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_extern_func.pyx0000644000175100001770000000124100000000000021763 0ustar00runnerdocker00000000000000# cython: c_string_type=str
# cython: c_string_encoding=ascii
# distutils: extra_compile_args=-fpermissive

__doc__ = """
>>> sqrt(1)
1.0
>>> pyx_sqrt(4)
2.0
>>> pxd_sqrt(9)
3.0
>>> log(10)  # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'log' is not defined
>>> strchr('abcabc', ord('c'))
'cabc'
>>> strchr(needle=ord('c'), haystack='abcabc')
'cabc'
"""

cdef extern from "math.h":
    cpdef double sqrt(double)
    cpdef double pyx_sqrt "sqrt"(double)
    cdef double log(double) # not wrapped

cdef extern from "string.h":
    # signature must be exact in C++, disagrees with C
    cpdef const char* strchr(const char *haystack, int needle);
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_extern_func_in_py.pxd0000644000175100001770000000010500000000000023132 0ustar00runnerdocker00000000000000
cdef extern from "math.h":
    cpdef double pxd_sqrt "sqrt"(double)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_extern_func_in_py.py0000644000175100001770000000044300000000000022774 0ustar00runnerdocker00000000000000
"""
>>> pxd_sqrt(9)
3.0
"""

import cython

if not cython.compiled:
    from math import sqrt as pxd_sqrt


@cython.test_assert_path_exists('//SimpleCallNode/NameNode[@type.is_pyobject = False]')
def call_pxd_sqrt(x):
    """
    >>> call_pxd_sqrt(9)
    3.0
    """
    return pxd_sqrt(x)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_method_override.pyx0000644000175100001770000000513500000000000022630 0ustar00runnerdocker00000000000000# mode: run
# tag: cpdef
# ticket: 1771

def _call_method(cls):
    obj = cls()
    obj.callmeth()
    obj = cls()
    obj.callmeth()
    obj.callmeth()
    obj = cls()
    obj.callmeth()
    obj.callmeth()
    obj.callmeth()


cdef class BaseType:
    """
    >>> BaseType().callmeth()
    BaseType.meth
    >>> obj = BaseType()
    >>> obj.callmeth()
    BaseType.meth
    >>> obj.callmeth()
    BaseType.meth
    >>> _call_method(BaseType)
    BaseType.meth
    BaseType.meth
    BaseType.meth
    BaseType.meth
    BaseType.meth
    BaseType.meth
    """
    cpdef callmeth(self):
        return self.callmeth2()
    cpdef callmeth2(self):
        # not overridden by subclasses
        return self.meth()
    cpdef meth(self):
        # overridden by subclasses
        print("BaseType.meth")


class NonOverride(BaseType):
    """
    >>> NonOverride().callmeth()
    BaseType.meth
    >>> obj = NonOverride()
    >>> obj.callmeth()
    BaseType.meth
    >>> obj.callmeth()
    BaseType.meth
    >>> _call_method(NonOverride)
    BaseType.meth
    BaseType.meth
    BaseType.meth
    BaseType.meth
    BaseType.meth
    BaseType.meth
    """


class PyClass(BaseType):
    """
    >>> PyClass().callmeth()
    PyClass.meth
    >>> obj = PyClass()
    >>> obj.callmeth()
    PyClass.meth
    >>> obj.callmeth()
    PyClass.meth
    >>> obj.callmeth()
    PyClass.meth
    >>> _call_method(PyClass)
    PyClass.meth
    PyClass.meth
    PyClass.meth
    PyClass.meth
    PyClass.meth
    PyClass.meth
    """
    def meth(self):
        print("PyClass.meth")


class PySlotsClass(BaseType):
    """
    >>> PySlotsClass().callmeth()
    PySlotsClass.meth
    >>> obj = PySlotsClass()
    >>> obj.callmeth()
    PySlotsClass.meth
    >>> obj.callmeth()
    PySlotsClass.meth
    >>> obj.callmeth()
    PySlotsClass.meth
    >>> _call_method(PySlotsClass)
    PySlotsClass.meth
    PySlotsClass.meth
    PySlotsClass.meth
    PySlotsClass.meth
    PySlotsClass.meth
    PySlotsClass.meth
    """
    __slots__ = []

    def meth(self):
        print("PySlotsClass.meth")


class DynamicOverride(BaseType):
    """
    >>> DynamicOverride().callmeth()
    meth1
    >>> obj = DynamicOverride()
    >>> obj.callmeth()
    meth1
    >>> obj.callmeth()
    meth2
    >>> obj.callmeth()
    BaseType.meth
    >>> obj.callmeth()
    BaseType.meth
    >>> _call_method(DynamicOverride)
    meth1
    meth1
    meth2
    meth1
    meth2
    BaseType.meth
    """
    def __init__(self):
        self.meth = self.meth1
    def meth1(self):
        self.meth = self.meth2
        print("meth1")
    def meth2(self):
        del self.meth
        print("meth2")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_method_override_recursion.pyx0000644000175100001770000000163000000000000024715 0ustar00runnerdocker00000000000000# mode: run
# tag: cpdef

# This also makes a nice benchmark for the cpdef method call dispatching code.

cdef class Ext:
    """
    >>> x = Ext()
    >>> x.rec(10)
    0
    """
    cpdef rec(self, int i):
        return 0 if i < 0 else self.rec(i-1)


class Py(Ext):
    """
    >>> p = Py()
    >>> p.rec(10)
    0
    """
    pass


class Slots(Ext):
    """
    >>> s = Slots()
    >>> s.rec(10)
    0
    """
    __slots__ = ()


class PyOverride(Ext):
    """
    >>> p = PyOverride()
    >>> p.rec(10)
    10
    5
    >>> p.rec(12)
    12
    11
    10
    5
    """
    def rec(self, i):
        print(i)
        return Ext.rec(self, i) if i > 10 else 5


class SlotsOverride(Ext):
    """
    >>> s = SlotsOverride()
    >>> s.rec(10)
    10
    6
    >>> s.rec(12)
    12
    11
    10
    6
    """
    __slots__ = ()
    def rec(self, i):
        print(i)
        return Ext.rec(self, i) if i > 10 else 6
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_nogil.pyx0000644000175100001770000000036100000000000020555 0ustar00runnerdocker00000000000000# cython: binding=True
# mode: run
# tag: cyfunction

cpdef int simple() nogil:
    """
    >>> simple()
    1
    """
    return 1


cpdef int call_nogil():
    """
    >>> call_nogil()
    1
    """
    with nogil:
        return simple()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_optargs.pyx0000644000175100001770000000346100000000000021130 0ustar00runnerdocker00000000000000# mode: run
# tag: cyfunction
# cython: binding=True

cimport cython


class PyClass(object):
    a = 2


class PyClass99(object):
    a = 99

    def pymethod(self, x, y=1, z=PyClass):
        """
        >>> obj = PyClass99()
        >>> obj.pymethod(0)
        (0, 1, 2)
        """
        return x, y, z.a


cdef class CyClass:
    cpdef cpmethod(self, x, y=1, z=PyClass):
        """
        >>> obj = CyClass()
        >>> obj.cpmethod(0)
        (0, 1, 2)
        >>> obj.cpmethod(0, 3)
        (0, 3, 2)
        >>> obj.cpmethod(0, 3, PyClass)
        (0, 3, 2)
        >>> obj.cpmethod(0, 3, 5)
        Traceback (most recent call last):
        AttributeError: 'int' object has no attribute 'a'
        """
        return x, y, z.a

    y_value = 3
    p_class = PyClass

    cpdef cpmethod2(self, x, y=y_value, z=p_class):
        """
        >>> obj = CyClass()
        >>> obj.cpmethod2(0)
        (0, 3, 2)
        """
        return x, y, z.a

    def pymethod(self, x, y=y_value, z=p_class):
        """
        >>> obj = CyClass()
        >>> obj.pymethod(0)
        (0, 3, 2)
        """
        return x, y, z.a

    # change values to check that defaults above stay unmodified
    y_value = 98
    p_class = PyClass99


cpdef func(x, y=1, z=PyClass):
    """
    >>> func(0)
    (0, 1, 2)
    >>> func(0, 3)
    (0, 3, 2)
    >>> func(0, 3, PyClass)
    (0, 3, 2)
    >>> func(0, 3, 5)
    Traceback (most recent call last):
    AttributeError: 'int' object has no attribute 'a'
    """
    return x, y, z.a


@cython.ccall
def pyfunc(x, y=1, z=PyClass):
    """
    >>> pyfunc(0)
    (0, 1, 2)
    >>> pyfunc(0, 3)
    (0, 3, 2)
    >>> pyfunc(0, 3, PyClass)
    (0, 3, 2)
    >>> pyfunc(0, 3, 5)
    Traceback (most recent call last):
    AttributeError: 'int' object has no attribute 'a'
    """
    return x, y, z.a
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_optargs_pure.pxd0000644000175100001770000000003000000000000022123 0ustar00runnerdocker00000000000000cpdef func(x, y=*, z=*)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_optargs_pure.py0000644000175100001770000000161600000000000021773 0ustar00runnerdocker00000000000000# mode: run
# tag: cyfunction
# cython: binding=True

import cython


class PyClass(object):
    a = 2


class PyClass99(object):
    a = 99

    def pymethod(self, x, y=1, z=PyClass):
        """
        >>> obj = PyClass99()
        >>> obj.pymethod(0)
        (0, 1, 2)
        """
        return x, y, z.a


def func(x, y=1, z=PyClass):
    """
    >>> func(0)
    (0, 1, 2)
    >>> func(0, 3)
    (0, 3, 2)
    >>> func(0, 3, PyClass)
    (0, 3, 2)
    >>> func(0, 3, 5)
    Traceback (most recent call last):
    AttributeError: 'int' object has no attribute 'a'
    """
    return x, y, z.a


@cython.ccall
def pyfunc(x, y=1, z=PyClass):
    """
    >>> pyfunc(0)
    (0, 1, 2)
    >>> pyfunc(0, 3)
    (0, 3, 2)
    >>> pyfunc(0, 3, PyClass)
    (0, 3, 2)
    >>> pyfunc(0, 3, 5)
    Traceback (most recent call last):
    AttributeError: 'int' object has no attribute 'a'
    """
    return x, y, z.a
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_pickle.srctree0000644000175100001770000000264200000000000021547 0ustar00runnerdocker00000000000000# mode: run
# tag: pickle

PYTHON main.py build_ext -i

######################### lib/__init__.py #########################

######################### lib/cy.pyx #########################
# cython: binding=True

cdef class WithoutC:
    def hello(self):
        return "Hello, World"

cdef class WithCPDef:
    cpdef str hello(self):
        return "Hello, World"

cdef class WithCDefWrapper:
    def hello(self):
        return _helloC(self)

cpdef _helloC(object caller):
    return "Hello, World"


######################### lib/cy.pxd #########################
# cython:language_level=3

cdef class WithoutCPDef:
    pass

cdef class WithCPDef:
    cpdef str hello(self)

cdef class WithCDefWrapper:
    pass

cpdef _helloC(object caller)


######################### main.py #########################
#!/usr/bin/env python3

from Cython.Build import cythonize
from distutils.core import setup

setup(
  ext_modules = cythonize(["lib/*.pyx"]),
)

import pickle as pkl
import os
from lib.cy import WithoutC, WithCPDef, WithCDefWrapper

def tryThis(obj):
    print("Pickling %s ..." % obj.__class__.__name__)
    try:
        with open("test.pkl", "wb") as fid:
            pkl.dump(obj, fid)
        print("\t... OK")
    except Exception as e:
        print("\t... KO: %s" % str(e))

try:
    for t in WithoutC(), WithCPDef(), WithCDefWrapper():
        tryThis(t)
finally:
    if os.path.exists("test.pkl"):
        os.remove("test.pkl")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_scoped_enums.pyx0000644000175100001770000000331500000000000022133 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp11

cdef extern from *:
    """
    enum class Enum1 {
        Item1 = 1,
        Item2 = 2
    };

    enum class Enum2 {
        Item4 = 4,
        Item5 = 5
    };
    """
    cpdef enum class Enum1:
        Item1
        Item2

    cpdef enum class Enum2:
        """Apricots and other fruits.
        """
        Item4
        Item5


def test_enum_to_list():
    """
    >>> test_enum_to_list()
    """
    assert list(Enum1) == [1, 2]
    assert list(Enum2) == [4, 5]


def test_enum_doc():
    """
    >>> Enum2.__doc__ == "Apricots and other fruits.\\n        "
    True
    >>> Enum1.__doc__ != "Apricots and other fruits.\\n        "
    True
    """
    pass


def to_from_py_conversion(Enum1 val):
    """
    >>> to_from_py_conversion(Enum1.Item1) is Enum1.Item1
    True

    Scoped enums should not be used as flags, and therefore attempts to set them
    with arbitrary values should fail
    >>> to_from_py_conversion(500)
    Traceback (most recent call last):
    ...
    ValueError: 500 is not a valid Enum1

    # Note that the ability to bitwise-or together the two numbers is inherited
    from the Python enum (so not in Cython's remit to prevent)
    >>> to_from_py_conversion(Enum1.Item1 | Enum1.Item2)
    Traceback (most recent call last):
    ...
    ValueError: 3 is not a valid Enum1
    """
    return val


def test_pickle():
    """
    >>> from pickle import loads, dumps
    >>> import sys

    Pickling enums won't work without the enum module, so disable the test
    >>> if sys.version_info < (3, 4):
    ...     loads = dumps = lambda x: x
    >>> loads(dumps(Enum1.Item2)) == Enum1.Item2
    True
    >>> loads(dumps(Enum2.Item4)) == Enum2.Item4
    True
    """
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_scoped_enums_import.srctree0000644000175100001770000000276200000000000024361 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp11

"""
PYTHON setup.py build_ext --inplace
PYTHON -c "import runner"
"""

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup
setup(ext_modules=cythonize("*.pyx", language='c++'))

setup(
  ext_modules = cythonize([
              "cheese.pyx",
              "import_scoped_enum_test.pyx",
              "dotted_import_scoped_enum_test.pyx"
              ])
)

######## cheese.pxd ########
# distutils: language = c++
# distutils: extra_compile_args = -std=c++11


cdef extern from * namespace "Namespace":
    """
    namespace Namespace {
        enum class Cheese {
            cheddar = 1,
            camembert = 2
        };
    }
    """
    cpdef enum class Cheese:
        cheddar
        camembert

######## cheese.pyx ########
# distutils: language = c++
# distutils: extra_compile_args = -std=c++11

pass

######## import_scoped_enum_test.pyx ########
# distutils: language = c++
# distutils: extra_compile_args = -std=c++11

from cheese import Cheese
from cheese cimport Cheese

cdef Cheese c = Cheese.cheddar
assert list(Cheese) == [1, 2]

######## dotted_import_scoped_enum_test.pyx ########
# distutils: language = c++
# distutils: extra_compile_args = -std=c++11


cimport cheese

cdef cheese.Cheese c = cheese.Cheese.cheddar
assert [cheese.Cheese.cheddar, cheese.Cheese.camembert] == [1, 2]
cdef cheese.Cheese d = int(1)

######## runner.py ########

import import_scoped_enum_test
import dotted_import_scoped_enum_test
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_temps_T411.pyx0000644000175100001770000000053700000000000021313 0ustar00runnerdocker00000000000000# ticket: t411

cdef class A:
    """
    >>> A().is_True()
    True
    >>> A().is_False()
    False
    """
    cpdef is_True(self):
        return True
    cpdef is_False(self):
        return not self.is_True()

class B(A):
    """
    >>> B().is_True()
    True
    >>> B().is_False()
    False
    """
    def is_True(self):
        return True
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpdef_void_return.pyx0000644000175100001770000000111500000000000022003 0ustar00runnerdocker00000000000000cpdef void unraisable() noexcept:
    """
    >>> unraisable()
    here
    """
    print('here')
    raise RuntimeError()

cpdef void raisable() except *:
    """
    >>> raisable()
    Traceback (most recent call last):
    ...
    RuntimeError
    """
    print('here')
    raise RuntimeError()

cdef class A:
    """
    >>> A().foo()
    A
    """
    cpdef void foo(self):
        print "A"

cdef class B(A):
    """
    >>> B().foo()
    B
    """
    cpdef void foo(self):
        print "B"

class C(B):
    """
    >>> C().foo()
    C
    """
    def foo(self):
        print "C"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpow.pyx0000644000175100001770000001705300000000000017262 0ustar00runnerdocker00000000000000# mode: run
# tag: warnings

from __future__ import print_function

cimport cython
import sys

if sys.version_info[0] > 2:
    # The  path doesn't work in Py2
    __doc__ = """
    >>> pow_double_double(-4, 0.5, 1e-15)
    soft double complex complex
    """

def pow_double_double(double a, double b, delta):
    """
    >>> pow_double_double(2, 2, 1e-15)
    soft double complex float
    >>> pow_double_double(4, 0.5, 1e-15)
    soft double complex float
    """
    c = a**b
    # print out the Cython type, and the coerced type
    print(cython.typeof(c), type(c).__name__)
    object_c = (a)**(b)
    assert abs((c/object_c) - 1) < delta

@cython.cpow(True)
def pow_double_double_cpow(double a, double b, delta=None):
    """
    >>> pow_double_double_cpow(2, 2, 1e-15)
    double float
    >>> pow_double_double_cpow(4, 0.5, 1e-15)
    double float
    >>> x = pow_double_double_cpow(-4, 0.5)
    double float
    >>> x == x  # is nan
    False
    """
    c = a**b
    # print out the Cython type, and the coerced type
    print(cython.typeof(c), type(c).__name__)
    if delta is not None:
        object_c = (a)**(b)
        assert abs((c/object_c) - 1) < delta
    else:
        return c

cdef cfunc_taking_double(double x):
    return x

def pow_double_double_coerced_directly(double a, double b):
    """
    >>> pow_double_double_coerced_directly(2, 2)
    8.0
    >>> x = pow_double_double_coerced_directly(-2, 0.5)
    >>> x == x  # nan
    False
    """
    # Because we're assigning directly to a double assume 'cpow'
    # but warn.
    cdef double c = a**b
    return cfunc_taking_double(a**b) + c

def pow_double_int(double a, int b):
    """
    # a few variations of 'double**int'. In all cases
    # Cython should realise that the result can't be complex
    # and avoid going through the soft complex type
    >>> pow_double_int(5, 2)
    double
    double
    double
    double
    double
    """
    c1 = a**b
    c2 = a**2.0
    c3 = a**-2.0
    c4 = a**5
    c5 = a**-5
    print(cython.typeof(c1))
    print(cython.typeof(c2))
    print(cython.typeof(c3))
    print(cython.typeof(c4))
    print(cython.typeof(c5))

def soft_complex_coerced_to_double(double a, double b):
    """
    >>> soft_complex_coerced_to_double(2, 2)
    4.0
    >>> soft_complex_coerced_to_double(-2, 0.25)
    Traceback (most recent call last):
    ...
    TypeError: Cannot convert 'complex' with non-zero imaginary component to 'double' (this most likely comes from the '**' operator; use 'cython.cpow(True)' to return 'nan' instead of a complex number).
    """
    c = a**b
    assert cython.typeof(c) == "soft double complex"
    cdef double d = c  # will raise if complex
    return d

def soft_complex_coerced_to_complex(double a, double b):
    """
    >>> soft_complex_coerced_to_complex(2, 2)
    (4+0j)
    >>> x = soft_complex_coerced_to_complex(-1, 0.5)
    >>> abs(x.real) < 1e-15
    True
    >>> abs(x.imag - 1) < 1e-15
    True
    """
    # This is always fine, but just check it works
    c = a**b
    assert cython.typeof(c) == "soft double complex"
    cdef double complex d = c
    return d

def soft_complex_type_inference_1(double a, double b, pick):
    """
    >>> soft_complex_type_inference_1(2, 1, False)
    soft double complex 2.0
    >>> soft_complex_type_inference_1(2, 3, True)
    soft double complex 4.0
    """
    # double and soft complex should infer to soft-complex
    if pick:
        c = a**2
    else:
        c = a**b
    print(cython.typeof(c), c)

def soft_complex_type_inference_2(double a, double b, expected):
    """
    >>> soft_complex_type_inference_2(2, 1, 1.0)
    soft double complex
    >>> soft_complex_type_inference_2(2, 3, 7.0)
    soft double complex
    """
    # double and soft complex should infer to soft-complex
    c = a**b
    c -= 1
    print(cython.typeof(c))
    delta = abs(c/expected - 1)
    assert delta < 1e-15, delta

def pow_int_int(int a, int b):
    """
    >>> pow_int_int(2, 2)
    double 4.0
    >>> pow_int_int(2, -2)
    double 0.25
    """
    c = a**b
    print(cython.typeof(c), c)

@cython.cpow(True)
def pow_int_int_cpow(int a, int b):
    """
    >>> pow_int_int_cpow(2, 2)
    int 4
    >>> pow_int_int_cpow(2, -2)
    int 0
    """
    c = a**b
    print(cython.typeof(c), c)

cdef cfunc_taking_int(int x):
    return x

def pow_int_int_coerced_directly(int a, int b):
    """
    Generates two warnings about using cpow.
    The actual behaviour isn't too easy to distinguish
    without inspecting the c code though.
    >>> pow_int_int_coerced_directly(2, 2)
    8
    """
    cdef int c = a**b
    return cfunc_taking_int(a**b) + c

def pow_int_int_non_negative(int a, unsigned int b):
    """
    A couple of combinations of non-negative values for the
    exponent, which lets us fall back to int as a return type
    >>> pow_int_int_non_negative(5, 3)
    unsigned int
    long
    """
    c1 = a**b
    c2 = a**5
    print(cython.typeof(c1))
    print(cython.typeof(c2))


ctypedef double f64

def pythagoras_with_typedef(double a, double b):
    # see https://github.com/cython/cython/issues/5203
    """
    >>> rc = pythagoras_with_typedef(2.0, 2.0)
    >>> pyresult = 1.0 / (2 * 2.0 ** 2) ** 0.5
    >>> pyresult - 0.001 < rc < pyresult + 0.001  or  (rc, pyresult)
    True
    """
    cdef f64 result = a * a + b * b
    result = 1.0 / result ** 0.5
    return result


@cython.cpow(False)
def power_coercion_in_nogil_1(double a, double b):
    """
    >>> power_coercion_in_nogil_1(2., 2.)
    4.0
    >>> power_coercion_in_nogil_1(-1., 0.5)
    Traceback (most recent call last):
    ...
    TypeError: Cannot convert 'complex' with non-zero imaginary component to 'double' (this most likely comes from the '**' operator; use 'cython.cpow(True)' to return 'nan' instead of a complex number).
    """
    cdef double c
    with nogil:
        c = a**b
    return c


cdef double nogil_fun(double x) nogil:
    return x

def power_coercion_in_nogil_2(double a, double b):
    """
    >>> power_coercion_in_nogil_2(2., 2.)
    4.0
    >>> power_coercion_in_nogil_2(-1., 0.5)
    Traceback (most recent call last):
    ...
    TypeError: Cannot convert 'complex' with non-zero imaginary component to 'double' (this most likely comes from the '**' operator; use 'cython.cpow(True)' to return 'nan' instead of a complex number).
    """
    c = a**b
    with nogil:
        d = nogil_fun(c)
    return d


def power_coercion_in_nogil_3(double a, double b, double c):
    """
    >>> power_coercion_in_nogil_3(2., 2., 1.0)
    0.25
    >>> power_coercion_in_nogil_3(-1., 0.5, 1.0)
    Traceback (most recent call last):
    ...
    TypeError: Cannot convert 'complex' with non-zero imaginary component to 'double' (this most likely comes from the '**' operator; use 'cython.cpow(True)' to return 'nan' instead of a complex number).
    """
    with nogil:
        c /= a**b
    return c


_WARNINGS = """
63:21: Treating '**' as if 'cython.cpow(True)' since it is directly assigned to a a non-complex C numeric type. This is likely to be fragile and we recommend setting 'cython.cpow' explicitly.
64:32: Treating '**' as if 'cython.cpow(True)' since it is directly assigned to a a non-complex C numeric type. This is likely to be fragile and we recommend setting 'cython.cpow' explicitly.
179:18: Treating '**' as if 'cython.cpow(True)' since it is directly assigned to a an integer C numeric type. This is likely to be fragile and we recommend setting 'cython.cpow' explicitly.
180:29: Treating '**' as if 'cython.cpow(True)' since it is directly assigned to a an integer C numeric type. This is likely to be fragile and we recommend setting 'cython.cpow' explicitly.
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpp_assignment_overload.srctree0000644000175100001770000000250600000000000024043 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp

"""
PYTHON setup.py build_ext --inplace
PYTHON -c "from assignment_overload import test; test()"
"""

######## setup.py ########

from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize("*.pyx", language='c++'))


######## assign.cpp ########

class wrapped_int {
public:
  long long val;
  wrapped_int() { val = 0; }
  wrapped_int(long long val) { this->val = val; }
  wrapped_int &operator=(const wrapped_int &other) {
    this->val = other.val;
    return *this;
  }
  wrapped_int &operator=(const long long val) {
    this->val = val;
    return *this;
  }
};


######## assign.pxd ########

cdef extern from "assign.cpp" nogil:
    cppclass wrapped_int:
        long long val
        wrapped_int()
        wrapped_int(long long val)
        wrapped_int& operator=(const wrapped_int &other)
        wrapped_int& operator=(const long long &other)


######## assignment_overload.pyx ########

from assign cimport wrapped_int

def test():
    cdef wrapped_int a = wrapped_int(2)
    cdef wrapped_int b = wrapped_int(3)
    cdef long long c = 4

    assert &a != &b
    assert a.val != b.val

    a = b
    assert &a != &b
    assert a.val == b.val
    a = c
    assert a.val == c

    a, b, c = 2, 3, 4
    a = b = c
    assert &a != &b
    assert a.val == b.val
    assert b.val == c
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpp_bool.pyx0000644000175100001770000000143200000000000020101 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, no-cpp-locals

from libcpp cimport bool

def test_bool(bool a):
    """
    >>> test_bool(True)
    True
    >>> test_bool(1)
    True
    >>> test_bool(0)
    False
    >>> test_bool(100)
    True
    >>> test_bool(None)
    False
    >>> test_bool([])
    False
    """
    return a


cdef bool may_raise_exception(bool value, exception) except *:
    if exception:
        raise exception
    else:
        return value

def test_may_raise_exception(bool value, exception=None):
    """
    >>> test_may_raise_exception(False)
    False
    >>> test_may_raise_exception(True)
    True
    >>> test_may_raise_exception(True, RuntimeError)
    Traceback (most recent call last):
    ...
    RuntimeError
    """
    return may_raise_exception(value, exception)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpp_bool_template_return.pyx0000644000175100001770000000051600000000000023375 0ustar00runnerdocker00000000000000# tag: cpp

from libcpp cimport bool

cdef extern from "cpp_templates_helper.h":
    cdef cppclass BinaryAnd[T1, T2]:
        @staticmethod
        T1 call(T1 x, T2 y)


def test_compound_bool_return(bool x, bool y):
    """
    >>> test_compound_bool_return(True, False)
    False
    """
    return BinaryAnd[bool, bool].call(x, y)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpp_call_stack_allocated.srctree0000644000175100001770000000211400000000000024103 0ustar00runnerdocker00000000000000# tag: cpp

"""
PYTHON setup.py build_ext --inplace
PYTHON -c "from call_stack_allocated import test; test()"
"""

######## setup.py ########

from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize('*.pyx', language='c++'))

######## call.cpp ########

class wint {
public:
  long long val;
  wint() { val = 0; }
  wint(long long val) { this->val = val; }
  long long &operator()() { return this->val; }
  long long operator()(long long i) { return this->val + i; }
  long long operator()(long long i, long long j) { return this->val + i + j; }
};

######## call.pxd ########

cdef extern from "call.cpp" nogil:
    cppclass wint:
        long long val
        wint()
        wint(long long val)
        long long& operator()()
        long long operator()(long long i)
        long long operator()(long long i, long long j)


######## call_stack_allocated.pyx ########

from call cimport wint
def test():
    cdef wint a = wint(4)
    cdef long long b = 3
    b = a()
    assert b == 4
    b = a(1ll)
    assert b == 5
    b = a(1ll, 1ll)
    assert b == 6

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpp_class_attrib.srctree0000644000175100001770000000125300000000000022450 0ustar00runnerdocker00000000000000# tag: cpp

PYTHON setup.py build_ext --inplace
PYTHON -c "import runner"

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup
import os

example_dir = os.path.abspath(os.path.join(os.environ['CYTHON_PROJECT_DIR'],
                              'docs/examples/userguide/wrapping_CPlusPlus'))

ext_modules= cythonize(os.path.join(example_dir, "rect_with_attributes.pyx"),
                       include_path=[example_dir])
setup(ext_modules=ext_modules)

######## runner.py ########

import rect_with_attributes

x0, y0, x1, y1 = 1, 2, 3, 4
rect_obj = rect_with_attributes.PyRectangle(x0, y0, x1, y1)

assert rect_obj.x0 == x0
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpp_class_redef.pxd0000644000175100001770000000015300000000000021372 0ustar00runnerdocker00000000000000# tag: cpp

cdef extern cppclass Foo:
    int _foo
    void set_foo(int foo) nogil
    int get_foo() nogil
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpp_class_redef.pyx0000644000175100001770000000103700000000000021421 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, warnings, no-cpp-locals

# This gives a warning about the previous .pxd definition, but should not give an error.
cdef cppclass Foo:
    int _foo
    int get_foo():
        return this._foo
    void set_foo(int foo):
        this._foo = foo

def test_Foo(n):
    """
    >>> test_Foo(1)
    1
    """
    cdef Foo* foo = NULL
    try:
        foo = new Foo()
        foo.set_foo(n)
        return foo.get_foo()
    finally:
        del foo


_WARNINGS = """
5:5: 'Foo' already defined  (ignoring second definition)
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpp_classes.pyx0000644000175100001770000001370200000000000020606 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, no-cpp-locals

from libcpp.vector cimport vector

cdef extern from "shapes.h" namespace "shapes":

    cdef cppclass Shape:
        float area()

    cdef cppclass Ellipse(Shape):
        Ellipse(int a, int b) except + nogil

    cdef cppclass Circle(Ellipse):
        int radius
        Circle(int r) except +

    cdef cppclass Rectangle(Shape):
        int width
        int height
        Rectangle() except +
        Rectangle(int h, int w) except +
        int method(int x)
        int method(bint b)

    cdef cppclass Square(Rectangle):
        int side
        Square(int s) except +

    cdef cppclass Empty(Shape):
        pass

    cdef cppclass EmptyWithDocstring(Shape):
        """
        This is a docstring !
        """


    int constructor_count, destructor_count


def test_new_del():
    """
    >>> test_new_del()
    2 0
    2 2
    """
    c,d = constructor_count, destructor_count
    cdef Rectangle *rect = new Rectangle(10, 20)
    cdef Circle *circ = new Circle(15)
    print constructor_count-c, destructor_count-d
    del rect, circ
    print constructor_count-c, destructor_count-d


def test_default_constructor():
    """
    >>> test_default_constructor()
    0.0
    """
    shape = new Empty()
    try:
        return shape.area()
    finally:
        del shape


def test_constructor_nogil():
    """
    >>> test_constructor_nogil()
    True
    """
    with nogil:
        shape = new Ellipse(4, 5)
    try:
        return 62 < shape.area() < 63 or shape.area()
    finally:
        del shape


def test_rect_area(w, h):
    """
    >>> test_rect_area(3, 4)
    12.0
    """
    cdef Rectangle *rect = new Rectangle(w, h)
    try:
        return rect.area()
    finally:
        del rect


def test_overload_bint_int():
    """
    >>> test_overload_bint_int()
    202
    201
    """
    cdef Rectangle *rect1 = new Rectangle(10, 20)
    cdef Rectangle *rect2 = new Rectangle(10, 20)

    try:
        print rect1.method( 2)
        print rect2.method( True)
    finally:
        del rect1
        del rect2


def test_square_area(w):
    """
    >>> test_square_area(15)
    (225.0, 225.0)
    """
    cdef Square *sqr = new Square(w)
    cdef Rectangle *rect = sqr
    try:
        return rect.area(), sqr.area()
    finally:
        del sqr


cdef double get_area(Rectangle s):
    return s.area()

def test_value_call(int w):
    """
    >>> test_value_call(5)
    (25.0, 25.0)
    """
    cdef Square *sqr = new Square(w)
    cdef Rectangle *rect = sqr
    try:
        return get_area(sqr[0]), get_area(rect[0])
    finally:
        del sqr


cdef struct StructWithEmpty:
    Empty empty


def get_destructor_count():
    return destructor_count

def test_stack_allocation(int w, int h):
    """
    >>> d = test_stack_allocation(10, 12)
    125
    >>> get_destructor_count() - d
    1
    """
    cdef Rectangle rect
    rect.width = w
    rect.height = h
    print rect.method(5)
    return destructor_count

def test_stack_allocation_in_struct():
    """
    >>> d = test_stack_allocation_in_struct()
    >>> get_destructor_count() - d
    1
    """
    cdef StructWithEmpty swe
    sizeof(swe.empty) # use it for something
    return destructor_count

cdef class EmptyHolder:
    cdef Empty empty

cdef class AnotherEmptyHolder(EmptyHolder):
    cdef Empty another_empty

cdef class EmptyViaStructHolder:
    cdef StructWithEmpty swe

def test_class_member():
    """
    >>> test_class_member()
    """
    start_constructor_count = constructor_count
    start_destructor_count = destructor_count
    e1 = EmptyHolder()
    assert constructor_count - start_constructor_count == 1, \
           constructor_count - start_constructor_count
    e2 = EmptyHolder()
    assert constructor_count - start_constructor_count == 2, \
           constructor_count - start_constructor_count
    del e1, e2
    assert destructor_count - start_destructor_count == 2, \
           destructor_count - start_destructor_count


def test_derived_class_member():
    """
    >>> test_derived_class_member()
    """
    start_constructor_count = constructor_count
    start_destructor_count = destructor_count
    e = AnotherEmptyHolder()
    assert constructor_count - start_constructor_count == 2, \
           constructor_count - start_constructor_count
    del e
    assert destructor_count - start_destructor_count == 2, \
           destructor_count - start_destructor_count

def test_class_in_struct_member():
    """
    >>> test_class_in_struct_member()
    """
    start_constructor_count = constructor_count
    start_destructor_count = destructor_count
    e = EmptyViaStructHolder()
    #assert constructor_count - start_constructor_count == 1, \
    #       constructor_count - start_constructor_count
    del e
    assert destructor_count - start_destructor_count == 1, \
           destructor_count - start_destructor_count

cdef class TemplateClassMember:
    cdef vector[int] x
    cdef vector[vector[Empty]] vec

def test_template_class_member():
    """
    >>> test_template_class_member()
    """
    cdef vector[Empty] inner
    inner.push_back(Empty())
    inner.push_back(Empty())
    o = TemplateClassMember()
    o.vec.push_back(inner)

    start_destructor_count = destructor_count
    del o
    assert destructor_count - start_destructor_count == 2, \
           destructor_count - start_destructor_count


ctypedef vector[int]* vector_int_ptr
cdef vector[vector_int_ptr] create_to_delete() except *:
    cdef vector[vector_int_ptr] v
    v.push_back(new vector[int]())
    return v
cdef int f(int x):
    return x


def test_nested_del():
    """
    >>> test_nested_del()
    """
    cdef vector[vector_int_ptr] v
    v.push_back(new vector[int]())
    del v[0]
    del create_to_delete()[f(f(0))]


def test_nested_del_repeat():
    """
    >>> test_nested_del_repeat()
    """
    cdef vector[vector_int_ptr] v
    v.push_back(new vector[int]())
    del v[0]
    del create_to_delete()[f(f(0))]
    del create_to_delete()[f(f(0))]
    del create_to_delete()[f(f(0))]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpp_classes_def.pyx0000644000175100001770000001475600000000000021436 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp11, no-cpp-locals
# cython: experimental_cpp_class_def=True

cdef double pi
from math import pi
from libc.math cimport sin, cos
from libcpp cimport bool
from libcpp.memory cimport unique_ptr
from libcpp.vector cimport vector
from cython.operator cimport dereference as deref
import cython

cdef extern from "shapes.h" namespace "shapes":
    cdef cppclass Shape:
        float area() const

cdef cppclass RegularPolygon(Shape):
    float radius # major
    int n
    __init__(int n, float radius):
        this.n = n
        this.radius = radius
    float area() noexcept const:
        cdef double theta = pi / this.n
        return this.radius * this.radius * sin(theta) * cos(theta) * this.n
    void do_with() except *:
        # only a compile test - the file doesn't actually have to exist
        # "with" was broken by https://github.com/cython/cython/issues/4212
        with open("does not matter") as f:
            return

def test_Poly(int n, float radius=1):
    """
    >>> test_Poly(4)
    2.0
    >>> test_Poly(3)         #doctest: +ELLIPSIS
    1.29903...
    >>> test_Poly(3, 10.0)   #doctest: +ELLIPSIS
    129.903...
    >>> test_Poly(100)       #doctest: +ELLIPSIS
    3.13952...
    >>> test_Poly(1000)      #doctest: +ELLIPSIS
    3.14157...
    """
    cdef RegularPolygon* poly
    try:
        poly = new RegularPolygon(n, radius)
        poly.n = n
        poly.radius = radius
        return poly.area()
    finally:
        del poly

cdef cppclass BaseClass:
    int n
    int method():
        return this.n

cdef cppclass SubClass(BaseClass):
    bool override
    __init__(bool override):
        this.n = 1
        this.override = override
    int method():
        if override:
            return 0
        else:
            return BaseClass.method()

def test_BaseMethods(x):
    """
    >>> test_BaseMethods(True)
    0
    >>> test_BaseMethods(False)
    1
    """
    cdef SubClass* subClass
    try:
        subClass = new SubClass(x)
        return subClass.method()
    finally:
        del subClass

cdef cppclass WithStatic:
    @staticmethod
    double square(double x):
        return x * x

def test_Static(x):
    """
    >>> test_Static(2)
    4.0
    >>> test_Static(0.5)
    0.25
    """
    return WithStatic.square(x)


cdef cppclass InitDealloc:
    __init__():
        try:
            print "Init"
        finally:
            return  # swallow any exceptions
    __dealloc__():
        try:
            print "Dealloc"
        finally:
            return  # swallow any exceptions

def test_init_dealloc():
    """
    >>> test_init_dealloc()
    start
    Init
    live
    Dealloc
    end
    """
    print "start"
    cdef InitDealloc *ptr = new InitDealloc()
    print "live"
    del ptr
    print "end"


cdef cppclass WithTemplate[T]:
    T value
    void set_value(T value):
        this.value = value
    T get_value():
        return this.value

cdef cppclass ResolveTemplate(WithTemplate[long]):
    pass

def test_templates(long value):
    """
    >>> test_templates(10)
    >>> test_templates(-2)
    """
    cdef WithTemplate[long] *base = new WithTemplate[long]()
    del base

    cdef ResolveTemplate *resolved = new ResolveTemplate()
    resolved.set_value(value)
    assert resolved.value == resolved.get_value() == value, resolved.value

    base = resolved
    base.set_value(2 * value)
    assert base.get_value() == base.value == 2 * value, base.value

    del base

cdef cppclass Simple:
  pass

def test_default_init_no_gil():
  with nogil:
    s = new Simple()
    del s


cdef class NoisyAlloc(object):
    cdef public name
    def __init__(self, name):
        print "NoisyAlloc.__init__", name
        self.name = name
    def __dealloc__(self):
        try:
            print "NoisyAlloc.__dealloc__", self.name
        except:
            pass  # Suppress unraisable exception warning.
    def __repr__(self):
        return "NoisyAlloc[%s]" % self.name

cdef cppclass CppClassWithObjectMember:
    NoisyAlloc o
    __init__(name):
        try:
            print "CppClassWithObjectMember.__init__", name
            this.o = NoisyAlloc(name)
        except:
            pass  # Suppress unraisable exception warning.
    __dealloc__():
        try:
            print "CppClassWithObjectMember.__dealloc__", this.o.name
        except:
            pass  # Suppress unraisable exception warning.

def test_CppClassWithObjectMember(name):
    """
    >>> test_CppClassWithObjectMember("gertrude")
    CppClassWithObjectMember.__init__ gertrude
    NoisyAlloc.__init__ gertrude
    CppClassWithObjectMember.__dealloc__ gertrude
    NoisyAlloc.__dealloc__ gertrude
    """
    x = new CppClassWithObjectMember(name)
    del x

def test_CppClassWithObjectMemberCopyAssign(name):
    """
    >>> test_CppClassWithObjectMemberCopyAssign("gretel")
    CppClassWithObjectMember.__init__ gretel
    NoisyAlloc.__init__ gretel
    CppClassWithObjectMember.__dealloc__ gretel
    Alive in vector NoisyAlloc[gretel]
    CppClassWithObjectMember.__init__ leterg
    NoisyAlloc.__init__ leterg
    NoisyAlloc.__dealloc__ gretel
    CppClassWithObjectMember.__dealloc__ leterg
    Alive in vector NoisyAlloc[leterg]
    CppClassWithObjectMember.__dealloc__ leterg
    NoisyAlloc.__dealloc__ leterg
    Nothing alive.
    """
    x = new CppClassWithObjectMember(name)
    cdef vector[CppClassWithObjectMember] v
    # Invokes copy constructor.
    v.push_back(deref(x))
    del x
    print "Alive in vector", v[0].o
    y = new CppClassWithObjectMember(name[::-1])
    # Invokes copy assignment.
    v[0] = deref(y)
    del y
    print "Alive in vector", v[0].o
    v.clear()
    print "Nothing alive."


# Github issue #1886.
cdef public cppclass PublicCppClassWithObjectMember:
  object o

def test_PublicCppClassWithObjectMember():
  """
  >>> test_PublicCppClassWithObjectMember()
  """
  cdef PublicCppClassWithObjectMember c
  assert c.o is None


cdef cppclass UncopyableConstructorArgument:
    unique_ptr[vector[int]] member
    __init__(unique_ptr[vector[int]] arg):
        this.member.reset(arg.release())

def test_uncopyable_constructor_argument():
    """
    >>> test_uncopyable_constructor_argument()
    """
    cdef UncopyableConstructorArgument *c = new UncopyableConstructorArgument(
        unique_ptr[vector[int]](new vector[int]()))
    del c

cdef cppclass CppClassWithDocstring:
    """
    This is a docstring !
    """

def test_CppClassWithDocstring():
    """
    >>> test_CppClassWithDocstring()
    OK
    """
    cdef CppClassWithDocstring *c = new CppClassWithDocstring()
    del c
    print "OK"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpp_const_method.pyx0000644000175100001770000000372200000000000021640 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, no-cpp-locals
# cython: experimental_cpp_class_def=True

from libcpp.vector cimport vector

cdef cppclass Wrapper[T]:
    T value
    __init__(T &value):
        this.value = value
    void set(T &value):
        this.value = value
    T get() const:
        return this.value


def test_const_get(int x):
    """
    >>> test_const_get(10)
    10
    """
    cdef const Wrapper[int] *wrapper = new Wrapper[int](x)
    try:
        return const_get(wrapper[0])
    finally:
        del wrapper

cdef int const_get(const Wrapper[int] wrapper):
    return wrapper.get()

def test_const_ref_get(int x):
    """
    >>> test_const_ref_get(100)
    100
    """
    cdef const Wrapper[int] *wrapper = new Wrapper[int](x)
    try:
        return const_ref_get(wrapper[0])
    finally:
        del wrapper

cdef int const_ref_get(const Wrapper[int] &wrapper):
    return wrapper.get()

def test_const_pointer_get(int x):
    """
    >>> test_const_pointer_get(1000)
    1000
    """
    cdef Wrapper[int] *wrapper = new Wrapper[int](x)
    cdef const Wrapper[int] *const_wrapper = wrapper
    try:
        return const_wrapper.get()
    finally:
        del wrapper


# TODO: parse vector[Wrapper[int]*]
ctypedef Wrapper[int] wrapInt

def test_vector_members(py_a, py_b):
    """
    >>> test_vector_members([1, 2, 3], [4,5, 6])
    ([1, 2, 3], 4)
    """
    cdef Wrapper[int] *value
    cdef const Wrapper[int] *const_value
    cdef vector[const Wrapper[int]*] a
    cdef vector[wrapInt*] b
    for x in py_a:
        a.push_back(new Wrapper[int](x))
    for x in py_b:
        b.push_back(new Wrapper[int](x))
    try:
        return vector_members(a, b)
    finally:
        for const_value in a:
            del const_value
        for value in b:
            del value

cdef vector_members(vector[const Wrapper[int]*] a, const vector[wrapInt*] b):
    # TODO: Cython-level error.
    # b[0].set(100)

    # TODO: const_iterator
    return [x.get() for x in a], b[0].get()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpp_custom_string.srctree0000644000175100001770000000302100000000000022671 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror

PYTHON setup.py build_ext --inplace
PYTHON -c "import a; a.test_convert()"

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from Cython.Compiler import PyrexTypes
PyrexTypes.cpp_string_conversions += ("MyString", "MyString2")

from distutils.core import setup

setup(
  ext_modules = cythonize("*.pyx"),
)

######## my_string.cpp ########

#include 

class MyString {
  public:
    MyString() { }
    MyString(const char* data, size_t size) : value_(data, size) { }
    const char* data() const { return value_.data(); }
    const size_t size() const { return value_.size(); }
  private:
    std::string value_;
};

class MyString2 : public MyString {
  public:
    MyString2() : MyString() { }
    MyString2(const char* data, size_t size) : MyString(data, size) { }
};

typedef MyString MyTypedefString;

######## a.pyx ########

# distutils: language = c++

cdef extern from "my_string.cpp":
  cdef cppclass MyString:
    pass

  cdef cppclass MyString2:
    pass

  ctypedef MyString2 MyTypedefString  # really a MyString

def do_convert(MyString value):
    return value

def do_convert2(MyString2 value):
    return value

def do_convert_typedef(MyTypedefString value):
    return value

def test_convert():
    assert do_convert(b"abc") == b"abc"
    assert do_convert(b"ab\0c") == b"ab\0c"

    assert do_convert2(b"abc") == b"abc"
    assert do_convert2(b"ab\0c") == b"ab\0c"

    assert do_convert_typedef(b"abc") == b"abc"
    assert do_convert_typedef(b"ab\0c") == b"ab\0c"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.3967223
Cython-3.0.8/tests/run/cpp_enums.pyx0000644000175100001770000000145200000000000020277 0ustar00runnerdocker00000000000000# tag: cpp
# mode: run, no-cpp-locals

cdef extern from *:
    """
    enum Enum1 {
        Item1,
        Item2
    };

    """
    cdef enum Enum1:
        Item1
        Item2

a = Item1
b = Item2

cdef Enum1 x, y
x = Item1
y = Item2


def compare_enums():
    """
    >>> compare_enums()
    (True, True, True, True)
    """
    return x == a, a == Item1, b == y, y == Item2


cdef extern from * namespace "Namespace1":
    """
    namespace Namespace1 {
        enum Enum2 {
            Item3,
            Item4
        };
    }
    """
    cdef enum Enum2:
        Item3
        Item4

c = Item3
d = Item4

cdef Enum2 z, w
z = Item3
w = Item4


def compare_namespace_enums():
    """
    >>> compare_namespace_enums()
    (True, True, True, True)
    """
    return z == c, c == Item3, d == w, d == Item4
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_exceptions.pyx0000644000175100001770000001254300000000000021334 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror

cdef int raise_py_error() except *:
    raise TypeError("custom")

cdef extern from "cpp_exceptions_helper.h":
    cdef int raise_int_raw "raise_int"(bint fire) except +
    cdef int raise_int_value "raise_int"(bint fire) except +ValueError
    cdef int raise_int_custom "raise_int"(bint fire) except +raise_py_error

    cdef int raise_index_raw "raise_index"(bint fire) except +
    cdef int raise_index_value "raise_index"(bint fire) except +ValueError
    cdef int raise_index_custom "raise_index"(bint fire) except +raise_py_error

    cdef void raise_domain_error() except +
    cdef void raise_ios_failure() except +
    cdef void raise_memory() except +
    cdef void raise_overflow() except +
    cdef void raise_range_error() except +
    cdef void raise_typeerror() except +
    cdef void raise_underflow() except +

    cdef raise_or_throw(bint py) except +
    cdef int raise_or_throw_int(bint py) except +*

    cdef cppclass Foo:
        int bar_raw "bar"(bint fire) except +
        int bar_value "bar"(bint fire) except +ValueError
        int bar_custom "bar"(bint fire) except +raise_py_error


def test_domain_error():
    """
    >>> test_domain_error()
    Traceback (most recent call last):
    ...
    ValueError: domain_error
    """
    raise_domain_error()

def test_ios_failure():
    """
    >>> try: test_ios_failure()
    ... except (IOError, OSError): pass
    """
    raise_ios_failure()

def test_memory():
    """
    >>> test_memory()
    Traceback (most recent call last):
    ...
    MemoryError
    """
    # Re-raise the exception without a description string because we can't
    # rely on the implementation-defined value of what() in the doctest.
    try:
        raise_memory()
    except MemoryError:
        raise MemoryError

def test_overflow():
    """
    >>> test_overflow()
    Traceback (most recent call last):
    ...
    OverflowError: overflow_error
    """
    raise_overflow()

def test_range_error():
    """
    >>> test_range_error()
    Traceback (most recent call last):
    ...
    ArithmeticError: range_error
    """
    raise_range_error()

def test_typeerror():
    """
    >>> test_typeerror()
    Traceback (most recent call last):
    ...
    TypeError
    """
    # Re-raise the exception without a description string because we can't
    # rely on the implementation-defined value of what() in the doctest.
    try:
        raise_typeerror()
    except TypeError:
        raise TypeError

def test_underflow():
    """
    >>> test_underflow()
    Traceback (most recent call last):
    ...
    ArithmeticError: underflow_error
    """
    raise_underflow()

def test_func_that_can_raise_or_throw(bint py):
    """
    >>> test_func_that_can_raise_or_throw(0)
    Traceback (most recent call last):
    ...
    RuntimeError: oopsie
    >>> test_func_that_can_raise_or_throw(1)
    Traceback (most recent call last):
    ...
    ValueError: oopsie
    """
    raise_or_throw(py)

def test_func_that_can_raise_or_throw_c_return(bint py):
    """
    >>> test_func_that_can_raise_or_throw_c_return(0)
    Traceback (most recent call last):
    ...
    RuntimeError: oopsie
    >>> test_func_that_can_raise_or_throw_c_return(1)
    Traceback (most recent call last):
    ...
    ValueError: oopsie
    """
    raise_or_throw_int(py)

def test_int_raw(bint fire):
    """
    >>> test_int_raw(False)
    >>> test_int_raw(True)
    Traceback (most recent call last):
    ...
    RuntimeError: Unknown exception
    """
    raise_int_raw(fire)

def test_int_value(bint fire):
    """
    >>> test_int_value(False)
    >>> test_int_value(True)
    Traceback (most recent call last):
    ...
    ValueError
    """
    raise_int_value(fire)

def test_int_custom(bint fire):
    """
    >>> test_int_custom(False)
    >>> test_int_custom(True)
    Traceback (most recent call last):
    ...
    TypeError: custom
    """
    raise_int_custom(fire)

def test_index_raw(bint fire):
    """
    >>> test_index_raw(False)
    >>> test_index_raw(True)
    Traceback (most recent call last):
    ...
    IndexError: c++ error
    """
    raise_index_raw(fire)

def test_index_value(bint fire):
    """
    >>> test_index_value(False)
    >>> test_index_value(True)
    Traceback (most recent call last):
    ...
    ValueError: c++ error
    """
    raise_index_value(fire)

def test_index_custom(bint fire):
    """
    >>> test_index_custom(False)
    >>> test_index_custom(True)
    Traceback (most recent call last):
    ...
    TypeError: custom
    """
    raise_index_custom(fire)

def test_cppclass_method_raw(bint fire):
    """
    >>> test_cppclass_method_raw(False)
    >>> test_cppclass_method_raw(True)
    Traceback (most recent call last):
    ...
    RuntimeError: Unknown exception
    """
    foo = new Foo()
    try:
        foo.bar_raw(fire)
    finally:
        del foo

def test_cppclass_method_value(bint fire):
    """
    >>> test_cppclass_method_value(False)
    >>> test_cppclass_method_value(True)
    Traceback (most recent call last):
    ...
    ValueError
    """
    foo = new Foo()
    try:
        foo.bar_value(fire)
    finally:
        del foo

def test_cppclass_method_custom(bint fire):
    """
    >>> test_cppclass_method_custom(False)
    >>> test_cppclass_method_custom(True)
    Traceback (most recent call last):
    ...
    TypeError: custom
    """
    foo = new Foo()
    try:
        foo.bar_custom(fire)
    finally:
        del foo
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_exceptions_helper.h0000644000175100001770000000306300000000000022277 0ustar00runnerdocker00000000000000#include 
#include 
#include 
#include 

int raise_int(int fire) {
    if (fire) {
        throw 1;
    }
    return 0;
}

int raise_index(int fire) {
    if (fire) {
        throw std::out_of_range("c++ error");
    }
    return 0;
}

class Foo {
 public:
  int bar(int fire) {
    if (fire) {
      throw 1;
    }
    return 0;
  }
};

void raise_domain_error() {
    throw std::domain_error("domain_error");
}

void raise_ios_failure() {
    throw std::ios_base::failure("iostream failure");
}

void raise_memory() {
    // std::bad_alloc can only be default constructed,
    // so we have no control over the error message
    throw std::bad_alloc();
}

void raise_overflow() {
    throw std::overflow_error("overflow_error");
}

void raise_range_error() {
    throw std::range_error("range_error");
}

struct Base { virtual ~Base() {} };
struct Derived : Base { void use() const { abort(); } };

void raise_typeerror() {
    Base foo;
    Base &bar = foo;    // prevents "dynamic_cast can never succeed" warning
    Derived &baz = dynamic_cast(bar);
    baz.use();          // not reached; prevents "unused variable" warning
}

void raise_underflow() {
    throw std::underflow_error("underflow_error");
}

PyObject *raise_or_throw(int py) {
    if (!py) {
        throw std::runtime_error("oopsie");
    }
    PyErr_SetString(PyExc_ValueError, "oopsie");
    return NULL;
}

int raise_or_throw_int(int py) {
    if (!py) {
        throw std::runtime_error("oopsie");
    }
    PyErr_SetString(PyExc_ValueError, "oopsie");
    return -1;
}
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_exceptions_nogil.pyx0000644000175100001770000001235600000000000022526 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror

cdef int raise_TypeError() except *:
    raise TypeError("custom")

cdef extern from "cpp_exceptions_nogil_helper.h" nogil:
    cdef void foo "foo"(int i) except +
    cdef void bar "foo"(int i) except +ValueError
    cdef void spam"foo"(int i) except +raise_TypeError

cdef int foo_nogil(int i) except * nogil:
    foo(i)

def test_foo_nogil():
    """
    >>> test_foo_nogil()
    """
    foo_nogil(0)
    with nogil:
        foo_nogil(0)

def test_foo():
    """
    >>> test_foo()
    """
    #
    foo(0)
    foo(0)
    with nogil:
        foo(0)
        foo(0)
    #
    try:
        with nogil:
            foo(0)
    finally:
        pass
    #
    try:
        with nogil:
            foo(0)
        with nogil:
            foo(0)
    finally:
        pass
    #
    try:
        with nogil:
            foo(0)
        with nogil:
            foo(1)
    except:
        with nogil:
            foo(0)
    finally:
        with nogil:
            foo(0)
        pass
    #
    try:
        with nogil:
            foo(0)
            foo(0)
    finally:
        pass
    #
    try:
        with nogil:
            foo(0)
            foo(1)
    except:
        with nogil:
            foo(0)
    finally:
        with nogil:
            foo(0)
        pass
    #
    try:
        with nogil:
            foo(0)
        try:
            with nogil:
                foo(1)
        except:
            with nogil:
                foo(1)
        finally:
            with nogil:
                foo(0)
            pass
    except:
        with nogil:
            foo(0)
    finally:
        with nogil:
            foo(0)
        pass
    #
    try:
        with nogil:
            foo(0)
        try:
            with nogil:
                foo(1)
        except:
            with nogil:
                foo(1)
        finally:
            with nogil:
                foo(1)
            pass
    except:
        with nogil:
            foo(0)
    finally:
        with nogil:
            foo(0)
        pass
    #

def test_bar():
    """
    >>> test_bar()
    """
    #
    bar(0)
    bar(0)
    with nogil:
        bar(0)
        bar(0)
    #
    try:
        with nogil:
            bar(0)
    finally:
        pass
    #
    try:
        with nogil:
            bar(0)
        with nogil:
            bar(0)
    finally:
        pass
    #
    try:
        with nogil:
            bar(0)
        with nogil:
            bar(1)
    except ValueError:
        with nogil:
            bar(0)
    finally:
        with nogil:
            bar(0)
        pass
    #
    try:
        with nogil:
            bar(0)
            bar(0)
    finally:
        pass
    #
    try:
        with nogil:
            bar(0)
            bar(1)
    except ValueError:
        with nogil:
            bar(0)
    finally:
        with nogil:
            bar(0)
        pass
    #
    try:
        with nogil:
            bar(0)
        try:
            with nogil:
                bar(1)
        except ValueError:
            with nogil:
                bar(1)
        finally:
            with nogil:
                bar(0)
            pass
    except ValueError:
        with nogil:
            bar(0)
    finally:
        with nogil:
            bar(0)
        pass
    #
    try:
        with nogil:
            bar(0)
        try:
            with nogil:
                bar(1)
        except ValueError:
            with nogil:
                bar(1)
        finally:
            with nogil:
                bar(1)
            pass
    except ValueError:
        with nogil:
            bar(0)
    finally:
        with nogil:
            bar(0)
        pass
    #

def test_spam():
    """
    >>> test_spam()
    """
    #
    spam(0)
    spam(0)
    with nogil:
        spam(0)
        spam(0)
    #
    try:
        with nogil:
            spam(0)
    finally:
        pass
    #
    try:
        with nogil:
            spam(0)
        with nogil:
            spam(0)
    finally:
        pass
    #
    try:
        with nogil:
            spam(0)
        with nogil:
            spam(1)
    except TypeError:
        with nogil:
            spam(0)
    finally:
        with nogil:
            spam(0)
        pass
    #
    try:
        with nogil:
            spam(0)
            spam(0)
    finally:
        pass
    #
    try:
        with nogil:
            spam(0)
            spam(1)
    except TypeError:
        with nogil:
            spam(0)
    finally:
        with nogil:
            spam(0)
        pass
    #
    try:
        with nogil:
            spam(0)
        try:
            with nogil:
                spam(1)
        except TypeError:
            with nogil:
                spam(1)
        finally:
            with nogil:
                spam(0)
            pass
    except TypeError:
        with nogil:
            spam(0)
    finally:
        with nogil:
            spam(0)
        pass
    #
    try:
        with nogil:
            spam(0)
        try:
            with nogil:
                spam(1)
        except TypeError:
            with nogil:
                spam(1)
        finally:
            with nogil:
                spam(1)
            pass
    except TypeError:
        with nogil:
            spam(0)
    finally:
        with nogil:
            spam(0)
        pass
    #
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_exceptions_nogil_helper.h0000644000175100001770000000010000000000000023454 0ustar00runnerdocker00000000000000void foo(int i) {
  if (i==0)
    return;
  else
    throw i;
}
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_exceptions_utility_code.pyx0000644000175100001770000000130600000000000024104 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, no-cpp-locals
# ticket: 3065

# This is intentionally in a file on its own. The issue was that it failed to generate utility-code
# and so putting it with the other c++ exception checks wouldn't be a useful test

cdef extern from *:
    """
    #include 

    void cppf(int raiseCpp) {
        if (raiseCpp) {
            throw std::runtime_error("cpp");
        } else {
            PyErr_SetString(PyExc_RuntimeError, "py");
        }
    }
    """
    void cppf(int) except+*


def callcppf(int raiseCpp):
    """
    >>> callcppf(0)
    py
    >>> callcppf(1)
    cpp
    """
    try:
        cppf(raiseCpp)
    except RuntimeError as e:
        print(e.args[0])
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_extern.srctree0000644000175100001770000000677700000000000021323 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp
# ticket: 1839

"""
PYTHON setup.py build_ext --inplace
PYTHON -c "from include_as_c_and_cpp import test; test()"
PYTHON -c "from include_from_c_and_cpp import test; test()"
PYTHON -c "from cdefines import test; test()"
"""

######## setup.py ########

from Cython.Build import cythonize
from Cython.Distutils.extension import Extension
from distutils.core import setup
import sys

include_as_c_and_cpp = Extension(
    "include_as_c_and_cpp",
    ["include_as_c_and_cpp.pyx", "include_as_c.cpp", "include_as_cpp.cpp"],
)
include_from_c_and_cpp = Extension(
    "include_from_c_and_cpp",
    ["include_from_c_and_cpp.pyx", "include_from_c.c", "include_from_cpp.cpp"],
)

cdefines = Extension(
    "cdefines",
    ["cdefines.pyx", "cdefines_clean.c", "cdefines_plain.cpp"],
    define_macros = [("CYTHON_EXTERN_C", 'extern "C"')],
)

ext_modules = [include_as_c_and_cpp, include_from_c_and_cpp]
if sys.platform != "win32":
    # It's very hard to get the command-line macro define to escape properly on Windows,
    # so skip it
    ext_modules.append(cdefines)

setup(
    ext_modules=cythonize(ext_modules),
)


######## include_as_c_and_cpp.pyx ########

# distutils: language = c++

from libcpp cimport vector

cdef public vector.vector[int] get_vector():
    return [1,2,3]

cdef extern from "include_as_c_and_cpp_header.h":
    cdef size_t size_vector1()
    cdef size_t size_vector2()

def test():
    assert size_vector1() == 3
    assert size_vector2() == 3

######## include_as_c_and_cpp_header.h ########

size_t size_vector1();
size_t size_vector2();

######## include_as_cpp.cpp ########

#include 
#include "include_as_c_and_cpp.h"

size_t size_vector1() {
    return get_vector().size();
}

######## include_as_c.cpp ########

#include 
extern "C" {
// #include within `extern "C"` is legal.
// We want to make sure here that Cython C++ functions are flagged as `extern "C++"`.
// Otherwise they would be interpreted with C-linkage if the header is include within a `extern "C"` block.
#include "include_as_c_and_cpp.h"
}

size_t size_vector2() {
    return get_vector().size();
}


######## include_from_c_and_cpp.pyx ########

cdef public char get_char():
    return 42

cdef extern from "include_from_c_and_cpp_header.h":
    cdef int get_int1()
    cdef int get_int2()

def test():
    assert get_int1() == 42
    assert get_int2() == 42

######## include_from_c_and_cpp_header.h ########

int get_int1();
int get_int2();

######## include_from_c.c ########

#include "include_from_c_and_cpp.h"

int get_int1() { return (int)get_char(); }

######## include_from_cpp.cpp ########

extern "C" {
#include "include_from_c_and_cpp.h"
}

extern "C" int get_int2() { return (int)get_char(); }


######## cdefines.pyx ########

# distutils: language = c++

cdef public char get_char():
    return 42

cdef extern from "cdefines_header.h":
    cdef int get_int1()
    cdef int get_int2()

def test():
    assert get_int1() == 42
    assert get_int2() == 42

######## cdefines_header.h ########

#ifdef __cplusplus
  #define cdefines_EXTERN_C extern "C"
#else
  #define cdefines_EXTERN_C
#endif

cdefines_EXTERN_C int get_int1();
int get_int2();

######## cdefines_clean.c ########

#undef CYTHON_EXTERN_C
#define CYTHON_EXTERN_C
#include "cdefines.h"

int get_int1() { return (int)get_char(); }

######## cdefines_plain.cpp ########

#include "cdefines.h"

int get_int2() { return (int)get_char(); }

######## cdefines.py ##########

# Dummy module so Windows test works
import sys
assert sys.platform == "win32"

def test():
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_forwarding_ref.pyx0000644000175100001770000000230600000000000022145 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp11, no-cpp-locals

from libcpp.utility cimport move


cdef extern from *:
    """
    #include 

    const char* f(int& x) {
        (void) x;
        return "lvalue-ref";
    }

    const char* f(int&& x) {
        (void) x;
        return "rvalue-ref";
    }

    template 
    const char* foo(T&& x)
    {
        return f(std::forward(x));
    }
    """
    const char* foo[T](T&& x)


cdef extern from *:
    """
    #include 

    template 
    const char* bar(T1 x, T1 y) {
        return "first";
    }

    template 
    const char* bar(T1&& x, T2 y, T2 z) {
        return "second";
    }

    """
    const char* bar[T1](T1 x, T1 y)
    const char* bar[T1, T2](T1&& x, T2 y, T2 z)

def test_forwarding_ref():
    """
    >>> test_forwarding_ref()
    """
    cdef int x = 1
    assert foo(x) == b"lvalue-ref"
    assert foo((1)) == b"rvalue-ref"
    assert foo(move(x)) == b"rvalue-ref"


def test_forwarding_ref_overload():
    """
    >>> test_forwarding_ref_overload()
    """
    cdef int x = 1
    cdef int y = 2
    cdef int z = 3
    assert bar(x, y) == b"first"
    assert bar(x, y, z) == b"second"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_function_lib.cpp0000644000175100001770000000170100000000000021562 0ustar00runnerdocker00000000000000#include "cpp_function_lib.h"

double add_one(double a, int b)
{
    return a + (double) b + 1.0;
}

double add_two(double a, int b)
{
    return a + (double) b + 2.0;
}


AddAnotherFunctor::AddAnotherFunctor(double to_add)
    : to_add(to_add)
{
}

double AddAnotherFunctor::operator()(double a, int b) const
{
    return a + (double) b + this->to_add;
};


FunctionKeeper::FunctionKeeper(std::function user_function)
    : my_function(user_function)
{
}

FunctionKeeper::~FunctionKeeper()
{
}

void FunctionKeeper::set_function(std::function user_function)
{
    this->my_function = user_function;
}

std::function FunctionKeeper::get_function() const
{
    return this->my_function;
}

double FunctionKeeper::call_function(double a, int b) const
{
    if (!this->my_function) {
        throw std::runtime_error("Trying to call undefined function!");
    }
    return this->my_function(a, b);
};
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_function_lib.h0000644000175100001770000000136600000000000021236 0ustar00runnerdocker00000000000000#ifndef CPP_FUNCTION_LIB_H
#define CPP_FUNCTION_LIB_H

#include 

// Functions, functor and a holder of std::function used by cpp_stl_function.pyx tests.

double add_one(double a, int b);
double add_two(double a, int b);

class AddAnotherFunctor
{
    double to_add;

public:
    AddAnotherFunctor(double to_add);
    double operator()(double a, int b) const;
};


class FunctionKeeper
{
    std::function my_function;

public:
    FunctionKeeper(std::function user_function);
    virtual ~FunctionKeeper();

    void set_function(std::function user_function);
    std::function get_function() const;

    double call_function(double a, int b) const;
};

#endif
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_function_lib.pxd0000644000175100001770000000131100000000000021570 0ustar00runnerdocker00000000000000from libcpp.functional cimport function

cdef extern from "cpp_function_lib.cpp":
    # CPP is include here so that it doesn't need to be compiled externally
    pass

cdef extern from "cpp_function_lib.h":
    double add_one(double, int)
    double add_two(double a, int b)

    cdef cppclass AddAnotherFunctor:
        AddAnotherFunctor(double to_add)
        double call "operator()"(double a, int b)

    cdef cppclass FunctionKeeper:
        FunctionKeeper(function[double(double, int) noexcept] user_function)
        void set_function(function[double(double, int) noexcept] user_function)
        function[double(double, int) noexcept] get_function()
        double call_function(double a, int b) except +
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_iterators.pyx0000644000175100001770000002240600000000000021166 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, no-cpp-locals

from libcpp.deque cimport deque
from libcpp.list cimport list as stdlist
from libcpp.map cimport map as stdmap
from libcpp.set cimport set as stdset
from libcpp.string cimport string
from libcpp.vector cimport vector
from libcpp.memory cimport shared_ptr, make_shared
from cython.operator cimport dereference as deref

cdef extern from "cpp_iterators_simple.h":
    cdef cppclass DoublePointerIter:
        DoublePointerIter(double* start, int len)
        double* begin()
        double* end()
    cdef cppclass DoublePointerIterDefaultConstructible:
        DoublePointerIterDefaultConstructible()
        DoublePointerIterDefaultConstructible(double* start, int len)
        double* begin()
        double* end()

def test_vector(py_v):
    """
    >>> test_vector([1, 2, 3])
    [1, 2, 3]
    """
    cdef vector[int] vint = py_v
    cdef vector[int] result
    with nogil:
        for item in vint:
            result.push_back(item)
    return result

def test_deque_iterator_subtraction(py_v):
    """
    >>> print(test_deque_iterator_subtraction([1, 2, 3]))
    3
    """
    cdef deque[int] dint
    for i in py_v:
        dint.push_back(i)
    cdef deque[int].iterator first = dint.begin()
    cdef deque[int].iterator last = dint.end()

    return last - first

def test_vector_iterator_subtraction(py_v):
    """
    >>> print(test_vector_iterator_subtraction([1, 2, 3]))
    3
    """
    cdef vector[int] vint = py_v
    cdef vector[int].iterator first = vint.begin()
    cdef vector[int].iterator last = vint.end()

    return last - first

def test_deque_iterator_addition(py_v):
    """
    >>> test_deque_iterator_addition([2, 4, 6])
    6
    """
    cdef deque[int] dint
    for i in py_v:
        dint.push_back(i)
    cdef deque[int].iterator first = dint.begin()

    return deref(first+2)

def test_vector_iterator_addition(py_v):
    """
    >>> test_vector_iterator_addition([2, 4, 6])
    6
    """
    cdef vector[int] vint = py_v
    cdef vector[int].iterator first = vint.begin()

    return deref(first+2)

def test_ptrs():
    """
    >>> test_ptrs()
    [1.0, 2.0, 3.0]
    """
    cdef double a = 1
    cdef double b = 2
    cdef double c = 3
    cdef vector[double*] v
    v.push_back(&a)
    v.push_back(&b)
    v.push_back(&c)
    return [item[0] for item in v]

def test_custom():
    """
    >>> test_custom()
    [1.0, 2.0, 3.0]
    """
    cdef double* values = [1, 2, 3]
    cdef DoublePointerIter* iter
    try:
        iter = new DoublePointerIter(values, 3)
        # TODO: It'd be nice to automatically dereference this in a way that
        # would not conflict with the pointer slicing iteration.
        return [x for x in iter[0]]
    finally:
        del iter

def test_custom_deref():
    """
    >>> test_custom_deref()
    [1.0, 2.0, 3.0]
    """
    cdef double* values = [1, 2, 3]
    cdef DoublePointerIter* iter
    try:
        iter = new DoublePointerIter(values, 3)
        return [x for x in deref(iter)]
    finally:
        del iter

def test_custom_genexp():
    """
    >>> test_custom_genexp()
    [1.0, 2.0, 3.0]
    """
    def to_list(g):  # function to hide the intent to avoid inlined-generator expression optimization
        return list(g)
    cdef double* values = [1, 2, 3]
    cdef DoublePointerIterDefaultConstructible* iter
    try:
        iter = new DoublePointerIterDefaultConstructible(values, 3)
        # TODO: Only needs to copy once - currently copies twice
        return to_list(x for x in iter[0])
    finally:
        del iter

def test_iteration_over_heap_vector(L):
    """
    >>> test_iteration_over_heap_vector([1,2])
    [1, 2]
    """
    cdef int i
    cdef vector[int] *vint = new vector[int]()
    try:
        for i in L:
            vint.push_back(i)
        return [ i for i in deref(vint) ]
    finally:
        del vint

def test_iteration_in_generator(vector[int] vint):
    """
    >>> list( test_iteration_in_generator([1,2]) )
    [1, 2]
    """
    for i in vint:
        yield i

def test_iteration_in_generator_reassigned():
    """
    >>> list( test_iteration_in_generator_reassigned() )
    [1]
    """
    cdef vector[int] *vint = new vector[int]()
    cdef vector[int] *orig_vint = vint
    vint.push_back(1)
    reassign = True
    try:
        for i in deref(vint):
            yield i
            if reassign:
                reassign = False
                vint = new vector[int]()
                vint.push_back(2)
    finally:
        if vint is not orig_vint:
            del vint
        del orig_vint

cdef extern from *:
    """
    std::vector make_vec1() {
        std::vector vint;
        vint.push_back(1);
        vint.push_back(2);
        return vint;
    }
    """
    cdef vector[int] make_vec1() except +

cdef vector[int] make_vec2() except *:
    return make_vec1()

cdef vector[int] make_vec3():
    try:
        return make_vec1()
    except:
        pass

def test_iteration_from_function_call():
    """
    >>> test_iteration_from_function_call()
    1
    2
    1
    2
    1
    2
    """
    for i in make_vec1():
        print(i)
    for i in make_vec2():
        print(i)
    for i in make_vec3():
        print(i)

def test_const_iterator_calculations(py_v):
    """
    >>> print(test_const_iterator_calculations([1, 2, 3]))
    [3, 3, 3, 3, True, True, False, False]
    """
    cdef deque[int] dint
    for i in py_v:
        dint.push_back(i)
    cdef deque[int].iterator first = dint.begin()
    cdef deque[int].iterator last = dint.end()
    cdef deque[int].const_iterator cfirst = first
    cdef deque[int].const_iterator clast = last

    return [
        last - first,
        last - cfirst,
        clast - first,
        clast - cfirst,
        first == cfirst,
        last == clast,
        first == clast,
        last == cfirst
    ]

cdef extern from "cpp_iterators_over_attribute_of_rvalue_support.h":
    cdef cppclass HasIterableAttribute:
        vector[int] vec
        HasIterableAttribute()
        HasIterableAttribute(vector[int])

cdef HasIterableAttribute get_object_with_iterable_attribute():
    return HasIterableAttribute()

def test_iteration_over_attribute_of_call():
    """
    >>> test_iteration_over_attribute_of_call()
    1
    2
    3
    42
    43
    44
    1
    2
    3
    """
    for i in HasIterableAttribute().vec:
        print(i)
    cdef vector[int] vec
    for i in range(42, 45):
        vec.push_back(i)
    for i in HasIterableAttribute(vec).vec:
        print(i)
    for i in get_object_with_iterable_attribute().vec:
        print(i)

cdef extern from *:
    # TODO: support make_shared[const int]
    shared_ptr[const int] make_shared_const_int "std::make_shared"(int)

def test_iteration_over_shared_const_ptr_vector(py_v):
    """
    >>> test_iteration_over_shared_const_ptr_vector([2, 4, 6])
    2
    4
    6
    """
    cdef vector[shared_ptr[const int]] s
    cdef int i
    for i in py_v:
        s.push_back(make_shared_const_int(i))

    cdef shared_ptr[const int] a
    for a in s:
        print(deref(a))

def test_iteration_over_reversed_list(py_v):
    """
    >>> test_iteration_over_reversed_list([2, 4, 6])
    6
    4
    2
    """
    cdef stdlist[int] lint
    for e in py_v:
        lint.push_back(e)
    for e in reversed(lint):
        print(e)

def test_iteration_over_reversed_map(py_v):
    """
    >>> test_iteration_over_reversed_map([(1, 10), (2, 20), (3, 30)])
    3 30
    2 20
    1 10
    """
    cdef stdmap[int, int] m
    for k, v in py_v:
        m[k] = v
    for k, v in reversed(m):
        print("%s %s" % (k, v))

def test_iteration_over_reversed_set(py_v):
    """
    >>> test_iteration_over_reversed_set([1, 2, 3])
    3
    2
    1
    """
    cdef stdset[int] s
    for e in py_v:
        s.insert(e)
    for e in reversed(s):
        print(e)

def test_iteration_over_reversed_string():
    """
    >>> test_iteration_over_reversed_string()
    n
    o
    h
    t
    y
    c
    """
    cdef string cppstr = "cython"
    for c in reversed(cppstr):
        print(chr(c))

def test_iteration_over_reversed_vector(py_v):
    """
    >>> test_iteration_over_reversed_vector([1, 2, 3])
    3
    2
    1
    """
    cdef vector[int] vint
    for e in py_v:
        vint.push_back(e)
    for e in reversed(vint):
        print(e)

def test_non_built_in_reversed_function(py_v):
    """
    >>> test_non_built_in_reversed_function([1, 3, 5])
    Non-built-in reversed called.
    5
    3
    1
    """
    def reversed(arg):
        print("Non-built-in reversed called.")
        return arg[::-1]

    cdef vector[int] vint
    for e in py_v:
        vint.push_back(e)
    for e in reversed(vint):
        print(e)


# Not strictly a C++ iterator test, but an issue with generator
# expressions and iteration from c++ const attributes so in this
# file as a related issue.  Mainly a test that it compiles.
# GH-5558
cdef extern from *:
    """
    struct ConstNumberHolder {
        const int num;

        explicit ConstNumberHolder(int num) :
            num(num)
        {}
    };
    """
    cppclass ConstNumberHolder:
        ConstNumberHolder(int num)

        const int num

def test_iteration_from_const_member(int num):
    """
    >>> tuple(test_iteration_from_const_member(5))
    (0, 1, 2, 3, 4)
    """
    num_holder = new ConstNumberHolder(num)
    try:
        return (i for i in range(num_holder.num))
    finally:
        del num_holder
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_iterators_over_attribute_of_rvalue_support.h0000644000175100001770000000036600000000000027552 0ustar00runnerdocker00000000000000#include 

class HasIterableAttribute {
public:
    std::vector vec;
    HasIterableAttribute() {
        for (int i = 1; i<=3; i++)
            vec.push_back(i);
    }
    HasIterableAttribute(std::vector vec) : vec(vec) {}
};
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_iterators_simple.h0000644000175100001770000000110500000000000022137 0ustar00runnerdocker00000000000000class DoublePointerIter {
public:
    DoublePointerIter(double* start, int len) : start_(start), len_(len) { }
    double* begin() { return start_; }
    double* end() { return start_ + len_; }
private:
    double* start_;
    int len_;
};

class DoublePointerIterDefaultConstructible: public DoublePointerIter {
    // an alternate version that is default-constructible
public:
    DoublePointerIterDefaultConstructible() :
        DoublePointerIter(0, 0)
    {}
    DoublePointerIterDefaultConstructible(double* start, int len) :
        DoublePointerIter(start, len)
    {}

};
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_locals_directive.pyx0000644000175100001770000001344000000000000022463 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp17, no-cpp-locals
# no-cpp-locals because the test is already run with it explicitly set

# cython: cpp_locals=True

cimport cython

from libcpp cimport bool as cppbool

cdef extern from *:
    r"""
    static void print_C_destructor();

    class C {
        public:
            C() = delete; // look! No default constructor
            C(int x, bool print_destructor=true) : x(x), print_destructor(print_destructor) {}
            C(C&& rhs) : x(rhs.x), print_destructor(rhs.print_destructor) {
                rhs.print_destructor = false; // moved-from instances are deleted silently
            }
            // also test that we don't require the assignment operator
            C& operator=(C&& rhs) = delete;
            C(const C& rhs) = delete;
            C& operator=(const C& rhs) = default;
            ~C() {
                if (print_destructor) print_C_destructor();
            }

            int getX() const { return x; }

        private:
            int x;
            bool print_destructor;
    };

    C make_C(int x) {
        return C(x);
    }
    """
    cdef cppclass C:
        C(int)
        C(int, cppbool)
        int getX() const
    C make_C(int) except +  # needs a temp to receive

# this function just makes sure the output from the destructor can be captured by doctest
cdef void print_C_destructor "print_C_destructor" () with gil:
    print("~C()")

def maybe_assign_infer(assign, value, do_print):
    """
    >>> maybe_assign_infer(True, 5, True)
    5
    ~C()
    >>> maybe_assign_infer(False, 0, True)
    Traceback (most recent call last):
        ...
    UnboundLocalError: local variable 'x' referenced before assignment
    >>> maybe_assign_infer(False, 0, False)  # no destructor call here
    """
    if assign:
        x = C(value)
    if do_print:
        print(x.getX())

def maybe_assign_cdef(assign, value):
    """
    >>> maybe_assign_cdef(True, 5)
    5
    ~C()
    >>> maybe_assign_cdef(False, 0)
    Traceback (most recent call last):
        ...
    UnboundLocalError: local variable 'x' referenced before assignment
    """
    cdef C x
    if assign:
        x = C(value)
    print(x.getX())

def maybe_assign_annotation(assign, value):
    """
    >>> maybe_assign_annotation(True, 5)
    5
    ~C()
    >>> maybe_assign_annotation(False, 0)
    Traceback (most recent call last):
        ...
    UnboundLocalError: local variable 'x' referenced before assignment
    """
    x: C
    if assign:
        x = C(value)
    print(x.getX())

def maybe_assign_directive1(assign, value):
    """
    >>> maybe_assign_directive1(True, 5)
    5
    ~C()
    >>> maybe_assign_directive1(False, 0)
    Traceback (most recent call last):
        ...
    UnboundLocalError: local variable 'x' referenced before assignment
    """
    x = cython.declare(C)
    if assign:
        x = C(value)
    print(x.getX())

@cython.locals(x=C)
def maybe_assign_directive2(assign, value):
    """
    >>> maybe_assign_directive2(True, 5)
    5
    ~C()
    >>> maybe_assign_directive2(False, 0)
    Traceback (most recent call last):
        ...
    UnboundLocalError: local variable 'x' referenced before assignment
    """
    if assign:
        x = C(value)
    print(x.getX())

def maybe_assign_nocheck(assign, value):
    """
    >>> maybe_assign_nocheck(True, 5)
    5
    ~C()

    # unfortunately it's quite difficult to test not assigning because there's a decent chance it'll crash
    """
    if assign:
        x = C(value)
    with cython.initializedcheck(False):
        print(x.getX())

def uses_temp(value):
    """
    needs a temp to handle the result of make_C - still doesn't use the default constructor
    >>> uses_temp(10)
    10
    ~C()
    """

    x = make_C(value)
    print(x.getX())

# c should not be optional - it isn't easy to check this, but we can at least check it compiles
cdef void has_argument(C c):
    print(c.getX())

def call_has_argument():
    """
    >>> call_has_argument()
    50
    """
    has_argument(C(50, False))

cdef class HoldsC:
    """
    >>> inst = HoldsC(True, False)
    >>> inst.getCX()
    10
    >>> access_from_function_with_different_directive(inst)
    10
    10
    >>> inst.getCX()  # it was changed in access_from_function_with_different_directive
    20
    >>> inst = HoldsC(False, False)
    >>> inst.getCX()
    Traceback (most recent call last):
        ...
    AttributeError: C++ attribute 'value' is not initialized
    >>> access_from_function_with_different_directive(inst)
    Traceback (most recent call last):
        ...
    AttributeError: C++ attribute 'value' is not initialized
    """
    cdef C value
    def __cinit__(self, initialize, print_destructor):
        if initialize:
            self.value = C(10, print_destructor)

    def getCX(self):
        return self.value.getX()

cdef acceptC(C& c):
    return c.getX()

@cython.cpp_locals(False)
def access_from_function_with_different_directive(HoldsC c):
    # doctest is in HoldsC class
    print(acceptC(c.value))  # this originally tried to pass a __Pyx_Optional as a C instance
    print(c.value.getX())
    c.value = C(20, False) # make sure that we can change it too

def dont_test_on_pypy(f):
    import sys
    if not hasattr(sys, "pypy_version_info"):
        return f

@dont_test_on_pypy  # non-deterministic destruction
def testHoldsCDestruction(initialize):
    """
    >>> testHoldsCDestruction(True)
    ~C()
    >>> testHoldsCDestruction(False)  # no destructor
    """
    x = HoldsC(initialize, True)
    del x

cdef C global_var

def initialize_global_var():
    global global_var
    global_var = C(-1, False)

def read_global_var():
    """
    >>> read_global_var()
    Traceback (most recent call last):
        ...
    NameError: C++ global 'global_var' is not initialized
    >>> initialize_global_var()
    >>> read_global_var()
    -1
    """
    print(global_var.getX())
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_locals_directive_unused.pyx0000644000175100001770000000055000000000000024044 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp17, no-cpp-locals
# no cpp_locals because this test is already run with cpp_locals explicitly set

# cython: cpp_locals=True

cdef cppclass C:
    C()

cdef class PyC:
    """
    >>> PyC() and None  # doesn't really do anything, but should run
    """
    cdef C  # this limited usage wasn't triggering the creation of utility code
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_locals_parallel.pyx0000644000175100001770000000116000000000000022275 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp17, no-cpp-locals, openmp
# no-cpp-locals because the test is already run with it explicitly set

# cython: cpp_locals=True

from cython.parallel cimport prange

cdef extern from *:
    """
    class Test {
    public:
        Test() = delete;
        Test(int v) : value(v) {}

        int get_value() const { return value; }
    private:
        int value;
    };
    """
    cdef cppclass Test:
        Test(int) nogil
        int get_value()

def test():
    """
    >>> test()
    9
    """
    cdef int i
    for i in prange(10, nogil=True):
        var = Test(i)
    print(var.get_value())
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_move.pyx0000644000175100001770000000154500000000000020121 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp11, no-cpp-locals

from libcpp cimport nullptr
from libcpp.memory cimport shared_ptr, make_shared
from libcpp.utility cimport move
from cython.operator cimport dereference

cdef extern from *:
    """
    #include 

    template const char* move_helper(T&) { return "lvalue-ref"; }
    template const char* move_helper(T&&) { return "rvalue-ref"; }
    """
    const char* move_helper[T](T)

def test_move_assignment():
    """
    >>> test_move_assignment()
    """
    cdef shared_ptr[int] p1, p2
    p1 = make_shared[int](1337)
    p2 = move(p1)
    assert p1 == nullptr
    assert dereference(p2) == 1337

def test_move_func_call():
    """
    >>> test_move_func_call()
    """
    cdef shared_ptr[int] p
    assert move_helper(p) == b'lvalue-ref'
    assert move_helper(move(p)) == b'rvalue-ref'
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_namespaces.pyx0000644000175100001770000000156200000000000021271 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror

cdef extern from "cpp_namespaces_helper.h" namespace "A":
    ctypedef int A_t
    cdef struct S:
        double x
        A_t k
    A_t A_func(A_t first, A_t)
    cdef void f(A_t)

cdef extern from "cpp_namespaces_helper.h" namespace "outer":
    int outer_value

cdef extern from "cpp_namespaces_helper.h" namespace "outer::inner":
    int inner_value

def test_function(x, y):
    """
    >>> test_function(1, 2)
    3
    >>> test_function(9, 16)
    25
    """
    return A_func(x, y)

def test_nested():
    """
    >>> test_nested()
    10
    100
    """
    print outer_value
    print inner_value

def test_typedef(A_t a):
    """
    >>> test_typedef(3)
    3
    """
    return a

def test_convert_struct(S s):
    """
    >>> py_value = {'x': 3.5, 'k': 10}
    >>> test_convert_struct(py_value) == py_value
    True
    """
    return s
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_namespaces_helper.h0000644000175100001770000000050300000000000022231 0ustar00runnerdocker00000000000000namespace outer {

    int x = 10;

    int outer_value = 10;

    namespace inner {

        int x = 100;

        int inner_value = 100;

    }

}

namespace A {

    typedef int A_t;

    struct S {
        A_t k;
        double x;
    };

    A_t A_func(A_t first, A_t second) {
        return first + second;
    }

}
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_nested_classes.pyx0000644000175100001770000001053100000000000022145 0ustar00runnerdocker00000000000000# tag: cpp, no-cpp-locals

cdef extern from "cpp_nested_classes_support.h":
    cdef cppclass A:
        cppclass B:
            int square(int)
            cppclass C:
                int cube(int)
        B* createB()
        ctypedef int my_int
        @staticmethod
        my_int negate(my_int)

    cdef cppclass TypedClass[T]:
        ctypedef T MyType
        struct MyStruct:
            T typed_value
            int int_value
        union MyUnion:
            T typed_value
            int int_value
        enum MyEnum:
            value

    cdef cppclass SpecializedTypedClass(TypedClass[double]):
        pass

cdef cppclass AA:
    cppclass BB:
        int square(int x):
            return x * x
        cppclass CC:
            int cube(int x):
                return x * x * x
    BB* createB():
        return new BB()
    ctypedef int my_int
    @staticmethod
    my_int negate(my_int x):
        return -x

cdef cppclass DD(AA):
    ctypedef int my_other_int

ctypedef A AliasA1
ctypedef AliasA1 AliasA2


def test_nested_classes():
    """
    >>> test_nested_classes()
    """
    cdef A a
    cdef A.B b
    assert b.square(3) == 9
    cdef A.B.C c
    assert c.cube(3) == 27

    cdef A.B *b_ptr = a.createB()
    assert b_ptr.square(4) == 16
    del b_ptr

def test_nested_defined_classes():
    """
    >>> test_nested_defined_classes()
    """
    cdef AA a
    cdef AA.BB b
    assert b.square(3) == 9
    cdef AA.BB.CC c
    assert c.cube(3) == 27

    cdef AA.BB *b_ptr = a.createB()
    assert b_ptr.square(4) == 16
    del b_ptr

def test_nested_inherited_classes():
    """
    >>> test_nested_inherited_classes()
    """
    cdef DD.BB b
    assert b.square(3) == 9

def test_nested_typedef(py_x):
    """
    >>> test_nested_typedef(5)
    """
    cdef A.my_int x = py_x
    assert A.negate(x) == -py_x

def test_nested_defined_typedef(py_x):
    """
    >>> test_nested_typedef(5)
    """
    cdef AA.my_int x = py_x
    assert AA.negate(x) == -py_x

def test_typedef_for_nested(py_x):
    """
    >>> test_typedef_for_nested(5)
    """
    cdef AliasA1.my_int x = py_x
    assert A.negate(x) == -py_x

def test_typedef_for_nested_deep(py_x):
    """
    >>> test_typedef_for_nested_deep(5)
    """
    cdef AliasA2.my_int x = py_x
    assert A.negate(x) == -py_x

def test_typed_nested_typedef(x):
    """
    >>> test_typed_nested_typedef(4)
    (4, 4.0)
    """
    cdef TypedClass[int].MyType ix = x
    cdef TypedClass[double].MyType dx = x
    return ix, dx

def test_nested_enum(TypedClass[double].MyEnum x):
    """
    >>> test_nested_enum(4)
    False
    """
    return x == 0

def test_nested_union(x):
    """
    >>> test_nested_union(2)
    2.0
    """
    cdef TypedClass[double].MyUnion u
    u.int_value = x
    assert u.int_value == x
    u.typed_value = x
    return u.typed_value

def test_nested_struct(x):
    """
    >>> test_nested_struct(2)
    2.0
    """
    cdef TypedClass[double].MyStruct s
    s.int_value = x
    assert s.int_value == x
    s.typed_value = x
    return s.typed_value



def test_typed_nested_sub_typedef(x):
    """
    >>> test_typed_nested_sub_typedef(4)
    4.0
    """
    cdef SpecializedTypedClass.MyType dx = x
    return dx

def test_nested_sub_enum(SpecializedTypedClass.MyEnum x):
    """
    >>> test_nested_sub_enum(4)
    False
    """
    return x == 0

def test_nested_sub_union(x):
    """
    >>> test_nested_sub_union(2)
    2.0
    """
    cdef SpecializedTypedClass.MyUnion u
    u.int_value = x
    assert u.int_value == x
    u.typed_value = x
    return u.typed_value

def test_nested_sub_struct(x):
    """
    >>> test_nested_sub_struct(2)
    2.0
    """
    cdef SpecializedTypedClass.MyStruct s
    s.int_value = x
    assert s.int_value == x
    s.typed_value = x
    return s.typed_value

cimport cpp_nested_names
cimport libcpp.string
from cython.operator cimport dereference as deref, preincrement as inc

def test_nested_names():
    """
    >>> test_nested_names()
    Nested
    NestedNested
    C
    y
    t
    h
    o
    n
    """
    cdef cpp_nested_names.Outer.Nested n = cpp_nested_names.Outer.get()
    cdef cpp_nested_names.Outer.Nested.NestedNested nn = n.get()
    print(n.get_str().decode('ascii'))
    print(nn.get_str().decode('ascii'))

    cdef libcpp.string.string s = "Cython"
    cdef libcpp.string.string.iterator i = s.begin()
    while i != s.end():
        print(chr(deref(i)))
        inc(i)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_nested_classes_support.h0000644000175100001770000000110600000000000023346 0ustar00runnerdocker00000000000000class A {
public:
  class B {
  public:
    int square(int x) { return x * x; }
    class C {
        public:
        int cube(int x) { return x * x * x; }
    };
  };
  B* createB() {
    return new B();
  }
  typedef int my_int;
  static my_int negate(my_int x) {
    return -x;
  }
};

template 
class TypedClass {
public:
  enum MyEnum {
    value = 39
  };
  union MyUnion {
    T typed_value;
    int int_value;
  };
  struct MyStruct {
    T typed_value;
    int int_value;
  };
  typedef T MyType;
};

class SpecializedTypedClass : public TypedClass {};
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_nested_names.pxd0000644000175100001770000000054700000000000021574 0ustar00runnerdocker00000000000000# cython: language_level=3

from libcpp.string cimport string

cdef extern from "cpp_nested_names_helper.h":
    cdef cppclass Outer:
        cppclass Nested:
            cppclass NestedNested:
                string get_str()

            string get_str()

            @staticmethod
            NestedNested get()

        @staticmethod
        Nested get()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_nested_names_helper.h0000644000175100001770000000057600000000000022571 0ustar00runnerdocker00000000000000#ifndef CPP_NESTED_NAMES_HELPER_H
#define CPP_NESTED_NAMES_HELPER_H

#include 

struct Outer {
  struct Nested {
    struct NestedNested {
      std::string get_str() { return "NestedNested"; }
    };

    std::string get_str() { return "Nested"; }

    static NestedNested get() { return NestedNested(); }
  };

  static Nested get() { return Outer::Nested(); }
};

#endif
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_nested_templates.pyx0000644000175100001770000000240500000000000022507 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror

from cython.operator cimport dereference as deref

cdef extern from "cpp_templates_helper.h":
    cdef cppclass Wrap[T]:
        Wrap(T)
        void set(T)
        T get()
        bint operator==(Wrap[T])

    cdef cppclass Pair[T1,T2]:
        Pair(T1,T2)
        T1 first()
        T2 second()
        bint operator==(Pair[T1,T2])
        bint operator!=(Pair[T1,T2])

def test_wrap_pair(int i, double x):
    """
    >>> test_wrap_pair(1, 1.5)
    (1, 1.5, True)
    >>> test_wrap_pair(2, 2.25)
    (2, 2.25, True)
    """
    try:
        wrap = new Wrap[Pair[int, double]](Pair[int, double](i, x))
        return wrap.get().first(), wrap.get().second(), deref(wrap) == deref(wrap)
    finally:
        del wrap

def test_wrap_pair_pair(int i, int j, double x):
    """
    >>> test_wrap_pair_pair(1, 3, 1.5)
    (1, 3, 1.5, True)
    >>> test_wrap_pair_pair(2, 5, 2.25)
    (2, 5, 2.25, True)
    """
    try:
        wrap = new Wrap[Pair[int, Pair[int, double]]](
                        Pair[int, Pair[int, double]](i,Pair[int, double](j, x)))
        return (wrap.get().first(),
                wrap.get().second().first(),
                wrap.get().second().second(),
                deref(wrap) == deref(wrap))
    finally:
        del wrap
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_nonstdint.h0000644000175100001770000000672000000000000020602 0ustar00runnerdocker00000000000000// -*- c++ -*-
#include 
template
class Integral {

  unsigned char bytes[N];

 public:
  Integral() {
    for (unsigned int i=0; i(const Integral &I) const
  { return cmp(I) > 0; }
  bool operator<=(const Integral &I) const
  { return cmp(I) <= 0; }
  bool operator>=(const Integral &I) const
  { return cmp(I) >= 0; }
  bool operator==(const Integral &I) const
  { return cmp(I) == 0; }
  bool operator!=(const Integral &I) const
  { return cmp(I) != 0; }
  
  bool operator==(const long long value) const {
    size_t len = sizeof(long long) > N ? sizeof(long long) : N;
    unsigned char* extended = new unsigned char[len];
    unsigned char* other;
    if (sizeof(long long) < N) {
        resize_signed_int((unsigned char*)&value, sizeof(value), extended, len);
        other = bytes;
    } else {
        resize_signed_int(bytes, N, extended, len);
    }
    bool res = memcmp(extended, other, len);
    delete [] extended;
    return res;
  }
  bool operator!=(const long long val) const
  { return !(*this == val); }

 private:
  static bool is_le() {
    int one = 1;
    int b = (int)*(unsigned char *)&one;
    return b ? true : false;
  }
  static unsigned int lsb() {
    return is_le() ? 0 : N-1;
  }
  static unsigned int msb() {
    return is_le() ? N-1 : 0;
  }
  int cmp(const Integral& J) const {
    const Integral& I = *this;
    unsigned char sI = I.bytes[msb()] & 0x80;
    unsigned char sJ = J.bytes[msb()] & 0x80;
    if (sI > sJ) return -1;
    if (sI < sJ) return +1;
    unsigned char bI = I.bytes[msb()] & 0x7F;
    unsigned char bJ = J.bytes[msb()] & 0x7F;
    int cmpabs = 0;
    if (bI < bJ)
      cmpabs = -1;
    else if (bI > bJ)
      cmpabs = +1;
    else {
      int incr = is_le() ? -1 : 1;
      unsigned int i = msb() + incr;
      while (i != lsb()) {
	if (I.bytes[i] < J.bytes[i])
	  { cmpabs = -1;  break; }
	if (I.bytes[i] > J.bytes[i])
	  { cmpabs = +1;  break; }
	i += incr;
      }
    }
    if (sI) return -cmpabs;
    else    return +cmpabs;
  }
  
  static void resize_signed_int(const unsigned char* src, size_t src_len, unsigned char* dst, size_t dst_len) {
    unsigned char msb;
    size_t dst_offset = 0;
    size_t src_offset = 0;
    if (is_le()) {
        dst_offset = 0;
        src_offset = 0;
        msb = ((unsigned char*) src)[src_len - 1];
        if (src_len > dst_len) {
            src_len = dst_len;
        }
    } else {
        if (dst_len > src_len) {
            dst_offset = dst_len - src_len;
        } else {
            src_offset = src_len - dst_len;
            src_len = dst_len;
        }
        msb = ((unsigned char*) src)[0];
    }
    if (msb & 0x80) {
        memset(dst, 0xFF, dst_len);
    } else {
        memset(dst, 0, dst_len);
    }
    memcpy(dst + dst_offset, src + src_offset, src_len);
  }
};

typedef Integral<3> Int24;
typedef Integral<7> Int56;
typedef Integral<11> Int88;
typedef Integral<64> Int512;
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_nonstdint.pyx0000644000175100001770000000572000000000000021172 0ustar00runnerdocker00000000000000# tag: cpp, no-cpp-locals

cdef extern from "cpp_nonstdint.h":
    ctypedef int Int24
    ctypedef int Int56
    ctypedef int Int88
    ctypedef int Int512

cdef object one = 1

# ---

INT24_MAX = (one<<(sizeof(Int24)*8-1))-one
INT24_MIN = (-INT24_MAX-one)

def test_int24(Int24 i):
    """
    >>> str(test_int24(-1))
    '-1'
    >>> str(test_int24(0))
    '0'
    >>> str(test_int24(1))
    '1'

    >>> test_int24(INT24_MAX) == INT24_MAX
    True
    >>> test_int24(INT24_MIN) == INT24_MIN
    True

    >>> test_int24(INT24_MIN-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: ...
    >>> test_int24(INT24_MAX+1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: ...

    >>> test_int24("123") #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: ...
    """
    return i

# ---

INT56_MAX = (one<<(sizeof(Int56)*8-1))-one
INT56_MIN = (-INT56_MAX-one)

def test_int56(Int56 i):
    """
    >>> str(test_int56(-1))
    '-1'
    >>> str(test_int56(0))
    '0'
    >>> str(test_int56(1))
    '1'

    >>> test_int56(INT56_MAX) == INT56_MAX
    True
    >>> test_int56(INT56_MIN) == INT56_MIN
    True

    >>> test_int56(INT56_MIN-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: ...
    >>> test_int56(INT56_MAX+1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: ...

    >>> test_int56("123") #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: ...
    """
    return i

# ---

INT88_MAX = (one<<(sizeof(Int88)*8-1))-one
INT88_MIN = (-INT88_MAX-one)

def test_int88(Int88 i):
    """
    >>> str(test_int88(-1))
    '-1'
    >>> str(test_int88(0))
    '0'
    >>> str(test_int88(1))
    '1'

    >>> test_int88(INT88_MAX) == INT88_MAX
    True
    >>> test_int88(INT88_MIN) == INT88_MIN
    True

    >>> test_int88(INT88_MIN-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: ...
    >>> test_int88(INT88_MAX+1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: ...

    >>> test_int88("123") #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: ...
    """
    return i

# ---

INT512_MAX = (one<<(sizeof(Int512)*8-1))-one
INT512_MIN = (-INT512_MAX-one)

def test_int512(Int512 i):
    """
    >>> str(test_int512(-1))
    '-1'
    >>> str(test_int512(0))
    '0'
    >>> str(test_int512(1))
    '1'

    >>> test_int512(INT512_MAX) == INT512_MAX
    True
    >>> test_int512(INT512_MIN) == INT512_MIN
    True

    >>> test_int512(INT512_MIN-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: ...
    >>> test_int512(INT512_MAX+1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: ...

    >>> test_int512("123") #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: ...
    """
    return i

# ---
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_operator_exc_handling.pyx0000644000175100001770000002133500000000000023510 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, no-cpp-locals

from cython.operator import (preincrement, predecrement,
                             postincrement, postdecrement)
from libcpp cimport bool

cdef extern from "cpp_operator_exc_handling_helper.hpp" nogil:
    cppclass wrapped_int:
        long long val
        wrapped_int()
        wrapped_int(long long val)
        wrapped_int(long long v1, long long v2) except +
        wrapped_int operator+(wrapped_int &other) except +ValueError
        wrapped_int operator+() except +RuntimeError
        wrapped_int operator-(wrapped_int &other) except +
        wrapped_int operator-() except +
        wrapped_int operator*(wrapped_int &other) except +OverflowError
        wrapped_int operator/(wrapped_int &other) except +
        wrapped_int operator%(wrapped_int &other) except +
        long long operator^(wrapped_int &other) except +
        long long operator&(wrapped_int &other) except +
        long long operator|(wrapped_int &other) except +
        wrapped_int operator~() except +
        long long operator&() except +
        long long operator==(wrapped_int &other) except +
        long long operator!=(wrapped_int &other) except +
        long long operator<(wrapped_int &other) except +
        long long operator<=(wrapped_int &other) except +
        long long operator>(wrapped_int &other) except +
        long long operator>=(wrapped_int &other) except +
        wrapped_int operator<<(long long shift) except +
        wrapped_int operator>>(long long shift) except +
        wrapped_int &operator++() except +
        wrapped_int &operator--() except +
        wrapped_int operator++(int) except +
        wrapped_int operator--(int) except +
        wrapped_int operator!() except +
        bool operator bool() except +
        wrapped_int &operator[](long long &index) except +IndexError
        long long &operator()() except +AttributeError
        wrapped_int &operator=(const wrapped_int &other) except +ArithmeticError
        wrapped_int &operator=(const long long &vao) except +

    cdef cppclass second_call_is_different:
        second_call_is_different()
        bool operator<(const second_call_is_different&) except +


def assert_raised(f, *args, **kwargs):
    err = kwargs.get('err', None)
    if err is None:
        try:
            f(*args)
            raised = False
        except:
            raised = True
    else:
        try:
            f(*args)
            raised = False
        except err:
            raised = True
    assert raised

def initialization(long long a, long long b):
    cdef wrapped_int w = wrapped_int(a, b)
    return w.val

def addition(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    cdef wrapped_int wb = wrapped_int(b)
    return (wa + wb).val

def subtraction(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    cdef wrapped_int wb = wrapped_int(b)
    return (wa - wb).val

def multiplication(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    cdef wrapped_int wb = wrapped_int(b)
    return (wa * wb).val

def division(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    cdef wrapped_int wb = wrapped_int(b)
    return (wa / wb).val

def mod(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    cdef wrapped_int wb = wrapped_int(b)
    return (wa % wb).val

def minus(long long a):
    cdef wrapped_int wa = wrapped_int(a)
    return (-wa).val

def plus(long long a):
    cdef wrapped_int wa = wrapped_int(a)
    return (+wa).val

def xor(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    cdef wrapped_int wb = wrapped_int(b)
    return wa ^ wb

def bitwise_and(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    cdef wrapped_int wb = wrapped_int(b)
    return wa & wb

def bitwise_or(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    cdef wrapped_int wb = wrapped_int(b)
    return wa | wb

def bitwise_not(long long a):
    cdef wrapped_int wa = wrapped_int(a)
    return (~a).val

def address(long long a):
    cdef wrapped_int wa = wrapped_int(a)
    return &wa

def iseq(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    cdef wrapped_int wb = wrapped_int(b)
    return wa == wb

def neq(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    cdef wrapped_int wb = wrapped_int(b)
    return wa != wb

def less(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    cdef wrapped_int wb = wrapped_int(b)
    return wa < wb

def leq(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    cdef wrapped_int wb = wrapped_int(b)
    return wa <= wb

def greater(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    cdef wrapped_int wb = wrapped_int(b)
    return wa > wb

def geq(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    cdef wrapped_int wb = wrapped_int(b)
    return wa < wb

def left_shift(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    return (wa << b).val

def right_shift(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    return (wa >> b).val

def cpp_preincrement(long long a):
    cdef wrapped_int wa = wrapped_int(a)
    return preincrement(wa).val

def cpp_predecrement(long long a):
    cdef wrapped_int wa = wrapped_int(a)
    return predecrement(wa).val

def cpp_postincrement(long long a):
    cdef wrapped_int wa = wrapped_int(a)
    return postincrement(wa).val

def cpp_postdecrement(long long a):
    cdef wrapped_int wa = wrapped_int(a)
    return postdecrement(wa).val

def negate(long long a):
    cdef wrapped_int wa = wrapped_int(a)
    return (not wa).val

def bool_cast(long long a):
    cdef wrapped_int wa = wrapped_int(a)
    if wa:
        return True
    else:
        return False

def index(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    return wa[b].val

def assign_index(long long a, long long b, long long c):
    cdef wrapped_int wa = wrapped_int(a)
    cdef wrapped_int wb = wrapped_int(b)
    wb[c] = wa
    return wb.val

def call(long long a):
    cdef wrapped_int wa = wrapped_int(a)
    return wa()

def assign_same(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    cdef wrapped_int wb = wrapped_int(b)
    wa = wb
    return wa.val

def assign_different(long long a, long long b):
    cdef wrapped_int wa = wrapped_int(a)
    wa = b
    return wa.val

def cascaded_assign(long long a, long long b, long long c):
    cdef wrapped_int wa = wrapped_int(a)
    a = b = c
    return a.val

def separate_exceptions(long long a, long long b, long long c, long long d, long long e):
    cdef:
        wrapped_int wa = wrapped_int(a)
        wrapped_int wc = wrapped_int(c)
        wrapped_int wd = wrapped_int(d)
        wrapped_int we = wrapped_int(e)
    wa[b] = (+wc) * wd + we
    return a.val

def call_temp_separation(long long a, long long b, long long c):
    cdef:
        wrapped_int wa = wrapped_int(a)
        wrapped_int wc = wrapped_int(c)
    wa[b] = wc()
    return wa.val

def test_operator_exception_handling():
    """
    >>> test_operator_exception_handling()
    """
    assert_raised(initialization, 1, 4)
    assert_raised(addition, 1, 4)
    assert_raised(subtraction, 1, 4)
    assert_raised(multiplication, 1, 4)
    assert_raised(division, 1, 4)
    assert_raised(mod, 1, 4)
    assert_raised(minus, 4)
    assert_raised(plus, 4)
    assert_raised(xor, 1, 4)
    assert_raised(address, 4)
    assert_raised(iseq, 1, 4)
    assert_raised(neq, 1, 4)
    assert_raised(left_shift, 1, 4)
    assert_raised(right_shift, 1, 4)
    assert_raised(cpp_preincrement, 4)
    assert_raised(cpp_predecrement, 4)
    assert_raised(cpp_postincrement, 4)
    assert_raised(cpp_postdecrement, 4)
    assert_raised(negate, 4)
    assert_raised(bool_cast, 4)
    assert_raised(index, 1, 4)
    assert_raised(assign_index, 1, 4, 4)
    assert_raised(call, 4)
    assert_raised(assign_same, 4, 4)
    assert_raised(assign_different, 4, 4)
    assert_raised(cascaded_assign, 4, 4, 1)
    assert_raised(cascaded_assign, 4, 1, 4)
    assert_raised(separate_exceptions, 1, 1, 1, 1, 4, err=ValueError)
    assert_raised(separate_exceptions, 1, 1, 1, 4, 1, err=OverflowError)
    assert_raised(separate_exceptions, 1, 1, 4, 1, 1, err=RuntimeError)
    assert_raised(separate_exceptions, 1, 4, 1, 1, 1, err=IndexError)
    assert_raised(separate_exceptions, 4, 1, 1, 1, 3, err=ArithmeticError)
    assert_raised(call_temp_separation, 2, 1, 4, err=AttributeError)
    assert_raised(call_temp_separation, 2, 4, 1, err=IndexError)

def test_only_single_call():
    """
    Previous version of the operator handling code called the operator twice
    (Resulting in a crash)
    >>> test_only_single_call()
    False
    """
    cdef second_call_is_different inst
    return inst

class wrapped_int {
public:
  long long val;
  wrapped_int() { val = 0; }
  wrapped_int(long long val) { this->val = val; }
  wrapped_int(long long v1, long long v2) {
    if (v2 == 4) {
      throw std::domain_error("4 isn't good for initialization!");
    }
    this->val = v1;
  }
  wrapped_int operator+(wrapped_int &other) {
    if (other.val == 4) {
      throw std::invalid_argument("tried to add 4");
    }
    return wrapped_int(this->val + other.val);
  }
  wrapped_int operator+() {
    if (this->val == 4) {
      throw std::domain_error("'4' not in valid domain.");
    }
    return *this;
  }
  wrapped_int operator-(wrapped_int &other) {
    if (other.val == 4) {
      throw std::overflow_error("Value '4' is no good.");
    }
    return *this;
  }
  wrapped_int operator-() {
    if (this->val == 4) {
      throw std::range_error("Can't take the negative of 4.");
    }
    return wrapped_int(-this->val);
  }
  wrapped_int operator*(wrapped_int &other) {
    if (other.val == 4) {
      throw std::out_of_range("Multiplying by 4 isn't going to work.");
    }
    return wrapped_int(this->val * other.val);
  }
  wrapped_int operator/(wrapped_int &other) {
    if (other.val == 4) {
      throw std::out_of_range("Multiplying by 4 isn't going to work.");
    }
    return wrapped_int(this->val / other.val);
  }
  wrapped_int operator%(wrapped_int &other) {
    if (other.val == 4) {
      throw std::out_of_range("Multiplying by 4 isn't going to work.");
    }
    return wrapped_int(this->val % other.val);
  }
  long long operator^(wrapped_int &other) {
    if (other.val == 4) {
      throw std::out_of_range("Multiplying by 4 isn't going to work.");
    }
    return this->val ^ other.val;
  }
  long long operator&(wrapped_int &other) {
    if (other.val == 4) {
      throw std::underflow_error("Can't do this with 4!");
    }
    return this->val & other.val;
  }
  long long operator|(wrapped_int &other) {
    if (other.val == 4) {
      throw std::underflow_error("Can't do this with 4!");
    }
    return this->val & other.val;
  }
  wrapped_int operator~() {
    if (this->val == 4) {
      throw std::range_error("4 is really just no good for this!");
    }
    return *this;
  }
  long long operator&() {
    if (this->val == 4) {
      throw std::out_of_range("4 cannot be located!");
    }
    return this->val;
  }
  long long operator==(wrapped_int &other) {
    if (other.val == 4) {
      throw std::invalid_argument("4 isn't logical and can't be equal to anything!");
    }
    return this->val == other.val;
  }
  long long operator!=(wrapped_int &other) {
    if (other.val == 4) {
      throw std::invalid_argument("4 isn't logical and can'd be not equal to anything either!");
    }
    return this->val != other.val;
  }
  long long operator<(wrapped_int &other) {
    if (other.val == 4) {
      throw std::invalid_argument("Can't compare with 4!");
    }
    return this->val < other.val;
  }
  long long operator<=(wrapped_int &other) {
    if (other.val == 4) {
      throw std::invalid_argument("Can't compare with 4!");
    }
    return this->val <= other.val;
  }
  long long operator>(wrapped_int &other) {
    if (other.val == 4) {
      throw std::invalid_argument("Can't compare with 4!");
    }
    return this->val > other.val;
  }
  long long operator>=(wrapped_int &other) {
    if (other.val == 4) {
      throw std::invalid_argument("Can't compare with 4!");
    }
    return this->val >= other.val;
  }
  wrapped_int operator<<(long long &shift) {
    if (shift == 4) {
      throw std::overflow_error("Shifting by 4 is just bad.");
    }
    return wrapped_int(this->val << shift);
  }
  wrapped_int operator>>(long long &shift) {
    if (shift == 4) {
      throw std::underflow_error("Shifting by 4 is just bad.");
    }
    return wrapped_int(this->val >> shift);
  }
  wrapped_int &operator++() {
    if (this->val == 4) {
      throw std::out_of_range("Can't increment 4!");
    }
    this->val += 1;
    return *this;
  }
  wrapped_int &operator--() {
    if (this->val == 4) {
      throw std::out_of_range("Can't decrement 4!");
    }
    this->val -= 1;
    return *this;
  }
  wrapped_int operator++(int) {
    if (this->val == 4) {
      throw std::out_of_range("Can't increment 4!");
    }
    wrapped_int t = *this;
    this->val += 1;
    return t;
  }
  wrapped_int operator--(int) {
    if (this->val == 4) {
      throw std::out_of_range("Can't decrement 4!");
    }
    wrapped_int t = *this;
    this->val -= 1;
    return t;
  }
  wrapped_int operator!() {
    if (this->val == 4) {
      throw std::out_of_range("Can't negate 4!");
    }
    return wrapped_int(!this->val);
  }
  operator bool() {
    if (this->val == 4) {
      throw std::invalid_argument("4 can't be cast to a boolean value!");
    }
    return (this->val != 0);
  }
  wrapped_int &operator[](long long &idx) {
    if (idx == 4) {
      throw std::invalid_argument("Index of 4 not allowed.");
    }
    return *this;
  }
  long long &operator()() {
    if (this->val == 4) {
      throw std::range_error("Can't call 4!");
    }
    return this->val;
  }
  wrapped_int &operator=(const wrapped_int &other) {
    if ((other.val == 4) && (this->val == 4)) {
      throw std::overflow_error("Can't assign 4 to 4!");
    }
    this->val = other.val;
    return *this;
  }
  wrapped_int &operator=(const long long &v) {
    if ((v == 4) && (this->val == 4)) {
      throw std::overflow_error("Can't assign 4 to 4!");
    }
    this->val = v;
    return *this;
  }
};

class second_call_is_different {
    int count;
    public:
        second_call_is_different(): count(0) {}
    bool operator<(const second_call_is_different& lhs) {
        if (count>0) {
            return true;
        }
        ++count;
        return false;
    }
};
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_operators.pyx0000644000175100001770000002635200000000000021174 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror

from __future__ import division

from cython cimport typeof

cimport cython.operator
from cython.operator cimport typeid, dereference as deref

from libc.string cimport const_char
from libcpp cimport bool


cdef out(s, result_type=None):
    print '%s [%s]' % (s.decode('ascii'), result_type)


cdef iout(int s, result_type=None):
    print '%s [%s]' % (s, result_type)


cdef extern from "cpp_operators_helper.h" nogil:
    cdef cppclass TestOps:

        const_char* operator+() except +
        const_char* operator-() except +
        const_char* operator*() except +
        const_char* operator~() except +
        const_char* operator!() except +

        # FIXME: using 'except +' here leads to wrong calls ???
        const_char* operator++()
        const_char* operator--()
        const_char* operator++(int)
        const_char* operator--(int)

        const_char* operator+(int) except +
        const_char* operator+(int,const TestOps&) except +
        const_char* operator-(int) except +
        const_char* operator-(int,const TestOps&) except +
        const_char* operator*(int) except +
        # deliberately omitted operator* to test case where only defined outside class
        const_char* operator/(int) except +
        const_char* operator/(int,const TestOps&) except +
        const_char* operator%(int) except +
        const_char* operator%(int,const TestOps&) except +

        const_char* operator|(int) except +
        const_char* operator|(int,const TestOps&) except +
        const_char* operator&(int) except +
        const_char* operator&(int,const TestOps&) except +
        const_char* operator^(int) except +
        const_char* operator^(int,const TestOps&) except +
        const_char* operator,(int) except +
        const_char* operator,(int,const TestOps&) except +

        const_char* operator<<(int) except +
        const_char* operator<<(int,const TestOps&) except +
        const_char* operator>>(int) except +
        const_char* operator>>(int,const TestOps&) except +

        # FIXME: using 'except +' here leads to invalid C++ code ???
        const_char* operator==(int)
        const_char* operator!=(int)
        const_char* operator>=(int)
        const_char* operator<=(int)
        const_char* operator>(int)
        const_char* operator<(int)

        const_char* operator[](int) except +
        const_char* operator()(int) except +

    # Defining the operator outside the class does work
    # but doesn't help when importing from pxd files
    # (they don't get imported)
    const_char* operator+(float,const TestOps&) except +
    # deliberately omitted operator- to test case where only defined in class
    const_char* operator*(float,const TestOps&) except +
    const_char* operator/(float,const TestOps&) except +
    const_char* operator%(float,const TestOps&) except +

    const_char* operator|(float,const TestOps&) except +
    const_char* operator&(float,const TestOps&) except +
    const_char* operator^(float,const TestOps&) except +
    const_char* operator,(float,const TestOps&) except +

    const_char* operator<<(float,const TestOps&) except +
    const_char* operator>>(float,const TestOps&) except +

    cdef cppclass RefTestOps:

        int& operator+() except +
        int& operator-() except +
        int& operator*() except +
        int& operator~() except +
        int& operator!() except +

        int& operator++() except +
        int& operator--() except +
        int& operator++(int) except +
        int& operator--(int) except +

        int& operator+(int) except +
        int& operator+(int,const TestOps&) except +
        int& operator-(int) except +
        int& operator-(int,const TestOps&) except +
        int& operator*(int) except +
        # deliberately omitted operator* to test case where only defined outside class
        int& operator/(int) except +
        int& operator/(int,const TestOps&) except +
        int& operator%(int) except +
        int& operator%(int,const TestOps&) except +

        int& operator|(int) except +
        int& operator|(int,const TestOps&) except +
        int& operator&(int) except +
        int& operator&(int,const TestOps&) except +
        int& operator^(int) except +
        int& operator^(int,const TestOps&) except +
        int& operator,(int) except +
        int& operator,(int,const TestOps&) except +

        int& operator<<(int) except +
        int& operator<<(int,const TestOps&) except +
        int& operator>>(int) except +
        int& operator>>(int,const TestOps&) except +

        int& operator==(int) except +
        int& operator!=(int) except +
        int& operator>=(int) except +
        int& operator<=(int) except +
        int& operator>(int) except +
        int& operator<(int) except +

        int& operator[](int) except +
        int& operator()(int) except +

    cdef cppclass TruthClass:
        TruthClass()
        TruthClass(bool)
        bool operator bool()
        bool value


cdef cppclass TruthSubClass(TruthClass):
    pass


def test_unops():
    """
    >>> test_unops()
    unary + [const_char *]
    unary - [const_char *]
    unary ~ [const_char *]
    unary * [const_char *]
    unary ! [const_char *]
    """
    cdef TestOps* t = new TestOps()
    out(+t[0], typeof(+t[0]))
    out(-t[0], typeof(-t[0]))
    out(~t[0], typeof(~t[0]))
    x = deref(t[0])
    out(x, typeof(x))
    out(not t[0], typeof(not t[0]))
    del t

def test_incdec():
    """
    >>> test_incdec()
    unary ++ [const_char *]
    unary -- [const_char *]
    post ++ [const_char *]
    post -- [const_char *]
    """
    cdef TestOps* t = new TestOps()
    a = cython.operator.preincrement(t[0])
    out(a, typeof(a))
    b = cython.operator.predecrement(t[0])
    out(b, typeof(b))
    c = cython.operator.postincrement(t[0])
    out(c, typeof(c))
    d = cython.operator.postdecrement(t[0])
    out(d, typeof(d))
    del t

def test_binop():
    """
    >>> test_binop()
    binary + [const_char *]
    binary - [const_char *]
    binary * [const_char *]
    binary / [const_char *]
    binary % [const_char *]
    binary & [const_char *]
    binary | [const_char *]
    binary ^ [const_char *]
    binary << [const_char *]
    binary >> [const_char *]
    binary COMMA [const_char *]
    """
    cdef TestOps* t = new TestOps()
    out(t[0] + 1, typeof(t[0] + 1))
    out(t[0] - 1, typeof(t[0] - 1))
    out(t[0] * 1, typeof(t[0] * 1))
    out(t[0] / 1, typeof(t[0] / 1))
    out(t[0] % 1, typeof(t[0] % 1))

    out(t[0] & 1, typeof(t[0] & 1))
    out(t[0] | 1, typeof(t[0] | 1))
    out(t[0] ^ 1, typeof(t[0] ^ 1))

    out(t[0] << 1, typeof(t[0] << 1))
    out(t[0] >> 1, typeof(t[0] >> 1))

    x = cython.operator.comma(t[0], 1)
    out(x, typeof(x))
    del t

def test_nonmember_binop():
    """
    >>> test_nonmember_binop()
    nonmember binary + [const_char *]
    nonmember binary - [const_char *]
    nonmember binary / [const_char *]
    nonmember binary % [const_char *]
    nonmember binary & [const_char *]
    nonmember binary | [const_char *]
    nonmember binary ^ [const_char *]
    nonmember binary << [const_char *]
    nonmember binary >> [const_char *]
    nonmember binary COMMA [const_char *]
    nonmember binary2 + [const_char *]
    nonmember binary2 * [const_char *]
    nonmember binary2 / [const_char *]
    nonmember binary2 % [const_char *]
    nonmember binary2 & [const_char *]
    nonmember binary2 | [const_char *]
    nonmember binary2 ^ [const_char *]
    nonmember binary2 << [const_char *]
    nonmember binary2 >> [const_char *]
    nonmember binary2 COMMA [const_char *]
    """

    cdef TestOps* t = new TestOps()
    out(1 + t[0], typeof(1 + t[0]))
    out(1 - t[0], typeof(1 - t[0]))
    # * deliberately omitted
    out(1 / t[0], typeof(1 / t[0]))
    out(1 % t[0], typeof(1 % t[0]))
    out(1 & t[0], typeof(1 & t[0]))
    out(1 | t[0], typeof(1 | t[0]))
    out(1 ^ t[0], typeof(1 ^ t[0]))
    out(1 << t[0], typeof(1 << t[0]))
    out(1 >> t[0], typeof(1 >> t[0]))

    x = cython.operator.comma(1, t[0])
    out(x, typeof(x))

    # now test float operators defined outside class
    out(1. + t[0], typeof(1. + t[0]))
    # operator - deliberately omitted
    out(1. * t[0], typeof(1. * t[0]))
    out(1. / t[0], typeof(1. / t[0]))
    out(1. % t[0], typeof(1. % t[0]))
    out(1. & t[0], typeof(1. & t[0]))
    out(1. | t[0], typeof(1. | t[0]))
    out(1. ^ t[0], typeof(1. ^ t[0]))
    out(1. << t[0], typeof(1. << t[0]))
    out(1. >> t[0], typeof(1. >> t[0]))

    # for some reason we need a cdef here - not sure this is quite right
    y = cython.operator.comma(1., t[0])
    out(y, typeof(y))
    del t

def test_cmp():
    """
    >>> test_cmp()
    binary == [const_char *]
    binary != [const_char *]
    binary >= [const_char *]
    binary > [const_char *]
    binary <= [const_char *]
    binary < [const_char *]
    """
    cdef TestOps* t = new TestOps()
    out(t[0] == 1, typeof(t[0] == 1))
    out(t[0] != 1, typeof(t[0] != 1))
    out(t[0] >= 1, typeof(t[0] >= 1))
    out(t[0] > 1, typeof(t[0] > 1))
    out(t[0] <= 1, typeof(t[0] <= 1))
    out(t[0] < 1, typeof(t[0] < 1))
    del t


def test_index_call():
    """
    >>> test_index_call()
    binary [] [const_char *]
    binary () [const_char *]
    """
    cdef TestOps* t = new TestOps()
    out(t[0][100], typeof(t[0][100]))
    out(t[0](100), typeof(t[0](100)))
    del t


def test_index_assignment():
    """
    >>> test_index_assignment()
    0 [int &]
    123 [int [&]]
    """
    cdef RefTestOps* t = new RefTestOps()
    iout(t[0][100], typeof(t[0][100]))
    t[0][99] = 123
    iout(t[0](100), typeof(t[0](100)))
    del t


def test_bool_op():
    """
    >>> test_bool_op()
    """
    cdef TruthClass yes = TruthClass(True)
    cdef TruthClass no = TruthClass(False)
    if yes:
        pass
    else:
        assert False
    if no:
        assert False

def test_bool_cond():
    """
    >>> test_bool_cond()
    """
    assert (TruthClass(False) or TruthClass(False)).value == False
    assert (TruthClass(False) or TruthClass(True)).value == True
    assert (TruthClass(True) or TruthClass(False)).value == True
    assert (TruthClass(True) or TruthClass(True)).value == True

    assert (TruthClass(False) and TruthClass(False)).value == False
    assert (TruthClass(False) and TruthClass(True)).value == False
    assert (TruthClass(True) and TruthClass(False)).value == False
    assert (TruthClass(True) and TruthClass(True)).value == True


ctypedef int* int_ptr

def test_typeid_op():
    """
    >>> test_typeid_op()
    """
    cdef TruthClass* test_1 = new TruthClass()
    cdef TruthSubClass* test_2 = new TruthSubClass()
    cdef TruthClass* test_3 =  test_2
    cdef TruthClass* test_4 =  0

    assert typeid(TruthClass).name()
    assert typeid(test_1).name()
    assert typeid(TruthClass) == typeid(deref(test_1))

    assert typeid(TruthSubClass).name()
    assert typeid(test_2).name()
    assert typeid(TruthSubClass) == typeid(deref(test_2))
    assert typeid(TruthSubClass) == typeid(deref(test_3))
    assert typeid(TruthClass) != typeid(deref(test_3))

    assert typeid(TruthClass).name()
    assert typeid(test_3).name()
    assert typeid(TruthSubClass).name()
    assert typeid(deref(test_2)).name()
    assert typeid(int_ptr).name()

    try:
        typeid(deref(test_4))
        assert False
    except TypeError:
        assert True

    del test_1, test_2
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_operators_helper.h0000644000175100001770000000474200000000000022141 0ustar00runnerdocker00000000000000#define UN_OP(op) const char* operator op () { return "unary "#op; }
#define POST_UN_OP(op) const char* operator op (int x) { x++; return "post "#op; }
#define BIN_OP(op) const char* operator op (int x) { x++; return "binary "#op; }
#define NONMEMBER_BIN_OP(op) const char* operator op (int x, const TestOps&) { x++; return "nonmember binary "#op; }
#define NONMEMBER_BIN_OP2(op) const char* operator op (double x, const TestOps&) { x++; return "nonmember binary2 "#op; }

#define COMMA ,

class TestOps {

public:

    UN_OP(-);
    UN_OP(+);
    UN_OP(*);
    UN_OP(~);
    UN_OP(!);
    UN_OP(&);

    UN_OP(++);
    UN_OP(--);
    POST_UN_OP(++);
    POST_UN_OP(--);

    BIN_OP(+);
    BIN_OP(-);
    BIN_OP(*);
    BIN_OP(/);
    BIN_OP(%);

    BIN_OP(<<);
    BIN_OP(>>);

    BIN_OP(|);
    BIN_OP(&);
    BIN_OP(^);
    BIN_OP(COMMA);

    BIN_OP(==);
    BIN_OP(!=);
    BIN_OP(<=);
    BIN_OP(<);
    BIN_OP(>=);
    BIN_OP(>);

    BIN_OP([]);
    BIN_OP(());

};

NONMEMBER_BIN_OP(+)
NONMEMBER_BIN_OP(-)
NONMEMBER_BIN_OP(*)
NONMEMBER_BIN_OP(/)
NONMEMBER_BIN_OP(%)

NONMEMBER_BIN_OP(<<)
NONMEMBER_BIN_OP(>>)

NONMEMBER_BIN_OP(|)
NONMEMBER_BIN_OP(&)
NONMEMBER_BIN_OP(^)
NONMEMBER_BIN_OP(COMMA)

NONMEMBER_BIN_OP2(+)
NONMEMBER_BIN_OP2(-)
NONMEMBER_BIN_OP2(*)
NONMEMBER_BIN_OP2(/)
NONMEMBER_BIN_OP2(%)

NONMEMBER_BIN_OP2(<<)
NONMEMBER_BIN_OP2(>>)

NONMEMBER_BIN_OP2(|)
NONMEMBER_BIN_OP2(&)
NONMEMBER_BIN_OP2(^)
NONMEMBER_BIN_OP2(COMMA)


/* RefTestOps */

#define REF_UN_OP(op) int& operator op () { return value; }
#define REF_POST_UN_OP(op) int& operator op (int x) { x++; return value; }
#define REF_BIN_OP(op) int& operator op (int x) { x++; return value; }

class RefTestOps {
    int value;

public:

    RefTestOps() { value = 0; }

    REF_UN_OP(-);
    REF_UN_OP(+);
    REF_UN_OP(*);
    REF_UN_OP(~);
    REF_UN_OP(!);
    REF_UN_OP(&);

    REF_UN_OP(++);
    REF_UN_OP(--);
    REF_POST_UN_OP(++);
    REF_POST_UN_OP(--);

    REF_BIN_OP(+);
    REF_BIN_OP(-);
    REF_BIN_OP(*);
    REF_BIN_OP(/);
    REF_BIN_OP(%);

    REF_BIN_OP(<<);
    REF_BIN_OP(>>);

    REF_BIN_OP(|);
    REF_BIN_OP(&);
    REF_BIN_OP(^);
    REF_BIN_OP(COMMA);

    REF_BIN_OP(==);
    REF_BIN_OP(!=);
    REF_BIN_OP(<=);
    REF_BIN_OP(<);
    REF_BIN_OP(>=);
    REF_BIN_OP(>);

    REF_BIN_OP([]);
    REF_BIN_OP(());
};


/* TruthClass */

class TruthClass {
public:
  TruthClass() : value(false) {}
  TruthClass(bool value) : value(value) {}
  virtual ~TruthClass() {};
  operator bool() { return value; }
  bool value;
};
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_scoped_enums.pyx0000644000175100001770000000435700000000000021643 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp11

from libcpp.limits cimport numeric_limits

cdef extern from *:
    """
    enum class Enum1 {
        Item1,
        Item2
    };
    """
    cdef enum class Enum1:
        Item1
        Item2


cdef extern from * namespace "Namespace1":
    """
    namespace Namespace1 {
        enum class Enum2 {
            Item1,
            Item2
        };
    }
    """
    cdef enum class Enum2:
        Item1
        Item2


cdef enum class Enum3(int):
    a = 1
    b = 2


cdef extern from *:
    """
    enum class sorted
    {
        a = 1,
        b = 0
    };
    """
    cdef enum class Enum4 "sorted":
        a
        b


cdef extern from *:
    """
    #include 

    enum class LongIntEnum : long int {
        val = std::numeric_limits::max(),
    };
    """
    enum class LongIntEnum(long int):
        val


def test_compare_enums():
    """
    >>> test_compare_enums()
    (True, True, False, False)
    """
    cdef Enum1 x, y
    x = Enum1.Item1
    y = Enum1.Item2

    return (
        x == Enum1.Item1,
        y == Enum1.Item2,
        x == Enum1.Item2,
        y == Enum1.Item1
    )

        
def test_compare_namespace_enums():
    """
    >>> test_compare_enums()
    (True, True, False, False)
    """
    cdef Enum2 z, w
    
    z = Enum2.Item1
    w = Enum2.Item2

    return (
        z == Enum2.Item1,
        w == Enum2.Item2,
        z == Enum2.Item2,
        w == Enum2.Item1
    )


def test_coerce_to_from_py_value(object i):
    """
    >>> test_coerce_to_from_py_value(1)
    (True, False)

    >>> test_coerce_to_from_py_value(2)
    (False, True)

    >>> test_coerce_to_from_py_value(3)
    (False, False)

    >>> test_coerce_to_from_py_value(11111111111111111111111111111111111111111111)
    Traceback (most recent call last):
    OverflowError: Python int too large to convert to C long
    """
    cdef Enum3 x = i
    y = Enum3.b

    return (
        x == Enum3.a,
        y == int(i)
    )


def test_reserved_cname():
    """
    >>> test_reserved_cname()
    True
    """
    cdef Enum4 x = Enum4.a
    return Enum4.a == int(1)


def test_large_enum():
    """
    >>> test_large_enum()
    True
    """
    long_max = int(numeric_limits[long].max())
    return LongIntEnum.val == long_max
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_smart_ptr.pyx0000644000175100001770000000600600000000000021163 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp14, no-cpp-locals

from libcpp.memory cimport unique_ptr, shared_ptr, default_delete, dynamic_pointer_cast, make_unique
from libcpp cimport nullptr

cdef extern from "cpp_smart_ptr_helper.h":
    cdef cppclass CountAllocDealloc:
        CountAllocDealloc(int*, int*)

    cdef cppclass FreePtr[T]:
        pass

    cdef cppclass RaiseOnConstruct:
        pass


ctypedef const CountAllocDealloc const_CountAllocDealloc


def test_unique_ptr():
    """
    >>> test_unique_ptr()
    """
    cdef int alloc_count = 0, dealloc_count = 0
    cdef unique_ptr[CountAllocDealloc] x_ptr
    x_ptr.reset(new CountAllocDealloc(&alloc_count, &dealloc_count))
    assert alloc_count == 1
    x_ptr.reset()
    assert alloc_count == 1
    assert dealloc_count == 1

    ##Repeat the above test with an explicit default_delete type
    alloc_count = 0
    dealloc_count = 0
    cdef unique_ptr[CountAllocDealloc,default_delete[CountAllocDealloc]] x_ptr2
    x_ptr2.reset(new CountAllocDealloc(&alloc_count, &dealloc_count))
    assert alloc_count == 1
    x_ptr2.reset()
    assert alloc_count == 1
    assert dealloc_count == 1

    alloc_count = 0
    dealloc_count = 0
    cdef unique_ptr[CountAllocDealloc,FreePtr[CountAllocDealloc]] x_ptr3
    x_ptr3.reset(new CountAllocDealloc(&alloc_count, &dealloc_count))
    assert x_ptr3.get() != nullptr;
    x_ptr3.reset()
    assert x_ptr3.get() == nullptr;

    # Test that make_unique works
    cdef unique_ptr[int] x_ptr4
    x_ptr4 = make_unique[int](5)
    assert(x_ptr4) != nullptr
    cdef unique_ptr[RaiseOnConstruct] x_ptr5
    try:
        x_ptr5 = make_unique[RaiseOnConstruct]()
    except RuntimeError:
        pass  # good - this is what we expect


def test_const_shared_ptr():
    """
    >>> test_const_shared_ptr()
    """
    cdef int alloc_count = 0, dealloc_count = 0
    cdef shared_ptr[const CountAllocDealloc] ptr = shared_ptr[const_CountAllocDealloc](
        new CountAllocDealloc(&alloc_count, &dealloc_count))
    assert alloc_count == 1
    assert dealloc_count == 0

    cdef shared_ptr[const CountAllocDealloc] ptr2 = ptr
    assert alloc_count == 1
    assert dealloc_count == 0

    ptr.reset()
    assert alloc_count == 1
    assert dealloc_count == 0

    ptr2.reset()
    assert alloc_count == 1
    assert dealloc_count == 1


cdef cppclass A:
    void some_method():  # Force this to be a polymorphic class for dynamic cast.
        pass

cdef cppclass B(A):
    pass

cdef cppclass C(B):
    pass

cdef shared_ptr[A] holding_subclass = shared_ptr[A](new C())


def test_assignment_to_base_class():
    """
    >>> test_assignment_to_base_class()
    """
    cdef shared_ptr[C] derived = shared_ptr[C](new C())
    cdef shared_ptr[A] base = derived


def test_dynamic_pointer_cast():
    """
    >>> test_dynamic_pointer_cast()
    """
    cdef shared_ptr[B] b = shared_ptr[B](new B())
    cdef shared_ptr[A] a = dynamic_pointer_cast[A, B](b)
    assert a.get() == b.get()

    a = shared_ptr[A](new A())
    b = dynamic_pointer_cast[B, A](a)
    assert b.get() == NULL
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_smart_ptr_helper.h0000644000175100001770000000113500000000000022127 0ustar00runnerdocker00000000000000#include 

class CountAllocDealloc {
  public:
      CountAllocDealloc(int* alloc_count, int* dealloc_count)
          : _alloc_count(alloc_count), _dealloc_count(dealloc_count) {
        (*_alloc_count)++;
      }
      ~CountAllocDealloc() {
        (*_dealloc_count)++;
      }
  private:
    int* _alloc_count;
    int* _dealloc_count;
};

template
struct FreePtr {
  void operator()( T * t )
  {
    if(t != nullptr) {
      delete t;
      t=nullptr;
    }
  }
};

class RaiseOnConstruct {
  public:
    RaiseOnConstruct() {
      throw std::runtime_error("Oh no!");
    }
};
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_static_method_overload.pyx0000644000175100001770000000163600000000000023676 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, no-cpp-locals

cdef extern from *:
    """
    struct Foo
    {

      static const char* bar(int x, int y) {
        return "second";
      }

      static const char* bar(int x) {
        return "first";
      }

      const char* baz(int x, int y) {
        return "second";
      }

      const char* baz(int x) {
        return "first";
      }
    };
    """
    cppclass Foo:
        @staticmethod
        const char* bar(int x)

        @staticmethod
        const char* bar(int x, int y)

        const char* baz(int x)
        const char* baz(int x, int y)

def test_normal_method_overload():
    """
    >>> test_normal_method_overload()
    """
    cdef Foo f
    assert f.baz(1) == b"first"
    assert f.baz(1, 2) == b"second"

def test_static_method_overload():
    """
    >>> test_static_method_overload()
    """
    assert Foo.bar(1) == b"first"
    assert Foo.bar(1, 2) == b"second"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl.pyx0000644000175100001770000000272500000000000017756 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror

cdef extern from "vector" namespace "std":

    cdef cppclass vector[T]:

        T at(int)
        void push_back(T t)
        void assign(int, T)
        void clear()
        int size()

        cppclass iterator:
            T operator*()
            iterator operator++()
            bint operator==(iterator)
            bint operator!=(iterator)

        iterator end()
        iterator begin()

from cython.operator cimport dereference as deref, preincrement as inc

def test_vector(L):
    """
    >>> test_vector([1,10,100])
    1
    10
    100
    """
    v = new vector[int]()
    for a in L:
        v.push_back(a)
    cdef int i
    for i in range(len(L)):
        print v.at(i)
    del v

ctypedef int my_int
def test_vector_typedef(L):
    """
    >>> test_vector_typedef([1, 2, 3])
    [1, 2, 3]
    """
    cdef vector[my_int] v = L
    cdef vector[int] vv = v
    return vv

def test_vector_iterator(L):
    """
    >>> test_vector([11, 37, 389, 5077])
    11
    37
    389
    5077
    """
    v = new vector[int]()
    for a in L:
        v.push_back(a)
    cdef vector[int].iterator iter = v.begin()
    while iter != v.end():
        print deref(iter)
        inc(iter)
    del v

cdef class VectorWrapper:
    """
    >>> VectorWrapper(1, .5, .25, .125)
    [1.0, 0.5, 0.25, 0.125]
    """
    cdef vector[double] vector
    def __init__(self, *args):
        self.vector = args
    def __repr__(self):
        return repr(self.vector)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_algo_comparison_ops.pyx0000644000175100001770000000373100000000000024071 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp17, no-cpp-locals

from libcpp cimport bool
from libcpp.algorithm cimport equal, lexicographical_compare
from libcpp.vector cimport vector

cdef bool compare(int a, int b):
    return a == b

cdef bool less_than(char a, char b):
    return a < b

def test_equal(vector[int] v1, vector[int] v2):
    """
    Test equal.

    >>> test_equal([1, 2, 3, 4], [1, 2, 3, 4])
    True
    >>> test_equal([1, 2, 3, 4], [9, 2, 3, 4])
    False
    """
    return equal(v1.begin(), v1.end(), v2.begin())

def test_equal_with_bin_pred(vector[int] v1, vector[int] v2):
    """
    Test equal with binary predicate.

    >>> test_equal_with_bin_pred([1, 2, 3, 4], [1, 2, 3, 4])
    True
    >>> test_equal_with_bin_pred([1, 2, 3, 4], [9, 2, 3, 4])
    False
    """
    return equal(v1.begin(), v1.end(), v2.begin(), compare)

def test_equal_with_second_range_and_bin_pred(vector[int] v1, vector[int] v2):
    """
    Test equal with second range and binary predicate.

    >>> test_equal_with_second_range_and_bin_pred([1, 2, 3, 4], [1, 2, 3, 4])
    True
    >>> test_equal_with_second_range_and_bin_pred([1, 2, 3, 4], [9, 2, 3, 4])
    False
    """
    return equal(v1.begin(), v1.end(), v2.begin(), v2.end(), compare)

def test_lexicographical_compare(vector[int] v1, vector[int] v2):
    """
    Test lexicographical_compare.

    >>> test_lexicographical_compare([1, 2, 3, 4], [5, 6, 7, 8])
    True
    >>> test_lexicographical_compare([1, 2, 3, 4], [1, 1, 3, 4])
    False
    """
    return lexicographical_compare(v1.begin(), v1.end(), v2.begin(), v2.end())

def test_lexicographical_compare_with_bin_pred(vector[int] v1, vector[int] v2):
    """
    Test lexicographical_compare with binary predicate

    >>> test_lexicographical_compare_with_bin_pred([1, 2, 3, 4], [5, 6, 7, 8])
    True
    >>> test_lexicographical_compare_with_bin_pred([1, 2, 3, 4], [1, 1, 3, 4])
    False
    """
    return lexicographical_compare(v1.begin(), v1.end(), v2.begin(), v2.end(), less_than)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_algo_execpolicies.pyx0000644000175100001770000000234400000000000023511 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp17, cppexecpolicies, no-cpp-locals

from libcpp.algorithm cimport is_sorted, sort, stable_sort, nth_element, all_of, count, copy
from libcpp.execution cimport seq
from libcpp.vector cimport vector
from libcpp.functional cimport greater
from libcpp.iterator cimport back_inserter
from libcpp cimport bool


def is_sorted_ints(vector[int] values):
    """
    Test is_sorted.

    >>> is_sorted_ints([3, 1, 4, 1, 5])
    False
    >>> is_sorted_ints([1, 1, 3, 4, 5])
    True
    """
    return is_sorted(seq, values.begin(), values.end())


def sort_ints_reverse(vector[int] values):
    """Test sort using a standard library comparison function object.

    >>> sort_ints_reverse([5, 7, 4, 2, 8, 6, 1, 9, 0, 3])
    [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    """
    sort(seq, values.begin(), values.end(), greater[int]())
    return values


def count_ones(vector[int] values):
    """
    Test count.

    >>> count_ones([1, 2, 1, 2])
    2
    """
    return count(seq, values.begin(), values.end(), 1)


def copy_int(vector[int] values):
    """
    Test copy.

    >>> copy_int(range(5))
    [0, 1, 2, 3, 4]
    """
    cdef vector[int] out
    copy(seq, values.begin(), values.end(), back_inserter(out))
    return out
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_algo_minmax_ops.pyx0000644000175100001770000000677000000000000023216 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp17, cppexecpolicies

from cython.operator cimport dereference as deref

from libcpp cimport bool
from libcpp.algorithm cimport (min_element, max_element, minmax, minmax_element, 
                               clamp)
from libcpp.vector cimport vector
from libcpp.pair cimport pair
from libcpp.execution cimport seq


cdef bool less(int a, int b):
    return a < b

def test_min_element(vector[int] v):
    """
    Test min_element.

    >>> test_min_element([0, 1, 2, 3, 4, 5])
    0
    """
    cdef vector[int].iterator it = min_element(v.begin(), v.end())
    return deref(it)

def test_min_element_with_pred(vector[int] v):
    """
    Test min_element with binary predicate.

    >>> test_min_element_with_pred([0, 1, 2, 3, 4, 5])
    0
    """
    cdef vector[int].iterator it = min_element(v.begin(), v.end(), less)
    return deref(it)

def test_min_element_with_exec(vector[int] v):
    """
    Test min_element with execution policy.

    >>> test_min_element_with_exec([0, 1, 2, 3, 4, 5])
    0
    """
    cdef vector[int].iterator it = min_element(seq, v.begin(), v.end())
    return deref(it)

def test_max_element(vector[int] v):
    """
    Test max_element.

    >>> test_max_element([0, 1, 2, 3, 4, 5])
    5
    """
    cdef vector[int].iterator it = max_element(v.begin(), v.end())
    return deref(it)

def test_max_element_with_pred(vector[int] v):
    """
    Test max_element with binary predicate.

    >>> test_max_element_with_pred([0, 1, 2, 3, 4, 5])
    5
    """
    cdef vector[int].iterator it = max_element(v.begin(), v.end(), less)
    return deref(it)

def test_max_element_with_exec(vector[int] v):
    """
    Test max_element with execution policy.

    >>> test_max_element_with_exec([0, 1, 2, 3, 4, 5])
    5
    """
    cdef vector[int].iterator it = max_element(seq, v.begin(), v.end())
    return deref(it)

def test_minmax(int a, int b):
    """
    Test minmax.

    >>> test_minmax(10, 20)
    [10, 20]
    """
    cdef pair[int, int] p = minmax(a, b)
    return [p.first, p.second]

def test_minmax_with_pred(int a, int b):
    """
    Test minmax with binary predicate.

    >>> test_minmax_with_pred(10, 20)
    [10, 20]
    """
    cdef pair[int, int] p = minmax(a, b, less)
    return [p.first, p.second]

def test_minmax_element(vector[int] v):
    """
    Test minmax_element.

    >>> test_minmax_element([0, 1, 2, 3, 4, 5])
    [0, 5]
    """
    cdef pair[vector[int].iterator, vector[int].iterator] p = minmax_element(v.begin(), v.end())
    return [deref(p.first), deref(p.second)]

def test_minmax_element_with_pred(vector[int] v):
    """
    Test minmax_element with binary predicate.

    >>> test_minmax_element_with_pred([0, 1, 2, 3, 4, 5])
    [0, 5]
    """
    cdef pair[vector[int].iterator, vector[int].iterator] p = minmax_element(v.begin(), v.end(), less)
    return [deref(p.first), deref(p.second)]

def test_minmax_element_with_exec(vector[int] v):
    """
    Test minmax_element with execution policy.

    >>> test_minmax_element_with_exec([0, 1, 2, 3, 4, 5])
    [0, 5]
    """
    cdef pair[vector[int].iterator, vector[int].iterator] p = minmax_element(seq, v.begin(), v.end())
    return [deref(p.first), deref(p.second)]

def test_clamp(int v, int lo, int hi):
    """
    Test clamp.

    >>> test_clamp(-129, -128, 255)
    -128
    """
    return clamp(v, lo, hi)

def test_clamp_with_pred(int v, int lo, int hi):
    """
    Test clamp with binary predicate

    >>> test_clamp_with_pred(-129, -128, 255)
    -128
    """
    return clamp(v, lo, hi, less)././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_algo_modifying_sequence_ops.pyx0000644000175100001770000002414300000000000025574 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp11, no-cpp-locals

from __future__ import print_function

from cython.operator cimport dereference as deref
from cython.operator cimport preincrement, postincrement
from libcpp cimport bool
from libcpp.algorithm cimport copy, copy_if, copy_n, copy_backward, move, move_backward, fill, fill_n, transform
from libcpp.algorithm cimport generate, generate_n, remove, remove_if, remove_copy, remove_copy_if, replace, replace_if
from libcpp.algorithm cimport replace_copy, replace_copy_if, swap, swap_ranges, iter_swap, reverse, reverse_copy
from libcpp.algorithm cimport rotate, rotate_copy, unique, unique_copy
from libcpp.algorithm cimport sort, upper_bound, min_element, max_element
from libcpp.iterator cimport back_inserter
from libcpp.string cimport string
from libcpp.vector cimport vector


def copy_int(vector[int] values):
    """
    Test copy.

    >>> copy_int(range(5))
    [0, 1, 2, 3, 4]
    """
    cdef vector[int] out
    copy(values.begin(), values.end(), back_inserter(out))
    return out


cdef bool is_odd(int i):
    return i % 2


def copy_int_if_odd(vector[int] values):
    """
    Test copy_if.

    >>> copy_int_if_odd(range(5))
    [1, 3]
    """
    cdef vector[int] out
    copy_if(values.begin(), values.end(), back_inserter(out), is_odd)
    return out


def copy_int_n(vector[int] values, int count):
    """
    Test copy_n.

    >>> copy_int_n(range(5), 2)
    [0, 1]
    """
    cdef vector[int] out
    copy_n(values.begin(), count, back_inserter(out))
    return out


def copy_int_backward(vector[int] values):
    """
    Test copy_backward.

    >>> copy_int_backward(range(5))
    [0, 0, 0, 0, 1, 2, 3, 4]
    """
    out = vector[int](values.size() + 3)
    copy_backward(values.begin(), values.end(), out.end())
    return out


def move_int(vector[int] values):
    """
    Test move.

    >>> move_int(range(5))
    [0, 1, 2, 3, 4]
    """
    cdef vector[int] out
    move(values.begin(), values.end(), back_inserter(out))
    return out


def move_int_backward(vector[int] values):
    """
    Test move_backward.

    >>> move_int_backward(range(5))
    [0, 0, 0, 0, 1, 2, 3, 4]
    """
    out = vector[int](values.size() + 3)
    move_backward(values.begin(), values.end(), out.end())
    return out


def fill_int(vector[int] array, int value):
    """
    Test fill.

    >>> fill_int(range(5), -1)
    [-1, -1, -1, -1, -1]
    """
    fill(array.begin(), array.end(), value)
    return array


def fill_int_n(vector[int] array, int count, int value):
    """
    Test fill_n.

    >>> fill_int_n(range(5), 3, -1)
    [-1, -1, -1, 3, 4]
    """
    fill_n(array.begin(), count, value)
    return array


cdef int to_ord(unsigned char c):
    return c


def string_to_ord(string s):
    """
    Test transform (unary version).

    >> string_to_ord(b"HELLO")
    [72, 69, 76, 76, 79]
    """
    cdef vector[int] ordinals
    transform(s.begin(), s.end(), back_inserter(ordinals), to_ord)
    return ordinals


cdef int add_ints(int lhs, int rhs):
    return lhs + rhs


def add_int_vectors(vector[int] lhs, vector[int] rhs):
    """
    Test transform (binary version).

    >>> add_int_vectors([1, 2, 3], [4, 5, 6])
    [5, 7, 9]
    """
    transform(lhs.begin(), lhs.end(), rhs.begin(), lhs.begin(), add_ints)
    return lhs


cdef int i = 0
cdef int generator():
    return postincrement(i)


def generate_ints(int count):
    """
    Test generate.

    >> generate_ints(5)
    [0, 1, 2, 3, 4]
    """
    out = vector[int](count)
    generate(out.begin(), out.end(), generator)
    return out


cdef int j = 0
cdef int generator2():
    return postincrement(j)


def generate_n_ints(int count):
    """
    Test generate_n.

    >> generate_n_ints(5)
    [0, 1, 2, 3, 4, 0, 0, 0]
    """
    out = vector[int](count + 3)
    generate_n(out.begin(), count, generator2)
    return out


def remove_spaces(string s):
    """
    Test remove.

    >>> print(remove_spaces(b"Text with some   spaces").decode("ascii"))
    Textwithsomespaces
    """
    s.erase(remove(s.begin(), s.end(), ord(" ")), s.end())
    return s


cdef bool is_whitespace(unsigned char c) except -1:
    # std::isspace from 
    return chr(c) in " \f\n\r\t\v"


def remove_whitespace(string s):
    r"""
    Test remove_if.

    >>> print(remove_whitespace(b"Text\n with\tsome \t  whitespaces\n\n").decode("ascii"))
    Textwithsomewhitespaces
    """
    s.erase(remove_if(s.begin(), s.end(), &is_whitespace), s.end())
    return s


def remove_spaces2(string s):
    """
    Test remove_copy.

    >>> print(remove_spaces2(b"Text with some   spaces").decode("ascii"))
    Textwithsomespaces
    """
    cdef string out
    remove_copy(s.begin(), s.end(), back_inserter(out), ord(" "))
    return out


def remove_whitespace2(string s):
    r"""
    Test remove_copy_if.

    >>> print(remove_whitespace2(b"Text\n with\tsome \t  whitespaces\n\n").decode("ascii"))
    Textwithsomewhitespaces
    """
    cdef string out
    remove_copy_if(s.begin(), s.end(), back_inserter(out), &is_whitespace)
    return out


def replace_ints(vector[int] values, int old, int new):
    """
    Test replace.

    >>> replace_ints([5, 7, 4, 2, 8, 6, 1, 9, 0, 3], 8, 88)
    [5, 7, 4, 2, 88, 6, 1, 9, 0, 3]
    """
    replace(values.begin(), values.end(), old, new)
    return values


cdef bool less_than_five(int i):
    return i < 5


def replace_ints_less_than_five(vector[int] values, int new):
    """
    Test replace_if (using cppreference example that doesn't translate well).

    >>> replace_ints_less_than_five([5, 7, 4, 2, 88, 6, 1, 9, 0, 3], 55)
    [5, 7, 55, 55, 88, 6, 55, 9, 55, 55]
    """
    replace_if(values.begin(), values.end(), less_than_five, new)
    return values


def replace_ints2(vector[int] values, int old, int new):
    """
    Test replace_copy.

    >>> replace_ints2([5, 7, 4, 2, 8, 6, 1, 9, 0, 3], 8, 88)
    [5, 7, 4, 2, 88, 6, 1, 9, 0, 3]
    """
    cdef vector[int] out
    replace_copy(values.begin(), values.end(), back_inserter(out), old, new)
    return out


def replace_ints_less_than_five2(vector[int] values, int new):
    """
    Test replace_copy_if (using cppreference example that doesn't translate well).

    >>> replace_ints_less_than_five2([5, 7, 4, 2, 88, 6, 1, 9, 0, 3], 55)
    [5, 7, 55, 55, 88, 6, 55, 9, 55, 55]
    """
    cdef vector[int] out
    replace_copy_if(values.begin(), values.end(), back_inserter(out), less_than_five, new)
    return out


def test_swap_ints():
    """
    >>> test_swap_ints()
    5 3
    3 5
    """
    cdef int a = 5, b = 3
    print(a, b)
    swap(a, b)
    print(a, b)


def test_swap_vectors():
    """
    >>> test_swap_vectors()
    [1, 2, 3] [4, 5, 6]
    [4, 5, 6] [1, 2, 3]
    """
    cdef vector[int] a = [1, 2, 3], b = [4, 5, 6]
    print(a, b)
    swap(a, b)
    print(a, b)


def test_swap_ranges():
    """
    >>> test_swap_ranges()
    [1, 2, 3] [4, 5, 6]
    [4, 5, 6] [1, 2, 3]
    """
    cdef vector[int] a = [1, 2, 3], b = [4, 5, 6]
    print(a, b)
    swap_ranges(a.begin(), a.end(), b.begin())
    print(a, b)


def selection_sort(vector[int] values, reversed=False):
    """
    Test iter_swap using cppreference example. Extra "reversed argument tests max_element

    >>> selection_sort([-7, 6, 2, 4, -1, 6, -9, -1, 2, -5, 10, -9, -5, -3, -5, -3, 6, 6, 1, 8])
    [-9, -9, -7, -5, -5, -5, -3, -3, -1, -1, 1, 2, 2, 4, 6, 6, 6, 6, 8, 10]
    >>> selection_sort([-7, 6, 2, 4, -1, 6, -9, -1, 2, -5, 10, -9, -5, -3, -5, -3, 6, 6, 1, 8], reversed=True)
    [10, 8, 6, 6, 6, 6, 4, 2, 2, 1, -1, -1, -3, -3, -5, -5, -5, -7, -9, -9]
    """
    i = values.begin()
    end = values.end()
    while i < end:
        iter_swap(i, min_element(i, end) if not reversed else max_element(i,end))
        preincrement(i)
    return values


def reverse_ints(vector[int] values):
    """
    Test reverse.

    >>> reverse_ints([1, 2, 3])
    [3, 2, 1]
    """
    reverse(values.begin(), values.end())
    return values


def reverse_ints2(vector[int] values):
    """
    Test reverse_copy.

    >>> reverse_ints2([1, 2, 3])
    [3, 2, 1]
    """
    cdef vector[int] out
    reverse_copy(values.begin(), values.end(), back_inserter(out))
    return out


def insertion_sort(vector[int] values):
    """
    Test rotate using cppreference example.

    >>> insertion_sort([2, 4, 2, 0, 5, 10, 7, 3, 7, 1])
    [0, 1, 2, 2, 3, 4, 5, 7, 7, 10]
    """
    i = values.begin()
    while i < values.end():
        rotate(upper_bound(values.begin(), i, deref(i)), i, i + 1)
        preincrement(i)
    return values


def rotate_ints_about_middle(vector[int] values):
    """
    Test rotate_copy.

    >>> rotate_ints_about_middle([1, 2, 3, 4, 5])
    [3, 4, 5, 1, 2]
    """
    cdef vector[int] out
    cdef vector[int].iterator pivot = values.begin() + values.size()/2
    rotate_copy(values.begin(), pivot, values.end(), back_inserter(out))
    return out


def unique_ints(vector[int] values):
    """
    Test unique.

    >>> unique_ints([1, 2, 3, 1, 2, 3, 3, 4, 5, 4, 5, 6, 7])
    [1, 2, 3, 4, 5, 6, 7]
    """
    sort(values.begin(), values.end())
    values.erase(unique(values.begin(), values.end()), values.end())
    return values


cdef bool both_space(unsigned char lhs, unsigned char rhs):
    return lhs == rhs == ord(' ')


def collapse_spaces(string text):
    """
    Test unique (predicate version) using cppreference example for unique_copy.

    >>> print(collapse_spaces(b"The      string    with many       spaces!").decode("ascii"))
    The string with many spaces!
    """
    last = unique(text.begin(), text.end(), &both_space)
    text.erase(last, text.end())
    return text


def unique_ints2(vector[int] values):
    """
    Test unique_copy.

    >>> unique_ints2([1, 2, 3, 1, 2, 3, 3, 4, 5, 4, 5, 6, 7])
    [1, 2, 3, 4, 5, 6, 7]
    """
    cdef vector[int] out
    sort(values.begin(), values.end())
    unique_copy(values.begin(), values.end(), back_inserter(out))
    return out


def collapse_spaces2(string text):
    """
    Test unique_copy (predicate version) using cppreference example.

    >>> print(collapse_spaces2(b"The      string    with many       spaces!").decode("ascii"))
    The string with many spaces!
    """
    cdef string out
    unique_copy(text.begin(), text.end(), back_inserter(out), &both_space)
    return out
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_algo_nonmodifying_sequence_ops.pyx0000644000175100001770000001724400000000000026313 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp11

from cython.operator cimport dereference as deref

from libcpp cimport bool
from libcpp.algorithm cimport all_of, any_of, none_of, for_each, count, count_if, mismatch, find, find_if, find_if_not
from libcpp.algorithm cimport find_end, find_first_of, adjacent_find, search, search_n
from libcpp.iterator cimport distance
from libcpp.string cimport string
from libcpp.vector cimport vector


cdef bool is_odd(int i):
    return i % 2


def all_odd(vector[int] values):
    """
    Test all_of with is_odd predicate.

    >>> all_odd([3, 5, 7, 11, 13, 17, 19, 23])
    True
    >>> all_odd([3, 4])
    False
    """
    return all_of(values.begin(), values.end(), is_odd)


def any_odd(vector[int] values):
    """
    Test any_of with is_odd predicate.

    >>> any_odd([1, 2, 3, 4])
    True
    >>> any_odd([2, 4, 6, 8])
    False
    """
    return any_of(values.begin(), values.end(), is_odd)


def none_odd(vector[int] values):
    """
    Test none_of with is_odd predicate.

    >>> none_odd([2, 4, 6, 8])
    True
    >>> none_odd([1, 2, 3, 4])
    False
    """
    return none_of(values.begin(), values.end(), is_odd)


def count_ones(vector[int] values):
    """
    Test count.

    >>> count_ones([1, 2, 1, 2])
    2
    """
    return count(values.begin(), values.end(), 1)


cdef void add_one(int &i):
    # https://github.com/cython/cython/issues/1863
    (&i)[0] += 1


def increment_ints(vector[int] values):
    """
    Test for_each.

    >>> increment_ints([3, 4, 2, 8, 15, 267])
    [4, 5, 3, 9, 16, 268]
    """
    for_each(values.begin(), values.end(), &add_one)
    return values


def count_odd(vector[int] values):
    """
    Test count_if with is_odd predicate.

    >>> count_odd([1, 2, 3, 4])
    2
    >>> count_odd([2, 4, 6, 8])
    0
    """
    return count_if(values.begin(), values.end(), is_odd)


def mirror_ends(string data):
    """
    Test mismatch using cppreference example.

    This program determines the longest substring that is simultaneously found at the very beginning of the given string
    and at the very end of it, in reverse order (possibly overlapping).

    >>> print(mirror_ends(b'abXYZba').decode('ascii'))
    ab
    >>> print(mirror_ends(b'abca').decode('ascii'))
    a
    >>> print(mirror_ends(b'aba').decode('ascii'))
    aba
    """
    return string(data.begin(), mismatch(data.begin(), data.end(), data.rbegin()).first)


def mismatch_ints(vector[int] values1, vector[int] values2):
    """
    Test mismatch(first1, last1, first2).

    >>> mismatch_ints([1, 2, 3], [1, 2, 3])
    >>> mismatch_ints([1, 2], [1, 2, 3])
    >>> mismatch_ints([1, 3], [1, 2, 3])
    (3, 2)
    """
    result = mismatch(values1.begin(), values1.end(), values2.begin())
    if result.first == values1.end():
        return
    return deref(result.first), deref(result.second)


def is_int_in(vector[int] values, int target):
    """
    Test find.

    >>> is_int_in(range(5), 3)
    True
    >>> is_int_in(range(5), 10)
    False
    """
    return find(values.begin(), values.end(), target) != values.end()


def find_odd(vector[int] values):
    """
    Test find_if using is_odd predicate.

    >>> find_odd([2, 3, 4])
    3
    >>> find_odd([2, 4, 6])
    """
    result = find_if(values.begin(), values.end(), is_odd)
    if result != values.end():
        return deref(result)
    else:
        return None


def find_even(vector[int] values):
    """
    Test find_if_not using is_odd predicate.

    >>> find_even([3, 4, 5])
    4
    >>> find_even([1, 3, 5])
    """
    result = find_if_not(values.begin(), values.end(), is_odd)
    if result != values.end():
        return deref(result)
    else:
        return None


def find_last_int_sequence(vector[int] values, vector[int] target):
    """
    Test find_end.

    >>> find_last_int_sequence([1, 2, 3, 1, 2, 3], [2, 3])
    4
    >>> find_last_int_sequence([1, 2, 3], [4, 5])
    """
    result = find_end(values.begin(), values.end(), target.begin(), target.end())
    if result != values.end():
        return distance(values.begin(), result)
    else:
        return None


cdef bool is_equal(int lhs, int rhs):
    return lhs == rhs


def find_last_int_sequence2(vector[int] values, vector[int] target):
    """
    Test find_end (using is_equal predicate).

    >>> find_last_int_sequence2([1, 2, 3, 1, 2, 3], [2, 3])
    4
    >>> find_last_int_sequence2([1, 2, 3], [4, 5])
    """
    result = find_end(values.begin(), values.end(), target.begin(), target.end(), &is_equal)
    if result != values.end():
        return distance(values.begin(), result)
    else:
        return None


def find_first_int_in_set(values, target):
    """
    Test find_first_of.

    >>> find_first_int_in_set([1, 2, 3, 4, 5], [3, 5])
    2
    >>> find_first_int_in_set([1, 2, 3], [4, 5])
    """
    cdef vector[int] v = values
    cdef vector[int] t = target
    result = find_first_of(v.begin(), v.end(), t.begin(), t.end())
    if result != v.end():
        return distance(v.begin(), result)
    else:
        return None


def find_first_int_in_set2(vector[int] values, vector[int] target):
    """
    Test find_first_of with is_equal predicate.

    >>> find_first_int_in_set2([1, 2, 3, 4, 5], [3, 5])
    2
    >>> find_first_int_in_set2([1, 2, 3], [4, 5])
    """
    result = find_first_of(values.begin(), values.end(), target.begin(), target.end(), is_equal)
    if result != values.end():
        return distance(values.begin(), result)
    else:
        return None


def find_adjacent_int(vector[int] values):
    """
    Test adjacent_find.

    >>> find_adjacent_int([0, 1, 2, 3, 40, 40, 41, 41, 5])
    4
    >>> find_adjacent_int(range(5))
    """
    result = adjacent_find(values.begin(), values.end())
    if result != values.end():
        return distance(values.begin(), result)
    else:
        return None


def find_adjacent_int2(vector[int] values):
    """
    Test find_adjacent with is_equal predicate.

    >>> find_adjacent_int2([0, 1, 2, 3, 40, 40, 41, 41, 5])
    4
    >>> find_adjacent_int2(range(5))
    """
    result = adjacent_find(values.begin(), values.end(), is_equal)
    if result != values.end():
        return distance(values.begin(), result)
    else:
        return None


def in_quote(string quote, string word):
    """
    Test search using cppreference example.

    >>> in_quote(b"why waste time learning, when ignorance is instantaneous?", b"learning")
    True
    >>> in_quote(b"why waste time learning, when ignorance is instantaneous?", b"lemming")
    False
    """
    return search(quote.begin(), quote.end(), word.begin(), word.end()) != quote.end()


def in_quote2(string quote, string word):
    """
    Test search using cppreference example (with is_equal predicate).

    >>> in_quote2(b"why waste time learning, when ignorance is instantaneous?", b"learning")
    True
    >>> in_quote2(b"why waste time learning, when ignorance is instantaneous?", b"lemming")
    False
    """
    return search(quote.begin(), quote.end(), word.begin(), word.end(), &is_equal) != quote.end()


def consecutive_values(string c, int count, char v):
    """
    Test search_n using cppreference example (without std::begin and std::end).

    >>> consecutive_values(b"1001010100010101001010101", 4, ord("0"))
    False
    >>> consecutive_values(b"1001010100010101001010101", 3, ord("0"))
    True
    """
    return search_n(c.begin(), c.end(), count, v) != c.end()


def consecutive_values2(string c, int count, char v):
    """
    Test search_n using cppreference example (with is_equal predicate).

    >>> consecutive_values2(b"1001010100010101001010101", 4, ord("0"))
    False
    >>> consecutive_values2(b"1001010100010101001010101", 3, ord("0"))
    True
    """
    return search_n(c.begin(), c.end(), count, v, &is_equal) != c.end()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_algo_partitioning_ops.pyx0000644000175100001770000000447600000000000024435 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp11, no-cpp-locals

from __future__ import print_function

from libcpp cimport bool
from libcpp.algorithm cimport is_partitioned, partition, partition_copy, stable_partition, partition_point
from libcpp.algorithm cimport for_each, copy, reverse
from libcpp.iterator cimport back_inserter
from libcpp.vector cimport vector


cdef bool is_even(int i):
    return i % 2 == 0


def test_is_partitioned():
    """
    >>> test_is_partitioned()
    False
    True
    False
    """
    cdef vector[int] values = range(10)
    print(is_partitioned(values.begin(), values.end(), is_even))

    partition(values.begin(), values.end(), &is_even)
    print(is_partitioned(values.begin(), values.end(), is_even))

    reverse(values.begin(), values.end())
    print(is_partitioned(values.begin(), values.end(), is_even))


cdef int print_int(int v) except -1:
    print(v, end=" ")


def print_partition(vector[int] values):
    """
    Test partition.

    >> print_partition(range(10))
    0 8 2 6 4  *  5 3 7 1 9
    """
    it = partition(values.begin(), values.end(), &is_even)
    for_each(values.begin(), it, &print_int)
    print("*", end=" ")
    for_each(it, values.end(), &print_int)
    print()


def partition_ints_even(vector[int] values):
    """
    Test partition_copy.

    >>> partition_ints_even(range(10))
    ([0, 2, 4, 6, 8], [1, 3, 5, 7, 9])
    """
    cdef vector[int] even_values, odd_values
    partition_copy(values.begin(), values.end(), back_inserter(even_values), back_inserter(odd_values), &is_even)
    return even_values, odd_values


cdef bool is_positive(int v):
    return v > 0


def partition_ints_positive(vector[int] values):
    """
    Test stable_partition.

    >>> partition_ints_positive([0, 0, 3, 0, 2, 4, 5, 0, 7])
    [3, 2, 4, 5, 7, 0, 0, 0, 0]
    """
    stable_partition(values.begin(), values.end(), &is_positive)
    return values


def partition_point_ints_even(vector[int] values):
    """
    Test partition_point.

    >>> partition_point_ints_even([0, 8, 2, 6, 4, 5, 3, 7, 1, 9])
    ([0, 8, 2, 6, 4], [5, 3, 7, 1, 9])
    """
    it = partition_point(values.begin(), values.end(), is_even)
    cdef vector[int] even_values, odd_values
    copy(values.begin(), it, back_inserter(even_values))
    copy(it, values.end(), back_inserter(odd_values))
    return even_values, odd_values
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_algo_permutation_ops.pyx0000644000175100001770000000566200000000000024273 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp17, no-cpp-locals, c_string_type=str
# cython: c_string_encoding=ascii, c_string_type=str

from libcpp cimport bool
from libcpp.algorithm cimport is_permutation, next_permutation, prev_permutation
from libcpp.vector cimport vector
from libcpp.string cimport string

cdef bool compare(int a, int b):
    return a == b

cdef bool less_than(char a, char b):
    return a < b

def test_is_permutation(vector[int] v1, vector[int] v2):
    """
    Test is_permutation.

    >>> test_is_permutation([1, 2, 3, 4], [4, 2, 3, 1])
    True
    >>> test_is_permutation([1, 2, 3, 4], [4, 4, 2, 5])
    False
    """
    return is_permutation(v1.begin(), v1.end(), v2.begin())

def test_is_permutation_with_bin_pred(vector[int] v1, vector[int] v2):
    """
    Test is_permutation with binary predicate

    >>> test_is_permutation_with_bin_pred([1, 2, 3, 4], [4, 2, 3, 1])
    True
    >>> test_is_permutation_with_bin_pred([1, 2, 3, 4], [4, 4, 2, 5])
    False
    """
    return is_permutation(v1.begin(), v1.end(), v2.begin(), compare)

def test_is_permutation_with_second_range_and_bin_pred(vector[int] v1, vector[int] v2):
    """
    Test is_permutation with second range and binary predicate

    >>> test_is_permutation_with_second_range_and_bin_pred([1, 2, 3, 4], [4, 2, 3, 1])
    True
    >>> test_is_permutation_with_second_range_and_bin_pred([1, 2, 3, 4], [4, 4, 2, 5])
    False
    """
    return is_permutation(v1.begin(), v1.end(), v2.begin(), v2.end(), compare)

def test_next_permutation(s_in, s_perm):
    """
    Test next_permutation.

    >>> test_next_permutation("aba", "baa")
    True
    >>> test_next_permutation("aba", "bab")
    False
    """
    cdef string ss = s_in
    cdef string expected = s_perm
    next_permutation(ss.begin(), ss.end())
    return ss == expected

def test_next_permutation_with_bin_pred(s_in, s_perm):
    """
    Test next_permutation with binary predicate

    >>> test_next_permutation_with_bin_pred("aba", "baa")
    True
    >>> test_next_permutation_with_bin_pred("aba", "bab")
    False
    """
    cdef string ss = s_in
    cdef string expected = s_perm
    next_permutation(ss.begin(), ss.end(), less_than)
    return ss == expected

def test_prev_permutation(s_in, s_perm):
    """
    Test prev_permutation.

    >>> test_prev_permutation("aba", "aab")
    True
    >>> test_prev_permutation("aba", "bab")
    False
    """
    cdef string ss = s_in
    cdef string expected = s_perm
    prev_permutation(ss.begin(), ss.end())
    return ss == expected

def test_prev_permutation_with_bin_pred(s_in, s_perm):
    """
    Test prev_permutation with binary predicate

    >>> test_prev_permutation_with_bin_pred("aba", "aab")
    True
    >>> test_prev_permutation_with_bin_pred("aba", "bab")
    False
    """
    cdef string ss = s_in
    cdef string expected = s_perm
    prev_permutation(ss.begin(), ss.end(), less_than)
    return ss == expected
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_algo_sample.pyx0000644000175100001770000000165400000000000022321 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp17

from libcpp.algorithm cimport sample
from libcpp.iterator cimport back_inserter
from libcpp.random cimport mt19937
from libcpp.utility cimport move
from libcpp.vector cimport vector


def sample_multiple(population_size, int sample_size):
    """
    >>> sample = sample_multiple(10, 7)
    >>> len(sample), len(set(sample))  # Check sampling without replacement.
    (7, 7)
    """
    cdef:
        vector[int] x, y
        int i
        mt19937 rd = mt19937(1)

    for i in range(population_size):
        x.push_back(i)
    sample(x.begin(), x.end(), back_inserter(y), sample_size, move(rd))
    return y


def sample_single(population_size):
    """
    >>> 0 <= sample_single(10) < 10
    True
    """
    cdef:
        vector[int] x
        int i
        mt19937 rd = mt19937(1)

    for i in range(population_size):
        x.push_back(i)
    sample(x.begin(), x.end(), &i, 1, move(rd))
    return i
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_algo_sorted_ranges_other_ops.pyx0000644000175100001770000000252000000000000025752 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp11

from cython.operator cimport dereference as deref

from libcpp cimport bool
from libcpp.algorithm cimport merge, inplace_merge
from libcpp.vector cimport vector


cdef bool less(int a, int b):
    return a < b

def test_merge(vector[int] v1, vector[int] v2):
    """
    Test merge.

    >>> test_merge([1, 3, 5], [2, 4])
    [1, 2, 3, 4, 5]
    """
    cdef vector[int] out = vector[int](v1.size() + v2.size())
    merge(v1.begin(), v1.end(), v2.begin(), v2.end(), out.begin())
    return out

def test_merge_with_bin_pred(vector[int] v1, vector[int] v2):
    """
    Test merge with binary predicate

    >>> test_merge_with_bin_pred([1, 3, 5], [2, 4])
    [1, 2, 3, 4, 5]
    """
    cdef vector[int] out = vector[int](v1.size() + v2.size())
    merge(v1.begin(), v1.end(), v2.begin(), v2.end(), out.begin(), less)
    return out

def test_inplace_merge(vector[int] v):
    """
    Test inplace_merge.

    >>> test_inplace_merge([4, 5, 6, 1, 2, 3])
    [1, 2, 3, 4, 5, 6]
    """
    inplace_merge(v.begin(), v.begin() + 3, v.end())
    return v

def test_inplace_merge_with_bin_pred(vector[int] v):
    """
    Test inplace_merge with binary predicate

    >>> test_inplace_merge_with_bin_pred([4, 5, 6, 1, 2, 3])
    [1, 2, 3, 4, 5, 6]
    """
    inplace_merge(v.begin(), v.begin() + 3, v.end(), less)
    return v././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_algo_sorted_ranges_set_ops.pyx0000644000175100001770000000721100000000000025426 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp11

from libcpp cimport bool
from libcpp.algorithm cimport (includes, set_difference, set_intersection, 
                               set_symmetric_difference, set_union)
from libcpp.vector cimport vector


cdef bool less(int a, int b):
    return a < b

def test_includes(vector[int] v1, vector[int] v2):
    """
    Test includes.

    >>> test_includes([1, 2, 3, 4], [1, 2, 3])
    True
    >>> test_includes([1, 2, 3, 4], [5, 6, 7])
    False
    """
    return includes(v1.begin(), v1.end(), v2.begin(), v2.end())

def test_includes_with_bin_pred(vector[int] v1, vector[int] v2):
    """
    Test includes with binary predicate

    >>> test_includes_with_bin_pred([1, 2, 3, 4], [1, 2, 3])
    True
    >>> test_includes_with_bin_pred([1, 2, 3, 4], [5, 6, 7])
    False
    """
    return includes(v1.begin(), v1.end(), v2.begin(), v2.end(), less)

def test_set_difference(vector[int] v1, vector[int] v2):
    """
    Test set_difference.

    >>> test_set_difference([1, 2, 5, 5, 5, 9], [2, 5, 7])
    [1, 5, 5, 9]
    """
    cdef vector[int] diff = vector[int](4)
    set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), diff.begin())
    return diff

def test_set_difference_with_bin_pred(vector[int] v1, vector[int] v2):
    """
    Test set_difference with binary predicate

    >>> test_set_difference_with_bin_pred([1, 2, 5, 5, 5, 9], [2, 5, 7])
    [1, 5, 5, 9]
    """
    cdef vector[int] diff = vector[int](4)
    set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), diff.begin(), less)
    return diff

def test_set_intersection(vector[int] v1, vector[int] v2):
    """
    Test set_intersection.

    >>> test_set_intersection([1, 2, 3, 4, 5, 6, 7, 8], [5, 7, 9, 10])
    [5, 7]
    """
    cdef vector[int] out = vector[int](2)
    set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), out.begin())
    return out

def test_set_intersection_with_bin_pred(vector[int] v1, vector[int] v2):
    """
    Test set_intersection with binary predicate

    >>> test_set_intersection_with_bin_pred([1, 2, 3, 4, 5, 6, 7, 8], [5, 7, 9, 10])
    [5, 7]
    """
    cdef vector[int] out = vector[int](2)
    set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), out.begin(), less)
    return out

def test_set_symmetric_difference(vector[int] v1, vector[int] v2):
    """
    Test set_symmetric_difference.

    >>> test_set_symmetric_difference([1, 2, 3, 4, 5, 6, 7, 8], [5, 7, 9, 10])
    [1, 2, 3, 4, 6, 8, 9, 10]
    """
    cdef vector[int] out = vector[int](8)
    set_symmetric_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), out.begin())
    return out

def test_set_symmetric_difference_with_bin_pred(vector[int] v1, vector[int] v2):
    """
    Test set_symmetric_difference with binary predicate

    >>> test_set_symmetric_difference_with_bin_pred([1, 2, 3, 4, 5, 6, 7, 8], [5, 7, 9, 10])
    [1, 2, 3, 4, 6, 8, 9, 10]
    """
    cdef vector[int] out = vector[int](8)
    set_symmetric_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), out.begin(), less)
    return out

def test_set_union(vector[int] v1, vector[int] v2):
    """
    Test set_union.

    >>> test_set_union([1, 2, 3, 4, 5], [3, 4, 5, 6, 7])
    [1, 2, 3, 4, 5, 6, 7]
    """
    cdef vector[int] out = vector[int](7)
    set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), out.begin())
    return out

def test_set_union_with_bin_pred(vector[int] v1, vector[int] v2):
    """
    Test set_union with binary predicate

    >>> test_set_union_with_bin_pred([1, 2, 3, 4, 5], [3, 4, 5, 6, 7])
    [1, 2, 3, 4, 5, 6, 7]
    """
    cdef vector[int] out = vector[int](7)
    set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), out.begin(), less)
    return out././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_algo_sorting_ops.pyx0000644000175100001770000001142500000000000023403 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp11, no-cpp-locals

from __future__ import print_function

from libcpp cimport bool
from libcpp.algorithm cimport is_sorted, is_sorted_until, sort, partial_sort, partial_sort_copy, stable_sort
from libcpp.algorithm cimport nth_element
from libcpp.functional cimport greater
from libcpp.iterator cimport distance
from libcpp.string cimport string
from libcpp.vector cimport vector


def is_sorted_ints(vector[int] values):
    """
    Test is_sorted.

    >>> is_sorted_ints([3, 1, 4, 1, 5])
    False
    >>> is_sorted_ints([1, 1, 3, 4, 5])
    True
    """
    return is_sorted(values.begin(), values.end())


def initial_sorted_elements(vector[int] values):
    """
    Test is_sorted_until.

    >>> initial_sorted_elements([4, 1, 9, 5, 1, 3])
    1
    >>> initial_sorted_elements([4, 5, 9, 3, 1, 1])
    3
    >>> initial_sorted_elements([9, 3, 1, 4, 5, 1])
    1
    >>> initial_sorted_elements([1, 3, 5, 4, 1, 9])
    3
    >>> initial_sorted_elements([5, 9, 1, 1, 3, 4])
    2
    >>> initial_sorted_elements([4, 9, 1, 5, 1, 3])
    2
    >>> initial_sorted_elements([1, 1, 4, 9, 5, 3])
    4
    """
    sorted_end = is_sorted_until(values.begin(), values.end())
    return distance(values.begin(), sorted_end)


def sort_ints(vector[int] values):
    """Test sort using the default operator<.

    >>> sort_ints([5, 7, 4, 2, 8, 6, 1, 9, 0, 3])
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    """
    sort(values.begin(), values.end())
    return values


def sort_ints_reverse(vector[int] values):
    """Test sort using a standard library comparison function object.

    >>> sort_ints_reverse([5, 7, 4, 2, 8, 6, 1, 9, 0, 3])
    [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    """
    sort(values.begin(), values.end(), greater[int]())
    return values


def partial_sort_ints(vector[int] values, int k):
    """
    Test partial_sort using the default operator<.

    >>> partial_sort_ints([4, 2, 3, 1, 5], 2)[:2]
    [1, 2]
    """
    partial_sort(values.begin(), values.begin() + k, values.end())
    return values


def partial_sort_ints_reverse(vector[int] values, int k):
    """
    Test partial_sort using a standard library comparison function object.

    >>> partial_sort_ints_reverse([4, 2, 3, 1, 5], 2)[:2]
    [5, 4]
    """
    partial_sort(values.begin(), values.begin() + k, values.end(), greater[int]())
    return values


def partial_sort_ints2(vector[int] values, int k):
    """
    Test partial_sort_copy using the default operator<.

    >>> partial_sort_ints2([4, 2, 3, 1, 5], 2)
    [1, 2]
    """
    output = vector[int](2)
    partial_sort_copy(values.begin(), values.end(), output.begin(), output.end())
    return output


def partial_sort_ints_reverse2(vector[int] values, int k):
    """
    Test partial_sort_copy using a standard library comparison function object.

    >>> partial_sort_ints_reverse2([4, 2, 3, 1, 5], 2)
    [5, 4]
    """
    output = vector[int](2)
    partial_sort_copy(values.begin(), values.end(), output.begin(), output.end(), greater[int]())
    return output


cdef extern from *:
    """
    struct Employee
    {
        Employee() = default;
        Employee(int age, std::string name): age(age), name(name) {}
        int age;
        std::string name;  // Does not participate in comparisons
    };

    bool operator<(const Employee& lhs, const Employee& rhs)
    {
        return lhs.age < rhs.age;
    }
    """
    cppclass Employee:
        Employee()
        Employee(int, string)
        int age
        string name

cdef bool Employee_greater(const Employee& lhs, const Employee& rhs):
    return lhs.age > rhs.age

def test_stable_sort():
    """
    Test stable_sort using cppreference example.

    >>> test_stable_sort()
    32, Arthur
    108, Zaphod
    108, Ford
    108, Zaphod
    108, Ford
    32, Arthur
    """
    cdef vector[Employee] employees
    employees.push_back(Employee(108, b"Zaphod"))
    employees.push_back(Employee(32, b"Arthur"))
    employees.push_back(Employee(108, b"Ford"))

    stable_sort(employees.begin(), employees.end())

    for e in employees:
        print("%s, %s" % (e.age, (e.name).decode("ascii")))

    stable_sort(employees.begin(), employees.end(), &Employee_greater)

    for e in employees:
        print("%s, %s" % (e.age, (e.name).decode("ascii")))


def second_smallest(vector[int] values):
    """
    Test nth_element using the default operator<.

    >>> second_smallest([5, 6, 4, 3, 2, 6, 7, 9, 3])
    3
    """
    nth_element(values.begin(), values.begin() + 1, values.end())
    return values[1]


def second_largest(vector[int] values):
    """
    Test nth_element using a standard library comparison function object.

    >>> second_largest([5, 6, 4, 3, 2, 6, 7, 9, 3])
    7
    """
    nth_element(values.begin(), values.begin() + 1, values.end(), greater[int]())
    return values[1]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_any.pyx0000644000175100001770000000303500000000000020620 0ustar00runnerdocker00000000000000# ticket: 2633
# mode: run
# tag: cpp, cpp17, werror

from libcpp cimport bool
from libcpp.any cimport any, any_cast
from libcpp.pair cimport pair
from cython.operator cimport typeid

def simple_test():
    """
    >>> simple_test()
    """
    cdef any u
    assert not u.has_value()
    v = new any(u)
    assert not v.has_value()
    u = 42
    assert u.has_value()
    v = new any(u)
    assert v.has_value()

def reset_test():
    """
    >>> reset_test()
    """
    cdef any a
    assert not a.has_value()
    a = 42
    assert a.has_value()
    a.reset()
    assert not a.has_value()

def cast_test():
    """
    >>> cast_test()
    """
    cdef any a
    a = 1
    assert a.type() == typeid(int)
    assert any_cast[int](a) == 1
    a = 3.14
    assert a.type() == typeid(double)
    assert any_cast[double](a) == 3.14
    a = (True)
    assert a.type() == typeid(bool)
    assert any_cast[bool](a) == True
    # bad cast
    try:
        a = 1
        b = any_cast[double](a)
    except TypeError:
        pass

def emplace_test():
    """
    >>> emplace_test()
    """
    cdef any a
    a = 42
    assert any_cast[int](a) == 42
    a.emplace[pair[int,int]](1,2)
    assert any_cast[pair[int,int]](a) == pair[int,int](1,2)
    a.reset()
    assert not a.has_value()
    a.emplace[pair[int,int]](1,2)
    assert any_cast[pair[int,int]](a) == pair[int,int](1,2)

def swap_test():
    """
    >>> swap_test()
    """
    cdef any a, b
    a = 42
    b = "hello"
    a.swap(b)
    assert any_cast[str](a) == "hello"
    assert any_cast[int](b) == 42
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_associated_containers_contains_cpp20.pyx0000644000175100001770000000554000000000000027302 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp20

# cython: language_level=3

from libcpp.map cimport map, multimap
from libcpp.set cimport set, multiset
from libcpp.unordered_map cimport unordered_map, unordered_multimap
from libcpp.unordered_set cimport unordered_set, unordered_multiset

def test_map_contains(vals, int key_to_find):
    """
    >>> test_map_contains([(1,100),(2,200),(3,300)], 3)
    True
    >>> test_map_contains([(1,100),(2,200),(3,300)], 4)
    False
    """
    cdef map[int,int] m = map[int, int]()
    for v in vals:
        m.insert(v)
    return m.contains(key_to_find)

def test_unordered_map_contains(vals, int key_to_find):
    """
    >>> test_unordered_map_contains([(1,100),(2,200),(3,300)], 3)
    True
    >>> test_unordered_map_contains([(1,100),(2,200),(3,300)], 4)
    False
    """
    cdef unordered_map[int,int] um = unordered_map[int, int]()
    for v in vals:
        um.insert(v)
    return um.contains(key_to_find)

def test_multimap_contains(vals, int key_to_find):
    """
    >>> test_multimap_contains([(1,100),(2,200),(3,300)], 3)
    True
    >>> test_multimap_contains([(1,100),(2,200),(3,300)], 4)
    False
    """
    cdef multimap[int,int] mm = multimap[int, int]()
    for v in vals:
        mm.insert(v)
    return mm.contains(key_to_find)

def test_unordered_multimap_contains(vals, int key_to_find):
    """
    >>> test_unordered_multimap_contains([(1,100),(2,200),(3,300)], 3)
    True
    >>> test_unordered_multimap_contains([(1,100),(2,200),(3,300)], 4)
    False
    """
    cdef unordered_multimap[int,int] umm = unordered_multimap[int, int]()
    for v in vals:
        umm.insert(v)
    return umm.contains(key_to_find)


def test_set_contains(vals, int val_to_find):
    """
    >>> test_set_contains([1, 2, 3], 3)
    True
    >>> test_set_contains([1, 2, 3], 4)
    False
    """
    cdef set[int] s = set[int]()
    for v in vals:
        s.insert(v)
    return s.contains(val_to_find)

def test_unordered_set_contains(vals, int val_to_find):
    """
    >>> test_unordered_set_contains([1, 2, 3], 3)
    True
    >>> test_unordered_set_contains([1, 2, 3], 4)
    False
    """
    cdef unordered_set[int] us = unordered_set[int]()
    for v in vals:
        us.insert(v)
    return us.contains(val_to_find)

def test_multiset_contains(vals, int val_to_find):
    """
    >>> test_multiset_contains([1, 2, 3], 3)
    True
    >>> test_multiset_contains([1, 2, 3], 4)
    False
    """
    cdef multiset[int] ms = multiset[int]()
    for v in vals:
        ms.insert(v)
    return ms.contains(val_to_find)

def test_unordered_multiset_contains(vals, int val_to_find):
    """
    >>> test_unordered_multiset_contains([1, 2, 3], 3)
    True
    >>> test_unordered_multiset_contains([1, 2, 3], 4)
    False
    """
    cdef unordered_multiset[int] ums = unordered_multiset[int]()
    for v in vals:
        ums.insert(v)
    return ums.contains(val_to_find)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_atomic.pyx0000644000175100001770000000302400000000000021303 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp11, werror, no-cpp-locals

from cython.operator cimport preincrement as incr, dereference as deref
from libc.stdint cimport *

from libcpp.atomic cimport atomic

def int_test(int x):
    """
    >>> int_test(55)
    3
    >>> int_test(42)
    3
    >>> int_test(100000)
    3
    """
    atom = new atomic[int](x)
    try:
        atom.store(0)
        incr(deref(atom))
        incr(deref(atom))
        incr(deref(atom))
        return atom.load()
    finally:
        del atom

ctypedef atomic[int32_t] atomint32_t

def typedef_test(int x):
    """
    >>> typedef_test(55)
    3
    >>> typedef_test(42)
    3
    >>> typedef_test(100000)
    3
    """
    atom = new atomint32_t(x)
    try:
        atom.store(0)
        incr(deref(atom))
        incr(deref(atom))
        incr(deref(atom))
        return atom.load()
    finally:
        del atom

def stack_allocation_test(int x):
    """
    >>> stack_allocation_test(55)
    3
    >>> stack_allocation_test(42)
    3
    >>> stack_allocation_test(100000)
    3
    """
    cdef atomint32_t atom
    atom.store(x)
    try:
        atom.store(0)
        incr(atom)
        incr(atom)
        incr(atom)
        return atom.load()
    finally:
        pass

def nogil_int_test(int x):
    """
    >>> nogil_int_test(55)
    55
    >>> nogil_int_test(42)
    42
    >>> nogil_int_test(100000)
    100000
    """
    with nogil:
        atom = new atomic[int](0)
    try:
        with nogil:
            atom.store(x)
        return atom.load()
    finally:
        del atom
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_bit_cpp20.pyx0000644000175100001770000000554100000000000021617 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp20

from libcpp cimport bool
from libc.stdint cimport uint8_t, int8_t
from libcpp.bit cimport (bit_cast, has_single_bit, bit_ceil, bit_floor, 
                        bit_width, rotr, rotl, countl_zero, countl_one, countr_zero, 
                        countr_one, popcount)

def test_bit_cast():
    """
    Test bit_cast with a signed 8bit wide integer type.
    -127U = 0b1000'0001U
    >>> test_bit_cast()
    129
    """
    cdef int8_t x = -127
    cdef result = bit_cast[uint8_t, int8_t](x)
    return result

def test_has_single_bit():
    """
    Test has_single_bit with a unsigned 8bit wide integer type.
    >>> test_has_single_bit()
    True
    """
    cdef uint8_t x = 1
    cdef bint res = has_single_bit[uint8_t](x)
    return res

def test_bit_ceil():
    """
    Test bit_ceil with a unsigned 8bit wide integer type.
    >>> test_bit_ceil()
    4
    """
    cdef uint8_t x = 3
    cdef uint8_t res = bit_ceil[uint8_t](x)
    return res

def test_bit_floor():
    """
    Test bit_floor with a unsigned 8bit wide integer type.
    >>> test_bit_floor()
    4
    """
    cdef uint8_t x = 5
    cdef uint8_t res = bit_floor[uint8_t](x)
    return res

def test_bit_width():
    """
    Test bit_width with a unsigned 8bit wide integer type.
    >>> test_bit_width()
    3
    """
    cdef uint8_t x = 5
    cdef int res = bit_width[uint8_t](x)
    return res

def test_rotl():
    """
    Test rotl with a unsigned 8bit wide integer type.
    >>> test_rotl()
    209
    """
    cdef uint8_t x = 29
    cdef int s = 4
    cdef uint8_t res = rotl[uint8_t](x, s)
    return res

def test_rotr():
    """
    Test rotr with a unsigned 8bit wide integer type.
    >>> test_rotr()
    142
    """
    cdef uint8_t x = 29
    cdef int s = 1
    cdef uint8_t res = rotr[uint8_t](x, s)
    return res

def test_countl_zero():
    """
    Test countl_zero with a unsigned 8bit wide integer type.
    >>> test_countl_zero()
    3
    """
    cdef uint8_t x = 24
    cdef int res = countl_zero[uint8_t](x)
    return res

def test_countr_zero():
    """
    Test countr_zero with a unsigned 8bit wide integer type.
    >>> test_countr_zero()
    3
    """
    cdef uint8_t x = 24
    cdef int res = countr_zero[uint8_t](x)
    return res

def test_countl_one():
    """
    Test countl_one with a unsigned 8bit wide integer type.
    >>> test_countl_one()
    3
    """
    cdef uint8_t x = 231
    cdef int res = countl_one[uint8_t](x)
    return res

def test_countr_one():
    """
    Test countr_one with a unsigned 8bit wide integer type.
    >>> test_countr_one()
    3
    """
    cdef uint8_t x = 231
    cdef int res = countr_one[uint8_t](x)
    return res

def test_popcount():
    """
    Test popcount with a unsigned 8bit wide integer type.
    >>> test_popcount()
    8
    """
    cdef uint8_t x = 255
    cdef int res = popcount[uint8_t](x)
    return res
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_cmath_cpp17.pyx0000644000175100001770000000123600000000000022140 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp17

from libcpp.cmath cimport beta, legendre, hypot

def test_beta(double x, double y):
    """
    Test C++17 std::beta function
    >>> test_beta(1.0, 1.0)
    1.0
    >>> test_beta(1.0, 2.0)
    0.5
    """
    return beta(x, y)

def test_legendre(int x, double y):
    """
    Test C++17 std::legendre function
    >>> test_legendre(1, 0.5)
    0.5
    >>> test_legendre(2, 0.5)
    -0.125
    """
    return legendre(x, y)

def test_hypot(double x, double y, double z):
    """
    Test C++17 std::hypot function
    >>> test_hypot(1.0, 2.0, 2.0)
    3.0
    >>> test_hypot(3.0, 4.0, 0.0)
    5.0
    """
    return hypot(x, y, z)././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_cmath_cpp20.pyx0000644000175100001770000000041500000000000022130 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp20

from libcpp.cmath cimport lerp

def test_lerp(double a, double b, double t):
    """ Test C++20 std::lerp function
    >>> test_lerp(1.0, 2.0, 0.5)
    1.5
    >>> test_lerp(1.0, 4.0, 0.5)
    2.5
    """
    return lerp(a, b, t)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_conversion.pyx0000644000175100001770000001531200000000000022217 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp11

import sys
from collections import defaultdict

from libcpp.map cimport map
from libcpp.unordered_map cimport unordered_map
from libcpp.set cimport set as cpp_set
from libcpp.unordered_set cimport unordered_set
from libcpp.string cimport string
from libcpp.pair cimport pair
from libcpp.vector cimport vector
from libcpp.list cimport list as cpp_list

py_set = set
py_xrange = xrange
py_unicode = unicode

cdef string add_strings(string a, string b) except *:
    return a + b

def normalize(bytes b):
    if sys.version_info[0] >= 3:
        return b.decode("ascii")
    else:
        return b

def test_string(o):
    """
    >>> normalize(test_string("abc".encode('ascii')))
    'abc'
    >>> normalize(test_string("abc\\x00def".encode('ascii')))
    'abc\\x00def'
    """
    cdef string s = o
    return s

def test_encode_to_string(o):
    """
    >>> normalize(test_encode_to_string('abc'))
    'abc'
    >>> normalize(test_encode_to_string('abc\\x00def'))
    'abc\\x00def'
    """
    cdef string s = o.encode('ascii')
    return s

def test_encode_to_string_cast(o):
    """
    >>> normalize(test_encode_to_string_cast('abc'))
    'abc'
    >>> normalize(test_encode_to_string_cast('abc\\x00def'))
    'abc\\x00def'
    """
    s = o.encode('ascii')
    return s

def test_unicode_encode_to_string(unicode o):
    """
    >>> normalize(test_unicode_encode_to_string(py_unicode('abc')))
    'abc'
    >>> normalize(test_unicode_encode_to_string(py_unicode('abc\\x00def')))
    'abc\\x00def'
    """
    cdef string s = o.encode('ascii')
    return s

def test_string_call(a, b):
    """
    >>> normalize(test_string_call("abc".encode('ascii'), "xyz".encode('ascii')))
    'abcxyz'
    """
    return add_strings(a, b)

def test_c_string_convert(char *c_string):
    """
    >>> normalize(test_c_string_convert("abc".encode('ascii')))
    'abc'
    """
    cdef string s
    with nogil:
        s = c_string
    return s

def test_bint_vector(o):
    """
    https://github.com/cython/cython/issues/5516
    Creating the "bint" specialization used to mess up the
    "int" specialization.

    >>> test_bint_vector([False, True])
    [False, True]
    >>> test_bint_vector(py_xrange(0,5))
    [False, True, True, True, True]
    >>> test_bint_vector(["", "hello"])
    [False, True]
    """

    cdef vector[bint] v = o
    return v

def test_int_vector(o):
    """
    >>> test_int_vector([1, 2, 3])
    [1, 2, 3]
    >>> test_int_vector((1, 10, 100))
    [1, 10, 100]
    >>> test_int_vector(py_xrange(1,10,2))
    [1, 3, 5, 7, 9]
    >>> test_int_vector([10**20])       #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: ...
    """
    cdef vector[int] v = o
    return v

cdef vector[int] takes_vector(vector[int] x):
    return x

def test_list_literal_to_vector():
    """
    >>> test_list_literal_to_vector()
    [1, 2, 3]
    """
    return takes_vector([1, 2, 3])

def test_tuple_literal_to_vector():
    """
    >>> test_tuple_literal_to_vector()
    [1, 2, 3]
    """
    return takes_vector((1, 2, 3))

def test_string_vector(s):
    """
    >>> list(map(normalize, test_string_vector('ab cd ef gh'.encode('ascii'))))
    ['ab', 'cd', 'ef', 'gh']
    """
    cdef vector[string] cpp_strings = s.split()
    return cpp_strings

cdef list convert_string_vector(vector[string] vect):
    return vect

def test_string_vector_temp_funcarg(s):
    """
    >>> list(map(normalize, test_string_vector_temp_funcarg('ab cd ef gh'.encode('ascii'))))
    ['ab', 'cd', 'ef', 'gh']
    """
    return convert_string_vector(s.split())

def test_double_vector(o):
    """
    >>> test_double_vector([1, 2, 3])
    [1.0, 2.0, 3.0]
    >>> test_double_vector([10**20])
    [1e+20]
    """
    cdef vector[double] v = o
    return v

def test_repeated_double_vector(a, b, int n):
    """
    >>> test_repeated_double_vector(1, 1.5, 3)
    [1.0, 1.5, 1.0, 1.5, 1.0, 1.5]
    """
    cdef vector[double] v = [a, b] * n
    return v

ctypedef int my_int

def test_typedef_vector(o):
    """
    >>> test_typedef_vector([1, 2, 3])
    [1, 2, 3]
    >>> test_typedef_vector([1, 2, 3**100])       #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: ...

    "TypeError: an integer is required" on CPython
    >>> test_typedef_vector([1, 2, None])       #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: ...int...
    """
    cdef vector[my_int] v = o
    return v

def test_pair(o):
    """
    >>> test_pair((1, 2))
    (1, 2.0)
    """
    cdef pair[long, double] p = o
    return p

def test_list(o):
    """
    >>> test_list([1, 2, 3])
    [1, 2, 3]
    """
    cdef cpp_list[int] l = o
    return l

def test_set(o):
    """
    >>> sorted(test_set([1, 2, 3]))
    [1, 2, 3]
    >>> sorted(test_set([1, 2, 3, 3]))
    [1, 2, 3]
    >>> type(test_set([])) is py_set
    True
    """
    cdef cpp_set[long] s = o
    return s

def test_unordered_set(o):
   """
   >>> sorted(test_unordered_set([1, 2, 3]))
   [1, 2, 3]
   >>> sorted(test_unordered_set([1, 2, 3, 3]))
   [1, 2, 3]
   >>> type(test_unordered_set([])) is py_set
   True
   """
   cdef unordered_set[long] s = o
   return s

def test_map(o):
    """
    >>> d = {1: 1.0, 2: 0.5, 3: 0.25}
    >>> test_map(d)
    {1: 1.0, 2: 0.5, 3: 0.25}
    >>> dd = defaultdict(float)
    >>> dd.update(d)
    >>> test_map(dd)  # try with a non-dict
    {1: 1.0, 2: 0.5, 3: 0.25}
    """
    cdef map[int, double] m = o
    return m

def test_unordered_map(o):
    """
    >>> d = {1: 1.0, 2: 0.5, 3: 0.25}
    >>> m = test_map(d)
    >>> sorted(m)
    [1, 2, 3]
    >>> (m[1], m[2], m[3])
    (1.0, 0.5, 0.25)

    >>> dd = defaultdict(float)
    >>> dd.update(d)
    >>> m = test_map(dd)
    >>> sorted(m)
    [1, 2, 3]
    >>> (m[1], m[2], m[3])
    (1.0, 0.5, 0.25)
    """
    cdef unordered_map[int, double] m = o
    return m

def test_nested(o):
    """
    >>> test_nested({})
    {}
    >>> d = test_nested({(1.0, 2.0): [1, 2, 3], (1.0, 0.5): [1, 10, 100]})
    >>> type(d) is dict or type(d)
    True
    >>> sorted(d)
    [(1.0, 0.5), (1.0, 2.0)]
    >>> d[(1.0, 0.5)]
    [1, 10, 100]
    >>> d[(1.0, 2.0)]
    [1, 2, 3]
    """
    cdef map[pair[double, double], vector[int]] m = o
    return m

cpdef enum Color:
    RED = 0
    GREEN
    BLUE

def test_enum_map(o):
    """
    >>> test_enum_map({RED: GREEN})
    {: }
    """
    cdef map[Color, Color] m = o
    return m

cdef map[unsigned int, unsigned int] takes_map(map[unsigned int, unsigned int] m):
    return m

def test_dict_literal_to_map():
    """
    >>> test_dict_literal_to_map()
    {1: 1}
    """
    return takes_map({1: 1})  # https://github.com/cython/cython/pull/4228
                              # DictNode could not be converted directly
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_cpp11.pyx0000644000175100001770000001323400000000000020757 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp11, no-cpp-locals

import sys
from libcpp.unordered_map cimport unordered_map
from libcpp.unordered_set cimport unordered_set
from libcpp.vector cimport vector
from libcpp.queue cimport queue
from libcpp.queue cimport priority_queue
from libcpp.vector cimport vector
from libcpp.pair cimport pair
from libcpp.map cimport map
from libcpp.set cimport set
from libcpp.deque cimport deque
from libcpp.functional cimport reference_wrapper


def test_reference_wrapper():
    """
    >>> test_reference_wrapper()
    'pass'
    """
    cdef:
        int x = 1
        vector[reference_wrapper[int]] ref_wrap_vector
    ref_wrap_vector.push_back(reference_wrapper[int](x))
    assert ref_wrap_vector[0].get() == 1
    return "pass"


def test_vector_functionality():
    """
    >>> test_vector_functionality()
    'pass'
    """
    cdef:
        vector[int] int_vector = vector[int]()
        int* data
        const int* const_data
    int_vector.push_back(77)
    data = int_vector.data()
    const_data = int_vector.const_data()
    assert data[0] == 77
    assert const_data[0] == 77
    return "pass"


def test_queue_functionality():
    """
    >>> test_queue_functionality()
    'pass'
    """
    cdef:
        queue[int] int_queue = queue[int]()
        queue[int] int_queue2 = queue[int]()
    int_queue.push(77)
    int_queue.swap(int_queue2)
    assert int_queue.size() == 0
    assert int_queue2.size() == 1
    return "pass"


def test_deque_functionality():
    """
    >>> test_deque_functionality()
    'pass'
    """
    cdef:
        deque[int] int_deque = deque[int]()
    int_deque.push_back(77)
    int_deque.shrink_to_fit()
    return "pass"


def test_priority_queue_functionality():
    """
    >>> test_priority_queue_functionality()
    'pass'
    """
    cdef:
        priority_queue[int] int_queue = priority_queue[int]()
        priority_queue[int] int_queue2 = priority_queue[int]()
    int_queue.push(77)
    int_queue.swap(int_queue2)
    assert int_queue.size() == 0
    assert int_queue2.size() == 1
    return "pass"


def test_set_functionality():
    """
    >>> test_set_functionality()
    'pass'
    """
    cdef:
        set[int] int_set
        set[int] int_set2
    int_set2.insert(77)
    int_set2.insert(66)
    int_set.insert(int_set2.const_begin(), int_set2.const_end())
    assert int_set.size() == 2
    assert int_set.erase(int_set.const_begin(), int_set.const_end()) == int_set.end()
    return "pass"


def test_map_functionality():
    """
    >>> test_map_functionality()
    'pass'
    """
    cdef:
        map[int, const void*] int_map
        const void* data
    int_map[77] = NULL
    data = int_map.const_at(77)
    return "pass"


def test_unordered_set_functionality():
    """
    >>> test_unordered_set_functionality()
    'pass'
    """
    cdef:
        unordered_set[int] int_set = unordered_set[int]()
        unordered_set[int] int_set2
        unordered_set[int].iterator iterator = int_set.begin()
    int_set.insert(1)
    assert int_set.size() == 1
    int_set.erase(unordered_set[int].const_iterator(int_set.begin()), unordered_set[int].const_iterator(int_set.end()))
    assert int_set.size() == 0
    int_set.insert(1)
    assert int_set.erase(1) == 1 # returns number of elements erased
    assert int_set.size() == 0
    int_set.insert(1)
    iterator = int_set.find(1)
    assert int_set.erase(iterator) == int_set.end()

    int_set2.insert(3)
    int_set2.insert(5)
    int_set.insert(int_set2.begin(), int_set2.end())
    assert int_set.size() == 2

    if sys.platform != 'darwin':
        int_set.max_load_factor(0.5)
        assert int_set.max_load_factor() == 0.5
    int_set.rehash(20)
    int_set.reserve(20)

    int_set.bucket_size(0)
    int_set.bucket_count()
    int_set.max_bucket_count()
    int_set.bucket(3)
    assert int_set.load_factor() > 0
    return "pass"


cdef extern from "cpp_unordered_map_helper.h":
    cdef cppclass IntVectorHash:
        pass


def test_unordered_map_functionality():
    """
    >>> test_unordered_map_functionality()
    'pass'
    """
    cdef:
        unordered_map[int, int] int_map = unordered_map[int,int]()
        pair[int, int] pair_insert = pair[int, int](1, 2)
        unordered_map[int,int].iterator iterator = int_map.begin()
        pair[unordered_map[int,int].iterator, bint] pair_iter  = int_map.insert(pair_insert)
        unordered_map[int, int] int_map2
        unordered_map[int, int*] intptr_map
        const int* intptr
        unordered_map[vector[int], int, IntVectorHash] int_vector_map
        vector[int] intvec
    assert int_map[1] == 2
    assert int_map.size() == 1
    assert int_map.erase(1) == 1 # returns number of elements erased
    assert int_map.size() == 0
    int_map[1] = 2
    assert int_map.size() == 1
    assert int_map[1] == 2
    iterator = int_map.find(1)
    assert int_map.erase(iterator) == int_map.end()

    int_map2[1] = 2
    int_map2[3] = 3
    int_map.clear()
    int_map.insert(int_map2.begin(), int_map2.end())
    assert int_map.size() == 2
    assert int_map.erase(unordered_map[int,int].const_iterator(int_map.begin()), unordered_map[int,int].const_iterator(int_map.end())) == int_map.end()

    int_map.max_load_factor(0.5)
    assert int_map.max_load_factor() == 0.5
    int_map.rehash(20)
    int_map.reserve(20)

    int_map[3] = 3
    int_map.bucket_size(0)
    int_map.bucket_count()
    int_map.max_bucket_count()
    int_map.bucket(3)
    assert int_map.load_factor() > 0

    intptr_map[0] = NULL
    intptr = intptr_map.const_at(0)

    intvec = [1, 2]
    int_vector_map[intvec] = 3
    intvec = [4, 5]
    int_vector_map[intvec] = 6
    assert int_vector_map[intvec] == 6
    intvec = [1, 2]
    assert int_vector_map[intvec] == 3
    return "pass"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_forward_list.pyx0000644000175100001770000000253500000000000022534 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp11, no-cpp-locals

from cython.operator cimport dereference as deref
from cython.operator cimport preincrement as incr

from libcpp.forward_list cimport forward_list
from libcpp cimport bool as cbool


def simple_iteration_test(L):
    """
    >>> iteration_test([1,2,4,8])
    8
    4
    2
    1
    >>> iteration_test([8,4,2,1])
    1
    2
    4
    8
    """
    cdef forward_list[int] l
    for a in L:
        l.push_front(a)
    for a in l:
        print(a)

def iteration_test(L):
    """
    >>> iteration_test([1,2,4,8])
    8
    4
    2
    1
    >>> iteration_test([8,4,2,1])
    1
    2
    4
    8
    """
    l = new forward_list[int]()
    try:
        for a in L:
            l.push_front(a)
        it = l.begin()
        while it != l.end():
            a = deref(it)
            incr(it)
            print(a)
    finally:
        del l

def test_value_type(x):
    """
    >>> test_value_type(2)
    2.0
    >>> test_value_type(2.5)
    2.5
    """
    cdef forward_list[double].value_type val = x
    return val

def test_value_type_complex(x):
    """
    >>> test_value_type_complex(2)
    (2+0j)
    """
    cdef forward_list[double complex].value_type val = x
    return val


#  Tests GitHub issue #1788.
cdef cppclass MyForwardList[T](forward_list):
    pass

cdef cppclass Ints(MyForwardList[int]):
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_function.pyx0000644000175100001770000000475600000000000021671 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp11

from libcpp.functional cimport function
cimport cpp_function_lib

def test_simple_function():
    '''
    >>> test_simple_function()
    6.0
    '''
    return cpp_function_lib.add_one(2.0, 3)


def test_AddAnotherFunctor(n):
    '''
    >>> test_AddAnotherFunctor(5.0)
    10.0
    '''
    return cpp_function_lib.AddAnotherFunctor(5.0).call(2.0, 3)


cdef class FunctionKeeper:
    """
    >>> fk = FunctionKeeper('add_one')
    >>> fk(2.0, 3)
    6.0
    >>> fk = FunctionKeeper('add_two')
    >>> fk(2.0, 3)
    7.0
    >>> fk = FunctionKeeper('AddAnotherFunctor5')
    >>> fk(2.0, 3)
    10.0
    >>> fk = FunctionKeeper('default')
    >>> bool(fk)
    False
    >>> fk(2.0, 3)
    Traceback (most recent call last):
    ...
    RuntimeError: Trying to call undefined function!
    >>> fk.set_function('AddAnotherFunctor5')
    >>> fk(2.0, 3)
    10.0
    >>> bool(fk)
    True
    >>> fk.set_function('NULL')
    >>> bool(fk)
    False
    """
    cdef cpp_function_lib.FunctionKeeper* function_keeper
    
    cdef function[double(double, int) noexcept]* _get_function_ptr_from_name(self, function_name):
        cdef function[double(double, int) noexcept] *f
        
        if function_name == 'add_one':
            f = new function[double(double, int) noexcept](cpp_function_lib.add_one)
        elif function_name == 'add_two':
            f = new function[double(double, int) noexcept](cpp_function_lib.add_two)
        elif function_name == 'AddAnotherFunctor5':
            f = new function[double(double, int) noexcept]()
            f[0] = cpp_function_lib.AddAnotherFunctor(5.0)
        elif function_name == 'NULL':
            f = new function[double(double, int) noexcept](NULL)
        elif function_name == 'default':
            f = new function[double(double, int) noexcept]()
            
        return f
   
    def __cinit__(self, function_name):
        cdef function[double(double, int) noexcept] *f = self._get_function_ptr_from_name(function_name)
        self.function_keeper = new cpp_function_lib.FunctionKeeper(f[0])
        del f

    def __dealloc__(self):
        del self.function_keeper

    def __call__(self, a, b):
        return self.function_keeper.call_function(a, b)

    def __bool__(self):
        return  self.function_keeper.get_function()

    def set_function(self, function_name):
        cdef function[double(double, int) noexcept] *f = self._get_function_ptr_from_name(function_name)
        self.function_keeper.set_function(f[0])
        del f
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_list.pyx0000644000175100001770000000550700000000000021012 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, no-cpp-locals

from cython.operator cimport dereference as deref
from cython.operator cimport preincrement as incr

from libcpp.list cimport list as cpp_list
from libcpp cimport bool as cbool


def simple_test(double x):
    """
    >>> simple_test(55)
    3
    """
    l = new cpp_list[double]()
    try:
        l.push_back(1.0)
        l.push_back(x)
        from math import pi
        l.push_back(pi)
        return l.size()
    finally:
        del l

def pylist_test(L):
    """
    >>> pylist_test([1,2,4,8])
    (4, 4)
    >>> pylist_test([])
    (0, 0)
    >>> pylist_test([-1] * 1000)
    (1000, 1000)
    """
    l = new cpp_list[int]()
    try:
        for a in L:
            l.push_back(a)
        return len(L), l.size()
    finally:
        del l


def iteration_test(L):
    """
    >>> iteration_test([1,2,4,8])
    1
    2
    4
    8
    """
    l = new cpp_list[int]()
    try:
        for a in L:
            l.push_back(a)
        it = l.begin()
        while it != l.end():
            a = deref(it)
            incr(it)
            print(a)
    finally:
        del l

def reverse_iteration_test(L):
    """
    >>> reverse_iteration_test([1,2,4,8])
    8
    4
    2
    1
    """
    l = new cpp_list[int]()
    try:
        for a in L:
            l.push_back(a)
        it = l.rbegin()
        while it != l.rend():
            a = deref(it)
            incr(it)
            print(a)
    finally:
        del l

def nogil_test(L):
    """
    >>> nogil_test([1,2,3])
    3
    """
    cdef int a
    with nogil:
        l = new cpp_list[int]()
    try:
        for a in L:
            with nogil:
                l.push_back(a)
        return l.size()
    finally:
        del l


cdef list to_pylist(cpp_list[int]& l):
    cdef list L = []
    it = l.begin()
    while it != l.end():
        L.append(deref(it))
        incr(it)
    return L

def item_ptr_test(L, int x):
    """
    >>> item_ptr_test(range(10), 100)
    [100, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    """
    cdef cpp_list[int] l = L
    cdef int* li_ptr = &l.front()
    li_ptr[0] = x
    return to_pylist(l)

def test_value_type(x):
    """
    >>> test_value_type(2)
    2.0
    >>> test_value_type(2.5)
    2.5
    """
    cdef cpp_list[double].value_type val = x
    return val

def test_value_type_complex(x):
    """
    >>> test_value_type_complex(2)
    (2+0j)
    """
    cdef cpp_list[double complex].value_type val = x
    return val

def test_insert():
    """
    >>> test_insert()
    """
    cdef cpp_list[int] l
    cdef cpp_list[int].size_type count = 5
    cdef int value = 0

    l.insert(l.end(), count, value)

    assert l.size() == count
    for element in l:
        assert element == value, '%s != %s' % (element, count)


#  Tests GitHub issue #1788.
cdef cppclass MyList[T](cpp_list):
    pass

cdef cppclass Ints(MyList[int]):
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_list_cpp11.pyx0000644000175100001770000000167300000000000022016 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, no-cpp-locals, cpp11

from cython.operator cimport dereference as deref
from cython.operator cimport preincrement as incr

from libcpp.list cimport list as cpp_list

def const_iteration_test(L):
    """
    >>> const_iteration_test([1,2,4,8])
    1
    2
    4
    8
    """
    l = new cpp_list[int]()
    try:
        for a in L:
            l.push_back(a)
        it = l.cbegin()
        while it != l.cend():
            a = deref(it)
            incr(it)
            print(a)
    finally:
        del l

cdef list const_to_pylist(cpp_list[int]& l):
    cdef list L = []
    it = l.cbegin()
    while it != l.cend():
        L.append(deref(it))
        incr(it)
    return L

def const_item_ptr_test(L, int x):
    """
    >>> const_item_ptr_test(range(10), 100)
    [100, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    """
    cdef cpp_list[int] l = L
    cdef int* li_ptr = &l.front()
    li_ptr[0] = x
    return const_to_pylist(l)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_map.pyx0000644000175100001770000001271500000000000020613 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp11

# cython: language_level=3

from libcpp.map cimport map
from libcpp.unordered_map cimport unordered_map
from libcpp.utility cimport pair

def test_map_insert(vals):
    """
    >>> test_map_insert([(1,1),(2,2),(2,2),(3,3),(-1,-1)])
    [(-1, -1), (1, 1), (2, 2), (3, 3)]
    """
    cdef map[int,int] m = map[int, int]()
    cdef pair[map[int, int].iterator, bint] ret
    for v in vals:
        ret = m.insert(v)
    return [ (item.first, item.second) for item in m ]

def test_map_insert_it(vals):
    """
    >>> test_map_insert_it([(1,1),(2,2),(2,2),(3,3),(-1,-1)])
    [(-1, -1), (1, 1), (2, 2), (3, 3)]
    """
    cdef unordered_map[int,int] um = unordered_map[int,int]()
    cdef map[int,int] m = map[int,int]()
    for k, v in vals:
        um.insert(pair[int,int](k, v))
    m.insert(um.begin(), um.end())
    return [ (item.first, item.second) for item in m ]

def test_const_map_insert_it(vals):
    """
    >>> test_const_map_insert_it([(1,1),(2,2),(2,2),(3,3),(-1,-1)])
    [(-1, -1), (1, 1), (2, 2), (3, 3)]
    """
    cdef unordered_map[int,int] um = unordered_map[int,int]()
    cdef map[int,int] m = map[int,int]()
    for k, v in vals:
        um.insert(pair[int,int](k, v))
    m.insert(um.cbegin(), um.cend())
    return [ (item.first, item.second) for item in m ]

def test_map_count(vals, to_find):
    """
    >>> test_map_count([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 1)
    1
    >>> test_map_count([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 2)
    1
    """
    cdef map[int,int] m = map[int,int]()
    for v in vals:
        m.insert(v)
    return m.count(to_find)

def test_map_erase(vals, int to_remove):
    """
    >>> test_map_erase([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 1)
    [(-1, -1), (2, 2), (3, 3)]
    >>> test_map_erase([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 2)
    [(-1, -1), (1, 1), (3, 3)]
    """
    cdef map[int,int] m = map[int,int]()
    cdef size_t ret
    for v in vals:
        m.insert(v)
    ret = m.erase(to_remove)
    return [ (item.first, item.second) for item in m ]

def test_map_find_erase(vals, to_remove):
    """
    >>> test_map_find_erase([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 1)
    [(-1, -1), (2, 2), (3, 3)]
    >>> test_map_find_erase([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 2)
    [(-1, -1), (1, 1), (3, 3)]
    """
    cdef map[int,int] m = map[int,int]()
    cdef map[int,int].iterator it
    for v in vals:
        m.insert(v)
    it = m.find(to_remove)
    it = m.erase(it)
    return [ (item.first, item.second) for item in m ]


def test_unordered_map_insert(vals):
    """
    >>> test_unordered_map_insert([(1,1),(2,2),(2,2),(3,3),(-1,-1)])
    [(-1, -1), (1, 1), (2, 2), (3, 3)]
    """
    cdef unordered_map[int,int] um = unordered_map[int,int]()
    cdef pair[unordered_map[int,int].iterator, bint] ret
    for v in vals:
        ret = um.insert(v)
    return sorted([ (item.first, item.second) for item in um ])

def test_unordered_map_insert_it(vals):
    """
    >>> test_unordered_map_insert_it([(1,1),(2,2),(2,2),(3,3),(-1,-1)])
    [(-1, -1), (1, 1), (2, 2), (3, 3)]
    """
    cdef map[int,int] m = map[int,int]()
    cdef unordered_map[int,int] um = unordered_map[int,int]()
    for v in vals:
        m.insert(v)
    um.insert(m.begin(), m.end())
    return sorted([ (item.first, item.second) for item in um ])

def test_const_unordered_map_insert_it(vals):
    """
    >>> test_const_unordered_map_insert_it([(1,1),(2,2),(2,2),(3,3),(-1,-1)])
    [(-1, -1), (1, 1), (2, 2), (3, 3)]
    """
    cdef map[int,int] m = map[int,int]()
    cdef unordered_map[int,int] um = unordered_map[int,int]()
    for v in vals:
        m.insert(v)
    um.insert(m.cbegin(), m.cend())
    return sorted([ (item.first, item.second) for item in um ])

def test_unordered_map_count(vals, to_find):
    """
    >>> test_unordered_map_count([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 1)
    1
    >>> test_unordered_map_count([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 2)
    1
    """
    cdef unordered_map[int,int] um = unordered_map[int,int]()
    for v in vals:
        um.insert(v)
    return um.count(to_find)

def test_unordered_map_erase(vals, int to_remove):
    """
    >>> test_unordered_map_erase([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 1)
    [(-1, -1), (2, 2), (3, 3)]
    >>> test_unordered_map_erase([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 2)
    [(-1, -1), (1, 1), (3, 3)]
    """
    cdef unordered_map[int,int] um = unordered_map[int,int]()
    cdef size_t ret
    for v in vals:
        um.insert(v)
    ret = um.erase(to_remove)
    return sorted([ (item.first, item.second) for item in um ])

def test_unordered_map_find_erase(vals, to_remove):
    """
    >>> test_unordered_map_find_erase([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 1)
    [(-1, -1), (2, 2), (3, 3)]
    >>> test_unordered_map_find_erase([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 2)
    [(-1, -1), (1, 1), (3, 3)]
    """
    cdef unordered_map[int,int] um = unordered_map[int,int]()
    cdef unordered_map[int,int].iterator it
    for v in vals:
        um.insert(v)
    it = um.find(to_remove)
    it = um.erase(it)
    return sorted([ item for item in um ])

def test_iterator_stack_allocated():
    """
    https://github.com/cython/cython/issues/4657 - mainly a compile test showing
    that const iterators can be stack allocated
    >>> test_iterator_stack_allocated()
    """
    cdef map[int,int] mymap = map[int,int]()
    cdef unordered_map[int,int] myumap = unordered_map[int,int]()
    cdef int ckey = 5
    it = mymap.const_find(ckey)
    assert it == mymap.const_end()
    uit = myumap.const_find(ckey)
    assert uit == myumap.const_end()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_multimap.pyx0000644000175100001770000001264100000000000021664 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp11

# cython: language_level=3

from libcpp.map cimport multimap
from libcpp.unordered_map cimport unordered_multimap
from libcpp.utility cimport pair

def test_multimap_insert(vals):
    """
    >>> test_multimap_insert([(1,1),(2,2),(2,2),(3,3),(-1,-1)])
    [(-1, -1), (1, 1), (2, 2), (2, 2), (3, 3)]
    """
    cdef multimap[int,int] mm = multimap[int, int]()
    cdef multimap[int, int].iterator it
    for v in vals:
        it = mm.insert(v)
    return [ (item.first, item.second) for item in mm ]

def test_multimap_insert_it(vals):
    """
    >>> test_multimap_insert_it([(1,1),(2,2),(2,2),(3,3),(-1,-1)])
    [(-1, -1), (1, 1), (2, 2), (2, 2), (3, 3)]
    """
    cdef unordered_multimap[int,int] umm = unordered_multimap[int,int]()
    cdef multimap[int,int] mm = multimap[int,int]()
    for k, v in vals:
        umm.insert(pair[int,int](k, v))
    mm.insert(umm.begin(), umm.end())
    return [ (item.first, item.second) for item in mm ]

def test_const_multimap_insert_it(vals):
    """
    >>> test_const_multimap_insert_it([(1,1),(2,2),(2,2),(3,3),(-1,-1)])
    [(-1, -1), (1, 1), (2, 2), (2, 2), (3, 3)]
    """
    cdef unordered_multimap[int,int] umm = unordered_multimap[int,int]()
    cdef multimap[int,int] mm = multimap[int,int]()
    for k, v in vals:
        umm.insert(pair[int,int](k, v))
    mm.insert(umm.cbegin(), umm.cend())
    return [ (item.first, item.second) for item in mm ]

def test_multimap_count(vals, to_find):
    """
    >>> test_multimap_count([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 1)
    1
    >>> test_multimap_count([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 2)
    2
    """
    cdef multimap[int,int] mm = multimap[int,int]()
    for v in vals:
        mm.insert(v)
    return mm.count(to_find)

def test_multimap_erase(vals, int to_remove):
    """
    >>> test_multimap_erase([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 1)
    [(-1, -1), (2, 2), (2, 2), (3, 3)]
    >>> test_multimap_erase([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 2)
    [(-1, -1), (1, 1), (3, 3)]
    """
    cdef multimap[int,int] mm = multimap[int,int]()
    for v in vals:
        mm.insert(v)
    cdef size_t ret = mm.erase(to_remove)
    return [ (item.first, item.second) for item in mm ]

def test_multimap_find_erase(vals, to_remove):
    """
    >>> test_multimap_find_erase([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 1)
    [(-1, -1), (2, 2), (2, 2), (3, 3)]
    >>> test_multimap_find_erase([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 2)
    [(-1, -1), (1, 1), (2, 2), (3, 3)]
    """
    cdef multimap[int,int] mm = multimap[int,int]()
    cdef multimap[int,int].iterator it
    for v in vals:
        mm.insert(v)
    it = mm.find(to_remove)
    it = mm.erase(it)
    return [ (item.first, item.second) for item in mm ]


def test_unordered_multimap_insert(vals):
    """
    >>> test_unordered_multimap_insert([(1,1),(2,2),(2,2),(3,3),(-1,-1)])
    [(-1, -1), (1, 1), (2, 2), (2, 2), (3, 3)]
    """
    cdef unordered_multimap[int,int] umm = unordered_multimap[int,int]()
    cdef unordered_multimap[int,int].iterator it
    for v in vals:
        it = umm.insert(v)
    return sorted([ (item.first, item.second) for item in umm ])

def test_unordered_multimap_insert_it(vals):
    """
    >>> test_unordered_multimap_insert_it([(1,1),(2,2),(2,2),(3,3),(-1,-1)])
    [(-1, -1), (1, 1), (2, 2), (2, 2), (3, 3)]
    """
    cdef multimap[int,int] mm = multimap[int,int]()
    cdef unordered_multimap[int,int] umm = unordered_multimap[int,int]()
    for v in vals:
        mm.insert(v)
    umm.insert(mm.begin(), mm.end())
    return sorted([ (item.first, item.second) for item in umm ])

def test_const_unordered_multimap_insert_it(vals):
    """
    >>> test_const_unordered_multimap_insert_it([(1,1),(2,2),(2,2),(3,3),(-1,-1)])
    [(-1, -1), (1, 1), (2, 2), (2, 2), (3, 3)]
    """
    cdef multimap[int,int] mm = multimap[int,int]()
    cdef unordered_multimap[int,int] umm = unordered_multimap[int,int]()
    for v in vals:
        mm.insert(v)
    umm.insert(mm.cbegin(), mm.cend())
    return sorted([ (item.first, item.second) for item in umm ])

def test_unordered_multimap_count(vals, to_find):
    """
    >>> test_unordered_multimap_count([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 1)
    1
    >>> test_unordered_multimap_count([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 2)
    2
    """
    cdef unordered_multimap[int,int] umm = unordered_multimap[int,int]()
    for v in vals:
        umm.insert(v)
    return umm.count(to_find)

def test_unordered_multimap_erase(vals, int to_remove):
    """
    >>> test_unordered_multimap_erase([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 1)
    [(-1, -1), (2, 2), (2, 2), (3, 3)]
    >>> test_unordered_multimap_erase([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 2)
    [(-1, -1), (1, 1), (3, 3)]
    """
    cdef unordered_multimap[int,int] umm = unordered_multimap[int,int]()
    for v in vals:
        umm.insert(v)
    cdef size_t ret = umm.erase(to_remove)
    return sorted([ (item.first, item.second) for item in umm ])

def test_unordered_multimap_find_erase(vals, to_remove):
    """
    >>> test_unordered_multimap_find_erase([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 1)
    [(-1, -1), (2, 2), (2, 2), (3, 3)]
    >>> test_unordered_multimap_find_erase([(1,1),(2,2),(2,2),(3,3),(-1,-1)], 2)
    [(-1, -1), (1, 1), (2, 2), (3, 3)]
    """
    cdef unordered_multimap[int,int] umm = unordered_multimap[int,int]()
    cdef unordered_multimap[int,int].iterator it
    for v in vals:
        umm.insert(v)
    it = umm.find(to_remove)
    it = umm.erase(it)
    return sorted([ item for item in umm ])
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_multiset.pyx0000644000175100001770000001126700000000000021705 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp11

# cython: language_level=3

from libcpp.set cimport multiset
from libcpp.unordered_set cimport unordered_multiset

def test_multiset_insert(vals):
    """
    >>> test_multiset_insert([1,2,2,3, -1])
    [-1, 1, 2, 2, 3]
    """
    cdef multiset[int] ms = multiset[int]()
    cdef multiset[int].iterator it
    for v in vals:
        it = ms.insert(v)
    return [ item for item in ms ]

def test_multiset_insert_it(vals):
    """
    >>> test_multiset_insert_it([1,2,2,3, -1])
    [-1, 1, 2, 2, 3]
    """
    cdef unordered_multiset[int] ums = unordered_multiset[int]()
    cdef multiset[int] ms = multiset[int]()
    for v in vals:
        ums.insert(v)
    ms.insert(ums.begin(), ums.end())
    return [ item for item in ms ]

def test_const_multiset_insert_it(vals):
    """
    >>> test_const_multiset_insert_it([1,2,2,3, -1])
    [-1, 1, 2, 2, 3]
    """
    cdef unordered_multiset[int] ums = unordered_multiset[int]()
    cdef multiset[int] ms = multiset[int]()
    for v in vals:
        ums.insert(v)
    ms.insert(ums.cbegin(), ums.cend())
    return [ item for item in ms ]

def test_multiset_count(vals, to_find):
    """
    >>> test_multiset_count([1,2,2,3, -1], 1)
    1
    >>> test_multiset_count([1,2,2,3, -1], 2)
    2
    """
    cdef multiset[int] ms = multiset[int]()
    for v in vals:
        ms.insert(v)
    return ms.count(to_find)

def test_multiset_erase(vals, int to_remove):
    """
    >>> test_multiset_erase([1,2,2,3, -1], 1)
    [-1, 2, 2, 3]
    >>> test_multiset_erase([1,2,2,3, -1], 2)  # removes both copies of 2
    [-1, 1, 3]
    """
    cdef multiset[int] ms = multiset[int]()
    cdef size_t ret
    for v in vals:
        ms.insert(v)
    ret = ms.erase(to_remove)
    return [ item for item in ms ]

def test_multiset_find_erase(vals, to_remove):
    """
    >>> test_multiset_find_erase([1,2,2,3, -1], 1)
    [-1, 2, 2, 3]
    >>> test_multiset_find_erase([1,2,2,3, -1], 2)  # removes a single copy of 2
    [-1, 1, 2, 3]
    """
    cdef multiset[int] ms = multiset[int]()
    cdef multiset[int].iterator it
    for v in vals:
        ms.insert(v)
    it = ms.find(to_remove)
    it = ms.erase(it)
    return [ item for item in ms ]


def test_unordered_multiset_insert(vals):
    """
    >>> test_unordered_multiset_insert([1,2,2,3, -1])
    [-1, 1, 2, 2, 3]
    """
    cdef unordered_multiset[int] ums = unordered_multiset[int]()
    cdef unordered_multiset[int].iterator it
    for v in vals:
        it = ums.insert(v)
    return sorted([ item for item in ums ])

def test_unordered_multiset_insert_it(vals):
    """
    >>> test_unordered_multiset_insert_it([1,2,2,3, -1])
    [-1, 1, 2, 2, 3]
    """
    cdef multiset[int] ms = multiset[int]()
    cdef unordered_multiset[int] ums = unordered_multiset[int]()
    for v in vals:
        ms.insert(v)
    ums.insert(ms.begin(), ms.end())
    return sorted([ item for item in ums ])

def test_const_unordered_multiset_insert_it(vals):
    """
    >>> test_const_unordered_multiset_insert_it([1,2,2,3, -1])
    [-1, 1, 2, 2, 3]
    """
    cdef multiset[int] ms = multiset[int]()
    cdef unordered_multiset[int] ums = unordered_multiset[int]()
    for v in vals:
        ms.insert(v)
    ums.insert(ms.cbegin(), ms.cend())
    return sorted([ item for item in ums ])

def test_unordered_multiset_count(vals, to_find):
    """
    >>> test_unordered_multiset_count([1,2,2,3, -1], 1)
    1
    >>> test_unordered_multiset_count([1,2,2,3, -1], 2)
    2
    """
    cdef unordered_multiset[int] ums = unordered_multiset[int]()
    for v in vals:
        ums.insert(v)
    return ums.count(to_find)

def test_unordered_multiset_erase(vals, int to_remove):
    """
    >>> test_unordered_multiset_erase([1,2,2,3, -1], 1)
    [-1, 2, 2, 3]
    >>> test_unordered_multiset_erase([1,2,2,3, -1], 2)  # removes both copies of 2
    [-1, 1, 3]
    """
    cdef unordered_multiset[int] ums = unordered_multiset[int]()
    cdef size_t ret
    for v in vals:
        ums.insert(v)
    ret = ums.erase(to_remove)
    return sorted([ item for item in ums ])

def test_unordered_multiset_find_erase(vals, to_remove):
    """
    >>> test_unordered_multiset_find_erase([1,2,2,3, -1], 1)
    [-1, 2, 2, 3]
    >>> test_unordered_multiset_find_erase([1,2,2,3, -1], 2)  # removes a single copy of 2
    [-1, 1, 2, 3]
    """
    cdef unordered_multiset[int] ums = unordered_multiset[int]()
    cdef unordered_multiset[int].iterator it
    for v in vals:
        ums.insert(v)
    it = ums.find(to_remove)
    it = ums.erase(it)
    return sorted([ item for item in ums ])


def test_unordered_multiset_misc():
    """
    >>> test_unordered_multiset_misc()
    """
    cdef unordered_multiset[int] ms = unordered_multiset[int]()
    ms.insert(1)
    assert ms.load_factor() > 0
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_numbers.pyx0000644000175100001770000000041600000000000021504 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp20, cpp

from libcpp.numbers cimport pi, e


def test_pi():
    """
    >>> import math
    >>> test_pi() == math.pi
    True
    """
    return pi

def test_e():
    """
    >>> import math
    >>> test_e() == math.e
    True
    """
    return e
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_numeric_ops.pyx0000644000175100001770000000774200000000000022365 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp11

from libcpp.numeric cimport inner_product, iota, accumulate, adjacent_difference, partial_sum
from libcpp.vector cimport vector
from libcpp cimport bool

# Subtracts two integers.
cdef int subtract_integers(int lhs, int rhs):
    return lhs - rhs

# Adds two integers.
cdef int add_integers(int lhs, int rhs):
    return lhs + rhs

# Multiplies two integers.
cdef int multiply_integers(int lhs, int rhs):
    return lhs * rhs

# Determines equality for two integers.
# If lhs == rhs, returns true. Returns false otherwise.
cdef bool is_equal(int lhs, int rhs):
    return lhs == rhs

def test_inner_product(vector[int] v1, vector[int] v2, int init):
    """
    Test inner_product with integer values.
    >>> test_inner_product([1, 2, 3], [1, 2, 3], 1)
    15
    """
    return inner_product(v1.begin(), v1.end(), v2.begin(), init)


def test_inner_product_with_zero(vector[int] v1, vector[int] v2, int init):
    """
    Test inner_product with a zero value in the container.
    >>> test_inner_product_with_zero([1, 2, 0], [1, 1, 1], 0)
    3
    """
    return inner_product(v1.begin(), v1.end(), v2.begin(), init)

def test_inner_product_with_bin_op(vector[int] v1, vector[int] v2, int init):
    """
    Test inner_product with two binary operations. In this case,
    Looks at number of pairwise matches between v1 and v2.
    [5, 1, 2, 3, 4]
    [5, 4, 2, 3, 1]
    There are 3 matches (5, 2, 3). So, 1 + 1 + 1 = 3.

    >>> test_inner_product_with_bin_op([5, 1, 2, 3, 4], [5, 4, 2, 3, 1], 0)
    3
    """
    return inner_product(v1.begin(), v1.end(), v2.begin(), init, add_integers, is_equal)

def test_iota(vector[int] v, int value):
    """
    Test iota with beginning value of 0.
    >>> test_iota(range(6), 0)
    [0, 1, 2, 3, 4, 5]
    """
    iota(v.begin(), v.end(), value)
    return v

def test_iota_negative_init(vector[int] v, int value):
    """
    Test iota with a negative beginning value.
    >>> test_iota_negative_init(range(7), -4)
    [-4, -3, -2, -1, 0, 1, 2]
    """
    iota(v.begin(), v.end(), value)
    return v

def test_accumulate(vector[int] v, int init):
    """
    Test accumulate.
     0 + 1 = 1
     1 + 2 = 3
     3 + 3 = 6
    >>> test_accumulate([1, 2, 3], 0)
    6
    """
    return accumulate(v.begin(), v.end(), init)

def test_accumulate_with_subtraction(vector[int] v, int init):
    """
    Test accumulate with subtraction. Note that accumulate is a fold-left operation.
     0 - 1 = -1
    -1 - 2 = -3
    -3 - 3 = -6
    >>> test_accumulate_with_subtraction([1, 2, 3], 0)
    -6
    """
    return accumulate(v.begin(), v.end(), init, subtract_integers)

def test_adjacent_difference(vector[int] v):
    """
    Test adjacent_difference with integer values.
    2 - 0,   -> 2
    4 - 2,   -> 2
    6 - 4,   -> 2
    8 - 6,   -> 2
    10 - 8,  -> 2
    12 - 10  -> 2
    >>> test_adjacent_difference([2, 4, 6, 8, 10, 12])
    [2, 2, 2, 2, 2, 2]
    """
    adjacent_difference(v.begin(), v.end(), v.begin())
    return v

def test_adjacent_difference_with_bin_op(vector[int] v):
    """
    Test adjacent_difference with a binary operation.
    0 + 1 -> 1
    1 + 2 -> 3
    2 + 4 -> 6
    4 + 5 -> 9
    5 + 6 -> 11
    >>> test_adjacent_difference_with_bin_op([1, 2, 4, 5, 6])
    [1, 3, 6, 9, 11]
    """
    adjacent_difference(v.begin(), v.end(), v.begin(), add_integers)
    return v

def test_partial_sum(vector[int] v):
    """
    Test partial_sum with integer values.
    2 + 0   -> 2
    2 + 2   -> 4
    4 + 2   -> 6
    6 + 2   -> 8
    8 + 2   -> 10
    10 + 2  -> 12
    >>> test_partial_sum([2, 2, 2, 2, 2, 2])
    [2, 4, 6, 8, 10, 12]
    """
    partial_sum(v.begin(), v.end(), v.begin())
    return v

def test_partial_sum_with_bin_op(vector[int] v):
    """
    Test partial_sum with a binary operation.
    Using multiply_integers, partial_sum will calculate the first 5 powers of 2.
    >>> test_partial_sum_with_bin_op([2, 2, 2, 2, 2])
    [2, 4, 8, 16, 32]
    """
    partial_sum(v.begin(), v.end(), v.begin(), multiply_integers)
    return v
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_numeric_ops_cpp17.pyx0000644000175100001770000002336000000000000023371 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp17, cppexecpolicies

from libcpp.numeric cimport (reduce, transform_reduce, inclusive_scan, 
                             exclusive_scan, transform_inclusive_scan, 
                             transform_exclusive_scan, gcd, lcm)
from libcpp.execution cimport seq
from libcpp.vector cimport vector

# Subtracts two integers.
cdef int subtract_integers(int lhs, int rhs):
    return lhs - rhs

# Adds two integers.
cdef int add_integers(int lhs, int rhs):
    return lhs + rhs

# Multiplies two integers.
cdef int multiply_integers(int lhs, int rhs):
    return lhs * rhs

# Multiplies a integer with 2
cdef int multiply_with_2(int val):
    return 2*val

def test_reduce(vector[int] v, int init):
    """
    Test reduce.
     0 + 1 = 1
     1 + 2 = 3
     3 + 3 = 6
    >>> test_reduce([1, 2, 3], 0)
    6
    """
    return reduce(v.begin(), v.end(), init)

def test_reduce_with_bin_op(vector[int] v, int init):
    """
    Test reduce with a binary operation (subtraction). 
     0 - 1 = -1
    -1 - 2 = -3
    -3 - 3 = -6
    >>> test_reduce_with_bin_op([1, 2, 3], 0)
    -6
    """
    return reduce(v.begin(), v.end(), init, subtract_integers)

# def test_reduce_with_execpolicy(vector[int] v, int init):
#     """
#     Test reduce with execution policy. 
#      0 + 1 = 1
#      1 + 2 = 3
#      3 + 3 = 6
#     >>> test_reduce_with_execpolicy([1, 2, 3], 0)
#     6
#     """
#     return reduce(seq, v.begin(), v.end(), init)

def test_reduce_with_bin_op_and_execpolicy(vector[int] v, int init):
    """
    Test reduce with execution policy and a binary operation (subtraction). 
     0 - 1 = -1
    -1 - 2 = -3
    -3 - 3 = -6
    >>> test_reduce_with_bin_op_and_execpolicy([1, 2, 3], 0)
    -6
    """
    return reduce(seq, v.begin(), v.end(), init, subtract_integers)

def test_transform_reduce(vector[int] v1, vector[int] v2, int init):
    """
    Test transform_reduce
    >>> test_transform_reduce([1, 2, 3], [1, 2, 3], 0)
    14
    """
    return transform_reduce(v1.begin(), v1.end(), v2.begin(), init)

def test_transform_reduce_with_bin_red_op_and_bin_tran_op(vector[int] v1, vector[int] v2, int init):
    """
    Test transform_reduce with a binary reduce and transform operations
    >>> test_transform_reduce_with_bin_red_op_and_bin_tran_op([1, 2, 3], [1, 2, 3], 0)
    14
    """
    return transform_reduce(v1.begin(), v1.end(), v2.begin(), init, add_integers, multiply_integers)

def test_transform_reduce_with_bin_op_and_unary_op(vector[int] v1, vector[int] v2, int init):
    """
    Test transform_reduce with a binary reduction and a unary transform operation
    >>> test_transform_reduce_with_bin_op_and_unary_op([1, 2, 3], [1, 2, 3], 0)
    12
    """
    return transform_reduce(v1.begin(), v1.end(), init, add_integers, multiply_with_2)

# def test_transform_reduce_with_execpolicy(vector[int] v1, vector[int] v2, int init):
#     """
#     Test transform_reduce with a execution policy
#     >>> test_transform_reduce_with_execpolicy([1, 2, 3], [1, 2, 3], 0)
#     14
#     """
#     return transform_reduce(seq, v1.begin(), v1.end(), v2.begin(), init)

def test_transform_reduce_with_execpolicy_bin_red_op_and_bin_tran_op(vector[int] v1, vector[int] v2, int init):
    """
    Test transform_reduce with a execution policy and binary reduce and transform operations
    >>> test_transform_reduce_with_execpolicy_bin_red_op_and_bin_tran_op([1, 2, 3], [1, 2, 3], 0)
    14
    """
    return transform_reduce(seq, v1.begin(), v1.end(), v2.begin(), init, add_integers, multiply_integers)

# def test_transform_reduce_with_execpolicy_bin_op_and_unary_op(vector[int] v1, vector[int] v2, int init):
#     """
#     Test transform_reduce with a execution policy and binary reduction and a unary transform operation
#     >>> test_transform_reduce_with_execpolicy_bin_op_and_unary_op([1, 2, 3], [1, 2, 3], 0)
#     12
#     """
#     return transform_reduce(seq, v1.begin(), v1.end(), v2.begin(), init, add_integers, multiply_with_2)

def test_inclusive_scan(vector[int] v):
    """
    Test inclusive_scan
    >>> test_inclusive_scan([1, 2, 3, 4])
    [1, 3, 6, 10]
    """
    cdef vector[int] out = vector[int](v.size())
    inclusive_scan(v.begin(), v.end(), out.begin())
    return out

# def test_inclusive_scan_with_execpolicy(vector[int] v):
#     """
#     Test inclusive_scan with a execution policy
#     >>> test_inclusive_scan_with_execpolicy([1, 2, 3, 4])
#     [1, 3, 6, 10]
#     """
#     cdef vector[int] out
#     inclusive_scan(seq, v.begin(), v.end(), out.begin())
#     return out

def test_inclusive_scan_with_bin_op(vector[int] v):
    """
    Test inclusive_scan with a binary operation
    >>> test_inclusive_scan_with_bin_op([1, 2, 3, 4])
    [1, 3, 6, 10]
    """
    cdef vector[int] out = vector[int](v.size())
    inclusive_scan(v.begin(), v.end(), out.begin(), add_integers)
    return out

# def test_inclusive_scan_with_execpolicy_and_bin_op(vector[int] v):
#     """
#     Test inclusive_scan with a execution policy and a binary operation
#     >>> test_inclusive_scan_with_execpolicy_and_bin_op([1, 2, 3, 4])
#     [1, 3, 6, 10]
#     """
#     cdef vector[int] out
#     inclusive_scan(seq, v.begin(), v.end(), out.begin(), add_integers)
#     return out

def test_inclusive_scan_with_bin_op_and_init(vector[int] v, int init):
    """
    Test inclusive_scan with a binary operation and a initial value
    >>> test_inclusive_scan_with_bin_op_and_init([1, 2, 3, 4], 0)
    [1, 3, 6, 10]
    """
    cdef vector[int] out = vector[int](v.size())
    inclusive_scan(v.begin(), v.end(), out.begin(), add_integers, init)
    return out

# def test_inclusive_scan_with_execpolicy_bin_op_and_init(vector[int] v, int init):
#     """
#     Test inclusive_scan with a execution policy, a binary operation and a initial value
#     >>> test_inclusive_scan_with_execpolicy_bin_op_and_init([1, 2, 3, 4], 0)
#     [1, 3, 6, 10]
#     """
#     cdef vector[int] out = vector[int](v.size())
#     inclusive_scan(seq, v.begin(), v.end(), out.begin(), add_integers, init)
#     return out

def test_transform_inclusive_scan(vector[int] v):
    """
    Test transform inclusive_scan
    >>> test_transform_inclusive_scan([1, 2, 3, 4])
    [2, 6, 12, 20]
    """
    cdef vector[int] out = vector[int](v.size())
    transform_inclusive_scan(v.begin(), v.end(), out.begin(), add_integers, multiply_with_2)
    return out

# def test_transform_inclusive_scan_with_execpolicy(vector[int] v):
#     """
#     Test transform inclusive_scan with a execution policy
#     >>> test_transform_inclusive_scan_with_execpolicy([1, 2, 3, 4])
#     [2, 6, 12, 20 ]
#     """
#     cdef vector[int] out
#     transform_inclusive_scan(seq, v.begin(), v.end(), out.begin(), add_integers, multiply_with_2)
#     return out

def test_transform_inclusive_scan_with_init(vector[int] v, int init):
    """
    Test transform inclusive_scan with an initial value
    >>> test_transform_inclusive_scan_with_init([1, 2, 3, 4], 0)
    [2, 6, 12, 20]
    """
    cdef vector[int] out = vector[int](v.size())
    transform_inclusive_scan(v.begin(), v.end(), out.begin(), add_integers, multiply_with_2, init)
    return out

def test_transform_inclusive_scan_with_execpolicy_and_init(vector[int] v, int init):
    """
    Test transform inclusive_scan with an initial value
    >>> test_transform_inclusive_scan_with_execpolicy_and_init([1, 2, 3, 4], 0)
    [2, 6, 12, 20]
    """
    cdef vector[int] out = vector[int](v.size())
    transform_inclusive_scan(seq, v.begin(), v.end(), out.begin(), add_integers, multiply_with_2, init)
    return out

def test_exclusive_scan(vector[int] v, int init):
    """
    Test exclusive_scan
    >>> test_exclusive_scan([1, 2, 3, 4], 0)
    [0, 1, 3, 6]
    """
    cdef vector[int] out = vector[int](v.size())
    exclusive_scan(v.begin(), v.end(), out.begin(), init)
    return out

# def test_exclusive_scan_with_execpolicy(vector[int] v, int init):
#     """
#     Test exclusive_scan with a execution policy
#     >>> test_exclusive_scan_with_execpolicy([1, 2, 3, 4], 0)
#     [0, 1, 3, 6]
#     """
#     cdef vector[int] out
#     exclusive_scan(seq, v.begin(), v.end(), out.begin(), init)
#     return out

def test_exclusive_scan_with_bin_op(vector[int] v, int init):
    """
    Test exclusive_scan with a binary operation
    >>> test_exclusive_scan_with_bin_op([1, 2, 3, 4], 0)
    [0, 1, 3, 6]
    """
    cdef vector[int] out = vector[int](v.size())
    exclusive_scan(v.begin(), v.end(), out.begin(), init, add_integers)
    return out

def test_exclusive_scan_with_execpolicy_and_bin_op(vector[int] v, int init):
    """
    Test exclusive_scan with a execution policy and a binary operation
    >>> test_exclusive_scan_with_execpolicy_and_bin_op([1, 2, 3, 4], 0)
    [0, 1, 3, 6]
    """
    cdef vector[int] out = vector[int](v.size())
    exclusive_scan(seq, v.begin(), v.end(), out.begin(), init, add_integers)
    return out


def test_transform_exclusive_scan_with_execpolicy(vector[int] v, int init):
    """
    Test transform_exclusive_scan
    >>> test_transform_exclusive_scan_with_execpolicy([1, 2, 3, 4], 0)
    [0, 2, 6, 12]
    """
    cdef vector[int] out = vector[int](v.size())
    transform_exclusive_scan(seq, v.begin(), v.end(), out.begin(), init, add_integers, multiply_with_2)
    return out

def test_transform_exclusive_scan_with_execpolicy(vector[int] v, int init):
    """
    Test transform_exclusive_scan with a execution policy
    >>> test_transform_exclusive_scan_with_execpolicy([1, 2, 3, 4], 0)
    [0, 2, 6, 12]
    """
    cdef vector[int] out = vector[int](v.size())
    transform_exclusive_scan(seq, v.begin(), v.end(), out.begin(), init, add_integers, multiply_with_2)
    return out

def test_gcd(int a, int b):
    """
    Test gcd
    >>> test_gcd(12, 18)
    6
    """
    return gcd[int](a, b)

def test_lcm(int a, int b):
    """
    Test lcm
    >>> test_lcm(45, 75)
    225
    """
    return lcm[int](a, b)././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_numeric_ops_cpp20.pyx0000644000175100001770000000070700000000000023363 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp20

from libcpp.numeric cimport midpoint

def test_midpoint_integer(int a, int b):
    """
    Test midpoint for integer types
    >>> test_midpoint_integer(2, 6)
    4
    """
    cdef int res = midpoint[int](a, b)
    return res


def test_midpoint_float(float a, float b):
    """
    Test midpoint for float
    >>> test_midpoint_float(2, 6)
    4.0
    """
    cdef float res = midpoint[float](a, b)
    return res
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_optional.pyx0000644000175100001770000000267600000000000021670 0ustar00runnerdocker00000000000000# ticket: 3293
# mode: run
# tag: cpp, cpp17, werror

from cython.operator cimport dereference as deref
from libcpp.optional cimport optional, nullopt, make_optional
from libcpp.string cimport string
from libcpp.pair cimport pair

def simple_test():
    """
    >>> simple_test()
    """
    cdef optional[int] o
    assert(not o.has_value())
    o = 5
    assert(o.has_value())
    assert(o.value()==5)
    o.reset()
    assert(not o.has_value())

def operator_test():
    """
    >>> operator_test()
    """
    cdef optional[int] o1, o2

    # operator bool
    assert(not o1)
    o1 = 5
    assert(o1)

    # operator *
    assert(deref(o1) == 5)

    # operator =,==,!=,>,<,>=,<=
    assert(not o1 == o2)
    assert(o1 != o2)
    o2 = o1
    assert(o1 == o2)
    assert(not o1 > o2)
    assert(not o1 < o2)
    assert(o1 >= o2)
    assert(o1 <= o2)

    # operators =,== for other types (all related operators are identical)
    o1 = 6
    assert(o1 == 6)
    o2 = nullopt
    assert(o2 == nullopt)

def misc_methods_test():
    """
    >>> misc_methods_test()
    """

    # make_optional
    cdef optional[int] o
    o = make_optional[int](5)
    assert(o == 5)

    # swap
    o.swap(optional[int](6))
    assert(o == 6)

    # emplace
    cdef optional[pair[int,int]] op
    cdef pair[int,int]* val_ptr = &op.emplace(1,2)
    assert(op.has_value())
    assert(op.value() == pair[int,int](1,2))
    assert(&op.value() == val_ptr) # check returned reference
    
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_random.pyx0000644000175100001770000002346100000000000021316 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp11

from libcpp.random cimport mt19937, mt19937_64, random_device, uniform_int_distribution, \
    uniform_real_distribution, bernoulli_distribution, binomial_distribution, \
    geometric_distribution, negative_binomial_distribution, poisson_distribution, \
    exponential_distribution, gamma_distribution, weibull_distribution, \
    extreme_value_distribution, normal_distribution, lognormal_distribution, \
    chi_squared_distribution, cauchy_distribution, fisher_f_distribution, student_t_distribution
from libc.float cimport DBL_MAX as DBL_MAX_


DBL_MAX = DBL_MAX_


def mt19937_seed_test():
    """
    >>> print(mt19937_seed_test())
    1608637542
    """
    cdef mt19937 gen = mt19937(42)
    return gen()


def mt19937_reseed_test():
    """
    >>> print(mt19937_reseed_test())
    1608637542
    """
    cdef mt19937 gen
    gen.seed(42)
    return gen()


def mt19937_min_max():
    """
    >>> x, y = mt19937_min_max()
    >>> print(x)
    0
    >>> print(y)  # 2 ** 32 - 1 because mt19937 is 32 bit.
    4294967295
    """
    cdef mt19937 gen
    return gen.min(), gen.max()


def mt19937_discard(z):
    """
    >>> x, y = mt19937_discard(13)
    >>> print(x)
    1972458954
    >>> print(y)
    1972458954
    """
    cdef mt19937 gen = mt19937(42)
    # Throw away z random numbers.
    gen.discard(z)
    a = gen()

    # Iterate over z random numbers.
    gen.seed(42)
    for _ in range(z + 1):
        b = gen()
    return a, b


def mt19937_64_seed_test():
    """
    >>> print(mt19937_64_seed_test())
    13930160852258120406
    """
    cdef mt19937_64 gen = mt19937_64(42)
    return gen()


def mt19937_64_reseed_test():
    """
    >>> print(mt19937_64_reseed_test())
    13930160852258120406
    """
    cdef mt19937_64 gen
    gen.seed(42)
    return gen()


def mt19937_64_min_max():
    """
    >>> x, y = mt19937_64_min_max()
    >>> print(x)
    0
    >>> print(y)  # 2 ** 64 - 1 because mt19937_64 is 64 bit.
    18446744073709551615
    """
    cdef mt19937_64 gen
    return gen.min(), gen.max()


def mt19937_64_discard(z):
    """
    >>> x, y = mt19937_64_discard(13)
    >>> print(x)
    11756813601242511406
    >>> print(y)
    11756813601242511406
    """
    cdef mt19937_64 gen = mt19937_64(42)
    # Throw away z random numbers.
    gen.discard(z)
    a = gen()

    # Iterate over z random numbers.
    gen.seed(42)
    for _ in range(z + 1):
        b = gen()
    return a, b


ctypedef fused any_dist:
    uniform_int_distribution[int]
    uniform_real_distribution[double]
    bernoulli_distribution
    binomial_distribution[int]
    geometric_distribution[int]
    negative_binomial_distribution[int]
    poisson_distribution[int]
    exponential_distribution[double]
    gamma_distribution[double]
    weibull_distribution[double]
    extreme_value_distribution[double]
    normal_distribution[double]
    lognormal_distribution[double]
    chi_squared_distribution[double]
    cauchy_distribution[double]
    fisher_f_distribution[double]
    student_t_distribution[double]


cdef sample_or_range(any_dist dist, bint sample):
    """
    This helper function returns a sample if `sample` is truthy and the range of the distribution
    if `sample` is falsy. We use a fused type to avoid duplicating the conditional statement in each
    distribution test.
    """
    cdef random_device rd
    if sample:
        dist(mt19937(rd()))
    else:
        return dist.min(), dist.max()


def uniform_int_distribution_test(a, b, sample=True):
    """
    >>> uniform_int_distribution_test(2, 3)
    >>> uniform_int_distribution_test(5, 9, False)
    (5, 9)
    """
    cdef uniform_int_distribution[int] dist = uniform_int_distribution[int](a, b)
    return sample_or_range[uniform_int_distribution[int]](dist, sample)


def uniform_real_distribution_test(a, b, sample=True):
    """
    >>> x = uniform_real_distribution_test(4, 5)
    >>> uniform_real_distribution_test(3, 8, False)
    (3.0, 8.0)
    """
    cdef uniform_real_distribution[double] dist = uniform_real_distribution[double](a, b)
    return sample_or_range[uniform_real_distribution[double]](dist, sample)


def bernoulli_distribution_test(proba, sample=True):
    """
    >>> bernoulli_distribution_test(0.2)
    >>> bernoulli_distribution_test(0.7, False)
    (False, True)
    """
    cdef bernoulli_distribution dist = bernoulli_distribution(proba)
    return sample_or_range[bernoulli_distribution](dist, sample)


def binomial_distribution_test(n, proba, sample=True):
    """
    >>> binomial_distribution_test(10, 0.7)
    >>> binomial_distribution_test(75, 0.3, False)
    (0, 75)
    """
    cdef binomial_distribution[int] dist = binomial_distribution[int](n, proba)
    return sample_or_range[binomial_distribution[int]](dist, sample)


def geometric_distribution_test(proba, sample=True):
    """
    >>> geometric_distribution_test(.4)
    >>> geometric_distribution_test(0.2, False)  # 2147483647 = 2 ** 32 - 1
    (0, 2147483647)
    """
    cdef geometric_distribution[int] dist = geometric_distribution[int](proba)
    return sample_or_range[geometric_distribution[int]](dist, sample)


def negative_binomial_distribution_test(n, p, sample=True):
    """
    >>> negative_binomial_distribution_test(5, .1)
    >>> negative_binomial_distribution_test(10, 0.2, False)  # 2147483647 = 2 ** 32 - 1
    (0, 2147483647)
    """
    cdef negative_binomial_distribution[int] dist = negative_binomial_distribution[int](n, p)
    return sample_or_range[negative_binomial_distribution[int]](dist, sample)


def poisson_distribution_test(rate, sample=True):
    """
    >>> poisson_distribution_test(7)
    >>> poisson_distribution_test(7, False)  # 2147483647 = 2 ** 32 - 1
    (0, 2147483647)
    """
    cdef poisson_distribution[int] dist = poisson_distribution[int](rate)
    return sample_or_range[poisson_distribution[int]](dist, sample)


def exponential_distribution_test(rate, sample=True):
    """
    >>> x = exponential_distribution_test(6)
    >>> l, u = exponential_distribution_test(1, False)
    >>> l
    0.0
    >>> u == DBL_MAX or u == float("inf")
    True
    """
    cdef exponential_distribution[double] dist = exponential_distribution[double](rate)
    return sample_or_range[exponential_distribution[double]](dist, sample)


def gamma_distribution_test(shape, scale, sample=True):
    """
    >>> gamma_distribution_test(3, 4)
    >>> l, u = gamma_distribution_test(1, 1, False)
    >>> l
    0.0
    >>> u == DBL_MAX or u == float("inf")
    True
    """
    cdef gamma_distribution[double] dist = gamma_distribution[double](shape, scale)
    return sample_or_range[gamma_distribution[double]](dist, sample)


def weibull_distribution_test(shape, scale, sample=True):
    """
    >>> weibull_distribution_test(3, 2)
    >>> l, u = weibull_distribution_test(1, 1, False)
    >>> l
    0.0
    >>> u == DBL_MAX or u == float("inf")
    True
    """
    cdef weibull_distribution[double] dist = weibull_distribution[double](shape, scale)
    return sample_or_range[weibull_distribution[double]](dist, sample)


def extreme_value_distribution_test(shape, scale, sample=True):
    """
    >>> extreme_value_distribution_test(3, 0.1)
    >>> l, u = extreme_value_distribution_test(1, 1, False)
    >>> l == -DBL_MAX or l == -float("inf")
    True
    >>> u == DBL_MAX or u == float("inf")
    True
    """
    cdef extreme_value_distribution[double] dist = extreme_value_distribution[double](shape, scale)
    return sample_or_range[extreme_value_distribution[double]](dist, sample)


def normal_distribution_test(loc, scale, sample=True):
    """
    >>> normal_distribution_test(3, 2)
    >>> l, u = normal_distribution_test(1, 1, False)
    >>> l == -DBL_MAX or l == -float("inf")
    True
    >>> u == DBL_MAX or u == float("inf")
    True
    """
    cdef normal_distribution[double] dist = normal_distribution[double](loc, scale)
    return sample_or_range[normal_distribution[double]](dist, sample)


def lognormal_distribution_test(loc, scale, sample=True):
    """
    >>> lognormal_distribution_test(3, 2)
    >>> l, u = lognormal_distribution_test(1, 1, False)
    >>> l
    0.0
    >>> u == DBL_MAX or u == float("inf")
    True
    """
    cdef lognormal_distribution[double] dist = lognormal_distribution[double](loc, scale)
    return sample_or_range[lognormal_distribution[double]](dist, sample)


def chi_squared_distribution_test(dof, sample=True):
    """
    >>> x = chi_squared_distribution_test(9)
    >>> l, u = chi_squared_distribution_test(5, False)
    >>> l
    0.0
    >>> u == DBL_MAX or u == float("inf")
    True
    """
    cdef chi_squared_distribution[double] dist = chi_squared_distribution[double](dof)
    return sample_or_range[chi_squared_distribution[double]](dist, sample)


def cauchy_distribution_test(loc, scale, sample=True):
    """
    >>> cauchy_distribution_test(3, 9)
    >>> l, u = cauchy_distribution_test(1, 1, False)
    >>> l == -DBL_MAX or l == -float("inf")
    True
    >>> u == DBL_MAX or u == float("inf")
    True
    """
    cdef cauchy_distribution[double] dist = cauchy_distribution[double](loc, scale)
    return sample_or_range[cauchy_distribution[double]](dist, sample)


def fisher_f_distribution_test(m, n, sample=True):
    """
    >>> x = fisher_f_distribution_test(9, 11)
    >>> l, u = fisher_f_distribution_test(1, 1, False)
    >>> l
    0.0
    >>> u == DBL_MAX or u == float("inf")
    True
    """
    cdef fisher_f_distribution[double] dist = fisher_f_distribution[double](m, n)
    return sample_or_range[fisher_f_distribution[double]](dist, sample)


def student_t_distribution_test(dof, sample=True):
    """
    >>> x = student_t_distribution_test(13)
    >>> l, u = student_t_distribution_test(1, False)
    >>> l == -DBL_MAX or l == -float("inf")
    True
    >>> u == DBL_MAX or u == float("inf")
    True
    """
    cdef student_t_distribution[double] dist = student_t_distribution[double](dof)
    return sample_or_range[student_t_distribution[double]](dist, sample)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_set.pyx0000644000175100001770000001071200000000000020624 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp11

# cython: language_level=3

from libcpp.set cimport set
from libcpp.unordered_set cimport unordered_set
from libcpp.utility cimport pair

def test_set_insert(vals):
    """
    >>> test_set_insert([1,2,2,3, -1])
    [-1, 1, 2, 3]
    """
    cdef set[int] s = set[int]()
    cdef pair[set[int].iterator, bint] ret
    for v in vals:
        ret = s.insert(v)
    return [item for item in s]

def test_set_insert_it(vals):
    """
    >>> test_set_insert_it([1,2,2,3, -1])
    [-1, 1, 2, 3]
    """
    cdef unordered_set[int] us = unordered_set[int]()
    cdef set[int] s = set[int]()
    for v in vals:
        us.insert(v)
    s.insert(us.begin(), us.end())
    return [item for item in s]

def test_const_set_insert_it(vals):
    """
    >>> test_const_set_insert_it([1,2,2,3, -1])
    [-1, 1, 2, 3]
    """
    cdef unordered_set[int] us = unordered_set[int]()
    cdef set[int] s = set[int]()
    for v in vals:
        us.insert(v)
    s.insert(us.cbegin(), us.cend())
    return [item for item in s]

def test_set_count(vals, to_find):
    """
    >>> test_set_count([1,2,2,3, -1], 1)
    1
    >>> test_set_count([1,2,2,3, -1], 2)
    1
    """
    cdef set[int] s = set[int]()
    for v in vals:
        s.insert(v)
    return s.count(to_find)

def test_set_erase(vals, int to_remove):
    """
    >>> test_set_erase([1,2,2,3, -1], 1)
    [-1, 2, 3]
    >>> test_set_erase([1,2,2,3, -1], 2)
    [-1, 1, 3]
    """
    cdef set[int] s = set[int]()
    cdef size_t ret
    for v in vals:
        s.insert(v)
    ret = s.erase(to_remove)
    return [item for item in s]

def test_set_find_erase(vals, to_remove):
    """
    >>> test_set_find_erase([1,2,2,3, -1], 1)
    [-1, 2, 3]
    >>> test_set_find_erase([1,2,2,3, -1], 2)
    [-1, 1, 3]
    """
    cdef set[int] s = set[int]()
    cdef set[int].iterator it
    for v in vals:
        s.insert(v)
    it = s.find(to_remove)
    it = s.erase(it)
    return [item for item in s]


def test_unordered_set_insert(vals):
    """
    >>> test_unordered_set_insert([1,2,2,3, -1])
    [-1, 1, 2, 3]
    """
    cdef unordered_set[int] us = unordered_set[int]()
    cdef pair[unordered_set[int].iterator, bint] ret
    for v in vals:
        ret = us.insert(v)
    return sorted([item for item in us])

def test_unordered_set_insert_it(vals):
    """
    >>> test_unordered_set_insert_it([1,2,2,3, -1])
    [-1, 1, 2, 3]
    """
    cdef set[int] s = set[int]()
    cdef unordered_set[int] us = unordered_set[int]()
    for v in vals:
        s.insert(v)
    us.insert(s.begin(), s.end())
    return sorted([item for item in us])

def test_const_unordered_set_insert_it(vals):
    """
    >>> test_const_unordered_set_insert_it([1,2,2,3, -1])
    [-1, 1, 2, 3]
    """
    cdef set[int] s = set[int]()
    cdef unordered_set[int] us = unordered_set[int]()
    for v in vals:
        s.insert(v)
    us.insert(s.cbegin(), s.cend())
    return sorted([item for item in us])

def test_unordered_set_count(vals, to_find):
    """
    >>> test_unordered_set_count([1,2,2,3, -1], 1)
    1
    >>> test_unordered_set_count([1,2,2,3, -1], 2)
    1
    """
    cdef unordered_set[int] us = unordered_set[int]()
    for v in vals:
        us.insert(v)
    return us.count(to_find)

def test_unordered_set_erase(vals, int to_remove):
    """
    >>> test_unordered_set_erase([1,2,2,3, -1], 1)
    [-1, 2, 3]
    >>> test_unordered_set_erase([1,2,2,3, -1], 2)
    [-1, 1, 3]
    """
    cdef unordered_set[int] us = unordered_set[int]()
    cdef size_t ret
    for v in vals:
        us.insert(v)
    ret = us.erase(to_remove)
    return sorted([item for item in us])

def test_unordered_set_find_erase(vals, to_remove):
    """
    >>> test_unordered_set_find_erase([1,2,2,3, -1], 1)
    [-1, 2, 3]
    >>> test_unordered_set_find_erase([1,2,2,3, -1], 2)
    [-1, 1, 3]
    """
    cdef unordered_set[int] us = unordered_set[int]()
    cdef unordered_set[int].iterator it
    for v in vals:
        us.insert(v)
    it = us.find(to_remove)
    it = us.erase(it)
    return sorted([item for item in us])

def test_iterator_stack_allocated():
    """
    https://github.com/cython/cython/issues/4657 - mainly a compile test showing
    that const iterators can be stack allocated
    >>> test_iterator_stack_allocated()
    """
    cdef set[int] myset = set[int]()
    cdef unordered_set[int] myuset = unordered_set[int]()
    cdef int ckey = 5
    it = myset.const_find(ckey)
    assert it == myset.const_end()
    uit = myuset.const_find(ckey)
    assert uit == myuset.const_end()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_string.pyx0000644000175100001770000002474500000000000021352 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, warnings

cimport cython

from libcpp.string cimport string, npos, to_string, stoi, stof

b_asdf = b'asdf'
b_asdg = b'asdg'
b_s = b's'


cdef int compare_to_asdf_ref(string& s) except -999:
    return s.compare(b"asdf")

def test_coerced_literal_ref():
    """
    >>> test_coerced_literal_ref()
    0
    """
    return compare_to_asdf_ref("asdf")


cdef int compare_to_asdf_const_ref(const string& s) except -999:
    return s.compare(b"asdf")

def test_coerced_literal_const_ref():
    """
    >>> test_coerced_literal_const_ref()
    0
    """
    return compare_to_asdf_const_ref("asdf")


cdef int compare_to_asdf_const(const string s) except -999:
    return s.compare(b"asdf")

def test_coerced_literal_const():
    """
    >>> test_coerced_literal_const()
    0
    """
    return compare_to_asdf_const("asdf")


def test_conversion(py_obj):
    """
    >>> test_conversion(b_asdf) == b_asdf or test_conversion(b_asdf)
    True
    >>> test_conversion(123)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: expected ..., int found
    """
    cdef string s = py_obj
    return s

def test_indexing(char *py_str):
    """
    >>> test_indexing(b_asdf)
    ('s', 's')
    """
    cdef string s
    s = string(py_str)
    return chr(s[1]), chr(s.at(1))

def test_size(char *py_str):
    """
    >>> test_size(b_asdf)
    (4, 4)
    """
    cdef string s
    s = string(py_str)
    return s.size(), s.length()

def test_compare(char *a, char *b):
    """
    >>> test_compare(b_asdf, b_asdf)
    0

    >>> test_compare(b_asdf, b_asdg) < 0
    True
    """
    cdef string s = string(a)
    cdef string t = string(b)
    return s.compare(t)

def test_empty():
    """
    >>> test_empty()
    (True, False)
    """
    cdef string a = string(b"")
    cdef string b = string(b"aa")
    return a.empty(), b.empty()

def test_push_back(char *a):
    """
    >>> test_push_back(b_asdf) == b_asdf + b_s
    True
    """
    cdef string s = string(a)
    s.push_back(ord('s'))
    return s.c_str()

def test_pop_back(char *a):
    """
    >>> test_pop_back(b'abc') == b'ab' or test_pop_back(b'abc')
    True
    """
    cdef string s = string(a)
    s.pop_back()
    return s

def test_insert(char *a, char *b, int i):
    """
    >>> test_insert('AAAA'.encode('ASCII'), 'BBBB'.encode('ASCII'), 2) == 'AABBBBAA'.encode('ASCII')
    True
    """
    cdef string s = string(a)
    cdef string t = string(b)
    cdef string u = s.insert(i, t)
    return u.c_str()

def test_copy(char *a):
    """
    >>> test_copy(b_asdf) == b_asdf[1:]
    True
    """
    cdef string t = string(a)
    cdef char[6] buffer
    cdef size_t length = t.copy(buffer, 4, 1)
    buffer[length] = c'\0'
    return buffer

def test_find(char *a, char *b):
    """
    >>> test_find(b_asdf, 'df'.encode('ASCII'))
    2
    """
    cdef string s = string(a)
    cdef string t = string(b)
    cdef size_t i = s.find(t)
    return i

def test_npos(char *a, char *b):
    """
    >>> test_npos(b'abc', b'x')
    True
    >>> test_npos(b'abc', b'a')
    False
    """
    cdef string s = string(a)
    cdef string st = string(b)
    return s.find(st) == npos

def test_clear():
    """
    >>> test_clear() == ''.encode('ASCII')
    True
    """
    cdef string s = string("asdf")
    s.clear()
    return s.c_str()

def test_erase(char *a, size_t pos=0, size_t count=npos):
    """
    >>> test_erase(b'abc') == b'' or test_erase(b'abc')
    True
    >>> test_erase(b'abc', 1) == b'a' or test_erase(b'abc', 1)
    True
    >>> test_erase(b'abc', 1, 1) == b'ac' or test_erase(b'abc', 1, 1)
    True
    """
    cdef string s = string(a)
    return s.erase(pos, count)

def test_assign(char *a):
    """
    >>> test_assign(b_asdf) == 'ggg'.encode('ASCII')
    True
    """
    cdef string s = string(a)
    s.assign("ggg")
    return s.c_str()


def test_substr(char *a):
    """
    >>> test_substr('ABCDEFGH'.encode('ASCII')) == ('BCDEFGH'.encode('ASCII'), 'BCDE'.encode('ASCII'), 'ABCDEFGH'.encode('ASCII'))
    True
    """
    cdef string s = string(a)
    cdef string x, y, z
    x = s.substr(1)
    y = s.substr(1, 4)
    z = s.substr()
    return x.c_str(), y.c_str(), z.c_str()

def test_append(char *a, char *b):
    """
    >>> test_append(b_asdf, '1234'.encode('ASCII')) == b_asdf + '1234'.encode('ASCII')
    True
    """
    cdef string s = string(a)
    cdef string t = string(b)
    cdef string j = s.append(t)
    return j.c_str()

def test_char_compare(py_str):
    """
    >>> test_char_compare(b_asdf)
    True
    """
    cdef char *a = py_str
    cdef string b = string(a)
    return b.compare(b) == 0

def test_cstr(char *a):
    """
    >>> test_cstr(b_asdf) == b_asdf
    True
    """
    cdef string b = string(a)
    return b.c_str()

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def test_decode(char* a):
    """
    >>> print(test_decode(b_asdf))
    asdf
    """
    cdef string b = string(a)
    return b.decode('ascii')


@cython.test_assert_path_exists("//ReturnStatNode//PythonCapiCallNode")
def test_cstr_decode(char* a):
    """
    >>> print(test_cstr_decode(b_asdf))
    asdf
    """
    cdef string b = string(a)
    return b.c_str().decode('utf-8')


@cython.test_assert_path_exists("//ReturnStatNode//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//ReturnStatNode//AttributeNode")
def test_cstr_ptr_decode(char* a):
    """
    >>> print(test_cstr_ptr_decode(b_asdf))
    asdf
    """
    cdef string b = string(a)
    s = b.c_str()
    return s.decode('utf-8')


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def test_decode_sliced(char* a):
    """
    >>> print(test_decode_sliced(b_asdf))
    sd
    """
    cdef string b = string(a)
    return b[1:3].decode('ascii')

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def test_decode_sliced_negative(char* a):
    """
    >>> a,b,c,d = test_decode_sliced_negative(b_asdf)
    >>> print(a)
    sd
    >>> print(b)
    a
    >>> print(c)
    
    >>> print(d)
    
    """
    cdef string b = string(a)
    return b[-3:-1].decode('ascii'), b[-5:-3].decode('ascii'), b[-20:-4].decode('ascii'), b[-2:-20].decode('ascii')

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def test_decode_sliced_end(char* a):
    """
    >>> a,b = test_decode_sliced_end(b_asdf)
    >>> print(a)
    asd
    >>> print(b)
    asdf
    """
    cdef string b = string(a)
    return b[:3].decode('ascii'), b[:42].decode('ascii')

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def test_decode_sliced_end_negative(char* a):
    """
    >>> a,b,c = test_decode_sliced_end_negative(b_asdf)
    >>> print(a)
    asd
    >>> print(b)
    a
    >>> print(c)
    
    """
    cdef string b = string(a)
    return b[:-1].decode('ascii'), b[:-3].decode('ascii'), b[:-4].decode('ascii')

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def test_decode_sliced_start(char* a):
    """
    >>> print(test_decode_sliced_start(b_asdf))
    df
    """
    cdef string b = string(a)
    return b[2:].decode('ascii')

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def test_decode_sliced_start_negative(char* a):
    """
    >>> a,b = test_decode_sliced_start_negative(b_asdf)
    >>> print(a)
    df
    >>> print(b)
    asdf
    """
    cdef string b = string(a)
    return b[-2:].decode('ascii'), b[-20:].decode('ascii')

def test_equals_operator(char *a, char *b):
    """
    >>> test_equals_operator(b_asdf, b_asdf)
    (True, False)
    """
    cdef string s = string(a)
    cdef string t = string(b)
    return t == s, t != "asdf"

def test_less_than(char *a, char *b):
    """
    >>> test_less_than(b_asdf[:-1], b_asdf)
    (True, True, True)

    >>> test_less_than(b_asdf[:-1], b_asdf[:-1])
    (False, False, True)
    """
    cdef string s = string(a)
    cdef string t = string(b)
    return (s < t, s < b, s <= b)

def test_greater_than(char *a, char *b):
    """
    >>> test_greater_than(b_asdf[:-1], b_asdf)
    (False, False, False)

    >>> test_greater_than(b_asdf[:-1], b_asdf[:-1])
    (False, False, True)
    """
    cdef string s = string(a)
    cdef string t = string(b)
    return (s > t, s > b, s >= b)


def test_iteration(string s):
    """
    >>> test_iteration(b'xyz')
    [120, 121, 122]
    >>> test_iteration(b'')
    []
    """
    return [c for c in s]

def test_to_string(x):
    """
    >>> print(test_to_string(5))
    si=5 sl=5 ss=5 sss=5
    >>> print(test_to_string(-5))
    si=-5 sl=-5 ss=5 sss=-5
    """
    si = to_string(x).decode('ascii')
    sl = to_string(x).decode('ascii')
    ss = to_string(abs(x)).decode('ascii')
    sss = to_string(x).decode('ascii')
    return f"si={si} sl={sl} ss={ss} sss={sss}"

def test_stoi(char *a):
    """
    >>> test_stoi(b'5')
    5
    """
    cdef string s = string(a)
    return stoi(s)

def test_stof(char *a):
    """
    >>> test_stof(b'5.5')
    5.5
    """
    cdef string s = string(a)
    return stof(s)

def test_to_string(x):
    """
    >>> print(test_to_string(5))
    si=5 sl=5 ss=5 sss=5
    >>> print(test_to_string(-5))
    si=-5 sl=-5 ss=5 sss=-5
    """
    si = to_string(x).decode('ascii')
    sl = to_string(x).decode('ascii')
    ss = to_string(abs(x)).decode('ascii')
    sss = to_string(x).decode('ascii')
    return f"si={si} sl={sl} ss={ss} sss={sss}"


def test_stoi(char *a):
    """
    >>> test_stoi(b'5')
    5
    """
    cdef string s = string(a)
    return stoi(s)


def test_stof(char *a):
    """
    >>> test_stof(b'5.5')
    5.5
    """
    cdef string s = string(a)
    return stof(s)


def test_swap():
    """
    >>> test_swap()
    """
    cdef string s1 = b_asdf, s_asdf = b_asdf
    cdef string s2 = b_asdg, s_asdg = b_asdg
    s1.swap(s2)
    assert s1 == s_asdg and s2 == s_asdf


def test_float_parsing(bstring):
    """
    >>> test_float_parsing(b'0.5')
    0.5
    >>> try: test_float_parsing(b'xxx')
    ... except ValueError: pass
    ... else: print("NOT RAISED!")
    >>> try: test_float_parsing(b'')
    ... except ValueError: pass
    ... else: print("NOT RAISED!")
    """
    cdef string s = bstring
    return float(s)


_WARNINGS = """
21:31: Cannot pass Python object as C++ data structure reference (string &), will pass by copy.
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_string_ascii_auto_encoding.pyx0000644000175100001770000000650200000000000025407 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror
# cython: c_string_encoding=ascii, c_string_type=unicode

from libcpp.string cimport string
from libcpp.vector cimport vector

b_asdf = b'asdf'
s_asdf = 'asdf'
u_asdf = u'asdf'
u_s = u's'


def test_conversion(py_obj):
    """
    >>> test_conversion(b_asdf) == u_asdf or test_conversion(b_asdf)
    True
    >>> test_conversion(u_asdf) == u_asdf or test_conversion(u_asdf)
    True
    >>> test_conversion(123)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: expected ..., int found
    """
    cdef string s = py_obj
    assert len(py_obj) == s.length(), '%d != %d' % (len(py_obj), s.length())
    return s


def test_empty(py_obj):
    """
    >>> test_empty('')
    True
    >>> test_empty('abc')
    False
    >>> test_empty(u_asdf[:0])
    True
    >>> test_empty(u_asdf)
    False
    """
    cdef string a = py_obj
    return a.empty()


def test_push_back(a):
    """
    >>> test_push_back(b_asdf) == u_asdf + u_s
    True
    >>> test_push_back(u_asdf) == u_asdf + u_s
    True
    """
    cdef string s = a
    s.push_back(ord('s'))
    return s


def test_clear(a):
    """
    >>> test_clear(u_asdf) == u_s[:0]
    True
    >>> test_clear(b_asdf) == u_s[:0]
    True
    """
    cdef string s = a
    s.clear()
    return s


def test_assign(char *a):
    """
    >>> test_assign(b_asdf) == 'ggg'
    True
    """
    cdef string s = string(a)
    s.assign("ggg")
    return s.c_str()


def test_bytes_cast(a):
    """
    >>> b = test_bytes_cast(b'abc')
    >>> isinstance(b, bytes)
    True
    >>> print(b.decode('ascii'))
    abc
    >>> b = test_bytes_cast(b'abc\\xe4\\xfc')
    >>> isinstance(b, bytes)
    True
    >>> len(b)
    5
    >>> print(b[:3].decode('ascii'))
    abc
    >>> print(ord(b[3:4]))
    228
    >>> print(ord(b[4:5]))
    252
    """
    cdef string s = a
    assert s.length() == len(a), "%d != %d" % (s.length(), len(a))
    return s


def test_bytearray_cast(a):
    """
    >>> b = test_bytearray_cast(b'abc')
    >>> isinstance(b, bytearray)
    True
    >>> print(b.decode('ascii'))
    abc
    >>> b = test_bytearray_cast(b'abc\\xe4\\xfc')
    >>> isinstance(b, bytearray)
    True
    >>> len(b)
    5
    >>> print(b[:3].decode('ascii'))
    abc
    >>> print(ord(b[3:4]))
    228
    >>> print(ord(b[4:5]))
    252
    """
    cdef string s = a
    assert s.length() == len(a), "%d != %d" % (s.length(), len(a))
    return s


def test_unicode_cast(a):
    """
    >>> u = test_unicode_cast(b'abc')
    >>> type(u) is type(u_asdf) or type(u)
    True
    >>> print(u)
    abc
    """
    cdef string s = a
    assert s.length() == len(a), "%d != %d" % (s.length(), len(a))
    return s


def test_str_cast(a):
    """
    >>> s = test_str_cast(b'abc')
    >>> type(s) is type(s_asdf) or type(s)
    True
    >>> print(s)
    abc
    """
    cdef string s = a
    assert s.length() == len(a), "%d != %d" % (s.length(), len(a))
    return s


def test_vector_of_strings(*strings):
    """
    >>> results = test_vector_of_strings(b_asdf, u_asdf)
    >>> results == [u_asdf, u_asdf] or results
    True
    >>> type(results[0]) is type(u_asdf) or type(results[0])
    True
    >>> type(results[1]) is type(u_asdf) or type(results[1])
    True
    """
    cdef vector[string] v = strings
    return v
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_string_ascii_auto_encoding_str.pyx0000644000175100001770000000570500000000000026303 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror
# cython: c_string_encoding=ascii, c_string_type=str

cimport cython

from libcpp.string cimport string

b_asdf = b'asdf'
u_asdf = u'asdf'
s_asdf = 'asdf'
s_s = 's'


def test_conversion(py_obj):
    """
    >>> test_conversion(b_asdf) == s_asdf or test_conversion(b_asdf)
    True
    >>> test_conversion(u_asdf) == s_asdf or test_conversion(u_asdf)
    True
    >>> test_conversion(123)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: expected ..., int found
    """
    cdef string s = py_obj
    assert len(py_obj) == s.length(), '%d != %d' % (len(py_obj), s.length())
    return s


def test_empty(py_obj):
    """
    >>> test_empty('')
    True
    >>> test_empty('abc')
    False
    >>> test_empty(u_asdf[:0])
    True
    >>> test_empty(u_asdf)
    False
    """
    cdef string a = py_obj
    return a.empty()


def test_push_back(a):
    """
    >>> test_push_back(b_asdf) == s_asdf + s_s
    True
    >>> test_push_back(u_asdf) == s_asdf + s_s
    True
    """
    cdef string s = a
    s.push_back(ord('s'))
    return s


def test_clear(a):
    """
    >>> test_clear(u_asdf) == s_s[:0]
    True
    >>> test_clear(b_asdf) == s_s[:0]
    True
    """
    cdef string s = a
    s.clear()
    return s


def test_assign(char *a):
    """
    >>> test_assign(b_asdf) == 'ggg'
    True
    """
    cdef string s = string(a)
    s.assign("ggg")
    return s.c_str()


def test_bytes_cast(a):
    """
    >>> b = test_bytes_cast(b'abc')
    >>> isinstance(b, bytes)
    True
    >>> print(b.decode('ascii'))
    abc
    >>> b = test_bytes_cast(b'abc\\xe4\\xfc')
    >>> isinstance(b, bytes)
    True
    >>> len(b)
    5
    >>> print(b[:3].decode('ascii'))
    abc
    >>> print(ord(b[3:4]))
    228
    >>> print(ord(b[4:5]))
    252
    """
    cdef string s = a
    assert s.length() == len(a), "%d != %d" % (s.length(), len(a))
    return s


def test_bytearray_cast(a):
    """
    >>> b = test_bytearray_cast(b'abc')
    >>> isinstance(b, bytearray)
    True
    >>> print(b.decode('ascii'))
    abc
    >>> b = test_bytearray_cast(b'abc\\xe4\\xfc')
    >>> isinstance(b, bytearray)
    True
    >>> len(b)
    5
    >>> print(b[:3].decode('ascii'))
    abc
    >>> print(ord(b[3:4]))
    228
    >>> print(ord(b[4:5]))
    252
    """
    cdef string s = a
    assert s.length() == len(a), "%d != %d" % (s.length(), len(a))
    return s


def test_unicode_cast(a):
    """
    >>> u = test_unicode_cast(b'abc')
    >>> type(u) is type(u_asdf) or type(u)
    True
    >>> print(u)
    abc
    """
    cdef string s = a
    assert s.length() == len(a), "%d != %d" % (s.length(), len(a))
    return s


def test_str_cast(a):
    """
    >>> s = test_str_cast(b'abc')
    >>> type(s) is type(s_asdf) or type(s)
    True
    >>> print(s)
    abc
    """
    cdef string s = a
    assert s.length() == len(a), "%d != %d" % (s.length(), len(a))
    return s
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_string_cpp11.pyx0000644000175100001770000000043000000000000022337 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp11

from libcpp.string cimport string

b_asdf = b'asdf'

def test_element_access(char *py_str):
    """
    >>> test_element_access(b_asdf)
    ('a', 'f')
    """
    cdef string s
    s = string(py_str)
    return chr(s.front()), chr(s.back())
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_string_cpp20.pyx0000644000175100001770000000260700000000000022347 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, cpp20

from libcpp cimport bool
from libcpp.string cimport string

b_A = b'A'
b_F = b'F'
b_abc = b"ABC"
b_def = b"DEF"

def test_string_starts_with_char(bytes py_str):
    """
    Test std::string.starts_with() with char type argument
    >>> test_string_starts_with_char(b'A')
    True
    >>> test_string_starts_with_char(b'F')
    False
    """
    cdef char c = py_str[0]
    cdef string s = b"ABCDEF"
    return s.starts_with(c)


def test_string_starts_with_cstr(bytes py_str):
    """
    Test std::string.starts_with() with c str type argument (char*)
    >>> test_string_starts_with_cstr(b"ABC")
    True
    >>> test_string_starts_with_cstr(b"DEF")
    False
    """
    cdef char* c = py_str
    cdef string s = b"ABCDEF"
    return s.starts_with(c)


def test_string_ends_with_char(bytes py_str):
    """
    Test std::string.ends_with() with char type argument
    >>> test_string_ends_with_char(b'F')
    True
    >>> test_string_ends_with_char(b'A')
    False
    """
    cdef char c = py_str[0]
    cdef string s = b"ABCDEF"
    return s.ends_with(c)


def test_string_ends_with_cstr(bytes py_str):
    """
    Test std::string.ends_with() with c str type argument (char*)
    >>> test_string_ends_with_cstr(b"DEF")
    True
    >>> test_string_ends_with_cstr(b"ABC")
    False
    """
    cdef char* c = py_str
    cdef string s = b"ABCDEF"
    return s.ends_with(c)././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_string_utf8_auto_encoding.pyx0000644000175100001770000000571200000000000025207 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror
# cython: c_string_encoding=utf-8, c_string_type=unicode

cimport cython

from libcpp.string cimport string

b_asdf = b'asdf'
s_asdf = 'asdf'
u_asdf = u'asdf'
u_s = u's'


def test_conversion(py_obj):
    """
    >>> test_conversion(b_asdf) == u_asdf or test_conversion(b_asdf)
    True
    >>> test_conversion(u_asdf) == u_asdf or test_conversion(u_asdf)
    True
    >>> test_conversion(123)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: expected ..., int found
    """
    cdef string s = py_obj
    assert len(py_obj) == s.length(), '%d != %d' % (len(py_obj), s.length())
    return s


def test_empty(py_obj):
    """
    >>> test_empty('')
    True
    >>> test_empty('abc')
    False
    >>> test_empty(u_asdf[:0])
    True
    >>> test_empty(u_asdf)
    False
    """
    cdef string a = py_obj
    return a.empty()


def test_push_back(a):
    """
    >>> test_push_back(b_asdf) == u_asdf + u_s
    True
    >>> test_push_back(u_asdf) == u_asdf + u_s
    True
    """
    cdef string s = a
    s.push_back(ord('s'))
    return s


def test_clear(a):
    """
    >>> test_clear(u_asdf) == u_s[:0]
    True
    >>> test_clear(b_asdf) == u_s[:0]
    True
    """
    cdef string s = a
    s.clear()
    return s


def test_assign(char *a):
    """
    >>> test_assign(b_asdf) == 'ggg'
    True
    """
    cdef string s = string(a)
    s.assign("ggg")
    return s.c_str()


def test_bytes_cast(a):
    """
    >>> b = test_bytes_cast(b'abc')
    >>> isinstance(b, bytes)
    True
    >>> print(b.decode('ascii'))
    abc
    >>> b = test_bytes_cast(b'abc\\xe4\\xfc')
    >>> isinstance(b, bytes)
    True
    >>> len(b)
    5
    >>> print(b[:3].decode('ascii'))
    abc
    >>> print(ord(b[3:4]))
    228
    >>> print(ord(b[4:5]))
    252
    """
    cdef string s = a
    assert s.length() == len(a), "%d != %d" % (s.length(), len(a))
    return s


def test_bytearray_cast(a):
    """
    >>> b = test_bytearray_cast(b'abc')
    >>> isinstance(b, bytearray)
    True
    >>> print(b.decode('ascii'))
    abc
    >>> b = test_bytearray_cast(b'abc\\xe4\\xfc')
    >>> isinstance(b, bytearray)
    True
    >>> len(b)
    5
    >>> print(b[:3].decode('ascii'))
    abc
    >>> print(ord(b[3:4]))
    228
    >>> print(ord(b[4:5]))
    252
    """
    cdef string s = a
    assert s.length() == len(a), "%d != %d" % (s.length(), len(a))
    return s


def test_unicode_cast(a):
    """
    >>> u = test_unicode_cast(b'abc')
    >>> type(u) is type(u_asdf) or type(u)
    True
    >>> print(u)
    abc
    """
    cdef string s = a
    assert s.length() == len(a), "%d != %d" % (s.length(), len(a))
    return s


def test_str_cast(a):
    """
    >>> s = test_str_cast(b'abc')
    >>> type(s) is type(s_asdf) or type(s)
    True
    >>> print(s)
    abc
    """
    cdef string s = a
    assert s.length() == len(a), "%d != %d" % (s.length(), len(a))
    return s
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_vector.pyx0000644000175100001770000001030000000000000021324 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, no-cpp-locals

from cython.operator cimport dereference as d
from cython.operator cimport preincrement as incr

from libcpp.vector cimport vector
from libcpp cimport bool as cbool

def simple_test(double x):
    """
    >>> simple_test(55)
    3
    """
    v = new vector[double]()
    try:
        v.push_back(1.0)
        v.push_back(x)
        from math import pi
        v.push_back(pi)
        return v.size()
    finally:
        del v

def list_test(L):
    """
    >>> list_test([1,2,4,8])
    (4, 4)
    >>> list_test([])
    (0, 0)
    >>> list_test([-1] * 1000)
    (1000, 1000)
    """
    v = new vector[int]()
    try:
        for a in L:
            v.push_back(a)
        return len(L), v.size()
    finally:
        del v

def index_test(L):
    """
    >>> index_test([1,2,4,8])
    (1.0, 8.0)
    >>> index_test([1.25])
    (1.25, 1.25)
    """
    v = new vector[double]()
    try:
        for a in L:
            v.push_back(a)
        return v[0][0], v[0][len(L)-1]
    finally:
        del v


def index_set_test(L):
    """
    >>> index_set_test([1,2,4,8])
    (-1.0, -8.0)
    >>> index_set_test([1.25])
    (-1.25, -1.25)
    """
    v = new vector[double]()
    try:
        for a in L:
            v.push_back(a)
        for i in range(v.size()):
            d(v)[i] = -d(v)[i]
        return d(v)[0], d(v)[v.size()-1]
    finally:
        del v

def iteration_test(L):
    """
    >>> iteration_test([1,2,4,8])
    1
    2
    4
    8
    """
    v = new vector[int]()
    try:
        for a in L:
            v.push_back(a)
        it = v.begin()
        while it != v.end():
            a = d(it)
            incr(it)
            print(a)
    finally:
        del v

def reverse_iteration_test(L):
    """
    >>> reverse_iteration_test([1,2,4,8])
    8
    4
    2
    1
    """
    v = new vector[int]()
    try:
        for a in L:
            v.push_back(a)
        it = v.rbegin()
        while it != v.rend():
            a = d(it)
            incr(it)
            print(a)
    finally:
        del v

def nogil_test(L):
    """
    >>> nogil_test([1,2,3])
    3
    """
    cdef int a
    with nogil:
        v = new vector[int]()
    try:
        for a in L:
            with nogil:
                v.push_back(a)
        return v.size()
    finally:
        del v

def item_ptr_test(L, int i, int x):
    """
    >>> item_ptr_test(range(10), 7, 100)
    [0, 1, 2, 3, 4, 5, 6, 100, 8, 9]
    """
    cdef vector[int] v = L
    cdef int* vi_ptr = &v[i]
    vi_ptr[0] = x
    return v

def test_value_type(x):
    """
    >>> test_value_type(2)
    2.0
    >>> test_value_type(2.5)
    2.5
    """
    cdef vector[double].value_type val = x
    return val

def test_value_type_complex(x):
    """
    >>> test_value_type_complex(2)
    (2+0j)
    """
    cdef vector[double complex].value_type val = x
    return val

def test_bool_vector_convert(o):
    """
    >>> test_bool_vector_convert([True, False, None, 3])
    [True, False, False, True]
    """
    cdef vector[cbool] v = o
    return v

def test_bool_vector_get_set():
    """
    >>> test_bool_vector_get_set()
    """
    cdef vector[cbool] v = range(5)
    # Test access.
    assert not v[0], v
    assert v[1], v
    assert not v.at(0), v
    assert v.at(1), v
    v[0] = True
    v[1] = False
    assert v == [True, False, True, True, True]

ctypedef vector[cbool] vector_bool
ctypedef vector[int] vector_int

def test_typedef_vector(L):
    """
    >>> test_typedef_vector([0, 1, True])
    ([0, 1, 1, 0, 1, 1], 0, [False, True, True, False, True, True], False)
    """
    cdef vector_int vi = L
    cdef vector_int vi2 = vi
    vi.insert(vi.begin(), vi2.begin(), vi2.end())

    cdef vector_bool vb = L
    cdef vector_bool vb2 = vb
    vb.insert(vb.begin(), vb2.begin(), vb2.end())

    return vi, vi.at(0), vb, vb.at(0)


def test_insert():
    """
    >>> test_insert()
    """
    cdef vector[int] v
    cdef vector[int].size_type count = 5
    cdef int value = 0

    v.insert(v.end(), count, value)

    assert v.size() == count
    for element in v:
        assert element == value, '%s != %s' % (element, count)


#  Tests GitHub issue #1788.
cdef cppclass MyVector[T](vector):
    pass

cdef cppclass Ints(MyVector[int]):
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_stl_vector_cpp11.pyx0000644000175100001770000000101200000000000022330 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, no-cpp-locals, cpp11

from cython.operator cimport dereference as d
from cython.operator cimport preincrement as incr

from libcpp.vector cimport vector

def const_iteration_test(L):
    """
    >>> const_iteration_test([1,2,4,8])
    1
    2
    4
    8
    """
    v = new vector[int]()
    try:
        for a in L:
            v.push_back(a)
        it = v.cbegin()
        while it != v.cend():
            a = d(it)
            incr(it)
            print(a)
    finally:
        del v
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_template_functions.pyx0000644000175100001770000000575400000000000023064 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, warnings, no-cpp-locals

cimport cython
from libcpp.pair cimport pair
from libcpp.vector cimport vector

cdef extern from "cpp_template_functions_helper.h":
    cdef T no_arg[T]()
    cdef T one_param[T](T)
    cdef pair[T, U] two_params[T, U](T, U)
    cdef cppclass A[T]:
        pair[T, U] method[U](T, U)
        U part_method[U](pair[T, U])
        U part_method_ref[U](pair[T, U]&)
        int overloaded(double x)
        T overloaded(pair[T, T])
        U overloaded[U](vector[U])
        X overloaded[X](char* s, vector[X])
    cdef T nested_deduction[T](const T*)
    pair[T, U] pair_arg[T, U](pair[T, U] a)
    cdef T* pointer_param[T](T*)
    cdef cppclass double_pair(pair[double, double]):
        double_pair(double, double)

def test_no_arg():
    """
    >>> test_no_arg()
    0
    """
    return no_arg[int]()

def test_one_param(int x):
    """
    >>> test_one_param(3)
    (3, 3.0)
    """
    return one_param[int](x), one_param[double](x)

def test_two_params(int x, int y):
    """
    >>> test_two_params(1, 2)
    (1, 2.0)
    """
    return two_params[int, double](x, y)

def test_method(int x, int y):
    """
    >>> test_method(5, 10)
    ((5, 10.0), (5.0, 10), (5, 10), (5.0, 10))
    """
    cdef A[int] a_int
    cdef A[double] a_double
    return (a_int.method[float](x, y), a_double.method[int](x, y),
        a_int.method(x, y), a_double.method(x, y))
#    return a_int.method[double](x, y), a_double.method[int](x, y)

def test_part_method(int x, int y):
    """
    >>> test_part_method(5, 10)
    (10.0, 10, 10.0)
    """
    cdef A[int] a_int
    cdef pair[int, double] p_int = (x, y)
    cdef A[double] a_double
    cdef pair[double, int] p_double = (x, y)
    return (a_int.part_method(p_int),
        a_double.part_method(p_double),
        a_double.part_method_ref(double_pair(x, y)))

def test_simple_deduction(int x, double y):
    """
    >>> test_simple_deduction(1, 2)
    (1, 2.0)
    """
    return one_param(x), one_param(y)

def test_more_deductions(int x, double y):
    """
    >>> test_more_deductions(1, 2)
    (1, 2.0)
    """
    return nested_deduction(&x), nested_deduction(&y)

def test_class_deductions(pair[long, double] x):
    """
    >>> test_class_deductions((1, 1.5))
    (1, 1.5)
    """
    return pair_arg(x)

def test_deduce_through_pointers(int k):
    """
    >>> test_deduce_through_pointers(5)
    (5, 5.0)
    """
    cdef double x = k
    return pointer_param(&k)[0], pointer_param(&x)[0]

def test_inference(int k):
    """
    >>> test_inference(27)
    27
    """
    res = one_param(&k)
    assert cython.typeof(res) == 'int *', cython.typeof(res)
    return res[0]

def test_overload_GH1583():
    """
    >>> test_overload_GH1583()
    """
    cdef A[int] a
    assert a.overloaded(1.5) == 1
    cdef pair[int, int] p = (2, 3)
    assert a.overloaded(p) == 2
    cdef vector[double] v = [0.25, 0.125]
    assert a.overloaded(v) == 0.25
    assert a.overloaded("s", v) == 0.25
    # GH Issue #1584
    # assert a.overloaded[double](v) == 0.25
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_template_functions_helper.h0000644000175100001770000000256600000000000024030 0ustar00runnerdocker00000000000000template 
T no_arg() {
    return T();
}

template 
T one_param(T value) {
    return value;
}

template 
std::pair two_params(T a, U b) {
    return std::pair(a, b);
}

template 
class A {
    public:
        template 
        std::pair method(T a, U b) {
            return std::pair(a, b);
        }
        template 
        U part_method(std::pair p) {
            return p.second;
        }
        template 
        U part_method_ref(const std::pair& p) {
            return p.second;
        }

        int overloaded(double d) {
            return (int) d;
        }
        T overloaded(std::pair p) {
            return p.first;
        }
        template 
        U overloaded(std::vector v) {
            return v[0];
        }
        template 
        U overloaded(char* c, std::vector v) {
            return v[0];
        }
};

template 
T nested_deduction(const T *a) {
    return *a;
}

template 
std::pair pair_arg(std::pair a) {
    return a;
}

template 
T* pointer_param(T* param) {
    return param;
}

class double_pair : public std::pair {
  public:
    double_pair(double x, double y) : std::pair(x, y) { };
};
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_template_ref_args.h0000644000175100001770000000053700000000000022245 0ustar00runnerdocker00000000000000#ifndef _TEMPLATE_ARGS_H_
#define _TEMPLATE_ARGS_H_

template 
struct Bar {
    Bar & ref() { return *this; }
    const Bar & const_ref() { return *this; }
    const Bar & const_ref_const() const { return *this; }
    T value;
};

template 
struct Foo {
    int bar_value(const Bar & bar) { return bar.value; }
};

#endif
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_template_ref_args.pyx0000644000175100001770000000217700000000000022640 0ustar00runnerdocker00000000000000# tag: cpp, no-cpp-locals

from libcpp.vector cimport vector


cdef extern from "cpp_template_ref_args.h":

    cdef cppclass Bar[T]:
        Bar()
        # bug: Bar[T] created before class fully defined
        T value
        Bar[T] & ref() except +
        const Bar[T] & const_ref() except +
        const Bar[T] & const_ref_const() except +

    cdef cppclass Foo[T]:
        Foo()
        int bar_value(Bar[int] & bar)


def test_template_ref_arg(int x):
    """
    >>> test_template_ref_arg(4)
    4
    """

    # Templated reference parameters in method
    # of templated classes were not properly coalesced.

    cdef Foo[size_t] foo
    cdef Bar[int] bar

    bar.value = x

    return foo.bar_value(bar.ref())

def test_template_ref_attr(int x):
    """
    >>> test_template_ref_attr(4)
    (4, 4)
    """
    cdef Bar[int] bar
    bar.value = x
    return bar.ref().value, bar.const_ref().value

def test_template_ref_const_attr(int x):
    """
    >>> test_template_ref_const_attr(4)
    4
    """
    cdef vector[int] v
    v.push_back(x)
    cdef const vector[int] *configs = &v
    cdef int value = configs.at(0)
    return value
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_template_subclasses.pyx0000644000175100001770000000740100000000000023212 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror, no-cpp-locals

from cython.operator import dereference as deref
from libcpp.pair cimport pair
from libcpp.vector cimport vector

cdef extern from "cpp_template_subclasses_helper.h":
    cdef cppclass Base:
        char* name()

    cdef cppclass A[A1](Base):
        A1 funcA(A1)

    cdef cppclass B[B1, B2](A[B2]):
        pair[B1, B2] funcB(B1, B2)

    cdef cppclass C[C1](B[long, C1]):
        C1 funcC(C1)

    cdef cppclass D[D1](C[pair[D1, D1]]):
        pass

    cdef cppclass E(D[double]):
        pass

def testA(x):
    """
    >>> testA(10)
    10.0
    """
    cdef Base *base
    cdef A[double] *a = NULL
    try:
        a = new A[double]()
        base = a
        assert base.name() == b"A", base.name()
        return a.funcA(x)
    finally:
        del a

def testB(x, y):
    """
    >>> testB(1, 2)
    >>> testB(1, 1.5)
    """
    cdef Base *base
    cdef A[double] *a
    cdef B[long, double] *b = NULL
    try:
        base = a = b = new B[long, double]()
        assert base.name() == b"B", base.name()
        assert a.funcA(y) == y
        assert b.funcB(x, y) == (x, y)
    finally:
        del b

def testC(x, y):
    """
    >>> testC(37, [1, 37])
    >>> testC(25, [1, 5, 25])
    >>> testC(105, [1, 3, 5, 7, 15, 21, 35, 105])
    """
    cdef Base *base
    cdef A[vector[long]] *a
    cdef B[long, vector[long]] *b
    cdef C[vector[long]] *c = NULL
    try:
        base = a = b = c = new C[vector[long]]()
        assert base.name() == b"C", base.name()
        assert a.funcA(y) == y
        assert b.funcB(x, y) == (x, y)
        assert c.funcC(y) == y
    finally:
        del c

def testD(x, y):
    """
    >>> testD(1, 1.0)
    >>> testD(2, 0.5)
    >>> testD(4, 0.25)
    """
    cdef Base *base
    cdef A[pair[double, double]] *a
    cdef B[long, pair[double, double]] *b
    cdef C[pair[double, double]] *c
    cdef D[double] *d = NULL
    try:
        base = a = b = c = d = new D[double]()
        assert base.name() == b"D", base.name()
        assert a.funcA((y, y)) == (y, y)
        assert b.funcB(x, (y, y + 1)) == (x, (y, y + 1))
        assert c.funcC((y, y)) == (y, y)
    finally:
        del d

def testE(x, y):
    """
    >>> testD(1, 1.0)
    >>> testD(2, 0.5)
    >>> testD(4, 0.25)
    """
    cdef Base *base
    cdef A[pair[double, double]] *a
    cdef B[long, pair[double, double]] *b
    cdef C[pair[double, double]] *c
    cdef D[double] *d
    cdef E *e = NULL
    try:
        base = a = b = c = d = e = new E()
        assert base.name() == b"E", base.name()
        assert a.funcA((y, y)) == (y, y)
        assert b.funcB(x, (y, y + 1)) == (x, (y, y + 1))
        assert c.funcC((y, y)) == (y, y)
    finally:
        del e


cdef public pair[int, double] public_return_pair(a, b) except *:
  return pair[int, double](a, b)

def test_GH1599(a, b):
  """
  >>> test_GH1599(1, 2)
  (1, 2.0)
  """
  return public_return_pair(a, b)


# Related to GH Issue #1852.

cdef cppclass Callback[T]:#(UntypedCallback):
    pass

cdef cppclass MyClass[O]:
    void Invoke(Callback[O]*)

cdef cppclass MySubclass[T](MyClass[T]):
    void Invoke(Callback[T]* callback):
      pass


cdef cppclass Getter[T]:
    T get(bint fire) except *:
        if fire:
            raise RuntimeError
        else:
           raise NotImplementedError

cdef cppclass GetInt(Getter[int]):
    int get(bint fire) except *:
        if fire:
            raise RuntimeError
        else:
            return 389

def test_subclass_exception_values(bint fire):
    """
    >>> test_subclass_exception_values(False)
    389
    >>> test_subclass_exception_values(True)
    Traceback (most recent call last):
    ...
    RuntimeError
    """
    cdef GetInt getter
    return getter.get(fire)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_template_subclasses_helper.h0000644000175100001770000000137500000000000024164 0ustar00runnerdocker00000000000000using namespace std;

class Base {
public:
    virtual const char* name() { return "Base"; }
    virtual ~Base() {}
};

template 
class A : public Base {
public:
    virtual const char* name() { return "A"; }
    A1 funcA(A1 x) { return x; }
};

template 
class B : public A {
public:
    virtual const char* name() { return "B"; }
    pair funcB(B1 x, B2 y) { return pair(x, y); }
};

template 
class C : public B {
public:
    virtual const char* name() { return "C"; }
    C1 funcC(C1 x) { return x; }
};

template 
class D : public C > {
    virtual const char* name() { return "D"; }
};

class E : public D {
    virtual const char* name() { return "E"; }
};
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_templates.pyx0000644000175100001770000000674000000000000021153 0ustar00runnerdocker00000000000000# tag: cpp

cimport cython
from cython.operator import dereference as deref

cdef extern from "cpp_templates_helper.h":
    cdef cppclass Wrap[T, AltType=*, UndeclarableAltType=*]:
        Wrap(T)
        void set(T)
        T get()
        bint operator==(Wrap[T])

        AltType get_alt_type()
        void set_alt_type(AltType)

        UndeclarableAltType create()
        bint accept(UndeclarableAltType)

    cdef cppclass Pair[T1,T2]:
        Pair(T1,T2)
        T1 first()
        T2 second()
        bint operator==(Pair[T1,T2])
        bint operator!=(Pair[T1,T2])

    cdef cppclass SuperClass[T1, T2]:
        pass

    cdef cppclass SubClass[T2, T3](SuperClass[T2, T3]):
        pass

    cdef cppclass Div[T]:
        @staticmethod
        T half(T value)

def test_int(int x, int y):
    """
    >>> test_int(3, 4)
    (3, 4, False)
    >>> test_int(100, 100)
    (100, 100, True)
    """
    try:
        a = new Wrap[int](x)
        b = new Wrap[int](0)
        b.set(y)
        return a.get(), b.get(), a[0] == b[0]
    finally:
        del a, b


def test_double(double x, double y):
    """
    >>> test_double(3, 3.5)
    (3.0, 3.5, False)
    >>> test_double(100, 100)
    (100.0, 100.0, True)
    """
    try:
        a = new Wrap[double](x)
        b = new Wrap[double](-1)
        b.set(y)
        return a.get(), b.get(), deref(a) == deref(b)
    finally:
        del a, b


def test_default_template_arguments(double x):
    """
    >>> test_default_template_arguments(3.5)
    (3.5, 3.0)
    """
    try:
        a = new Wrap[double](x)
        b = new Wrap[double, int, long](x)

        ax = a.get_alt_type()
        a.set_alt_type(ax)
        assert a.accept(a.create())  # never declared

        bx = b.get_alt_type()
        b.set_alt_type(bx)

        bc = b.create()              # declaration here is fine
        assert b.accept(bc)

        return a.get(), b.get()
    finally:
        del a


def test_pair(int i, double x):
    """
    >>> test_pair(1, 1.5)
    (1, 1.5, True, False)
    >>> test_pair(2, 2.25)
    (2, 2.25, True, False)
    """
    try:
        pair = new Pair[int, double](i, x)
        return pair.first(), pair.second(), deref(pair) == deref(pair), deref(pair) != deref(pair)
    finally:
        del pair

def test_ptr(int i):
    """
    >>> test_ptr(3)
    3
    >>> test_ptr(5)
    5
    """
    try:
        w = new Wrap[int*](&i)
        return deref(w.get())
    finally:
        del w

cdef double f(double x):
    return x*x

def test_func_ptr(double x):
    """
    >>> test_func_ptr(3)
    9.0
    >>> test_func_ptr(-1.5)
    2.25
    """
    try:
        w = new Wrap[double (*)(double)](&f)
        return w.get()(x)
    finally:
        del w

def test_typeof(double x):
    """
    >>> test_func_ptr(3)
    9.0
    >>> test_func_ptr(-1.5)
    2.25
    """
    try:
        w = new Wrap[cython.typeof(&f)](&f)
        return w.get()(x)
    finally:
        del w

def test_cast_template_pointer():
    """
    >>> test_cast_template_pointer()
    """
    cdef SubClass[int, float] *sub = new SubClass[int, float]()
    cdef SuperClass[int, float] *sup

    sup = sub
    sup =  sub

def test_static(x):
    """
    >>> test_static(2)
    (1, 1.0)
    >>> test_static(3)
    (1, 1.5)
    """
    return Div[int].half(x), Div[double].half(x)

def test_pure_syntax(int i):
    """
    >>> test_ptr(3)
    3
    >>> test_ptr(5)
    5
    """
    try:
        w = new Wrap[cython.pointer(int)](&i)
        return deref(w.get())
    finally:
        del w
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_templates_helper.h0000644000175100001770000000234500000000000022116 0ustar00runnerdocker00000000000000template 
class Wrap {
    T value;
public:
    typedef S AltType;

    Wrap(T v) : value(v) { }
    void set(T v) { value = v; }
    T get(void) { return value; }
    bool operator==(Wrap other) { return value == other.value; }

    S get_alt_type(void) { return (S) value; }
    void set_alt_type(S v) { value = (T) v; }

    U create(void) { return (U) value; }
    bool accept(U v) { return v == (U) value; }
};

template 
class Pair {
    T1 _first;
    T2 _second;
public:
    Pair() { }
    Pair(T1 u, T2 v) { _first = u; _second = v; }
    T1 first(void) { return _first; }
    T2 second(void) { return _second; }
    bool operator==(Pair other) { return _first == other._first && _second == other._second; }
    bool operator!=(Pair other) { return _first != other._first || _second != other._second; }
};

template 
class SuperClass {
public:
    SuperClass() {}
};

template 
class SubClass : public SuperClass {
};

template 
class Div {
public:
    static T half(T value) { return value / 2; }
};

template 
class BinaryAnd {
public:
    static T1 call(T1 x, T2 y) { return x & y; }
};
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_type_inference.pyx0000644000175100001770000000346200000000000022152 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, werror

cdef extern from "shapes.h" namespace "shapes":
    cdef cppclass Shape:
        float area()

    cdef cppclass Circle(Shape):
        int radius
        Circle(int)

    cdef cppclass Square(Shape):
        Square(int)

    cdef cppclass Empty(Shape):
        Empty()

    cdef Empty make_Empty "shapes::Empty"()

from cython cimport typeof

from cython.operator cimport dereference as d
from cython.operator cimport preincrement as incr
from libcpp.vector cimport vector

def test_reversed_vector_iteration(L):
    """
    >>> test_reversed_vector_iteration([1,2,3])
    int: 3
    int: 2
    int: 1
    int
    """
    cdef vector[int] v = L

    it = v.rbegin()
    while it != v.rend():
        a = d(it)
        incr(it)
        print('%s: %s' % (typeof(a), a))
    print(typeof(a))

def test_derived_types(int size, bint round):
    """
    >>> test_derived_types(5, True)
    Shape *
    >>> test_derived_types(5, False)
    Shape *
    """
    if round:
        ptr = new Circle(size)
    else:
        ptr = new Square(size)
    print typeof(ptr)
    del ptr

def test_stack_allocated(bint b=True):
    """
    >>> test_stack_allocated()
    """
    e1 = Empty()
    e2 = Empty()
    e = e1 if b else e2
    assert typeof(e1) == "Empty", typeof(e1)
    assert typeof(e2) == "Empty", typeof(e2)
    assert typeof(e) == "Empty", typeof(e)

cdef extern from *:
    """
    template 
    struct MyTemplate {};
    """
    cdef cppclass MyTemplate[T]:
        MyTemplate()

def test_template_types():
    """
    >>> test_template_types()
    """
    t_stack = MyTemplate[int]()
    assert typeof(t_stack) == "MyTemplate[int]", typeof(t_stack)

    t_ptr = new MyTemplate[double]()
    try:
        assert typeof(t_ptr) == "MyTemplate[double] *", typeof(t_ptr)
    finally:
        del t_ptr
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_unordered_map_helper.h0000644000175100001770000000043500000000000022742 0ustar00runnerdocker00000000000000#include 
#include 

struct IntVectorHash {
  size_t operator()(const std::vector& v) const {
    std::hash hasher;
    size_t seed = 0;
    for (int i : v) {
      seed ^= hasher(i) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
    }
    return seed;
  }
};
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpp_vector_in_generator.pyx0000644000175100001770000000033400000000000023204 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp

from libcpp.vector cimport vector

def stack_vector_in_generator(vector[int] vint):
    """
    >>> tuple( stack_vector_in_generator([1,2]) )
    (1, 2)
    """
    for i in vint:
        yield i
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4007223
Cython-3.0.8/tests/run/cpython_capi.pyx0000644000175100001770000000146200000000000020767 0ustar00runnerdocker00000000000000# mode: run
# tag: c-api

from cpython cimport mem
from cpython.pystate cimport PyGILState_Ensure, PyGILState_Release, PyGILState_STATE


def test_pymalloc():
    """
    >>> test_pymalloc()
    3
    """
    cdef char* m2
    cdef char* m =  mem.PyMem_Malloc(20)
    assert m
    try:
        m[0] = 1
        m[1] = 2
        m[2] = 3
        m2 =  mem.PyMem_Realloc(m, 10)
        assert m2
        m = m2
        return m[2]
    finally:
        mem.PyMem_Free(m)


def test_gilstate():
    """
    >>> test_gilstate()
    'ok'
    """

    # cython used to have invalid definition for PyGILState_STATE, which was
    # making the following code fail to compile
    cdef PyGILState_STATE gstate = PyGILState_Ensure()
    # TODO assert that GIL is taken
    PyGILState_Release(gstate)
    return 'ok'
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cpython_capi_py35.pyx0000644000175100001770000000273000000000000021646 0ustar00runnerdocker00000000000000# mode: run
# tag: c-api

# PyMem_RawMalloc tests that need to be disabled for Python < 3.5
# (some of these would work of Python 3.4, but it's easier to disable
# them in one place)

from cpython cimport mem

cdef short _assert_calloc(short* s, int n) except -1 with gil:
    """Assert array ``s`` of length ``n`` is zero and return 3."""
    assert not s[0] and not s[n - 1]
    s[0] += 1
    s[n - 1] += 3
    for i in range(1, n - 1):
        assert not s[i]
    return s[n - 1]

def test_pycalloc():
    """
    >>> test_pycalloc()
    3
    """
    cdef short* s =  mem.PyMem_Calloc(10, sizeof(short))
    if not s:
        raise MemoryError()
    try:
        return _assert_calloc(s, 10)
    finally:
        mem.PyMem_Free(s)

def test_pymalloc_raw():
    """
    >>> test_pymalloc_raw()
    3
    """
    cdef short i
    cdef short* s
    cdef char* m
    cdef char* m2 = NULL
    with nogil:
        s =  mem.PyMem_RawCalloc(10, sizeof(short))
        if not s:
            raise MemoryError()
        try:
            i = _assert_calloc(s, 10)
        finally:
            mem.PyMem_RawFree(s)
        m =  mem.PyMem_RawMalloc(20)
        if not m:
            raise MemoryError()
        try:
            m[0] = 1
            m[1] = 2
            m[2] = i
            m2 =  mem.PyMem_RawRealloc(m, 10)
            if m2:
                m = m2
            retval = m[2]
        finally:
            mem.PyMem_RawFree(m)
    assert m2
    return retval
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/crashT245.h0000644000175100001770000000005100000000000017366 0ustar00runnerdocker00000000000000typedef struct {
    int x;
} MyStruct;

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/crashT245.pyx0000644000175100001770000000022300000000000017760 0ustar00runnerdocker00000000000000# ticket: t245

cimport crashT245_pxd

def f():
    """
    >>> f()
    {'x': 1}
    """
    cdef crashT245_pxd.MyStruct s
    s.x = 1
    print s
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/crashT245_pxd.pxd0000644000175100001770000000011500000000000020606 0ustar00runnerdocker00000000000000cdef extern from "crashT245.h":
    ctypedef struct MyStruct:
        int x

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cross_closure_type_inference.pyx0000644000175100001770000000351100000000000024250 0ustar00runnerdocker00000000000000# mode: run
# tag: typeinference

cimport cython


def test_outer_inner_double():
    """
    >>> print(test_outer_inner_double())
    double
    """
    x = 1.0
    def inner():
        nonlocal x
        x = 2.0
    inner()
    assert x == 2.0, str(x)
    return cython.typeof(x)


def test_outer_inner_double_int():
    """
    >>> print(test_outer_inner_double_int())
    ('double', 'double')
    """
    x = 1.0
    y = 2
    def inner():
        nonlocal x, y
        x = 1
        y = 2.0
    inner()
    return cython.typeof(x), cython.typeof(y)


def test_outer_inner_pyarg():
    """
    >>> print(test_outer_inner_pyarg())
    2
    long
    """
    x = 1
    def inner(y):
        return x + y
    print inner(1)
    return cython.typeof(x)


def test_outer_inner_carg():
    """
    >>> print(test_outer_inner_carg())
    2.0
    long
    """
    x = 1
    def inner(double y):
        return x + y
    print inner(1)
    return cython.typeof(x)


def test_outer_inner_incompatible():
    """
    >>> print(test_outer_inner_incompatible())
    Python object
    """
    x = 1.0
    def inner():
        nonlocal x
        x = 'test'
    inner()
    return cython.typeof(x)


def test_outer_inner_ptr():
    """
    >>> print(test_outer_inner_ptr())
    double *
    """
    x = 1.0
    xptr_outer = &x
    def inner():
        nonlocal x
        x = 1
        xptr_inner = &x
        assert cython.typeof(xptr_inner) == cython.typeof(xptr_outer), (
            '%s != %s' % (cython.typeof(xptr_inner), cython.typeof(xptr_outer)))
    inner()
    return cython.typeof(xptr_outer)


def test_outer_inner2_double():
    """
    >>> print(test_outer_inner2_double())
    double
    """
    x = 1.0
    def inner1():
        nonlocal x
        x = 2
    def inner2():
        nonlocal x
        x = 3.0
    inner1()
    inner2()
    return cython.typeof(x)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cstringmeth.pyx0000644000175100001770000000014200000000000020630 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> y
('1', '2', '3')
>>> x
'1foo2foo3'
"""


y = ('1','2','3')

x = 'foo'.join(y)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cstringmul.pyx0000644000175100001770000000163700000000000020502 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> print(spam)
eggseggseggseggs
>>> print(uspam)
eggseggseggseggs
>>> print(bspam.decode('ascii'))
eggseggseggseggs

>>> print(grail)
tomatotomatotomatotomatotomatotomatotomato
>>> len(grail_long)
4200
>>> print(ugrail)
tomatotomatotomatotomatotomatotomatotomato
>>> len(ugrail_long)
4200
>>> print(bgrail.decode('ascii'))
tomatotomatotomatotomatotomatotomatotomato
>>> len(bgrail_long)
4200
"""

bspam = b"eggs" * 4
bgrail = 7 * b"tomato"
bgrail_long = 700 * b"tomato"

spam = "eggs" * 4
grail = 7 * "tomato"
grail_long = 700 * "tomato"

uspam = u"eggs" * 4
ugrail = 7 * u"tomato"
ugrail_long = 700 * u"tomato"

cimport cython

@cython.test_assert_path_exists("//StringNode[@value = '-----']")
@cython.test_assert_path_exists("//StringNode[@unicode_value = '-----']")
def gh3951():
    """
    Bug occurs with language_level=2 and affects StringNode.value
    >>> gh3951()
    '-----'
    """
    return "-"*5
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cstruct.pyx0000644000175100001770000000210600000000000017772 0ustar00runnerdocker00000000000000cdef struct Grail

cdef struct Spam:
    int i
    char c
    float *p[42]
    Grail *g

cdef struct Grail:
    Spam *s

cdef Spam spam, ham

cdef void eggs_i(Spam s):
    cdef int j
    j = s.i
    s.i = j

cdef void eggs_c(Spam s):
    cdef char c
    c = s.c
    s.c = c

cdef void eggs_p(Spam s):
    cdef float *p
    p = s.p[0]
    s.p[0] = p

cdef void eggs_g(Spam s):
    cdef float *p
    p = s.p[0]
    s.p[0] = p

spam = ham

def test_i():
    """
    >>> test_i()
    """
    spam.i = 1
    eggs_i(spam)

def test_c():
    """
    >>> test_c()
    """
    spam.c = c'a'
    eggs_c(spam)

def test_p():
    """
    >>> test_p()
    """
    cdef float f
    spam.p[0] = &f
    eggs_p(spam)

def test_g():
    """
    >>> test_g()
    """
    cdef Grail l
    spam.g = &l
    eggs_g(spam)


cdef struct Ints:
    int a, b

def assign_fields_in_loop():
    """
    >>> assign_fields_in_loop()
    2
    """
    cdef int i = 0
    cdef Ints s
    for s.a, s.b in enumerate(range(3)):
        assert s.a == s.b
        assert s.a == i
        i += 1

    assert s.a == s.b
    return s.b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/ct_DEF.pyx0000644000175100001770000002244500000000000017377 0ustar00runnerdocker00000000000000# mode: run
# tag: warnings

cimport cython

__doc__ = u"""
    >>> s()
    b'spam'
"""

_unicode = unicode

import sys
IS_PY3 = sys.version_info[0] >= 3

if not IS_PY3:
    __doc__ = __doc__.replace(u" b'", u" '")


def print_large_number(n):
    print(str(n).rstrip('L'))


DEF TUPLE = (1, 2, u"buckle my shoe")
DEF TRUE_FALSE = (True, False)
DEF NONE = None

DEF CHAR = c'x'
DEF INT0 = -1
DEF INT1 = 42
DEF INT2 = 0x42
DEF INT3 = -0x42
DEF LONG = 666L
DEF LARGE_NUM32 = (1 << 32) - 1
DEF LARGE_NUM64 = (1 << 64) - 1
DEF FLOAT = 12.5
DEF EXACT_FLOAT = 0.577215664901532860606512090082402431
DEF E_FLOAT = 0.5772156E4  # Cannot currently warn about this since we can't safely compare the string repr.
DEF BYTES = b"spam"
DEF UNICODE = u"spam-u"
DEF TWO = TUPLE[1]
DEF FIVE = TWO + 3
DEF TRUE  = TRUE_FALSE[0]
DEF FALSE = TRUE_FALSE[1]
DEF INT_TUPLE1 = TUPLE[:2]
DEF INT_TUPLE2 = TUPLE[1:4:2]
DEF ELLIPSIS = ...
DEF EXPRESSION = int(float(2*2)) + int(str(2)) + int(max(1,2,3)) + sum([TWO, FIVE])
DEF UNICODE_EXPRESSION = unicode(BYTES.decode('utf8')).encode('ascii').decode('latin1')


def c():
    """
    >>> c()
    120
    """
    cdef char c = CHAR
    return c

def i0():
    """
    >>> i0() == -1
    True
    """
    cdef int i = INT0
    return i

def i1():
    """
    >>> i1() == 42
    True
    """
    cdef int i = INT1
    return i

def i2():
    """
    >>> i2() == 0x42
    True
    """
    cdef int i = INT2
    return i

def i3():
    """
    >>> i3() == -0x42
    True
    """
    cdef int i = INT3
    return i

def l():
    """
    >>> l()
    666
    """
    cdef long l = LONG
    return l

def large_nums():
    """
    >>> ul32, ul64, l64, n64 = large_nums()
    >>> print_large_number(ul32)
    4294967295
    >>> print_large_number(ul64)
    18446744073709551615
    >>> print_large_number(l64)
    4294967295
    >>> print_large_number(n64)
    -4294967295
    """
    cdef unsigned long ul32 = LARGE_NUM32
    cdef unsigned long long ul64 = LARGE_NUM64
    cdef long long l64 = LARGE_NUM32
    cdef long long n64 = -LARGE_NUM32
    return ul32, ul64, l64, n64

def f():
    """
    >>> f()
    12.5
    """
    cdef float f = FLOAT
    return f

def s():
    """
    see module docstring above
    """
    cdef char* s = BYTES
    return s

def type_of_bytes():
    """
    >>> t, s = type_of_bytes()
    >>> assert t is bytes, t
    >>> assert type(s) is bytes, type(s)
    """
    t = type(BYTES)
    s = BYTES
    return t, s

def type_of_unicode():
    """
    >>> t, s = type_of_unicode()
    >>> assert t is _unicode, t
    >>> assert type(s) is _unicode, type(s)
    """
    t = type(UNICODE)
    s = UNICODE
    return t, s

@cython.test_assert_path_exists('//TupleNode')
def constant_tuple():
    """
    >>> constant_tuple()[:-1]
    (1, 2)
    >>> print(constant_tuple()[-1])
    buckle my shoe
    """
    cdef object t = TUPLE
    return t

@cython.test_assert_path_exists('//IntNode')
def tuple_indexing():
    """
    >>> tuple_indexing()
    2
    """
    cdef int two = INT_TUPLE1[-1]
    return two

def two():
    """
    >>> two()
    2
    """
    cdef int two = TWO
    return two

def five():
    """
    >>> five()
    5
    """
    cdef int five = FIVE
    return five

@cython.test_assert_path_exists('//BoolNode')
def true():
    """
    >>> true()
    True
    """
    cdef bint true = TRUE
    return true

@cython.test_assert_path_exists('//BoolNode')
def false():
    """
    >>> false()
    False
    """
    cdef bint false = FALSE
    return false

def ellipsis():
    """
    >>> ellipsis()
    Ellipsis
    """
    return ELLIPSIS

@cython.test_assert_path_exists('//IntNode')
@cython.test_fail_if_path_exists('//AddNode')
def expression():
    """
    >>> expression()
    16
    """
    cdef int i = EXPRESSION
    return i


def unicode_expression():
    """
    >>> print(unicode_expression())
    spam
    """
    s = UNICODE_EXPRESSION
    return s


def none():
    """
    >>> none()
    """
    return NONE


_IGNORE = """
24:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
25:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
26:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
28:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
29:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
30:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
31:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
32:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
33:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
34:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
35:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
36:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
37:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
37:18: Using this floating point value with DEF may lose precision, using 0.5772156649015329
38:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
39:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
40:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
41:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
42:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
43:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
44:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
45:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
46:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
47:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
48:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
49:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
"""

_WARNINGS = """
37:18: Using this floating point value with DEF may lose precision, using 0.5772156649015329
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/ct_IF.pyx0000644000175100001770000000622100000000000017271 0ustar00runnerdocker00000000000000# mode: run
# tag: warnings

DEF NO = 0
DEF YES = 1

def f():
    """
    >>> f()
    1
    """
    cdef int i
    IF YES:
        i = 1
    ELIF NO:
        i = 2
    ELSE:
        i = 3
    return i

def g():
    """
    >>> g()
    2
    """
    cdef int i
    IF NO:
        i = 1
    ELIF YES:
        i = 2
    ELSE:
        i = 3
    return i

def h():
    """
    >>> h()
    3
    """
    cdef int i
    IF NO:
        i = 1
    ELIF NO:
        i = 2
    ELSE:
        i = 3
    return i


def control_flow_DEF1():
    """
    >>> control_flow_DEF1()
    B should be 2.
    2
    """
    IF YES:
        DEF B=2
        print('B should be 2.')
    ELSE:
        DEF B=3
        print('B should be 3.')
    return B


def control_flow_DEF2():
    """
    >>> control_flow_DEF2()
    B should be 3.
    3
    """
    IF NO:
        DEF B=2
        print('B should be 2.')
    ELSE:
        DEF B=3
        print('B should be 3.')
    return B


_IGNORE = """
4:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
5:0: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
57:8: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
60:8: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
72:8: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
75:8: The 'DEF' statement is deprecated and will be removed in a future Cython version. Consider using global variables, constants, and in-place literals instead. See https://github.com/cython/cython/issues/4310
"""

_WARNINGS = """
13:4: The 'IF' statement is deprecated and will be removed in a future Cython version. Consider using runtime conditions or C macros instead. See https://github.com/cython/cython/issues/4310
27:4: The 'IF' statement is deprecated and will be removed in a future Cython version. Consider using runtime conditions or C macros instead. See https://github.com/cython/cython/issues/4310
41:4: The 'IF' statement is deprecated and will be removed in a future Cython version. Consider using runtime conditions or C macros instead. See https://github.com/cython/cython/issues/4310
56:4: The 'IF' statement is deprecated and will be removed in a future Cython version. Consider using runtime conditions or C macros instead. See https://github.com/cython/cython/issues/4310
71:4: The 'IF' statement is deprecated and will be removed in a future Cython version. Consider using runtime conditions or C macros instead. See https://github.com/cython/cython/issues/4310
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/ctruthtests.pyx0000644000175100001770000000301400000000000020676 0ustar00runnerdocker00000000000000def test_ptr():
    """
    >>> test_ptr()
    False
    """
    cdef void* p = NULL
    if p:
        return True
    else:
        return False

def test_ptr2():
    """
    >>> test_ptr2()
    2
    """
    cdef char* p1 = NULL
    cdef char* p2 = NULL
    p1 += 1

    if p1 and p2:
        return 1
    elif p1 or p2:
        return 2
    else:
        return 3

def test_int(int i):
    """
    >>> test_int(0)
    False
    >>> test_int(1)
    True
    """
    if i:
        return True
    else:
        return False

def test_short(short i):
    """
    >>> test_short(0)
    False
    >>> test_short(1)
    True
    """
    if i:
        return True
    else:
        return False

def test_Py_ssize_t(Py_ssize_t i):
    """
    >>> test_Py_ssize_t(0)
    False
    >>> test_Py_ssize_t(1)
    True
    """
    if i:
        return True
    else:
        return False

cdef class TestExtInt:
    cdef int i
    def __init__(self, i): self.i = i

def test_attr_int(TestExtInt e):
    """
    >>> test_attr_int(TestExtInt(0))
    False
    >>> test_attr_int(TestExtInt(1))
    True
    """
    if e.i:
        return True
    else:
        return False

ctypedef union _aux:
    size_t i
    void *p

cdef class TestExtPtr:
    cdef void* p
    def __init__(self, int i):
        cdef _aux aux
        aux.i = i
        self.p = aux.p

def test_attr_ptr(TestExtPtr e):
    """
    >>> test_attr_ptr(TestExtPtr(0))
    False
    >>> test_attr_ptr(TestExtPtr(1))
    True
    """
    if e.p:
        return True
    else:
        return False
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/ctuple.pyx0000644000175100001770000001370600000000000017607 0ustar00runnerdocker00000000000000# mode: run

import cython


def simple_convert(*o):
    """
    >>> simple_convert(1, 2)
    (1, 2.0)

    >>> simple_convert(1)
    Traceback (most recent call last):
    TypeError: Expected a sequence of size 2, got size 1
    >>> simple_convert(1, 2, 3)
    Traceback (most recent call last):
    TypeError: Expected a sequence of size 2, got size 3
    """
    cdef (int, double) xy = o
    return xy


def convert_from_list(*o):
    """
    >>> convert_from_list(1, 2)
    (1, 2.0)

    >>> convert_from_list(1)
    Traceback (most recent call last):
    TypeError: Expected a sequence of size 2, got size 1
    >>> convert_from_list(1, 2, 3)
    Traceback (most recent call last):
    TypeError: Expected a sequence of size 2, got size 3
    """
    cdef object values = list(o)
    cdef (int, double) xy = values
    return xy


def convert_from_deque(*o):
    """
    >>> convert_from_deque(1, 2)
    (1, 2.0)

    >>> convert_from_deque(1)
    Traceback (most recent call last):
    TypeError: Expected a sequence of size 2, got size 1
    >>> convert_from_deque(1, 2, 3)
    Traceback (most recent call last):
    TypeError: Expected a sequence of size 2, got size 3
    """
    from collections import deque
    cdef object values = deque(o)
    cdef (int, double) xy = values
    return xy


def indexing((int, double) xy):
    """
    >>> indexing((1, 2))
    (2, 3.0)
    """
    x = xy[0]
    y = xy[1]
    xy[0] = x + 1
    xy[1] = y + 1
    return xy

def unpacking((int, double) xy):
    """
    >>> unpacking((1, 2))
    (1, 2.0)
    """
    x, y = xy
    return x, y

cdef (int, double) side_effect((int, double) xy):
    print "called with", xy
    return xy

def unpacking_with_side_effect((int, double) xy):
    """
    >>> unpacking_with_side_effect((1, 2))
    called with (1, 2.0)
    (1, 2.0)
    """
    x, y = side_effect(xy)
    return x, y

def packing_tuple(int x, double y):
    """
    >>> packing_tuple(1, 2)
    (1, 2.0)
    """
    cdef (int, double) xy = (x, y)
    assert xy == (x, y), xy
    xy = (x, y) * 1
    assert xy == (x, y), xy
    xy = 1 * (x, y)
    return xy

def packing_list(int x, double y):
    """
    >>> packing_list(1, 2)
    (1, 2.0)
    """
    cdef (int, double) xy = [x, y]
    assert xy == (x, y), xy
    xy = [x, y] * 1
    assert xy == (x, y), xy
    xy = 1 * [x, y]
    return xy

def coerce_packing_tuple(int x, int y):
    cdef (int, double) xy = (x, y)
    """
    >>> coerce_packing_tuple(1, 2)
    (1, 2.0)
    """
    return xy

def c_types(int a, double b):
    """
    >>> c_types(1, 2)
    (1, 2.0)
    """
    cdef int* a_ptr
    cdef double* b_ptr
    cdef (int*, double*) ab = (&a, &b)
    a_ptr, b_ptr = ab
    return a_ptr[0], b_ptr[0]


cdef union Union:
    int x
    double y


def union_in_ctuple_literal():
    """
    >>> union_in_ctuple_literal()
    (1, 2.0)
    """
    cdef (Union,) a = ({"x": 1},)
    cdef (Union,) b = ({"y": 2},)
    return a[0].x, b[0].y


def union_in_ctuple_dynamic(*values):
    """
    >>> union_in_ctuple_dynamic(1, {'x': 1})
    1
    >>> union_in_ctuple_dynamic(2, {'y': 2})
    2.0
    >>> union_in_ctuple_dynamic(1, {'x': 1, 'y': 2})
    Traceback (most recent call last):
    ValueError: More than one union attribute passed: 'x' and 'y'
    """
    cdef (int, Union) a = values
    return a[1].x if a[0] == 1 else a[1].y


cdef (int, int*) cdef_ctuple_return_type(int x, int* x_ptr):
    return x, x_ptr

def call_cdef_ctuple_return_type(int x):
    """
    >>> call_cdef_ctuple_return_type(2)
    (2, 2)
    """
    cdef (int, int*) res = cdef_ctuple_return_type(x, &x)
    return res[0], res[1][0]


cpdef (int, double) cpdef_ctuple_return_type(int x, double y):
    """
    >>> cpdef_ctuple_return_type(1, 2)
    (1, 2.0)
    """
    return x, y


def cast_to_ctuple(*o):
    """
    >>> cast_to_ctuple(1, 2.)
    (1, 2.0)
    """
    cdef int x
    cdef double y
    x, y = <(int, double)>o
    return x, y


@cython.infer_types(True)
def test_type_inference():
    """
    >>> test_type_inference()
    """
    cdef int x = 1
    cdef double y = 2
    cdef object o = 3
    xy = (x, y)
    assert cython.typeof(xy) == "(int, double)", cython.typeof(xy)
    xo = (x, o)
    assert cython.typeof(xo) == "tuple object", cython.typeof(xo)


@cython.locals(a=(int,int), b=(cython.long,cython.float))
def test_pure_python_declaration(x, y):
    """
    >>> test_pure_python_declaration(1, 2)
    (int, int)
    (long, float)
    ((1, 2), (1, 2.0))
    >>> test_pure_python_declaration(1.0, 2.0)
    (int, int)
    (long, float)
    ((1, 2), (1, 2.0))
    >>> test_pure_python_declaration('x', 'y')
    Traceback (most recent call last):
    TypeError: an integer is required
    """
    a = (x, y)
    b = (x, y)
    print(cython.typeof(a))
    print(cython.typeof(b))
    return (a, b)


def test_equality((int, int) ab, (int, int) cd, (int, int) ef):
    """
    >>> test_equality((1, 2), (3, 4), (5, 6))
    True
    >>> test_equality((1, 2), (3, 4), (3, 4))
    True
    >>> test_equality((3, 4), (3, 4), (3, 4))
    False
    """
    return ab < cd <= ef

def test_equality_different_types((double, int) ab, (int, int) cd, (long, int) ef):
    """
    >>> test_equality((1, 2), (3, 4), (5, 6))
    True
    >>> test_equality((1, 2), (3, 4), (3, 4))
    True
    >>> test_equality((3, 4), (3, 4), (3, 4))
    False
    """
    return ab < cd <= ef

def test_binop((int, int) ab, (double, double) cd):
    """
    >>> test_binop((1, 2), (3, 4))
    (1, 2, 3.0, 4.0)
    """
    return ab + cd

def test_mul((int, int) ab, int c):
    """
    >>> test_mul((1, 2), 3)
    (1, 2, 1, 2, 1, 2)
    """
    return ab * c

def test_mul_to_ctuple((int, int) ab, int c):
    """
    >>> test_mul_to_ctuple((1, 2), 2)
    (1, 2, 1, 2)
    >>> test_mul_to_ctuple((1, 2), 3)
    Traceback (most recent call last):
    TypeError: Expected a sequence of size 4, got size 6
    """
    result: tuple[cython.int, cython.int, cython.int, cython.int] = ab * c
    return result

def test_unop((int, int) ab):
    """
    >>> test_unop((1, 2))
    True
    """
    return not ab
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/ctypedef_bint.pyx0000644000175100001770000000302500000000000021123 0ustar00runnerdocker00000000000000from __future__ import print_function

from cython cimport typeof

ctypedef bint mybool

cdef mybool mybul = True
cdef bint bul = True
cdef int num = 42


def CondExprNode_to_obj(test):
    """
    >>> CondExprNode_to_obj(True)
    Python object | Python object
    2
    >>> CondExprNode_to_obj(False)
    Python object | Python object
    84
    """

    print(typeof(mybul if test else num), "|", typeof(bul if test else num))

    return (mybul if test else num) + (bul if test else num)


def BoolBinopNode_to_obj():
    """
    >>> BoolBinopNode_to_obj()
    Python object | Python object
    2
    """

    print(typeof(mybul or num), "|", typeof(bul or num))

    return (mybul or num) + (bul or num)


cdef int test_bool(mybool arg):
    return arg


def CondExprNode_to_bool(test):
    """
    >>> CondExprNode_to_bool(True)
    bint | bint
    0
    >>> CondExprNode_to_bool(False)
    bint | bint
    2
    """

    print(typeof(not mybul if test else mybul), "|", typeof(not bul if test else bul))

    # test_bool() would silently crash if one of the types is cast
    # to Python object and not just assigned.
    # It happens when a type is wrongly inferred as Python object
    # instead of bint or mybool.
    return test_bool(not mybul if test else mybul) + test_bool(not bul if test else bul)


def BoolBinopNode_to_bool():
    """
    >>> BoolBinopNode_to_bool()
    bint | bint
    2
    """

    print(typeof(not mybul or mybul), "|", typeof(not bul or bul))

    return test_bool(not mybul or mybul) + test_bool(not bul or bul)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/ctypedef_char_types.pyx0000644000175100001770000000264200000000000022334 0ustar00runnerdocker00000000000000
cimport cython
from cython cimport typeof

from libc.string cimport const_char, const_uchar

@cython.test_assert_path_exists(
    "//NameNode[@name = 'st' and @type.is_string = True]",
    "//NameNode[@name = 'ust' and @type.is_string = True]",
    "//NameNode[@name = 'my_st' and @type.is_string = True]",
    "//NameNode[@name = 'my_ust' and @type.is_string = True]",
    )
def const_charptrs():
    """
    >>> const_charptrs()
    """
    cdef object obj
    cdef const_char*  st  = b'XYZ'
    cdef const_uchar* ust = b'XYZ' # needs cast to unsigned

    assert typeof(st) == "const_char *", typeof(st)
    my_st = st
    assert typeof(my_st) == "const_char *", typeof(my_st)
    obj = my_st
    assert obj == b'XYZ', obj

    assert typeof(ust) == "const_uchar *", typeof(ust)
    my_ust = ust
    assert typeof(my_ust) == "const_uchar *", typeof(my_ust)
    obj = my_ust
    assert obj == b'XYZ', obj

ctypedef char mychar
ctypedef unsigned char myuchar

def const_char_arrays():
    """
    >>> const_char_arrays()
    """
    cdef int i
    cdef object obj
    cdef mychar[4]  st
    cdef myuchar[4] ust
    cdef char ch

    i = 0
    for ch in b'XYZ\0':
        st[i] = ch
        ust[i] = ch
        i += 1

    assert typeof(st) == "mychar [4]", typeof(st)
    obj = st
    assert obj == b'XYZ', obj

    assert typeof(ust) == "myuchar [4]", typeof(ust)
    obj = ust
    assert obj == b'XYZ', obj
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/ctypedef_delegation.pyx0000644000175100001770000000024200000000000022300 0ustar00runnerdocker00000000000000
ctypedef char* LPSTR

def typedef_delegation():
    """
    >>> typedef_delegation()
    """
    cdef LPSTR c_str = b"ascii"
    assert c_str == b"ascii"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/ctypedef_int_types_T333.pyx0000644000175100001770000003637100000000000022733 0ustar00runnerdocker00000000000000# ticket: t333
#cython: autotestdict=True

# -------------------------------------------------------------------

cdef extern from "ctypedef_int_types_chdr_T333.h":
     ctypedef int SChar     ## "signed char"
     ctypedef int UChar     ## "unsigned char"
     ctypedef int SShort    ## "signed short"
     ctypedef int UShort    ## "unsigned short"
     ctypedef int SInt      ## "signed int"
     ctypedef int UInt      ## "unsigned int"
     ctypedef int SLong     ## "signed long"
     ctypedef int ULong     ## "unsigned long"
     ctypedef int SLongLong ## "signed PY_LONG_LONG"
     ctypedef int ULongLong ## "unsigned PY_LONG_LONG"

# -------------------------------------------------------------------

SCHAR_MAX = ((-1)>>1)
SCHAR_MIN = (-SCHAR_MAX-1)

def test_schar(SChar x):
   u"""
   >>> test_schar(-129) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to SChar
   >>> test_schar(-128)
   -128
   >>> test_schar(0)
   0
   >>> test_schar(127)
   127
   >>> test_schar(128) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to SChar
   """
   return x

def test_add_schar(x, y):
   u"""
   >>> test_add_schar(SCHAR_MIN, -1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to SChar
   >>> test_add_schar(SCHAR_MIN, 0) == SCHAR_MIN
   True
   >>> test_add_schar(SCHAR_MIN, 1) == SCHAR_MIN+1
   True
   >>> test_add_schar(SCHAR_MAX, -1) == SCHAR_MAX-1
   True
   >>> test_add_schar(SCHAR_MAX, 0) == SCHAR_MAX
   True
   >>> test_add_schar(SCHAR_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to SChar
   """
   cdef SChar r = x + y
   return r

UCHAR_MAX = ((-1))

def test_uchar(UChar x):
   u"""
   >>> test_uchar(-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: can't convert negative value to UChar
   >>> test_uchar(0)
   0
   >>> test_uchar(1)
   1
   >>> test_uchar(UCHAR_MAX) == UCHAR_MAX
   True
   >>> test_uchar(UCHAR_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to UChar
   """
   return x

def test_add_uchar(x, y):
   u"""
   >>> test_add_uchar(UCHAR_MAX, 0) == UCHAR_MAX
   True
   >>> test_add_uchar(UCHAR_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to UChar
   """
   cdef UChar r = x + y
   return r

# -------------------------------------------------------------------

SSHORT_MAX = ((-1)>>1)
SSHORT_MIN = (-SSHORT_MAX-1)

def test_sshort(SShort x):
   u"""
   >>> test_sshort(SSHORT_MIN-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to SShort
   >>> test_sshort(SSHORT_MIN) == SSHORT_MIN
   True
   >>> test_sshort(-1)
   -1
   >>> test_sshort(0)
   0
   >>> test_sshort(1)
   1
   >>> test_sshort(SSHORT_MAX) == SSHORT_MAX
   True
   >>> test_sshort(SSHORT_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_sshort(x, y):
   u"""
   >>> test_add_sshort(SSHORT_MIN, -1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to SShort
   >>> test_add_sshort(SSHORT_MIN, 0) == SSHORT_MIN
   True
   >>> test_add_sshort(SSHORT_MIN, 1) == SSHORT_MIN+1
   True
   >>> test_add_sshort(SSHORT_MAX, -1) == SSHORT_MAX-1
   True
   >>> test_add_sshort(SSHORT_MAX, 0) == SSHORT_MAX
   True
   >>> test_add_sshort(SSHORT_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to SShort
   """
   cdef SShort r = x + y
   return r

USHORT_MAX = ((-1))

def test_ushort(UShort x):
   u"""
   >>> test_ushort(-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: can't convert negative value to UShort
   >>> test_ushort(0)
   0
   >>> test_ushort(1)
   1
   >>> test_ushort(USHORT_MAX) == USHORT_MAX
   True
   >>> test_ushort(USHORT_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to UShort
   """
   return x

def test_add_ushort(x, y):
   u"""
   >>> test_add_ushort(USHORT_MAX, 0) == USHORT_MAX
   True
   >>> test_add_ushort(USHORT_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: value too large to convert to UShort
   """
   cdef UShort r = x + y
   return r

# -------------------------------------------------------------------

SINT_MAX = ((-1)>>1)
SINT_MIN = (-SINT_MAX-1)

def test_sint(SInt x):
   u"""
   >>> test_sint(SINT_MIN-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_sint(SINT_MIN) == SINT_MIN
   True
   >>> test_sint(-1)
   -1
   >>> test_sint(0)
   0
   >>> test_sint(1)
   1
   >>> test_sint(SINT_MAX) == SINT_MAX
   True
   >>> test_sint(SINT_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_sint(x, y):
   u"""
   >>> test_add_sint(SINT_MIN, -1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_add_sint(SINT_MIN, 0) == SINT_MIN
   True
   >>> test_add_sint(SINT_MIN, 1) == SINT_MIN+1
   True
   >>> test_add_sint(SINT_MAX, -1) == SINT_MAX-1
   True
   >>> test_add_sint(SINT_MAX, 0) == SINT_MAX
   True
   >>> test_add_sint(SINT_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   cdef SInt r = x + y
   return r

UINT_MAX = (-1)

def test_uint(UInt x):
   u"""
   >>> test_uint(-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: can't convert negative value to UInt
   >>> print(test_uint(0))
   0
   >>> print(test_uint(1))
   1
   >>> test_uint(UINT_MAX) == UINT_MAX
   True
   >>> test_uint(UINT_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_uint(x, y):
   u"""
   >>> test_add_uint(UINT_MAX, 0) == UINT_MAX
   True
   >>> test_add_uint(UINT_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   cdef UInt r = x + y
   return r

# -------------------------------------------------------------------

SLONG_MAX = ((-1)>>1)
SLONG_MIN = (-SLONG_MAX-1)

def test_slong(long x):
   u"""
   >>> test_slong(SLONG_MIN-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_slong(SLONG_MIN) == SLONG_MIN
   True
   >>> test_slong(-1)
   -1
   >>> test_slong(0)
   0
   >>> test_slong(1)
   1
   >>> test_slong(SLONG_MAX) == SLONG_MAX
   True
   >>> test_slong(SLONG_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_slong(x, y):
   u"""
   >>> test_add_slong(SLONG_MIN, -1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_add_slong(SLONG_MIN, 0) == SLONG_MIN
   True
   >>> test_add_slong(SLONG_MIN, 1) == SLONG_MIN+1
   True
   >>> test_add_slong(SLONG_MAX, -1) == SLONG_MAX-1
   True
   >>> test_add_slong(SLONG_MAX, 0) == SLONG_MAX
   True
   >>> test_add_slong(SLONG_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   cdef SLong r = x + y
   return r

ULONG_MAX = (-1)

def test_ulong(ULong x):
   u"""
   >>> test_ulong(-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: can't convert negative value to ULong
   >>> print(test_ulong(0))
   0
   >>> print(test_ulong(1))
   1
   >>> test_ulong(ULONG_MAX) == ULONG_MAX
   True
   >>> test_ulong(ULONG_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_ulong(x, y):
   u"""
   >>> test_add_ulong(ULONG_MAX, 0) == ULONG_MAX
   True
   >>> test_add_ulong(ULONG_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   cdef ULong r = x + y
   return r

# -------------------------------------------------------------------

SLONGLONG_MAX = ((-1)>>1)
SLONGLONG_MIN = (-SLONGLONG_MAX-1)

def test_slonglong(long long x):
   u"""
   >>> test_slonglong(SLONGLONG_MIN-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_slonglong(SLONGLONG_MIN) == SLONGLONG_MIN
   True
   >>> print(test_slonglong(-1))
   -1
   >>> print(test_slonglong(0))
   0
   >>> print(test_slonglong(1))
   1
   >>> test_slonglong(SLONGLONG_MAX) == SLONGLONG_MAX
   True
   >>> test_slonglong(SLONGLONG_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_slonglong(x, y):
   u"""
   >>> test_add_slonglong(SLONGLONG_MIN, -1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_add_slonglong(SLONGLONG_MIN, 0) == SLONGLONG_MIN
   True
   >>> test_add_slonglong(SLONGLONG_MIN, 1) == SLONGLONG_MIN+1
   True
   >>> test_add_slonglong(SLONGLONG_MAX, -1) == SLONGLONG_MAX-1
   True
   >>> test_add_slonglong(SLONGLONG_MAX, 0) == SLONGLONG_MAX
   True
   >>> test_add_slonglong(SLONGLONG_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   cdef SLongLong r = x + y
   return r

ULONGLONG_MAX = (-1)

def test_ulonglong(ULongLong x):
   u"""
   >>> test_ulonglong(-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: can't convert negative value to ULongLong
   >>> print(test_ulonglong(0))
   0
   >>> print(test_ulonglong(1))
   1
   >>> test_ulonglong(ULONGLONG_MAX) == ULONGLONG_MAX
   True
   >>> test_ulonglong(ULONGLONG_MAX+1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   return x

def test_add_ulonglong(x, y):
   u"""
   >>> test_add_ulonglong(ULONGLONG_MAX, 0) == ULONGLONG_MAX
   True
   >>> test_add_ulonglong(ULONGLONG_MAX, 1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   """
   cdef ULongLong r = x + y
   return r

# -------------------------------------------------------------------

cdef class MyClass:
    """
    >>> a = MyClass()

    >>> vals = (SCHAR_MIN,     UCHAR_MAX,
    ...         SSHORT_MIN,    USHORT_MAX,
    ...         SINT_MIN,      UINT_MAX,
    ...         SLONG_MIN,     ULONG_MAX,
    ...         SLONGLONG_MIN, ULONGLONG_MAX)
    >>> a.setvalues(*vals)
    >>> a.getvalues() == vals
    True

    >>> vals = (SCHAR_MAX,     UCHAR_MAX,
    ...         SSHORT_MAX,    USHORT_MAX,
    ...         SINT_MAX,      UINT_MAX,
    ...         SLONG_MAX,     ULONG_MAX,
    ...         SLONGLONG_MAX, ULONGLONG_MAX)
    >>> a.setvalues(*vals)
    >>> a.getvalues() == vals
    True

    >>> vals = (0,) * 10
    >>> a.setvalues(*vals)
    >>> a.getvalues() == vals
    True


    """
    cdef:
       SChar     attr_schar
       UChar     attr_uchar
       SShort    attr_sshort
       UShort    attr_ushort
       SInt      attr_sint
       UInt      attr_uint
       SLong     attr_slong
       ULong     attr_ulong
       SLongLong attr_slonglong
       ULongLong attr_ulonglong

    cpdef setvalues(self,
                    SChar     arg_schar     ,
                    UChar     arg_uchar     ,
                    SShort    arg_sshort    ,
                    UShort    arg_ushort    ,
                    SInt      arg_sint      ,
                    UInt      arg_uint      ,
                    SLong     arg_slong     ,
                    ULong     arg_ulong     ,
                    SLongLong arg_slonglong ,
                    ULongLong arg_ulonglong ):
        self.attr_schar     = arg_schar
        self.attr_uchar     = arg_uchar
        self.attr_sshort    = arg_sshort
        self.attr_ushort    = arg_ushort
        self.attr_sint      = arg_sint
        self.attr_uint      = arg_uint
        self.attr_slong     = arg_slong
        self.attr_ulong     = arg_ulong
        self.attr_slonglong = arg_slonglong
        self.attr_ulonglong = arg_ulonglong

    cpdef getvalues(self):
        return (self.attr_schar     ,
                self.attr_uchar     ,
                self.attr_sshort    ,
                self.attr_ushort    ,
                self.attr_sint      ,
                self.attr_uint      ,
                self.attr_slong     ,
                self.attr_ulong     ,
                self.attr_slonglong ,
                self.attr_ulonglong )


# -------------------------------------------------------------------

cdef extern from *:
    ctypedef signed   MySInt1 "signed short"
    ctypedef unsigned MyUInt1 "unsigned short"

def test_MySInt1(MySInt1 x):
   u"""
   >>> test_MySInt1(-1)
   -1
   >>> test_MySInt1(0)
   0
   >>> test_MySInt1(1)
   1
   """
   return x

def test_MyUInt1(MyUInt1 x):
   u"""
   >>> test_MyUInt1(-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: ...
   >>> test_MyUInt1(0)
   0
   >>> test_MyUInt1(1)
   1
   """
   return x

cdef extern from *:
    ctypedef signed   MySInt2 "signed short"
    ctypedef unsigned MyUInt2 "unsigned short"

def test_MySInt2(MySInt2 x):
   u"""
   >>> test_MySInt2(-1)
   -1
   >>> test_MySInt2(0)
   0
   >>> test_MySInt2(1)
   1
   """
   return x

def test_MyUInt2(MyUInt2 x):
   u"""
   >>> test_MyUInt2(-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: can't convert negative value to ...
   >>> test_MyUInt2(0)
   0
   >>> test_MyUInt2(1)
   1
   """
   return x

# -------------------------------------------------------------------

cimport ctypedef_int_types_defs_T333 as defs

def test_DefSInt(defs.SInt x):
   u"""
   >>> test_DefSInt(-1)
   -1
   >>> test_DefSInt(0)
   0
   >>> test_DefSInt(1)
   1
   """
   return x

def test_DefUChar(defs.UChar x):
   u"""
   >>> test_DefUChar(-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: can't convert negative value to ...
   >>> test_DefUChar(0)
   0
   >>> test_DefUChar(1)
   1
   """
   return x

def test_ExtSInt(defs.ExtSInt x):
   u"""
   >>> test_ExtSInt(-1)
   -1
   >>> test_ExtSInt(0)
   0
   >>> test_ExtSInt(1)
   1
   """
   return x

def test_ExtUInt(defs.ExtUInt x):
   u"""
   >>> test_ExtUInt(-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: can't convert negative value to ...
   >>> test_ExtUInt(0)
   0
   >>> test_ExtUInt(1)
   1
   """
   return x


ctypedef defs.SShort LocSInt
ctypedef defs.UShort LocUInt

def test_LocSInt(LocSInt x):
   u"""
   >>> test_LocSInt(-1)
   -1
   >>> test_LocSInt(0)
   0
   >>> test_LocSInt(1)
   1
   """
   return x

def test_LocUInt(LocUInt x):
   u"""
   >>> test_LocUInt(-1) #doctest: +ELLIPSIS
   Traceback (most recent call last):
       ...
   OverflowError: can't convert negative value to ...
   >>> test_LocUInt(0)
   0
   >>> test_LocUInt(1)
   1
   """
   return x

# -------------------------------------------------------------------
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/ctypedef_int_types_chdr_T333.h0000644000175100001770000000054600000000000023335 0ustar00runnerdocker00000000000000typedef signed   char  	    SChar;
typedef unsigned char  	    UChar;
typedef signed   short 	    SShort;
typedef unsigned short 	    UShort;
typedef signed   int   	    SInt;
typedef unsigned int   	    UInt;
typedef signed   long  	    SLong;
typedef unsigned long  	    ULong;
typedef signed   long long  SLongLong;
typedef unsigned long long  ULongLong;
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/ctypedef_int_types_defs_T333.pxd0000644000175100001770000000115400000000000023676 0ustar00runnerdocker00000000000000cdef extern from "ctypedef_int_types_chdr_T333.h":
    ctypedef int SChar     ## "signed char"
    ctypedef int UChar     ## "unsigned char"
    ctypedef int SShort    ## "signed short"
    ctypedef int UShort    ## "unsigned short"
    ctypedef int SInt      ## "signed int"
    ctypedef int UInt      ## "unsigned int"
    ctypedef int SLong     ## "signed long"
    ctypedef int ULong     ## "unsigned long"
    ctypedef int SLongLong ## "signed PY_LONG_LONG"
    ctypedef int ULongLong ## "unsigned PY_LONG_LONG"

cdef extern from *:
    ctypedef int ExtSInt "signed short"
    ctypedef int ExtUInt "unsigned short"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cunion.pyx0000644000175100001770000000367700000000000017614 0ustar00runnerdocker00000000000000cdef union Spam:
    int i
    char c
    float *p[42]

cdef Spam spam, ham

cdef void eggs_i(Spam s):
    cdef int j
    j = s.i
    s.i = j

cdef void eggs_c(Spam s):
    cdef char c
    c = s.c
    s.c = c

cdef void eggs_p(Spam s):
    cdef float *p
    p = s.p[0]
    s.p[0] = p

spam = ham


def test_i():
    """
    >>> test_i()
    """
    spam.i = 1
    eggs_i(spam)


def test_c():
    """
    >>> test_c()
    """
    spam.c = c'a'
    eggs_c(spam)


def test_p():
    """
    >>> test_p()
    """
    cdef float f
    spam.p[0] = &f
    eggs_p(spam)


cdef union AllCharptr:
    char* s1
    char* s2
    char* s3


def test_charptr_to_py():
    """
    >>> result = test_charptr_to_py()
    >>> len(result)
    3
    >>> result['s1'] == b'abc'
    True
    >>> result['s2'] == b'abc'
    True
    >>> result['s3'] == b'abc'
    True
    """
    cdef AllCharptr u
    u.s1 = b"abc"
    return u


cdef union SafeMix:
    char c
    unsigned char uc
    signed char sc
    short w
    int i
    long l
    size_t z
    float f
    double d


def test_safe_type_mix_from_to_py(v):
    """
    >>> test_safe_type_mix_from_to_py({'l': 32, 'c': 32})
    Traceback (most recent call last):
    ValueError: More than one union attribute passed: 'c' and 'l'

    >>> result = test_safe_type_mix_from_to_py({'c': 32})
    >>> sorted(result)
    ['c', 'd', 'f', 'i', 'l', 'sc', 'uc', 'w', 'z']
    >>> result['c']
    32
    >>> result['z'] != 0
    True

    >>> result = test_safe_type_mix_from_to_py({'uc': 32})
    >>> len(result)
    9
    >>> result['uc']
    32

    >>> result = test_safe_type_mix_from_to_py({'l': 100})
    >>> result['l']
    100

    >>> result = test_safe_type_mix_from_to_py({'z': 0})
    >>> result['z']
    0
    >>> result['i']
    0
    >>> result['l']
    0

    >>> result = test_safe_type_mix_from_to_py({'d': 2**52 - 1})
    >>> result['d']
    4503599627370495.0
    >>> result['z'] != 0
    True
    """
    cdef SafeMix u = v
    return u
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/curiously_recurring_template_pattern_GH1458.pyx0000644000175100001770000000114300000000000026751 0ustar00runnerdocker00000000000000# tag: cpp

cdef extern from "curiously_recurring_template_pattern_GH1458_suport.h":

    cdef cppclass Base[T, Derived]:
        Base(T)
        Derived half()
        T calculate()

    cdef cppclass Square[T](Base[T, Square[T]]):
        Square(T)

    cdef cppclass Cube[T](Base[T, Cube[T]]):
        Cube(T)


def test_derived(int x):
    """
    >>> test_derived(5)
    (6.25, 8)
    """
    try:
        square_double = new Square[double](x)
        cube_int = new Cube[int](x)
        return square_double.half().calculate(), cube_int.half().calculate()
    finally:
        del square_double, cube_int
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/curiously_recurring_template_pattern_GH1458_suport.h0000644000175100001770000000112100000000000027770 0ustar00runnerdocker00000000000000template
class Base {
public:
    Base(T x) : x_(x) { };

    Derived half() {
        Derived d(x_ / 2);
        return d;
    };

    virtual T calculate() = 0;
    virtual ~Base() { };

protected:
    T x_;
};


template
class Square : public Base > {
public:
    Square(T x) : Base >(x) { };

    T calculate() { return this->x_ * this->x_; }
};


template
class Cube : public Base > {
public:
    Cube(T x) : Base >(x) { };

    T calculate() { return this->x_ * this->x_ * this->x_; }
};
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cyclic_gc.pyx0000644000175100001770000001302400000000000020223 0ustar00runnerdocker00000000000000# mode: run
# tag: cyclicgc


cimport cython

@cython.test_fail_if_path_exists('//CClassDefNode[@scope.has_cyclic_pyobject_attrs = True]')
@cython.test_assert_path_exists('//CClassDefNode',
                                '//CClassDefNode[@scope]',
                                '//CClassDefNode[@scope.has_cyclic_pyobject_attrs = False]')
cdef class ExtTypeNoGC:
    """
    >>> obj = ExtTypeNoGC()
    >>> obj = ExtTypeNoGC()
    >>> obj = ExtTypeNoGC()
    >>> obj = ExtTypeNoGC()
    >>> obj = ExtTypeNoGC()
    >>> obj = ExtTypeNoGC()
    """


@cython.test_fail_if_path_exists('//CClassDefNode[@scope.has_cyclic_pyobject_attrs = True]')
@cython.test_assert_path_exists('//CClassDefNode',
                                '//CClassDefNode[@scope]',
                                '//CClassDefNode[@scope.has_cyclic_pyobject_attrs = False]')
@cython.final
cdef class ExtTypeFinalNoGC:
    """
    >>> obj = ExtTypeFinalNoGC()
    >>> obj = ExtTypeFinalNoGC()
    >>> obj = ExtTypeFinalNoGC()
    >>> obj = ExtTypeFinalNoGC()
    >>> obj = ExtTypeFinalNoGC()
    >>> obj = ExtTypeFinalNoGC()
    """
    cdef bytes s


@cython.test_fail_if_path_exists('//CClassDefNode[@scope.has_cyclic_pyobject_attrs = True]')
@cython.test_assert_path_exists('//CClassDefNode',
                                '//CClassDefNode[@scope]',
                                '//CClassDefNode[@scope.has_cyclic_pyobject_attrs = False]')
cdef class ExtSubTypeNoGC(ExtTypeNoGC):
    """
    >>> obj = ExtSubTypeNoGC()
    >>> obj = ExtSubTypeNoGC()
    >>> obj = ExtSubTypeNoGC()
    >>> obj = ExtSubTypeNoGC()
    >>> obj = ExtSubTypeNoGC()
    >>> obj = ExtSubTypeNoGC()
    """


@cython.test_fail_if_path_exists('//CClassDefNode[@scope.has_cyclic_pyobject_attrs = True]')
@cython.test_assert_path_exists('//CClassDefNode',
                                '//CClassDefNode[@scope]',
                                '//CClassDefNode[@scope.has_cyclic_pyobject_attrs = False]')
cdef class ExtTypePyArgsNoGC:
    """
    >>> obj = ExtTypePyArgsNoGC()
    >>> obj = ExtTypePyArgsNoGC()
    >>> obj = ExtTypePyArgsNoGC()
    >>> obj = ExtTypePyArgsNoGC()
    >>> obj = ExtTypePyArgsNoGC()
    >>> obj = ExtTypePyArgsNoGC()
    """
    cdef bytes b
    cdef str s
    cdef unicode u
# eventually, this should work, too:
#    cdef ExtTypeFinalNoGC x


@cython.test_fail_if_path_exists('//CClassDefNode[@scope.has_cyclic_pyobject_attrs = True]')
@cython.test_assert_path_exists('//CClassDefNode',
                                '//CClassDefNode[@scope]',
                                '//CClassDefNode[@scope.has_cyclic_pyobject_attrs = False]')
cdef class ExtSubTypePyArgsNoGC(ExtTypePyArgsNoGC):
    """
    >>> obj = ExtSubTypePyArgsNoGC()
    >>> obj = ExtSubTypePyArgsNoGC()
    >>> obj = ExtSubTypePyArgsNoGC()
    >>> obj = ExtSubTypePyArgsNoGC()
    >>> obj = ExtSubTypePyArgsNoGC()
    >>> obj = ExtSubTypePyArgsNoGC()
    """


@cython.test_fail_if_path_exists('//CClassDefNode[@scope.has_cyclic_pyobject_attrs = False]')
@cython.test_assert_path_exists('//CClassDefNode',
                                '//CClassDefNode[@scope]',
                                '//CClassDefNode[@scope.has_cyclic_pyobject_attrs = True]')
cdef class ExtTypePyArgsWithGC:
    """
    >>> obj = ExtTypePyArgsWithGC()
    >>> obj = ExtTypePyArgsWithGC()
    >>> obj = ExtTypePyArgsWithGC()
    >>> obj = ExtTypePyArgsWithGC()
    >>> obj = ExtTypePyArgsWithGC()
    >>> obj = ExtTypePyArgsWithGC()
    >>> obj.create_cycle()
    """
    cdef bytes b
    cdef str s
    cdef unicode u
    cdef list l

    def create_cycle(self):
        self.l = [self]


@cython.test_fail_if_path_exists('//CClassDefNode[@scope.has_cyclic_pyobject_attrs = True]')
@cython.test_assert_path_exists('//CClassDefNode',
                                '//CClassDefNode[@scope]',
                                '//CClassDefNode[@scope.has_cyclic_pyobject_attrs = False]')
cdef class ExtSubTypePyArgsWithGC(ExtTypePyArgsWithGC):
    """
    >>> obj = ExtSubTypePyArgsWithGC()
    >>> obj = ExtSubTypePyArgsWithGC()
    >>> obj = ExtSubTypePyArgsWithGC()
    >>> obj = ExtSubTypePyArgsWithGC()
    >>> obj = ExtSubTypePyArgsWithGC()
    >>> obj = ExtSubTypePyArgsWithGC()
    >>> obj.create_cycle()
    """


@cython.test_fail_if_path_exists('//CClassDefNode[@scope.has_cyclic_pyobject_attrs = True]')
@cython.test_assert_path_exists('//CClassDefNode',
                                '//CClassDefNode[@scope]',
                                '//CClassDefNode[@scope.has_cyclic_pyobject_attrs = False]')
cdef class ExtSubTypePlusPyArgsWithGC(ExtSubTypePyArgsWithGC):
    """
    >>> obj = ExtSubTypePlusPyArgsWithGC()
    >>> obj = ExtSubTypePlusPyArgsWithGC()
    >>> obj = ExtSubTypePlusPyArgsWithGC()
    >>> obj = ExtSubTypePlusPyArgsWithGC()
    >>> obj = ExtSubTypePlusPyArgsWithGC()
    >>> obj = ExtSubTypePlusPyArgsWithGC()
    >>> obj.create_cycle()
    """
    cdef bytes b2
    cdef unicode u2


@cython.test_fail_if_path_exists('//CClassDefNode[@scope.has_cyclic_pyobject_attrs = False]')
@cython.test_assert_path_exists('//CClassDefNode',
                                '//CClassDefNode[@scope]',
                                '//CClassDefNode[@scope.has_cyclic_pyobject_attrs = True]')
cdef class ExtSubTypePlusGCPyArgsWithGC(ExtSubTypePlusPyArgsWithGC):
    """
    >>> obj = ExtSubTypePlusGCPyArgsWithGC()
    >>> obj = ExtSubTypePlusGCPyArgsWithGC()
    >>> obj = ExtSubTypePlusGCPyArgsWithGC()
    >>> obj = ExtSubTypePlusGCPyArgsWithGC()
    >>> obj = ExtSubTypePlusGCPyArgsWithGC()
    >>> obj = ExtSubTypePlusGCPyArgsWithGC()
    >>> obj.create_cycle()
    """
    cdef tuple t
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cyfunction.pyx0000644000175100001770000002304200000000000020466 0ustar00runnerdocker00000000000000# cython: binding=True
# mode: run
# tag: cyfunction

import sys
IS_PY2 = sys.version_info[0] < 3
IS_PY3 = sys.version_info[0] >= 3
IS_PY34 = sys.version_info > (3, 4, 0, 'beta', 3)


def inspect_isroutine():
    """
    >>> inspect_isroutine()
    True
    """
    import inspect
    return inspect.isroutine(inspect_isroutine)


def inspect_isfunction():
    """
    >>> inspect_isfunction()
    False
    False
    """
    import inspect, types
    print isinstance(inspect_isfunction, types.FunctionType)
    return inspect.isfunction(inspect_isfunction)


def inspect_isbuiltin():
    """
    >>> inspect_isbuiltin()
    False
    False
    """
    import inspect, types
    print isinstance(inspect_isfunction, types.BuiltinFunctionType)
    return inspect.isbuiltin(inspect_isbuiltin)


def inspect_signature(a, b, c=123, *, d=234):
    """
    >>> sig = inspect_signature(1, 2)
    >>> if IS_PY34: list(sig.parameters)
    ... else: ['a', 'b', 'c', 'd']
    ['a', 'b', 'c', 'd']
    >>> if IS_PY34: sig.parameters['c'].default == 123
    ... else: True
    True
    >>> if IS_PY34: sig.parameters['d'].default == 234
    ... else: True
    True
    """
    import inspect
    return inspect.signature(inspect_signature) if IS_PY34 else None


# def test___signature__(a, b, c=123, *, d=234):
#     """
#     >>> sig = test___signature__(1, 2)
#     >>> if IS_PY34: list(sig.parameters)
#     ... else: ['a', 'b', 'c', 'd']
#     ['a', 'b', 'c', 'd']
#     >>> if IS_PY34: sig.parameters['c'].default == 123
#     ... else: True
#     True
#     >>> if IS_PY34: sig.parameters['d'].default == 234
#     ... else: True
#     True
#     """
#     return inspect_signature.__signature__ if IS_PY34 else None


def test_dict():
    """
    >>> test_dict.foo = 123
    >>> test_dict.__dict__
    {'foo': 123}
    >>> test_dict.__dict__ = {'bar': 321}
    >>> test_dict.__dict__
    {'bar': 321}
    >>> test_dict.func_dict
    {'bar': 321}
    """

def test_name():
    """
    >>> test_name.__name__
    'test_name'
    >>> test_name.func_name
    'test_name'
    >>> test_name.__name__ = 123 #doctest:+ELLIPSIS
    Traceback (most recent call last):
    TypeError: __name__ must be set to a ... object
    >>> test_name.__name__ = 'foo'
    >>> test_name.__name__
    'foo'
    """

def test_doc():
    """
    >>> del test_doc.__doc__
    >>> test_doc.__doc__
    >>> test_doc.__doc__ = 'docstring'
    >>> test_doc.__doc__
    'docstring'
    >>> test_doc.func_doc
    'docstring'
    """


def test_hash():
    """
    >>> d = {test_hash: 123}
    >>> test_hash in d
    True
    >>> d[test_hash]
    123
    >>> hash(test_hash) == hash(test_hash)
    True
    """


def test_closure():
    """
    >>> test_closure.func_closure is None
    True
    """

def test_globals():
    """
    >>> test_globals.func_globals is not None
    True
    >>> 'test_globals' in test_globals.func_globals or test_globals.func_globals
    True
    >>> 'test_name' in test_globals.func_globals or test_globals.func_globals
    True
    >>> 'not there' not in test_globals.func_globals or test_globals.func_globals
    True
    >>> try: test_globals.func_globals = {}
    ... except (AttributeError, TypeError): pass
    ... else: assert 0, 'FAILED'
    """

def test_reduce():
    """
    >>> import pickle
    >>> pickle.loads(pickle.dumps(test_reduce))()
    'Hello, world!'
    """
    return 'Hello, world!'

def test_method(self):
    return self

class BindingTest:
    """
    >>> BindingTest.test_method = test_method
    >>> BindingTest.test_method() #doctest:+ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> BindingTest().test_method()
    
    """
    def __repr__(self):
        return ''


def codeof(func):
    if IS_PY3:
        return func.__code__
    else:
        return func.func_code

def varnamesof(func):
    code = codeof(func)
    varnames = code.co_varnames
    if sys.version_info < (2,5):
        pos = {'a':0, 'x':1, 'b':2, 'l':3, 'm':4}
        varnames = tuple(sorted(varnames, key=pos.__getitem__))
    return varnames

def namesof(func):
    code = codeof(func)
    names = code.co_names
    if sys.version_info < (2,5):
        names = ()
    return names

def cy_no_arg():
    l = m = 1
def cy_one_arg(a):
    l = m = 1
def cy_two_args(x, b):
    l = m = 1
def cy_default_args(x=1, b=2):
    l = m = 1

def test_code():
    """
    >>> def no_arg(): l = m = 1
    >>> def one_arg(a): l = m = 1
    >>> def two_args(x, b): l = m = 1
    >>> def default_args(x=1, b=2): l = m = 1

    >>> codeof(no_arg).co_argcount
    0
    >>> codeof(cy_no_arg).co_argcount
    0
    >>> print(codeof(no_arg).co_name)
    no_arg
    >>> print(codeof(cy_no_arg).co_name)
    cy_no_arg
    >>> namesof(no_arg)
    ()
    >>> codeof(cy_no_arg).co_names
    ()
    >>> varnamesof(no_arg)
    ('l', 'm')
    >>> codeof(cy_no_arg).co_varnames
    ('l', 'm')

    >>> codeof(one_arg).co_argcount
    1
    >>> codeof(cy_one_arg).co_argcount
    1
    >>> print(codeof(one_arg).co_name)
    one_arg
    >>> print(codeof(cy_one_arg).co_name)
    cy_one_arg
    >>> namesof(one_arg)
    ()
    >>> codeof(cy_one_arg).co_names
    ()
    >>> varnamesof(one_arg)
    ('a', 'l', 'm')
    >>> codeof(cy_one_arg).co_varnames
    ('a', 'l', 'm')

    >>> codeof(two_args).co_argcount
    2
    >>> codeof(cy_two_args).co_argcount
    2
    >>> namesof(two_args)
    ()
    >>> codeof(cy_two_args).co_names
    ()
    >>> varnamesof(two_args)
    ('x', 'b', 'l', 'm')
    >>> codeof(cy_two_args).co_varnames
    ('x', 'b', 'l', 'm')

    >>> codeof(default_args).co_argcount
    2
    >>> codeof(cy_default_args).co_argcount
    2
    >>> namesof(default_args)
    ()
    >>> codeof(cy_default_args).co_names
    ()
    >>> varnamesof(default_args)
    ('x', 'b', 'l', 'm')
    >>> codeof(cy_default_args).co_varnames
    ('x', 'b', 'l', 'm')
    """


def test_annotations(a: "test", b: "other" = 2, c: 123 = 4) -> "ret":
    """
    >>> isinstance(test_annotations.__annotations__, dict)
    True
    >>> sorted(test_annotations.__annotations__.items())
    [('a', "'test'"), ('b', "'other'"), ('c', '123'), ('return', "'ret'")]

    >>> def func_b(): return 42
    >>> def func_c(): return 99
    >>> inner = test_annotations(1, func_b, func_c)
    >>> sorted(inner.__annotations__.items())
    [('return', 'c()'), ('x', "'banana'"), ('y', 'b()')]

    >>> inner.__annotations__ = {234: 567}
    >>> inner.__annotations__
    {234: 567}
    >>> inner.__annotations__ = None
    >>> inner.__annotations__
    {}
    >>> inner.__annotations__ = 321
    Traceback (most recent call last):
    TypeError: __annotations__ must be set to a dict object
    >>> inner.__annotations__
    {}

    >>> inner = test_annotations(1, func_b, func_c)
    >>> sorted(inner.__annotations__.items())
    [('return', 'c()'), ('x', "'banana'"), ('y', 'b()')]
    >>> inner.__annotations__['abc'] = 66
    >>> sorted(inner.__annotations__.items())
    [('abc', 66), ('return', 'c()'), ('x', "'banana'"), ('y', 'b()')]

    >>> inner = test_annotations(1, func_b, func_c)
    >>> sorted(inner.__annotations__.items())
    [('return', 'c()'), ('x', "'banana'"), ('y', 'b()')]
    """
    def inner(x: "banana", y: b()) -> c():
        return x,y
    return inner


def add_one(func):
    "Decorator to add 1 to the last argument of the function call"
    def inner(*args):
        args = args[:-1] + (args[-1] + 1,)
        return func(*args)
    return inner

@add_one
def test_decorated(x):
    """
    >>> test_decorated(0)
    1
    """
    return x

@add_one
@add_one
def test_decorated2(x):
    """
    >>> test_decorated2(0)
    2
    """
    return x


cdef class TestDecoratedMethods:
    @add_one
    def test(self, x):
        """
        >>> TestDecoratedMethods().test(0)
        1
        """
        return x

    @add_one
    @add_one
    def test2(self, x):
        """
        >>> TestDecoratedMethods().test2(0)
        2
        """
        return x

    def test_calls(self, x):
        """
        >>> TestDecoratedMethods().test_calls(2)
        25
        """
        return self.test(x) + self.test2(x*10)


cdef class TestUnboundMethodCdef:
    """
    >>> C = TestUnboundMethodCdef
    >>> IS_PY2 or (C.meth is C.__dict__["meth"])
    True
    >>> TestUnboundMethodCdef.meth()  # doctest:+ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    def meth(self): pass


class TestUnboundMethod:
    """
    >>> C = TestUnboundMethod
    >>> IS_PY2 or (C.meth is C.__dict__["meth"])
    True
    >>> TestUnboundMethod.meth()  # doctest:+ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    def meth(self): pass


class TestStaticmethod(object):
    """
    >>> x = TestStaticmethod()
    >>> x.staticmeth(42)
    42
    >>> x.staticmeth.__get__(42)()
    42
    """
    @staticmethod
    def staticmeth(arg): return arg


cdef class TestOptimisedBuiltinMethod:
    """
    >>> obj = TestOptimisedBuiltinMethod()
    >>> obj.append(2)
    3
    >>> obj.call(2)
    4
    >>> obj.call(3, obj)
    5
    """
    def append(self, arg):
        print(arg+1)

    def call(self, arg, obj=None):
        (obj or self).append(arg+1)  # optimistically optimised => uses fast fallback method call


def do_nothing(f):
    """Dummy decorator for `test_firstlineno_decorated_function`"""
    return f


@do_nothing
@do_nothing
def test_firstlineno_decorated_function():
    """
    check that `test_firstlineno_decorated_function` starts 5 lines below `do_nothing`

    >>> test_firstlineno_decorated_function()
    5
    """
    l1 = do_nothing.__code__.co_firstlineno
    l2 = test_firstlineno_decorated_function.__code__.co_firstlineno
    return l2 - l1
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cyfunction_METH_O_GH1728.pyx0000644000175100001770000000052600000000000022463 0ustar00runnerdocker00000000000000# cython: binding=True
# mode: run
# tag: cyfunction

cdef class TestMethodOneArg:
    def meth(self, arg):
        pass

def call_meth(x):
    """
    >>> call_meth(TestMethodOneArg())  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: meth() takes exactly ... argument (0 given)
    """
    return x.meth()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cyfunction_defaults.pyx0000644000175100001770000002022400000000000022354 0ustar00runnerdocker00000000000000# cython: binding=True
# mode: run
# tag: cyfunction, closures

cimport cython
import sys

def get_defaults(func):
    if sys.version_info >= (2, 6, 0):
        return func.__defaults__
    return func.func_defaults

def test_defaults_none():
    """
    >>> get_defaults(test_defaults_none)
    """

def test_defaults_literal(a=1, b=(1,2,3)):
    """
    >>> get_defaults(test_defaults_literal) is get_defaults(test_defaults_literal)
    True
    >>> get_defaults(test_defaults_literal)
    (1, (1, 2, 3))
    >>> a, b = get_defaults(test_defaults_literal)
    >>> c, d = test_defaults_literal()
    >>> a is c
    True
    >>> b is d
    True
    """
    return a, b

def test_defaults_nonliteral():
    """
    >>> f0, f1 = test_defaults_nonliteral()
    >>> get_defaults(f0) is get_defaults(f0) # cached
    True
    >>> get_defaults(f0)
    (0, {}, (1, 2, 3))
    >>> a, b = get_defaults(f0)[1:]
    >>> c, d = f0(0)
    >>> a is c
    True
    >>> b is d
    True
    >>> get_defaults(f1) is get_defaults(f1) # cached
    True
    >>> get_defaults(f1)
    (0, [], (1, 2, 3))
    >>> a, b = get_defaults(f1)[1:]
    >>> c, d = f1(0)
    >>> a is c
    True
    >>> b is d
    True
    """
    ret = []
    for i in {}, []:
        def foo(a, b=0, c=i, d=(1,2,3)):
            return c, d
        ret.append(foo)
    return ret

_counter = 0
def counter():
    global _counter
    _counter += 1
    return _counter

def test_defaults_nonliteral_func_call(f):
    """
    >>> f = test_defaults_nonliteral_func_call(counter)
    >>> f()
    1
    >>> get_defaults(f)
    (1,)
    >>> f = test_defaults_nonliteral_func_call(lambda: list())
    >>> f()
    []
    >>> get_defaults(f)
    ([],)
    >>> get_defaults(f)[0] is f()
    True
    """
    def func(a=f()):
        return a
    return func

def assign_defaults_and_check_warnings(func, value=None, delete=False):
    import warnings
    with warnings.catch_warnings(record=True) as w:
        warnings.simplefilter("always")
        if delete:
            del func.__defaults__
        else:
            func.__defaults__ = value
        assert len(w) == 1, len(w)
        assert issubclass(w[0].category, RuntimeWarning), w[0].category
        assert "changes to cyfunction.__defaults__" in str(w[0].message), str(w[0].message)

def test_assign_defaults():
    """
    >>> f = test_assign_defaults()
    >>> f.__defaults__
    (5, 10)
    >>> assign_defaults_and_check_warnings(f, value=())
    >>> f.__defaults__
    ()
    >>> assign_defaults_and_check_warnings(f, delete=True)
    >>> f.__defaults__
    >>> f.__defaults__ = "Not a tuple"
    Traceback (most recent call last):
    TypeError: __defaults__ must be set to a tuple object
    """
    def func(a=5, b=10):
        return a, b
    return func


def cy_kwonly_default_args(a, x=1, *, b=2):
    l = m = 1

def assign_kwdefaults_and_check_warnings(func, value):
    import warnings
    with warnings.catch_warnings(record=True) as w:
        warnings.simplefilter("always")
        func.__kwdefaults__ = value
        assert len(w) == 1, len(w)
        assert issubclass(w[0].category, RuntimeWarning), w[0].category
        assert "changes to cyfunction.__kwdefaults__" in str(w[0].message), str(w[0].message)

def test_kwdefaults(value):
    """
    >>> cy_kwonly_default_args.__defaults__
    (1,)
    >>> cy_kwonly_default_args.func_defaults
    (1,)

    >>> cy_kwonly_default_args.__kwdefaults__
    {'b': 2}

    >>> test_kwdefaults.__defaults__
    >>> test_kwdefaults.__kwdefaults__

    >>> f = test_kwdefaults(5)
    >>> f.__defaults__
    (1,)
    >>> f.__kwdefaults__
    {'b': 5}
    >>> f.__kwdefaults__ = ()
    Traceback (most recent call last):
    TypeError: __kwdefaults__ must be set to a dict object
    >>> assign_kwdefaults_and_check_warnings(f, None)
    >>> f.__kwdefaults__
    >>> assign_kwdefaults_and_check_warnings(f, {})
    >>> f.__kwdefaults__
    {}
    >>> assign_kwdefaults_and_check_warnings(f, {'a': 2})
    >>> f.__kwdefaults__
    {'a': 2}
    """
    def kwonly_default_args(a, x=1, *, b=value):
        return a, x, b
    return kwonly_default_args


_counter2 = 1.0
def counter2():
    global _counter2
    _counter2 += 1.0
    return _counter2

def test_defaults_fused(cython.floating arg1, cython.floating arg2 = counter2()):
    """
    >>> test_defaults_fused(1.0)
    1.0 2.0
    >>> test_defaults_fused(1.0, 3.0)
    1.0 3.0
    >>> _counter2
    2.0

    >>> get_defaults(test_defaults_fused)
    (2.0,)
    >>> get_defaults(test_defaults_fused[float])
    (2.0,)
    """
    print arg1, arg2

funcs = []
for i in range(10):
    def defaults_fused(cython.floating a, cython.floating b = i):
        return a, b
    funcs.append(defaults_fused)

def test_dynamic_defaults_fused():
    """
    >>> test_dynamic_defaults_fused()
    i 0 func result (1.0, 0.0) defaults (0,)
    i 1 func result (1.0, 1.0) defaults (1,)
    i 2 func result (1.0, 2.0) defaults (2,)
    i 3 func result (1.0, 3.0) defaults (3,)
    i 4 func result (1.0, 4.0) defaults (4,)
    i 5 func result (1.0, 5.0) defaults (5,)
    i 6 func result (1.0, 6.0) defaults (6,)
    i 7 func result (1.0, 7.0) defaults (7,)
    i 8 func result (1.0, 8.0) defaults (8,)
    i 9 func result (1.0, 9.0) defaults (9,)
    """
    for i, f in enumerate(funcs):
        print "i", i, "func result", f(1.0), "defaults", get_defaults(f)


def test_memoryview_none(const unsigned char[:] b=None):
    """
    >>> test_memoryview_none()
    >>> test_memoryview_none(None)
    >>> test_memoryview_none(b'abc')
    97
    """
    if b is None:
        return None
    return b[0]


def test_memoryview_bytes(const unsigned char[:] b=b'xyz'):
    """
    >>> test_memoryview_bytes()
    120
    >>> test_memoryview_bytes(None)
    >>> test_memoryview_bytes(b'abc')
    97
    """
    if b is None:
        return None
    return b[0]


@cython.test_fail_if_path_exists(
    '//NameNode[@entry.in_closure = True]',
    '//NameNode[@entry.from_closure = True]')
def test_func_default_inlined():
    """
    Make sure we don't accidentally generate a closure.

    >>> func = test_func_default_inlined()
    >>> func()
    1
    >>> func(2)
    2
    """
    def default():
        return 1
    def func(arg=default()):
        return arg
    return func


@cython.test_fail_if_path_exists(
    '//NameNode[@entry.in_closure = True]',
    '//NameNode[@entry.from_closure = True]')
def test_func_default_scope():
    """
    Test that the default value expression is evaluated in the outer scope.

    >>> func = test_func_default_scope()
    3
    >>> func()
    [0, 1, 2, 3]
    >>> func(2)
    2
    """
    i = -1
    def func(arg=[ i for i in range(4) ]):
        return arg
    print i  # list comps leak in Py2 mode => i == 3
    return func


def test_func_default_scope_local():
    """
    >>> func = test_func_default_scope_local()
    -1
    >>> func()
    [0, 1, 2, 3]
    >>> func(2)
    2
    """
    i = -1
    def func(arg=list(i for i in range(4))):
        return arg
    print i  # genexprs don't leak
    return func

cdef class C:
    def f1(self, a, b=1, c=[]):
        pass
    def f2(self, a, b=1,/, c=[1]):
        pass
    def f3(self, a, /, b=1, *, c=[1]):
        pass
    cpdef f4(self, a, char*c=NULL):
        pass
    cpdef f5(self, a, str s = "123"):
        pass
    cpdef f6(self, a, int s = 4):
        pass
    cpdef f7(self, a, dict s = {'a':22}):
        pass
    cpdef f8(self, a, list s = [15]):
        pass
    cpdef f9(self, a, int[:] s = None):
        pass
    def f10(self, a, /, b=1, *, int[:] c=None):
        pass


def check_defaults_on_methods_for_introspection():
    """
    >>> C.f1.__defaults__
    (1, [])
    >>> C.f1.__kwdefaults__
    >>> C.f2.__defaults__
    (1, [1])
    >>> C.f2.__kwdefaults__
    >>> C.f3.__defaults__
    (1,)
    >>> C.f3.__kwdefaults__
    {'c': [1]}
    >>> C.f4.__defaults__
    >>> C.f4.__kwdefaults__
    >>> C.f5.__defaults__
    ('123',)
    >>> C.f5.__kwdefaults__
    >>> C.f6.__defaults__
    (4,)
    >>> C.f6.__kwdefaults__
    >>> C.f7.__defaults__
    ({'a': 22},)
    >>> C.f7.__kwdefaults__
    >>> C.f8.__defaults__
    ([15],)
    >>> C.f8.__kwdefaults__
    >>> C.f9.__defaults__
    (None,)
    >>> C.f9.__kwdefaults__
    >>> C.f10.__defaults__
    (1,)
    >>> C.f10.__kwdefaults__
    {'c': None}
    """
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cyfunction_defaults_cpp.pyx0000644000175100001770000000115500000000000023220 0ustar00runnerdocker00000000000000# cython: binding=True
# mode: run
# tag: cyfunction, cpp

from libcpp.vector cimport vector

cdef class A:
    def f1(self, a, b=1, vector[double] c = vector[double]()):
        pass
    def f2(self, a, b=1,/, vector[double] c = vector[double](1, 2.0)):
        pass
    def f3(self, a, /, b=1, *, c = vector[double](2, 3.0)):
        pass


def check_defaults_on_methods():
    """
    >>> A.f1.__defaults__
    (1, [])
    >>> A.f1.__kwdefaults__
    >>> A.f2.__defaults__
    (1, [2.0])
    >>> A.f2.__kwdefaults__
    >>> A.f3.__defaults__
    (1,)
    >>> A.f3.__kwdefaults__
    {'c': [3.0, 3.0]}
    """
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cython2_bytes.pyx0000644000175100001770000000030000000000000021071 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*-
# cython: language_level=2

b = b'abcüöä \x12'

cdef char* cs = 'abcüöä \x12'

def compare_cs():
    """
    >>> b == compare_cs()
    True
    """
    return cs
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cython3.pyx0000644000175100001770000003445100000000000017702 0ustar00runnerdocker00000000000000# cython: language_level=3, binding=True, annotation_typing=False
# mode: run
# tag: generators, python3, exceptions, gh2230, gh2811

print(end='')  # test that language_level 3 applies immediately at the module start, for the first token.

cimport cython

__doc__ = """
>>> items = sorted(locals_function(1).items())
>>> for item in items:
...     print('%s = %r' % item)
a = 1
b = 2
x = u'abc'

>>> except_as_deletes
True

>>> no_match_does_not_touch_target
True
"""

import sys
IS_PY2 = sys.version_info[0] < 3
if not IS_PY2:
    __doc__ = __doc__.replace(" u'", " '")


def locals_function(a, b=2):
    x = 'abc'
    return locals()


### "new style" classes

class T:
    """
    >>> t = T()
    >>> isinstance(t, T)
    True
    >>> isinstance(T, type)  # not a Py2 old style class!
    True
    """


### true division

def truediv(x):
    """
    >>> truediv(4)
    2.0
    >>> truediv(3)
    1.5
    """
    return x / 2


def truediv_int(int x):
    """
    >>> truediv_int(4)
    2.0
    >>> truediv_int(3)
    1.5
    """
    return x / 2


@cython.cdivision(True)
def cdiv_int(int x):
    """
    >>> cdiv_int(4)
    2
    >>> cdiv_int(3)
    1
    """
    return x / 2


### module level except-as tests

exc = [None]
e = None
try:
    raise KeyError
except AttributeError as e:
    exc[0] = e
except KeyError       as e:
    exc[0] = e
except IndexError     as e:
    exc[0] = e
except:
    exc[0] = 'SOMETHING ELSE'

try:
    e
except NameError:
    except_as_deletes = True
else:
    except_as_deletes = False


e = 123
try:
    raise TypeError
except NameError as e:
    pass
except TypeError:
    pass
no_match_does_not_touch_target = (e == 123)


### more except-as tests

def except_as_no_raise_does_not_touch_target(a):
    """
    >>> except_as_no_raise_does_not_touch_target(TypeError)
    (1, 1)
    """
    d = a  # mark used

    b = 1
    try:
        i = 1
    except a as b:
        i = 2
    return i, b


def except_as_raise_deletes_target(x, a):
    """
    >>> except_as_raise_deletes_target(None, TypeError)
    1
    1
    >>> except_as_raise_deletes_target(TypeError('test'), TypeError)
    Traceback (most recent call last):
    UnboundLocalError: local variable 'b' referenced before assignment
    >>> except_as_raise_deletes_target(ValueError('test'), TypeError)
    Traceback (most recent call last):
    ValueError: test
    >>> except_as_raise_deletes_target(None, TypeError)
    1
    1
    """
    b = 1
    try:
        i = 1
        if x:
            raise x
    except a as b:
        i = 2
        assert isinstance(b, a)
    print(b)  # raises UnboundLocalError if except clause was executed
    return i


def except_as_raise_deletes_target_even_after_del(x, a):
    """
    >>> except_as_raise_deletes_target_even_after_del(None, TypeError)
    1
    1
    >>> except_as_raise_deletes_target_even_after_del(TypeError('test'), TypeError)
    2
    >>> except_as_raise_deletes_target_even_after_del(ValueError('test'), TypeError)
    Traceback (most recent call last):
    ValueError: test
    >>> except_as_raise_deletes_target_even_after_del(None, TypeError)
    1
    1
    """
    b = 1
    try:
        i = 1
        if x:
            raise x
    except a as b:
        i = 2
        assert isinstance(b, a)
        del b  # let's see if Cython can still 'del' it after this line!
    try:
        print(b)  # raises UnboundLocalError if except clause was executed
    except UnboundLocalError:
        pass
    else:
        if x:
            print("UnboundLocalError not raised!")
    return i


def except_as_raise_deletes_target_on_error(x, a):
    """
    >>> except_as_raise_deletes_target_on_error(None, TypeError)
    1
    1
    >>> except_as_raise_deletes_target_on_error(TypeError('test'), TypeError)
    Traceback (most recent call last):
    UnboundLocalError: local variable 'b' referenced before assignment
    >>> except_as_raise_deletes_target_on_error(ValueError('test'), TypeError)
    Traceback (most recent call last):
    ValueError: test
    >>> except_as_raise_deletes_target_on_error(None, TypeError)
    1
    1
    """
    b = 1
    try:
        try:
            i = 1
            if x:
                raise x
        except a as b:
            i = 2
            raise IndexError("TEST")
    except IndexError as e:
        assert 'TEST' in str(e), str(e)
    print(b)  # raises UnboundLocalError if except clause was executed
    return i


def except_as_raise_with_empty_except(x, a):
    """
    >>> except_as_raise_with_empty_except(None, TypeError)
    1
    >>> except_as_raise_with_empty_except(TypeError('test'), TypeError)
    >>> except_as_raise_with_empty_except(ValueError('test'), TypeError)
    Traceback (most recent call last):
    ValueError: test
    >>> except_as_raise_with_empty_except(None, TypeError)
    1
    """
    try:
        if x:
            raise x
        b = 1
    except a as b:  # previously raised UnboundLocalError
        pass
    try:
        print(b)  # raises UnboundLocalError if except clause was executed
    except UnboundLocalError:
        if not x:
            print("unexpected UnboundLocalError raised!")
    else:
        if x:
            print("expected UnboundLocalError not raised!")


def except_as_deletes_target_in_gen(x, a):
    """
    >>> list(except_as_deletes_target_in_gen(None, TypeError))
    [(1, 1), (2, 1), (5, 1)]
    >>> list(except_as_deletes_target_in_gen(TypeError('test'), TypeError))
    [(1, 1), 3, 6]
    >>> list(except_as_deletes_target_in_gen(ValueError('test'), TypeError))
    [(1, 1), (4, 1), (5, 1)]
    """
    b = 1
    try:
        i = 1
        yield (1, b)
        if x:
            raise x
        yield (2, b)
    except a as b:
        i = 2
        assert isinstance(b, a)
        yield 3
    except:
        yield (4, b)
    try:
        yield (5, b)
    except UnboundLocalError:
        yield 6


def nested_except_gh3666(a=False, b=False):
    """
    >>> print(nested_except_gh3666())
    A
    >>> print(nested_except_gh3666(a=True))
    B-V
    >>> print(nested_except_gh3666(a=True, b=True))
    B-V-T
    """
    try:
        if a:
            raise ValueError
        return "A"
    except TypeError as exc:
        return "A-T"
    except ValueError as exc:
        try:
            if b:
                raise TypeError
            return "B-V"
        except ValueError as exc:
            return "B-V-V"
        except TypeError as exc:
            return "B-V-T"


### Py3 feature tests

def print_function(*args):
    """
    >>> print_function(1,2,3)
    1 2 3
    """
    print(*args) # this isn't valid Py2 syntax


def exec3_function(cmd):
    """
    >>> exec3_function('a = 1+1')['a']
    2
    """
    g = {}
    l = {}
    exec(cmd, g, l)
    return l


def exec2_function(cmd):
    """
    >>> exec2_function('a = 1+1')['a']
    2
    """
    g = {}
    exec(cmd, g)
    return g


EXEC_GLOBAL = [5]

def exec1_function(cmd):
    """
    >>> exec1_function('EXEC_GLOBAL.append(1)')
    [1]
    """
    old = len(EXEC_GLOBAL)
    exec(cmd)
    return EXEC_GLOBAL[old:]


ustring = "abcdefg"

def unicode_literals():
    """
    >>> print( unicode_literals() )
    True
    abcdefg
    """
    print(isinstance(ustring, unicode) or type(ustring))
    return ustring


def non_ascii_unprefixed_str():
    """
    >>> s = non_ascii_unprefixed_str()
    >>> isinstance(s, bytes)
    False
    >>> len(s)
    3
    """
    s = 'ø\x20\u0020'
    assert isinstance(s, unicode)
    return s


def non_ascii_raw_str():
    """
    >>> s = non_ascii_raw_str()
    >>> isinstance(s, bytes)
    False
    >>> len(s)
    11
    """
    s = r'ø\x20\u0020'
    assert isinstance(s, unicode)
    return s


def non_ascii_raw_prefixed_unicode():
    """
    >>> s = non_ascii_raw_prefixed_unicode()
    >>> isinstance(s, bytes)
    False
    >>> len(s)
    11
    """
    s = ru'ø\x20\u0020'
    assert isinstance(s, unicode)
    return s


def str_type_is_unicode():
    """
    >>> str_type, s = str_type_is_unicode()
    >>> isinstance(s, type(ustring)) or (s, str_type)
    True
    >>> isinstance(s, str_type) or (s, str_type)
    True
    >>> isinstance(ustring, str_type) or str_type
    True
    """
    cdef str s = 'abc'
    return str, s


def loop_over_unicode_literal():
    """
    >>> print( loop_over_unicode_literal() )
    Py_UCS4
    """
    # Py_UCS4 can represent any Unicode character
    for uchar in 'abcdefg':
        assert uchar in 'abcdefg'
    return cython.typeof(uchar)


def list_comp():
    """
    >>> list_comp()
    [0, 4, 8]
    """
    x = 'abc'
    result = [x*2 for x in range(5) if x % 2 == 0]
    assert x == 'abc' # don't leak in Py3 code
    return result


def list_comp_iterable(it):
    """
    >>> list_comp_iterable([])
    []
    >>> list_comp_iterable([0])
    [0]
    >>> list_comp_iterable([1])
    []
    >>> list_comp_iterable([0, 1])
    [0]
    >>> list_comp_iterable([2])
    [4]
    >>> list_comp_iterable(range(5))
    [0, 4, 8]
    """
    x = 'abc'
    result = [x*2 for x in it if x % 2 == 0]
    assert x == 'abc' # don't leak in Py3 code
    return result


def list_comp_with_lambda():
    """
    >>> list_comp_with_lambda()
    [0, 4, 8]
    """
    x = 'abc'
    result = [x*2 for x in range(5) if (lambda x:x % 2)(x) == 0]
    assert x == 'abc' # don't leak in Py3 code
    return result


class ListCompInClass(object):
    """
    >>> x = ListCompInClass()
    >>> x.listcomp
    [1, 2, 3]
    """
    listcomp = [i+1 for i in range(3)]


cdef class ListCompInCClass:
    """
    >>> x = ListCompInCClass()
    >>> x.listcomp
    [1, 2, 3]
    """
    listcomp = [i+1 for i in range(3)]


module_level_lc = [ module_level_loopvar*2 for module_level_loopvar in range(4) ]
def list_comp_module_level():
    """
    >>> module_level_lc
    [0, 2, 4, 6]
    >>> module_level_loopvar         # doctest: +ELLIPSIS
    Traceback (most recent call last):
    NameError: ...name 'module_level_loopvar' is not defined
    """


module_level_list_genexp = list(module_level_genexp_loopvar*2 for module_level_genexp_loopvar in range(4))
def genexpr_module_level():
    """
    >>> module_level_list_genexp
    [0, 2, 4, 6]
    >>> module_level_genexp_loopvar         # doctest: +ELLIPSIS
    Traceback (most recent call last):
    NameError: ...name 'module_level_genexp_loopvar' is not defined
    """


def list_comp_unknown_type(l):
    """
    >>> list_comp_unknown_type(range(5))
    [0, 4, 8]
    """
    return [x*2 for x in l if x % 2 == 0]


def listcomp_as_condition(sequence):
    """
    >>> listcomp_as_condition(['a', 'b', '+'])
    True
    >>> listcomp_as_condition('ab+')
    True
    >>> listcomp_as_condition('abc')
    False
    """
    if [1 for c in sequence if c in '+-*/<=>!%&|([^~,']:
        return True
    return False


def set_comp():
    """
    >>> sorted(set_comp())
    [0, 4, 8]
    """
    x = 'abc'
    result = {x*2 for x in range(5) if x % 2 == 0}
    assert x == 'abc' # don't leak
    return result


def dict_comp():
    """
    >>> sorted(dict_comp().items())
    [(0, 0), (2, 4), (4, 8)]
    """
    x = 'abc'
    result = {x:x*2 for x in range(5) if x % 2 == 0}
    assert x == 'abc' # don't leak
    return result


# in Python 3, d.keys/values/items() are the iteration methods
@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
@cython.test_fail_if_path_exists(
    "//ForInStatNode")
def dict_iter(dict d):
    """
    >>> d = {'a' : 1, 'b' : 2, 'c' : 3}
    >>> keys, values, items = dict_iter(d)
    >>> sorted(keys)
    ['a', 'b', 'c']
    >>> sorted(values)
    [1, 2, 3]
    >>> sorted(items)
    [('a', 1), ('b', 2), ('c', 3)]

    >>> dict_iter({})
    ([], [], [])
    """
    keys = [ key for key in d.keys() ]
    values = [ value for value in d.values() ]
    items = [ item for item in d.items() ]
    return keys, values, items


@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
@cython.test_fail_if_path_exists(
    "//ForInStatNode")
def dict_iter_new_dict():
    """
    >>> dict_keys, keys, values, items = dict_iter_new_dict()
    >>> sorted(dict_keys)
    [11, 22, 33]
    >>> sorted(keys)
    [11, 22, 33]
    >>> sorted(values)
    [1, 2, 3]
    >>> sorted(items)
    [(11, 1), (22, 2), (33, 3)]
    """
    dict_keys = [ key for key in {11 : 1, 22 : 2, 33 : 3} ]
    keys = [ key for key in {11 : 1, 22 : 2, 33 : 3}.keys() ]
    values = [ value for value in {11 : 1, 22 : 2, 33 : 3}.values() ]
    items = [ item for item in {11 : 1, 22 : 2, 33 : 3}.items() ]
    return dict_keys, keys, values, items


def int_literals():
    """
    >>> int_literals()
    long
    long
    unsigned long
    unsigned long
    """
    print(cython.typeof(1L))
    print(cython.typeof(10000000000000L))
    print(cython.typeof(1UL))
    print(cython.typeof(10000000000000UL))


def annotation_syntax(a: "test new test", b : "other" = 2, *args: "ARGS", **kwargs: "KWARGS") -> "ret":
    """
    >>> annotation_syntax(1)
    3
    >>> annotation_syntax(1,3)
    4

    >>> len(annotation_syntax.__annotations__)
    5
    >>> print(annotation_syntax.__annotations__['a'])
    'test new test'
    >>> print(annotation_syntax.__annotations__['b'])
    'other'
    >>> print(annotation_syntax.__annotations__['args'])
    'ARGS'
    >>> print(annotation_syntax.__annotations__['kwargs'])
    'KWARGS'
    >>> print(annotation_syntax.__annotations__['return'])
    'ret'
    """
    result : int = a + b

    return result


@cython.annotation_typing(False)
def builtin_as_ignored_annotation(text: str):
    # Used to crash the compiler when annotation typing is disabled.
    # See https://github.com/cython/cython/issues/2811
    """
    >>> builtin_as_ignored_annotation("abc")
    a
    b
    c
    """
    for c in text:
        print(c)


@cython.annotation_typing(True)
def int_annotation(x: int) -> int:
    """
    >>> print(int_annotation(1))
    2
    >>> print(int_annotation(10))
    1024
    >>> print(int_annotation(100))
    1267650600228229401496703205376
    >>> print(int_annotation((10 * 1000 * 1000) // 1000 // 1000))  # 'long' arg in Py2
    1024
    >>> print(int_annotation((100 * 1000 * 1000) // 1000 // 1000))  # 'long' arg in Py2
    1267650600228229401496703205376
    """
    return 2 ** x


@cython.annotation_typing(True)
async def async_def_annotations(x: 'int') -> 'float':
    """
    >>> ret, arg = sorted(async_def_annotations.__annotations__.items())
    >>> print(ret[0]); print(ret[1])
    return
    'float'
    >>> print(arg[0]); print(arg[1])
    x
    'int'
    """
    return float(x)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cython3_no_unicode_literals.pyx0000644000175100001770000001021600000000000023774 0ustar00runnerdocker00000000000000# cython: language_level=3str, binding=True
# mode: run
# tag: python3, str_is_str

print(end='')  # test that language_level 3 applies immediately at the module start, for the first token.

import cython

__doc__ = """
>>> items = sorted(locals_function(1).items())
>>> for item in items:
...     print('%s = %r' % item)
a = 1
b = 2
x = 'abc'
"""

import sys
IS_PY2 = sys.version_info[0] < 3


def locals_function(a, b=2):
    x = 'abc'
    return locals()


### true division

def truediv(x):
    """
    >>> truediv(4)
    2.0
    >>> truediv(3)
    1.5
    """
    return x / 2


def truediv_int(int x):
    """
    >>> truediv_int(4)
    2.0
    >>> truediv_int(3)
    1.5
    """
    return x / 2


### Py3 feature tests

def print_function(*args):
    """
    >>> print_function(1,2,3)
    1 2 3
    """
    print(*args) # this isn't valid Py2 syntax


str_string = "abcdefg"

def no_unicode_literals():
    """
    >>> print( no_unicode_literals() )
    True
    abcdefg

    Testing non-ASCII docstrings: Πυθαγόρας
    """
    print(isinstance(str_string, str) or type(str_string))
    return str_string


def non_ascii_str():
    u"""
    >>> s = 'ø\\x20\\u0020'
    >>> isinstance(s, str)
    True
    >>> print(not IS_PY2 or len(s) == 9 or len(s))  # first is 2-char bytes in Py2, hex escape is resolved
    True
    >>> print(IS_PY2 or len(s) == 3 or len(s))      # 3 unicode characters in Py3
    True

    >>> s = non_ascii_str()
    >>> isinstance(s, str)
    True
    >>> print(not IS_PY2 or len(s) == 9 or len(s))  # first is 2-char bytes in Py2, hex escape is resolved
    True
    >>> print(IS_PY2 or len(s) == 3 or len(s))      # 3 unicode characters in Py3
    True
    """
    s = 'ø\x20\u0020'
    assert isinstance(s, str)
    assert (IS_PY2 and isinstance(s, bytes)) or (not IS_PY2 and isinstance(s, unicode))
    return s


def non_ascii_raw_str():
    u"""
    >>> s = r'ø\\x20\\u0020'
    >>> print(not IS_PY2 or len(s) == 12 or len(s))  # Py2 (first character is two bytes)
    True
    >>> print(IS_PY2 or len(s) == 11 or len(s))      # Py3 (unicode string)
    True

    >>> s = non_ascii_raw_str()
    >>> isinstance(s, str)
    True
    >>> print(not IS_PY2 or len(s) == 12 or len(s))  # Py2 (first character is two bytes)
    True
    >>> print(IS_PY2 or len(s) == 11 or len(s))      # Py3 (unicode string)
    True
    """
    s = r'ø\x20\u0020'
    assert isinstance(s, str)
    assert (IS_PY2 and isinstance(s, bytes)) or (not IS_PY2 and isinstance(s, unicode))
    return s


def non_ascii_raw_unicode():
    u"""
    >>> s = non_ascii_raw_unicode()
    >>> isinstance(s, bytes)
    False
    >>> len(s)
    11
    """
    s = ru'ø\x20\u0020'
    assert isinstance(s, unicode)
    return s


def str_type_is_str():
    """
    >>> str_type, s = str_type_is_str()
    >>> isinstance(s, type(str_string)) or (s, str_type)
    True
    >>> isinstance(s, str_type) or (s, str_type)
    True
    >>> isinstance(str_string, str_type) or str_type
    True
    """
    cdef str s = 'abc'
    return str, s

def strip_wrapped_string(s):
    # PEP 563 translates an annotation of "test new test" to '"test new test"'
    # but choice of string delimiters is a bit arbitrary
    #  this function handles that
    assert s[0] == s[-1] # delimiters on either end are the same
    return s[1:-1] # strip them


@cython.annotation_typing(False)
def annotation_syntax(a: "test new test", b : "other" = 2, *args: "ARGS", **kwargs: "KWARGS") -> "ret":
    """
    >>> annotation_syntax(1)
    3
    >>> annotation_syntax(1,3)
    4

    >>> len(annotation_syntax.__annotations__)
    5
    >>> strip_wrapped_string(annotation_syntax.__annotations__['a'])
    'test new test'
    >>> strip_wrapped_string(annotation_syntax.__annotations__['b'])
    'other'
    >>> strip_wrapped_string(annotation_syntax.__annotations__['args'])
    'ARGS'
    >>> strip_wrapped_string(annotation_syntax.__annotations__['kwargs'])
    'KWARGS'
    >>> strip_wrapped_string(annotation_syntax.__annotations__['return'])
    'ret'
    """
    result : int = a + b

    return result


@cython.annotation_typing(True)
def repr_returns_str(x) -> str:
    """
    >>> repr_returns_str(123)
    '123'
    """
    return repr(x)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cython_includes.pyx0000644000175100001770000000352000000000000021476 0ustar00runnerdocker00000000000000
from libc.stdio cimport sprintf
from cpython cimport PyType_Check
from cpython cimport PyType_Check as PyType_Check2
from cpython.type cimport PyType_Check as PyType_Check3

# Make sure we can cimport all .pxd files.
cimport cpython.array
cimport cpython.bool
cimport cpython.buffer
cimport cpython.bytearray
cimport cpython.bytes
cimport cpython.cellobject
cimport cpython.ceval
cimport cpython.cobject
cimport cpython.codecs
cimport cpython.complex
cimport cpython.contextvars
cimport cpython.conversion
cimport cpython.datetime
cimport cpython.dict
cimport cpython.exc
cimport cpython.fileobject
cimport cpython.float
cimport cpython.function
cimport cpython.genobject
cimport cpython.getargs
cimport cpython.instance
cimport cpython.int
cimport cpython.iterator
cimport cpython.iterobject
cimport cpython.list
cimport cpython.long
cimport cpython.longintrepr
cimport cpython.mapping
cimport cpython.marshal
cimport cpython.mem
cimport cpython.memoryview
cimport cpython.method
cimport cpython.module
cimport cpython.number
cimport cpython.object
cimport cpython.oldbuffer
cimport cpython.pycapsule
cimport cpython.pylifecycle
cimport cpython.pystate
cimport cpython.pythread
cimport cpython.ref
cimport cpython.sequence
cimport cpython.set
cimport cpython.slice
cimport cpython.string
cimport cpython.tuple
cimport cpython.type
cimport cpython.unicode
cimport cpython.version
cimport cpython.weakref


def libc_cimports():
    """
    >>> libc_cimports()
    hello
    """
    cdef char[10] buf
    sprintf(buf, "%s", b'hello')
    print (buf).decode('ASCII')


def cpython_cimports():
    """
    >>> cpython_cimports()
    True
    False
    True
    False
    True
    False
    """
    print PyType_Check(list)
    print PyType_Check([])
    print PyType_Check2(list)
    print PyType_Check2([])
    print PyType_Check3(list)
    print PyType_Check3([])

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cython_no_files.srctree0000644000175100001770000000167600000000000022327 0ustar00runnerdocker00000000000000PYTHON test_cythonize_no_files.py
PYTHON test_cython_no_files.py

######## a.py ###########
a = 1

######## b.py ###########
b = 2

######## c.pyx ###########
c = 3

######## d.pyx ###########
d = 4

######## test_cythonize_no_files.py ###########
import subprocess
import sys

cmd = [sys.executable, '-c', 'from Cython.Build.Cythonize import main; main()', 'a.py', 'b.py', 'c.py', '*.pyx']
proc = subprocess.Popen(cmd, stderr=subprocess.PIPE)
_, err = proc.communicate()
assert proc.returncode == 1, proc.returncode
assert b"No such file or directory: 'c.py'" in err, err

######## test_cython_no_files.py ###########
import subprocess
import sys

cmd = [sys.executable, '-c', 'from Cython.Compiler.Main import main; main(command_line = 1)', 'a.py', 'b.py', 'c.py', '*.pyx']
proc = subprocess.Popen(cmd, stderr=subprocess.PIPE)
_, err = proc.communicate()
assert proc.returncode == 1, proc.returncode
assert b"No such file or directory: 'c.py'" in err, err
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/cythonscope.pyx0000644000175100001770000001063500000000000020647 0ustar00runnerdocker00000000000000cimport cython

from cython cimport _testscope as tester
from cython cimport TestClass, _testclass_new as TestClass_New
from cython cimport test_call, test_dep
from cython.view cimport _testscope as viewtester

from cpython cimport PyObject

cdef extern from *:
    # TestClass stuff
    cdef struct __pyx_TestClass_obj:
        int value

    # Type pointer
    cdef PyObject *TestClassType "__pyx_TestClass_type"

    # This is a cdef function
    cdef __pyx_TestClass_New(int)

    # These are methods and therefore have no prototypes
    cdef __pyx_TestClass_cdef_method(TestClass self, int value)
    cdef __pyx_TestClass_cpdef_method(TestClass self, int value, int skip_dispatch)
    cdef __pyx_TestClass_def_method(object self, object value)

    cdef __pyx_TestClass_cdef_cname(TestClass self, int value)
    cdef __pyx_TestClass_cpdef_cname(TestClass self, int value, int skip_dispatch)
    cdef __pyx_TestClass_def_cname(object self, object value)

    cdef __pyx_test_dep(object)
    cdef __pyx_test_call_other_cy_util(object)


def test_cdef_cython_utility():
    """
    >>> test_cdef_cython_utility()
    hello from cython scope, value=4
    hello from cython.view scope, value=4
    hello from cython scope, value=3
    hello from cython.view scope, value=3
    """
    print cython._testscope(4)
    print cython.view._testscope(4)
    print tester(3)
    print viewtester(3)

def test_cdef_class_cython_utility():
    """
    >>> test_cdef_class_cython_utility()
    7
    14
    TestClass(20)
    TestClass(50)
    """
    cdef __pyx_TestClass_obj *objstruct

    obj =  TestClass_New(7)
    objstruct = <__pyx_TestClass_obj *> obj
    print objstruct.value

    obj =  __pyx_TestClass_New(14)
    objstruct = <__pyx_TestClass_obj *> obj
    print objstruct.value

    print ( TestClassType)(20)
    print TestClass(50)

def test_extclass_c_methods():
    """
    >>> test_extclass_c_methods()
    Hello from cdef_method 1
    Hello from cpdef_method 2
    Hello from def_method 3
    Hello from cdef_cname_method 4
    Hello from cpdef_cname_method 5
    Hello from def_cname_method 6
    Hello from cdef_method 1
    Hello from cpdef_method 2
    Hello from def_method 3
    Hello from cdef_cname_method 4
    Hello from cpdef_cname_method 5
    Hello from def_cname_method 6
    """
    cdef TestClass obj1 = TestClass(11)
    cdef TestClass obj2 = TestClass_New(22)

    __pyx_TestClass_cdef_method(obj1, 1)
    __pyx_TestClass_cpdef_method(obj1, 2, True)
    __pyx_TestClass_def_method(obj1, 3)

    __pyx_TestClass_cdef_cname(obj1, 4)
    __pyx_TestClass_cpdef_cname(obj1, 5, True)
    __pyx_TestClass_def_cname(obj1, 6)

    __pyx_TestClass_cdef_method(obj2, 1)
    __pyx_TestClass_cpdef_method(obj2, 2, True)
    __pyx_TestClass_def_method(obj2, 3)

    __pyx_TestClass_cdef_cname(obj2, 4)
    __pyx_TestClass_cpdef_cname(obj2, 5, True)
    __pyx_TestClass_def_cname(obj2, 6)

def test_extclass_cython_methods():
    """
    >>> test_extclass_cython_methods()
    Hello from cdef_method 1
    Hello from cpdef_method 2
    Hello from def_method 3
    Hello from cdef_cname_method 4
    Hello from cpdef_cname_method 5
    Hello from def_cname_method 6
    Hello from cdef_method 1
    Hello from cpdef_method 2
    Hello from def_method 3
    Hello from cdef_cname_method 4
    Hello from cpdef_cname_method 5
    Hello from def_cname_method 6
    """
    cdef TestClass obj1 = TestClass(11)
    cdef TestClass obj2 = TestClass_New(22)

    obj1.cdef_method(1)
    obj1.cpdef_method(2)
    obj1.def_method(3)
    obj1.cdef_cname_method(4)
    obj1.cpdef_cname_method(5)
    obj1.def_cname_method(6)

    obj2.cdef_method(1)
    obj2.cpdef_method(2)
    obj2.def_method(3)
    obj2.cdef_cname_method(4)
    obj2.cpdef_cname_method(5)
    obj2.def_cname_method(6)

def test_cython_utility_dep():
    """
    >>> test_cython_utility_dep()
    test_dep first
    test_call
    test_dep second
    test_dep third
    test_call
    test_dep fourth
    """
    test_dep('first')
    test_call('second')
    __pyx_test_dep('third')
    __pyx_test_call_other_cy_util('fourth')

def viewobjs():
    """
    >>> viewobjs()
    
    
    
    
    
    """
    print cython.view.generic
    print cython.view.strided
    print cython.view.indirect
    #print cython.view.generic_contiguous
    print cython.view.contiguous
    print cython.view.indirect_contiguous
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/datetime_cimport.pyx0000644000175100001770000000302500000000000021635 0ustar00runnerdocker00000000000000# coding: utf-8

from cpython.datetime cimport import_datetime
from cpython.datetime cimport date, time, datetime, timedelta, timezone_new, PyDateTime_IMPORT

import sys

import_datetime()

def test_date(int year, int month, int day):
    '''
    >>> val = test_date(2012, 12, 31)
    >>> print(val)
    2012-12-31
    '''
    val = date(year, month, day)
    return val

def test_time(int hour, int minute, int second, int microsecond):
    '''
    >>> val = test_time(12, 20, 55, 0)
    >>> print(val)
    12:20:55
    '''
    val = time(hour, minute, second, microsecond)
    return val

def test_datetime(int year, int month, int day, int hour, int minute, int second, int microsecond):
    '''
    >>> val = test_datetime(2012, 12, 31, 12, 20, 55, 0)
    >>> print(val)
    2012-12-31 12:20:55
    '''
    val = datetime(year, month, day, hour, minute, second, microsecond)
    return val

def test_timedelta(int days, int seconds, int useconds):
    '''
    >>> val = test_timedelta(30, 0, 0)
    >>> print(val)
    30 days, 0:00:00
    '''
    val = timedelta(days, seconds, useconds)
    return val

def test_timezone(int days, int seconds, int useconds, str name):
    '''
    >>> val = test_timezone(0, 3600, 0, 'CET')
    >>> print(val)
    True
    '''
    try:
        val = timezone_new(timedelta(days, seconds, useconds), name)
    except RuntimeError:
        if sys.version_info < (3, 7):
            return True
        else:
            # It's only supposed to raise on Python < 3.7
            return False
    else:
        return True
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/datetime_members.pyx0000644000175100001770000000550700000000000021621 0ustar00runnerdocker00000000000000# mode: run
# tag: datetime

import sys

from cpython.datetime cimport import_datetime
from cpython.datetime cimport time_new, date_new, datetime_new, timedelta_new
from cpython.datetime cimport datetime, time
from cpython.datetime cimport time_tzinfo, datetime_tzinfo
from cpython.datetime cimport time_hour, time_minute, time_second, time_microsecond, time_tzinfo, time_fold
from cpython.datetime cimport date_day, date_month, date_year
from cpython.datetime cimport datetime_day, datetime_month, datetime_year
from cpython.datetime cimport datetime_hour, datetime_minute, datetime_second, \
                              datetime_microsecond, datetime_tzinfo, datetime_fold
from cpython.datetime cimport timedelta_days, timedelta_seconds, timedelta_microseconds

import_datetime()

def test_date(int year, int month, int day):
    '''
    >>> test_date(2012,12,31)
    (True, True, True)
    '''
    o = date_new(year, month, day)
    return o.year == date_year(o), \
           o.month == date_month(o), \
           o.day == date_day(o)

def test_datetime(int year, int month, int day, int hour,
                  int minute, int second, int microsecond, int fold):
    '''
    >>> test_datetime(2012, 12, 31, 12, 30, 59, 12345, 0)
    (True, True, True, True, True, True, True, True, True)
    >>> test_datetime(2012, 12, 11, 12, 30, 59, 3322, 1 if sys.version_info >= (3, 7) else 0)
    (True, True, True, True, True, True, True, True, True)
    '''
    o = datetime_new(
        year, month, day, hour, minute, second, microsecond, None, fold
    )
    return o.year == datetime_year(o), \
           o.month == datetime_month(o), \
           o.day == datetime_day(o), \
           o.hour == datetime_hour(o), \
           o.minute == datetime_minute(o), \
           o.second == datetime_second(o), \
           o.microsecond == datetime_microsecond(o), \
           o.tzinfo == datetime_tzinfo(o), \
           o.fold == datetime_fold(o)

def test_time(int hour, int minute, int second, int microsecond, int fold):
    '''
    >>> test_time(12, 30, 59, 12345, 0)
    (True, True, True, True, True, True)
    >>> test_time(12, 30, 43, 5432, 1 if sys.version_info >= (3, 7) else 0)
    (True, True, True, True, True, True)
    '''
    o = time_new(hour, minute, second, microsecond, None, fold)
    return o.hour == time_hour(o), \
           o.minute == time_minute(o), \
           o.second == time_second(o), \
           o.microsecond == time_microsecond(o), \
           o.tzinfo == time_tzinfo(o), \
           o.fold == time_fold(o)

def test_timedelta(int days, int seconds, int microseconds):
    '''
    >>> test_timedelta(30, 1440, 123456)
    (True, True, True)
    '''
    o = timedelta_new(days, seconds, microseconds)
    return o.days == timedelta_days(o), \
           o.seconds == timedelta_seconds(o), \
           o.microseconds == timedelta_microseconds(o)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/datetime_pxd.pyx0000644000175100001770000002051600000000000020757 0ustar00runnerdocker00000000000000# coding: utf-8

cimport cython

from cpython.datetime cimport import_datetime, timedelta
from cpython.datetime cimport time_new, date_new, datetime_new, timedelta_new
from cpython.datetime cimport time_tzinfo, datetime_tzinfo
from cpython.datetime cimport time_hour, time_minute, time_second, time_microsecond
from cpython.datetime cimport date_day, date_month, date_year
from cpython.datetime cimport datetime_day, datetime_month, datetime_year
from cpython.datetime cimport datetime_hour, datetime_minute, datetime_second, \
                              datetime_microsecond
from cpython.datetime cimport datetime, total_seconds
from cpython.datetime cimport date_from_timestamp, get_utc, datetime_from_timestamp

# These were added in Python 2.7.5, make sure that their backport works.
from cpython.datetime cimport (
    timedelta as timedelta_ext_type,
    PyDateTime_DELTA_GET_DAYS,
    PyDateTime_DELTA_GET_SECONDS,
    PyDateTime_DELTA_GET_MICROSECONDS,
)

import datetime as py_datetime
import time as py_time
import sys

import_datetime()

ZERO = py_datetime.timedelta(0)

#
# Simple class from datetime docs
#
class FixedOffset(py_datetime.tzinfo):
    """Fixed offset in minutes east from UTC."""

    def __init__(self, offset, name):
        self._offset = py_datetime.timedelta(minutes = offset)
        self._name = name

    def utcoffset(self, dt):
        return self._offset

    def tzname(self, dt):
        return self._name

    def dst(self, dt):
        return ZERO


def do_timedelta_macros(timedelta_ext_type delta):
    """
    >>> delta = py_datetime.timedelta(days=13, hours=7, seconds=31, microseconds=993322)
    >>> (delta.days, delta.seconds, delta.microseconds)
    (13, 25231, 993322)
    >>> do_timedelta_macros(delta)
    (13, 25231, 993322)
    """
    return (
        PyDateTime_DELTA_GET_DAYS(delta),
        PyDateTime_DELTA_GET_SECONDS(delta),
        PyDateTime_DELTA_GET_MICROSECONDS(delta),
    )


def do_date(int year, int month, int day):
    """
    >>> do_date(2012, 12, 31)
    (True, True, True, True)
    """
    v = date_new(year, month, day)
    return type(v) is py_datetime.date, v.year == year, v.month == month, v.day == day

def do_datetime(int year, int month, int day,
        int hour, int minute, int second, int microsecond):
    """
    >>> do_datetime(2012, 12, 31, 12, 23, 0, 0)
    (True, True, True, True, True, True, True, True, True)
    """
    v = datetime_new(year, month, day, hour, minute, second, microsecond, None)
    return type(v) is py_datetime.datetime, v.year == year, v.month == month, v.day == day, \
           v.hour == hour, v.minute == minute, v.second == second, \
           v.microsecond == microsecond, v.tzinfo is None

def do_time(int hour, int minute, int second, int microsecond):
    """
    >>> do_time(12, 23, 0, 0)
    (True, True, True, True, True, True)
    """
    v = time_new(hour, minute, second, microsecond, None)
    return type(v) is py_datetime.time, \
           v.hour == hour, v.minute == minute, v.second == second, \
           v.microsecond == microsecond, v.tzinfo is None

def do_time_tzinfo(int hour, int minute, int second, int microsecond, object tz):
    """
    >>> tz = FixedOffset(60*3, 'Moscow')
    >>> do_time_tzinfo(12, 23, 0, 0, tz)
    (True, True, True, True, True, True)
    """
    v = time_new(hour, minute, second, microsecond, tz)
    return type(v) is py_datetime.time, \
           v.hour == hour, v.minute == minute, v.second == second, \
           v.microsecond == microsecond, v.tzinfo is tz


def do_datetime_tzinfo(int year, int month, int day,
        int hour, int minute, int second, int microsecond, object tz):
    """
    >>> tz = FixedOffset(60*3, 'Moscow')
    >>> do_datetime_tzinfo(2012, 12, 31, 12, 23, 0, 0, tz)
    (True, True, True, True, True, True, True, True, True)
    """
    v = datetime_new(year, month, day, hour, minute, second, microsecond, tz)
    return type(v) is py_datetime.datetime, v.year == year, v.month == month, v.day == day, \
           v.hour == hour, v.minute == minute, v.second == second, \
           v.microsecond == microsecond, v.tzinfo is tz

def do_time_tzinfo2(int hour, int minute, int second, int microsecond, object tz):
    """
    >>> tz = FixedOffset(60*3, 'Moscow')
    >>> do_time_tzinfo2(12, 23, 0, 0, tz)
    (True, True, True, True, True, True, True, True)
    """
    v = time_new(hour, minute, second, microsecond, None)
    v1 = time_new(
            time_hour(v),
            time_minute(v),
            time_second(v),
            time_microsecond(v),
            tz)
    r1 = (v1.tzinfo == tz)
    r2 = (tz == time_tzinfo(v1))
    v2 = time_new(
            time_hour(v1),
            time_minute(v1),
            time_second(v1),
            time_microsecond(v1),
            None)
    r3 = (v2.tzinfo == None)
    r4 = (None == time_tzinfo(v2))
    v3 = time_new(
            time_hour(v2),
            time_minute(v2),
            time_second(v2),
            time_microsecond(v2),
            tz)
    r5 = (v3.tzinfo == tz)
    r6 = (tz == time_tzinfo(v3))
    r7 = (v2 == v)
    r8 = (v3 == v1)
    return r1, r2, r3, r4, r5, r6, r7, r8


def do_datetime_tzinfo2(int year, int month, int day,
                              int hour, int minute, int second, int microsecond, object tz):
    """
    >>> tz = FixedOffset(60*3, 'Moscow')
    >>> do_datetime_tzinfo2(2012, 12, 31, 12, 23, 0, 0, tz)
    (True, True, True, True, True, True, True, True)
    """
    v = datetime_new(year, month, day, hour, minute, second, microsecond, None)
    v1 = datetime_new(
            datetime_year(v),
            datetime_month(v),
            datetime_day(v),
            datetime_hour(v),
            datetime_minute(v),
            datetime_second(v),
            datetime_microsecond(v),
            tz)
    r1 = (v1.tzinfo == tz)
    r2 = (tz == datetime_tzinfo(v1))
    v2 = datetime_new(
            datetime_year(v1),
            datetime_month(v1),
            datetime_day(v1),
            datetime_hour(v1),
            datetime_minute(v1),
            datetime_second(v1),
            datetime_microsecond(v1),
            None)
    r3 = (v2.tzinfo == None)
    r4 = (None == datetime_tzinfo(v2))
    v3 = datetime_new(
            datetime_year(v2),
            datetime_month(v2),
            datetime_day(v2),
            datetime_hour(v2),
            datetime_minute(v2),
            datetime_second(v2),
            datetime_microsecond(v2),
            tz)
    r5 = (v3.tzinfo == tz)
    r6 = (tz == datetime_tzinfo(v3))
    r7 = (v2 == v)
    r8 = (v3 == v1)
    return r1, r2, r3, r4, r5, r6, r7, r8


def test_timedelta_total_seconds():
    """
    >>> cytotal, pytotal = test_timedelta_total_seconds()
    >>> assert cytotal == pytotal, (cytotal, pytotal)
    >>> cytotal == pytotal
    True
    """
    cdef:
        datetime now = py_datetime.datetime.now()
        timedelta td = now - py_datetime.datetime(1970, 1, 1)

    pytd = now - py_datetime.datetime(1970, 1, 1)

    return total_seconds(td), pytd.total_seconds()


@cython.test_fail_if_path_exists(
    "//CoerceFromPyTypeNode",
    "//AttributeNode",
)
def test_datetime_attrs_inlined(datetime dt):
    # GH#3737
    """
    >>> from datetime import datetime
    >>> py_dt = datetime(2020, 8, 18, 4, 9)
    >>> dt = test_datetime_attrs_inlined(py_dt)
    >>> dt[:5]
    (2020, 8, 18, 4, 9)
    >>> dt[5] == py_dt.second  or  (dt[5], py_dt.second)
    True
    >>> dt[6] == py_dt.microsecond  or  (dt[6], py_dt.microsecond)
    True
    """
    return (
        dt.year,
        dt.month,
        dt.day,
        dt.hour,
        dt.minute,
        dt.second,
        dt.microsecond,
    )

def test_date_from_timestamp():
    """
    >>> from datetime import datetime
    >>> tp, dt = test_date_from_timestamp()
    >>> tp == dt
    True
    """
    tp = date_from_timestamp(1518185542)
    dt = py_datetime.date(2018, 2, 9)
    return tp, dt

def test_get_utc():
    """
    >>> from datetime import datetime
    >>> test_get_utc()
    True
    """
    try:
        get_utc()
    except RuntimeError:
        if sys.version_info >= (3, 7):
            raise  # get_utc() is only supposed to raise on Python < 3.7
    return True

def test_datetime_from_timestamp():
    """
    >>> from datetime import datetime
    >>> tp, dt = test_datetime_from_timestamp()
    >>> tp == dt
    True
    """
    time = py_time.time()
    tp = datetime_from_timestamp(time)
    dt = py_datetime.datetime.fromtimestamp(time)
    return tp, dt
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/decorator_lambda.pyx0000644000175100001770000000057200000000000021572 0ustar00runnerdocker00000000000000# mode: run
# tag: decorator, lambda

def decorate(f):
    return f

@decorate(lambda x: x)
class TestClassDecorator(object):
    """
    >>> obj = TestClassDecorator()
    >>> obj.hello()
    'Hello, world!'
    """
    def hello(self):
        return "Hello, world!"


@decorate(lambda x: x)
def test_function():
    """
    >>> test_function()
    123
    """
    return 123
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/decorators.pyx0000644000175100001770000000470500000000000020457 0ustar00runnerdocker00000000000000__doc__ = u"""
  >>> f(1,2)
  4
  >>> f.HERE
  1

  >>> g(1,2)
  5
  >>> g.HERE
  5

  >>> h(1,2)
  6
  >>> h.HERE
  1
  >>> i(4)
  3
  >>> i.HERE
  1
  >>> i_called_directly(4)
  3
  >>> i_called_directly.HERE
  1
"""

class wrap:
    def __init__(self, func):
        self.func = func
        self.HERE = 1
    def __call__(self, *args, **kwargs):
        return self.func(*args, **kwargs)

def decorate(func):
    try:
        func.HERE += 1
    except AttributeError:
        func = wrap(func)
    return func

def decorate2(a,b):
    return decorate

@decorate
def f(a,b):
    return a+b+1

@decorate
@decorate
@decorate
@decorate
@decorate
def g(a,b):
    return a+b+2

@decorate2(1,2)
def h(a,b):
    return a+b+3

class A:
    def decorate(self, func):
        return decorate(func)


a = A()
@a.decorate
def i(x):
    return x - 1

@A().decorate
def i_called_directly(x):
    # PEP 614 means this now works
    return x - 1

list_of_decorators = [decorate, decorate2]

@list_of_decorators[0]
def test_index_from_decorator_list0(a, b):
    """
    PEP 614 means this now works
    >>> test_index_from_decorator_list0(1, 2)
    4
    >>> test_index_from_decorator_list0.HERE
    1
    """
    return a+b+1

@list_of_decorators[1](1,2)
def test_index_from_decorator_list1(a, b):
    """
    PEP 614 means this now works
    >>> test_index_from_decorator_list1(1, 2)
    4
    >>> test_index_from_decorator_list1.HERE
    1
    """
    return a+b+1

def append_to_list_decorator(lst):
    def do_append_to_list_dec(func):
        def new_func():
            return lst + func()
        return new_func
    return do_append_to_list_dec

def outer(arg1, arg2):
    """
    ensure decorators are analysed in the correct scope
    https://github.com/cython/cython/issues/4367
    mainly intended as a compile-time test (but it does run...)
    >>> outer(append_to_list_decorator, [1,2,3])
    [1, 2, 3, 4]
    """
    @arg1([x for x in arg2])
    def method():
        return [4]
    return method()

class HasProperty(object):
    """
    >>> hp = HasProperty()
    >>> hp.value
    0
    >>> hp.value = 1
    >>> hp.value
    1
    """
    def __init__(self) -> None:
        self._value = 0

    @property
    def value(self) -> int:
        return self._value

    # https://github.com/cython/cython/issues/4836
    # The variable tracker was confusing "value" in the decorator
    # for "value" in the argument list
    @value.setter
    def value(self, value: int):
        self._value = value
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/decorators_T593.pyx0000644000175100001770000000377700000000000021213 0ustar00runnerdocker00000000000000# mode: run
# ticket: t593
# tag: property, decorator

"""
>>> am_i_buggy
False
>>> Foo
False
"""
def testme(func):
    try:
        am_i_buggy
        return True
    except NameError:
        return False

@testme
def am_i_buggy():
    pass

def testclass(klass):
    try:
        Foo
        return True
    except NameError:
        return False
@testclass
class Foo:
    pass


def called_deco(a,b,c):
    def count(f):
        a.append( (b,c) )
        return f
    return count

L = []

@called_deco(L, 5, c=6)
@called_deco(L, c=3, b=4)
@called_deco(L, 1, 2)
def wrapped_func(x):
    """
    >>> L
    [(1, 2), (4, 3), (5, 6)]
    >>> wrapped_func(99)
    99
    >>> L
    [(1, 2), (4, 3), (5, 6)]
    """
    return x


def class_in_closure(x):
    """
    >>> C1, c0 = class_in_closure(5)
    >>> C1().smeth1()
    (5, ())
    >>> C1.smeth1(1,2)
    (5, (1, 2))
    >>> C1.smeth1()
    (5, ())
    >>> c0.smeth0()
    1
    >>> c0.__class__.smeth0()
    1
    """
    class ClosureClass1(object):
        @staticmethod
        def smeth1(*args):
            return x, args

    class ClosureClass0(object):
        @staticmethod
        def smeth0():
            return 1

    return ClosureClass1, ClosureClass0()

def class_not_in_closure():
    """
    >>> c = class_not_in_closure()
    >>> c.smeth0()
    1
    >>> c.__class__.smeth0()
    1
    """
    class ClosureClass0(object):
        @staticmethod
        def smeth0():
            return 1

    return ClosureClass0()

class ODict(dict):
   def __init__(self):
       dict.__init__(self)
       self._order = []
       dict.__setitem__(self, '_order', self._order)
   def __setitem__(self, key, value):
       dict.__setitem__(self, key, value)
       self._order.append(key)

class Base(type):
   @staticmethod
   def __prepare__(*args, **kwargs):
       return ODict()

class Bar(metaclass=Base):
   """
   >>> [n for n in Bar._order if n not in {"__qualname__", "__annotations__"}]
   ['__module__', '__doc__', 'bar']
   """
   @property
   def bar(self):
       return 0
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/decorators_py_T593.py0000644000175100001770000000265000000000000021520 0ustar00runnerdocker00000000000000# mode: run
# ticket: t593
# tag: property, decorator

"""
>>> am_i_buggy
False
"""

def testme(func):
    try:
        am_i_buggy
        return True
    except NameError:
        return False

@testme
def am_i_buggy():
    pass

def called_deco(a,b,c):
    a.append( (1,b,c) )
    def count(f):
        a.append( (2,b,c) )
        return f
    return count

L = []

@called_deco(L, 5, c=6)
@called_deco(L, c=3, b=4)
@called_deco(L, 1, 2)
def wrapped_func(x):
    """
    >>> L
    [(1, 5, 6), (1, 4, 3), (1, 1, 2), (2, 1, 2), (2, 4, 3), (2, 5, 6)]
    >>> wrapped_func(99)
    99
    >>> L
    [(1, 5, 6), (1, 4, 3), (1, 1, 2), (2, 1, 2), (2, 4, 3), (2, 5, 6)]
    """
    return x


def class_in_closure(x):
    """
    >>> C1, c0 = class_in_closure(5)
    >>> C1().smeth1()
    (5, ())
    >>> C1.smeth1(1,2)
    (5, (1, 2))
    >>> C1.smeth1()
    (5, ())
    >>> c0.smeth0()
    1
    >>> c0.__class__.smeth0()
    1
    """
    class ClosureClass1(object):
        @staticmethod
        def smeth1(*args):
            return x, args

    class ClosureClass0(object):
        @staticmethod
        def smeth0():
            return 1

    return ClosureClass1, ClosureClass0()

def class_not_in_closure():
    """
    >>> c = class_not_in_closure()
    >>> c.smeth0()
    1
    >>> c.__class__.smeth0()
    1
    """
    class ClosureClass0(object):
        @staticmethod
        def smeth0():
            return 1

    return ClosureClass0()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/default_args_T674.py0000644000175100001770000000052300000000000021300 0ustar00runnerdocker00000000000000# mode: run
# ticket: t674

def test_inner(a):
    """
    >>> a = test_inner(1)
    >>> b = test_inner(2)
    >>> a()
    1
    >>> b()
    2
    """
    def inner(b=a):
        return b
    return inner

def test_lambda(n):
    """
    >>> [f() for f in test_lambda(3)]
    [0, 1, 2]
    """
    return [lambda v=i: v for i in range(n)]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/default_optional_gh5643.py0000644000175100001770000000336200000000000022451 0ustar00runnerdocker00000000000000# mode: run
# tag: pep484, warnings, pure3.6
# ticket: 5643
# cython: language_level=3

try:
    from typing import Optional
except ImportError:
    pass


# no crash
def gh5643_optional(a: Optional[int] = None):
    """
    >>> gh5643_optional()
    True
    >>> gh5643_optional(1)
    False
    """
    return a is None


# no crash
def gh5643_int_untyped(a: int = 1, b = None):
    """
    >>> gh5643_int_untyped(2)
    (False, True)
    >>> gh5643_int_untyped(2, None)
    (False, True)
    >>> gh5643_int_untyped(1, 3)
    (True, False)
    """
    return a == 1, b is None


# used to crash
def gh5643_int_int_none(a: int = 1, b: int = None):  # should warn about missing "Optional[]"
    """
    >>> gh5643_int_int_none()
    (True, True)
    >>> gh5643_int_int_none(2, 3)
    (False, False)
    """
    return a == 1, b is None


def gh5643_int_int_integer(a: int = 1, b: int = 3):
    """
    >>> gh5643_int_int_integer()
    (True, True)
    >>> gh5643_int_int_integer(2, 3)
    (False, True)
    """
    return a == 1, b == 3


# used to crash
def gh5643_int_optional_none(a: int = 1, b: Optional[int] = None):
    """
    >>> gh5643_int_optional_none()
    (True, True)
    >>> gh5643_int_optional_none(2)
    (False, True)
    >>> gh5643_int_optional_none(2, 3)
    (False, False)
    """
    return a == 1, b is None


def gh5643_int_optional_integer(a: int = 1, b: Optional[int] = 2):
    """
    >>> gh5643_int_optional_integer()
    (True, True)
    >>> gh5643_int_optional_integer(2)
    (False, True)
    >>> gh5643_int_optional_integer(2, 3)
    (False, False)
    >>> gh5643_int_optional_integer(2, 2)
    (False, True)
    """
    return a == 1, b == 2


_WARNINGS = """
37:36: PEP-484 recommends 'typing.Optional[...]' for arguments that can be None.
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/define_macro.pyx0000644000175100001770000000030000000000000020710 0ustar00runnerdocker00000000000000#distutils: define_macros = DEFINE_NO_VALUE  DEFINE_WITH_VALUE=0

cdef extern from "define_macro_helper.h" nogil:
    int VAL;

def test():
    """
    >>> test()
    1
    """
    return VAL
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/define_macro_helper.h0000644000175100001770000000016300000000000021665 0ustar00runnerdocker00000000000000#pragma once
#ifdef DEFINE_NO_VALUE
#define VAL (DEFINE_WITH_VALUE + 1)
#else
#define VAL DEFINE_WITH_VALUE
#endif
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/defnode_err_val.pyx0000644000175100001770000000047400000000000021427 0ustar00runnerdocker00000000000000# mode: run

cdef class TestErrVal(object):
    def __cinit__(self, TestErrVal a):
        pass


def test_errval():
    """
    >>> test_errval()
    Traceback (most recent call last):
    ...
    TypeError: Argument 'a' has incorrect type (expected defnode_err_val.TestErrVal, got int)
    """
    TestErrVal(123)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/delete.pyx0000644000175100001770000000452700000000000017556 0ustar00runnerdocker00000000000000
cimport cython

class A(object):
    """
    >>> a = A()
    >>> a.f()
    [2, 1]
    >>> a.g()
    (False, True)
    """
    def f(self):
        self.refs = [3,2,1]
        del self.refs[0]
        return self.refs

    def g(self):
        self.a = 3
        del self.a
        return (hasattr(self, u"a"), hasattr(self, u"g"))

def del_item(L, o):
    """
    >>> del_item({1: 'a', 2: 'b'}, 1)
    {2: 'b'}
    >>> del_item(list(range(10)), 2)
    [0, 1, 3, 4, 5, 6, 7, 8, 9]
    """
    del L[o]
    return L


@cython.test_assert_path_exists('//DelStatNode//IndexNode//NoneCheckNode')
def del_dict(dict D, o):
    """
    >>> del_dict({1: 'a', 2: 'b'}, 1)
    {2: 'b'}
    >>> del_dict(None, 1)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: 'NoneType' object ...
    """
    del D[o]
    return D


@cython.test_fail_if_path_exists('//DelStatNode//IndexNode//NoneCheckNode')
def del_dict_ann(D: dict, o):
    """
    >>> del_dict_ann({1: 'a', 2: 'b'}, 1)
    {2: 'b'}
    >>> del_dict_ann(None, 1)
    Traceback (most recent call last):
    TypeError: Argument 'D' has incorrect type (expected dict, got NoneType)
    """
    del D[o]
    return D


@cython.test_fail_if_path_exists('//NoneCheckNode')
def del_dict_from_literal(o):
    """
    >>> del_dict_from_literal(1)
    {2: 'b'}
    """
    D = {1: 'a', 2: 'b'}
    del D[o]
    return D

def del_list(list L, o):
    """
    >>> del_list(list(range(5)), 3)
    [0, 1, 2, 4]
    """
    del L[o]
    return L

def del_int(L, int i):
    """
    >>> del_int(list(range(5)), 3)
    [0, 1, 2, 4]
    >>> del_int({-1: 'neg', 1: 'pos'}, -1)
    {1: 'pos'}
    """
    del L[i]
    return L

def del_list_int(L, int i):
    """
    >>> del_list_int(list(range(5)), 3)
    [0, 1, 2, 4]
    """
    del L[i]
    return L

def del_temp_slice(a):
    """
    >>> class A(object):
    ...     attr = [1,2,3]
    >>> a = A()
    >>> a.attr
    [1, 2, 3]
    >>> del_temp_slice(a)
    []
    >>> a.attr
    []
    >>> del_temp_slice(a)
    []
    >>> a.attr
    []
    """
    while a.attr:
        del a.attr[:]
    return a.attr

def del_local(a):
    """
    >>> del_local(object())
    """
    del a
    assert 'a' not in locals()

def del_seq(a, b, c):
    """
    >>> del_seq(1, 2, 3)
    """
    del a, (b, c)
    assert 'a' not in locals()
    assert 'b' not in locals()
    assert 'c' not in locals()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/delslice.py0000644000175100001770000000405200000000000017701 0ustar00runnerdocker00000000000000# mode: run
# tag: del, slicing

def del_constant_start_stop(x):
    """
    >>> l = [1,2,3,4]
    >>> del_constant_start_stop(l)
    [1, 2]

    >>> l = [1,2,3,4,5,6,7]
    >>> del_constant_start_stop(l)
    [1, 2, 7]
    """
    del x[2:6]
    return x


def del_start(x, start):
    """
    >>> l = [1,2,3,4]
    >>> del_start(l, 2)
    [1, 2]

    >>> l = [1,2,3,4,5,6,7]
    >>> del_start(l, 20)
    [1, 2, 3, 4, 5, 6, 7]
    >>> del_start(l, 8)
    [1, 2, 3, 4, 5, 6, 7]
    >>> del_start(l, 4)
    [1, 2, 3, 4]

    >>> del_start(l, -2)
    [1, 2]
    >>> l
    [1, 2]
    >>> del_start(l, -2)
    []
    >>> del_start(l, 2)
    []
    >>> del_start(l, -2)
    []
    >>> del_start(l, 20)
    []

    >>> del_start([1,2,3,4], -20)
    []
    >>> del_start([1,2,3,4], 0)
    []
    """
    del x[start:]
    return x


def del_stop(x, stop):
    """
    >>> l = [1,2,3,4]
    >>> del_stop(l, 2)
    [3, 4]

    >>> l = [1,2,3,4,5,6,7]
    >>> del_stop(l, -20)
    [1, 2, 3, 4, 5, 6, 7]
    >>> del_stop(l, -8)
    [1, 2, 3, 4, 5, 6, 7]
    >>> del_stop(l, -4)
    [4, 5, 6, 7]

    >>> del_stop(l, -2)
    [6, 7]
    >>> l
    [6, 7]
    >>> del_stop(l, -2)
    [6, 7]
    >>> del_stop(l, 2)
    []
    >>> del_stop(l, -2)
    []
    >>> del_stop(l, 20)
    []

    >>> del_stop([1,2,3,4], -20)
    [1, 2, 3, 4]
    >>> del_stop([1,2,3,4], 0)
    [1, 2, 3, 4]
    """
    del x[:stop]
    return x


def del_start_stop(x, start, stop):
    """
    >>> l = [1,2,3,4]
    >>> del_start_stop(l, 0, 2)
    [3, 4]
    >>> l
    [3, 4]

    >>> l = [1,2,3,4,5,6,7]
    >>> del_start_stop(l, -1, -20)
    [1, 2, 3, 4, 5, 6, 7]
    >>> del_start_stop(l, -20, -8)
    [1, 2, 3, 4, 5, 6, 7]
    >>> del_start_stop(l, -6, -4)
    [1, 4, 5, 6, 7]

    >>> del_start_stop(l, -20, -2)
    [6, 7]
    >>> l
    [6, 7]
    >>> del_start_stop(l, -2, 1)
    [7]
    >>> del_start_stop(l, -2, 3)
    []
    >>> del_start_stop(l, 2, 4)
    []

    >>> del_start_stop([1,2,3,4], 20, -20)
    [1, 2, 3, 4]
    >>> del_start_stop([1,2,3,4], 0, 0)
    [1, 2, 3, 4]
    """
    del x[start:stop]
    return x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/dict.pyx0000644000175100001770000000662500000000000017240 0ustar00runnerdocker00000000000000import sys

IS_PY35 = sys.version_info >= (3, 5)


def empty():
    """
    >>> empty()
    {}
    """
    d = {}
    return d

def keyvalue(key, value):
    """
    >>> keyvalue(1, 2)
    {1: 2}
    """
    d = {key:value}
    return d

def keyvalues(key1, value1, key2, value2):
    """
    >>> sorted(keyvalues(1, 2, 3, 4).items())
    [(1, 2), (3, 4)]
    """
    d = {key1:value1, key2:value2}
    return d

def keyvalues2(key1, value1, key2, value2):
    """
    >>> sorted(keyvalues2(1, 2, 3, 4).items())
    [(1, 2), (3, 4)]
    """
    d = {key1:value1, key2:value2,}
    return d

def constant():
    """
    >>> len(constant())
    2
    >>> print(constant()['parrot'])
    resting
    >>> print(constant()['answer'])
    42
    """
    d = {u"parrot":u"resting", u"answer":42}
    return d

def dict_call():
    """
    >>> print(dict_call()['parrot'])
    resting
    >>> print(dict_call()['answer'])
    42
    """
    d = dict(parrot=u"resting", answer=42)
    return d

def dict_call_dict():
    """
    >>> print(dict_call_dict()['parrot'])
    resting
    >>> print(dict_call_dict()['answer'])
    42
    """
    d = dict(dict(parrot=u"resting", answer=42))
    return d

def dict_call_kwargs():
    """
    >>> print(dict_call_kwargs()['parrot1'])
    resting
    >>> print(dict_call_kwargs()['parrot2'])
    resting
    >>> print(dict_call_kwargs()['answer1'])
    42
    >>> print(dict_call_kwargs()['answer2'])
    42
    """
    kwargs = dict(parrot1=u"resting", answer1=42)
    d = dict(parrot2=u"resting", answer2=42, **kwargs)
    return d


def items_of_dict_call():
    """
    >>> items_of_dict_call()
    [('answer1', 42), ('answer2', 42), ('parrot1', 'resting'), ('parrot2', 'resting')]
    """
    kwargs = dict(parrot1="resting", answer1=42)
    items = dict(kwargs.items(), parrot2="resting", answer2=42, **kwargs).items()
    return sorted(items)


def item_creation_sideeffect(L, sideeffect, unhashable):
    """
    >>> def sideeffect(x):
    ...     L.append(x)
    ...     return x
    >>> def unhashable(x):
    ...     L.append(x)
    ...     return [x]

    >>> L = []
    >>> item_creation_sideeffect(L, sideeffect, unhashable)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...unhashable...
    >>> L
    [2, 4]

    >>> L = []
    >>> {1:2, sideeffect(2): 3, 3: 4, unhashable(4): 5, sideeffect(5): 6}  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...unhashable...
    >>> L if IS_PY35 else (L + [5])
    [2, 4, 5]
    """
    return {1:2, sideeffect(2): 3, 3: 4, unhashable(4): 5, sideeffect(5): 6}


def dict_unpacking_not_for_arg_create_a_copy():
    """
    >>> dict_unpacking_not_for_arg_create_a_copy()
    [('a', 'modified'), ('b', 'original')]
    [('a', 'original'), ('b', 'original')]
    """
    data = {'a': 'original', 'b': 'original'}

    func = lambda: {**data}

    call_once = func()
    call_once['a'] = 'modified'

    call_twice = func()

    print(sorted(call_once.items()))
    print(sorted(call_twice.items()))

def from_keys_bound(dict d, val):
    """
    https://github.com/cython/cython/issues/5051
    Optimization of bound method calls was breaking classmethods
    >>> sorted(from_keys_bound({}, 100).items())
    [('a', 100), ('b', 100)]
    >>> sorted(from_keys_bound({}, None).items())
    [('a', None), ('b', None)]
    """
    if val is not None:
        return d.fromkeys(("a", "b"), val)
    else:
        return d.fromkeys(("a", "b"))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/dict_get.pyx0000644000175100001770000000360600000000000020073 0ustar00runnerdocker00000000000000
cimport cython

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def get(dict d, key):
    """
    >>> d = { 1: 10 }
    >>> d.get(1)
    10
    >>> get(d, 1)
    10

    >>> d.get(2) is None
    True
    >>> get(d, 2) is None
    True

    >>> d.get((1,2)) is None
    True
    >>> get(d, (1,2)) is None
    True

    >>> class Unhashable:
    ...    def __hash__(self):
    ...        raise ValueError

    >>> d.get(Unhashable())
    Traceback (most recent call last):
    ValueError
    >>> get(d, Unhashable())
    Traceback (most recent call last):
    ValueError

    >>> None.get(1)
    Traceback (most recent call last):
    ...
    AttributeError: 'NoneType' object has no attribute 'get'
    >>> get(None, 1)
    Traceback (most recent call last):
    ...
    AttributeError: 'NoneType' object has no attribute 'get'
    """
    return d.get(key)


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def get_default(dict d, key, default):
    """
    >>> d = { 1: 10 }

    >>> d.get(1, 2)
    10
    >>> get_default(d, 1, 2)
    10

    >>> d.get(2, 2)
    2
    >>> get_default(d, 2, 2)
    2

    >>> d.get((1,2), 2)
    2
    >>> get_default(d, (1,2), 2)
    2

    >>> class Unhashable:
    ...    def __hash__(self):
    ...        raise ValueError

    >>> d.get(Unhashable(), 2)
    Traceback (most recent call last):
    ValueError
    >>> get_default(d, Unhashable(), 2)
    Traceback (most recent call last):
    ValueError
    """
    return d.get(key, default)


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def get_in_condition(dict d, key, expected_result):
    """
    >>> d = dict(a=1, b=2)
    >>> get_in_condition(d, 'a', 1)
    True
    """
    return d.get(key) is expected_result or d.get(key) == expected_result
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/dict_getitem.pyx0000644000175100001770000000761200000000000020753 0ustar00runnerdocker00000000000000# mode: run
# tag: dict, getitem

cimport cython

def test(dict d, index):
    """
    >>> d = { 1: 10 }
    >>> test(d, 1)
    10

    >>> test(d, 2)
    Traceback (most recent call last):
    KeyError: 2

    >>> test(d, (1,2))
    Traceback (most recent call last):
    KeyError: (1, 2)

    >>> import sys
    >>> try: d[(1,)]
    ... except KeyError:
    ...     args = sys.exc_info()[1].args
    ...     if sys.version_info >= (2,5): print(args)
    ...     else: print((args,))   # fake it for older CPython versions
    ((1,),)

    >>> import sys
    >>> try: test(d, (1,))
    ... except KeyError:
    ...     args = sys.exc_info()[1].args
    ...     if sys.version_info >= (2,5): print(args)
    ...     else: print((args,))   # fake it for older CPython versions
    ((1,),)

    >>> class Unhashable:
    ...    def __hash__(self):
    ...        raise ValueError
    >>> test(d, Unhashable())
    Traceback (most recent call last):
    ValueError

    >>> test(None, 1) # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...object...
    """
    return d[index]


def getitem_str(dict d, obj, str index):
    """
    >>> d = {'abc': 1, 'xyz': 2, None: 3}
    >>> getitem_str(d, d, 'abc')
    (1, 1)
    >>> getitem_str(d, d, 'xyz')
    (2, 2)
    >>> getitem_str(d, d, None)
    (3, 3)

    >>> class GetItem(object):
    ...     def __getitem__(self, name): return d[name]
    >>> getitem_str(d, GetItem(), 'abc')
    (1, 1)
    >>> getitem_str(d, GetItem(), 'xyz')
    (2, 2)
    >>> getitem_str(d, GetItem(), None)
    (3, 3)
    >>> getitem_str(d, GetItem(), 'no')
    Traceback (most recent call last):
    KeyError: 'no'

    >>> class GetItemFail(object):
    ...     def __getitem__(self, name): raise ValueError("failed")
    >>> getitem_str(d, GetItemFail(), 'abc')
    Traceback (most recent call last):
    ValueError: failed
    >>> getitem_str(d, GetItemFail(), None)
    Traceback (most recent call last):
    ValueError: failed
    """
    return d[index], obj[index]


def getitem_unicode(dict d, obj, unicode index):
    """
    >>> d = {'abc': 1, 'xyz': 2, None: 3}
    >>> getitem_unicode(d, d, u'abc')
    (1, 1)
    >>> getitem_unicode(d, d, u'xyz')
    (2, 2)
    >>> getitem_unicode(d, d, None)
    (3, 3)

    >>> class GetItem(object):
    ...     def __getitem__(self, name): return d[name]
    >>> getitem_unicode(d, GetItem(), u'abc')
    (1, 1)
    >>> getitem_unicode(d, GetItem(), u'xyz')
    (2, 2)
    >>> getitem_unicode(d, GetItem(), None)
    (3, 3)
    >>> try: getitem_unicode(d, GetItem(), u'no')
    ... except KeyError as exc: assert exc.args[0] == u'no', str(exc)
    ... else: assert False, "KeyError not raised"

    >>> class GetItemFail(object):
    ...     def __getitem__(self, name): raise ValueError("failed")
    >>> getitem_unicode(d, GetItemFail(), u'abc')
    Traceback (most recent call last):
    ValueError: failed
    """
    return d[index], obj[index]


def getitem_tuple(dict d, index):
    """
    >>> d = {1: 1, (1,): 2}
    >>> getitem_tuple(d, 1)
    (1, 2)
    """
    return d[index], d[index,]


def getitem_in_condition(dict d, key, expected_result):
    """
    >>> d = dict(a=1, b=2)
    >>> getitem_in_condition(d, 'a', 1)
    True
    """
    return d[key] is expected_result or d[key] == expected_result


@cython.test_fail_if_path_exists('//NoneCheckNode')
def getitem_not_none(dict d not None, key):
    """
    >>> d = { 1: 10 }
    >>> test(d, 1)
    10

    >>> test(d, 2)
    Traceback (most recent call last):
    KeyError: 2

    >>> test(d, (1,2))
    Traceback (most recent call last):
    KeyError: (1, 2)
    """
    return d[key]


def getitem_int_key(d, int key):
    """
    >>> d = {-1: 10}
    >>> getitem_int_key(d, -1)  # dict
    10
    >>> class D(dict): pass
    >>> d = D({-1: 10})
    >>> getitem_int_key(d, -1)  # D
    10
    """
    # Based on GH-1807: must check Mapping protocol first, even for integer "index" keys.
    return d[key]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/dict_iter_unpack.pyx0000644000175100001770000000070100000000000021611 0ustar00runnerdocker00000000000000# mode: run
# tag: dictiter

def iteritems_unpack(dict the_dict):
    """
    >>> d = {(1,2): (3,4), (5,6): (7,8)}
    >>> iteritems_unpack(d)
    [(1, 2, 3, 4), (5, 6, 7, 8)]
    """
    return sorted([ (a,b,c,d) for (a,b), (c,d) in the_dict.iteritems() ])

def itervalues_unpack(dict the_dict):
    """
    >>> d = {1: (3,4), 2: (7,8)}
    >>> itervalues_unpack(d)
    [(3, 4), (7, 8)]
    """
    return [(a,b) for a,b in the_dict.itervalues() ]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/dict_pop.pyx0000644000175100001770000000302200000000000020102 0ustar00runnerdocker00000000000000# mode: run
# tag: dict, pop, builtins

cimport cython

@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def dict_pop(dict d, key):
    """
    >>> d = { 1: 10, 2: 20 }
    >>> dict_pop(d, 1)
    (10, {2: 20})
    >>> dict_pop(d, 3)
    Traceback (most recent call last):
    KeyError: 3
    >>> dict_pop(d, 2)
    (20, {})
    """
    return d.pop(key), d


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def dict_pop_default(dict d, key, default):
    """
    >>> d = { 1: 10, 2: 20 }
    >>> dict_pop_default(d, 1, "default")
    (10, {2: 20})
    >>> dict_pop_default(d, 3, None)
    (None, {2: 20})
    >>> dict_pop_default(d, 3, "default")
    ('default', {2: 20})
    >>> dict_pop_default(d, 2, "default")
    (20, {})
    """
    return d.pop(key, default), d


cdef class MyType:
    cdef public int i
    def __init__(self, i):
        self.i = i


@cython.test_assert_path_exists("//SingleAssignmentNode//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//SingleAssignmentNode//AttributeNode")
def dict_pop_default_typed(dict d, key, default):
    """
    >>> d = {1: MyType(2)}
    >>> dict_pop_default_typed(d, 1, None)
    2
    >>> dict_pop_default_typed(d, 3, None)
    >>> dict_pop_default_typed(d, 3, "default")  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: Cannot convert str to ...MyType
    """
    cdef MyType x = d.pop(key, default)
    return x.i if x is not None else None
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/dict_setdefault.py0000644000175100001770000000601100000000000021255 0ustar00runnerdocker00000000000000
import cython

class Unhashable(object):
    def __hash__(self):
        raise TypeError('I am not hashable')

class Hashable(object):
    def __hash__(self):
        return 1
    def __eq__(self, other):
        return isinstance(other, Hashable)

class CountedHashable(object):
    def __init__(self):
        self.hash_count = 0
        self.eq_count = 0
    def __hash__(self):
        self.hash_count += 1
        return 42
    def __eq__(self, other):
        self.eq_count += 1
        return id(self) == id(other)

@cython.test_fail_if_path_exists('//AttributeNode')
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.locals(d=dict)
def setdefault1(d, key):
    """
    >>> d = {}
    >>> setdefault1(d, 1)
    >>> len(d)
    1
    >>> setdefault1(d, 1)
    >>> len(d)
    1
    >>> d[1]
    >>> setdefault1(d, Unhashable())
    Traceback (most recent call last):
    TypeError: I am not hashable
    >>> len(d)
    1
    >>> h1 = setdefault1(d, Hashable())
    >>> len(d)
    2
    >>> h2 = setdefault1(d, Hashable())
    >>> len(d)
    2
    >>> d[Hashable()]

    # CPython's behaviour depends on version and py_debug setting, so just compare to it
    >>> py_hashed1 = CountedHashable()
    >>> y = {py_hashed1: 5}
    >>> py_hashed2 = CountedHashable()
    >>> y.setdefault(py_hashed2)

    >>> cy_hashed1 = CountedHashable()
    >>> y = {cy_hashed1: 5}
    >>> cy_hashed2 = CountedHashable()
    >>> setdefault1(y, cy_hashed2)
    >>> py_hashed1.hash_count - cy_hashed1.hash_count
    0
    >>> py_hashed2.hash_count - cy_hashed2.hash_count
    0
    >>> (py_hashed1.eq_count + py_hashed2.eq_count) - (cy_hashed1.eq_count + cy_hashed2.eq_count)
    0
    """
    return d.setdefault(key)

@cython.test_fail_if_path_exists('//AttributeNode')
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.locals(d=dict)
def setdefault2(d, key, value):
    """
    >>> d = {}
    >>> setdefault2(d, 1, 2)
    2
    >>> len(d)
    1
    >>> setdefault2(d, 1, 2)
    2
    >>> len(d)
    1
    >>> l = setdefault2(d, 2, [])
    >>> len(d)
    2
    >>> l.append(1)
    >>> setdefault2(d, 2, [])
    [1]
    >>> len(d)
    2
    >>> setdefault2(d, Unhashable(), 1)
    Traceback (most recent call last):
    TypeError: I am not hashable
    >>> h1 = setdefault2(d, Hashable(), 55)
    >>> len(d)
    3
    >>> h2 = setdefault2(d, Hashable(), 66)
    >>> len(d)
    3
    >>> d[Hashable()]
    55

    # CPython's behaviour depends on version and py_debug setting, so just compare to it
    >>> py_hashed1 = CountedHashable()
    >>> y = {py_hashed1: 5}
    >>> py_hashed2 = CountedHashable()
    >>> y.setdefault(py_hashed2, [])
    []

    >>> cy_hashed1 = CountedHashable()
    >>> y = {cy_hashed1: 5}
    >>> cy_hashed2 = CountedHashable()
    >>> setdefault2(y, cy_hashed2, [])
    []
    >>> py_hashed1.hash_count - cy_hashed1.hash_count
    0
    >>> py_hashed2.hash_count - cy_hashed2.hash_count
    0
    >>> (py_hashed1.eq_count + py_hashed2.eq_count) - (cy_hashed1.eq_count + cy_hashed2.eq_count)
    0
    """
    return d.setdefault(key, value)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/dict_values_in_expression.pyx0000644000175100001770000000060600000000000023555 0ustar00runnerdocker00000000000000
def values_in_expression(**kwargs):
    """
    >>> sorted(values_in_expression(a=3, b=4))
    [1, 2, 3, 4]
    """
    return [ arg for arg in [1,2] + list(kwargs.values()) ]


cdef dict make_dict(d):
    return dict(d)

def values_of_expression(**kwargs):
    """
    >>> sorted(values_of_expression(a=3, b=4))
    [3, 4]
    """
    return [ arg for arg in make_dict(kwargs).values() ]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/dictcomp.pyx0000644000175100001770000000426500000000000020115 0ustar00runnerdocker00000000000000
cimport cython

def dictcomp():
    """
    >>> sorted(dictcomp().items())
    [(2, 0), (4, 4), (6, 8)]
    >>> sorted(dictcomp().items())
    [(2, 0), (4, 4), (6, 8)]
    """
    x = 'abc'
    result = { x+2:x*2
               for x in range(5)
               if x % 2 == 0 }
    assert x == 'abc' # do not leak!
    return result

@cython.test_assert_path_exists(
    "//InlinedGeneratorExpressionNode",
    "//DictComprehensionAppendNode")
def genexpr():
    """
    >>> type(genexpr()) is dict
    True
    >>> type(genexpr()) is dict
    True
    """
    x = 'abc'
    result = dict( (x+2,x*2)
                   for x in range(5)
                   if x % 2 == 0 )
    assert x == 'abc'
    return result

cdef class A:
    def __repr__(self): return u"A"
    def __richcmp__(one, other, int op): return one is other
    def __hash__(self): return id(self) % 65536

def typed_dictcomp():
    """
    >>> list(typed_dictcomp().items())
    [(A, 1), (A, 1), (A, 1)]
    """
    cdef A obj
    return {obj:1 for obj in [A(), A(), A()]}

def iterdict_dictcomp():
    """
    >>> sorted(iterdict_dictcomp().items())
    [(1, 'a'), (2, 'b'), (3, 'c')]
    """
    cdef dict d = dict(a=1,b=2,c=3)
    return {d[key]:key for key in d}

def sorted(it):
    l = list(it)
    l.sort()
    return l


# Copied from sre_compile.py in CPython 3.7.  Previously failed to detect variable initialisation.
_equivalences = (
    # LATIN SMALL LETTER I, LATIN SMALL LETTER DOTLESS I
    (0x69, 0x131), # iı
    # LATIN SMALL LETTER S, LATIN SMALL LETTER LONG S
    (0x73, 0x17f), # sſ
    # MICRO SIGN, GREEK SMALL LETTER MU
    (0xb5, 0x3bc), # µμ
    # COMBINING GREEK YPOGEGRAMMENI, GREEK SMALL LETTER IOTA, GREEK PROSGEGRAMMENI
    (0x345, 0x3b9, 0x1fbe), # \u0345ιι
    # ...
)

_ignorecase_fixes = {
    i: tuple(j for j in t if i != j)
    for t in _equivalences for i in t
}

def nested_tuple():
    """
    >>> modlevel, funclevel = nested_tuple()
    >>> modlevel == funclevel or (modlevel, funclevel)
    True
    """
    inner_ignorecase_fixes = {
        i: tuple(j for j in t if i != j)
        for t in _equivalences for i in t
    }

    return sorted(_ignorecase_fixes.items()), sorted(inner_ignorecase_fixes.items())
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/dictintindex.pyx0000644000175100001770000001063200000000000020774 0ustar00runnerdocker00000000000000def test_get_char_neg():
    """
    >>> test_get_char_neg()
    0
    """
    cdef char key = -1
    if -1 < 0:
        d = {-1:0}
    else:
        d = {255:0}
    return d[key]
def test_get_char_zero():
    """
    >>> test_get_char_zero()
    1
    """
    cdef char key = 0
    d = {0:1}
    return d[key]
def test_get_char_pos():
    """
    >>> test_get_char_pos()
    2
    """
    cdef char key = 1
    d = {1:2}
    return d[key]


def test_get_uchar_zero():
    """
    >>> test_get_uchar_zero()
    1
    """
    cdef unsigned char key = 0
    d = {0:1}
    return d[key]
def test_get_uchar_pos():
    """
    >>> test_get_uchar_pos()
    2
    """
    cdef unsigned char key = 1
    d = {1:2}
    return d[key]


def test_get_int_neg():
    """
    >>> test_get_int_neg()
    0
    """
    cdef int key = -1
    d = {-1:0}
    return d[key]
def test_get_int_zero():
    """
    >>> test_get_int_zero()
    1
    """
    cdef int key = 0
    d = {0:1}
    return d[key]
def test_get_int_pos():
    """
    >>> test_get_int_pos()
    2
    """
    cdef int key = 1
    d = {1:2}
    return d[key]


def test_get_uint_zero():
    """
    >>> test_get_uint_zero()
    1
    """
    cdef unsigned int key = 0
    d = {0:1}
    return d[key]
def test_get_uint_pos():
    """
    >>> test_get_uint_pos()
    2
    """
    cdef unsigned int key = 1
    d = {1:2}
    return d[key]


def test_get_longlong_neg():
    """
    >>> test_get_longlong_neg()
    0
    """
    cdef long long key = -1
    d = {-1:0}
    return d[key]
def test_get_longlong_zero():
    """
    >>> test_get_longlong_zero()
    1
    """
    cdef long long key = 0
    d = {0:1}
    return d[key]
def test_get_longlong_pos():
    """
    >>> test_get_longlong_pos()
    2
    """
    cdef long long key = 1
    d = {1:2}
    return d[key]
def test_get_longlong_big():
    """
    >>> test_get_longlong_big()
    3
    """
    cdef unsigned int shift = sizeof(long)+2
    cdef long long big = 1
    cdef long long key = big<>> test_get_ulonglong_zero()
    1
    """
    cdef unsigned long long key = 0
    d = {0:1}
    return d[key]
def test_get_ulonglong_pos():
    """
    >>> test_get_ulonglong_pos()
    2
    """
    cdef unsigned long long key = 1
    d = {1:2}
    return d[key]
def test_get_ulonglong_big():
    """
    >>> test_get_ulonglong_big()
    3
    """
    cdef unsigned int shift = sizeof(long)+2
    cdef unsigned long long big = 1
    cdef unsigned long long key = big<>> test_del_char()
    Traceback (most recent call last):
    KeyError: 0
    """
    cdef char key = 0
    d = {0:1}
    del d[key]
    return d[key]

def test_del_uchar():
    """
    >>> test_del_uchar()
    Traceback (most recent call last):
    KeyError: 0
    """
    cdef unsigned char key = 0
    d = {0:1}
    del d[key]
    return d[key]

def test_del_int():
    """
    >>> test_del_int()
    Traceback (most recent call last):
    KeyError: 0
    """
    cdef int key = 0
    d = {0:1}
    del d[key]
    return d[key]

def test_del_uint():
    """
    >>> test_del_uint()  #doctest: +ELLIPSIS
    Traceback (most recent call last):
    KeyError: 0...
    """
    cdef unsigned int key = 0
    d = {0:1}
    del d[key]
    return d[key]

def test_del_longlong():
    """
    >>> test_del_longlong() #doctest: +ELLIPSIS
    Traceback (most recent call last):
    KeyError: 0...
    """
    cdef long long key = 0
    d = {0:1}
    del d[key]
    return d[key]

def test_del_ulonglong():
    """
    >>> test_del_ulonglong() #doctest: +ELLIPSIS
    Traceback (most recent call last):
    KeyError: 0...
    """
    cdef unsigned long long key = 0
    d = {0:1}
    del d[key]
    return d[key]

def test_del_longlong_big():
    """
    >>> test_del_longlong_big() #doctest: +ELLIPSIS
    Traceback (most recent call last):
    KeyError: ...
    """
    cdef int shift = sizeof(long)+2
    cdef long long big = 1
    cdef long long key = big<>> test_del_ulonglong_big() #doctest: +ELLIPSIS
    Traceback (most recent call last):
    KeyError: ...
    """
    cdef unsigned int shift = sizeof(long)+2
    cdef unsigned long long big = 1
    cdef unsigned long long key = big<>> test()
    1.0
    """
    cdef float[10][10] v
    v[1][2] = 1.0
    return v[1][2]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/different_package_names.srctree0000644000175100001770000000160500000000000023741 0ustar00runnerdocker00000000000000# mode: run
# tag: import,cimport,packages

PYTHON setup.py build_ext --inplace
PYTHON -c "import pkg_py"
PYTHON -c "import pkg_py.pkg_pyx"
PYTHON -c "import pkg_py.pkg_pyx.module as module; module.run_test()"

######## setup.py ########

from distutils.core import setup
from Cython.Build import cythonize

setup(
    ext_modules=cythonize('**/*.pyx', language_level=3),
)


######## pkg_py/__init__.py ########

TYPE = 'py'

######## pkg_py/pkg_pyx/__init__.pyx ########

TYPE = 'pyx'

######## pkg_py/pkg_pyx/pkg_pxd/__init__.pxd ########

# Not what Python would consider a package, but Cython can use it for cimports.
from libc.math cimport fabs

######## pkg_py/pkg_pyx/module.pyx ########

from pkg_py.pkg_pyx.pkg_pxd cimport fabs

def run_test():
    import pkg_py
    assert pkg_py.TYPE == 'py'

    import pkg_py.pkg_pyx
    assert pkg_py.pkg_pyx.TYPE == 'pyx'

    assert fabs(-2.0) == 2.0
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/directive_locals_in_pxd.pxd0000644000175100001770000000026500000000000023136 0ustar00runnerdocker00000000000000cimport cython

@cython.locals(egg=double)
cdef foo(egg)

@cython.locals(egg=cython.double)
cdef foo_defval(egg=*)

@cython.locals(egg=cython.bint, v=cython.int)
cpdef cpfoo(egg=*)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/directive_locals_in_pxd.py0000644000175100001770000000106400000000000022771 0ustar00runnerdocker00000000000000import cython

def foo(egg):
    if not cython.compiled:
        egg = float(egg)
    return egg

def foo_defval(egg=1):
    if not cython.compiled:
        egg = float(egg)
    return egg**2

def cpfoo(egg=False):
    if not cython.compiled:
        egg = bool(egg)
        v = int(not egg)
    else:
        v = not egg
    return egg, v

def test_pxd_locals():
    """
    >>> v1, v2, v3 = test_pxd_locals()
    >>> isinstance(v1, float)
    True
    >>> isinstance(v2, float)
    True
    >>> v3
    (True, 0)
    """
    return foo(1), foo_defval(), cpfoo(1)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/division_T384.pyx0000644000175100001770000000045200000000000020653 0ustar00runnerdocker00000000000000# ticket: t384

"""
>>> test(3)
(3+1j)
"""

cimport cython

ctypedef Py_ssize_t index_t

ctypedef double complex mycomplex

ctypedef struct MyStruct:
    mycomplex a, b

@cython.cdivision(False)
def test(index_t x):
    cdef index_t y = x // 2
    cdef MyStruct s
    s.a = x + y*1j
    return s.a
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/dotted_filenames.srctree0000644000175100001770000000062400000000000022443 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import a; assert a.a == 5"

######## setup.py ########

from setuptools import setup
from Cython.Build import cythonize

setup(
    name="My hello app",
    ext_modules=cythonize("a.pyx", include_path=['include']),
)

######## a.pyx ########

from test.ext cimport bar

a = bar()

######## include/test.ext.pxd ########

cdef inline int bar():
    return 5
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/double_dealloc_T796.pyx0000644000175100001770000000302400000000000021771 0ustar00runnerdocker00000000000000"""
Initial cleanup and 'calibration':
>>> _ = gc.collect()
>>> old_unreachable = gc.collect()

Test:
>>> x = SimpleGarbage()
SimpleGarbage(1) __cinit__
>>> del x
SimpleGarbage(1) __dealloc__
Collector.__dealloc__

Make sure nothing changed in the environment:
>>> new_unreachable = get_new_unreachable()
>>> new_unreachable == old_unreachable or (old_unreachable, new_unreachable)
True
"""

import gc

cdef Py_ssize_t new_unreachable = 0

def get_new_unreachable():
    return new_unreachable

cdef int counter = 0
cdef int next_counter():
    global counter
    counter += 1
    return counter

cdef class Collector:
    # Indirectly trigger garbage collection in SimpleGarbage deallocation.
    # The __dealloc__ method of SimpleGarbage won't trigger the bug as the
    # refcount is artificially inflated for the duration of that function.
    def __dealloc__(self):
        print "Collector.__dealloc__"
        global new_unreachable
        new_unreachable = gc.collect()

cdef class SimpleGarbage:
    cdef Collector c  # to participate in garbage collection
    cdef int index
    cdef bint deallocated
    def __cinit__(self):
        self.index = next_counter()
        self.c = Collector()
        print self, "__cinit__"
    def __dealloc__(self):
        print self, "__dealloc__"
        if self.deallocated:
            print "Double dealloc!"
        self.deallocated = True
        gc.collect()
    def __str__(self):
        return "SimpleGarbage(%s)" % self.index
    def __repr__(self):
        return "SimpleGarbage(%s)" % self.index
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/duplicate_keyword_in_call.py0000644000175100001770000000116200000000000023313 0ustar00runnerdocker00000000000000# mode: run
# tag: kwargs, call
# ticket: t717

def f(**kwargs):
    return sorted(kwargs.items())

def test_call(kwargs):
    """
    >>> kwargs = {'b' : 2}
    >>> f(a=1, **kwargs)
    [('a', 1), ('b', 2)]
    >>> test_call(kwargs)
    [('a', 1), ('b', 2)]

    >>> kwargs = {'a' : 2}
    >>> f(a=1, **kwargs)    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...got multiple values for keyword argument 'a'

    >>> test_call(kwargs)   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...got multiple values for keyword argument 'a'
    """
    return f(a=1, **kwargs)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/duplicate_utilitycode_from_pyx.srctree0000644000175100001770000000114500000000000025447 0ustar00runnerdocker00000000000000

PYTHON setup.py build_ext --inplace
PYTHON -c "import modb; modb.ClassB()"

#################### moda.pyx ####################

cdef class ClassA:
    cdef int[2] a

#################### modb.pyx #####################

from moda cimport ClassA

cdef class ClassB(ClassA):
    cdef int[2] b

###################### setup.py ###################

from setuptools import setup
from Cython.Build import cythonize
import Cython.Compiler.Options

Cython.Compiler.Options.cimport_from_pyx = True

setup(
        ext_modules = cythonize(["moda.pyx", "modb.pyx"],
            compiler_directives={'language_level': 3})
)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/dynamic_args.pyx0000644000175100001770000000075000000000000020746 0ustar00runnerdocker00000000000000# mode: run
# ticket: t674

cdef class Foo:
    cdef str name

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return '<%s>' % self.name

def test_exttype_args(a, b, c):
    """
    >>> f1 = test_exttype_args([1, 2, 3], 123, Foo('Foo'))
    >>> f2 = test_exttype_args([0], 0, Foo('Bar'))
    >>> f1()
    ([1, 2, 3], 123, )
    >>> f2()
    ([0], 0, )
    """
    def inner(a=a, int b=b, Foo c=c):
        return a, b, c
    return inner
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/dynamic_attributes.pxd0000644000175100001770000000005400000000000022150 0ustar00runnerdocker00000000000000cdef class MegaSpam:
    cdef dict __dict__
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/dynamic_attributes.pyx0000644000175100001770000000227500000000000022204 0ustar00runnerdocker00000000000000# mode: run

cimport cython

cdef class Spam:
    cdef dict __dict__

cdef class SuperSpam(Spam):
    pass

cdef class MegaSpam:
    pass

cdef public class UltraSpam [type UltraSpam_Type, object UltraSpam_Object]:
    cdef dict __dict__


cdef class OwnProperty1:
    """
    >>> obj = OwnProperty1()
    >>> assert obj.__dict__ == {'a': 123}
    """
    @property
    def __dict__(self):
        return {'a': 123}


cdef class OwnProperty2:
    """
    >>> obj = OwnProperty2()
    >>> assert obj.__dict__ == {'a': 123}
    """
    property __dict__:
        def __get__(self):
            return {'a': 123}


def test_class_attributes():
    """
    >>> test_class_attributes()
    'bar'
    """
    o = Spam()
    o.foo = "bar"
    return o.foo

def test_subclass_attributes():
    """
    >>> test_subclass_attributes()
    'bar'
    """
    o = SuperSpam()
    o.foo = "bar"
    return o.foo

def test_defined_class_attributes():
    """
    >>> test_defined_class_attributes()
    'bar'
    """
    o = MegaSpam()
    o.foo = "bar"
    return o.foo

def test_public_class_attributes():
    """
    >>> test_public_class_attributes()
    'bar'
    """
    o = UltraSpam()
    o.foo = "bar"
    return o.foo
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/ellipsis_T488.pyx0000644000175100001770000000054200000000000020660 0ustar00runnerdocker00000000000000# ticket: t488

"""
>>> test()
"""
def test():
    x = ...
    assert x is Ellipsis

    d = {}
    d[...] = 1
    assert d[...] == 1
    del d[...]
    assert ... not in d

    d[..., ...] = 1
    assert d[..., ...] == 1
    assert d[..., Ellipsis] == 1
    assert (Ellipsis, Ellipsis) in d
    del d[..., ...]
    assert (Ellipsis, Ellipsis) not in d

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/embedsignatures.pyx0000644000175100001770000003117600000000000021475 0ustar00runnerdocker00000000000000#cython: embedsignature=True, annotation_typing=False

# signatures here are a little fragile - when they are
# generated during the build process gives slightly
# different (but equivalent) forms - therefore tests
# may need changing occasionally to reflect behaviour
# and this isn't necessarily a bug

import sys

if sys.version_info >= (3, 4):
    def funcdoc(f):
        if not getattr(f, "__text_signature__", None):
            return f.__doc__
        doc = '%s%s' % (f.__name__, f.__text_signature__)
        if f.__doc__:
            if '\n' in f.__doc__:
                # preceding line endings get stripped
                doc = '%s\n\n%s' % (doc, f.__doc__)
            else:
                doc = '%s\n%s' % (doc, f.__doc__)
        return doc

else:
    def funcdoc(f):
        return f.__doc__


# note the r, we use \n below
__doc__ = ur"""
    >>> print (Ext.__doc__)
    Ext(a, b, c=None)

    >>> print (Ext.attr0.__doc__)
    attr0: 'int'
    attr0 docstring
    >>> print (Ext.attr1.__doc__)
    attr1: object
    attr1 docstring
    >>> print (Ext.attr2.__doc__)
    attr2: list
    >>> print (Ext.attr3.__doc__)
    attr3: embedsignatures.Ext

    >>> print (Ext.prop0.__doc__)
    prop0 docstring
    >>> print (Ext.prop1.__doc__)
    None
    >>> print (Ext.attr4.__doc__)
    attr4 docstring
    >>> print (Ext.attr5.__doc__)
    attr5: 'int'
    attr5 docstring

    >>> print (Ext.a.__doc__)
    Ext.a(self)

    >>> print (Ext.b.__doc__)
    Ext.b(self, a, b, c)

    >>> print (Ext.c.__doc__)
    Ext.c(self, a, b, c=1)

    >>> print (Ext.d.__doc__)
    Ext.d(self, a, b, *, c=88)

    >>> print (Ext.e.__doc__)
    Ext.e(self, a, b, c=88, **kwds)

    >>> print (Ext.f.__doc__)
    Ext.f(self, a, b, *, c, d=42)

    >>> print (Ext.g.__doc__)
    Ext.g(self, a, b, *, c, d=42, e=17, f, **kwds)

    >>> print (Ext.h.__doc__)
    Ext.h(self, a, b, *args, c, d=42, e=17, f, **kwds)

    >>> print (Ext.k.__doc__)
    Ext.k(self, a, b, c=1, *args, d=42, e=17, f, **kwds)

    >>> print (Ext.l.__doc__)
    Ext.l(self, a, b, c=1, *args, d=42, e=17, f, **kwds)
    Existing string

    >>> print (Ext.m.__doc__)
    Ext.m(self, a=u'spam', b='foo', c=b'bar')

    >>> print (Ext.n.__doc__)
    Ext.n(self, a: int, b: float = 1.0, *args: tuple, **kwargs: dict) -> (None, True)

    >>> print (Ext.o.__doc__)
    Ext.o(self, a, b=1, /, c=5, *args, **kwargs)

    >>> print (Ext.get_int.__doc__)
    Ext.get_int(self) -> int

    >>> print (Ext.get_float.__doc__)
    Ext.get_float(self) -> float

    >>> print (Ext.get_str.__doc__)
    Ext.get_str(self) -> str
    Existing string

    >>> print (Ext.clone.__doc__)
    Ext.clone(self) -> Ext

    >>> print (funcdoc(foo))
    foo()

    >>> funcdoc(with_doc_1)
    'with_doc_1(a, b, c)\nExisting string'

    >>> funcdoc(with_doc_2)
    'with_doc_2(a, b, c)\n\n    Existing string\n    '

    >>> funcdoc(with_doc_3)
    'with_doc_3(a, b, c)\nExisting string'

    >>> funcdoc(with_doc_4)
    'with_doc_4(int a, str b, list c) -> str\n\n    Existing string\n    '

    >>> funcdoc(f_sd)
    "f_sd(str s='spam')"

    >>> funcdoc(cf_sd)
    "cf_sd(str s='spam') -> str"

    >>> funcdoc(types)
    'types(Ext a, int b, unsigned short c, float d, e)'

    >>> print(funcdoc(f_c))
    f_c(char c) -> char

    >>> print(funcdoc(f_uc))
    f_uc(unsigned char c) -> unsigned char

    >>> print(funcdoc(f_sc))
    f_sc(signed char c) -> signed char

    >>> print(funcdoc(f_s))
    f_s(short s) -> short

    >>> print(funcdoc(f_us))
    f_us(unsigned short s) -> unsigned short


    >>> print(funcdoc(f_i))
    f_i(int i) -> int

    >>> print(funcdoc(f_ui))
    f_ui(unsigned int i) -> unsigned int

    >>> print(funcdoc(f_bint))
    f_bint(bool i) -> bool


    >>> print(funcdoc(f_l))
    f_l(long l) -> long

    >>> print(funcdoc(f_ul))
    f_ul(unsigned long l) -> unsigned long


    >>> print(funcdoc(f_L))
    f_L(long long L) -> long long

    >>> print(funcdoc(f_uL))
    f_uL(unsigned long long L) -> unsigned long long


    >>> print(funcdoc(f_f))
    f_f(float f) -> float

    >>> print(funcdoc(f_d))
    f_d(double d) -> double

    >>> print(funcdoc(f_D))
    f_D(long double D) -> long double

    >>> print(funcdoc(f_my_i))
    f_my_i(MyInt i) -> MyInt

    >>> print(funcdoc(f_my_f))
    f_my_f(MyFloat f) -> MyFloat

    >>> print(funcdoc(f_defexpr1))
    f_defexpr1(int x=FLAG1, int y=FLAG2)

    >>> print(funcdoc(f_defexpr2))
    f_defexpr2(int x=FLAG1 | FLAG2, y=FLAG1 & FLAG2)

    >>> print(funcdoc(f_defexpr3))
    f_defexpr3(int x=Ext.CONST1, f=__builtins__.abs)

    >>> print(funcdoc(f_defexpr4))
    f_defexpr4(int x=(Ext.CONST1 + FLAG1) * Ext.CONST2)

    >>> print(funcdoc(f_defexpr5))
    f_defexpr5(int x=2 + 2)

    >>> print(funcdoc(f_charptr_null))
    f_charptr_null(char *s=NULL) -> char *
"""

cdef class Ext:

    cdef public int  attr0
    """attr0 docstring"""
    cdef public      attr1
    """attr1 docstring"""
    cdef public list attr2
    cdef public Ext attr3

    """NOT attr3 docstring"""
    cdef        int  attr4
    cdef public int \
        attr5
    """attr5 docstring"""

    CONST1, CONST2 = 1, 2

    property prop0:
        """prop0 docstring"""
        def __get__(self):
            return self.attr0

    property prop1:
        def __get__(self):
            return self.attr1

    property attr4:
        """attr4 docstring"""
        def __get__(self):
            return self.attr4

    def __init__(self, a, b, c=None):
        pass

    def a(self):
        pass

    def b(self, a, b, c):
        pass

    def c(self, a, b, c=1):
        pass

    def d(self, a, b, *, c = 88):
        pass

    def e(self, a, b, c = 88, **kwds):
        pass

    def f(self, a, b, *, c, d = 42):
        pass

    def g(self, a, b, *, c, d = 42, e = 17, f, **kwds):
        pass

    def h(self, a, b, *args, c, d = 42, e = 17, f, **kwds):
        pass

    def k(self, a, b, c=1, *args, d = 42, e = 17, f, **kwds):
        pass

    def l(self, a, b, c=1, *args, d = 42, e = 17, f, **kwds):
        """Existing string"""
        pass

    def m(self, a=u'spam', b='foo', c=b'bar'):
        pass

    def n(self, a: int, b: float = 1.0, *args: tuple, **kwargs: dict) -> (None, True):
        pass

    def o(self, a, b=1, /, c=5, *args, **kwargs):
        pass

    cpdef int get_int(self):
        return 0

    cpdef float get_float(self):
        return 0.0

    cpdef str get_str(self):
        """Existing string"""
        return "string"

    cpdef Ext clone(self):
        return Ext(1,2)

def foo():
    pass

def types(Ext a, int b, unsigned short c, float d, e):
    pass

def with_doc_1(a, b, c):
    """Existing string"""
    pass

def with_doc_2(a, b, c):
    """
    Existing string
    """
    pass

cpdef with_doc_3(a, b, c):
    """Existing string"""
    pass

cpdef str with_doc_4(int a, str b, list c):
    """
    Existing string
    """
    return b

def f_sd(str s='spam'):
    return s

cpdef str cf_sd(str s='spam'):
    return s

cpdef char f_c(char c):
    return c

cpdef unsigned char f_uc(unsigned char c):
    return c

cpdef signed char f_sc(signed char c):
    return c


cpdef short f_s(short s):
    return s

cpdef unsigned short f_us(unsigned short s):
    return s


cpdef int f_i(int i):
    return i

cpdef unsigned int f_ui(unsigned int i):
    return i

cpdef bint f_bint(bint i):
    return i


cpdef long f_l(long l):
    return l

cpdef unsigned long f_ul(unsigned long l):
    return l


cpdef long long f_L(long long L):
    return L

cpdef unsigned long long f_uL(unsigned long long L):
    return L


cpdef float f_f(float f):
    return f

cpdef double f_d(double d):
    return d

cpdef long double f_D(long double D):
    return D

ctypedef int MyInt
cpdef MyInt f_my_i(MyInt i):
    return i

ctypedef float MyFloat
cpdef MyFloat f_my_f(MyFloat f):
    return f

cdef enum:
    FLAG1
    FLAG2

cpdef f_defexpr1(int x = FLAG1, int y = FLAG2):
    pass

cpdef f_defexpr2(int x = FLAG1 | FLAG2, y = FLAG1 & FLAG2):
    pass

cpdef f_defexpr3(int x = Ext.CONST1, f = __builtins__.abs):
    pass

cpdef f_defexpr4(int x = (Ext.CONST1 + FLAG1) * Ext.CONST2):
    pass

cpdef f_defexpr5(int x = 2+2):
    pass

cpdef (char*) f_charptr_null(char* s=NULL):
    return s or b'abc'


# no signatures for lambda functions
lambda_foo = lambda x: 10
lambda_bar = lambda x: 20


cdef class Foo:
    def __init__(self, *args, **kwargs): pass
    def m00(self, a: None) ->  None: pass
    def m01(self, a: ...) ->  Ellipsis: pass
    def m02(self, a: True, b: False) ->  bool: pass
    def m03(self, a: 42, b: +42, c: -42) ->  int : pass  # XXX +42 -> 42
    def m04(self, a: 3.14, b: +3.14, c: -3.14) -> float : pass
    def m05(self, a: 1 + 2j, b: +2j, c: -2j) -> complex : pass
    def m06(self, a: "abc", b: b"abc", c: u"abc") -> (str, bytes, unicode) : pass
    def m07(self, a: [1, 2, 3], b: []) -> list: pass
    def m08(self, a: (1, 2, 3), b: ()) -> tuple: pass
    def m09(self, a: {1, 2, 3}, b: {i for i in ()}) -> set: pass
    def m10(self, a: {1: 1, 2: 2, 3: 3}, b: {}) -> dict: pass
   #def m11(self, a: [str(i) for i in range(3)]): pass  # Issue 1782
    def m12(self, a: (str(i) for i in range(3))): pass
    def m13(self, a: (str(i) for i in range(3) if bool(i))): pass
    def m14(self, a: {str(i) for i in range(3)}): pass
    def m15(self, a: {str(i) for i in range(3) if bool(i)}): pass
    def m16(self, a: {str(i): id(i) for i in range(3)}): pass
    def m17(self, a: {str(i): id(i) for i in range(3) if bool(i)}): pass
    def m18(self, a: dict.update(x=42, **dict(), **{})): pass
    def m19(self, a: sys is None, b: sys is not None): pass
    def m20(self, a: sys in [], b: sys not in []): pass
    def m21(self, a: (sys or sys) and sys, b: not (sys or sys)): pass
    def m22(self, a: 42 if sys else None): pass
    def m23(self, a: +int(), b: -int(), c: ~int()): pass
    def m24(self, a: (1+int(2))*3+(4*int(5))**(1+0.0/1)): pass
    def m25(self, a: list(range(3))[:]): pass
    def m26(self, a: list(range(3))[1:]): pass
    def m27(self, a: list(range(3))[:1]): pass
    def m28(self, a: list(range(3))[::1]): pass
    def m29(self, a: list(range(3))[0:1:1]): pass
    def m30(self, a: list(range(3))[7, 3:2:1, ...]): pass
    def m31(self, double[::1] a): pass
    def m32(self, a: tuple[()]) -> tuple[tuple[()]]: pass

__doc__ += ur"""
>>> print(Foo.__doc__)
Foo(*args, **kwargs)
>>> assert Foo.__init__.__doc__ == type.__init__.__doc__

>>> print(Foo.m00.__doc__)
Foo.m00(self, a: None) -> None

>>> print(Foo.m01.__doc__)
Foo.m01(self, a: ...) -> Ellipsis

>>> print(Foo.m02.__doc__)
Foo.m02(self, a: True, b: False) -> bool

>>> print(Foo.m03.__doc__)
Foo.m03(self, a: 42, b: +42, c: -42) -> int

>>> print(Foo.m04.__doc__)
Foo.m04(self, a: 3.14, b: +3.14, c: -3.14) -> float

>>> print(Foo.m05.__doc__)
Foo.m05(self, a: 1 + 2j, b: +2j, c: -2j) -> complex

>>> print(Foo.m06.__doc__)
Foo.m06(self, a: 'abc', b: b'abc', c: 'abc') -> (str, bytes, unicode)

>>> print(Foo.m07.__doc__)
Foo.m07(self, a: [1, 2, 3], b: []) -> list

>>> print(Foo.m08.__doc__)
Foo.m08(self, a: (1, 2, 3), b: ()) -> tuple

>>> print(Foo.m09.__doc__)
Foo.m09(self, a: {1, 2, 3}, b: {i for i in ()}) -> set

>>> print(Foo.m10.__doc__)
Foo.m10(self, a: {1: 1, 2: 2, 3: 3}, b: {}) -> dict

# >>> print(Foo.m11.__doc__)
# Foo.m11(self, a: [str(i) for i in range(3)])

>>> print(Foo.m12.__doc__)
Foo.m12(self, a: (str(i) for i in range(3)))

>>> print(Foo.m13.__doc__)
Foo.m13(self, a: (str(i) for i in range(3) if bool(i)))

>>> print(Foo.m14.__doc__)
Foo.m14(self, a: {str(i) for i in range(3)})

>>> print(Foo.m15.__doc__)
Foo.m15(self, a: {str(i) for i in range(3) if bool(i)})

>>> print(Foo.m16.__doc__)
Foo.m16(self, a: {str(i): id(i) for i in range(3)})

>>> print(Foo.m17.__doc__)
Foo.m17(self, a: {str(i): id(i) for i in range(3) if bool(i)})

>>> print(Foo.m18.__doc__)
Foo.m18(self, a: dict.update(x=42, **dict()))

>>> print(Foo.m19.__doc__)
Foo.m19(self, a: sys is None, b: sys is not None)

>>> print(Foo.m20.__doc__)
Foo.m20(self, a: sys in [], b: sys not in [])

>>> print(Foo.m21.__doc__)
Foo.m21(self, a: (sys or sys) and sys, b: not (sys or sys))

>>> print(Foo.m22.__doc__)
Foo.m22(self, a: 42 if sys else None)

>>> print(Foo.m23.__doc__)
Foo.m23(self, a: +int(), b: -int(), c: ~int())

>>> print(Foo.m24.__doc__)
Foo.m24(self, a: (1 + int(2)) * 3 + (4 * int(5)) ** (1 + 0.0 / 1))

>>> print(Foo.m25.__doc__)
Foo.m25(self, a: list(range(3))[:])

>>> print(Foo.m26.__doc__)
Foo.m26(self, a: list(range(3))[1:])

>>> print(Foo.m27.__doc__)
Foo.m27(self, a: list(range(3))[:1])

>>> print(Foo.m28.__doc__)
Foo.m28(self, a: list(range(3))[::1])

>>> print(Foo.m29.__doc__)
Foo.m29(self, a: list(range(3))[0:1:1])

>>> print(Foo.m30.__doc__)
Foo.m30(self, a: list(range(3))[7, 3:2:1, ...])

>>> print(Foo.m31.__doc__)
Foo.m31(self, double[::1] a)

>>> print(Foo.m32.__doc__)
Foo.m32(self, a: tuple[()]) -> tuple[tuple[()]]

"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/embedsignatures_clinic.pyx0000644000175100001770000000420100000000000023003 0ustar00runnerdocker00000000000000# cython: embedsignature=True
# cython: embedsignature.format=clinic
# cython: annotation_typing=False
# cython: binding=False
# cython: c_string_type=bytearray
# tag: py3only

def f00(a, object b=42):
    "f00 docstring"
    pass

def f01(unsigned int a: int, unsigned int b: int = 42, /, c=123):
    "f01 docstring"
    pass

def f02(unsigned int a: float, *, unsigned int b: float = 42) -> tuple[int]:
    "f02 docstring"
    pass

__doc__ = ur"""
>>> print(f00.__doc__)
f00 docstring
>>> print(f00.__text_signature__)
(a, b=42)

>>> print(f01.__doc__)
f01 docstring
>>> print(f01.__text_signature__)
(a, b=42, /, c=123)

>>> print(f02.__doc__)
f02 docstring
>>> print(f02.__text_signature__)
(a, *, b=42)

"""


cdef class Foo:
    "Foo docstring"

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        "init Foo"
        pass

    def m00(self, a, b=42, *args, c=123):
        "m00 docstring"
        pass

    def m01(self, a, b=42, *, c=123, **kwargs):
        "m01 docstring"
        pass

    @classmethod
    def c00(cls, a):
        "c00 docstring"
        pass

    @staticmethod
    def s00(a):
        "s00 docstring"
        pass

    cdef public long int p0
    property p1:
        "p1 docstring"
        def __get__(self):
            return 0
    property p2:
        "p2 docstring"
        def __get__(self) -> int:
            return 0
    cdef public Foo p3


__doc__ += ur"""
>>> print(Foo.__doc__)
Foo docstring
>>> print(Foo.__init__.__doc__)
init Foo
>>> print(Foo.__init__.__text_signature__)
($self, *args, **kwargs)

"""

__doc__ += ur"""
>>> print(Foo.m00.__doc__)
m00 docstring
>>> print(Foo.m00.__text_signature__)
($self, a, b=42, *args, c=123)

>>> print(Foo.m01.__doc__)
m01 docstring
>>> print(Foo.m01.__text_signature__)
($self, a, b=42, *, c=123, **kwargs)

"""

__doc__ += ur"""
>>> print(Foo.c00.__doc__)
c00 docstring
>>> print(Foo.c00.__text_signature__)
($type, a)

>>> print(Foo.s00.__doc__)
s00 docstring
>>> print(Foo.s00.__text_signature__)
(a)

"""


__doc__ += ur"""
>>> print(Foo.p0.__doc__)
None

>>> print(Foo.p1.__doc__)
p1 docstring

>>> print(Foo.p2.__doc__)
p2 docstring

>>> print(Foo.p3.__doc__)
None

"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/embedsignatures_python.pyx0000644000175100001770000001403400000000000023070 0ustar00runnerdocker00000000000000# cython: embedsignature=True
# cython: embedsignature.format=python
# cython: annotation_typing=False
# cython: c_string_type=bytearray

cpdef object      f00(object a): return a
cpdef long double f01(unsigned int a): return a
cpdef long double f02(unsigned int a: float): return a

__doc__ = ur"""
>>> print(f00.__doc__)
f00(a)

>>> print(f01.__doc__)
f01(a: int) -> float

>>> print(f02.__doc__)
f02(a: float) -> float

"""


cdef class Foo:
    "Foo docstring"

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        "init Foo"
        pass

    def m00(self, a): return a
    def m01(self, unsigned int a): return a
    def m02(self, unsigned int a: int): return a
    def m03(self: Self, unsigned int a: int) -> float: return a
    def m04(self, const char* a): return a
    def m05(self, const char a[]): return a
    def m06(self, const char* a: bytes) -> bytes: return a

    @classmethod
    def c00(cls, a): return a
    @classmethod
    def c01(type cls, unsigned int a): return a
    @classmethod
    def c02(cls: type[Foo], unsigned int a: int): return a
    @classmethod
    def c03(type cls: type[Foo], unsigned int a: int) -> float: return a

    @staticmethod
    def s00(a): return a
    @staticmethod
    def s01(unsigned int a): return a
    @staticmethod
    def s02(unsigned int a: int): return a
    @staticmethod
    def s03(unsigned int a: int) -> float: return a

    cdef public long int p0
    property p1:
        """p1 docstring"""
        def __get__(self):
            return 0
    property p2:
        """p2 docstring"""
        def __get__(self) -> int:
            return 0
    cdef public Foo p3


__doc__ += ur"""
>>> print(Foo.__doc__)
Foo docstring
>>> print(Foo.__init__.__doc__)
__init__(self, *args: Any, **kwargs: Any) -> None
init Foo

"""

__doc__ += ur"""
>>> print(Foo.m00.__doc__)
m00(self, a)

>>> print(Foo.m01.__doc__)
m01(self, a: int)

>>> print(Foo.m02.__doc__)
m02(self, a: int)

>>> print(Foo.m03.__doc__)
m03(self: Self, a: int) -> float

>>> print(Foo.m04.__doc__)
m04(self, a: bytearray)

>>> print(Foo.m05.__doc__)
m05(self, a: bytearray)

>>> print(Foo.m06.__doc__)
m06(self, a: bytes) -> bytes

"""

__doc__ += ur"""
>>> print(Foo.c00.__doc__)
c00(cls, a)

>>> print(Foo.c01.__doc__)
c01(cls, a: int)

>>> print(Foo.c02.__doc__)
c02(cls: type[Foo], a: int)

>>> print(Foo.c03.__doc__)
c03(cls: type[Foo], a: int) -> float

"""

__doc__ += ur"""
>>> print(Foo.s00.__doc__)
s00(a)

>>> print(Foo.s01.__doc__)
s01(a: int)

>>> print(Foo.s02.__doc__)
s02(a: int)

>>> print(Foo.s03.__doc__)
s03(a: int) -> float

"""

__doc__ += ur"""
>>> print(Foo.p0.__doc__)
p0: int

>>> print(Foo.p1.__doc__)
p1 docstring

>>> print(Foo.p2.__doc__)
p2: int
p2 docstring

>>> print(Foo.p3.__doc__)
p3: Foo

"""

ctypedef long     long      LongLong
ctypedef signed   long long LongLongSigned
ctypedef unsigned long long LongLongUnsigned

cdef class Bar:

    cpdef          char       m00(self,          char       a): return a
    cpdef signed   char       m01(self, signed   char       a): return a
    cpdef unsigned char       m02(self, unsigned char       a): return a

    cpdef          short      m10(self,          short      a): return a
    cpdef signed   short      m11(self, signed   short      a): return a
    cpdef unsigned short      m12(self, unsigned short      a): return a

    cpdef          int        m20(self,          int        a): return a
    cpdef signed   int        m21(self, signed   int        a): return a
    cpdef unsigned int        m22(self, unsigned int        a): return a

    cpdef          long       m30(self,          long       a): return a
    cpdef signed   long       m31(self, signed   long       a): return a
    cpdef unsigned long       m32(self, unsigned long       a): return a

    cpdef          long long  m40(self,          long long  a): return a
    cpdef signed   long long  m41(self, signed   long long  a): return a
    cpdef unsigned long long  m42(self, unsigned long long  a): return a

    cpdef LongLong            m43(self, LongLong            a): return a
    cpdef LongLongSigned      m44(self, LongLongSigned      a): return a
    cpdef LongLongUnsigned    m45(self, LongLongUnsigned    a): return a

    cpdef float               m50(self, float               a): return a
    cpdef double              m60(self, double              a): return a
    cpdef long double         m70(self, long double         a): return a

    cpdef float       complex m51(self, float       complex a): return a
    cpdef double      complex m61(self, double      complex a): return a
    cpdef long double complex m71(self, long double complex a): return a


__doc__ += ur"""
>>> print(Bar.m00.__doc__)
m00(self, a: int) -> int

>>> print(Bar.m01.__doc__)
m01(self, a: int) -> int

>>> print(Bar.m02.__doc__)
m02(self, a: int) -> int

"""

__doc__ += ur"""
>>> print(Bar.m10.__doc__)
m10(self, a: int) -> int

>>> print(Bar.m11.__doc__)
m11(self, a: int) -> int

>>> print(Bar.m12.__doc__)
m12(self, a: int) -> int

"""

__doc__ += ur"""
>>> print(Bar.m20.__doc__)
m20(self, a: int) -> int

>>> print(Bar.m21.__doc__)
m21(self, a: int) -> int

>>> print(Bar.m22.__doc__)
m22(self, a: int) -> int

"""

__doc__ += ur"""
>>> print(Bar.m30.__doc__)
m30(self, a: int) -> int

>>> print(Bar.m31.__doc__)
m31(self, a: int) -> int

>>> print(Bar.m32.__doc__)
m32(self, a: int) -> int

"""

__doc__ += ur"""
>>> print(Bar.m40.__doc__)
m40(self, a: int) -> int

>>> print(Bar.m41.__doc__)
m41(self, a: int) -> int

>>> print(Bar.m42.__doc__)
m42(self, a: int) -> int

"""

__doc__ += ur"""
>>> print(Bar.m43.__doc__)
m43(self, a: int) -> int

>>> print(Bar.m44.__doc__)
m44(self, a: int) -> int

>>> print(Bar.m45.__doc__)
m45(self, a: int) -> int

"""

__doc__ += ur"""
>>> print(Bar.m50.__doc__)
m50(self, a: float) -> float

>>> print(Bar.m60.__doc__)
m60(self, a: float) -> float

>>> print(Bar.m70.__doc__)
m70(self, a: float) -> float

"""

__doc__ += ur"""
>>> print(Bar.m51.__doc__)
m51(self, a: complex) -> complex

>>> print(Bar.m61.__doc__)
m61(self, a: complex) -> complex

>>> print(Bar.m71.__doc__)
m71(self, a: complex) -> complex

"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/empty_builtin_constructors.pyx0000644000175100001770000000245100000000000024022 0ustar00runnerdocker00000000000000
cimport cython
import sys

IS_PY3 = sys.version_info[0] >= 3

def _bool():
    """
    >>> _bool() == bool()
    True
    """
    return bool()

def _int():
    """
    >>> _int() == int()
    True
    """
    return int()

def _long():
    """
    >>> IS_PY3 or _long() == long()
    True
    """
    return long()

def _float():
    """
    >>> _float() == float()
    True
    """
    return float()

def _complex():
    """
    >>> _complex() == complex()
    True
    """
    return complex()

def _bytes():
    """
    >>> IS_PY3 and _bytes() == bytes() or _bytes() == str()
    True
    """
    return bytes()

def _str():
    """
    >>> _str() == str()
    True
    """
    return str()

def _unicode():
    """
    >>> IS_PY3 and _unicode() == str() or _unicode() == unicode()
    True
    """
    return unicode()

def _tuple():
    """
    >>> _tuple() == tuple()
    True
    """
    return tuple()

def _list():
    """
    >>> _list() == list()
    True
    """
    return list()

def _dict():
    """
    >>> _dict() == dict()
    True
    """
    return dict()

py_set = cython.set

def _set():
    """
    >>> _set() == py_set()
    True
    """
    return set()

py_frozenset = cython.frozenset

def _frozenset():
    """
    >>> _frozenset() == py_frozenset()
    True
    """
    return frozenset()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/empty_declarators.pyx0000644000175100001770000000022500000000000022024 0ustar00runnerdocker00000000000000cpdef zed(short, long, complex, x):
    """
    >>> zed(short=1, long=2, complex=3, x=4)
    (1, 2, 3, 4)
    """
    return short, long, complex, x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/empty_for_loop_T208.pyx0000644000175100001770000000045000000000000022055 0ustar00runnerdocker00000000000000# ticket: t208

def go_py_empty():
    """
    >>> go_py_empty()
    20
    """
    i = 20
    for i in range(4,0):
        print u"Spam!"
    return i

def go_c_empty():
    """
    >>> go_c_empty()
    20
    """
    cdef int i = 20
    for i in range(4,0):
        print u"Spam!"
    return i
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/enumboolctx.pyx0000644000175100001770000000124600000000000020646 0ustar00runnerdocker00000000000000cdef public enum Truth:
   FALSE=0
   TRUE=1

def enum_boolctx(Truth arg):
    """
    >>> enum_boolctx(FALSE)
    False
    >>> enum_boolctx(TRUE)
    True
    """
    if arg:
        return True
    else:
        return False

cdef extern from *:
    enum: FALSE_VALUE "(0)"
    enum: TRUE_VALUE "(1)"

def extern_enum_false():
    """
    >>> extern_enum_false()
    """
    if FALSE_VALUE:
        raise ValueError

def extern_enum_true():
    """
    >>> extern_enum_true()
    """
    if not TRUE_VALUE:
        raise ValueError

def extern_enum_false_true():
    """
    >>> extern_enum_false_true()
    """
    if not TRUE_VALUE or FALSE_VALUE:
        raise ValueError
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/enumerate_T316.pyx0000644000175100001770000001116500000000000021012 0ustar00runnerdocker00000000000000# ticket: t316

cimport cython

@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode[@name = 'enumerate']")
def go_py_enumerate():
    """
    >>> go_py_enumerate()
    0 1
    1 2
    2 3
    3 4
    """
    for i,k in enumerate(range(1,5)):
        print i, k

@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode[@name = 'enumerate']")
def py_enumerate_list_index_target():
    """
    >>> py_enumerate_list_index_target()
    [0] 1
    [1] 2
    [2] 3
    [3] 4
    """
    target = [None]
    for target[0],k in enumerate(range(1,5)):
        print target, k

@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode[@name = 'enumerate']")
def go_py_enumerate_start():
    """
    >>> go_py_enumerate_start()
    5 1
    6 2
    7 3
    8 4
    """
    for i,k in enumerate(range(1,5), 5):
        print i, k

@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode[@name = 'enumerate']")
def go_c_enumerate():
    """
    >>> go_c_enumerate()
    0 1
    1 2
    2 3
    3 4
    """
    cdef int i,k
    for i,k in enumerate(range(1,5)):
        print i, k

@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode[@name = 'enumerate']")
def c_enumerate_carray_target():
    """
    >>> c_enumerate_carray_target()
    0 1
    1 2
    2 3
    3 4
    """
    cdef int k
    cdef int[1] i
    for i[0],k in enumerate(range(1,5)):
        print i[0], k

@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode[@name = 'enumerate']")
def go_c_enumerate_step():
    """
    >>> go_c_enumerate_step()
    0 1
    1 3
    2 5
    """
    cdef int i,k
    for i,k in enumerate(range(1,7,2)):
        print i, k

@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode[@name = 'enumerate']")
def py_enumerate_dict(dict d):
    """
    >>> py_enumerate_dict({})
    :: 55 99
    >>> py_enumerate_dict(dict(a=1, b=2, c=3))
    0 True
    1 True
    2 True
    :: 2 True
    """
    cdef int i = 55
    k = 99
    keys = list(d.keys())
    for i,k in enumerate(d):
        k = keys[i] == k
        print i, k
    print u"::", i, k

@cython.test_fail_if_path_exists("//SimpleCallNode")
def py_enumerate_break(*t):
    """
    >>> py_enumerate_break(1,2,3,4)
    0 1
    :: 0 1
    """
    i,k = 55,99
    for i,k in enumerate(t):
        print i, k
        break
    print u"::", i, k

@cython.test_fail_if_path_exists("//SimpleCallNode")
def py_enumerate_return(*t):
    """
    >>> py_enumerate_return()
    :: 55 99
    >>> py_enumerate_return(1,2,3,4)
    0 1
    """
    i,k = 55,99
    for i,k in enumerate(t):
        print i, k
        return
    print u"::", i, k

@cython.test_fail_if_path_exists("//SimpleCallNode")
def py_enumerate_continue(*t):
    """
    >>> py_enumerate_continue(1,2,3,4)
    0 1
    1 2
    2 3
    3 4
    :: 3 4
    """
    i,k = 55,99
    for i,k in enumerate(t):
        print i, k
        continue
    print u"::", i, k

@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode[@name = 'enumerate']")
def empty_c_enumerate():
    """
    >>> empty_c_enumerate()
    (55, 99)
    """
    cdef int i = 55, k = 99
    for i,k in enumerate(range(0)):
        print i, k
    return i, k

# not currently optimised
def single_target_enumerate():
    """
    >>> single_target_enumerate()
    0 1
    1 2
    2 3
    3 4
    """
    for t in enumerate(range(1,5)):
        print t[0], t[1]

@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode[@name = 'enumerate']")
def multi_enumerate():
    """
    >>> multi_enumerate()
    0 0 0 1
    1 1 1 2
    2 2 2 3
    3 3 3 4
    """
    for a,(b,(c,d)) in enumerate(enumerate(enumerate(range(1,5)))):
        print a,b,c,d

@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode[@name = 'enumerate']")
def multi_enumerate_start():
    """
    >>> multi_enumerate_start()
    0 2 0 1
    1 3 1 2
    2 4 2 3
    3 5 3 4
    """
    for a,(b,(c,d)) in enumerate(enumerate(enumerate(range(1,5)), 2)):
        print a,b,c,d

@cython.test_fail_if_path_exists("//SimpleCallNode")
def multi_c_enumerate():
    """
    >>> multi_c_enumerate()
    0 0 0 1
    1 1 1 2
    2 2 2 3
    3 3 3 4
    """
    cdef int a,b,c,d
    for a,(b,(c,d)) in enumerate(enumerate(enumerate(range(1,5)))):
        print a,b,c,d

@cython.test_fail_if_path_exists("//SimpleCallNode")
def convert_target_enumerate(L):
    """
    >>> convert_target_enumerate([2,3,5])
    0 2
    1 3
    2 5
    """
    cdef int a,b
    for a, b in enumerate(L):
        print a,b

@cython.test_fail_if_path_exists("//SimpleCallNode")
def convert_target_enumerate_start(L, int n):
    """
    >>> convert_target_enumerate_start([2,3,5], 3)
    3 2
    4 3
    5 5
    """
    cdef int a,b
    for a, b in enumerate(L, n):
        print a,b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/error_pos.srctree0000644000175100001770000000121600000000000021145 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON test_error_pos.py

######## setup.py ###########
from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules=cythonize("error_pos.pyx"))

######## error_pos.pyx ###########
from os import *

abcdefg(line)

######## test_error_pos.py ###########
import subprocess
import sys

cmd = [sys.executable, '-c', 'import error_pos']
proc = subprocess.Popen(cmd, stderr=subprocess.PIPE)
_, err = proc.communicate()
# The error should contain the line number and the line text where the
# undefined identifier is used.
assert b'line 3, in init error_pos' in err and b'abcdefg(line)' in err, err
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/eval.pyx0000644000175100001770000000070100000000000017231 0ustar00runnerdocker00000000000000# mode: run
# tag: eval

GLOBAL = 123

def eval_simple(local):
    """
    >>> eval_simple(321)
    (123, 321)
    """
    return eval('GLOBAL, local')

def eval_class_scope():
    """
    >>> eval_class_scope().c
    3
    """
    class TestClassScope:
        a = 1
        b = 2
        c = eval('a + b')
    return TestClassScope

def eval_locals(a, b):
    """
    >>> eval_locals(1, 2)
    (1, 2)
    """
    return eval('a, b', {}, locals())
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/exarkun.pyx0000644000175100001770000000112100000000000017754 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> p = Point(1,2,3)
    >>> p.gettuple()
    (1.0, 2.0, 3.0)
    >>> q = p + Point(2,3,4)
    >>> q.gettuple()
    (3.0, 5.0, 7.0)
    >>> p.gettuple()
    (1.0, 2.0, 3.0)
"""

cdef class Point:
    cdef double x, y, z
    def __init__(self, double x, double y, double z):
        self.x = x
        self.y = y
        self.z = z

    # XXX: originally, this said "def __add__(self, other)"
    def __add__(Point self, Point other):
        return Point(self.x + other.x, self.y + other.y, self.z + other.z)

    def gettuple(self):
        return (self.x, self.y, self.z)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/exceptionpropagation.pyx0000644000175100001770000000564200000000000022555 0ustar00runnerdocker00000000000000cdef int CHKERR(int ierr) except -1:
    if ierr==0: return 0
    raise RuntimeError

cdef int obj2int(object ob) except *:
    return ob

def foo(a):
    """
    >>> foo(0)
    >>> foo(1)
    Traceback (most recent call last):
    RuntimeError
    """
    cdef int i = obj2int(a)
    CHKERR(i)

cdef int* except_expr(bint fire) except -1:
    if fire:
        raise RuntimeError

def test_except_expr(bint fire):
    """
    >>> test_except_expr(False)
    >>> test_except_expr(True)
    Traceback (most recent call last):
    ...
    RuntimeError
    """
    except_expr(fire)

cdef double except_big_result(bint fire) except 100000000000000000000000000000000:
    if fire:
        raise RuntimeError

def test_except_big_result(bint fire):
    """
    >>> test_except_big_result(False)
    >>> test_except_big_result(True)
    Traceback (most recent call last):
    ...
    RuntimeError
    """
    except_big_result(fire)


cdef unsigned short except_promotion_compare(bint fire) except *:
    if fire:
        raise RuntimeError

def test_except_promotion_compare(bint fire):
    """
    >>> test_except_promotion_compare(False)
    >>> test_except_promotion_compare(True)
    Traceback (most recent call last):
    ...
    RuntimeError
    """
    except_promotion_compare(fire)


cdef int cdef_function_that_raises():
    raise RuntimeError

cdef int cdef_noexcept_function_that_raises() noexcept:
    raise RuntimeError

def test_except_raise_by_default():
    """
    >>> test_except_raise_by_default()
    Traceback (most recent call last):
    ...
    RuntimeError
    """
    cdef_function_that_raises()

def test_noexcept():
    """
    >>> test_noexcept()
    """
    cdef_noexcept_function_that_raises()


cdef int* cdef_ptr_func(int* input, int failure_mode):
    # should have except NULL? by default
    # failure mode is 0, 1, or 2
    if failure_mode == 0:
        return input  # don't fail
    elif failure_mode == 1:
        return NULL  # no exception
    else:
        raise RuntimeError("help!")

ctypedef int* (*cdef_ptr_func_ptr)(int*, int) except? NULL

def test_ptr_func(int failure_mode):
    """
    >>> test_ptr_func(0)
    100
    >>> test_ptr_func(1)
    NULL
    >>> test_ptr_func(2)
    exception
    """
    # check that the signature is what we think it is
    cdef cdef_ptr_func_ptr fptr = cdef_ptr_func
    cdef int a = 100
    try:
        out = fptr(&a, failure_mode)
        if out:
            return out[0]
        else:
            print("NULL")
    except RuntimeError:
        print("exception")

def test_ptr_func2(int failure_mode):
    """
    >>> test_ptr_func(0)
    100
    >>> test_ptr_func(1)
    NULL
    >>> test_ptr_func(2)
    exception
    """
    # as above, but don't go through a function pointer
    cdef int a = 100
    try:
        out = cdef_ptr_func(&a, failure_mode)
        if out:
            return out[0]
        else:
            print("NULL")
    except RuntimeError:
        print("exception")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/exceptionrefcount.pyx0000644000175100001770000000303600000000000022052 0ustar00runnerdocker00000000000000# mode: run

"""
>>> class SampleException(Exception): pass

>>> def assert_refcount(rc1, rc2, func):
...     # test ref-counts, but allow a bit of freedom
...     assert rc2 <= rc1 + 4, "%s, before: %d, after %d" % (
...         func.__name__, rc1, rc2)

>>> def run_test(repeat, test_func):
...     initial_refcount = get_refcount(SampleException)
...     for i in range(repeat):
...         try: raise SampleException
...         except:
...             refcount1 = get_refcount(SampleException)
...             test_func()
...             refcount2 = get_refcount(SampleException)
...
...             assert_refcount(refcount1, refcount2, test_func)
...             assert_refcount(initial_refcount, refcount2, test_func)
...         refcount3 = get_refcount(SampleException)
...         assert_refcount(refcount1, refcount3, test_func)
...         assert_refcount(initial_refcount, refcount3, test_func)

>>> run_test(50, test_no_exception_else)
>>> run_test(50, test_no_exception)
>>> run_test(50, test_exception)
>>> run_test(50, test_finally)
"""

cimport cython
from cpython.ref cimport PyObject

@cython.binding(False)
@cython.always_allow_keywords(False)
def get_refcount(obj):
    return (obj).ob_refcnt

def test_no_exception():
    try:
        a = 1+1
    except:
        pass

def test_no_exception_else():
    try:
        a = 1+1
    except:
        pass
    else:
        b = 1+1

def test_exception():
    try:
        raise TypeError
    except:
        pass

def test_finally():
    try:
        a = 1+1
    finally:
        b = 1+1
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/exceptions_nogil.pyx0000644000175100001770000001557100000000000021666 0ustar00runnerdocker00000000000000# mode: run
# tag: nogil, withgil, exceptions

cdef void foo_nogil(int i) except * nogil:
    if i != 0: raise ValueError("huhu !")


cdef void foo(int i) except * with gil:
    if i != 0: raise ValueError


cdef int bar(int i) except? -1 with gil:
    if i != 0: raise ValueError
    return 0


cdef int spam(int i) except? -1 with gil:
    if i != 0: raise TypeError
    return -1


def test_foo_nogil():
    """
    >>> test_foo_nogil()
    """
    #
    foo_nogil(0)
    foo_nogil(0)
    with nogil:
        foo_nogil(0)
        foo_nogil(0)
    #
    try:
        with nogil:
            foo_nogil(0)
    finally:
        pass
    #
    try:
        with nogil:
            foo_nogil(0)
        with nogil:
            foo_nogil(0)
    finally:
        pass
    #
    try:
        with nogil:
            foo_nogil(0)
        with nogil:
            foo_nogil(1)
    except:
        with nogil:
            foo_nogil(0)
    finally:
        with nogil:
            foo_nogil(0)
        pass
    #
    try:
        with nogil:
            foo_nogil(0)
            foo_nogil(0)
    finally:
        pass
    #
    try:
        with nogil:
            foo_nogil(0)
            foo_nogil(1)
    except:
        with nogil:
            foo_nogil(0)
    finally:
        with nogil:
            foo_nogil(0)
        pass
    #
    try:
        with nogil:
            foo_nogil(0)
        try:
            with nogil:
                foo_nogil(1)
        except:
            with nogil:
                foo_nogil(1)
        finally:
            with nogil:
                foo_nogil(0)
            pass
    except:
        with nogil:
            foo_nogil(0)
    finally:
        with nogil:
            foo_nogil(0)
        pass
    #
    try:
        with nogil:
            foo_nogil(0)
        try:
            with nogil:
                foo_nogil(1)
        except:
            with nogil:
                foo_nogil(1)
        finally:
            with nogil:
                foo_nogil(1)
            pass
    except:
        with nogil:
            foo_nogil(0)
    finally:
        with nogil:
            foo_nogil(0)
        pass
    #


def test_foo():
    """
    >>> test_foo()
    """
    #
    foo(0)
    foo(0)
    with nogil:
        foo(0)
        foo(0)
    #
    try:
        with nogil:
            foo(0)
    finally:
        pass
    #
    try:
        with nogil:
            foo(0)
        with nogil:
            foo(0)
    finally:
        pass
    #
    try:
        with nogil:
            foo(0)
        with nogil:
            foo(1)
    except:
        with nogil:
            foo(0)
    finally:
        with nogil:
            foo(0)
        pass
    #
    try:
        with nogil:
            foo(0)
            foo(0)
    finally:
        pass
    #
    try:
        with nogil:
            foo(0)
            foo(1)
    except:
        with nogil:
            foo(0)
    finally:
        with nogil:
            foo(0)
        pass
    #
    try:
        with nogil:
            foo(0)
        try:
            with nogil:
                foo(1)
        except:
            with nogil:
                foo(1)
        finally:
            with nogil:
                foo(0)
            pass
    except:
        with nogil:
            foo(0)
    finally:
        with nogil:
            foo(0)
        pass
    #
    try:
        with nogil:
            foo(0)
        try:
            with nogil:
                foo(1)
        except:
            with nogil:
                foo(1)
        finally:
            with nogil:
                foo(1)
            pass
    except:
        with nogil:
            foo(0)
    finally:
        with nogil:
            foo(0)
        pass
    #


def test_bar():
    """
    >>> test_bar()
    """
    #
    bar(0)
    bar(0)
    with nogil:
        bar(0)
        bar(0)
    #
    try:
        with nogil:
            bar(0)
    finally:
        pass
    #
    try:
        with nogil:
            bar(0)
        with nogil:
            bar(0)
    finally:
        pass
    #
    try:
        with nogil:
            bar(0)
        with nogil:
            bar(1)
    except ValueError:
        with nogil:
            bar(0)
    finally:
        with nogil:
            bar(0)
        pass
    #
    try:
        with nogil:
            bar(0)
            bar(0)
    finally:
        pass
    #
    try:
        with nogil:
            bar(0)
            bar(1)
    except ValueError:
        with nogil:
            bar(0)
    finally:
        with nogil:
            bar(0)
        pass
    #
    try:
        with nogil:
            bar(0)
        try:
            with nogil:
                bar(1)
        except ValueError:
            with nogil:
                bar(1)
        finally:
            with nogil:
                bar(0)
            pass
    except ValueError:
        with nogil:
            bar(0)
    finally:
        with nogil:
            bar(0)
        pass
    #
    try:
        with nogil:
            bar(0)
        try:
            with nogil:
                bar(1)
        except ValueError:
            with nogil:
                bar(1)
        finally:
            with nogil:
                bar(1)
            pass
    except ValueError:
        with nogil:
            bar(0)
    finally:
        with nogil:
            bar(0)
        pass
    #

def test_spam():
    """
    >>> test_spam()
    """
    #
    spam(0)
    spam(0)
    with nogil:
        spam(0)
        spam(0)
    #
    try:
        with nogil:
            spam(0)
    finally:
        pass
    #
    try:
        with nogil:
            spam(0)
        with nogil:
            spam(0)
    finally:
        pass
    #
    try:
        with nogil:
            spam(0)
        with nogil:
            spam(1)
    except TypeError:
        with nogil:
            spam(0)
    finally:
        with nogil:
            spam(0)
        pass
    #
    try:
        with nogil:
            spam(0)
            spam(0)
    finally:
        pass
    #
    try:
        with nogil:
            spam(0)
            spam(1)
    except TypeError:
        with nogil:
            spam(0)
    finally:
        with nogil:
            spam(0)
        pass
    #
    try:
        with nogil:
            spam(0)
        try:
            with nogil:
                spam(1)
        except TypeError:
            with nogil:
                spam(1)
        finally:
            with nogil:
                spam(0)
            pass
    except TypeError:
        with nogil:
            spam(0)
    finally:
        with nogil:
            spam(0)
        pass
    #
    try:
        with nogil:
            spam(0)
        try:
            with nogil:
                spam(1)
        except TypeError:
            with nogil:
                spam(1)
        finally:
            with nogil:
                spam(1)
            pass
    except TypeError:
        with nogil:
            spam(0)
    finally:
        with nogil:
            spam(0)
        pass
    #
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/exec_noargs.pyx0000644000175100001770000000076400000000000020610 0ustar00runnerdocker00000000000000# mode: run
# tag: exec

exec "GLOBAL = 1234"

def exec_module_scope():
    """
    >>> globals()['GLOBAL']
    1234
    """

def exec_func_scope():
    """
    >>> sorted(exec_func_scope().items())
    [('G', 1234), ('a', 'b')]
    """
    d = {}
    exec "d['a'] = 'b'; d['G'] = GLOBAL"
    return d

def exec_pyclass_scope():
    """
    >>> obj = exec_pyclass_scope()
    >>> obj.a
    'b'
    >>> obj.G
    1234
    """
    class TestExec:
        exec "a = 'b'; G = GLOBAL"
    return TestExec
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/exectest.pyx0000644000175100001770000000632400000000000020135 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*-

__doc__ = u"""
#>>> a
#Traceback (most recent call last):
#NameError: name 'a' is not defined
#>>> test_module_scope()
#>>> a
"""

#def test_module_scope():
#    exec "a=1+1"
#    return __dict__['a']

def test_dict_scope1():
    """
    >>> test_dict_scope1()
    2
    """
    cdef dict d = {}
    exec u"b=1+1" in d
    return d[u'b']

def test_dict_scope2(d):
    """
    >>> d = {}
    >>> test_dict_scope2(d)
    >>> d['b']
    2
    """
    exec u"b=1+1" in d

def test_dict_scope3(d1, d2):
    """
    >>> d1 = {}
    >>> test_dict_scope3(d1, d1)
    >>> d1['b']
    2

    >>> d1, d2 = {}, {}
    >>> test_dict_scope3(d1, d2)
    >>> (d1.get('b'), d2.get('b'))
    (None, 2)

    >>> d1, d2 = {}, {}
    >>> test_dict_scope3(d1, d2)
    >>> (d1.get('b'), d2.get('b'))
    (None, 2)
    """
    exec u"b=1+1" in d1, d2

def test_dict_scope_ref(d1, d2):
    """
    >>> d1, d2 = dict(a=11), dict(c=5)
    >>> test_dict_scope_ref(d1, d2)
    >>> (d1.get('b'), d2.get('b'))
    (None, 16)

    >>> d = dict(a=11, c=5)
    >>> test_dict_scope_ref(d, d)
    >>> d['b']
    16

    >>> d1, d2 = {}, {}
    >>> test_dict_scope_ref(d1, d2)         # doctest: +ELLIPSIS
    Traceback (most recent call last):
    NameError: ...name 'a' is not defined
    """
    exec u"b=a+c" in d1, d2

def test_dict_scope_tuple2():
    """
    >>> test_dict_scope_tuple2()
    2
    """
    cdef dict d = {}
    exec(u"b=1+1", d)   # Py3 compatibility syntax
    return d[u'b']

def test_dict_scope_tuple3(d1, d2):
    """
    >>> d1, d2 = {}, {}
    >>> test_dict_scope_tuple3(d1, d2)
    >>> (d1.get('b'), d2.get('b'))
    (None, 2)
    """
    exec(u"b=1+1", d1, d2)

def test_def(d, varref):
    """
    >>> d = dict(seq = [1,2,3,4])
    >>> add_iter = test_def(d, 'seq')
    >>> list(add_iter())
    [2, 3, 4, 5]
    """
    exec u"""
def test():
    for x in %s:
        yield x+1
""" % varref in d
    return d[u'test']

import sys

def test_encoding(d1, d2):
    u"""
    >>> d = {}
    >>> test_encoding(d, None)
    >>> print(d['b'])
    üöä
    """
    if sys.version_info[0] >= 3:
        s = "b = 'üöä'"
    else:
        s = "# -*- coding: utf-8 -*-" + "\n" + "b = u'üöä'"
    exec s in d1, d2

def test_encoding_unicode(d1, d2):
    u"""
    >>> d = {}
    >>> test_encoding_unicode(d, None)
    >>> print(d['b'])
    üöä
    """
    if sys.version_info[0] >= 3:
        s = u"b = 'üöä'"
    else:
        s = u"b = u'üöä'"
    exec s in d1, d2

def test_compile(d):
    """
    >>> d = dict(a=1, c=3)
    >>> test_compile(d)
    >>> d['b']
    4
    """
    c = compile(u"b = a+c", u"", u"exec")
    exec c in d

def exec_invalid_type(x):
    """
    >>> exec_invalid_type(42)
    Traceback (most recent call last):
    TypeError: exec: arg 1 must be string, bytes or code object, got int
    """
    exec x in {}


def exec_with_new_features(s, d):
    """
    >>> import sys
    >>> pyversion = sys.version_info[:2]

    >>> d = {}
    >>> exec_with_new_features('print(123)', d)
    123
    >>> if pyversion == (2, 7): exec_with_new_features('exec "123"', d)
    >>> if pyversion >= (3, 6): exec_with_new_features('f = f"abc"', d)
    >>> if pyversion >= (3, 8): exec_with_new_features('a = (b := 1)', d)
    """
    exec s in d
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/existing_output_files.srctree0000644000175100001770000001075100000000000023573 0ustar00runnerdocker00000000000000PYTHON test.py

######## test.py ########

from __future__ import print_function

import os.path
from Cython.Utils import is_cython_generated_file
from Cython.Compiler.Errors import CompileError
from Cython.Build.Dependencies import cythonize

# Make sure the source files are newer than the .c files, so that cythonize() regenerates them.
files = {}
for source_file in sorted(os.listdir(os.getcwd())):
    if 'module' in source_file and (source_file.endswith(".pyx") or source_file.endswith(".py")):
        c_file = files[source_file] = os.path.splitext(source_file)[0] + ".c"
        os.utime(source_file, None)
        assert not os.path.exists(c_file) or os.path.getmtime(source_file) >= os.path.getmtime(c_file)

for source_file, c_file in files.items():
    print("Testing:", source_file, c_file)
    assert is_cython_generated_file(c_file, allow_failed=True, if_not_found=True)

    # cythonizing should (re)generate the file
    cythonize(source_file, language_level=3)
    assert is_cython_generated_file(c_file, if_not_found=False)
    assert os.path.getmtime(source_file) <= os.path.getmtime(c_file)

    # calling cythonize again should not rewrite the file
    # (not asserting this here, but at least it shouldn't fail)
    cythonize(source_file, language_level=3)
    assert is_cython_generated_file(c_file, if_not_found=False)
    assert os.path.getmtime(source_file) <= os.path.getmtime(c_file)


# But overwriting an unknown file should fail, even when requested multiple times.
for source_file in [
        "refuse_to_overwrite.pyx",
        "refuse_to_overwrite.py",
        "compile_failure.pyx",
        "refuse_to_overwrite_header.pyx",
        "refuse_to_overwrite_api_header.pyx",
]:
    if 'api_header' in source_file:
        target_file = os.path.splitext(source_file)[0] + "_api.h"
    elif 'header' in source_file:
        target_file = os.path.splitext(source_file)[0] + ".h"
    else:
        target_file = os.path.splitext(source_file)[0] + ".c"

    for _ in range(3):
        os.utime(source_file, None)
        assert not is_cython_generated_file(target_file)
        try:
            print("Testing:", source_file)
            cythonize(source_file, language_level=3)
        except CompileError:
            print("REFUSED to overwrite %s, OK" % target_file)
            assert not is_cython_generated_file(target_file)
        else:
            assert False, "FAILURE: Existing output file was overwritten for source file %s" % source_file


######## pymodule.c ########
#error Do not use this file, it is the result of a failed Cython compilation.

######## pymodule.py ########
"""
Overwriting a failed .py file result works
"""

######## cymodule.c ########
#error Do not use this file, it is the result of a failed Cython compilation.

######## cymodule.pyx ########
"""
Overwriting a failed .pyx file result works
"""

######## overwritten_cymodule.c ########
/* Generated by Cython 0.8.15 */

######## overwritten_cymodule.pyx ########
"""
Overwriting an outdated .c file works
"""


######## new_cymodule.pyx ########
"""
Creating a new .c file works
"""

######## new_pymodule.py ########
"""
Creating a new .c file works
"""


######## refuse_to_overwrite.c ########
static int external_function(int x) {
    return x + 1;
}

######## refuse_to_overwrite.py ########
"""
Do not overwrite an unknown output file
"""

######## refuse_to_overwrite.pyx ########
"""
Do not overwrite an unknown output file
"""


######## compile_failure.c ########
static int external_function(int x) {
    return x + 1;
}

######## compile_failure.pyx ########
"""
Do not overwrite an unknown output file even on compile failures.
"""

Not Python syntax!



######## write_module_header.pyx ########

cdef public int func():
    return 1


######## overwrite_module_header.c ########
/* Generated by Cython 0.8.15 */

######## overwrite_module_header.pyx ########

cdef public int func():
    return 1


######## refuse_to_overwrite_header.h ########
static int external_function(int x) {
    return x + 1;
}

######## refuse_to_overwrite_header.pyx ########

cdef public int func():
    return 1


######## write_module_api_header.pyx ########

cdef api int func():
    return 1


######## overwrite_module_api_header.c ########
/* Generated by Cython 0.8.15 */

######## overwrite_module_api_header.pyx ########

cdef public int func():
    return 1


######## refuse_to_overwrite_api_header_api.h ########
static int external_function(int x) {
    return x + 1;
}

######## refuse_to_overwrite_api_header.pyx ########

cdef api int func():
    return 1
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/ext_attr_assign.pyx0000644000175100001770000000413100000000000021501 0ustar00runnerdocker00000000000000# mode: run
# tag: assign, exttype

cdef struct X:
    int ix
    X* x


cdef class A:
    cdef int i
    cdef list l
    cdef object o
    cdef X x

    def assign_A(self):
        """
        >>> A().assign_A()
        (2, [1, 2, 3])
        """
        a = A()
        a.i = 1
        a.l = [1, 2, 3]
        a.o = a.l
        a.o = a.o
        a.l = a.o
        a.i = a.l[1]
        return a.i, a.l

    def assign_A_struct(self):
        """
        >>> A().assign_A_struct()
        (5, 2, 2, 5)
        """
        cdef X x
        a = A()
        a.x.ix = 2
        a.x.x = &x
        x.ix = 5
        x.x = &a.x
        assert a.x.x.x is &a.x

        a.x.x.x.x.x.x.x = a.x.x.x.x
        assert x.x is &x
        assert x.x.x is &x
        assert a.x.x is &x

        a.x.x.x.x.x.x.x, a.x.x.x = a.x.x.x.x, &a.x   # replay+undo :)
        assert x.x is &a.x
        assert x.x.x is &x
        return x.ix, x.x.ix, a.x.ix, a.x.x.ix


cdef class B(A):
    cdef int ib
    cdef object ob
    cdef A a

    def assign_B(self):
        """
        >>> B().assign_B()
        (1, 2, 5, 9, 2)
        """
        b = B()
        b.i = 1
        b.ib = 2
        b.l = [b.i, b.ib]
        b.o = b.l
        b.ob = b.o
        assert b.ob == b.l
        b.o = b.ob = b.l

        b.a = A()   # only one reference!
        b.a.o = 5
        b.a.i = 5
        b.a, b.a.i = A(), b.a.i  # overwrite b.a but keep b.a.i
        assert b.a.i == 5
        assert b.a.o is None
        b.a.o = 9
        b.a, b.a.i, b.a.o = A(), b.a.i, b.a.o
        return b.i, b.ib, b.a.i, b.a.o, b.o[1]

    def cross_assign_Ba(self):
        """
        >>> B().cross_assign_Ba()
        2
        """
        b = B()
        b.a = A()
        b.a.i = 1
        b.a.o = A()   # only one reference!
        (b.a.o).i = 2
        b.a = b.a.o
        return b.a.i

    def cascaded_assign_B(self):
        """
        >>> B().cascaded_assign_B()
        (2, 2)
        """
        cdef B b = B()
        b.ib = 1
        b.a = A()
        b.a.o = B()   # only one reference!
        (b.a.o).ib = 2
        b = b.ob = b.a.o
        return b.ib, (b.ob).ib
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/ext_attr_getter.srctree0000644000175100001770000002024600000000000022343 0ustar00runnerdocker00000000000000# mode: run
# tag: cgetter, property

"""
PYTHON setup.py build_ext --inplace
PYTHON run_failure_tests.py
PYTHON runner.py
"""

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup

# Enforce the right build order
setup(ext_modules = cythonize("foo_extension.pyx", language_level=3))
setup(ext_modules = cythonize("getter[0-9].pyx", language_level=3))


######## run_failure_tests.py ########

import glob
import sys

from Cython.Build.Dependencies import cythonize
from Cython.Compiler.Errors import CompileError

# Run the failure tests
failed_tests = []
passed_tests = []

def run_test(name):
    title = name
    with open(name, 'r') as f:
        for line in f:
            if 'TEST' in line:
                title = line.partition('TEST:')[2].strip()
                break
    sys.stderr.write("\n### TESTING: %s\n" % title)

    try:
        cythonize(name, language_level=3)
    except CompileError as e:
        sys.stderr.write("\nOK: got expected exception\n")
        passed_tests.append(name)
    else:
        sys.stderr.write("\nFAIL: compilation did not detect the error\n")
        failed_tests.append(name)

for name in sorted(glob.glob("getter_fail*.pyx")):
    run_test(name)

assert not failed_tests, "Failed tests: %s" % failed_tests
assert passed_tests  # check that tests were found at all


######## foo.h ########

#include 

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
    PyObject_HEAD
    int f0;
    int f1;
    int f2;
    int v[10];
} FooStructNominal;

typedef struct {
    PyObject_HEAD
} FooStructOpaque;


#define PyFoo_GET0M(a) (((FooStructNominal*)a)->f0)
#define PyFoo_GET1M(a) (((FooStructNominal*)a)->f1)
#define PyFoo_GET2M(a) (((FooStructNominal*)a)->f2)

int PyFoo_Get0F(FooStructOpaque *f)
{
    return PyFoo_GET0M(f);
}

int PyFoo_Get1F(FooStructOpaque *f)
{
    return PyFoo_GET1M(f);
}

int PyFoo_Get2F(FooStructOpaque *f)
{
    return PyFoo_GET2M(f);
}

int *PyFoo_GetV(FooStructOpaque *f)
{
    return ((FooStructNominal*)f)->v;
}

#ifdef __cplusplus
}
#endif


######## foo_extension.pyx ########

cdef class Foo:
    cdef public int _field0, _field1, _field2;
    cdef public int _vector[10];

    @property
    def field0(self):
        return self._field0

    @property
    def field1(self):
        return self._field1

    @property
    def field2(self):
        return self._field2

    def __init__(self, f0, f1, f2, vec=None):
        if vec is None:
            vec = ()
        if not isinstance(vec, tuple):
            raise ValueError("v must be None or a tuple")
        self._field0 = f0
        self._field1 = f1
        self._field2 = f2
        i = 0
        for v in vec:
            self._vector[i] = v
            if i > 9:
                break
            i += 1
        for j in range(i,10):
            self._vector[j] = 0

# A pure-python class that disallows direct access to fields
class OpaqueFoo(Foo):

    @property
    def field0(self):
        raise AttributeError('no direct access to field0')

    @property
    def field1(self):
        raise AttributeError('no direct access to field1')

    @property
    def field2(self):
        raise AttributeError('no direct access to field2')


######## getter0.pyx ########

# Access base Foo fields from C via aliased field names

cdef extern from "foo.h":

    ctypedef class foo_extension.Foo [object FooStructNominal]:
        cdef:
            int field0 "f0"
            int field1 "f1"
            int field2 "f2"

def sum(Foo f):
    # Note - not a cdef function but compiling the f.__getattr__('field0')
    # notices the alias and replaces the __getattr__ in c by f->f0 anyway
    return f.field0 + f.field1 + f.field2

def check_pyobj(Foo f):
    # compare the c code to the check_pyobj in getter2.pyx
    return bool(f.field1)


######## getter.pxd ########

# Access base Foo fields from C via getter functions


cdef extern from "foo.h":
    ctypedef class foo_extension.Foo [object FooStructOpaque, check_size ignore]:
        @property
        cdef inline int fieldM0(self):
            return PyFoo_GET0M(self)

        @property
        cdef inline int fieldF1(self) except -123:
            return PyFoo_Get1F(self)

        @property
        cdef inline int fieldM2(self):
            return PyFoo_GET2M(self)

        @property
        cdef inline int *vector(self):
            return PyFoo_GetV(self)

        @property
        cdef inline int meaning_of_life(self) except -99:
            cdef int ret = 21
            ret *= 2
            return ret

    int PyFoo_GET0M(Foo);  # this is actually a macro !
    int PyFoo_Get1F(Foo);
    int PyFoo_GET2M(Foo);  # this is actually a macro !
    int *PyFoo_GetV(Foo);


######## getter1.pyx ########

cimport getter

def sum(getter.Foo f):
    # Note - not a cdef function but compiling the f.__getattr__('field0')
    # notices the getter and replaces the __getattr__ in c by PyFoo_GET anyway
    return f.fieldM0 + f.fieldF1 + f.fieldM2

def check_10(getter.Foo f):
    return f.fieldF1 != 10

def vec0(getter.Foo f):
    return f.vector[0]

def check_binop(getter.Foo f):
    return f.fieldF1 / 10


######## getter2.pyx ########

cimport getter

def check_pyobj(getter.Foo f):
    return bool(f.fieldF1)
 
def check_unary(getter.Foo f):
    return -f.fieldF1

def check_meaning_of_life(getter.Foo f):
    return f.meaning_of_life


######## getter_fail_classmethod.pyx ########

# TEST: Make sure not all decorators are accepted.

cdef extern from "foo.h":
    ctypedef class foo_extension.Foo [object FooStructOpaque]:
        @property
        @classmethod
        cdef inline int field0(cls):
            print('in classmethod of Foo')


######## getter_fail_dot_getter.pyx ########

# TEST: Make sure not all decorators are accepted.

cdef extern from "foo.h":
    ctypedef class foo_extension.Foo [object FooStructOpaque]:
        @property
        cdef inline int field0(self):
            pass

        @field0.getter
        cdef inline void field1(self):
            pass


######## getter_fail_no_inline.pyx ########

# TEST: Properties must be declared "inline".

cdef extern from "foo.h":
    ctypedef class foo_extension.Foo [object FooStructOpaque]:
        @property
        cdef int field0(self):
            pass


######## getter_fail_void.pyx ########

# TEST: Properties must have a non-void return type.

cdef extern from "foo.h":
    ctypedef class foo_extension.Foo [object FooStructOpaque]:
        @property
        cdef void field0(self):
            pass


######## getter_fail_no_args.pyx ########

# TEST: Properties must have the right signature.

cdef extern from "foo.h":
    ctypedef class foo_extension.Foo [object FooStructOpaque]:
        @property
        cdef int field0():
            pass


######## getter_fail_too_many_args.pyx ########

# TEST: Properties must have the right signature.

cdef extern from "foo.h":
    ctypedef class foo_extension.Foo [object FooStructOpaque]:
        @property
        cdef int field0(x, y):
            pass


######## runner.py ########

import warnings
import foo_extension, getter0, getter1, getter2

def sum(f):
    # pure python field access, but code is identical to cython cdef sum
    return f.field0 + f.field1 + f.field2

# Baseline test: if this fails something else is wrong
foo = foo_extension.Foo(23, 123, 1023)

assert foo.field0 == 23
assert foo.field1 == 123
assert foo.field2 == 1023

ret =  getter0.sum(foo)
assert ret == sum(foo)

# Aliasing test. Check 'cdef int field0 "f0" works as advertised:
# - C can access the fields through the aliases
# - Python cannot access the fields at all

opaque_foo = foo_extension.OpaqueFoo(23, 123, 1023)

opaque_ret = getter0.sum(opaque_foo)
assert opaque_ret == ret

val = getter2.check_pyobj(opaque_foo)
assert val is True
val = getter2.check_unary(opaque_foo)
assert val == -123
val = getter2.check_meaning_of_life(opaque_foo)
assert val == 42

try:
    f0 = opaque_ret.field0
    assert False
except AttributeError as e:
    pass

# Getter test. Check C-level getter works as advertised:
# - C accesses the fields through getter calls (maybe macros)
# - Python accesses the fields through attribute lookup

opaque_foo = foo_extension.OpaqueFoo(23, 123, 1023, (1, 2, 3))

opaque_ret = getter1.sum(opaque_foo)
assert opaque_ret == ret

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/ext_attribute_cache.pyx0000644000175100001770000000153000000000000022311 0ustar00runnerdocker00000000000000# mode: run
# tag: tpflags, type_version_tag

cimport cython


cdef extern from *:
    unsigned long PY_VERSION_HEX
    unsigned long Py_TPFLAGS_HAVE_VERSION_TAG
    ctypedef struct PyTypeObject:
        unsigned long tp_flags


def test_flag(t):
    return ((t).tp_flags & Py_TPFLAGS_HAVE_VERSION_TAG) != 0


cdef class ImplicitAttrCache(object):
    """
    >>> flag = test_flag(ImplicitAttrCache)
    >>> print(flag)
    True
    """
    cdef public int x
    cdef object y


@cython.type_version_tag(True)
cdef class ExplicitAttrCache(object):
    """
    >>> flag = test_flag(ImplicitAttrCache)
    >>> print(flag)
    True
    """
    cdef public int x
    cdef object y


@cython.type_version_tag(False)
cdef class NoAttrCache(object):
    """
    >>> test_flag(NoAttrCache)
    False
    """
    cdef public int x
    cdef object y

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/ext_auto_richcmp.py0000644000175100001770000002517000000000000021456 0ustar00runnerdocker00000000000000# mode: run

import cython
compiled = cython.compiled

import sys
IS_PY2 = sys.version_info[0] == 2


@cython.cclass
class X(object):
    x = cython.declare(cython.int)

    def __init__(self, x):
        self.x = x

    def __repr__(self):
        return "<%d>" % self.x


@cython.cfunc
@cython.locals(x=X)
def x_of(x):
    return x.x


@cython.cclass
class ClassEq(X):
    """
    >>> a = ClassEq(1)
    >>> b = ClassEq(2)
    >>> c = ClassEq(1)
    >>> a == a
    True
    >>> a != a
    False

    >>> a == b
    False
    >>> a != b
    True

    >>> a == c
    True
    >>> if IS_PY2 and not compiled: a is c
    ... else: a != c
    False

    >>> b == c
    False
    >>> b != c
    True

    >>> c == a
    True
    >>> if IS_PY2 and not compiled: c is a
    ... else: c != a
    False

    >>> b == a
    False
    >>> b != a
    True

    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: a < b
    Traceback (most recent call last):
    TypeError...
    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: a > b
    Traceback (most recent call last):
    TypeError...
    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: a <= b
    Traceback (most recent call last):
    TypeError...
    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: a >= b
    Traceback (most recent call last):
    TypeError...

    >>> print(a.__eq__.__doc__)
    EQ
    """
    def __eq__(self, other):
        """EQ"""
        assert 1 <= self.x <= 2
        assert isinstance(self, ClassEq), type(self)
        if isinstance(other, X):
            return self.x == x_of(other)
        elif isinstance(other, int):
            return self.x < other
        return NotImplemented


@cython.cclass
class ClassEqNe(ClassEq):
    """
    >>> a = ClassEqNe(1)
    >>> b = ClassEqNe(2)
    >>> c = ClassEqNe(1)
    >>> a == a
    True
    >>> a != a
    False

    >>> a == b
    False
    >>> a != b
    True

    >>> a == c
    True
    >>> a != c
    False

    >>> b == c
    False
    >>> b != c
    True

    >>> c == a
    True
    >>> c != a
    False

    >>> b == a
    False
    >>> b != a
    True

    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: a < b
    Traceback (most recent call last):
    TypeError...
    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: a > b
    Traceback (most recent call last):
    TypeError...
    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: a <= b
    Traceback (most recent call last):
    TypeError...
    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: a >= b
    Traceback (most recent call last):
    TypeError...

    #>>> print(a.__eq__.__doc__)
    #EQ
    >>> print(a.__ne__.__doc__)
    NE
    """
    def __ne__(self, other):
        """NE"""
        assert 1 <= self.x <= 2
        assert isinstance(self, ClassEqNe), type(self)
        if isinstance(other, X):
            return self.x != x_of(other)
        elif isinstance(other, int):
            return self.x < other
        return NotImplemented


@cython.cclass
class ClassEqNeGe(ClassEqNe):
    """
    >>> a = ClassEqNeGe(1)
    >>> b = ClassEqNeGe(2)
    >>> c = ClassEqNeGe(1)
    >>> a == a
    True
    >>> a != a
    False
    >>> a >= a
    True
    >>> a <= a
    True

    >>> a == b
    False
    >>> a != b
    True
    >>> a >= b
    False
    >>> b <= a
    False

    >>> a == c
    True
    >>> a != c
    False
    >>> a >= c
    True
    >>> c <= a
    True

    >>> b == c
    False
    >>> b != c
    True
    >>> b >= c
    True
    >>> c <= b
    True

    >>> c == a
    True
    >>> c != a
    False
    >>> c >= a
    True
    >>> a <= c
    True

    >>> b == a
    False
    >>> b != a
    True
    >>> b >= a
    True
    >>> a <= b
    True

    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: a < b
    Traceback (most recent call last):
    TypeError...
    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: a > b
    Traceback (most recent call last):
    TypeError...

    >>> 2 <= a
    False
    >>> a >= 2
    False
    >>> 1 <= a
    True
    >>> a >= 1
    True
    >>> a >= 2
    False

    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: 'x' <= a
    Traceback (most recent call last):
    TypeError...
    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: a >= 'x'
    Traceback (most recent call last):
    TypeError...

    #>>> print(a.__eq__.__doc__)
    #EQ
    #>>> print(a.__ne__.__doc__)
    #NE
    >>> print(a.__ge__.__doc__)
    GE
   """
    def __ge__(self, other):
        """GE"""
        assert 1 <= self.x <= 2
        assert isinstance(self, ClassEqNeGe), type(self)
        if isinstance(other, X):
            return self.x >= x_of(other)
        elif isinstance(other, int):
            return self.x >= other
        return NotImplemented


@cython.cclass
class ClassRichcmpOverride(ClassEqNeGe):
    """
    >>> a = ClassRichcmpOverride(1)
    >>> b = ClassRichcmpOverride(1)

    >>> a == a
    True
    >>> a != a
    False

    >>> a != b if compiled else a == b  # Python ignores __richcmp__()
    True
    >>> a == b if compiled else a != b  # Python ignores __richcmp__()
    False

    >>> if IS_PY2 or not compiled: raise TypeError  # doctest: +ELLIPSIS
    ... else: a >= b  # should no longer work when __richcmp__ is overwritten
    Traceback (most recent call last):
    TypeError...
    """
    def __richcmp__(self, other, op):
        return NotImplemented


@cython.cclass
class ClassLe(X):
    """
    >>> a = ClassLe(1)
    >>> b = ClassLe(2)
    >>> c = ClassLe(1)

    >>> a <= b
    True
    >>> b >= a
    True
    >>> b <= a
    False
    >>> a >= b
    False

    >>> a <= c
    True
    >>> c >= a
    True
    >>> c <= a
    True
    >>> a >= c
    True

    >>> b <= c
    False
    >>> c >= b
    False
    >>> c <= b
    True
    >>> b >= c
    True

    >>> 2 >= a
    True
    >>> a <= 2
    True
    >>> 1 >= a
    True
    >>> a <= 1
    True
    >>> a <= 0
    False

    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: 'x' >= a
    Traceback (most recent call last):
    TypeError...
    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: a <= 'x'
    Traceback (most recent call last):
    TypeError...
    """
    def __le__(self, other):
        assert 1 <= self.x <= 2
        assert isinstance(self, ClassLe), type(self)
        if isinstance(other, X):
            return self.x <= x_of(other)
        elif isinstance(other, int):
            return self.x <= other
        return NotImplemented


@cython.cclass
class ClassLt(X):
    """
    >>> a = ClassLt(1)
    >>> b = ClassLt(2)
    >>> c = ClassLt(1)

    >>> a < b
    True
    >>> b > a
    True
    >>> b < a
    False
    >>> a > b
    False

    >>> a < c
    False
    >>> c > a
    False
    >>> c < a
    False
    >>> a > c
    False

    >>> b < c
    False
    >>> c > b
    False
    >>> c < b
    True
    >>> b > c
    True

    >>> sorted([a, b, c])
    [<1>, <1>, <2>]
    >>> sorted([b, a, c])
    [<1>, <1>, <2>]

    >>> 2 > a
    True
    >>> a < 2
    True
    >>> 1 > a
    False
    >>> a < 1
    False

    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: 1 < a
    Traceback (most recent call last):
    TypeError...

    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: 'x' > a
    Traceback (most recent call last):
    TypeError...
    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: a < 'x'
    Traceback (most recent call last):
    TypeError...
    """
    def __lt__(self, other):
        assert 1 <= self.x <= 2
        assert isinstance(self, ClassLt), type(self)
        if isinstance(other, X):
            return self.x < x_of(other)
        elif isinstance(other, int):
            return self.x < other
        return NotImplemented


@cython.cclass
class ClassLtGtInherited(X):
    """
    >>> a = ClassLtGtInherited(1)
    >>> b = ClassLtGtInherited(2)
    >>> c = ClassLtGtInherited(1)

    >>> a < b
    True
    >>> b > a
    True
    >>> b < a
    False
    >>> a > b
    False

    >>> a < c
    False
    >>> c > a
    False
    >>> c < a
    False
    >>> a > c
    False

    >>> b < c
    False
    >>> c > b
    False
    >>> c < b
    True
    >>> b > c
    True

    >>> sorted([a, b, c])
    [<1>, <1>, <2>]
    >>> sorted([b, a, c])
    [<1>, <1>, <2>]
    """
    def __gt__(self, other):
        assert 1 <= self.x <= 2
        assert isinstance(self, ClassLtGtInherited), type(self)
        if isinstance(other, X):
            return self.x > x_of(other)
        elif isinstance(other, int):
            return self.x > other
        return NotImplemented


@cython.cclass
class ClassLtGt(X):
    """
    >>> a = ClassLtGt(1)
    >>> b = ClassLtGt(2)
    >>> c = ClassLtGt(1)

    >>> a < b
    True
    >>> b > a
    True
    >>> b < a
    False
    >>> a > b
    False

    >>> a < c
    False
    >>> c > a
    False
    >>> c < a
    False
    >>> a > c
    False

    >>> b < c
    False
    >>> c > b
    False
    >>> c < b
    True
    >>> b > c
    True

    >>> sorted([a, b, c])
    [<1>, <1>, <2>]
    >>> sorted([b, a, c])
    [<1>, <1>, <2>]

    >>> 2 > a
    True
    >>> 2 < a
    False
    >>> a < 2
    True
    >>> a > 2
    False

    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: 'x' > a
    Traceback (most recent call last):
    TypeError...
    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: 'x' < a
    Traceback (most recent call last):
    TypeError...
    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: a < 'x'
    Traceback (most recent call last):
    TypeError...
    >>> if IS_PY2: raise TypeError  # doctest: +ELLIPSIS
    ... else: a > 'x'
    Traceback (most recent call last):
    TypeError...
    """
    def __lt__(self, other):
        assert 1 <= self.x <= 2
        assert isinstance(self, ClassLtGt), type(self)
        if isinstance(other, X):
            return self.x < x_of(other)
        elif isinstance(other, int):
            return self.x < other
        return NotImplemented

    def __gt__(self, other):
        assert 1 <= self.x <= 2
        assert isinstance(self, ClassLtGt), type(self)
        if isinstance(other, X):
            return self.x > x_of(other)
        elif isinstance(other, int):
            return self.x > other
        return NotImplemented


@cython.cclass
class List(list):
    """
    >>> l = [1, 2, 3, 4]
    >>> notl = List(l)
    >>> notl == l
    False
    >>> notl != l     # implemented by base type
    False
    >>> notl == notl
    True
    >>> notl != notl  # implemented by base type
    False
    """
    def __eq__(self, other):
        return self is other or list(self) != list(other)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4047222
Cython-3.0.8/tests/run/ext_instance_type_T232.pyx0000644000175100001770000000032600000000000022544 0ustar00runnerdocker00000000000000# ticket: t232

cdef class MyExt:
    cdef object attr

def set_attr(value):
    """
    >>> set_attr(5)
    """
    MyExt().attr = value

def get_attr():
    """
    >>> get_attr()
    """
    return MyExt().attr
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/ext_type_none_arg.pyx0000644000175100001770000001651700000000000022027 0ustar00runnerdocker00000000000000
cimport cython
try:
    import typing
    from typing import Optional
except ImportError:
    pass  # Cython can still identify the use of "typing" even if the module doesn't exist


### extension types

cdef class MyExtType:
    cdef object attr
    def __cinit__(self):
        self.attr = 123

cdef attr(MyExtType x):
    return x is None and 321 or x.attr


# defaults, without 'not/or None'

def ext_default(MyExtType x): # currently behaves like 'or None'
    """
    >>> ext_default(MyExtType())
    123
    >>> ext_default(None)
    321
    """
    return attr(x)

@cython.allow_none_for_extension_args(False)
def ext_default_none(MyExtType x=None): # special cased default arg
    """
    >>> ext_default_none(MyExtType())
    123
    >>> ext_default_none(None)
    321
    >>> ext_default_none()
    321
    """
    return attr(x)

@cython.allow_none_for_extension_args(True)
def ext_default_check_off(MyExtType x):
    """
    >>> ext_default_check_off(MyExtType())
    123
    >>> ext_default_check_off(None)
    321
    """
    return attr(x)

@cython.allow_none_for_extension_args(False)
def ext_default_check_on(MyExtType x):
    """
    >>> ext_default_check_on(MyExtType())
    123
    >>> ext_default_check_on(None)
    Traceback (most recent call last):
    TypeError: Argument 'x' has incorrect type (expected ext_type_none_arg.MyExtType, got NoneType)
    """
    return attr(x)


# with 'or/not None'

def ext_or_none(MyExtType x or None):
    """
    >>> ext_or_none(MyExtType())
    123
    >>> ext_or_none(None)
    321
    """
    return attr(x)

def ext_not_none(MyExtType x not None):
    """
    >>> ext_not_none(MyExtType())
    123
    >>> ext_not_none(None)
    Traceback (most recent call last):
    TypeError: Argument 'x' has incorrect type (expected ext_type_none_arg.MyExtType, got NoneType)
    """
    return attr(x)

def ext_annotations(x: MyExtType):
    """
    Behaves the same as "MyExtType x not None"
    >>> ext_annotations(MyExtType())
    123
    >>> ext_annotations(None)
    Traceback (most recent call last):
    TypeError: Argument 'x' has incorrect type (expected ext_type_none_arg.MyExtType, got NoneType)
    """
    return attr(x)

@cython.allow_none_for_extension_args(False)
def ext_annotations_check_on(x: MyExtType):
    """
    >>> ext_annotations_check_on(MyExtType())
    123
    >>> ext_annotations_check_on(None)
    Traceback (most recent call last):
    TypeError: Argument 'x' has incorrect type (expected ext_type_none_arg.MyExtType, got NoneType)
    """
    return attr(x)

def ext_optional(x: typing.Optional[MyExtType], y: Optional[MyExtType]):
    """
    Behaves the same as "or None"
    >>> ext_optional(MyExtType(), MyExtType())
    246
    >>> ext_optional(MyExtType(), None)
    444
    >>> ext_optional(None, MyExtType())
    444
    """
    return attr(x) + attr(y)

### builtin types (using list)

cdef litem(list L, int item):
    return L is None and 321 or L[item]


# defaults, without 'not/or None'

def builtin_default(list L): # currently behaves like 'or None'
    """
    >>> builtin_default([123])
    123
    >>> builtin_default(None)
    321
    """
    return litem(L, 0)

@cython.allow_none_for_extension_args(False)
def builtin_default_none(list L=None): # special cased default arg
    """
    >>> builtin_default_none([123])
    123
    >>> builtin_default_none(None)
    321
    >>> builtin_default_none()
    321
    """
    return litem(L, 0)

@cython.allow_none_for_extension_args(True)
def builtin_default_check_off(list L):
    """
    >>> builtin_default_check_off([123])
    123
    >>> builtin_default_check_off(None)
    321
    """
    return litem(L, 0)

@cython.allow_none_for_extension_args(False)
def builtin_default_check_on(list L):
    """
    >>> builtin_default_check_on([123])
    123
    >>> builtin_default_check_on(None)
    Traceback (most recent call last):
    TypeError: Argument 'L' has incorrect type (expected list, got NoneType)
    """
    return litem(L, 0)


# with 'or/not None'

def builtin_or_none(list L or None):
    """
    >>> builtin_or_none([123])
    123
    >>> builtin_or_none(None)
    321
    """
    return litem(L, 0)

def builtin_not_none(list L not None):
    """
    >>> builtin_not_none([123])
    123
    >>> builtin_not_none(None)
    Traceback (most recent call last):
    TypeError: Argument 'L' has incorrect type (expected list, got NoneType)
    """
    return litem(L, 0)


## builtin type 'object' - isinstance(None, object) is True!

@cython.allow_none_for_extension_args(False)
def object_default(object o): # always behaves like 'or None'
    """
    >>> object_default(object())
    'object'
    >>> object_default([])
    'list'
    >>> object_default(None)
    'NoneType'
    """
    return type(o).__name__

@cython.allow_none_for_extension_args(False)
def object_default_annotation(o : object):
    """
    >>> object_default_annotation(object())
    'object'
    >>> object_default_annotation([])
    'list'
    >>> object_default_annotation(None)
    'NoneType'
    """
    return type(o).__name__

# no decorator
def object_default_annotation2(o : object):
    """
    >>> object_default_annotation2(object())
    'object'
    >>> object_default_annotation2([])
    'list'
    >>> object_default_annotation2(None)
    'NoneType'
    """
    return type(o).__name__

@cython.allow_none_for_extension_args(False)
def object_default_none(object o=None): # behaves like 'or None'
    """
    >>> object_default_none(object())
    'object'
    >>> object_default_none([])
    'list'
    >>> object_default_none(None)
    'NoneType'
    >>> object_default_none()
    'NoneType'
    """
    return type(o).__name__

@cython.allow_none_for_extension_args(False)
def object_or_none(object o or None):
    """
    >>> object_or_none(object())
    'object'
    >>> object_or_none([])
    'list'
    >>> object_or_none(None)
    'NoneType'
    """
    return type(o).__name__

@cython.allow_none_for_extension_args(False)
def object_not_none(object o not None):
    """
    >>> object_not_none(object())
    'object'
    >>> object_not_none([])
    'list'
    >>> object_not_none(None)
    Traceback (most recent call last):
    TypeError: Argument 'o' must not be None
    """
    return type(o).__name__


## untyped 'object' - isinstance(None, object) is True!

@cython.allow_none_for_extension_args(False)
def notype_default(o): # behaves like 'or None'
    """
    >>> notype_default(object())
    'object'
    >>> notype_default([])
    'list'
    >>> notype_default(None)
    'NoneType'
    """
    return type(o).__name__

@cython.allow_none_for_extension_args(False)
def notype_default_none(o=None): # behaves like 'or None'
    """
    >>> notype_default_none(object())
    'object'
    >>> notype_default_none([])
    'list'
    >>> notype_default_none(None)
    'NoneType'
    >>> notype_default_none()
    'NoneType'
    """
    return type(o).__name__

@cython.allow_none_for_extension_args(False)
def notype_or_none(o or None):
    """
    >>> notype_or_none(object())
    'object'
    >>> notype_or_none([])
    'list'
    >>> notype_or_none(None)
    'NoneType'
    """
    return type(o).__name__

@cython.allow_none_for_extension_args(False)
def notype_not_none(o not None):
    """
    >>> notype_not_none(object())
    'object'
    >>> notype_not_none([])
    'list'
    >>> notype_not_none(None)
    Traceback (most recent call last):
    TypeError: Argument 'o' must not be None
    """
    return type(o).__name__
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extclassbody.pyx0000644000175100001770000000035700000000000021015 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> s = Spam()
>>> s.a
2
>>> s.c
3
>>> s.test(5)
13
>>> s.b
5
"""

cdef class Spam:
    a = 1
    def test(self, a):
        return a + self.b + self.c
    b = a + 2 # 3
    a = b - 1 # 2
    c = 3     # 3
    b = c + a # 5
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extclasspass.pyx0000644000175100001770000000014100000000000021015 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> e = Eggs()
    >>> type(e).__name__
    'Eggs'
"""

cdef class Eggs: pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extcmethod.pyx0000644000175100001770000000246100000000000020453 0ustar00runnerdocker00000000000000# mode: run


cdef class Spam:

    cdef int tons

    cdef void add_tons(self, int x):
        self.tons += x

    cdef void eat(self):
        self.tons = 0

    def lift(self):
        print self.tons


cdef class SubSpam(Spam):

    cdef void add_tons(self, int x):
        self.tons += 2 * x


def test_spam():
    """
    >>> test_spam()
    5
    0
    20
    5
    """
    cdef Spam s
    cdef SubSpam ss
    s = Spam()
    s.eat()
    s.add_tons(5)
    s.lift()

    ss = SubSpam()
    ss.eat()
    ss.lift()

    ss.add_tons(10)
    ss.lift()

    s.lift()


cdef class SpamDish:
    cdef int spam

    cdef void describe(self):
        print "This dish contains", self.spam, "tons of spam."


cdef class FancySpamDish(SpamDish):
    cdef int lettuce

    cdef void describe(self):
        print "This dish contains", self.spam, "tons of spam",
        print "and", self.lettuce, "milligrams of lettuce."


cdef void describe_dish(SpamDish d):
    d.describe()


def test_spam_dish():
    """
    >>> test_spam_dish()
    This dish contains 42 tons of spam.
    This dish contains 88 tons of spam and 5 milligrams of lettuce.
    """
    cdef SpamDish s
    cdef FancySpamDish ss
    s = SpamDish()
    s.spam = 42
    ss = FancySpamDish()
    ss.spam = 88
    ss.lettuce = 5
    describe_dish(s)
    describe_dish(ss)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extended_unpacking_T235.pyx0000644000175100001770000002011600000000000022660 0ustar00runnerdocker00000000000000# ticket: t235

__doc__ = u"""
    >>> class FakeSeq(object):
    ...     def __init__(self, length):
    ...         self._values = list(range(1,length+1))
    ...     def __getitem__(self, i):
    ...         return self._values[i]

    >>> unpack( FakeSeq(2) )
    (1, 2)
    >>> unpack_recursive( FakeSeq(4) )
    (1, [2, 3], 4)
"""

def unpack(l):
    """
    >>> unpack([1,2])
    (1, 2)
    >>> unpack('12')
    ('1', '2')
    """
    a, b = l
    return a,b

def unpack_list(list l):
    """
    >>> unpack_list([1,2])
    (1, 2)
    """
    a, b = l
    return a,b

def unpack_tuple(tuple t):
    """
    >>> unpack_tuple((1,2))
    (1, 2)
    """
    a, b = t
    return a,b

def unpack_single(l):
    """
    >>> unpack_single([1])
    [1]
    >>> unpack_single('1')
    ['1']
    """
    *a, = l
    return a

def unpack_tuple_single(tuple t):
    """
    >>> unpack_tuple_single((1,))
    [1]
    """
    *a, = t
    return a

def assign():
    """
    >>> assign()
    (1, [2, 3, 4], 5)
    """
    *a, b = 1,2,3,4,5
    assert a+[b] == [1,2,3,4,5], (a,b)
    a, *b = 1,2,3,4,5
    assert [a]+b == [1,2,3,4,5], (a,b)
    [a, *b, c] = 1,2,3,4,5
    return a,b,c

def unpack_into_list(l):
    """
    >>> unpack_into_list('123')
    ('1', ['2'], '3')
    """
    [*a, b] = l
    assert a+[b] == list(l), repr((a+[b],list(l)))
    [a, *b] = l
    assert [a]+b == list(l), repr(([a]+b,list(l)))
    [a, *b, c] = l
    return a,b,c

def unpack_into_tuple(t):
    """
    >>> unpack_into_tuple('123')
    ('1', ['2'], '3')
    """
    (*a, b) = t
    assert a+[b] == list(t), repr((a+[b],list(t)))
    (a, *b) = t
    assert [a]+b == list(t), repr(([a]+b,list(t)))
    (a, *b, c) = t
    return a,b,c

def unpack_in_loop(list_of_sequences):
    """
    >>> unpack_in_loop([(1,2), (1,2,3), (1,2,3,4)])
    1
    ([1], 2)
    ([1, 2], 3)
    ([1, 2, 3], 4)
    2
    (1, [2])
    (1, [2, 3])
    (1, [2, 3, 4])
    3
    (1, [], 2)
    (1, [2], 3)
    (1, [2, 3], 4)
    """
    print 1
    for *a,b in list_of_sequences:
        print((a,b))
    print 2
    for a,*b in list_of_sequences:
        print((a,b))
    print 3
    for a,*b, c in list_of_sequences:
        print((a,b,c))

def unpack_recursive(t):
    """
    >>> unpack_recursive((1,2,3,4))
    (1, [2, 3], 4)
    """
    *(a, *b), c  = t
    return a,b,c

def unpack_typed(t):
    """
    >>> unpack_typed((1,2))
    ([1], 2)
    """
    cdef list a
    *a, b  = t
    return a,b


def unpack_right(l):
    """
    >>> unpack_right('')
    Traceback (most recent call last):
    ValueError: need more than 0 values to unpack
    >>> unpack_right('1')
    ('1', [])
    >>> unpack_right([1])
    (1, [])
    >>> unpack_right('12')
    ('1', ['2'])
    >>> unpack_right([1,2])
    (1, [2])
    >>> unpack_right('123')
    ('1', ['2', '3'])
    >>> unpack_right([1,2,3])
    (1, [2, 3])
    """
    a, *b = l
    return a,b

def unpack_right_list(list l):
    """
    >>> unpack_right_list([])
    Traceback (most recent call last):
    ValueError: need more than 0 values to unpack
    >>> unpack_right_list([1])
    (1, [])
    >>> unpack_right_list([1,2])
    (1, [2])
    >>> unpack_right_list([1,2,3])
    (1, [2, 3])
    """
    a, *b = l
    return a,b

def unpack_right_tuple(tuple t):
    """
    >>> unpack_right_tuple(())
    Traceback (most recent call last):
    ValueError: need more than 0 values to unpack
    >>> unpack_right_tuple((1,))
    (1, [])
    >>> unpack_right_tuple((1,2))
    (1, [2])
    >>> unpack_right_tuple((1,2,3))
    (1, [2, 3])
    """
    a, *b = t
    return a,b


def unpack_left(l):
    """
    >>> unpack_left('')
    Traceback (most recent call last):
    ValueError: need more than 0 values to unpack
    >>> unpack_left('1')
    ([], '1')
    >>> unpack_left([1])
    ([], 1)
    >>> unpack_left('12')
    (['1'], '2')
    >>> unpack_left([1,2])
    ([1], 2)
    >>> unpack_left('123')
    (['1', '2'], '3')
    >>> unpack_left([1,2,3])
    ([1, 2], 3)
    """
    *a, b = l
    return a,b

def unpack_left_list(list l):
    """
    >>> unpack_left_list([])
    Traceback (most recent call last):
    ValueError: need more than 0 values to unpack
    >>> unpack_left_list([1])
    ([], 1)
    >>> unpack_left_list([1,2])
    ([1], 2)
    >>> unpack_left_list([1,2,3])
    ([1, 2], 3)
    """
    *a, b = l
    return a,b

def unpack_left_tuple(tuple t):
    """
    >>> unpack_left_tuple(())
    Traceback (most recent call last):
    ValueError: need more than 0 values to unpack
    >>> unpack_left_tuple((1,))
    ([], 1)
    >>> unpack_left_tuple((1,2))
    ([1], 2)
    >>> unpack_left_tuple((1,2,3))
    ([1, 2], 3)
    """
    *a, b = t
    return a,b


def unpack_middle(l):
    """
    >>> unpack_middle('')
    Traceback (most recent call last):
    ValueError: need more than 0 values to unpack
    >>> unpack_middle([])
    Traceback (most recent call last):
    ValueError: need more than 0 values to unpack
    >>> unpack_middle(())
    Traceback (most recent call last):
    ValueError: need more than 0 values to unpack
    >>> unpack_middle('1')
    Traceback (most recent call last):
    ValueError: need more than 1 value to unpack
    >>> unpack_middle([1])
    Traceback (most recent call last):
    ValueError: need more than 1 value to unpack
    >>> unpack_middle('12')
    ('1', [], '2')
    >>> unpack_middle([1,2])
    (1, [], 2)
    >>> unpack_middle('123')
    ('1', ['2'], '3')
    >>> unpack_middle([1,2,3])
    (1, [2], 3)
    """
    a, *b, c = l
    return a,b,c

def unpack_middle_list(list l):
    """
    >>> unpack_middle_list([])
    Traceback (most recent call last):
    ValueError: need more than 0 values to unpack
    >>> unpack_middle_list([1])
    Traceback (most recent call last):
    ValueError: need more than 1 value to unpack
    >>> unpack_middle_list([1,2])
    (1, [], 2)
    >>> unpack_middle_list([1,2,3])
    (1, [2], 3)
    """
    a, *b, c = l
    return a,b,c

def unpack_middle_tuple(tuple t):
    """
    >>> unpack_middle_tuple(())
    Traceback (most recent call last):
    ValueError: need more than 0 values to unpack
    >>> unpack_middle_tuple((1,))
    Traceback (most recent call last):
    ValueError: need more than 1 value to unpack
    >>> unpack_middle_tuple((1,2))
    (1, [], 2)
    >>> unpack_middle_tuple((1,2,3))
    (1, [2], 3)
    >>> a,b,c = unpack_middle(list(range(100)))
    >>> a, len(b), c
    (0, 98, 99)
    >>> a,b,c = unpack_middle_list(list(range(100)))
    >>> a, len(b), c
    (0, 98, 99)
    >>> a,b,c = unpack_middle_tuple(tuple(range(100)))
    >>> a, len(b), c
    (0, 98, 99)
    """
    a, *b, c = t
    return a,b,c

def unpack_many_middle(it):
    """
    >>> unpack_many_middle(list(range(14)))
    (0, 1, 2, 3, 4, [5, 6, 7, 8, 9], 10, 11, 12, 13)
    >>> unpack_many_middle(tuple(range(14)))
    (0, 1, 2, 3, 4, [5, 6, 7, 8, 9], 10, 11, 12, 13)
    >>> unpack_many_middle(iter(range(14)))
    (0, 1, 2, 3, 4, [5, 6, 7, 8, 9], 10, 11, 12, 13)
    """
    a,b,c,d,e,*f,g,h,i,j = it
    return a,b,c,d,e,f,g,h,i,j

def unpack_many_left(it):
    """
    >>> unpack_many_left(list(range(14)))
    (0, 1, 2, 3, 4, 5, 6, 7, 8, [9, 10, 11, 12, 13])
    >>> unpack_many_left(tuple(range(14)))
    (0, 1, 2, 3, 4, 5, 6, 7, 8, [9, 10, 11, 12, 13])
    >>> unpack_many_left(iter(range(14)))
    (0, 1, 2, 3, 4, 5, 6, 7, 8, [9, 10, 11, 12, 13])
    """
    a,b,c,d,e,f,g,h,i,*j = it
    return a,b,c,d,e,f,g,h,i,j

def unpack_many_right(it):
    """
    >>> unpack_many_right(list(range(14)))
    ([0, 1, 2, 3, 4], 5, 6, 7, 8, 9, 10, 11, 12, 13)
    >>> unpack_many_right(tuple(range(14)))
    ([0, 1, 2, 3, 4], 5, 6, 7, 8, 9, 10, 11, 12, 13)
    >>> unpack_many_right(iter(range(14)))
    ([0, 1, 2, 3, 4], 5, 6, 7, 8, 9, 10, 11, 12, 13)
    """
    *a,b,c,d,e,f,g,h,i,j = it
    return a,b,c,d,e,f,g,h,i,j

def unpack_many_right_loop(it):
    """
    >>> unpack_many_right_loop(list(range(14)))
    ([0, 1, 2, 3, 4], 5, 6, 7, 8, 9, 10, 11, 12, 13)
    >>> unpack_many_right_loop(tuple(range(14)))
    ([0, 1, 2, 3, 4], 5, 6, 7, 8, 9, 10, 11, 12, 13)
    >>> unpack_many_right_loop(iter(range(14)))
    ([0, 1, 2, 3, 4], 5, 6, 7, 8, 9, 10, 11, 12, 13)
    """
    cdef int i
    for i in range(1):
        *a,b,c,d,e,f,g,h,i,j = it
    return a,b,c,d,e,f,g,h,i,j
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extended_unpacking_T409.pyx0000644000175100001770000000061300000000000022663 0ustar00runnerdocker00000000000000# ticket: t409

def simple():
    """
    >>> simple()
    ([1, 2], [1, 2])
    """
    d = e = [1,2]
    return d, e

def simple_parallel():
    """
    >>> simple_parallel()
    (1, 2, [1, 2], [1, 2])
    """
    a, c = d = e = [1,2]
    return a, c, d, e

def extended():
    """
    >>> extended()
    (1, [], 2, [1, 2], [1, 2])
    """
    a, *b, c = d = e = [1,2]
    return a, b, c, d, e
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extern_builtins_T258.pyx0000644000175100001770000000163200000000000022246 0ustar00runnerdocker00000000000000# ticket: t258

cdef extern from "Python.h":

    ctypedef class __builtin__.list  [object PyListObject]:
        cdef Py_ssize_t allocated

    ctypedef class __builtin__.dict  [object PyDictObject]:
        pass

    cdef Py_ssize_t Py_SIZE(object o)

cdef list L = [1,2,4]
cdef dict d = {'A': 'a'}


def test_list(list L):
    """
    >>> test_list(list(range(10)))
    True
    >>> class list_subclass(list): pass
    >>> test_list(list_subclass([1,2,3]))
    True
    """
    return Py_SIZE(L) <= L.allocated

def test_tuple(tuple t):
    """
    Actual builtin types are restrictive wrt subclassing so optimizations can be safely performed.

    >>> test_tuple((1,2))
    2
    >>> class tuple_subclass(tuple): pass
    >>> test_tuple(tuple_subclass((1,2)))
    Traceback (most recent call last):
    ...
    TypeError: Argument 't' has incorrect type (expected tuple, got tuple_subclass)
    """
    return len(t)

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extern_impl.srctree0000644000175100001770000000071200000000000021461 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import foo"
PYTHON -c "import a"

######## setup.py ########

from Cython.Build import cythonize
from distutils.core import setup

setup(
  ext_modules = cythonize("*.pyx"),
)

######## foo.pxd ########

cdef void bar() except *

######## foo.pyx ########

cdef extern from "bar_impl.c":
    void bar() except *

######## bar_impl.c ########

static void bar() {}

######## a.pyx ########

from foo cimport bar
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extern_impl_excvalue.srctree0000644000175100001770000000153300000000000023357 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import foo"
PYTHON -c "import a"
PYTHON -c "import b"

######## setup.py ########

from Cython.Build import cythonize
from distutils.core import setup

setup(
  ext_modules = cythonize("*.pyx"),
)

######## foo.pxd ########

cdef int bar() except *

cdef extern from "bar_impl.c":
    struct mystruct:
        int (*func_ptr)(int param) nogil

######## foo.pyx ########

cdef extern from "bar_impl.c":
    int bar() except *

######## bar_impl.c ########

static int bar() { return -1; }

typedef struct mystruct {
  int (*func_ptr)(int param);
} mystruct_t;

######## a.pyx ########

cimport cython
from foo cimport bar

assert bar() == -1


######## b.pyx ########

from foo cimport mystruct

cdef int cb(int param) noexcept nogil:
    return param

cdef mystruct ms = mystruct(&cb)
assert ms.func_ptr(5) == 5
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extern_include_order.srctree0000644000175100001770000000202500000000000023335 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import a"
PYTHON -c "import b"

######## setup.py ########

from Cython.Build import cythonize
from distutils.core import setup

setup(
    ext_modules = cythonize("*.pyx"),
)

######## a.pxd ########
# cython: preliminary_late_includes_cy28=True

cdef extern from "a_early.h":
  ctypedef int my_int

cdef extern from "a_late.h":
    my_int square_value_plus_one()

cdef my_int my_value "my_value"

cdef my_int square "square"(my_int x)

######## a.pyx ########

my_value = 10

cdef my_int square "square"(my_int x):
    return x * x

assert square_value_plus_one() == 101

# Square must be explicitly used for its proto to be generated.
cdef my_int use_square(x):
  return square(x)

######## a_early.h ########

typedef int my_int;

######## a_late.h ########

static my_int square_value_plus_one() {
  return square(my_value) + 1;
}

######## b.pyx ########

cimport a

# Likewise, a.square must be explicitly used.
assert a.square(a.my_value) + 1 == 101
assert a.square_value_plus_one() == 101
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extern_varobject_extensions.srctree0000644000175100001770000000420300000000000024755 0ustar00runnerdocker00000000000000# mode: run

PYTHON setup.py build_ext --inplace
PYTHON -c "import classes"
PYTHON -c "import test_inherit"

######## setup.py ########

from Cython.Build.Dependencies import cythonize

from distutils.core import setup

setup(
  ext_modules=cythonize("*.pyx"),
)

######  dummy_module.py ###########

tpl = tuple
lst = list

###### classes.pxd ################

cdef extern from *:
    # apart from list, these are all variable sized types
    # and Cython shouldn't trip up about the struct size
    ctypedef class dummy_module.tpl [object PyTupleObject]:
        pass
    ctypedef class dummy_module.lst [object PyListObject]:
        pass
    ctypedef class types.CodeType [object PyCodeObject]:
        pass
    # Note that bytes doesn't work here because it further 
    # the tp_basicsize to save space
        
##### classes.pyx #################

def check_tuple(tpl x):
    assert isinstance(x, tuple)
    
def check_list(lst x):
    assert isinstance(x, list)
    
def check_code(CodeType x):
    import types
    assert isinstance(x, types.CodeType)
    
check_tuple((1, 2))
check_list([1, 2])
check_code(eval("lambda: None").__code__)

##### failed_inherit1.pyx #############

from classes cimport tpl

cdef class SuperTuple(tpl):
    cdef int a  # importing this gives an error message

##### failed_inherit2.pyx #############

from classes cimport tpl

cdef class SuperTuple(tpl):
    # adding a method creates a vtab so should also fail
    cdef int func(self):
        return 1
    
##### successful_inherit.pyx #########

from classes cimport lst, tpl

cdef class SuperList(lst):
    cdef int a  # This works OK
    
cdef class SuperTuple(tpl):
    # This is actually OK because it doesn't add anything
    pass
    
##### test_inherit.py ################

try:
    import failed_inherit1
except TypeError as e:
    assert e.args[0] == "inheritance from PyVarObject types like 'tuple' not currently supported", e.args[0]
else:
    assert False
try:
    import failed_inherit2
except TypeError as e:
    assert e.args[0] == "inheritance from PyVarObject types like 'tuple' not currently supported", e.args[0]
else:
    assert False
    
import successful_inherit
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/external_defs.h0000644000175100001770000000110200000000000020530 0ustar00runnerdocker00000000000000
typedef float FloatTypedef;
typedef double DoubleTypedef;
typedef long double LongDoubleTypedef;

typedef char CharTypedef;
typedef short ShortTypedef;
typedef int IntTypedef;
typedef long LongTypedef;
#if defined(T_LONGLONG)
typedef PY_LONG_LONG LongLongTypedef;
#else
typedef long LongLongTypedef;
#endif

typedef unsigned char UCharTypedef;
typedef unsigned short UShortTypedef;
typedef unsigned int UIntTypedef;
typedef unsigned long ULongTypedef;
#if defined(T_LONGLONG)
typedef unsigned PY_LONG_LONG ULongLongTypedef;
#else
typedef unsigned long ULongLongTypedef;
#endif
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/external_inline_declaration.srctree0000644000175100001770000000061600000000000024663 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import a; assert a.test() == 1"

######## setup.py ########

from Cython.Build.Dependencies import cythonize

from distutils.core import setup

setup(
    ext_modules = cythonize("a.py"),
)

######## a.py ########

def inlined_func(x):
    return x

def test():
    return inlined_func(1)

######## a.pxd ########

cdef inline int inlined_func(int x)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/external_ref_reassignment.pyx0000644000175100001770000000104000000000000023534 0ustar00runnerdocker00000000000000# Test that variable visible outside of the local scope (e.g. closure, cglobals)
# is set before original value is decrefed.
cdef object g

def test_cglobals_reassignment():
    """
    >>> test_cglobals_reassignment()
    1234
    """
    global g
    class Special:
        def __del__(self):
            print g
    g = (Special(),)
    g = 1234

def test_closure_reassignment():
    """
    >>> test_closure_reassignment()
    4321
    """
    class Special:
        def __del__(self):
            print c
    c = (Special(),)
    c = 4321
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extinherit.pyx0000644000175100001770000000077300000000000020476 0ustar00runnerdocker00000000000000cdef class Parrot:
    cdef object name
    cdef int alive

cdef class Norwegian(Parrot):
    cdef object plumage_colour

def create():
    cdef Parrot p
    p = Norwegian()
    p.alive = 1
    return p

def rest(Norwegian polly):
    """
    >>> p = create()
    >>> rest(p)
    0
    """
    cdef Parrot fred
    cdef object spam
    spam = None

    fred = polly
    polly = fred
    polly = spam
    assert polly is None
    assert fred.alive

    spam = polly
    fred.alive = 0

    return fred.alive
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extinstantiate.pyx0000644000175100001770000000017200000000000021350 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> type(f()).__name__
    'Spam'
"""

cdef class Spam:
    pass

def f():
    s = Spam()
    return s
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extkwonlyargs.pyx0000644000175100001770000000561400000000000021233 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> ext = Ext()
    >>> b,c,d,e,f,g,h,k = ext.b,ext.c,ext.d,ext.e,ext.f,ext.g,ext.h,ext.k

"""

cdef class Ext:
    def b(self, a, b, c):
        pass

    def c(self, a, b, c=1):
        pass

    def d(self, a, b, *, c = 88):
        pass

    def e(self, a, b, c = 88, **kwds):
        pass

    def f(self, a, b, *, c, d = 42):
        pass

    def g(self, a, b, *, c, d = 42, e = 17, f, **kwds):
        pass

    def h(self, a, b, *args, c, d = 42, e = 17, f, **kwds):
        pass

    def k(self, a, b, c=1, *args, d = 42, e = 17, f, **kwds):
        pass
"""# c
    >>> c(1,2)
    >>> c(1,2,3)
    >>> c(1,2,3,4)
    Traceback (most recent call last):
    TypeError: c() takes at most 3 positional arguments (4 given)

# b
    >>> b(1,2,3)
    >>> b(1,2,3,4)
    Traceback (most recent call last):
    TypeError: b() takes exactly 3 positional arguments (4 given)

# e
    >>> e(1,2)
    >>> e(1,2, c=1)
    >>> e(1,2, d=1)
    >>> e(1,2, c=1, d=2, e=3)
    >>> e(1,2,3)
    >>> e(1,2,3,4)
    Traceback (most recent call last):
    TypeError: e() takes at most 3 positional arguments (4 given)

# d
    >>> d(1,2)
    >>> d(1,2, c=1)

    >>> d(1,2,3)
    Traceback (most recent call last):
    TypeError: d() takes exactly 2 positional arguments (3 given)
    >>> d(1,2, d=1)
    Traceback (most recent call last):
    TypeError: d() got an unexpected keyword argument 'd'

# g
    >>> g(1,2, c=1, f=2)
    >>> g(1,2, c=1, e=0, f=2, d=11)
    >>> g(1,2, c=1, f=2, e=0, x=25)

    >>> g(1,2,3)
    Traceback (most recent call last):
    TypeError: g() takes exactly 2 positional arguments (3 given)
    >>> g(1,2)
    Traceback (most recent call last):
    TypeError: g() needs keyword-only argument c
    >>> g(1,2, c=1)
    Traceback (most recent call last):
    TypeError: g() needs keyword-only argument f

# f
    >>> f(1,2, c=1)
    >>> f(1,2, c=1, d=2)

    >>> f(1,2,3)
    Traceback (most recent call last):
    TypeError: f() takes exactly 2 positional arguments (3 given)
    >>> f(1,2)
    Traceback (most recent call last):
    TypeError: f() needs keyword-only argument c
    >>> f(1,2, c=1, e=2)
    Traceback (most recent call last):
    TypeError: f() got an unexpected keyword argument 'e'

# h
    >>> h(1,2, c=1, f=2)
    >>> h(1,2, c=1, f=2, e=3)
    >>> h(1,2,3,4,5,6, c=1, f=2)
    >>> h(1,2,3,4,5,6, c=1, f=2, e=3, x=25, y=11)

    >>> h(1,2,3)
    Traceback (most recent call last):
    TypeError: h() needs keyword-only argument c
    >>> h(1,2, d=1)
    Traceback (most recent call last):
    TypeError: h() needs keyword-only argument c

# k
    >>> k(1,2, c=1, f=2)
    >>> k(1,2, c=1, f=2, e=3)
    >>> k(1,2,3,4,5,6, d=1, f=2)
    >>> k(1,2,3,4,5,6, d=1, f=2, e=3, x=25, y=11)

    >>> k(1,2,3)
    Traceback (most recent call last):
    TypeError: k() needs keyword-only argument f
    >>> k(1,2, d=1)
    Traceback (most recent call last):
    TypeError: k() needs keyword-only argument f
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extlen.pyx0000644000175100001770000000015000000000000017577 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> len(Spam())
    0
"""

cdef class Spam:

    def __len__(self):
        return 0
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extmember.pxd0000644000175100001770000000005000000000000020242 0ustar00runnerdocker00000000000000cdef class Spam:
    cdef public Spam e
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extmember.pyx0000644000175100001770000000077200000000000020302 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> s = Spam()
    >>> s.e = s
    >>> s.e = 1
    Traceback (most recent call last):
    TypeError: Cannot convert int to extmember.Spam
    >>> s.e is s
    True
    >>> s.e = None

    >>> s = Bot()
    >>> s.e = s
    >>> s.e = 1
    Traceback (most recent call last):
    TypeError: Cannot convert int to extmember.Bot
    >>> s.e is s
    True
    >>> s.e = None
"""

# declared in the pxd
cdef class Spam:
    pass

# not declared in the pxd
cdef class Bot:
    cdef public Bot e
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extpropertyref.pyx0000644000175100001770000000167700000000000021421 0ustar00runnerdocker00000000000000# cython: autotestdict=True

cdef class Spam:

    property eggs:

        def __get__(self):
            """
            This is the docstring for Spam.eggs.__get__

            >>> True
            True
            """
            return 42

def tomato():
    """
    >>> tomato()
    42

    >>> lines = __test__.keys()
    >>> len(lines)
    3
    >>> 'Spam.eggs.__get__ (line 7)' in lines or lines
    True
    >>> 'tomato (line 16)' in lines or lines
    True
    """
    cdef Spam spam
    cdef object lettuce
    spam = Spam()
    lettuce = spam.eggs
    return lettuce

cdef class Bacon(object):
    cdef object number_of_slices
    cdef public object is_a_vegetable

def breakfast():
    """
    >>> breakfast()
    """
    cdef Bacon myslices = Bacon()
    myslices.is_a_vegetable = True
    assert myslices.is_a_vegetable, myslices.is_a_vegetable
    del myslices.is_a_vegetable
    assert myslices.is_a_vegetable is None, myslices.is_a_vegetable
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extra_walrus.py0000644000175100001770000001042500000000000020636 0ustar00runnerdocker00000000000000# mode: run
# tag: pure3.8

# These are extra tests for the assignment expression/walrus operator/named expression that cover things
# additional to the standard Python test-suite in tests/run/test_named_expressions.pyx

import cython
import sys

@cython.test_assert_path_exists("//PythonCapiCallNode")
def optimized(x):
    """
    x*2 is optimized to a PythonCapiCallNode. The test fails unless the CloneNode is kept up-to-date
    (in the event that the optimization changes and test_assert_path_exists fails, the thing to do
    is to find another case that's similarly optimized - the test isn't specifically interested in
    multiplication)

    >>> optimized(5)
    10
    """
    return (x:=x*2)

# FIXME: currently broken; GH-4146
# Changing x in the assignment expression should not affect the value used on the right-hand side
#def order(x):
#    """
#    >>> order(5)
#    15
#    """
#    return x+(x:=x*2)

@cython.test_fail_if_path_exists("//CloneNode")
def optimize_literals1():
    """
    There's a small optimization for literals to avoid creating unnecessary temps
    >>> optimize_literals1()
    10
    """
    x = 5
    return (x := 10)

@cython.test_fail_if_path_exists("//CloneNode")
def optimize_literals2():
    """
    There's a small optimization for literals to avoid creating unnecessary temps
    Test is in __doc__ (for Py2 string formatting reasons)
    """
    x = 5
    return (x := u"a string")

@cython.test_fail_if_path_exists("//CloneNode")
def optimize_literals3():
    """
    There's a small optimization for literals to avoid creating unnecessary temps
    Test is in __doc__ (for Py2 string formatting reasons)
    """
    x = 5
    return (x := b"a bytes")

@cython.test_fail_if_path_exists("//CloneNode")
def optimize_literals4():
    """
    There's a small optimization for literals to avoid creating unnecessary temps
    Test is in __doc__ (for Py2 string formatting reasons)
    """
    x = 5
    return (x := (u"tuple", 1, 1.0, b"stuff"))

if sys.version_info[0] != 2:
    __doc__ = """
        >>> optimize_literals2()
        'a string'
        >>> optimize_literals3()
        b'a bytes'
        >>> optimize_literals4()
        ('tuple', 1, 1.0, b'stuff')
        """
else:
    __doc__ = """
        >>> optimize_literals2()
        u'a string'
        >>> optimize_literals3()
        'a bytes'
        >>> optimize_literals4()
        (u'tuple', 1, 1.0, 'stuff')
        """


@cython.test_fail_if_path_exists("//CoerceToPyTypeNode//AssignmentExpressionNode")
def avoid_extra_coercion(x : cython.double):
    """
    The assignment expression and x are both coerced to PyObject - this should happen only once
    rather than to both separately
    >>> avoid_extra_coercion(5.)
    5.0
    """
    y : object = "I'm an object"
    return (y := x)

async def async_func():
    """
    DW doesn't understand async functions well enough to make it a runtime test, but it was causing
    a compile-time failure at one point
    """
    if variable := 1:
        pass

y_global = 6

class InLambdaInClass:
    """
    >>> InLambdaInClass.x1
    12
    >>> InLambdaInClass.x2
    [12, 12]
    """
    x1 = (lambda y_global: (y_global := y_global + 1) + y_global)(2) + y_global
    x2 = [(lambda y_global: (y_global := y_global + 1) + y_global)(2) + y_global for _ in range(2) ]

def in_lambda_in_list_comprehension1():
    """
    >>> in_lambda_in_list_comprehension1()
    [[0, 2, 4, 6], [0, 2, 4, 6], [0, 2, 4, 6], [0, 2, 4, 6], [0, 2, 4, 6]]
    """
    return [ (lambda x: [(x := y) + x for y in range(4)])(x) for x in range(5) ]

def in_lambda_in_list_comprehension2():
    """
    >>> in_lambda_in_list_comprehension2()
    [[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7]]
    """
    return [ (lambda z: [(x := y) + z for y in range(4)])(x) for x in range(5) ]

def in_lambda_in_generator_expression1():
    """
    >>> in_lambda_in_generator_expression1()
    [(0, 2, 4, 6), (0, 2, 4, 6), (0, 2, 4, 6), (0, 2, 4, 6), (0, 2, 4, 6)]
    """
    return [ (lambda x: tuple((x := y) + x for y in range(4)))(x) for x in range(5) ]

def in_lambda_in_generator_expression2():
    """
    >>> in_lambda_in_generator_expression2()
    [(0, 1, 2, 3), (1, 2, 3, 4), (2, 3, 4, 5), (3, 4, 5, 6), (4, 5, 6, 7)]
    """
    return [ (lambda z: tuple((x := y) + z for y in range(4)))(x) for x in range(5) ]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/extstarargs.pyx0000644000175100001770000001170100000000000020653 0ustar00runnerdocker00000000000000cimport cython

cdef sorteditems(d):
    return tuple(sorted(d.items()))


cdef class Silly:

    def __init__(self, *a):
        """
        >>> s = Silly(1,2,3, 'test')
        """

    def spam(self, x, y, z):
        """
        >>> s = Silly()
        >>> s.spam(1,2,3)
        (1, 2, 3)
        >>> s.spam(1,2)
        Traceback (most recent call last):
        TypeError: spam() takes exactly 3 positional arguments (2 given)
        >>> s.spam(1,2,3,4)
        Traceback (most recent call last):
        TypeError: spam() takes exactly 3 positional arguments (4 given)
        >>> s.spam(1,2,3, a=1)
        Traceback (most recent call last):
        TypeError: spam() got an unexpected keyword argument 'a'
        """
        return (x, y, z)

    def grail(self, x, y, z, *a):
        """
        >>> s = Silly()
        >>> s.grail(1,2,3)
        (1, 2, 3, ())
        >>> s.grail(1,2,3,4)
        (1, 2, 3, (4,))
        >>> s.grail(1,2,3,4,5,6,7,8,9)
        (1, 2, 3, (4, 5, 6, 7, 8, 9))
        >>> s.grail(1,2)
        Traceback (most recent call last):
        TypeError: grail() takes at least 3 positional arguments (2 given)
        >>> s.grail(1,2,3, a=1)
        Traceback (most recent call last):
        TypeError: grail() got an unexpected keyword argument 'a'
        """
        return (x, y, z, a)

    def swallow(self, x, y, z, **k):
        """
        >>> s = Silly()
        >>> s.swallow(1,2,3)
        (1, 2, 3, ())
        >>> s.swallow(1,2,3,4)
        Traceback (most recent call last):
        TypeError: swallow() takes exactly 3 positional arguments (4 given)
        >>> s.swallow(1,2,3, a=1, b=2)
        (1, 2, 3, (('a', 1), ('b', 2)))
        >>> s.swallow(1,2,3, x=1)
        Traceback (most recent call last):
        TypeError: swallow() got multiple values for keyword argument 'x'
        """
        return (x, y, z, sorteditems(k))

    def creosote(self, x, y, z, *a, **k):
        """
        >>> s = Silly()
        >>> s.creosote(1,2,3)
        (1, 2, 3, (), ())
        >>> s.creosote(1,2,3,4)
        (1, 2, 3, (4,), ())
        >>> s.creosote(1,2,3, a=1)
        (1, 2, 3, (), (('a', 1),))
        >>> s.creosote(1,2,3,4, a=1, b=2)
        (1, 2, 3, (4,), (('a', 1), ('b', 2)))
        >>> s.creosote(1,2,3,4, x=1)
        Traceback (most recent call last):
        TypeError: creosote() got multiple values for keyword argument 'x'
        """
        return (x, y, z, a, sorteditems(k))

    def onlyt(self, *a):
        """
        >>> s = Silly()
        >>> s.onlyt(1)
        (1,)
        >>> s.onlyt(1,2)
        (1, 2)
        >>> s.onlyt(a=1)
        Traceback (most recent call last):
        TypeError: onlyt() got an unexpected keyword argument 'a'
        >>> s.onlyt(1, a=2)
        Traceback (most recent call last):
        TypeError: onlyt() got an unexpected keyword argument 'a'
        """
        return a

    @cython.binding(False)  # passthrough of exact same tuple can't work with binding
    def onlyt_nobinding(self, *a):
        """
        >>> s = Silly()
        >>> s.onlyt_nobinding(1)
        (1,)
        >>> s.onlyt_nobinding(1,2)
        (1, 2)
        >>> s.onlyt_nobinding(a=1)
        Traceback (most recent call last):
        TypeError: onlyt_nobinding() got an unexpected keyword argument 'a'
        >>> s.onlyt_nobinding(1, a=2)
        Traceback (most recent call last):
        TypeError: onlyt_nobinding() got an unexpected keyword argument 'a'
        >>> test_no_copy_args(s.onlyt_nobinding)
        True
        """
        return a

    def onlyk(self, **k):
        """
        >>> s = Silly()
        >>> s.onlyk(a=1)
        (('a', 1),)
        >>> s.onlyk(a=1, b=2)
        (('a', 1), ('b', 2))
        >>> s.onlyk(1)
        Traceback (most recent call last):
        TypeError: onlyk() takes exactly 0 positional arguments (1 given)
        >>> s.onlyk(1, 2)
        Traceback (most recent call last):
        TypeError: onlyk() takes exactly 0 positional arguments (2 given)
        >>> s.onlyk(1, a=1, b=2)
        Traceback (most recent call last):
        TypeError: onlyk() takes exactly 0 positional arguments (1 given)
        """
        return sorteditems(k)

    def tk(self, *a, **k):
        """
        >>> s = Silly()
        >>> s.tk(a=1)
        (('a', 1),)
        >>> s.tk(a=1, b=2)
        (('a', 1), ('b', 2))
        >>> s.tk(1)
        (1,)
        >>> s.tk(1, 2)
        (1, 2)
        >>> s.tk(1, a=1, b=2)
        (1, ('a', 1), ('b', 2))
        """
        return a + sorteditems(k)

    @cython.binding(False)  # passthrough of exact same tuple can't work with binding
    def t_kwonly(self, *a, k):
        """
        >>> s = Silly()
        >>> test_no_copy_args(s.t_kwonly, k=None)
        True
        """
        return a


def test_no_copy_args(func, **kw):
    """
    func is a function such that func(*args, **kw) returns args.
    We test that no copy is made of the args tuple.
    This tests both the caller side and the callee side.
    """
    args = (1, 2, 3)
    return func(*args, **kw) is args
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/exttype.pyx0000644000175100001770000000304400000000000020007 0ustar00runnerdocker00000000000000# mode: run
# tag: exttype, tpnew

from __future__ import print_function

from cpython.object cimport PyTypeObject


cdef gobble(a, b):
    print(a, b)


def tp_new_ptr(exttype):
    assert isinstance(exttype, type)
    tp =  exttype
    return tp.tp_new


cdef class Empty:
    """
    >>> n = Empty()
    >>> isinstance(n, Empty)
    True
    >>> tp_new_ptr(Empty) != 0
    True
    """


cdef class EmptySubclass(Empty):
    """
    >>> n = EmptySubclass()
    >>> isinstance(n, EmptySubclass)
    True
    >>> tp_new_ptr(EmptySubclass) != 0
    True
    >>> tp_new_ptr(EmptySubclass) == tp_new_ptr(Empty)
    True
    """


cdef class CInit:
    """
    >>> c = CInit()
    >>> isinstance(c, CInit)
    True
    """
    def __cinit__(self):
        assert self is not None


cdef class Spam:
    """
    >>> s = Spam(12)
    >>> s.eat()
    12 42
    """
    cdef eggs
    cdef int ham

    def __cinit__(self, eggs):
        self.eggs = eggs
        self.ham = 42

    def __dealloc__(self):
        self.ham = 0

    def eat(self):
        gobble(self.eggs, self.ham)


def f(Spam spam):
    """
    >>> s = Spam(12)
    >>> f(s)   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    AttributeError: '...Spam' object has no attribute 'foo'
    >>> s.eat()
    12 42
    >>> class Spam2(Spam):
    ...     foo = 1
    >>> s = Spam2(12)
    >>> s.eat()
    12 42
    >>> f(s)
    >>> s.eat()
    12 42
    """
    x = spam.eggs
    y = spam.ham
    z = spam.foo
    spam.eggs = x
    spam.ham = y
    spam.foo = z
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/exttype_dealloc.pyx0000644000175100001770000000631300000000000021474 0ustar00runnerdocker00000000000000# mode: run
# tag: dealloc

import gc
import sys


test_results = []


cdef void add_name(obj):
    name = type(obj).__name__.rsplit('.', 1)[-1]
    test_results.append(name)


def find_name(exttype):
    name = exttype.__name__.rsplit('.', 1)[-1]
    return test_results.count(name)


cdef class ExtTypeSimple:
    """
    >>> obj = ExtTypeSimple()
    >>> find_name(ExtTypeSimple)
    0
    >>> obj = None
    >>> _ = gc.collect()
    >>> find_name(ExtTypeSimple)
    1
    """
    cdef int x
    def __dealloc__(self):
        add_name(self)
        self.x = 0


class PySubTypeSimple(ExtTypeSimple):
    """
    >>> obj = PySubTypeSimple()
    >>> find_name(PySubTypeSimple)
    0
    >>> obj = None
    >>> _ = gc.collect()
    >>> find_name(PySubTypeSimple)
    1
    """


class PySubTypeDel(ExtTypeSimple):
    """
    >>> obj = PySubTypeDel()
    >>> find_name(PySubTypeDel)
    0
    >>> obj = None
    >>> _ = gc.collect()
    >>> find_name(PySubTypeDel)
    2
    """
    def __del__(self):
        add_name(self)


cdef class ExtSubTypeObjAttr(ExtTypeSimple):
    """
    >>> obj = ExtSubTypeObjAttr()
    >>> find_name(ExtSubTypeObjAttr)
    0
    >>> obj = None
    >>> _ = gc.collect()

    # both this type and the base class add the same name
    >>> find_name(ExtSubTypeObjAttr)
    2
    """
    cdef object attr
    def __dealloc__(self):
        add_name(self)
        self.x = 1


cdef class ExtTypeRaise:
    """
    >>> obj = ExtTypeRaise()
    >>> find_name(ExtTypeRaise)
    0
    >>> obj = None
    >>> _ = gc.collect()
    >>> find_name(ExtTypeRaise)
    1
    """
    def __dealloc__(self):
        add_name(self)
        raise RuntimeError("HUHU !")


class PySubTypeRaise(ExtTypeRaise):
    """
    >>> obj = PySubTypeRaise()
    >>> obj.ref = obj
    >>> find_name(PySubTypeRaise)
    0
    >>> obj = None
    >>> _ = gc.collect()
    >>> find_name(PySubTypeRaise)
    1
    """


cdef class ExtTypeRefCycle:
    """
    >>> obj = ExtTypeRefCycle()
    >>> obj.ref = obj
    >>> find_name(ExtTypeRefCycle)
    0
    >>> obj = None
    >>> _ = gc.collect()
    >>> find_name(ExtTypeRefCycle)
    1
    """
    cdef public object ref
    cdef int x
    def __dealloc__(self):
        add_name(self)
        self.x = 1


class PySubTypeRefCycleDel(ExtTypeRefCycle):
    """
    >>> obj = PySubTypeRefCycleDel()
    >>> obj.ref = obj
    >>> find_name(PySubTypeRefCycleDel)
    0
    >>> obj = None
    >>> _ = gc.collect()

    >>> count = 2
    >>> if sys.version_info >= (3, 4):
    ...     count = find_name(PySubTypeRefCycleDel)
    >>> count
    2
    """
    def __del__(self):
        add_name(self)


cdef class ExtTypeRefCycleRaise:
    """
    >>> obj = ExtTypeRefCycleRaise()
    >>> obj.ref = obj
    >>> find_name(ExtTypeRefCycleRaise)
    0
    >>> obj = None
    >>> _ = gc.collect()
    >>> find_name(ExtTypeRefCycleRaise)
    1
    """
    cdef public object ref
    def __dealloc__(self):
        add_name(self)
        raise RuntimeError("Cleaning up !")


class PySubTypeRefCycleRaise(ExtTypeRefCycleRaise):
    """
    >>> obj = PySubTypeRefCycleRaise()
    >>> obj.ref = obj
    >>> find_name(PySubTypeRefCycleRaise)
    0
    >>> obj = None
    >>> _ = gc.collect()
    >>> find_name(PySubTypeRefCycleRaise)
    1
    """
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/exttype_freelist.pyx0000644000175100001770000002564500000000000021717 0ustar00runnerdocker00000000000000# mode: run
# tag: freelist, cyclicgc

cimport cython

@cython.freelist(4)
cdef class ExtTypeNoGC:
    """
    >>> obj = ExtTypeNoGC()
    >>> obj = ExtTypeNoGC()
    >>> obj = ExtTypeNoGC()
    >>> obj = ExtTypeNoGC()
    >>> obj = ExtTypeNoGC()
    >>> obj = ExtTypeNoGC()

    >>> class PyClass(ExtTypeNoGC): a = 1
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj

    >>> class PyClass(ExtTypeNoGC): __slots__ = ()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj
    """


cdef class ExtSubTypeNoGC(ExtTypeNoGC):
    """
    >>> obj = ExtSubTypeNoGC()
    >>> obj = ExtSubTypeNoGC()
    >>> obj = ExtSubTypeNoGC()
    >>> obj = ExtSubTypeNoGC()
    >>> obj = ExtSubTypeNoGC()
    >>> obj = ExtSubTypeNoGC()

    >>> class PyClass(ExtSubTypeNoGC): a = 1
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj

    >>> class PyClass(ExtSubTypeNoGC): __slots__ = ()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj
    """
    cdef bytes x


@cython.freelist(4)
cdef class ExtTypeWithGC:
    """
    >>> obj = ExtTypeWithGC()
    >>> obj = ExtTypeWithGC()
    >>> obj = ExtTypeWithGC()
    >>> obj = ExtTypeWithGC()
    >>> obj = ExtTypeWithGC()
    >>> obj = ExtTypeWithGC()

    >>> class PyClass(ExtTypeWithGC): a = 1
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj

    >>> class PyClass(ExtTypeWithGC): __slots__ = ()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj
    """
    cdef attribute

    def __init__(self):
        self.attribute = object()


def tpnew_ExtTypeWithGC():
    """
    >>> obj = tpnew_ExtTypeWithGC()
    >>> obj = tpnew_ExtTypeWithGC()
    >>> obj = tpnew_ExtTypeWithGC()
    >>> obj = tpnew_ExtTypeWithGC()
    >>> obj = tpnew_ExtTypeWithGC()
    >>> obj = tpnew_ExtTypeWithGC()
    """
    return ExtTypeWithGC.__new__(ExtTypeWithGC)


cdef class ExtSubType(ExtTypeWithGC):
    """
    >>> obj = ExtSubType()
    >>> obj = ExtSubType()
    >>> obj = ExtSubType()
    >>> obj = ExtSubType()
    >>> obj = ExtSubType()
    >>> obj = ExtSubType()

    >>> class PyClass(ExtSubType): a = 1
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj

    >>> class PyClass(ExtSubType): __slots__ = ()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj
    """


cdef class LargerExtSubType(ExtSubType):
    """
    >>> obj = LargerExtSubType()
    >>> obj = LargerExtSubType()
    >>> obj = LargerExtSubType()
    >>> obj = LargerExtSubType()
    >>> obj = LargerExtSubType()
    >>> obj = LargerExtSubType()

    >>> class PyClass(LargerExtSubType): a = 1
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj

    >>> class PyClass(LargerExtSubType): __slots__ = ()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj
    """
    cdef attribute2

    def __cinit__(self):
        self.attribute2 = object()


@cython.freelist(4)
cdef class ExtTypeWithCAttr:
    """
    >>> obj = ExtTypeWithCAttr()
    >>> obj = ExtTypeWithCAttr()
    >>> obj = ExtTypeWithCAttr()
    >>> obj = ExtTypeWithCAttr()
    >>> obj = ExtTypeWithCAttr()
    >>> obj = ExtTypeWithCAttr()

    >>> class PyClass(ExtTypeWithCAttr): a = 1
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj

    >>> class PyClass(ExtTypeWithCAttr): __slots__ = ()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj
    """
    cdef int cattr

    def __cinit__(self):
        assert self.cattr == 0
        self.cattr = 1


cdef class ExtSubTypeWithCAttr(ExtTypeWithCAttr):
    """
    >>> obj = ExtSubTypeWithCAttr()
    >>> obj = ExtSubTypeWithCAttr()
    >>> obj = ExtSubTypeWithCAttr()
    >>> obj = ExtSubTypeWithCAttr()
    >>> obj = ExtSubTypeWithCAttr()
    >>> obj = ExtSubTypeWithCAttr()

    >>> class PyClass(ExtSubTypeWithCAttr): a = 1
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()

    >>> class PyClass(ExtSubTypeWithCAttr): __slots__ = ()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    """


cdef class ExtTypeWithCAttrNoFreelist:
    """
    For comparison with normal CPython instantiation.

    >>> obj = ExtTypeWithCAttrNoFreelist()
    >>> obj = ExtTypeWithCAttrNoFreelist()
    >>> obj = ExtTypeWithCAttrNoFreelist()
    >>> obj = ExtTypeWithCAttrNoFreelist()
    >>> obj = ExtTypeWithCAttrNoFreelist()
    >>> obj = ExtTypeWithCAttrNoFreelist()

    >>> class PyClass(ExtTypeWithCAttrNoFreelist): a = 1
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj

    >>> class PyClass(ExtTypeWithCAttrNoFreelist): __slots__ = ()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj
    """
    cdef int cattr

    def __cinit__(self):
        assert self.cattr == 0
        self.cattr = 1


@cython.freelist(4)
cdef class ExtTypeWithCMethods:
    """
    >>> obj = ExtTypeWithCMethods()
    >>> test_cmethods(obj)
    (1, 2)
    >>> obj = ExtTypeWithCMethods()
    >>> test_cmethods(obj)
    (1, 2)
    >>> obj = ExtTypeWithCMethods()
    >>> test_cmethods(obj)
    (1, 2)
    >>> obj = ExtTypeWithCMethods()
    >>> test_cmethods(obj)
    (1, 2)
    >>> obj = ExtTypeWithCMethods()
    >>> test_cmethods(obj)
    (1, 2)
    >>> obj = ExtTypeWithCMethods()
    >>> test_cmethods(obj)
    (1, 2)

    >>> class PyClass(ExtTypeWithCMethods): a = 1
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> test_cmethods(obj)
    (1, 2)
    >>> obj = PyClass()
    >>> test_cmethods(obj)
    (1, 2)
    >>> obj = PyClass()
    >>> del PyClass, obj

    >>> class PyClass(ExtTypeWithCMethods): __slots__ = ()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> test_cmethods(obj)
    (1, 2)
    >>> obj = PyClass()
    >>> test_cmethods(obj)
    (1, 2)
    >>> obj = PyClass()
    >>> del PyClass, obj
    """
    cdef int cattr

    def __cinit__(self):
        assert self.cattr == 0
        self.cattr = 1

    cdef int get_cattr(self):
        return self.cattr

    cdef set_cattr(self, int value):
        self.cattr = value


def test_cmethods(ExtTypeWithCMethods obj not None):
    x = obj.get_cattr()
    obj.set_cattr(2)
    return x, obj.get_cattr()


cdef class ExtSubTypeWithCMethods(ExtTypeWithCMethods):
    """
    >>> obj = ExtSubTypeWithCMethods()
    >>> test_cmethods(obj)
    (1, 2)
    >>> obj = ExtSubTypeWithCMethods()
    >>> test_cmethods(obj)
    (1, 2)
    >>> obj = ExtSubTypeWithCMethods()
    >>> test_cmethods(obj)
    (1, 2)
    >>> obj = ExtSubTypeWithCMethods()
    >>> test_cmethods(obj)
    (1, 2)
    >>> obj = ExtSubTypeWithCMethods()
    >>> test_cmethods(obj)
    (1, 2)
    >>> obj = ExtSubTypeWithCMethods()
    >>> test_cmethods(obj)
    (1, 2)

    >>> class PyClass(ExtSubTypeWithCMethods): a = 1
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj

    >>> class PyClass(ExtSubTypeWithCMethods): __slots__ = ()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj
    """


cdef class ExtSubTypeWithMoreCMethods(ExtSubTypeWithCMethods):
    """
    >>> obj = ExtSubTypeWithMoreCMethods()
    >>> test_more_cmethods(obj)
    (2, 3, 3)
    >>> obj = ExtSubTypeWithCMethods()
    >>> test_cmethods(obj)
    (1, 2)
    >>> obj = ExtTypeWithCMethods()
    >>> test_cmethods(obj)
    (1, 2)
    >>> obj = ExtSubTypeWithMoreCMethods()
    >>> test_more_cmethods(obj)
    (2, 3, 3)
    >>> obj2 = ExtSubTypeWithMoreCMethods()
    >>> test_more_cmethods(obj2)
    (2, 3, 3)
    >>> obj2 = ExtSubTypeWithCMethods()
    >>> test_cmethods(obj2)
    (1, 2)
    >>> obj = ExtSubTypeWithMoreCMethods()
    >>> test_more_cmethods(obj)
    (2, 3, 3)
    >>> obj2 = ExtTypeWithCMethods()
    >>> test_cmethods(obj2)
    (1, 2)
    >>> obj = ExtSubTypeWithMoreCMethods()
    >>> test_more_cmethods(obj)
    (2, 3, 3)
    >>> obj2 = ExtSubTypeWithCMethods()
    >>> test_cmethods(obj2)
    (1, 2)
    >>> obj = ExtSubTypeWithMoreCMethods()
    >>> test_more_cmethods(obj)
    (2, 3, 3)
    >>> obj2 = ExtSubTypeWithCMethods()
    >>> test_cmethods(obj2)
    (1, 2)
    >>> obj = ExtTypeWithCMethods()
    >>> test_cmethods(obj)
    (1, 2)

    >>> class PyClass(ExtSubTypeWithMoreCMethods): a = 1
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj

    >>> class PyClass(ExtSubTypeWithMoreCMethods): __slots__ = ()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj
    """
    def __cinit__(self):
        assert self.cattr == 1
        self.cattr = 2

    cdef int get_cattr2(self):
        return self.cattr

    cdef set_cattr2(self, int value):
        self.cattr = value


def test_more_cmethods(ExtSubTypeWithMoreCMethods obj not None):
    x = obj.get_cattr()
    assert obj.get_cattr2() == x
    obj.set_cattr2(2)
    assert obj.get_cattr2() == 2
    obj.set_cattr(3)
    return x, obj.get_cattr(), obj.get_cattr2()


@cython.freelist(4)
cdef class ExtTypeWithRefCycle:
    """
    >>> obj = first = ExtTypeWithRefCycle()
    >>> obj.attribute is None
    True
    >>> obj = ExtTypeWithRefCycle(obj)
    >>> obj.attribute is first
    True
    >>> obj = ExtTypeWithRefCycle(obj)
    >>> obj = ExtTypeWithRefCycle(obj)
    >>> obj = ExtTypeWithRefCycle(obj)
    >>> obj = ExtTypeWithRefCycle(obj)
    >>> obj.attribute is not None
    True
    >>> first.attribute = obj
    >>> del obj, first

    >>> class PyClass(ExtTypeWithRefCycle): a = 1
    >>> obj = PyClass()
    >>> obj.attribute = obj
    >>> obj.attribute = PyClass(obj)
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj

    >>> class PyClass(ExtTypeWithRefCycle): __slots__ = ()
    >>> obj = PyClass()
    >>> obj.attribute = obj
    >>> obj.attribute = PyClass(obj)
    >>> obj = PyClass()
    >>> obj = PyClass()
    >>> del PyClass, obj
    """
    cdef public attribute

    def __init__(self, obj=None):
        self.attribute = obj


@cython.freelist(3)
@cython.cclass
class DecoratedPyClass(object):
    """
    >>> obj1 = DecoratedPyClass()
    >>> obj2 = DecoratedPyClass()
    >>> obj3 = DecoratedPyClass()
    >>> obj4 = DecoratedPyClass()

    >>> obj1 = DecoratedPyClass()
    >>> obj2 = DecoratedPyClass()
    >>> obj3 = DecoratedPyClass()
    >>> obj4 = DecoratedPyClass()
    """
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/exttype_gc.pyx0000644000175100001770000000133700000000000020463 0ustar00runnerdocker00000000000000# mode: run
# tag: gc


def create_obj(cls):
    cls()  # create and discard


cdef class BaseTypeNoGC:
    pass


cdef class ExtTypeGC(BaseTypeNoGC):
    """
    >>> create_obj(ExtTypeGC)
    >>> create_obj(ExtTypeGC)
    >>> create_obj(ExtTypeGC)

    >>> class PyExtTypeGC(ExtTypeGC): pass
    >>> create_obj(PyExtTypeGC)
    >>> create_obj(PyExtTypeGC)
    >>> create_obj(PyExtTypeGC)
    """
    cdef object attr


cdef class ExtTypeNoGC(BaseTypeNoGC):
    """
    >>> create_obj(ExtTypeNoGC)
    >>> create_obj(ExtTypeNoGC)
    >>> create_obj(ExtTypeNoGC)

    >>> class PyExtTypeNoGC(ExtTypeNoGC): pass
    >>> create_obj(PyExtTypeNoGC)
    >>> create_obj(PyExtTypeNoGC)
    >>> create_obj(PyExtTypeNoGC)
    """
    cdef int x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/exttype_total_ordering.pyx0000644000175100001770000005666400000000000023123 0ustar00runnerdocker00000000000000# mode: run
# tag: total_ordering

from __future__ import print_function

"""
    >>> class PyTotalOrdering:
    ...     def __init__(self, value):
    ...         self.value = value
    ...     def __eq__(self, other):
    ...         return self.value == other.value
    ...     def __lt__(self, other):
    ...         return self.value < other.value
    >>> test_all_comp(functools.total_ordering(PyTotalOrdering))
    True
"""

cimport cython
import functools
from functools import total_ordering as total_ordering_by_another_name
import operator

COMPARISONS = [
    # Don't test equals, the directive doesn't add that.
    # ('==', operator.__eq__),
    ('!=', operator.__ne__),
    ('<',  operator.__lt__),
    ('>',  operator.__gt__),
    ('<=', operator.__le__),
    ('>=', operator.__ge__),
]

def test_all_comp(cls):
    """Check every combination of comparison operators."""
    a, b, c = 10, 15, 20
    succeeded = True
    for comp, func in COMPARISONS:
        for left in [cls(a), cls(b), cls(c)]:
            for right in [ValueHolder(a), ValueHolder(b), ValueHolder(c)]:
                expected = func(left.value, right.value)
                try:
                    result = func(left, right)
                    # repeat to rule out deallocation bugs (and assert determinism)
                    for _ in range(10):
                        assert result == func(left, right)
                except TypeError:
                    print("TypeError:", left.value, comp, right.value)
                    succeeded = False
                else:
                    if expected != result:
                        print(
                            left.value, comp, right.value,
                            "expected:", expected, "got:", result
                        )
                        succeeded = False
    return succeeded

class ValueHolder:
    """Has a value, but can't compare."""
    def __init__(self, value):
        self.value = value



cdef class ExtTypeNoTotalOrdering:
    """
    >>> a = ExtTypeNoTotalOrdering(5)
    >>> b = ExtTypeNoTotalOrdering(10)
    >>> a == b
    False
    >>> a != b  # Added in Python 3, but Cython backports
    True
    >>> a < b
    True
    >>> b < a
    False
    >>> a > b
    False
    >>> b > a
    True
    >>> import sys
    >>> try: _ =  a >= b
    ... except TypeError:
    ...     assert sys.version_info[0] >= 3
    ... else:
    ...     assert sys.version_info[0] < 3
    >>> try: _ =  a <= b
    ... except TypeError:
    ...     assert sys.version_info[0] >= 3
    ... else:
    ...     assert sys.version_info[0] < 3
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __lt__(self, other):
        return self.value < other.value

    def __eq__(self, other):
        return self.value == other.value

# Every combination of methods which is valid.

@cython.total_ordering
cdef class ExtTypeTotalOrderingNeGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingNeGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __ne__(self, other):
        return self.value != other.value

    def __ge__(self, other):
        return self.value >= other.value

@functools.total_ordering
cdef class ExtTypeTotalOrderingNeLe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingNeLe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __ne__(self, other):
        return self.value != other.value

    def __le__(self, other):
        return self.value <= other.value

@functools.total_ordering
cdef class ExtTypeTotalOrderingNeLeGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingNeLeGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __ne__(self, other):
        return self.value != other.value

    def __le__(self, other):
        return self.value <= other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingNeGt:
    """
    >>> test_all_comp(ExtTypeTotalOrderingNeGt)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __ne__(self, other):
        return self.value != other.value

    def __gt__(self, other):
        return self.value > other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingNeGtGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingNeGtGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __ne__(self, other):
        return self.value != other.value

    def __gt__(self, other):
        return self.value > other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingNeGtLe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingNeGtLe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __ne__(self, other):
        return self.value != other.value

    def __gt__(self, other):
        return self.value > other.value

    def __le__(self, other):
        return self.value <= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingNeGtLeGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingNeGtLeGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __ne__(self, other):
        return self.value != other.value

    def __gt__(self, other):
        return self.value > other.value

    def __le__(self, other):
        return self.value <= other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingNeLt:
    """
    >>> test_all_comp(ExtTypeTotalOrderingNeLt)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __ne__(self, other):
        return self.value != other.value

    def __lt__(self, other):
        return self.value < other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingNeLtGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingNeLtGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __ne__(self, other):
        return self.value != other.value

    def __lt__(self, other):
        return self.value < other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingNeLtLe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingNeLtLe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __ne__(self, other):
        return self.value != other.value

    def __lt__(self, other):
        return self.value < other.value

    def __le__(self, other):
        return self.value <= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingNeLtLeGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingNeLtLeGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __ne__(self, other):
        return self.value != other.value

    def __lt__(self, other):
        return self.value < other.value

    def __le__(self, other):
        return self.value <= other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingNeLtGt:
    """
    >>> test_all_comp(ExtTypeTotalOrderingNeLtGt)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __ne__(self, other):
        return self.value != other.value

    def __lt__(self, other):
        return self.value < other.value

    def __gt__(self, other):
        return self.value > other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingNeLtGtGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingNeLtGtGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __ne__(self, other):
        return self.value != other.value

    def __lt__(self, other):
        return self.value < other.value

    def __gt__(self, other):
        return self.value > other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingNeLtGtLe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingNeLtGtLe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __ne__(self, other):
        return self.value != other.value

    def __lt__(self, other):
        return self.value < other.value

    def __gt__(self, other):
        return self.value > other.value

    def __le__(self, other):
        return self.value <= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingNeLtGtLeGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingNeLtGtLeGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __ne__(self, other):
        return self.value != other.value

    def __lt__(self, other):
        return self.value < other.value

    def __gt__(self, other):
        return self.value > other.value

    def __le__(self, other):
        return self.value <= other.value

    def __ge__(self, other):
        return self.value >= other.value

@total_ordering_by_another_name
cdef class ExtTypeTotalOrderingEqGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqLe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqLe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __le__(self, other):
        return self.value <= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqLeGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqLeGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __le__(self, other):
        return self.value <= other.value

    def __ge__(self, other):
        return self.value >= other.value

@total_ordering_by_another_name
cdef class ExtTypeTotalOrderingEqGt:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqGt)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __gt__(self, other):
        return self.value > other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqGtGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqGtGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __gt__(self, other):
        return self.value > other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqGtLe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqGtLe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __gt__(self, other):
        return self.value > other.value

    def __le__(self, other):
        return self.value <= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqGtLeGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqGtLeGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __gt__(self, other):
        return self.value > other.value

    def __le__(self, other):
        return self.value <= other.value

    def __ge__(self, other):
        return self.value >= other.value

# cython.total_ordering implicitly means cclass too
@cython.total_ordering
class ExtTypeTotalOrderingEqLt:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqLt)
    True
    """
    _value: int

    @property
    def value(self):
        return self._value  # it's hard to make value public directly in pure syntax

    def __init__(self, val):
        self._value = val

    def __eq__(self, other):
        return self._value == other.value

    def __lt__(self, other):
        return self._value < other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqLtGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqLtGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __lt__(self, other):
        return self.value < other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqLtLe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqLtLe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __lt__(self, other):
        return self.value < other.value

    def __le__(self, other):
        return self.value <= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqLtLeGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqLtLeGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __lt__(self, other):
        return self.value < other.value

    def __le__(self, other):
        return self.value <= other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqLtGt:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqLtGt)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __lt__(self, other):
        return self.value < other.value

    def __gt__(self, other):
        return self.value > other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqLtGtGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqLtGtGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __lt__(self, other):
        return self.value < other.value

    def __gt__(self, other):
        return self.value > other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqLtGtLe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqLtGtLe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __lt__(self, other):
        return self.value < other.value

    def __gt__(self, other):
        return self.value > other.value

    def __le__(self, other):
        return self.value <= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqLtGtLeGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqLtGtLeGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __lt__(self, other):
        return self.value < other.value

    def __gt__(self, other):
        return self.value > other.value

    def __le__(self, other):
        return self.value <= other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqNeGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqNeGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __ne__(self, other):
        return self.value != other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqNeLe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqNeLe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __ne__(self, other):
        return self.value != other.value

    def __le__(self, other):
        return self.value <= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqNeLeGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqNeLeGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __ne__(self, other):
        return self.value != other.value

    def __le__(self, other):
        return self.value <= other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqNeGt:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqNeGt)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __ne__(self, other):
        return self.value != other.value

    def __gt__(self, other):
        return self.value > other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqNeGtGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqNeGtGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __ne__(self, other):
        return self.value != other.value

    def __gt__(self, other):
        return self.value > other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqNeGtLe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqNeGtLe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __ne__(self, other):
        return self.value != other.value

    def __gt__(self, other):
        return self.value > other.value

    def __le__(self, other):
        return self.value <= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqNeGtLeGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqNeGtLeGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __ne__(self, other):
        return self.value != other.value

    def __gt__(self, other):
        return self.value > other.value

    def __le__(self, other):
        return self.value <= other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqNeLt:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqNeLt)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __ne__(self, other):
        return self.value != other.value

    def __lt__(self, other):
        return self.value < other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqNeLtGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqNeLtGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __ne__(self, other):
        return self.value != other.value

    def __lt__(self, other):
        return self.value < other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqNeLtLe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqNeLtLe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __ne__(self, other):
        return self.value != other.value

    def __lt__(self, other):
        return self.value < other.value

    def __le__(self, other):
        return self.value <= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqNeLtLeGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqNeLtLeGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __ne__(self, other):
        return self.value != other.value

    def __lt__(self, other):
        return self.value < other.value

    def __le__(self, other):
        return self.value <= other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqNeLtGt:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqNeLtGt)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __ne__(self, other):
        return self.value != other.value

    def __lt__(self, other):
        return self.value < other.value

    def __gt__(self, other):
        return self.value > other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqNeLtGtGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqNeLtGtGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __ne__(self, other):
        return self.value != other.value

    def __lt__(self, other):
        return self.value < other.value

    def __gt__(self, other):
        return self.value > other.value

    def __ge__(self, other):
        return self.value >= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqNeLtGtLe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqNeLtGtLe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __ne__(self, other):
        return self.value != other.value

    def __lt__(self, other):
        return self.value < other.value

    def __gt__(self, other):
        return self.value > other.value

    def __le__(self, other):
        return self.value <= other.value

@cython.total_ordering
cdef class ExtTypeTotalOrderingEqNeLtGtLeGe:
    """
    >>> test_all_comp(ExtTypeTotalOrderingEqNeLtGtLeGe)
    True
    """
    cdef public int value
    def __init__(self, val):
        self.value = val

    def __eq__(self, other):
        return self.value == other.value

    def __ne__(self, other):
        return self.value != other.value

    def __lt__(self, other):
        return self.value < other.value

    def __gt__(self, other):
        return self.value > other.value

    def __le__(self, other):
        return self.value <= other.value

    def __ge__(self, other):
        return self.value >= other.value
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/fastcall.pyx0000644000175100001770000000610600000000000020100 0ustar00runnerdocker00000000000000# mode: run
# tag: METH_FASTCALL

cimport cython

import sys
import struct
from collections import deque

pack = struct.pack


def deque_methods(v):
    """
    >>> deque_methods(2)
    [1, 2, 3, 4]
    """
    d = deque([1, 3, 4])
    assert list(d) == [1,3,4]
    if sys.version_info >= (3, 5):
        d.insert(1, v)
    else:
        # deque has no 2-args methods in older Python versions
        d.rotate(-1)
        d.appendleft(2)
        d.rotate(1)
    assert list(d) == [1,2,3,4]
    d.rotate(len(d) // 2)
    assert list(d) == [3,4,1,2]
    d.rotate(len(d) // 2)
    assert list(d) == [1,2,3,4]

    return list(d)


def struct_methods(v):
    """
    >>> i, lf, i2, f = struct_methods(2)
    >>> struct.unpack('i', i)
    (2,)
    >>> struct.unpack('i', i2)
    (2,)
    >>> struct.unpack('lf', lf)
    (2, 4.0)
    >>> struct.unpack('f', f)
    (2.0,)
    """
    local_pack = pack
    return [
        struct.pack('i', v),
        struct.pack('lf', v, v*2),
        pack('i', v),
        local_pack('f', v),
    ]


cdef class SelfCast:
    """
    >>> f = SelfCast()
    >>> f.index_of_self([f])
    0
    >>> f.index_of_self([])  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError...
    """
    def index_of_self(self, list orbit not None):
        return orbit.index(self)


cdef extern from *:
    """
    #ifdef NDEBUG
    int DEBUG_MODE = 0;
    #else
    int DEBUG_MODE = 1;
    #endif
    """
    int PyCFunction_GET_FLAGS(op)
    int DEBUG_MODE


def has_fastcall(meth):
    """
    Given a builtin_function_or_method or cyfunction ``meth``,
    return whether it uses ``METH_FASTCALL``.
    """
    # Hardcode METH_FASTCALL constant equal to 0x80 for simplicity
    if sys.version_info >= (3, 11) and DEBUG_MODE:
        # PyCFunction_GET_FLAGS isn't safe to use on cyfunctions in
        # debug mode in Python 3.11 because it does an exact type check
        return True
    return bool(PyCFunction_GET_FLAGS(meth) & 0x80)


def assert_fastcall(meth):
    """
    Assert that ``meth`` uses ``METH_FASTCALL`` if the Python
    implementation supports it.
    """
    # getattr uses METH_FASTCALL on CPython >= 3.7
    if has_fastcall(getattr) and not has_fastcall(meth):
        raise AssertionError(f"{meth} does not use METH_FASTCALL")


@cython.binding(False)
def fastcall_function(**kw):
    """
    >>> assert_fastcall(fastcall_function)
    """
    return kw

@cython.binding(True)
def fastcall_cyfunction(**kw):
    """
    >>> assert_fastcall(fastcall_cyfunction)
    """
    return kw

cdef class Dummy:
    @cython.binding(False)
    def fastcall_method(self, x, *args, **kw):
        """
        >>> assert_fastcall(Dummy().fastcall_method)
        """
        return tuple(args) + tuple(kw)

cdef class CyDummy:
    @cython.binding(True)
    def fastcall_method(self, x, *args, **kw):
        """
        >>> assert_fastcall(CyDummy.fastcall_method)
        """
        return tuple(args) + tuple(kw)

class PyDummy:
    def fastcall_method(self, x, *args, **kw):
        """
        >>> assert_fastcall(PyDummy.fastcall_method)
        """
        return tuple(args) + tuple(kw)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/file_encoding_T740.py0000644000175100001770000000012100000000000021411 0ustar00runnerdocker00000000000000# encoding: koi8-r
# mode: run
# ticket: t740
"""
>>> wtf
'wtf'
"""

wtf = 'wtf'
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/filenames.pxi0000644000175100001770000000002000000000000020217 0ustar00runnerdocker00000000000000spam = u"ftang"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/filenames.pyx0000644000175100001770000000012700000000000020247 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> print(spam)
ftang
>>> foo
42
"""

include "filenames.pxi"

foo = 42
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/final_cdef_class.pyx0000644000175100001770000000141400000000000021543 0ustar00runnerdocker00000000000000
cimport cython

@cython.final
cdef class FinalClass:
    """
    >>> f = FinalClass()
    >>> test_final_class(f)
    Type tested

    >>> try:
    ...     class SubType(FinalClass): pass
    ... except TypeError:
    ...     print('PASSED!')
    PASSED!
    """

cdef class NonFinalClass:
    """
    >>> class SubType(NonFinalClass): pass
    >>> s = SubType()
    """

@cython.final
cdef class FinalSubClass(NonFinalClass):
    """
    >>> f = FinalSubClass()
    >>> test_non_final_class(f)
    Type tested

    >>> try:
    ...     class SubType(FinalSubClass): pass
    ... except TypeError:
    ...     print('PASSED!')
    PASSED!
    """


def test_final_class(FinalClass c):
    print u"Type tested"

def test_non_final_class(NonFinalClass c):
    print u"Type tested"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/final_in_pxd.srctree0000644000175100001770000000313700000000000021571 0ustar00runnerdocker00000000000000PYTHON -c "import a; assert a.__file__.rstrip('co').endswith('.py'), a.__file__; a.test()"
PYTHON setup.py build_ext --inplace
PYTHON -c "import a; assert not a.__file__.rstrip('co').endswith('.py'), a.__file__; a.test()"

######## setup.py ########

from Cython.Build.Dependencies import cythonize

from distutils.core import setup

setup(
    ext_modules = cythonize("a.py"),
    )

######## a.pxd ########

cimport cython

cdef class ExtType:
    @cython.final
    cdef int final_func(self)

@cython.final
cdef class FinalExtType:
    cdef int func(self)

@cython.final
cdef class FinalExtSubType(ExtType):
    cdef int func(self)

cdef class NonFinalSubType(ExtType):
    cdef int func(self)


######## a.py ########

import cython

class ExtType(object):
    @cython.test_assert_path_exists("//CFuncDefNode[@entry.is_final_cmethod=True]")
    def final_func(self):
        return 1

class FinalExtType(object):
    @cython.test_assert_path_exists("//CFuncDefNode[@entry.is_final_cmethod=True]")
    def func(self):
        return 2

class FinalExtSubType(ExtType):
    @cython.test_assert_path_exists("//CFuncDefNode[@entry.is_final_cmethod=True]")
    def func(self):
        return 3

class NonFinalSubType(ExtType):
    @cython.test_assert_path_exists("//CFuncDefNode[@entry.is_final_cmethod=True]")
    @cython.final
    def func(self):
        return 4


def test():
    assert ExtType().final_func() == 1
    assert FinalExtSubType().final_func() == 1
    assert NonFinalSubType().final_func() == 1

    assert FinalExtType().func() == 2
    assert FinalExtSubType().func() == 3
    assert NonFinalSubType().func() == 4
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/final_method_T586.pyx0000644000175100001770000000323300000000000021464 0ustar00runnerdocker00000000000000# mode: run
# ticket: t568

cimport cython

@cython.final
cdef class FinalType(object):
    """
    >>> obj = FinalType()
    >>> obj.test_cdef()
    >>> obj.test_cpdef()
    """

    @cython.test_assert_path_exists("//CFuncDefNode[@entry.is_final_cmethod=True]")
    cdef cdef_method(self):
        pass

    @cython.test_assert_path_exists("//CFuncDefNode[@entry.is_final_cmethod=True]")
    @cython.test_fail_if_path_exists("//CFuncDefNode//OverrideCheckNode")
    cpdef cpdef_method(self):
        pass

    @cython.test_assert_path_exists("//AttributeNode[@entry.is_final_cmethod=True]")
    def test_cdef(self):
        self.cdef_method()

    @cython.test_assert_path_exists("//AttributeNode[@entry.is_final_cmethod=True]")
    def test_cpdef(self):
        self.cpdef_method()


def test_external_call():
    """
    >>> test_external_call()
    """
    f = FinalType()
    return f.cpdef_method()

def test_external_call_in_temp():
    """
    >>> test_external_call_in_temp()
    """
    return FinalType().cpdef_method()


cdef class BaseTypeWithFinalMethods(object):
    """
    >>> obj = BaseTypeWithFinalMethods()
    >>> obj.test_cdef()
    """

    @cython.test_assert_path_exists("//CFuncDefNode[@entry.is_final_cmethod=True]")
    @cython.final
    cdef cdef_method(self):
        pass

    @cython.test_assert_path_exists("//AttributeNode[@entry.is_final_cmethod=True]")
    def test_cdef(self):
        self.cdef_method()


cdef class SubType(BaseTypeWithFinalMethods):
    """
    >>> obj = SubType()
    >>> obj.test_cdef()
    """
    @cython.test_assert_path_exists("//AttributeNode[@entry.is_final_cmethod=True]")
    def test_cdef(self):
        self.cdef_method()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/flatin.pyx0000644000175100001770000000156600000000000017571 0ustar00runnerdocker00000000000000def test_in(s):
    """
    >>> test_in('ABC')
    1
    >>> test_in('abc')
    2
    >>> test_in('X')
    3
    >>> test_in('XYZ')
    4
    >>> test_in('ABCXYZ')
    5
    >>> test_in('')
    5
    """
    if s in (u'ABC', u'BCD', u'ABC'[:3], u'ABC'[::-1], u'ABC'[-1]):
        return 1
    elif s.upper() in (u'ABC', u'BCD'):
        return 2
    elif len(s) in (1,2):
        return 3
    elif len(s) in (3,4):
        return 4
    else:
        return 5

def test_not_in(s):
    """
    >>> test_not_in('abc')
    1
    >>> test_not_in('CDE')
    2
    >>> test_not_in('CDEF')
    3
    >>> test_not_in('BCD')
    4
    """
    if s not in (u'ABC', u'BCD', u'CDE', u'CDEF'):
        return 1
    elif s.upper() not in (u'ABC', u'BCD', u'CDEF'):
        return 2
    elif len(s) not in [3]:
        return 3
    elif len(s) not in [1,2]:
        return 4
    else:
        return 5
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/float_division.pyx0000644000175100001770000001337400000000000021325 0ustar00runnerdocker00000000000000# mode: run
# tag: division


def int_by_float():
    """
    >>> int_by_float()
    0.5
    """
    return 1 / 2.0


def float_by_int():
    """
    >>> float_by_int()
    2.0
    """
    return 2.0 / 1


def float_by_float():
    """
    >>> float_by_float()
    1.5
    """
    return 3.0 / 2.0


def div_by_0(x):
    """
    >>> div_by_0(0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    >>> div_by_0(0.0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    >>> div_by_0(1)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    >>> div_by_0(1.0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    >>> float('inf') / 0.0  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    >>> div_by_0(float('inf'))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    >>> div_by_0(float('-inf'))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    >>> float('nan') / 0.0  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    >>> div_by_0(float('nan'))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    """
    return x / 0.0


def div_1_by(x):
    """
    >>> div_1_by(1.0)
    1.0
    >>> div_1_by(2.0)
    0.5
    >>> div_1_by(0.5)
    2.0
    >>> 1.0 / float('inf')
    0.0
    >>> div_1_by(float('inf'))
    0.0
    >>> div_1_by(float('-inf'))
    -0.0
    >>> div_1_by(float('nan'))
    nan
    >>> div_1_by(0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    >>> div_1_by(0.0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    """
    return 1.0 / x


def div_by_2(x):
    """
    >>> div_by_2(1.0)
    0.5
    >>> float('inf') / 2.0
    inf
    >>> div_by_2(float('inf'))
    inf
    >>> div_by_2(float('-inf'))
    -inf
    >>> float('nan') / 2.0
    nan
    >>> div_by_2(float('nan'))
    nan
    """
    return x / 2.0


def div_by_neg_2(x):
    """
    >>> div_by_neg_2(1.0)
    -0.5
    >>> div_by_neg_2(-1.0)
    0.5
    >>> (-2**14) / (-2.0)
    8192.0
    >>> div_by_neg_2(-2**14)
    8192.0
    >>> (-2**52) / (-2.0)
    2251799813685248.0
    >>> div_by_neg_2(-2**52)
    2251799813685248.0
    >>> (-2**53-1) / (-2.0)
    4503599627370496.0
    >>> div_by_neg_2(-2**53-1)
    4503599627370496.0
    >>> float('inf') / -2.0
    -inf
    >>> div_by_neg_2(float('inf'))
    -inf
    >>> div_by_neg_2(float('-inf'))
    inf
    >>> float('nan') / -2.0
    nan
    >>> div_by_neg_2(float('nan'))
    nan
    """
    return x / -2.0


def div_neg_2_by(x):
    """
    >>> div_neg_2_by(1.0)
    -2.0
    >>> div_neg_2_by(-1)
    2.0
    >>> div_neg_2_by(-2.0)
    1.0
    >>> div_neg_2_by(-2)
    1.0
    >>> -2.0 / float('inf')
    -0.0
    >>> div_neg_2_by(float('inf'))
    -0.0
    >>> div_neg_2_by(float('-inf'))
    0.0
    >>> float('nan') / -2.0
    nan
    >>> div_neg_2_by(float('nan'))
    nan
    >>> div_neg_2_by(0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    >>> div_neg_2_by(0.0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    """
    return (-2.0) / x


def div_by_nan(x):
    """
    >>> 1.0 / float('nan')
    nan
    >>> div_by_nan(1.0)
    nan
    >>> float('nan') / float('nan')
    nan
    >>> div_by_nan(float('nan'))
    nan
    >>> float('inf') / float('nan')
    nan
    >>> div_by_nan(float('inf'))
    nan
    """
    return x / float("nan")


def div_nan_by(x):
    """
    >>> float('nan') / 1.0
    nan
    >>> div_nan_by(1.0)
    nan
    >>> float('nan') / float('nan')
    nan
    >>> div_nan_by(float('nan'))
    nan
    >>> div_nan_by(0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    >>> div_nan_by(0.0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    """
    return float("nan") / x


def div_by_inf(x):
    """
    >>> 1 / float('inf')
    0.0
    >>> div_by_inf(1)
    0.0
    >>> 1.0 / float('inf')
    0.0
    >>> div_by_inf(1.0)
    0.0
    >>> div_by_inf(float('inf'))
    nan
    """
    return x / float("inf")


def div_inf_by(x):
    """
    >>> float('inf') / 1.0
    inf
    >>> div_inf_by(1.0)
    inf
    >>> float('inf') / float('nan')
    nan
    >>> div_inf_by(float('nan'))
    nan
    >>> float('inf') / float('-inf')
    nan
    >>> div_inf_by(float('-inf'))
    nan
    >>> float("inf") / 0.0  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    >>> div_inf_by(0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    >>> div_inf_by(0.0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    """
    return float("inf") / x


def div_neg_inf_by(x):
    """
    >>> float('-inf') / 1.0
    -inf
    >>> div_neg_inf_by(1.0)
    -inf
    >>> float('-inf') / -1.0
    inf
    >>> div_neg_inf_by(-1.0)
    inf
    >>> float("-inf") / 0.0  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    >>> div_neg_inf_by(0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    >>> div_neg_inf_by(0.0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: float division...
    """
    return float("-inf") / x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/float_floor_division_T260.pyx0000644000175100001770000000041700000000000023233 0ustar00runnerdocker00000000000000# ticket: t260

def floor_div_float(double a, double b):
    """
    >>> floor_div_float(2, 1.5)
    1.0
    >>> floor_div_float(2, -1.5)
    -2.0
    >>> floor_div_float(-2.3, 1.5)
    -2.0
    >>> floor_div_float(1e10, 1e-10) == 1e20
    True
    """
    return a // b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/float_len_T480.pyx0000644000175100001770000000050300000000000020764 0ustar00runnerdocker00000000000000# ticket: t480

def f(x):
    return x

def len_f(x):
    """
    >>> len_f([1,2,3])
    3
    """
    return len(f(x))

def float_len_f(x):
    """
    >>> float_len_f([1,2,3])
    3.0
    """
    return float(len(f(x)))

def cast_len_f(x):
    """
    >>> cast_len_f([1,2,3])
    3.0
    """
    return len(f(x))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/fmod.pyx0000644000175100001770000000013600000000000017231 0ustar00runnerdocker00000000000000def fmod(double a, double b):
    """
    >>> fmod(7, 1.25)
    0.75
    """
    return a % b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/for_decrement.pyx0000644000175100001770000000176600000000000021132 0ustar00runnerdocker00000000000000"""
>>> range_loop_indices()
** Calculating step **
(9, 9, 8, 1, 2)
>>> from_loop_indices()
** Calculating step **
(10, 10, 0)
"""

cdef int get_step():
    """
    This should only be called once, when used in range().
    """
    print u"** Calculating step **"
    return 2

def range_loop_indices():
    """
    Optimized integer for loops using range() should follow Python behavior,
    and leave the index variable with the last value of the range.
    """
    cdef int i, j, k=0, l=10, m=10
    for i in range(10): pass
    for j in range(2,10): pass
    for k in range(0,10,get_step()): pass
    for l in range(10,0,-1): pass
    for m in range(10,0,-2): pass
    return i, j, k, l, m

def from_loop_indices():
    """
    for-from-loops should follow C behavior, and leave the index variable
    incremented one step after the last iteration.
    """
    cdef int i, j, k
    for i from 0 <= i < 5+5 by get_step(): pass
    for j from 0 <= j < 10: pass
    for k from 10 > k > 0: pass
    return i, j, k
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/for_from_float_T254.pyx0000644000175100001770000000212100000000000022014 0ustar00runnerdocker00000000000000# ticket: t254

def double_target(a, b):
    """
    >>> double_target(0, 4)
    at 0.0
    at 1.0
    at 2.0
    at 3.0
    4.0
    """
    cdef double x
    for x from a <= x < b:
        print u"at", x
    return x

def double_step(a, b, dx):
    """
    >>> double_step(0, 2, .5)
    at 0.0
    at 0.5
    at 1.0
    at 1.5
    2.0
    """
    cdef double x
    for x from a <= x < b by dx:
        print u"at", x
    return x

def double_step_typed(a, b, double dx):
    """
    >>> double_step_typed(0, 2, .5)
    at 0.0
    at 0.5
    at 1.0
    at 1.5
    2.0
    """
    cdef double x
    for x from a <= x < b by dx:
        print u"at", x
    return x

def double_step_py_target(a, b, double dx):
    """
    >>> double_step_py_target(0, 2, .5)
    at 0.0
    at 0.5
    at 1.0
    at 1.5
    2.0
    """
    cdef object x
    for x from a <= x < b by dx:
        print u"at", x
    return x

def int_step_py_target(a, b, int dx):
    """
    >>> int_step_py_target(0, 2, 1)
    at 0
    at 1
    2
    """
    cdef object x
    for x from a <= x < b by dx:
        print u"at", x
    return x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/for_from_pyvar_loop_T601.pyx0000644000175100001770000000234200000000000023102 0ustar00runnerdocker00000000000000# ticket: t601

cdef unsigned long size2():
    return 3

def for_from_plain_ulong():
    """
    >>> for_from_plain_ulong()
    0
    1
    2
    """
    cdef object j = 0
    for j from 0 <= j < size2():
        print j

def for_in_plain_ulong():
    """
    >>> for_in_plain_ulong()
    0
    1
    2
    """
    cdef object j = 0
    for j in range(size2()):
        print j


cdef extern from *:
    """typedef unsigned long Ulong;"""
    ctypedef unsigned long Ulong

cdef Ulong size():
    return 3

def for_from_ctypedef_ulong():
    """
    >>> for_from_ctypedef_ulong()
    0
    1
    2
    """
    cdef object j = 0
    for j from 0 <= j < size():
        print j

def for_in_ctypedef_ulong():
    """
    >>> for_in_ctypedef_ulong()
    0
    1
    2
    """
    cdef object j = 0
    for j in range(size()):
        print j


class ForFromLoopInPyClass(object):
    """
    >>> ForFromLoopInPyClass.i    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    AttributeError: ...ForLoopInPyClass... has no attribute ...i...
    >>> ForFromLoopInPyClass.k
    0
    >>> ForFromLoopInPyClass.m
    1
    """
    for i from 0 <= i < 1:
        pass

    for k from 0 <= k < 2:
        pass

    for m from 0 <= m < 3:
        pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/for_in_break_continue_T533.pyx0000644000175100001770000000226300000000000023351 0ustar00runnerdocker00000000000000# mode: run
# ticket: t533
# ticket: gh1093

def for_in():
    """
    >>> for_in()
    CONTINUE -1
    CONTINUE 4
    BREAK 6
    6
    """
    i = -1
    for L in [[], range(5), range(10)]:
        for i in L:
            if i > 5:
                break
        else:
            print "CONTINUE", i
            continue
        print "BREAK", i
        break
    return i


def for_from():
    """
    >>> for_from()
    CONTINUE 0
    CONTINUE 5
    BREAK 6
    6
    """
    i = -1
    for L in [[], range(5), range(10)]:
        for i from 0 <= i < len(L):
            if i > 5:
                break
        else:
            print "CONTINUE", i
            continue
        print "BREAK", i
        break
    return i


def for_in_break2(data, avoid):
    """
    >>> for_in_break2([1,2,3,None], avoid=[1,2,3])
    3
    >>> for_in_break2([1,2,3,None], avoid=[1])
    1
    >>> for_in_break2([1,2,3,None], avoid=[1])
    1
    """
    data_iter = iter(data)
    value = None
    while 1:
        match = next(data_iter)
        if match is None:
            break
        for value in avoid:
            if match == value:
                break
        else:
            break

    return value
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/for_in_iter.py0000644000175100001770000000766600000000000020432 0ustar00runnerdocker00000000000000# mode: run
# tag: forin

import sys
import cython

try:
    from builtins import next
except ImportError:
    def next(it):
        return it.next()

def for_in_pyiter_pass(it):
    """
    >>> it = Iterable(5)
    >>> for_in_pyiter_pass(it)
    >>> next(it)
    Traceback (most recent call last):
    StopIteration
    """
    for item in it:
        pass

def for_in_pyiter(it):
    """
    >>> for_in_pyiter(Iterable(5))
    [0, 1, 2, 3, 4]
    """
    l = []
    for item in it:
        l.append(item)
    return l

def for_in_list():
    """
    >>> for_in_pyiter([1,2,3,4,5])
    [1, 2, 3, 4, 5]
    """

@cython.test_assert_path_exists('//TupleNode//IntNode')
@cython.test_fail_if_path_exists('//ListNode//IntNode')
def for_in_literal_list():
    """
    >>> for_in_literal_list()
    [1, 2, 3, 4]
    """
    l = []
    for i in [1,2,3,4]:
        l.append(i)
    return l

@cython.test_assert_path_exists('//TupleNode//IntNode')
@cython.test_fail_if_path_exists('//ListNode//IntNode')
def for_in_literal_mult_list():
    """
    >>> for_in_literal_mult_list()
    [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
    """
    l = []
    for i in [1,2,3,4] * 3:
        l.append(i)
    return l


def listcomp_over_multiplied_constant_tuple():
    """
    >>> listcomp_over_multiplied_constant_tuple()
    [[], [1, 2, 3], [1, 2, 3, 1, 2, 3], [1, 2, 3, 1, 2, 3, 1, 2, 3], [1, 2, 3, 1, 2, 3]]
    """
    return [
        [i for i in (1, 2, 3) * 0],
        [i for i in (1, 2, 3) * 1],
        [i for i in (1, 2, 3) * 2],
        [i for i in (1, 2, 3) * 3],
        [i for i in (1, 2, 3) * 2],
    ]


@cython.test_assert_path_exists('//ReturnStatNode//ForInStatNode//TupleNode')
@cython.test_fail_if_path_exists('//ReturnStatNode//ForInStatNode//ListNode')
def listcomp_over_multiplied_constant_list():
    """
    >>> listcomp_over_multiplied_constant_list()
    [[], [1, 2, 3], [1, 2, 3, 1, 2, 3], [1, 2, 3, 1, 2, 3, 1, 2, 3], [1, 2, 3, 1, 2, 3]]
    """
    return [
        [i for i in [1, 2, 3] * 0],
        [i for i in [1, 2, 3] * 1],
        [i for i in [1, 2, 3] * 2],
        [i for i in [1, 2, 3] * 3],
        [i for i in [1, 2, 3] * 2],
    ]


class Iterable(object):
    """
    >>> for_in_pyiter(Iterable(5))
    [0, 1, 2, 3, 4]
    """
    def __init__(self, N):
        self.N = N
        self.i = 0
    def __iter__(self):
        return self
    def __next__(self):
        if self.i < self.N:
            i = self.i
            self.i += 1
            return i
        raise StopIteration
    next = __next__

if sys.version_info[0] >= 3:
    class NextReplacingIterable(object):
        def __init__(self):
            self.i = 0
        def __iter__(self):
            return self

        def __next__(self):
            if self.i > 5:
                raise StopIteration
            self.i += 1
            self.__next__ = self.next2
            return 1
        def next2(self):
            self.__next__ = self.next3
            return 2
        def next3(self):
            del self.__next__
            raise StopIteration
else:
    class NextReplacingIterable(object):
        def __init__(self):
            self.i = 0
        def __iter__(self):
            return self

        def next(self):
            if self.i > 5:
                raise StopIteration
            self.i += 1
            self.next = self.next2
            return 1
        def next2(self):
            self.next = self.next3
            return 2
        def next3(self):
            del self.next
            raise StopIteration

def for_in_next_replacing_iter():
    """
    >>> for_in_pyiter(NextReplacingIterable())
    [1, 1, 1, 1, 1, 1]
    """

def for_in_gen(N):
    """
    >>> for_in_pyiter(for_in_gen(10))
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    """
    for i in range(N):
        yield i

def for_in_range_invalid_arg_count():
    """
    >>> for_in_range_invalid_arg_count()     # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    for i in range(1, 2, 3, 4):
        pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/for_in_range_T372.pyx0000644000175100001770000000510700000000000021456 0ustar00runnerdocker00000000000000# mode: run
# ticket: t372

cimport cython

@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def test_modify():
    """
    >>> test_modify()
    0
    1
    2
    3
    4
    
    (4, 0)
    """
    cdef int i, n = 5
    for i in range(n):
        print i
        n = 0
    print
    return i,n


@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def test_negindex():
    """
    >>> test_negindex()
    6
    5
    4
    3
    2
    (2, 0)
    """
    cdef int i, n = 5
    for i in range(n+1, 1, -1):
        print i
        n = 0
    return i,n


@cython.test_assert_path_exists("//ForFromStatNode",
                                "//ForFromStatNode//PrintStatNode//CoerceToPyTypeNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def test_negindex_inferred():
    """
    >>> test_negindex_inferred()
    5
    4
    3
    2
    (2, 0)
    """
    cdef int n = 5
    for i in range(n, 1, -1):
        print i
        n = 0
    return i,n


@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def test_fix():
    """
    >>> test_fix()
    0
    1
    2
    3
    4
    
    4
    """
    cdef int i
    for i in range(5):
        print i
    print
    return i


@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def test_break():
    """
    >>> test_break()
    0
    1
    2
    
    (2, 0)
    """
    cdef int i, n = 5
    for i in range(n):
        print i
        n = 0
        if i == 2:
            break
    else:
        print "FAILED!"
    print
    return i,n


@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def test_return():
    """
    >>> test_return()
    0
    1
    2
    (2, 0)
    """
    cdef int i, n = 5
    for i in range(n):
        print i
        n = 0
        if i == 2:
            return i,n
    print
    return "FAILED!"


ctypedef enum RangeEnum:
    EnumValue1
    EnumValue2
    EnumValue3


@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def test_enum_range():
    """
    # NOTE: it's not entirely clear that this is the expected behaviour, but that's how it currently is.
    >>> test_enum_range()
    'RangeEnum'
    """
    cdef RangeEnum n = EnumValue3
    for i in range(n):
        assert 0 <= i < n
        assert cython.typeof(i) == "RangeEnum", cython.typeof(i)
    return cython.typeof(i)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/for_in_string.pyx0000644000175100001770000001342300000000000021151 0ustar00runnerdocker00000000000000cimport cython

bytes_abc = b'abc'
bytes_ABC = b'ABC'
bytes_abc_null = b'a\0b\0c'
bytes_ABC_null = b'A\0B\0C'

unicode_abc = u'abc'
unicode_ABC = u'ABC'
unicode_abc_null = u'a\0b\0c'
unicode_ABC_null = u'A\0B\0C'


def for_in_bytes(bytes s):
    """
    >>> for_in_bytes(bytes_abc)
    'X'
    >>> for_in_bytes(bytes_ABC)
    'C'
    >>> for_in_bytes(bytes_abc_null)
    'X'
    >>> for_in_bytes(bytes_ABC_null)
    'C'
    """
    for c in s:
        # Py2/Py3
        if c == b'C' or c == c'C':
            return 'C'
    else:
        return 'X'

@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def for_char_in_bytes(bytes s):
    """
    >>> for_char_in_bytes(bytes_abc)
    'X'
    >>> for_char_in_bytes(bytes_ABC)
    'C'
    >>> for_char_in_bytes(bytes_abc_null)
    'X'
    >>> for_char_in_bytes(bytes_ABC_null)
    'C'
    """
    cdef char c
    for c in s:
        if c == b'C':
            return 'C'
    else:
        return 'X'

#### Py2 and Py3 behave differently here: Py2->bytes, Py3->integer
##
## @cython.test_assert_path_exists("//ForFromStatNode")
## @cython.test_fail_if_path_exists("//ForInStatNode")
## def for_obj_in_bytes_slice(bytes s):
##     """
##     >>> for_obj_in_bytes_slice(bytes_abc)
##     'X'
##     >>> for_obj_in_bytes_slice(bytes_ABC)
##     'B'
##     >>> for_obj_in_bytes_slice(bytes_abc_null)
##     'X'
##     >>> for_obj_in_bytes_slice(bytes_ABC_null)
##     'B'
##     """
##     for c in s[1:-1]:
##         if c == b'B':
##             return 'B'
##     else:
##         return 'X'

@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def for_char_in_bytes_slice(bytes s):
    """
    >>> for_char_in_bytes_slice(bytes_abc)
    'X'
    >>> for_char_in_bytes_slice(bytes_ABC)
    'B'
    >>> for_char_in_bytes_slice(bytes_abc_null)
    'X'
    >>> for_char_in_bytes_slice(bytes_ABC_null)
    'B'
    """
    cdef char c
    for c in s[1:-1]:
        if c == c'B':
            return 'B'
    else:
        return 'X'

@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def for_char_in_enumerate_bytes(bytes s):
    """
    >>> for_char_in_enumerate_bytes(bytes_abc)
    'X'
    >>> for_char_in_enumerate_bytes(bytes_ABC)
    2
    >>> for_char_in_enumerate_bytes(bytes_abc_null)
    'X'
    >>> for_char_in_enumerate_bytes(bytes_ABC_null)
    4
    """
    cdef char c
    cdef Py_ssize_t i
    for i, c in enumerate(s):
        if c == b'C':
            return i
    else:
        return 'X'

#### Py2 and Py3 behave differently here: Py2->bytes, Py3->integer
##
## @cython.test_assert_path_exists("//ForFromStatNode")
## @cython.test_fail_if_path_exists("//ForInStatNode")
## def for_pyvar_in_char_ptr(char* c_string):
##     """
##     >>> for_pyvar_in_char_ptr( (bytes_abc+bytes_ABC) * 2 )
##     [True, True, True, False, False, False, True, True, True, False]
##     >>> for_pyvar_in_char_ptr( bytes_abc_null * 2 )
##     [True, False, True, False, True, True, False, True, False, True]
##     """
##     in_test = []
##     cdef object c
##     for c in c_string[:10]:
##         in_test.append( c in b'abc' )
##     return in_test

@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def for_char_in_char_ptr(char* c_string):
    """
    >>> for_char_in_char_ptr( (bytes_abc+bytes_ABC) * 2 )
    [True, True, True, False, False, False, True, True, True, False]
    >>> for_char_in_char_ptr( bytes_abc_null * 2 )
    [True, False, True, False, True, True, False, True, False, True]
    """
    in_test = []
    cdef char c
    for c in c_string[:10]:
        in_test.append( c in b'abc' )
    return in_test

@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def for_pyunicode_in_unicode(unicode s):
    """
    >>> for_pyunicode_in_unicode(unicode_abc)
    'X'
    >>> for_pyunicode_in_unicode(unicode_ABC)
    'C'
    >>> for_pyunicode_in_unicode(unicode_abc_null)
    'X'
    >>> for_pyunicode_in_unicode(unicode_ABC_null)
    'C'
    """
    cdef Py_UNICODE c
    for c in s:
        if c == u'C':
            return 'C'
    else:
        return 'X'

@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def for_pyunicode_in_enumerate_unicode(unicode s):
    """
    >>> for_pyunicode_in_enumerate_unicode(unicode_abc)
    'X'
    >>> for_pyunicode_in_enumerate_unicode(unicode_ABC)
    2
    >>> for_pyunicode_in_enumerate_unicode(unicode_abc_null)
    'X'
    >>> for_pyunicode_in_enumerate_unicode(unicode_ABC_null)
    4
    """
    cdef Py_UNICODE c
    cdef Py_ssize_t i
    for i, c in enumerate(s):
        if c == u'C':
            return i
    else:
        return 'X'

@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def for_pyucs4_in_unicode(unicode s):
    """
    >>> for_pyucs4_in_unicode(unicode_abc)
    'X'
    >>> for_pyucs4_in_unicode(unicode_ABC)
    'C'
    >>> for_pyucs4_in_unicode(unicode_abc_null)
    'X'
    >>> for_pyucs4_in_unicode(unicode_ABC_null)
    'C'
    """
    cdef Py_UCS4 c
    for c in s:
        if c == u'C':
            return 'C'
    else:
        return 'X'

@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def for_pyucs4_in_enumerate_unicode(unicode s):
    """
    >>> for_pyucs4_in_enumerate_unicode(unicode_abc)
    'X'
    >>> for_pyucs4_in_enumerate_unicode(unicode_ABC)
    2
    >>> for_pyucs4_in_enumerate_unicode(unicode_abc_null)
    'X'
    >>> for_pyucs4_in_enumerate_unicode(unicode_ABC_null)
    4
    """
    cdef Py_UCS4 c
    cdef Py_ssize_t i
    for i, c in enumerate(s):
        if c == u'C':
            return i
    else:
        return 'X'
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/forfrom.pyx0000644000175100001770000000052000000000000017753 0ustar00runnerdocker00000000000000
def for_else():
    """
    >>> for_else()
    30
    >>> print( int_comp() )
    00*01*02
    """
    cdef int i, j=0, k=2
    for i from 0 <= i < 10:
        j += k
    else:
        k = j+10
    return k

def int_comp():
    cdef int i
    return u'*'.join(tuple([ u"%02d" % i
                             for i from 0 <= i < 3 ]))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/fstring.pyx0000644000175100001770000003412100000000000017761 0ustar00runnerdocker00000000000000# mode: run
# tag: f_strings, pep498, werror

####
# Cython specific PEP 498 tests in addition to test_fstring.pyx from CPython
####

cimport cython

import sys
IS_PYPY = hasattr(sys, 'pypy_version_info')

from libc.limits cimport INT_MAX, LONG_MAX, LONG_MIN

max_int = INT_MAX
max_long = LONG_MAX
min_long = LONG_MIN


@cython.test_fail_if_path_exists(
    "//JoinedStrNode",
)
@cython.test_assert_path_exists(
    "//AddNode",
)
def concat_strings(a, b):
    """
    >>> concat_strings("", "")
    x
    
    x
    x
    x
    xx
    >>> concat_strings("a", "")
    ax
    a
    x
    ax
    ax
    axx
    >>> concat_strings("", "b")
    x
    b
    xb
    xb
    xb
    xxb
    >>> concat_strings("a", "b")
    ax
    ab
    xb
    axb
    axb
    axxb
    >>> concat_strings("".join(["a", "b"]), "")  # fresh temp string left
    abx
    ab
    x
    abx
    abx
    abxx
    >>> concat_strings("", "".join(["a", "b"]))  # fresh temp string right
    x
    ab
    xab
    xab
    xab
    xxab
    """
    print(f"{a}x")
    print(f"{a}{b}")
    print(f"x{b}")
    print(f"{a+'x'}{b}")      # fresh temp string left
    print(f"{a}{'x'+b}")      # fresh temp string right
    print(f"{a+'x'}{'x'+b}")  # fresh temp strings right and left


@cython.test_fail_if_path_exists(
    "//FormattedValueNode",
    "//JoinedStrNode",
    "//AddNode",
)
def escaping():
    """
    >>> escaping()
    """
    assert f'{{{{{"abc"}}}}}{{}}{{' == '{{abc}}{}{'
    s = f'{{{{{"abc"}}}}}{{}}{{'
    assert s == '{{abc}}{}{', s

    assert f'\x7b}}' == '{}'
    s = f'\x7b}}'
    assert s == '{}', s

    assert f'{"{{}}"}' == '{{}}'
    s = f'{"{{}}"}'
    assert s == '{{}}', s


@cython.test_fail_if_path_exists(
    "//FormattedValueNode",
    "//JoinedStrNode",
    "//AddNode",
)
def nested_constant():
    """
    >>> print(nested_constant())
    xyabc123321
    """
    return f"""{f'''xy{f"abc{123}{'321'}"!s}'''}"""


def format2(ab, cd):
    """
    >>> a, b, c = format2(1, 2)
    >>> print(a)
    ab2
    >>> print(b)
    1cd
    >>> print(c)
    12

    >>> a, b, c = format2('ab', 'cd')
    >>> print(a)
    abcd
    >>> print(b)
    abcd
    >>> print(c)
    abcd
    """
    a = f"ab{cd}"
    assert isinstance(a, unicode), type(a)
    b = f"{ab}cd"
    assert isinstance(b, unicode), type(b)
    c = f"{ab}{cd}"
    assert isinstance(c, unicode) or (IS_PYPY and isinstance(c, str)), type(c)
    return a, b, c


ctypedef enum TestValues:
    enum_ABC = 1
    enum_XYZ = 2


@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode",
)
def format_c_enum():
    """
    >>> s = format_c_enum()
    >>> s == '1-2' or s
    True
    """
    return f"{enum_ABC}-{enum_XYZ}"


def format_c_numbers(signed char c, short s, int n, long l, float f, double d):
    """
    >>> s1, s2, s3, s4 = format_c_numbers(123, 135, 12, 12312312, 2.3456, 3.1415926)
    >>> print(s1)
    123 13512312312122.35
    >>> print(s2)
    3.14 2.3
    >>> print(s3)
      12f
    >>> print(s4)
    0C014 3.14

    >>> s1, s2, s3, s4 = format_c_numbers(-123, -135, -12, -12312312, -2.3456, -3.1415926)
    >>> print(s1)
    -123-135-12312312-12-2.35
    >>> print(s2)
    -3.14-2.3
    >>> print(s3)
     -12f
    >>> print(s4)
    -C-14-3.14

    >>> s1, s2, s3, s4 = format_c_numbers(0, 0, 0, 0, -2.3456, -0.1415926)
    >>> print(s1)
    0   000-2.35
    >>> print(s2)
    -0.142-2.3
    >>> print(s3)
       0f
    >>> print(s4)
    00000-0.142

    """
    s1 = f"{c}{s:4}{l}{n}{f:.3}"
    assert isinstance(s1, unicode), type(s1)
    s2 = f"{d:.3}{f:4.2}"
    assert isinstance(s2, unicode), type(s2)
    s3 = f"{n:-4}f"
    assert isinstance(s3, unicode), type(s3)
    s4 = f"{n:02X}{n:03o}{d:5.3}"
    assert isinstance(s4, unicode), type(s4)
    return s1, s2, s3, s4


def format_c_numbers_unsigned(unsigned char c, unsigned short s, unsigned int n, unsigned long l):
    """
    >>> s1, s2, s3 = format_c_numbers_unsigned(123, 135, 12, 12312312)
    >>> print(s1)
    123 135 5675737012
    >>> print(s2)
      12f
    >>> print(s3)
    0C014    bbdef8

    """
    s1 = f"{c}{s:4} {l:o}{n}"
    assert isinstance(s1, unicode), type(s1)
    s2 = f"{n:-4}f"
    assert isinstance(s2, unicode), type(s2)
    s3 = f"{n:02X}{n:03o}{l:10x}"
    assert isinstance(s3, unicode), type(s3)
    return s1, s2, s3


@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode",
)
def format_c_numbers_max(int n, long l):
    """
    >>> n, l = max_int, max_long
    >>> s1, s2 = format_c_numbers_max(n, l)
    >>> s1 == '{n}:{l}'.format(n=n, l=l) or s1
    True
    >>> s2 == '{n:012X}:{l:020X}'.format(n=n, l=l) or s2
    True

    >>> n, l = -max_int-1, -max_long-1
    >>> s1, s2 = format_c_numbers_max(n, l)
    >>> s1 == '{n}:{l}'.format(n=n, l=l) or s1
    True
    >>> s2 == '{n:012X}:{l:020X}'.format(n=n, l=l) or s2
    True
    """
    s1 = f"{n}:{l}"
    assert isinstance(s1, unicode), type(s1)
    s2 = f"{n:012X}:{l:020X}"
    assert isinstance(s2, unicode), type(s2)
    return s1, s2


def format_c_number_const():
    """
    >>> s = format_c_number_const()
    >>> s == '{0}'.format(max_long) or s
    True
    """
    return f"{LONG_MAX}"


@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode",
)
def format_c_number_range(int n):
    """
    >>> for i in range(-1000, 1001):
    ...     assert format_c_number_range(i) == str(i)
    """
    return f'{n}'


@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode",
)
def format_c_number_range_width(int n):
    """
    >>> for i in range(-1000, 1001):
    ...     formatted = format_c_number_range_width(i)
    ...     expected = '{n:04d}'.format(n=i)
    ...     assert formatted == expected, "%r != %r" % (formatted, expected)
    """
    return f'{n:04}'


def format_c_number_range_width0(int n):
    """
    >>> for i in range(-100, 101):
    ...     formatted = format_c_number_range_width0(i)
    ...     expected = '{n:00d}'.format(n=i)
    ...     assert formatted == expected, "%r != %r" % (formatted, expected)
    """
    return f'{n:00}'


@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode",
)
def format_c_number_range_width1(int n):
    """
    >>> for i in range(-100, 101):
    ...     formatted = format_c_number_range_width1(i)
    ...     expected = '{n:01d}'.format(n=i)
    ...     assert formatted == expected, "%r != %r" % (formatted, expected)
    """
    return f'{n:01}'


@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode",
)
def format_c_number_range_width_m4(int n):
    """
    >>> for i in range(-100, 101):
    ...     formatted = format_c_number_range_width_m4(i)
    ...     expected = '{n:-4d}'.format(n=i)
    ...     assert formatted == expected, "%r != %r" % (formatted, expected)
    """
    return f'{n:-4}'


def format_c_number_range_dyn_width(int n, int width):
    """
    >>> for i in range(-1000, 1001):
    ...     assert format_c_number_range_dyn_width(i, 0) == str(i), format_c_number_range_dyn_width(i, 0)
    ...     assert format_c_number_range_dyn_width(i, 1) == '%01d' % i, format_c_number_range_dyn_width(i, 1)
    ...     assert format_c_number_range_dyn_width(i, 4) == '%04d' % i, format_c_number_range_dyn_width(i, 4)
    ...     assert format_c_number_range_dyn_width(i, 5) == '%05d' % i, format_c_number_range_dyn_width(i, 5)
    ...     assert format_c_number_range_dyn_width(i, 6) == '%06d' % i, format_c_number_range_dyn_width(i, 6)
    """
    return f'{n:0{width}}'


@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode",
)
def format_bool(bint x):
    """
    >>> a, b, c, d = format_bool(1)
    >>> print(a)  # 1
    True
    >>> print(b)  # 1
    True
    >>> print(c)  # 1
    False
    >>> print(d)  # 1
    False

    >>> a, b, c, d = format_bool(2)
    >>> print(a)  # 2
    True
    >>> print(b)  # 2
    True
    >>> print(c)  # 2
    False
    >>> print(d)  # 2
    False

    >>> a, b, c, d = format_bool(0)
    >>> print(a)  # 3
    False
    >>> print(b)  # 3
    True
    >>> print(c)  # 3
    False
    >>> print(d)  # 3
    False
    """
    return f'{x}', f'{True}', f'{x == 2}', f'{2 > 3}'


def format_c_values(Py_UCS4 uchar, Py_UNICODE pyunicode):
    """
    >>> s, s1, s2, s3 = format_c_values(b'A'.decode('ascii'), b'X'.decode('ascii'))
    >>> print(s)
    AXAX
    >>> print(s1)
    A
    >>> print(s2)
    X
    >>> print(s3)
    None

    """
    s = f"{uchar}{pyunicode}{uchar!s}{pyunicode!s}"
    assert isinstance(s, unicode), type(s)
    s1 = f"{uchar}"
    assert isinstance(s1, unicode), type(s1)
    s2 = f"{pyunicode}"
    assert isinstance(s2, unicode), type(s2)
    l = [1, 2, 3]
    s3 = f"{l.reverse()}"  # C int return value => 'None'
    assert isinstance(s3, unicode), type(s3)
    assert l == [3, 2, 1]
    return s, s1, s2, s3


xyz_ustring = u'xÄyÖz'

def format_strings(str s, unicode u):
    u"""
    >>> a, b, c, d, e, f, g = format_strings('abc', b'xyz'.decode('ascii'))
    >>> print(a)
    abcxyz
    >>> print(b)
    xyzabc
    >>> print(c)
    uxyzsabc
    >>> print(d)
    sabcuxyz
    >>> print(e)
    sabcuÄÄuxyz
    >>> print(f)
    sabcu\N{SNOWMAN}uxyz
    >>> print(g)
    sabcu\N{OLD PERSIAN SIGN A}uxyz\N{SNOWMAN}

    >>> a, b, c, d, e, f, g = format_strings('abc', xyz_ustring)
    >>> print(a)
    abcxÄyÖz
    >>> print(b)
    xÄyÖzabc
    >>> print(c)
    uxÄyÖzsabc
    >>> print(d)
    sabcuxÄyÖz
    >>> print(e)
    sabcuÄÄuxÄyÖz
    >>> print(f)
    sabcu\N{SNOWMAN}uxÄyÖz
    >>> print(g)
    sabcu\N{OLD PERSIAN SIGN A}uxÄyÖz\N{SNOWMAN}
    """
    a = f"{s}{u}"
    assert isinstance(a, unicode), type(a)
    b = f"{u}{s}"
    assert isinstance(b, unicode), type(b)
    c = f"u{u}s{s}"
    assert isinstance(c, unicode), type(c)
    d = f"s{s}u{u}"
    assert isinstance(d, unicode), type(d)
    e = f"s{s}uÄÄu{u}"
    assert isinstance(e, unicode), type(e)
    f = f"s{s}u\N{SNOWMAN}u{u}"
    assert isinstance(f, unicode), type(f)
    g = f"s{s}u\N{OLD PERSIAN SIGN A}u{u}\N{SNOWMAN}"
    assert isinstance(g, unicode), type(g)
    return a, b, c, d, e, f, g


def format_pystr(str s1, str s2):
    """
    >>> a, b, c, d = format_pystr('abc', 'xyz')
    >>> print(a)
    abcxyz
    >>> print(b)
    xyzabc
    >>> print(c)
    uxyzsabc
    >>> print(d)
    sabcuxyz
    """
    a = f"{s1}{s2}"
    assert isinstance(a, unicode) or (IS_PYPY and isinstance(a, str)), type(a)
    b = f"{s2}{s1}"
    assert isinstance(b, unicode) or (IS_PYPY and isinstance(a, str)), type(b)
    c = f"u{s2}s{s1}"
    assert isinstance(c, unicode), type(c)
    d = f"s{s1}u{s2}"
    assert isinstance(d, unicode), type(d)
    return a, b, c, d


def raw_fstring(value):
    """
    >>> print(raw_fstring('abc'))
    abc\\x61
    """
    return fr'{value}\x61'


def format_repr(value):
    """
    >>> a, b = format_repr('abc')
    >>> print('x{value!r}x'.format(value='abc'))
    x'abc'x
    >>> print('x{value!r:6}x'.format(value='abc'))
    x'abc' x
    >>> print(a)
    x'abc'x
    >>> print(b)
    x'abc' x
    """
    a = f'x{value!r}x'
    assert isinstance(a, unicode), type(a)
    b = f'x{value!r:6}x'
    assert isinstance(b, unicode), type(b)
    return a, b


def format_str(value):
    """
    >>> a, b = format_str('abc')
    >>> print('x{value!s}x'.format(value='abc'))
    xabcx
    >>> print('x{value!s:6}x'.format(value='abc'))
    xabc   x
    >>> print(a)
    xabcx
    >>> print(b)
    xabc   x
    """
    a = f'x{value!s}x'
    assert isinstance(a, unicode), type(a)
    b = f'x{value!s:6}x'
    assert isinstance(b, unicode), type(b)
    return a, b


@cython.test_fail_if_path_exists(
    "//FormattedValueNode",  # bytes.decode() returns unicode => formatting is useless
    "//JoinedStrNode",       # replaced by call to PyUnicode_Concat()
    "//PythonCapiCallNode//PythonCapiCallNode",
)
def format_decoded_bytes(bytes value):
    """
    >>> print(format_decoded_bytes(b'xyz'))
    U-xyz
    """
    return f"U-{value.decode('utf-8')}"


@cython.test_fail_if_path_exists(
    "//AddNode",
    "//ModNode",
)
@cython.test_assert_path_exists(
    "//FormattedValueNode",
    "//JoinedStrNode",
)
def generated_fstring(int i, float f, unicode u not None, o):
    """
    >>> i, f, u, o = 11, 1.3125, u'xyz', [1]
    >>> print(((
    ...     u"(i) %s-%.3s-%r-%.3r-%d-%3d-%-3d-%o-%04o-%x-%4x-%X-%03X-%.1f-%04.2f %% "
    ...     u"(u) %s-%.2s-%r-%.7r-%05s-%-5s %% "
    ...     u"(o) %s-%.2s-%r-%.2r %% "
    ...     u"(f) %.2f-%d"
    ... ) % (
    ...     i, i, i, i, i, i, i, i, i, i, i, i, i, i, i,
    ...     u, u, u, u, u, u,
    ...     o, o, o, o,
    ...     f, f,
    ... )).replace("-u'xyz'", "-'xyz'"))
    (i) 11-11-11-11-11- 11-11 -13-0013-b-   b-B-00B-11.0-11.00 % (u) xyz-xy-'xyz'-'xyz'-  xyz-xyz   % (o) [1]-[1-[1]-[1 % (f) 1.31-1

    >>> print(generated_fstring(i, f, u, o).replace("-u'xyz'", "-'xyz'"))
    (i) 11-11-11-11-11- 11-11 -13-0013-b-   b-B-00B-11.0-11.00 % (u) xyz-xy-'xyz'-'xyz'-  xyz-xyz   % (o) [1]-[1-[1]-[1 % (f) 1.31-1
    """
    return (
        u"(i) %s-%.3s-%r-%.3r-%d-%3d-%-3d-%o-%04o-%x-%4x-%X-%03X-%.1f-%04.2f %% "
        u"(u) %s-%.2s-%r-%.7r-%05s-%-5s %% "
        u"(o) %s-%.2s-%r-%.2r %% "
        u"(f) %.2f-%d"
    ) % (
        i, i, i, i, i, i, i, i, i, i, i, i, i, i, i,
        u, u, u, u, u, u,
        o, o, o, o,
        f, f,
    )


@cython.test_assert_path_exists(
    "//FormattedValueNode",
    "//JoinedStrNode",
)
def percent_s_unicode(u, int i):
    u"""
    >>> u = u'x\u0194z'
    >>> print(percent_s_unicode(u, 12))
    x\u0194z-12
    """
    return u"%s-%d" % (u, i)


@cython.test_assert_path_exists(
    "//FormattedValueNode",
)
def sideeffect(l):
    """
    >>> class Listish(list):
    ...     def __format__(self, format_spec):
    ...         self.append("format called")
    ...         return repr(self)
    ...     def append(self, item):
    ...         list.append(self, item)
    ...         return self

    >>> l = Listish()
    >>> sideeffect(l)  if getattr(sys, 'pypy_version_info', ())[:2] != (7,3) else [123, 'format called']   # 7.3.4, 7.3.5
    [123, 'format called']
    """
    f"{l.append(123)}"  # unused f-string !
    return list(l)


########################################
# await inside f-string

def test_await_inside_f_string():
    """
    >>> test_await_inside_f_string()
    PARSED_SUCCESSFULLY
    """

    async def f():
        return "some value"

    async def main():
        print(f"{await f()}")

    print("PARSED_SUCCESSFULLY")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/funcexc_iter_T228.pyx0000644000175100001770000001017500000000000021505 0ustar00runnerdocker00000000000000# ticket: t228

__doc__ = u"""
>>> def py_iterator():
...    if True: return
...    yield None

>>> list(py_iterator())
[]
>>> list(cy_iterator())
[]

>>> try:
...     raise ValueError
... except:
...     print(sys.exc_info()[0] is ValueError or sys.exc_info()[0])
...     a = list(py_iterator())
...     print(sys.exc_info()[0] is ValueError or sys.exc_info()[0])
True
True

>>> print(sys.exc_info()[0] is None or sys.exc_info()[0])
True

>>> try:
...     raise ValueError
... except:
...     print(sys.exc_info()[0] is ValueError or sys.exc_info()[0])
...     a = list(py_iterator())
...     print(sys.exc_info()[0] is ValueError or sys.exc_info()[0])
...     a = list(cy_iterator())
...     print(sys.exc_info()[0] is ValueError or sys.exc_info()[0])
True
True
True

>>> print(sys.exc_info()[0] is None or sys.exc_info()[0])
True

>>> double_raise(py_iterator)
True
True
True

>>> print(sys.exc_info()[0] is None or sys.exc_info()[0])
True
"""

import sys
if sys.version_info[0] < 3:
    sys.exc_clear()

cdef class cy_iterator(object):
    def __iter__(self):
        return self
    def __next__(self):
        raise StopIteration

def double_raise(py_iterator):
    try:
        raise ValueError
    except:
        print(sys.exc_info()[0] is ValueError or sys.exc_info()[0])
        a = list(py_iterator())
        print(sys.exc_info()[0] is ValueError or sys.exc_info()[0])
        a = list(cy_iterator())
        print(sys.exc_info()[0] is ValueError or sys.exc_info()[0])


###### Tests to do with the optimization of StopIteration to "return NULL" #######
# we're mainly checking that
#  1. Calling __next__ manually doesn't crash (the wrapper function adds the exception)
#  2. if you raise a value then that value gets raised
#  3. putting the exception in various places try...finally / try...except blocks works

def call_next_directly():
    """
    >>> call_next_directly()
    Traceback (most recent call last):
    ...
    StopIteration
    """
    cy_iterator().__next__()

cdef class cy_iter_many_options:
    cdef what
    def __init__(self, what):
        self.what = what

    def __iter__(self):
        return self

    def __next__(self):
        if self.what == "StopIteration in finally no return":
            try:
                raise StopIteration
            finally:
                print "Finally..."
        elif self.what == "StopIteration in finally return":
            try:
                raise StopIteration
            finally:
                self.what = None
                return "in finally"  # but will stop iterating next time
        elif self.what == "StopIteration from finally":
            try:
                raise ValueError
            finally:
                raise StopIteration
        elif self.what == "catch StopIteration":
            try:
                raise StopIteration
            except StopIteration:
                self.what = None
                return "in except"  # but will stop next time
        elif self.what == "don't catch StopIteration":
            try:
                raise StopIteration
            except ValueError:
                return 0
        elif self.what == "StopIteration from except":
            try:
                raise ValueError
            except ValueError:
                raise StopIteration
        elif self.what == "StopIteration with value":
            raise StopIteration("I'm a value!")
        elif self.what is None:
            raise StopIteration
        else:
            raise ValueError("self.what didn't match anything")

def test_cy_iter_many_options(option):
    """
    >>> test_cy_iter_many_options("StopIteration in finally no return")
    Finally...
    []
    >>> test_cy_iter_many_options("StopIteration in finally return")
    ['in finally']
    >>> test_cy_iter_many_options("StopIteration from finally")
    []
    >>> test_cy_iter_many_options("catch StopIteration")
    ['in except']
    >>> test_cy_iter_many_options("don't catch StopIteration")
    []
    >>> try:
    ...     cy_iter_many_options("StopIteration with value").__next__()
    ... except StopIteration as e:
    ...     print(e.args)
    ("I'm a value!",)
    """
    return list(cy_iter_many_options(option))

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/funcexcept.pyx0000644000175100001770000000146300000000000020454 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> import sys
>>> if not IS_PY3: sys.exc_clear()

>>> def test_py():
...   try:
...     raise AttributeError
...   except AttributeError:
...     print(sys.exc_info()[0] == AttributeError or sys.exc_info()[0])
...   print((IS_PY3 and sys.exc_info()[0] is None) or
...         (not IS_PY3 and sys.exc_info()[0] == AttributeError) or
...         sys.exc_info()[0])

>>> print(sys.exc_info()[0]) # 0
None
>>> test_py()
True
True

>>> print(sys.exc_info()[0]) # test_py()
None

>>> test_c()
True
True
>>> print(sys.exc_info()[0]) # test_c()
None
"""

import sys

IS_PY3 = sys.version_info[0] >= 3

def test_c():
    try:
        raise AttributeError
    except AttributeError:
        print(sys.exc_info()[0] == AttributeError or sys.exc_info()[0])
    print(sys.exc_info()[0] is None or sys.exc_info()[0])
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/funcexceptchained.pyx0000644000175100001770000000467200000000000021775 0ustar00runnerdocker00000000000000# mode: run
# tag: exceptions

import sys
IS_PY3 = sys.version_info[0] >= 3


__doc__ = u"""
>>> if not IS_PY3: sys.exc_clear()

>>> def test_py(outer_exc):
...   try:
...     raise AttributeError
...   except AttributeError:
...     print(sys.exc_info()[0] is AttributeError or sys.exc_info()[0])
...     try: raise KeyError
...     except:
...       print(sys.exc_info()[0] is KeyError or sys.exc_info()[0])
...       if IS_PY3:
...         print(isinstance(sys.exc_info()[1].__context__, AttributeError)
...               or sys.exc_info()[1].__context__)
...       else:
...         print(True)
...     print((IS_PY3 and sys.exc_info()[0] is AttributeError) or
...           (not IS_PY3 and sys.exc_info()[0] is KeyError) or
...           sys.exc_info()[0])
...   print((IS_PY3 and sys.exc_info()[0] is outer_exc) or
...         (not IS_PY3 and sys.exc_info()[0] is KeyError) or
...         sys.exc_info()[0])

>>> print(sys.exc_info()[0]) # 0
None

>>> test_py(None)
True
True
True
True
True
>>> print(sys.exc_info()[0]) # test_py()
None

>>> test_c(None)
True
True
True
True
True
>>> print(sys.exc_info()[0]) # test_c()
None

>>> def test_py2():
...   try:
...     raise Exception
...   except Exception:
...     test_py(Exception)
...     print(sys.exc_info()[0] is Exception or sys.exc_info()[0])
...   print((IS_PY3 and sys.exc_info()[0] is None) or
...         (not IS_PY3 and sys.exc_info()[0] is Exception) or
...         sys.exc_info()[0])

>>> test_py2()
True
True
True
True
True
True
True
>>> print(sys.exc_info()[0]) # test_py2()
None

>>> test_c2()
True
True
True
True
True
True
True
>>> print(sys.exc_info()[0]) # test_c2()
None
"""


def test_c(outer_exc):
    try:
        raise AttributeError
    except AttributeError:
        print(sys.exc_info()[0] is AttributeError or sys.exc_info()[0])
        try: raise KeyError
        except:
            print(sys.exc_info()[0] is KeyError or sys.exc_info()[0])
            if IS_PY3:
                print(isinstance(sys.exc_info()[1].__context__, AttributeError)
                      or sys.exc_info()[1].__context__)
            else:
                print(True)
        print(sys.exc_info()[0] is AttributeError or sys.exc_info()[0])
    print(sys.exc_info()[0] is outer_exc or sys.exc_info()[0])


def test_c2():
    try:
        raise Exception
    except Exception:
        test_c(Exception)
        print(sys.exc_info()[0] is Exception or sys.exc_info()[0])
    print(sys.exc_info()[0] is None or sys.exc_info()[0])
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/funcexceptcypy.pyx0000644000175100001770000000250300000000000021355 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> import sys
>>> if not IS_PY3: sys.exc_clear()

>>> def test_py():
...   old_exc = sys.exc_info()[0]
...   try:
...     raise AttributeError("test")
...   except AttributeError:
...     test_c(error=AttributeError)
...     print(sys.exc_info()[0] is AttributeError or sys.exc_info()[0])
...   print((IS_PY3 and sys.exc_info()[0] is old_exc) or
...         (not IS_PY3 and sys.exc_info()[0] is AttributeError) or
...         sys.exc_info()[0])

>>> print(sys.exc_info()[0]) # 0
None
>>> test_py()
True
True
True
True

>>> print(sys.exc_info()[0]) # test_py()
None

>>> test_c(test_py)
True
True
True
True
True
True

>>> print(sys.exc_info()[0]) # test_c()
None

>>> def test_raise():
...   raise TestException("test")
>>> test_catch(test_raise, TestException)
True
None
"""

import sys
IS_PY3 = sys.version_info[0] >= 3

class TestException(Exception):
    pass

def test_c(func=None, error=None):
    try:
        raise TestException(u"test")
    except TestException:
        if func:
            func()
        print(sys.exc_info()[0] is TestException or sys.exc_info()[0])
    print(sys.exc_info()[0] is error or sys.exc_info()[0])

def test_catch(func, error):
    try:
        func()
    except error:
        print(sys.exc_info()[0] is error or sys.exc_info()[0])
    print(sys.exc_info()[0] is error or sys.exc_info()[0])
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/funcexceptraise.pyx0000644000175100001770000000047500000000000021502 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> def bar():
...     try:
...         foo()
...     except ValueError:
...         pass

>>> bar()
>>> print(sys.exc_info())
(None, None, None)
"""

import sys
if sys.version_info[0] < 3:
    sys.exc_clear()

def foo():
    try:
        raise TypeError
    except TypeError:
        raise ValueError
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/funcexceptraisefrom.pyx0000644000175100001770000000171300000000000022362 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> def bar():
...     try:
...         foo()
...     except ValueError:
...         if IS_PY3:
...             print(isinstance(sys.exc_info()[1].__cause__, TypeError))
...         else:
...             print(True)

>>> bar()
True

>>> print(sys.exc_info())
(None, None, None)

>>> def bar2():
...     try:
...         foo2()
...     except ValueError:
...         if IS_PY3:
...             cause = sys.exc_info()[1].__cause__
...             print(isinstance(cause, TypeError))
...             print(cause.args==('value',))
...             pass
...         else:
...             print(True)
...             print(True)

>>> bar2()
True
True
"""

import sys
IS_PY3 = sys.version_info[0] >= 3
if not IS_PY3:
    sys.exc_clear()

def foo():
    try:
        raise TypeError
    except TypeError:
        raise ValueError from TypeError

def foo2():
    try:
        raise TypeError
    except TypeError:
        raise ValueError() from TypeError('value')

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/funcexceptreplace.pyx0000644000175100001770000000051400000000000022004 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> try: exc()
... except IndexError:
...     if IS_PY3:
...         print(isinstance(sys.exc_info()[1].__context__, ValueError))
...     else:
...         print(True)
True
"""

import sys
IS_PY3 = sys.version_info[0] >= 3

def exc():
    try:
        raise ValueError
    except ValueError:
        raise IndexError
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/funcexceptreraise.pyx0000644000175100001770000000227200000000000022026 0ustar00runnerdocker00000000000000import sys

def reraise(f, exc):
    """
    >>> def f(exc): raise exc
    >>> reraise(f, TypeError)
    Traceback (most recent call last):
    TypeError

    >>> def f(exc): raise exc('hiho')
    >>> reraise(f, TypeError)
    Traceback (most recent call last):
    TypeError: hiho
    """
    try:
        f(exc)
    except:
        assert sys.exc_info()[0] is exc, str(sys.exc_info()[1])
        raise

def reraise_original(f, exc, raise_catch):
    """
    >>> def f(exc): raise exc
    >>> def raise_catch_py():
    ...     try: raise ValueError
    ...     except: pass

    >>> reraise_original(f, TypeError, raise_catch_py)
    Traceback (most recent call last):
    TypeError

    >>> reraise_original(f, TypeError, raise_catch_cy)
    Traceback (most recent call last):
    TypeError

    >>> reraise_original(f, TypeError, raise_catch_cy_non_empty)
    Traceback (most recent call last):
    TypeError
    """
    try:
        f(exc)
    except:
        raise_catch()
        assert sys.exc_info()[0] is exc, str(sys.exc_info()[1])
        raise


def raise_catch_cy():
    try: raise ValueError
    except: pass

def raise_catch_cy_non_empty():
    try: raise ValueError
    except:
        a = 1+1
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/funcexceptreturn.pyx0000644000175100001770000000062600000000000021714 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> import sys
>>> if not IS_PY3: sys.exc_clear()

>>> print(sys.exc_info()[0]) # 0
None
>>> exc = test_c()
>>> isinstance(exc, TestException) or exc
True
>>> print(sys.exc_info()[0]) # test_c()
None
"""

import sys

IS_PY3 = sys.version_info[0] >= 3

class TestException(Exception):
    pass

def test_c():
    try:
        raise TestException
    except TestException, e:
        return e
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/function_as_method_T494.pyx0000644000175100001770000000152100000000000022677 0ustar00runnerdocker00000000000000# ticket: t494
# cython: binding=True

__doc__ = """
    >>> A.foo = foo
    >>> A().foo()
    True
"""

class A:
    pass

def foo(self):
    return self is not None

# assignment of functions used in a "static method" type way behaves differently
# in Python2 and 3
import sys
if sys.version_info[0] == 2:
    __doc__ = """>>> B.plus1(1) #doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
    ...
TypeError: unbound
"""
else:
    __doc__ = """>>> B.plus1(1)
2
"""

# with binding==False assignment of functions always worked - doesn't match Python
# behaviour but ensures Cython behaviour stays consistent
__doc__ += """
>>> B.plus1_nobind(1)
2
"""

cimport cython

def f_plus(a):
    return a + 1

@cython.binding(False)
def f_plus_nobind(a):
    return a+1

cdef class B:
    plus1 = f_plus
    plus1_nobind = f_plus_nobind


././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/function_as_method_py_T494.py0000644000175100001770000000126700000000000023226 0ustar00runnerdocker00000000000000# ticket: t494

__doc__ = """
    >>> A.foo = foo
    >>> A().foo()
    True
"""

class A:
    pass

def foo(self):
    return self is not None


# assignment of functions used in a "static method" type way behaves differently
# in Python2 and 3
import sys
if sys.version_info[0] == 2:
    __doc__ = u"""
>>> B.plus1(1) #doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
    ...
TypeError: unbound
>>> C.plus1(1) #doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
    ...
TypeError: unbound
"""
else:
    __doc__ = u"""
>>> B.plus1(1)
2
>>> C.plus1(1)
2
"""

def f_plus(a):
    return a + 1

class B:
    plus1 = f_plus

class C(object):
    plus1 = f_plus
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/function_binding_T494.pyx0000644000175100001770000000123600000000000022351 0ustar00runnerdocker00000000000000# ticket: t494

cimport cython

class SomeNumber(object):

    def __init__(self, n):
        self._n = n

    def __repr__(self):
        return "SomeNumber(%s)" % self._n

@cython.binding(True)
def add_to_func(self, x):
    """
    >>> add_to_func(SomeNumber(2), 5)
    7
    >>> SomeNumber(3).add_to(10)
    13
    >>> SomeNumber.add_to(SomeNumber(22), 7)
    29
    """
    return self._n + x

@cython.binding(False)
def new_num(n):
    """
    >>> new_num(11)
    SomeNumber(11)
    >>> SomeNumber.new(11)
    SomeNumber(11)
    >>> SomeNumber(3).new(11)
    SomeNumber(11)
    """
    return SomeNumber(n)

SomeNumber.add_to = add_to_func
SomeNumber.new = new_num
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/function_self.py0000644000175100001770000000333600000000000020757 0ustar00runnerdocker00000000000000# mode: run
# tag: pure2.7

# cython: binding=True

import cython
import sys

def regular(x):
    """
    >>> hasattr(regular, "__self__")
    False
    >>> nested = regular(10)
    >>> hasattr(nested, "__self__")
    False
    """
    def nested(y):
        return x+y
    return nested

@cython.locals(x=cython.floating)
def fused(x):
    """
    >>> nested = fused(10.)
    >>> hasattr(nested, "__self__")
    False

    >>> hasattr(fused, "__self__")
    False
    """
    def nested_in_fused(y):
        return x+y
    return nested_in_fused

# FIXME - doesn't currently work at all
#def get_nested_fused(x):
#    @cython.locals(x=cython.floating)
#    def nested_fused(y):
#        return x+y
#    return nested_fused

class C:
    """
    >>> c = C()
    >>> c.regular.__self__ is c
    True
    >>> c.fused.__self__ is c
    True
    """
    def regular(self):
        pass

    @cython.locals(x=cython.floating)
    def fused(self, x):
        return x

__doc__ = ""
if sys.version_info[0] > 2 or cython.compiled:
    __doc__ += """
    >>> hasattr(C.regular, "__self__")  # __self__==None on pure-python 2
    False

    # returns None on pure-python 2
    >>> C.fused.__self__  #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    AttributeError: 'function' object has no attribute '__self__'...
    """

if cython.compiled:
    __doc__ = """
    >>> hasattr(fused['double'], '__self__')
    False

    >>> hasattr(C.fused['double'], '__self__')
    False

    >>> c = C()
    >>> c.fused['double'].__self__ is c   #doctest: +ELLIPSIS
    True

    # The PR that changed __self__ also changed how __doc__ is set up slightly
    >>> fused['double'].__doc__ == fused.__doc__ and isinstance(fused.__doc__, str)
    True
    """
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/fused_bound_functions.py0000644000175100001770000001413200000000000022502 0ustar00runnerdocker00000000000000# mode: run
# tag: pure3.0
# cython: binding=True

"""
Test that fused functions can be used in the same way as CyFunctions with respect to
assigning them to class attributes. Previously they enforced extra type/argument checks
beyond those which CyFunctions did.
"""

import cython

MyFusedClass = cython.fused_type(
    float,
    'Cdef',
    object)

def fused_func(x: MyFusedClass):
    return (type(x).__name__, cython.typeof(x))

IntOrFloat = cython.fused_type(int, float)

def fused_func_0(x: IntOrFloat = 0):
    """
    Fused functions can legitimately take 0 arguments
    >>> fused_func_0()
    ('int', 'int')

    # subscripted in module __doc__ conditionally
    """
    return (type(x).__name__, cython.typeof(x))

def regular_func(x):
    return (type(x).__name__, cython.typeof(x))

def regular_func_0():
    return

@classmethod
def fused_classmethod_free(cls, x: IntOrFloat):
    return (cls.__name__, type(x).__name__)

@cython.cclass
class Cdef:
    __doc__ = """
    >>> c = Cdef()

    # functions are callable with an instance of c
    >>> c.fused_func()
    ('Cdef', 'Cdef')
    >>> c.regular_func()
    ('Cdef', '{typeofCdef}')
    >>> c.fused_in_class(1.5)
    ('float', 'float')

    # Fused functions are callable without an instance
    # (This applies to everything in Py3 - see __doc__ below)
    >>> Cdef.fused_func(1.5)
    ('float', 'float')
    >>> Cdef.fused_in_class(c, 1.5)
    ('float', 'float')
    >>> Cdef.fused_func_0()
    ('int', 'int')

    # Functions not expecting an argument don't work with an instance
    >>> c.regular_func_0()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: regular_func_0() takes ... arguments ...1... given...

    # Looking up a class attribute doesn't go through all of __get__
    >>> Cdef.fused_in_class is Cdef.fused_in_class
    True

    # looking up a classmethod does go through __get__ though
    >>> Cdef.fused_classmethod is Cdef.fused_classmethod
    False
    >>> Cdef.fused_classmethod_free is Cdef.fused_classmethod_free
    False
    >>> Cdef.fused_classmethod(1)
    ('Cdef', 'int')
    >>> Cdef.fused_classmethod_free(1)
    ('Cdef', 'int')
    """.format(typeofCdef = 'Python object' if cython.compiled else 'Cdef')

    if cython.compiled:
        __doc__ += """

    # fused_func_0 does not accept a "Cdef" instance
    >>> c.fused_func_0()
    Traceback (most recent call last):
    TypeError: No matching signature found

    # subscripting requires fused methods (so  not pure Python)
    >>> Cdef.fused_func_0['float']()
    ('float', 'float')
    >>> c.fused_func_0['float']()  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    TypeError: (Exception looks quite different in Python2 and 3 so no way to match both)

    >>> Cdef.fused_classmethod['float'] is Cdef.fused_classmethod['float']
    False
    >>> Cdef.fused_classmethod_free['float'] is Cdef.fused_classmethod_free['float']
    False
    """
    fused_func = fused_func
    fused_func_0 = fused_func_0
    regular_func = regular_func
    regular_func_0 = regular_func_0

    fused_classmethod_free = fused_classmethod_free

    def fused_in_class(self, x: MyFusedClass):
        return (type(x).__name__, cython.typeof(x))

    def regular_in_class(self):
        return type(self).__name__

    @classmethod
    def fused_classmethod(cls, x: IntOrFloat):
        return (cls.__name__, type(x).__name__)

class Regular(object):
    __doc__ = """
    >>> c = Regular()

    # Functions are callable with an instance of C
    >>> c.fused_func()
    ('Regular', '{typeofRegular}')
    >>> c.regular_func()
    ('Regular', '{typeofRegular}')

    # Fused functions are callable without an instance
    # (This applies to everything in Py3 - see __doc__ below)
    >>> Regular.fused_func(1.5)
    ('float', 'float')
    >>> Regular.fused_func_0()
    ('int', 'int')

    # Functions not expecting an argument don't work with an instance
    >>> c.regular_func_0()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: regular_func_0() takes ... arguments ...1... given...

    # Looking up a class attribute doesn't go through all of __get__
    >>> Regular.fused_func is Regular.fused_func
    True

    # looking up a classmethod does go __get__ though
    >>> Regular.fused_classmethod is Regular.fused_classmethod
    False
    >>> Regular.fused_classmethod_free is Regular.fused_classmethod_free
    False
    >>> Regular.fused_classmethod(1)
    ('Regular', 'int')
    >>> Regular.fused_classmethod_free(1)
    ('Regular', 'int')
    """.format(typeofRegular = "Python object" if cython.compiled else 'Regular')
    if cython.compiled:
        __doc__ += """
    # fused_func_0 does not accept a "Regular" instance
    >>> c.fused_func_0()
    Traceback (most recent call last):
    TypeError: No matching signature found

    # subscripting requires fused methods (so  not pure Python)
    >>> c.fused_func_0['float']()  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    TypeError: (Exception looks quite different in Python2 and 3 so no way to match both)
    >>> Regular.fused_func_0['float']()
    ('float', 'float')

    >>> Regular.fused_classmethod['float'] is Regular.fused_classmethod['float']
    False
    >>> Regular.fused_classmethod_free['float'] is Regular.fused_classmethod_free['float']
    False
    """

    fused_func = fused_func
    fused_func_0 = fused_func_0
    regular_func = regular_func
    regular_func_0 = regular_func_0

    fused_classmethod_free = fused_classmethod_free

    @classmethod
    def fused_classmethod(cls, x: IntOrFloat):
        return (cls.__name__, type(x).__name__)

import sys
if sys.version_info[0] > 2:
    # extra Py3 only tests - shows that functions added to a class can be called
    # with an type as the first argument
    __doc__ = """
    >>> Cdef.regular_func(1.5)
    ('float', '{typeoffloat}')
    >>> Regular.regular_func(1.5)
    ('float', '{typeoffloat}')
    >>> Cdef.regular_func_0()
    >>> Regular.regular_func_0()
    """.format(typeoffloat='Python object' if cython.compiled else 'float')
if cython.compiled:
    __doc__ += """
    >>> fused_func_0['float']()
    ('float', 'float')
    """
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/fused_cmethods.srctree0000644000175100001770000001347100000000000022135 0ustar00runnerdocker00000000000000"""
PYTHON setup.py build_ext -i
PYTHON main.py
"""

######## main.py ########

from __future__ import absolute_import
from pkg.user import UseRegisters

def test():
    from pkg import called
    assert called == [], called

    ureg = UseRegisters()

    assert called == [
        'Before setFullFlags',
        'setFullFlags was called',
        'After setFullFlags',
    ], called

    del called[:]
    ureg.call_write()

    assert called == [
        'Before regWriteWithOpWords',
        'regWriteWithOpWords was called',
        'regWriteWithOpWords leave function',
        'After regWriteWithOpWords',
    ], called

    del called[:]
    ureg.call_non_fused()

    assert called == [
        'Before nonFusedMiddle',
        'nonFusedMiddle was called',
        'After nonFusedMiddle',
        'Before nonFusedBottom',
        'nonFusedBottom was called',
        'After nonFusedBottom',
        'Before nonFusedTop',
        'nonFusedTop was called',
        'After nonFusedTop',
    ], called


def test_sub():
    from pkg import called
    from pkg.registers import SubRegisters
    ureg = UseRegisters(reg_type=SubRegisters)

    del called[:]
    ureg.call_sub()

    assert called == [
        'Before nonFusedSub',
        'nonFusedSub was called',
        'After nonFusedSub',
        'Before fusedSub',
        'fusedSub was called',
        'After fusedSub',
    ], called


test()
test_sub()


######## setup.py ########

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize('pkg/*.pyx'))

######## pkg/__init__.py ########

called = []

######## pkg/user.pxd ########

from .registers cimport Registers, SubRegisters

cdef class UseRegisters:
    cdef Registers registers


######## pkg/user.pyx ########

from . import called

cdef class UseRegisters:
    def __init__(self, reg_type=Registers):
        self.registers = reg_type()
        called.append("Before setFullFlags")
        self.registers.setFullFlags(12345, 0)
        called.append("After setFullFlags")

    def call_write(self):
        called.append("Before regWriteWithOpWords")
        self.registers.regWriteWithOpWords(0, 0)
        called.append("After regWriteWithOpWords")

    def call_non_fused(self):
        called.append("Before nonFusedMiddle")
        self.registers.nonFusedMiddle(0, 0)
        called.append("After nonFusedMiddle")

        called.append("Before nonFusedBottom")
        self.registers.nonFusedBottom(0, 0)
        called.append("After nonFusedBottom")

        called.append("Before nonFusedTop")
        self.registers.nonFusedTop(0, 0)
        called.append("After nonFusedTop")

    def call_sub(self):
        assert isinstance(self.registers, SubRegisters), type(self.registers)
        called.append("Before nonFusedSub")
        (self.registers).nonFusedSub(0, 0)
        called.append("After nonFusedSub")

        called.append("Before fusedSub")
        (self.registers).fusedSub(0, 0)
        called.append("After fusedSub")


######## pkg/registers.pxd ########

from cython cimport integral

cdef class Registers:
    cdef unsigned long long regs[1]
    cdef void nonFusedTop(self, unsigned short regId, unsigned int value)
    cdef void regWriteWithOpWords(self, unsigned short regId, integral value)
    cdef void nonFusedMiddle(self, unsigned short regId, unsigned int value)
    cdef void setFullFlags(self, integral reg0, unsigned int reg1)
    cdef void nonFusedBottom(self, unsigned short regId, unsigned int value)
    cdef void lastFusedImplFirst(self, integral reg0, unsigned int reg1)


cdef class SubRegisters(Registers):
    cdef void fusedSub(self, integral reg0, unsigned int reg1)
    cdef void nonFusedSub(self, unsigned short regId, unsigned int value)


######## pkg/registers.pyx ########

from . import called

cdef class Registers:
    def __init__(self):
        pass

    cdef void lastFusedImplFirst(self, integral reg0, unsigned int reg1):
        called.append("lastFusedImplFirst was called")

    cdef void nonFusedTop(self, unsigned short regId, unsigned int value):
        called.append("nonFusedTop was called")

    cdef void regWriteWithOpWords(self, unsigned short regId, integral value):
        called.append("regWriteWithOpWords was called")
        self.regs[regId] = value
        called.append("regWriteWithOpWords leave function")

    cdef void nonFusedMiddle(self, unsigned short regId, unsigned int value):
        called.append("nonFusedMiddle was called")

    cdef void setFullFlags(self, integral reg0, unsigned int reg1):
        called.append("setFullFlags was called")

    cdef void nonFusedBottom(self, unsigned short regId, unsigned int value):
        called.append("nonFusedBottom was called")


cdef class SubRegisters(Registers):
    cdef void fusedSub(self, integral reg0, unsigned int reg1):
        called.append("fusedSub was called")

    cdef void nonFusedSub(self, unsigned short regId, unsigned int value):
        called.append("nonFusedSub was called")


######## pkg/sub.pxd ########

from .registers cimport *

cdef class SubSubRegisters(SubRegisters):
    cdef void fusedSubSubFirst(self, integral reg0, unsigned int reg1)
    cdef void nonFusedSubSub(self, unsigned short regId, unsigned int value)
    cdef void fusedSubSubLast(self, integral reg0, unsigned int reg1)


######## pkg/sub.pyx ########

from . import called

cdef class SubSubRegisters(SubRegisters):
    cdef void fusedSubSubFirst(self, integral reg0, unsigned int reg1):
        called.append("fusedSubSubFirst was called")

    cdef void nonFusedSubSub(self, unsigned short regId, unsigned int value):
        called.append("nonFusedSubSub was called")

    cdef void fusedSubSubLast(self, integral reg0, unsigned int reg1):
        called.append("fusedSubSubLast was called")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/fused_cpdef.pxd0000644000175100001770000000014000000000000020521 0ustar00runnerdocker00000000000000cimport cython

cdef class C:
    cpdef object has_default_struct(self, cython.floating x, a=?)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/fused_cpdef.pyx0000644000175100001770000001235100000000000020555 0ustar00runnerdocker00000000000000# cython: language_level=3str
# mode: run

cimport cython
import sys, io

cy = __import__("cython")

cpdef func1(self, cython.integral x):
    print(f"{self},", end=' ')
    if cython.integral is int:
        print('x is int', x, cython.typeof(x))
    else:
        print('x is long', x, cython.typeof(x))


class A(object):
    meth = func1

    def __str__(self):
        return "A"

cdef class B:
    cpdef int meth(self, cython.integral x):
        print(f"{self},", end=' ')
        if cython.integral is int:
            print('x is int', x, cython.typeof(x))
        else:
            print('x is long', x, cython.typeof(x))
        return 0

    def __str__(self):
        return "B"

pyfunc = func1

def test_fused_cpdef():
    """
    >>> test_fused_cpdef()
    None, x is int 2 int
    None, x is long 2 long
    None, x is long 2 long
    
    None, x is int 2 int
    None, x is long 2 long
    
    A, x is int 2 int
    A, x is long 2 long
    A, x is long 2 long
    A, x is long 2 long
    
    B, x is long 2 long
    """
    func1[int](None, 2)
    func1[long](None, 2)
    func1(None, 2)

    print()

    pyfunc[cy.int](None, 2)
    pyfunc(None, 2)

    print()

    A.meth[cy.int](A(), 2)
    A.meth(A(), 2)
    A().meth[cy.long](2)
    A().meth(2)

    print()

    B().meth(2)


midimport_run = io.StringIO()
if sys.version_info.major < 3:
    # Monkey-patch midimport_run.write to accept non-unicode strings under Python 2.
    midimport_run.write = lambda c: io.StringIO.write(midimport_run, unicode(c))

realstdout = sys.stdout
sys.stdout = midimport_run

try:
    # Run `test_fused_cpdef()` during import and save the result for
    #        `test_midimport_run()`.
    test_fused_cpdef()
except Exception as e:
    midimport_run.write(f"{e!r}\n")
finally:
    sys.stdout = realstdout

def test_midimport_run():
    # At one point, dynamically calling fused cpdef functions during import
    #        would fail because the type signature-matching indices weren't
    #        yet initialized.
    #        (See Compiler.FusedNode.FusedCFuncDefNode._fused_signature_index,
    #        GH-3366.)
    """
    >>> test_midimport_run()
    None, x is int 2 int
    None, x is long 2 long
    None, x is long 2 long
    
    None, x is int 2 int
    None, x is long 2 long
    
    A, x is int 2 int
    A, x is long 2 long
    A, x is long 2 long
    A, x is long 2 long
    
    B, x is long 2 long
    """
    print(midimport_run.getvalue(), end='')


def assert_raise(func, *args):
    try:
        func(*args)
    except TypeError:
        pass
    else:
        assert False, "Function call did not raise TypeError"

def test_badcall():
    """
    >>> test_badcall()
    """
    assert_raise(pyfunc)
    assert_raise(pyfunc, 1, 2, 3)
    assert_raise(pyfunc[cy.int], 10, 11, 12)
    assert_raise(pyfunc, None, object())
    assert_raise(A().meth)
    assert_raise(A.meth)
    assert_raise(A().meth[cy.int])
    assert_raise(A.meth[cy.int])
    assert_raise(B().meth, 1, 2, 3)

def test_nomatch():
    """
    >>> func1(None, ())
    Traceback (most recent call last):
    TypeError: No matching signature found
    """

ctypedef long double long_double

cpdef multiarg(cython.integral x, cython.floating y):
    if cython.integral is int:
        print("x is an int,", end=' ')
    else:
        print("x is a long,", end=' ')

    if cython.floating is long_double:
        print("y is a long double:", end=' ')
    elif float is cython.floating:
        print("y is a float:", end=' ')
    else:
        print("y is a double:", end=' ')

    print(x, y)

def test_multiarg():
    """
    >>> test_multiarg()
    x is an int, y is a float: 1 2.0
    x is an int, y is a float: 1 2.0
    x is a long, y is a double: 4 5.0
    >>> multiarg()
    Traceback (most recent call last):
    TypeError: Expected at least 2 arguments, got 0
    >>> multiarg(1, 2.0, 3)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...2...arg...3...
    """
    multiarg[int, float](1, 2.0)
    multiarg[cy.int, cy.float](1, 2.0)
    multiarg(4, 5.0)

def test_ambiguousmatch():
    """
    >>> multiarg(5, ())
    Traceback (most recent call last):
    TypeError: Function call with ambiguous argument types
    >>> multiarg((), 2.0)
    Traceback (most recent call last):
    TypeError: Function call with ambiguous argument types
    """

# https://github.com/cython/cython/issues/4409
# default arguments + fused cpdef were crashing
cpdef literal_default(cython.integral x, some_string="value"):
    return x, some_string

cpdef mutable_default(cython.integral x, some_value=[]):
    some_value.append(x)
    return some_value

def test_defaults():
    """
    >>> literal_default(1)
    (1, 'value')
    >>> literal_default(1, "hello")
    (1, 'hello')
    >>> mutable_default(1)
    [1]
    >>> mutable_default(2)
    [1, 2]
    >>> mutable_default(3,[])
    [3]
    """

cdef class C:
    cpdef object has_default_struct(self, cython.floating x, a=None):
        return x, a

# https://github.com/cython/cython/issues/5588
# On some Python versions this was causing a compiler crash
def test_call_has_default_struct(C c, double x):
    """
    >>> test_call_has_default_struct(C(), 5.)
    (5.0, None)
    """
    return c.has_default_struct(x)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/fused_cpp.pyx0000644000175100001770000000372700000000000020265 0ustar00runnerdocker00000000000000# tag: cpp

cimport cython
from libcpp.vector cimport vector
from libcpp.map cimport map
from libcpp.typeinfo cimport type_info
from cython.operator cimport typeid

def test_cpp_specialization(cython.floating element):
    """
    >>> import cython
    >>> test_cpp_specialization[cython.float](10.0)
    vector[float] * float 10.0
    >>> test_cpp_specialization[cython.double](10.0)
    vector[double] * double 10.0
    """
    cdef vector[cython.floating] *v = new vector[cython.floating]()
    v.push_back(element)
    print cython.typeof(v), cython.typeof(element), v.at(0)

cdef fused C:
   int
   object

cdef const type_info* tidint = &typeid(int)
def typeid_call(C x):
    """
    For GH issue 3203
    >>> typeid_call(1)
    True
    """
    cdef const type_info* a = &typeid(C)
    return a[0] == tidint[0]

cimport cython

def typeid_call2(cython.integral x):
    """
    For GH issue 3203
    >>> typeid_call2[int](1)
    True
    """
    cdef const type_info* a = &typeid(cython.integral)
    return a[0] == tidint[0]

cdef fused_ref(cython.integral& x):
    return x*2

def test_fused_ref(int x):
    """
    >>> test_fused_ref(5)
    (10, 10)
    """
    return fused_ref(x), fused_ref[int](x)

ctypedef fused nested_fused:
    vector[cython.integral]

cdef vec_of_fused(nested_fused v):
    x = v[0]
    return cython.typeof(x)

def test_nested_fused():
    """
    >>> test_nested_fused()
    int
    long
    """
    cdef vector[int] vi = [0,1]
    cdef vector[long] vl = [0,1]
    print vec_of_fused(vi)
    print vec_of_fused(vl)

ctypedef fused nested_fused2:
    map[cython.integral, cython.floating]

cdef map_of_fused(nested_fused2 m):
    for pair in m:
        return cython.typeof(pair.first), cython.typeof(pair.second)

def test_nested_fused2():
    """
    >>> test_nested_fused2()
    ('int', 'float')
    ('long', 'double')
    """
    cdef map[int, float] mif = { 0: 0.0 }
    cdef map[long, double] mld = { 0: 0.0 }
    print map_of_fused(mif)
    print map_of_fused(mld)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/fused_def.pyx0000644000175100001770000002727400000000000020244 0ustar00runnerdocker00000000000000# mode: run

"""
Test Python def functions without extern types
"""

cy = __import__("cython")
cimport cython

cdef extern from *:
    int __Pyx_CyFunction_Check(object)

cdef class Base(object):
    def __repr__(self):
        return type(self).__name__


cdef class ExtClassA(Base):
    pass

cdef class ExtClassB(Base):
    pass

cdef enum MyEnum:
    entry0
    entry1
    entry2
    entry3
    entry4

ctypedef fused fused_t:
    str
    int
    long
    complex
    ExtClassA
    ExtClassB
    MyEnum


ctypedef ExtClassA xxxlast
ctypedef ExtClassB aaafirst


ctypedef fused fused_with_object:
    aaafirst
    object
    xxxlast
    int
    long


f = 5.6
i = 9


def opt_func(fused_t obj, cython.floating myf = 1.2, cython.integral myi = 7,
             another_opt = 2, yet_another_opt=3):
    """
    Test runtime dispatch, indexing of various kinds and optional arguments.
    Use 5 arguments because at one point the optional argument from the
    5th argument was overwriting that of the __pyx_fused dispatcher.
    https://github.com/cython/cython/issues/3511

    >>> opt_func("spam", f, i)
    str object double long
    spam 5.60 9 5.60 9
    >>> opt_func("spam", f, myi=i)
    str object double long
    spam 5.60 9 5.60 9
    >>> opt_func("spam", myf=f, myi=i)
    str object double long
    spam 5.60 9 5.60 9
    >>> opt_func[str, float, int]("spam", f, i)
    str object float int
    spam 5.60 9 5.60 9
    >>> opt_func[str, cy.double, cy.long]("spam", f, i)
    str object double long
    spam 5.60 9 5.60 9
    >>> opt_func[str, cy.double, cy.long]("spam", f, myi=i)
    str object double long
    spam 5.60 9 5.60 9
    >>> opt_func[str, float, cy.int]("spam", f, i)
    str object float int
    spam 5.60 9 5.60 9


    >>> opt_func(ExtClassA(), f, i)
    ExtClassA double long
    ExtClassA 5.60 9 5.60 9
    >>> opt_func[ExtClassA, float, int](ExtClassA(), f, i)
    ExtClassA float int
    ExtClassA 5.60 9 5.60 9
    >>> opt_func[ExtClassA, cy.double, cy.long](ExtClassA(), f, i)
    ExtClassA double long
    ExtClassA 5.60 9 5.60 9

    >>> opt_func(ExtClassB(), f, i)
    ExtClassB double long
    ExtClassB 5.60 9 5.60 9
    >>> opt_func[ExtClassB, cy.double, cy.long](ExtClassB(), f, i)
    ExtClassB double long
    ExtClassB 5.60 9 5.60 9

    >>> opt_func(10, f)
    long double long
    10 5.60 7 5.60 9
    >>> opt_func[int, float, int](10, f)
    int float int
    10 5.60 7 5.60 9

    >>> opt_func(10 + 2j, myf = 2.6)
    double complex double long
    (10+2j) 2.60 7 5.60 9
    >>> opt_func[cy.py_complex, float, int](10 + 2j, myf = 2.6)
    double complex float int
    (10+2j) 2.60 7 5.60 9
    >>> opt_func[cy.doublecomplex, cy.float, cy.int](10 + 2j, myf = 2.6)
    double complex float int
    (10+2j) 2.60 7 5.60 9

    >>> opt_func(object(), f)
    Traceback (most recent call last):
    TypeError: Function call with ambiguous argument types
    >>> opt_func()
    Traceback (most recent call last):
    TypeError: Expected at least 1 argument, got 0
    >>> opt_func("abc", f, i, 5, 5, 5)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...at most 5...
    >>> opt_func[ExtClassA, cy.float, cy.long](object(), f)
    Traceback (most recent call last):
    TypeError: Argument 'obj' has incorrect type (expected fused_def.ExtClassA, got object)
    """
    print cython.typeof(obj), cython.typeof(myf), cython.typeof(myi)
    print obj, "%.2f" % myf, myi, "%.2f" % f, i

def non_fused_opt(fused_t obj, value=5):
    """
    PyObject constants as parts of fused functions weren't being created correctly
    which would lead this to crash
    >>> non_fused_opt(0)
    5
    >>> non_fused_opt("str", 10)
    10
    """
    print value

def run_cyfunction_check():
    """
    tp_base of the fused function was being set incorrectly meaning
    it wasn't being identified as a CyFunction
    >>> run_cyfunction_check()
    fused_cython_function
    1
    """
    print(type(opt_func).__name__.rsplit('.', 1)[-1])
    print(__Pyx_CyFunction_Check(opt_func))  # should be True

def test_opt_func():
    """
    >>> test_opt_func()
    str object double long
    ham 5.60 4 5.60 9
    """
    opt_func("ham", f, entry4)


def test_opt_func_introspection():
    """
    >>> opt_func.__defaults__
    (1.2, 7, 2, 3)
    >>> opt_func.__kwdefaults__
    >>> opt_func.__annotations__
    {}

    >>> opt_func[str, float, int].__defaults__
    (1.2, 7, 2, 3)
    >>> opt_func[str, float, int].__kwdefaults__
    >>> opt_func[str, float, int].__annotations__
    {}

    >>> opt_func[str, cy.double, cy.long].__defaults__
    (1.2, 7, 2, 3)
    >>> opt_func[str, cy.double, cy.long].__kwdefaults__
    >>> opt_func[str, cy.double, cy.long].__annotations__
    {}
    """


def func_with_object(fused_with_object obj, cython.integral myi = 7):
    """
    >>> func_with_object(1)
    long long
    1 7
    >>> func_with_object(1, 3)
    long long
    1 3
    >>> func_with_object['int', 'int'](1, 3)
    int int
    1 3
    >>> func_with_object(1j, 3)
    Python object long
    1j 3
    >>> func_with_object('abc', 3)
    Python object long
    abc 3
    >>> func_with_object(ExtClassA(), 3)
    xxxlast long
    ExtClassA 3
    >>> func_with_object(ExtClassB(), 3)
    aaafirst long
    ExtClassB 3
    >>> func_with_object['object', 'long'](ExtClassA(), 3)
    Python object long
    ExtClassA 3
    >>> func_with_object['object', 'long'](ExtClassB(), 3)
    Python object long
    ExtClassB 3
    """
    print cython.typeof(obj), cython.typeof(myi)
    print obj, myi



def args_kwargs(fused_t obj, cython.floating myf = 1.2, *args, **kwargs):
    """
    >>> args_kwargs("foo")
    str object double
    foo 1.20 5.60 () {}

    >>> args_kwargs("eggs", f, 1, 2, [], d={})
    str object double
    eggs 5.60 5.60 (1, 2, []) {'d': {}}

    >>> args_kwargs[str, float]("eggs", f, 1, 2, [], d={})
    str object float
    eggs 5.60 5.60 (1, 2, []) {'d': {}}

    """
    print cython.typeof(obj), cython.typeof(myf)
    print obj, "%.2f" % myf, "%.2f" % f, args, kwargs


class BaseClass(object):
    """
    Test fused class/static/normal methods and super() without args
    """

    @staticmethod
    def mystaticmethod(cython.integral arg1):
        print cython.typeof(arg1), arg1

    @classmethod
    def myclassmethod(cls, cython.integral arg1):
        print cls, cython.typeof(arg1), arg1

    def normalmethod(self, cython.integral arg1):
        print self, cython.typeof(arg1), arg1

    def __repr__(self):
        return "<%s.%s object>" % (__name__, type(self).__name__)

class SubClass(BaseClass):

    @staticmethod
    def mystaticmethod(self, cython.integral arg1):
        print cython.typeof(arg1), arg1
        super().mystaticmethod(arg1 + 1)

    @classmethod
    def myclassmethod(cls, cython.integral arg1):
        print cls, cython.typeof(arg1), arg1
        super().myclassmethod(arg1 + 1)

    def normalmethod(self, cython.integral arg1):
        print self, cython.typeof(arg1), arg1
        super().normalmethod(arg1 + 1)

class SubSubClass(SubClass):
    pass

def test_fused_def_super():
    """
    >>> test_fused_def_super()
    long 10
    long 11
    long 11
    long 12
    short 12
    long 13
    short 13
    long 14
     long 14
     long 15
     long 15
     long 16
     short 16
     long 17
     short 17
     long 18
     long 18
     long 19
     long 19
     long 20
     short 20
     long 21
     short 21
     long 22
    """
    obj = SubClass()
    cls = SubClass

    obj.mystaticmethod(obj, 10)
    cls.mystaticmethod(obj, 11)
    obj.mystaticmethod[cy.short](obj, 12)
    cls.mystaticmethod[cy.short](obj, 13)

    obj.myclassmethod(14)
    cls.myclassmethod(15)
    obj.myclassmethod[cy.short](16)
    cls.myclassmethod[cy.short](17)

    obj.normalmethod(18)
    cls.normalmethod(obj, 19)
    obj.normalmethod[cy.short](20)
    cls.normalmethod[cy.short](obj, 21)

def test_fused_def_classmethod():
    """
    >>> test_fused_def_classmethod()
     long 10
     long 11
     long 11
     long 12
     short 12
     long 13
     short 13
     long 14
    """
    SubSubClass().myclassmethod(10)
    SubSubClass.myclassmethod(11)

    SubSubClass().myclassmethod[cy.short](12)
    SubSubClass.myclassmethod[cy.short](13)

cdef class CBaseClass(object):
    """
    Test fused def and cpdef methods in cdef classes.

    >>> import cython as cy
    >>> obj = CBaseClass()
    >>> cls = CBaseClass

    >>> obj.mystaticmethod(10)
    long 10
    >>> obj.mystaticmethod[cy.short](10)
    short 10
    >>> cls.mystaticmethod(10)
    long 10
    >>> cls.mystaticmethod[cy.short](10)
    short 10

    >>> obj.myclassmethod(10)
    CBaseClass long 10
    >>> obj.myclassmethod[cy.short](10)
    CBaseClass short 10
    >>> cls.myclassmethod(10)
    CBaseClass long 10
    >>> cls.myclassmethod[cy.short](10)
    CBaseClass short 10

    >>> obj.normalmethod(10, 11, 12)
     long 10 11 12
    >>> obj.normalmethod[cy.short](10, 11, 12)
     short 10 11 12
    >>> cls.normalmethod(obj, 10, 11, 12)
     long 10 11 12
    >>> cls.normalmethod[cy.short](obj, 10, 11, 12)
     short 10 11 12

    >>> obj.cpdefmethod(10)
     long 10
    >>> obj.cpdefmethod[cy.short](10)
     short 10
    >>> cls.cpdefmethod(obj, 10)
     long 10
    >>> cls.cpdefmethod[cy.short](obj, 10)
     short 10
    """

    @staticmethod
    def mystaticmethod(cython.integral arg1):
        print cython.typeof(arg1), arg1

    @classmethod
    def myclassmethod(cls, cython.integral arg1):
        print cls.__name__, cython.typeof(arg1), arg1

    def normalmethod(self, cython.integral arg1, arg2, arg3):
        print self, cython.typeof(arg1), arg1, arg2, arg3

    cpdef cpdefmethod(self, cython.integral arg1):
        print self, cython.typeof(arg1), arg1

    def __repr__(self):
        return "<%s.%s object>" % (__name__, type(self).__name__)

def getcode(func):
    return getattr(func, '__code__', None) or func.func_code

def test_code_object(cython.floating dummy = 2.0):
    """
    A test for default arguments is in cyfunction_defaults

    >>> getcode(test_code_object) is getcode(test_code_object[float])
    True
    """

def create_dec(value):
    def dec(f):
        if not hasattr(f, 'order'):
            f.order = []
        f.order.append(value)
        return f
    return dec

@create_dec(1)
@create_dec(2)
@create_dec(3)
def test_decorators(cython.floating arg):
    """
    >>> test_decorators.order
    [3, 2, 1]
    """

@cython.binding(True)
def bind_me(self, cython.floating a=1.):
    return a

cdef class HasBound:
    """
    Using default arguments of bound specialized fused functions used to cause a segfault
    https://github.com/cython/cython/issues/3370
    >>> inst = HasBound()
    >>> inst.func()
    1.0
    >>> inst.func(2)
    2.0
    >>> inst.func_fused()
    1.0
    >>> inst.func_fused(2.)
    2.0
    >>> bind_me.__defaults__
    (1.0,)
    >>> inst.func.__defaults__
    (1.0,)
    >>> inst.func_fused.__defaults__
    (1.0,)
    """
    func = bind_me[float]

    func_fused = bind_me
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/fused_types.pyx0000644000175100001770000004651300000000000020647 0ustar00runnerdocker00000000000000# mode: run
# ticket: 1772
# cython: language_level=3str

cimport cython
from cython.view cimport array

from cython cimport integral
from cpython cimport Py_INCREF

from Cython import Shadow as pure_cython
ctypedef char * string_t

# floating = cython.fused_type(float, double) floating
# integral = cython.fused_type(int, long) integral
ctypedef cython.floating floating
fused_type1 = cython.fused_type(int, long, float, double, string_t)
fused_type2 = cython.fused_type(string_t)
ctypedef fused_type1 *composed_t
other_t = cython.fused_type(int, double)
ctypedef double *p_double
ctypedef int *p_int
fused_type3 = cython.fused_type(int, double)
fused_composite = cython.fused_type(fused_type2, fused_type3)
just_float = cython.fused_type(float)

ctypedef int inttypedef
ctypedef double doubletypedef
fused_with_typedef = cython.fused_type(inttypedef, doubletypedef)

ctypedef float const_inttypedef  # misleading name
fused_misleading_name = cython.fused_type(const_inttypedef, char)


def test_pure():
    """
    >>> test_pure()
    10
    """
    mytype = pure_cython.typedef(pure_cython.fused_type(int, long, complex))
    print(mytype(10))


cdef cdef_func_with_fused_args(fused_type1 x, fused_type1 y, fused_type2 z):
    if fused_type1 is string_t:
        print(x.decode('ascii'), y.decode('ascii'), z.decode('ascii'))
    else:
        print(x, y, z.decode('ascii'))

    return x + y

def test_cdef_func_with_fused_args():
    """
    >>> test_cdef_func_with_fused_args()
    spam ham eggs
    spamham
    10 20 butter
    30
    4.2 8.6 bunny
    12.8
    """
    print(cdef_func_with_fused_args(b'spam', b'ham', b'eggs').decode('ascii'))
    print(cdef_func_with_fused_args(10, 20, b'butter'))
    print(cdef_func_with_fused_args(4.2, 8.6, b'bunny'))

cdef fused_type1 fused_with_pointer(fused_type1 *array):
    for i in range(5):
        if fused_type1 is string_t:
            print(array[i].decode('ascii'))
        else:
            print(array[i])

    obj = array[0] + array[1] + array[2] + array[3] + array[4]
    # if cython.typeof(fused_type1) is string_t:
    Py_INCREF(obj)
    return obj

def test_fused_with_pointer():
    """
    >>> test_fused_with_pointer()
    0
    1
    2
    3
    4
    10
    
    0
    1
    2
    3
    4
    10
    
    0.0
    1.0
    2.0
    3.0
    4.0
    10.0
    
    humpty
    dumpty
    fall
    splatch
    breakfast
    humptydumptyfallsplatchbreakfast
    """
    cdef int[5] int_array
    cdef long[5] long_array
    cdef float[5] float_array
    cdef string_t[5] string_array

    cdef char *s

    strings = [b"humpty", b"dumpty", b"fall", b"splatch", b"breakfast"]

    for i in range(5):
        int_array[i] = i
        long_array[i] = i
        float_array[i] = i
        s = strings[i]
        string_array[i] = s

    print(fused_with_pointer(int_array))
    print()
    print(fused_with_pointer(long_array))
    print()
    print(fused_with_pointer(float_array))
    print()
    print(fused_with_pointer(string_array).decode('ascii'))

cdef fused_type1* fused_pointer_except_null(fused_type1* x) except NULL:
    if fused_type1 is string_t:
        assert(bool(x[0]))
    else:
        assert(x[0] < 10)
    return x

def test_fused_pointer_except_null(value):
    """
    >>> test_fused_pointer_except_null(1)
    1
    >>> test_fused_pointer_except_null(2.0)
    2.0
    >>> test_fused_pointer_except_null(b'foo')
    foo
    >>> test_fused_pointer_except_null(16)
    Traceback (most recent call last):
    AssertionError
    >>> test_fused_pointer_except_null(15.1)
    Traceback (most recent call last):
    AssertionError
    >>> test_fused_pointer_except_null(b'')
    Traceback (most recent call last):
    AssertionError
    """
    if isinstance(value, int):
        test_int = cython.declare(cython.int, value)
        print(fused_pointer_except_null(&test_int)[0])
    elif isinstance(value, float):
        test_float = cython.declare(cython.float, value)
        print(fused_pointer_except_null(&test_float)[0])
    elif isinstance(value, bytes):
        test_str = cython.declare(string_t, value)
        print(fused_pointer_except_null(&test_str)[0].decode('ascii'))

include "../testsupport/cythonarrayutil.pxi"

cpdef cython.integral test_fused_memoryviews(cython.integral[:, ::1] a):
    """
    >>> import cython
    >>> a = create_array((3, 5), mode="c")
    >>> test_fused_memoryviews[cython.int](a)
    7
    """
    return a[1, 2]

ctypedef int[:, ::1] memview_int
ctypedef long[:, ::1] memview_long
memview_t = cython.fused_type(memview_int, memview_long)

def test_fused_memoryview_def(memview_t a):
    """
    >>> a = create_array((3, 5), mode="c")
    >>> test_fused_memoryview_def["memview_int"](a)
    7
    """
    return a[1, 2]

cdef test_specialize(fused_type1 x, fused_type1 *y, composed_t z, other_t *a):
    cdef fused_type1 result

    if composed_t is p_double:
        print("double pointer")

    if fused_type1 in floating:
        result = x + y[0] + z[0] + a[0]
        return result

def test_specializations():
    """
    >>> test_specializations()
    double pointer
    double pointer
    double pointer
    double pointer
    double pointer
    """
    cdef object (*f)(double, double *, double *, int *)

    cdef double somedouble = 2.2
    cdef double otherdouble = 3.3
    cdef int someint = 4

    cdef p_double somedouble_p = &somedouble
    cdef p_double otherdouble_p = &otherdouble
    cdef p_int someint_p = &someint

    f = test_specialize
    assert f(1.1, somedouble_p, otherdouble_p, someint_p) == 10.6

    f =  test_specialize
    assert f(1.1, somedouble_p, otherdouble_p, someint_p) == 10.6

    assert (
            test_specialize)(1.1, somedouble_p, otherdouble_p, someint_p) == 10.6

    f = test_specialize[double, int]
    assert f(1.1, somedouble_p, otherdouble_p, someint_p) == 10.6

    assert test_specialize[double, int](1.1, somedouble_p, otherdouble_p, someint_p) == 10.6

    # The following cases are not supported
    # f = test_specialize[double][p_int]
    # print f(1.1, somedouble_p, otherdouble_p)
    # print

    # print test_specialize[double][p_int](1.1, somedouble_p, otherdouble_p)
    # print

    # print test_specialize[double](1.1, somedouble_p, otherdouble_p)
    # print

cdef opt_args(integral x, floating y = 4.0):
    print(x, y)

def test_opt_args():
    """
    >>> test_opt_args()
    3 4.0
    3 4.0
    3 4.0
    3 4.0
    """
    opt_args[int,  float](3)
    opt_args[int, double](3)
    opt_args[int,  float](3, 4.0)
    opt_args[int, double](3, 4.0)

class NormalClass(object):
    def method(self, cython.integral i):
        print(cython.typeof(i), i)

def test_normal_class():
    """
    >>> test_normal_class()
    short 10
    """
    NormalClass().method[pure_cython.short](10)

def test_normal_class_refcount():
    """
    >>> test_normal_class_refcount()
    short 10
    0
    """
    import sys
    x = NormalClass()
    c = sys.getrefcount(x)
    x.method[pure_cython.short](10)
    print(sys.getrefcount(x) - c)

def test_fused_declarations(cython.integral i, cython.floating f):
    """
    >>> test_fused_declarations[pure_cython.short, pure_cython.float](5, 6.6)
    short
    float
    25 43.56
    >>> test_fused_declarations[pure_cython.long, pure_cython.double](5, 6.6)
    long
    double
    25 43.56
    """
    cdef cython.integral squared_int = i * i
    cdef cython.floating squared_float = f * f

    assert cython.typeof(squared_int) == cython.typeof(i)
    assert cython.typeof(squared_float) == cython.typeof(f)

    print(cython.typeof(squared_int))
    print(cython.typeof(squared_float))
    print('%d %.2f' % (squared_int, squared_float))

def test_sizeof_fused_type(fused_type1 b):
    """
    >>> test_sizeof_fused_type[pure_cython.double](11.1)
    """
    t = sizeof(b), sizeof(fused_type1), sizeof(double)
    assert t[0] == t[1] == t[2], t

def get_array(itemsize, format):
    result = array((10,), itemsize, format)
    result[5] = 5.0
    result[6] = 6.0
    return result

def get_intc_array():
    result = array((10,), sizeof(int), 'i')
    result[5] = 5
    result[6] = 6
    return result

def test_fused_memslice_dtype(cython.floating[:] array):
    """
    Note: the np.ndarray dtype test is in numpy_test

    >>> import cython
    >>> sorted(test_fused_memslice_dtype.__signatures__)
    ['double', 'float']

    >>> test_fused_memslice_dtype[cython.double](get_array(8, 'd'))
    double[:] double[:] 5.0 6.0
    >>> test_fused_memslice_dtype[cython.float](get_array(4, 'f'))
    float[:] float[:] 5.0 6.0

    # None should evaluate to *something* (currently the first
    # in the list, but this shouldn't be a hard requirement)
    >>> test_fused_memslice_dtype(None)
    float[:]
    >>> test_fused_memslice_dtype[cython.double](None)
    double[:]
    """
    if array is None:
        print(cython.typeof(array))
        return
    cdef cython.floating[:] otherarray = array[0:100:1]
    print(cython.typeof(array), cython.typeof(otherarray),
          array[5], otherarray[6])
    cdef cython.floating value;
    cdef cython.floating[:] test_cast = &value

def test_fused_memslice_dtype_repeated(cython.floating[:] array1, cython.floating[:] array2):
    """
    Note: the np.ndarray dtype test is in numpy_test

    >>> sorted(test_fused_memslice_dtype_repeated.__signatures__)
    ['double', 'float']

    >>> test_fused_memslice_dtype_repeated(get_array(8, 'd'), get_array(8, 'd'))
    double[:] double[:]
    >>> test_fused_memslice_dtype_repeated(get_array(4, 'f'), get_array(4, 'f'))
    float[:] float[:]
    >>> test_fused_memslice_dtype_repeated(get_array(8, 'd'), get_array(4, 'f'))
    Traceback (most recent call last):
    ValueError: Buffer dtype mismatch, expected 'double' but got 'float'
    """
    print(cython.typeof(array1), cython.typeof(array2))

def test_fused_memslice_dtype_repeated_2(cython.floating[:] array1, cython.floating[:] array2,
                                         fused_type3[:] array3):
    """
    Note: the np.ndarray dtype test is in numpy_test

    >>> sorted(test_fused_memslice_dtype_repeated_2.__signatures__)
    ['double|double', 'double|int', 'float|double', 'float|int']

    >>> test_fused_memslice_dtype_repeated_2(get_array(8, 'd'), get_array(8, 'd'), get_array(8, 'd'))
    double[:] double[:] double[:]
    >>> test_fused_memslice_dtype_repeated_2(get_array(8, 'd'), get_array(8, 'd'), get_intc_array())
    double[:] double[:] int[:]
    >>> test_fused_memslice_dtype_repeated_2(get_array(4, 'f'), get_array(4, 'f'), get_intc_array())
    float[:] float[:] int[:]
    """
    print(cython.typeof(array1), cython.typeof(array2), cython.typeof(array3))

def test_fused_const_memslice_dtype_repeated(const cython.floating[:] array1, cython.floating[:] array2):
    """Test fused types memory view with one being const

    >>> sorted(test_fused_const_memslice_dtype_repeated.__signatures__)
    ['double', 'float']

    >>> test_fused_const_memslice_dtype_repeated(get_array(8, 'd'), get_array(8, 'd'))
    const double[:] double[:]
    >>> test_fused_const_memslice_dtype_repeated(get_array(4, 'f'), get_array(4, 'f'))
    const float[:] float[:]
    >>> test_fused_const_memslice_dtype_repeated(get_array(8, 'd'), get_array(4, 'f'))
    Traceback (most recent call last):
    ValueError: Buffer dtype mismatch, expected 'double' but got 'float'
    """
    print(cython.typeof(array1), cython.typeof(array2))

def test_cython_numeric(cython.numeric arg):
    """
    Test to see whether complex numbers have their utility code declared
    properly.

    >>> test_cython_numeric(10.0 + 1j)
    double complex (10+1j)
    """
    print(cython.typeof(arg), arg)


cdef fused int_t:
    int

def test_pylong(int_t i):
    """
    >>> import cython
    >>> try:    long = long # Python 2
    ... except: long = int  # Python 3

    >>> test_pylong[int](int(0))
    int
    >>> test_pylong[cython.int](int(0))
    int
    >>> test_pylong(int(0))
    int

    >>> test_pylong[int](long(0))
    int
    >>> test_pylong[cython.int](long(0))
    int
    >>> test_pylong(long(0))
    int

    >>> test_pylong[cython.long](0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    KeyError: ...
    """
    print(cython.typeof(i))


cdef fused ints_t:
    int
    long

cdef _test_index_fused_args(cython.floating f, ints_t i):
    print(cython.typeof(f), cython.typeof(i))

def test_index_fused_args(cython.floating f, ints_t i):
    """
    >>> import cython
    >>> test_index_fused_args[cython.double, cython.int](2.0, 3)
    double int
    """
    _test_index_fused_args[cython.floating, ints_t](f, i)

cdef _test_index_const_fused_args(const cython.floating f, const ints_t i):
    print((cython.typeof(f), cython.typeof(i)))

def test_index_const_fused_args(const cython.floating f, const ints_t i):
    """Test indexing function implementation with const fused type args

    >>> import cython
    >>> test_index_const_fused_args[cython.double, cython.int](2.0, 3)
    ('const double', 'const int')
    """
    _test_index_const_fused_args[cython.floating, ints_t](f, i)


def test_composite(fused_composite x):
    """
    >>> print(test_composite(b'a').decode('ascii'))
    a
    >>> test_composite(3)
    6
    >>> test_composite(3.0)
    6.0
    """
    if fused_composite is string_t:
        return x
    else:
        return 2 * x


cdef cdef_func_const_fused_arg(const cython.floating val,
                               const fused_type1 * ptr_to_const,
                               const (cython.floating *) const_ptr):
    print((val, cython.typeof(val)))
    print((ptr_to_const[0], cython.typeof(ptr_to_const[0])))
    print((const_ptr[0], cython.typeof(const_ptr[0])))

    ptr_to_const = NULL  # pointer is not const, value is const
    const_ptr[0] = 0.0  # pointer is const, value is not const

def test_cdef_func_with_const_fused_arg():
    """Test cdef function with const fused type argument

    >>> test_cdef_func_with_const_fused_arg()
    (0.0, 'const float')
    (1, 'const int')
    (2.0, 'float')
    """
    cdef float arg0 = 0.0
    cdef int arg1 = 1
    cdef float arg2 = 2.0
    cdef_func_const_fused_arg(arg0, &arg1, &arg2)


cdef in_check_1(just_float x):
    return just_float in floating

cdef in_check_2(just_float x, floating y):
    # the "floating" on the right-hand side of the in statement should not be specialized
    # - the test should still work.
    return just_float in floating

cdef in_check_3(floating x):
    # the floating on the left-hand side of the in statement should be specialized
    # but the one of the right-hand side should not (so that the test can still work).
    return floating in floating

def test_fused_in_check():
    """
    It should be possible to use fused types on in "x in ...fused_type" statements
    even if that type is specialized in the function.

    >>> test_fused_in_check()
    True
    True
    True
    True
    """
    print(in_check_1(1.0))
    print(in_check_2(1.0, 2.0))
    print(in_check_2[float, double](1.0, 2.0))
    print(in_check_3[float](1.0))


### see GH3642 - presence of cdef inside "unrelated" caused a type to be incorrectly inferred
cdef unrelated(cython.floating x):
    cdef cython.floating t = 1
    return t

cdef handle_float(float* x): return 'float'

cdef handle_double(double* x): return 'double'

def convert_to_ptr(cython.floating x):
    """
    >>> convert_to_ptr(1.0)
    'double'
    >>> convert_to_ptr['double'](1.0)
    'double'
    >>> convert_to_ptr['float'](1.0)
    'float'
    """
    if cython.floating is float:
        return handle_float(&x)
    elif cython.floating is double:
        return handle_double(&x)

def constfused_with_typedef(const fused_with_typedef[:] x):
    """
    >>> constfused_with_typedef(get_array(8, 'd'))
    5.0
    >>> constfused_with_typedef(get_intc_array())
    5
    """
    return x[5]

def constfused_typedef_name_clashes(const fused_with_typedef[:] x, fused_misleading_name[:] y):
    """
    This'll deliberately end up with two typedefs that generate the same name in dispatch code
    (and thus one needs to end up numbered to make it work).
    It's mainly a compile test and the runtime part is fairly token.

    >>> constfused_typedef_name_clashes(get_intc_array(), get_array(4, 'f'))
    (5, 5.0)
    """
    return x[5], y[5]

cdef double get_double():
    return 1.0
cdef float get_float():
    return 0.0

cdef call_func_pointer(cython.floating (*f)()):
    return f()

def test_fused_func_pointer():
    """
    >>> test_fused_func_pointer()
    1.0
    0.0
    """
    print(call_func_pointer(get_double))
    print(call_func_pointer(get_float))

cdef double get_double_from_int(int i):
    return i

cdef call_func_pointer_with_1(cython.floating (*f)(cython.integral)):
    return f(1)

def test_fused_func_pointer2():
    """
    >>> test_fused_func_pointer2()
    1.0
    """
    print(call_func_pointer_with_1(get_double_from_int))

cdef call_function_that_calls_fused_pointer(object (*f)(cython.floating (*)(cython.integral))):
    if cython.floating is double and cython.integral is int:
        return 5*f(get_double_from_int)
    else:
        return None  # practically it's hard to make this kind of function useful...

def test_fused_func_pointer_multilevel():
    """
    >>> test_fused_func_pointer_multilevel()
    5.0
    None
    """
    print(call_function_that_calls_fused_pointer(call_func_pointer_with_1[double, int]))
    print(call_function_that_calls_fused_pointer(call_func_pointer_with_1[float, int]))

cdef null_default(cython.floating x, cython.floating *x_minus_1_out=NULL):
    # On C++ a void* can't be assigned to a regular pointer, therefore setting up
    # needs to avoid going through a void* temp
    if x_minus_1_out:
        x_minus_1_out[0] = x-1
    return x

def test_null_default():
    """
    >>> test_null_default()
    2.0 1.0
    2.0
    2.0 1.0
    2.0
    """
    cdef double xd = 2.
    cdef double xd_minus_1
    result = null_default(xd, &xd_minus_1)
    print(result, xd_minus_1)
    result = null_default(xd)
    print(result)

    cdef float xf = 2.
    cdef float xf_minus_1
    result = null_default(xf, &xf_minus_1)
    print(result, xf_minus_1)
    result = null_default(xf)
    print(result)


cdef cython.numeric fused_numeric_default(int a = 1, cython.numeric x = 0):
    return x + a

def test_fused_numeric_default(int a, x):
    """
    >>> test_fused_numeric_default(1, 0)
    [1, 1.0, (1+0j)]

    >>> test_fused_numeric_default(1, 2)
    [3, 3.0, (3+0j)]

    >>> test_fused_numeric_default(2, 0)
    [2, 2.0, (2+0j)]

    >>> test_fused_numeric_default(2, 1)
    [3, 3.0, (3+0j)]
    """
    result = []

    if a == 1 and x == 0:
        result.append(fused_numeric_default[int]())
    elif x == 0:
        result.append(fused_numeric_default[int](a))
    elif a == 1:
        result.append(fused_numeric_default[int](1, x))
    else:
        result.append(fused_numeric_default[int](a, x))

    if a == 1 and x == 0:
        result.append(fused_numeric_default[float]())
    elif x == 0:
        result.append(fused_numeric_default[float](a))
    elif a == 1:
        result.append(fused_numeric_default[float](1, x))
    else:
        result.append(fused_numeric_default[float](a, x))

    if a == 1 and x == 0:
        result.append(fused_numeric_default[cython.doublecomplex]())
    elif x == 0:
        result.append(fused_numeric_default[cython.doublecomplex](a))
    elif a == 1:
        result.append(fused_numeric_default[cython.doublecomplex](1, x))
    else:
        result.append(fused_numeric_default[cython.doublecomplex](a, x))

    return result
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/fused_types_complex.pyx0000644000175100001770000000311700000000000022367 0ustar00runnerdocker00000000000000# mode: run
# ticket: 5644
# cython: language_level=3
# distutils: define_macros=CYTHON_CCOMPLEX=0

cimport cython

# We used to generate invalid C code for the fused default value assignment
# (int -> complex) with CYTHON_CCOMPLEX=0.

cdef cython.numeric fused_numeric_default(int a = 1, cython.numeric x = 0):
    return x + a


def test_fused_numeric_default(int a, x):
    """
    >>> test_fused_numeric_default(1, 0)
    [1, 1.0, (1+0j)]

    >>> test_fused_numeric_default(1, 2)
    [3, 3.0, (3+0j)]

    >>> test_fused_numeric_default(2, 0)
    [2, 2.0, (2+0j)]

    >>> test_fused_numeric_default(2, 1)
    [3, 3.0, (3+0j)]
    """
    result = []

    if a == 1 and x == 0:
        result.append(fused_numeric_default[int]())
    elif x == 0:
        result.append(fused_numeric_default[int](a))
    elif a == 1:
        result.append(fused_numeric_default[int](1, x))
    else:
        result.append(fused_numeric_default[int](a, x))

    if a == 1 and x == 0:
        result.append(fused_numeric_default[float]())
    elif x == 0:
        result.append(fused_numeric_default[float](a))
    elif a == 1:
        result.append(fused_numeric_default[float](1, x))
    else:
        result.append(fused_numeric_default[float](a, x))

    if a == 1 and x == 0:
        result.append(fused_numeric_default[cython.doublecomplex]())
    elif x == 0:
        result.append(fused_numeric_default[cython.doublecomplex](a))
    elif a == 1:
        result.append(fused_numeric_default[cython.doublecomplex](1, x))
    else:
        result.append(fused_numeric_default[cython.doublecomplex](a, x))

    return result
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/future_division.pyx0000644000175100001770000001065500000000000021531 0ustar00runnerdocker00000000000000from __future__ import division

cimport cython


def bigints(values):
    for x in values:
        print(repr(x).rstrip('L'))


def doit(x,y):
    """
    >>> doit(1,2)
    (0.5, 0)
    >>> doit(4,3)
    (1.3333333333333333, 1)
    >>> doit(4,3.0)
    (1.3333333333333333, 1.0)
    >>> doit(4,2)
    (2.0, 2)
    """
    return x/y, x//y

def doit_inplace(x,y):
    """
    >>> doit_inplace(1,2)
    0.5
    """
    x /= y
    return x

def doit_inplace_floor(x,y):
    """
    >>> doit_inplace_floor(1,2)
    0
    """
    x //= y
    return x

def constants():
    """
    >>> constants()
    (0.5, 0, 2.5, 2.0, 2.5, 2)
    """
    return 1/2, 1//2, 5/2.0, 5//2.0, 5/2, 5//2


def py_mix(a):
    """
    >>> py_mix(1)
    (0.5, 0, 0.5, 0.0, 0.5, 0)
    >>> py_mix(1.0)
    (0.5, 0.0, 0.5, 0.0, 0.5, 0.0)
    >>> 2**53 / 2.0
    4503599627370496.0
    >>> bigints(py_mix(2**53))
    4503599627370496.0
    4503599627370496
    4503599627370496.0
    4503599627370496.0
    4503599627370496.0
    4503599627370496
    >>> bigints(py_mix(2**53 + 1))
    4503599627370496.0
    4503599627370496
    4503599627370496.0
    4503599627370496.0
    4503599627370496.0
    4503599627370496
    >>> py_mix(2**53 + 1.0)
    (4503599627370496.0, 4503599627370496.0, 4503599627370496.0, 4503599627370496.0, 4503599627370496.0, 4503599627370496.0)
    """
    return a/2, a//2, a/2.0, a//2.0, a/2, a//2


def py_mix_by_neg1(a):
    """
    >>> py_mix_by_neg1(0)
    (-0.0, 0, -0.0, -0.0, -0.0, 0)
    >>> py_mix_by_neg1(-1)
    (1.0, 1, 1.0, 1.0, 1.0, 1)
    >>> py_mix_by_neg1(int(2**31-1))
    (-2147483647.0, -2147483647, -2147483647.0, -2147483647.0, -2147483647.0, -2147483647)
    >>> bigints(py_mix_by_neg1(int(-2**31-1)))
    2147483649.0
    2147483649
    2147483649.0
    2147483649.0
    2147483649.0
    2147483649
    >>> results = py_mix_by_neg1(int(2**63-1))
    >>> results[0] == results[2] == results[3] == results[4] == float(2**63-1) / -1.0 or results
    True
    >>> results[1] == results[5] == (2**63-1) // -1 or results
    True
    >>> results = py_mix_by_neg1(int(-2**63-1))
    >>> results[0] == results[2] == results[3] == results[4] == float(-2**63-1) / -1.0 or results
    True
    >>> results[1] == results[5] == (-2**63-1) // -1 or results
    True
    """
    return a/-1, a//-1, a/-1.0, a//-1.0, a/-1, a//-1


def py_mix_rev(a):
    """
    >>> py_mix_rev(4)
    (0.25, 0, 1.25, 1.0, 1.25, 1)
    >>> py_mix_rev(4.0)
    (0.25, 0.0, 1.25, 1.0, 1.25, 1.0)
    """
    return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a

def int_mix(int a):
    """
    >>> int_mix(1)
    (0.5, 0, 0.5, 0.0, 0.5, 0)
    """
    return a/2, a//2, a/2.0, a//2.0, a/2, a//2

def int_mix_rev(int a):
    """
    >>> int_mix_rev(4)
    (0.25, 0, 1.25, 1.0, 1.25, 1)
    """
    return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a

def float_mix(float a):
    """
    >>> float_mix(1.0)
    (0.5, 0.0, 0.5, 0.0, 0.5, 0.0)
    """
    return a/2, a//2, a/2.0, a//2.0, a/2, a//2

def float_mix_rev(float a):
    """
    >>> float_mix_rev(4.0)
    (0.25, 0.0, 1.25, 1.0, 1.25, 1.0)
    """
    return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a


def infer_division_type():
    """
    >>> v = infer_division_type()
    double
    >>> v
    8333333.25
    """
    v = (10000**2 - 1) / 12
    print(cython.typeof(v))
    return v

def int_int(int a, int b):
    """
    >>> int_int(1, 2)
    (0.5, 2.0)
    """
    return a/b, b/a


def div_by_0(a):
    """
    >>> div_by_0(0)
    'OK'
    >>> div_by_0(0.0)
    'OK'
    """
    try:
        1/a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 1"
    try:
        1//a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 2"
    try:
        5.0/a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 3"
    try:
        5.0//a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 4"
    try:
        5/a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 5"
    try:
        5//a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 6"
    try:
        (2**15)/a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 7"
    try:
        (2**15)//a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 8"
    try:
        (2**30)/a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 9"
    try:
        (2**30)//a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 10"
    return 'OK'
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/future_unicode_literals.pyx0000644000175100001770000000117500000000000023227 0ustar00runnerdocker00000000000000from __future__ import unicode_literals

import sys
if sys.version_info[0] >= 3:
    __doc__ = u"""
    >>> u == 'test'
    True
    >>> isinstance(u, str)
    True
    >>> isinstance(b, bytes)
    True
    >>> raw ==  'abc\\\\xf8\\\\t\\u00f8\\U000000f8'  # unescaped by Python (required by doctest)
    True
"""
else:
    __doc__ = u"""
    >>> u == u'test'
    True
    >>> isinstance(u, unicode)
    True
    >>> isinstance(b, str)
    True
    >>> raw == u'abc\\\\xf8\\\\t\\u00f8\\U000000f8'  # unescaped by Python (required by doctest)
    True
"""

u = "test"

cdef char* s = "bytes test"
b = s

raw = r'abc\xf8\t\u00f8\U000000f8'
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/generator_expressions.pyx0000644000175100001770000000252200000000000022735 0ustar00runnerdocker00000000000000# mode: run
# tag: generators, lambda

def genexpr():
    """
    >>> genexpr()
    [0, 2, 4, 6, 8]
    """
    x = 'abc'
    result = list( x*2 for x in range(5) )
    assert x == 'abc' # don't leak
    return result

def genexpr_if():
    """
    >>> genexpr_if()
    [0, 4, 8]
    """
    x = 'abc'
    result = list( x*2 for x in range(5) if x % 2 == 0 )
    assert x == 'abc' # don't leak
    return result

def genexpr_if_false():
    """
    >>> genexpr_if_false()
    []
    """
    x = 'abc'
    result = list( x*2 for x in range(5) if False )
    assert x == 'abc' # don't leak
    return result

def genexpr_with_lambda():
    """
    >>> genexpr_with_lambda()
    [0, 4, 8]
    """
    x = 'abc'
    result = list( x*2 for x in range(5) if (lambda x:x % 2)(x) == 0 )
    assert x == 'abc' # don't leak
    return result

def genexpr_of_lambdas(int N):
    """
    >>> [ (f(), g()) for f,g in genexpr_of_lambdas(5) ]
    [(0, 0), (1, 2), (2, 4), (3, 6), (4, 8)]
    """
    return ( ((lambda : x), (lambda : x*2)) for x in range(N) )


def genexpr_with_bool_binop(values):
    """
    >>> values = [(1, 2, 3), (None, 4, None), (5, None, 6)]
    >>> genexpr_with_bool_binop(values)
    [(1, 2, 3), ('X', 4, 'X'), (5, 'X', 6)]
    """
    # copied from CPython's test_itertools.py
    return [tuple((e is None and 'X' or e) for e in t) for t in values]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/generator_expressions_and_locals.pyx0000644000175100001770000000035200000000000025113 0ustar00runnerdocker00000000000000# mode: run
# tag: genexpr, locals
# ticket: t715

def genexpr_not_in_locals():
    """
    >>> genexpr_not_in_locals()
    {'t': (0, 1, 4, 9, 16, 25, 36, 49, 64, 81)}
    """
    t = tuple(x*x for x in range(10))
    return locals()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/generator_expressions_in_class.py0000644000175100001770000000104700000000000024421 0ustar00runnerdocker00000000000000# mode: run
# tag: generators


class TestClass(object):
    """
    >>> TestClass.x
    [1, 2, 3]
    >>> list(TestClass.gen)
    []
    >>> TestClass.gen_result
    [2, 4, 6]
    >>> TestClass.test
    True
    >>> list(TestClass.gen3)
    [2, 4, 6, 8, 10, 12]
    """

    x = [1, 2, 3]

    gen = (i * 2 for i in x)

    test = all(i * 2 for i in x)

    gen_result = list(gen)

    nested_list = [[1, 2, 3], [4, 5, 6]]

    #gen2 = (i * 2 for i in x for x in nested_list)  # move to error test

    gen3 = (i * 2 for x in nested_list for i in x)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/generator_expressions_nested.pyx0000644000175100001770000000314200000000000024276 0ustar00runnerdocker00000000000000# mode: run
# tag: genexpr
# cython: language_level=3

"""
Adapted from CPython's test_grammar.py
"""

def genexpr_simple():
    """
    >>> sum([ x**2 for x in range(10) ])
    285
    >>> sum(genexpr_simple())
    285
    """
    return (x**2 for x in range(10))

def genexpr_conditional():
    """
    >>> sum([ x*x for x in range(10) if x%2 ])
    165
    >>> sum(genexpr_conditional())
    165
    """
    return (x*x for x in range(10) if x%2)

def genexpr_nested2():
    """
    >>> sum([x for x in range(10)])
    45
    >>> sum(genexpr_nested2())
    45
    """
    return (x for x in (y for y in range(10)))

def genexpr_nested3():
    """
    >>> sum([x for x in range(10)])
    45
    >>> sum(genexpr_nested3())
    45
    """
    return (x for x in (y for y in (z for z in range(10))))

def genexpr_nested_listcomp():
    """
    >>> sum([x for x in range(10)])
    45
    >>> sum(genexpr_nested_listcomp())
    45
    """
    return (x for x in [y for y in (z for z in range(10))])

def genexpr_nested_conditional():
    """
    >>> sum([ x for x in [y for y in [z for z in range(10) if True]] if True ])
    45
    >>> sum(genexpr_nested_conditional())
    45
    """
    return (x for x in (y for y in (z for z in range(10) if True)) if True)

def genexpr_nested2_conditional_empty():
    """
    >>> sum(genexpr_nested2_conditional_empty())
    0
    """
    return (y for y in (z for z in range(10) if True) if False)

def genexpr_nested3_conditional_empty():
    """
    >>> sum(genexpr_nested3_conditional_empty())
    0
    """
    return (x for x in (y for y in (z for z in range(10) if True) if False) if True)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/generator_frame_cycle.py0000644000175100001770000000246000000000000022435 0ustar00runnerdocker00000000000000# mode: run
# tag: generator

import cython
import sys


def test_generator_frame_cycle():
    """
    >>> test_generator_frame_cycle()
    ("I'm done",)
    """
    testit = []
    def whoo():
        try:
            yield
        except:
            yield
        finally:
            testit.append("I'm done")
    g = whoo()
    next(g)

    # Frame object cycle
    eval('g.throw(ValueError)', {'g': g})
    del g

    return tuple(testit)


def test_generator_frame_cycle_with_outer_exc():
    """
    >>> test_generator_frame_cycle_with_outer_exc()
    ("I'm done",)
    """
    testit = []
    def whoo():
        try:
            yield
        except:
            yield
        finally:
            testit.append("I'm done")
    g = whoo()
    next(g)

    try:
        raise ValueError()
    except ValueError as exc:
        assert sys.exc_info()[1] is exc, sys.exc_info()
        # Frame object cycle
        eval('g.throw(ValueError)', {'g': g})
        # CPython 3.3 handles this incorrectly itself :)
        if cython.compiled or sys.version_info[:2] not in [(3, 2), (3, 3)]:
            assert sys.exc_info()[1] is exc, sys.exc_info()
        del g
        if cython.compiled or sys.version_info[:2] not in [(3, 2), (3, 3)]:
            assert sys.exc_info()[1] is exc, sys.exc_info()

    return tuple(testit)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/generator_type_inference.pyx0000644000175100001770000000174600000000000023361 0ustar00runnerdocker00000000000000# mode: run
# tag: typeinference, generators

cimport cython

def test_type_inference():
    """
    >>> list(test_type_inference())
    [(2.0, 'double'), (2.0, 'double'), (2.0, 'double')]
    """
    x = 1.0
    for i in range(3):
        yield x * 2.0, cython.typeof(x)

def test_unicode_loop():
    """
    >>> chars = list(test_unicode_loop())
    1 Py_UCS4
    2 Py_UCS4
    2 Py_UCS4
    2 Py_UCS4
    2 Py_UCS4
    >>> len(chars)
    4
    >>> ''.join(chars) == 'abcd'
    True
    """
    ustr = u'abcd'
    print 1, cython.typeof(ustr[0])
    for c in ustr:
        print 2, cython.typeof(c)
        yield c

def test_with_nonlocal():
    """
    >>> chars = list(test_with_nonlocal())
    1 Py_UCS4
    2 Py_UCS4
    2 Py_UCS4
    >>> len(chars)
    2
    >>> ''.join(chars) == 'ab'
    True
    """
    ustr = u'ab'
    print 1, cython.typeof(ustr[0])
    def gen():
        nonlocal ustr
        for c in ustr:
            print 2, cython.typeof(c)
            yield c
    return gen()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/generators.pyx0000644000175100001770000002613400000000000020463 0ustar00runnerdocker00000000000000# mode: run
# tag: generators, gh3265

try:
    import backports_abc
except ImportError: pass
else: backports_abc.patch()

try:
    from collections.abc import Generator
except ImportError:
    try:
        from collections import Generator
    except ImportError:
        Generator = object  # easy win


def very_simple():
    """
    >>> x = very_simple()
    >>> next(x)
    1
    >>> next(x)
    Traceback (most recent call last):
    StopIteration
    >>> next(x)
    Traceback (most recent call last):
    StopIteration

    >>> x = very_simple()
    >>> x.send(1)
    Traceback (most recent call last):
    TypeError: can't send non-None value to a just-started generator
    """
    yield 1


def attributes():
    """
    >>> x = attributes()
    >>> x.__name__
    'attributes'
    >>> x.__qualname__
    'attributes'
    >>> x.gi_running  # before next()
    False
    >>> inner = next(x)
    >>> x.gi_running  # after next()
    False
    >>> next(x)
    Traceback (most recent call last):
    StopIteration
    >>> x.gi_running  # after termination
    False

    >>> y = inner()
    >>> y.__name__
    ''
    >>> y.__qualname__
    'attributes..inner..'

    >>> y.__name__ = 123
    Traceback (most recent call last):
    TypeError: __name__ must be set to a string object
    >>> y.__name__
    ''
    >>> y.__qualname__ = None
    Traceback (most recent call last):
    TypeError: __qualname__ must be set to a string object
    >>> y.__qualname__
    'attributes..inner..'

    >>> y.__name__ = 'abc'
    >>> y.__name__
    'abc'
    >>> y.__name__ = None
    Traceback (most recent call last):
    TypeError: __name__ must be set to a string object
    >>> y.__name__
    'abc'
    >>> y.__qualname__ = 'huhu'
    >>> y.__qualname__
    'huhu'
    >>> y.__qualname__ = 123
    Traceback (most recent call last):
    TypeError: __qualname__ must be set to a string object
    >>> y.__qualname__
    'huhu'
    """
    def inner():
        return (lambda : (yield 1))
    yield inner()


def simple():
    """
    >>> x = simple()
    >>> list(x)
    [1, 2, 3]
    """
    yield 1
    yield 2
    yield 3

def simple_seq(seq):
    """
    >>> x = simple_seq("abc")
    >>> list(x)
    ['a', 'b', 'c']
    """
    for i in seq:
        yield i

def simple_send():
    """
    >>> x = simple_send()
    >>> next(x)
    >>> x.send(1)
    1
    >>> x.send(2)
    2
    >>> x.send(3)
    3
    """
    i = None
    while True:
        i = yield i

def raising():
    """
    >>> x = raising()
    >>> next(x)
    Traceback (most recent call last):
    KeyError: 'foo'
    >>> next(x)
    Traceback (most recent call last):
    StopIteration
    """
    yield {}['foo']

def with_outer(*args):
    """
    >>> x = with_outer(1, 2, 3)
    >>> list(x())
    [1, 2, 3]
    """
    def generator():
        for i in args:
            yield i
    return generator

def with_outer_raising(*args):
    """
    >>> x = with_outer_raising(1, 2, 3)
    >>> list(x())
    [1, 2, 3]
    """
    def generator():
        for i in args:
            yield i
        raise StopIteration
    return generator

def test_close():
    """
    >>> x = test_close()
    >>> x.close()
    >>> x = test_close()
    >>> next(x)
    >>> x.close()
    >>> next(x)
    Traceback (most recent call last):
    StopIteration
    """
    while True:
        yield

def test_ignore_close():
    """
    >>> x = test_ignore_close()
    >>> x.close()
    >>> x = test_ignore_close()
    >>> next(x)
    >>> x.close()
    Traceback (most recent call last):
    RuntimeError: generator ignored GeneratorExit
    """
    try:
        yield
    except GeneratorExit:
        yield

def check_throw():
    """
    >>> x = check_throw()
    >>> x.throw(ValueError)
    Traceback (most recent call last):
    ValueError
    >>> next(x)
    Traceback (most recent call last):
    StopIteration
    >>> x = check_throw()
    >>> next(x)
    >>> x.throw(ValueError)
    >>> next(x)
    >>> x.throw(IndexError, "oops")
    Traceback (most recent call last):
    IndexError: oops
    >>> next(x)
    Traceback (most recent call last):
    StopIteration
    """
    while True:
        try:
            yield
        except ValueError:
            pass

def test_first_assignment():
    """
    >>> gen = test_first_assignment()
    >>> next(gen)
    5
    >>> next(gen)
    10
    >>> next(gen)
    (5, 10)
    """
    cdef x = 5 # first
    yield x
    cdef y = 10 # first
    yield y
    yield (x,y)

def test_swap_assignment():
    """
    >>> gen = test_swap_assignment()
    >>> next(gen)
    (5, 10)
    >>> next(gen)
    (10, 5)
    """
    x,y = 5,10
    yield (x,y)
    x,y = y,x   # no ref-counting here
    yield (x,y)


class Foo(object):
    """
    >>> obj = Foo()
    >>> list(obj.simple(1, 2, 3))
    [1, 2, 3]
    """
    def simple(self, *args):
        for i in args:
            yield i

def generator_nonlocal():
    """
    >>> g = generator_nonlocal()
    >>> list(g(5))
    [2, 3, 4, 5, 6]
    """
    def f(x):
        def g(y):
            nonlocal x
            for i in range(y):
                x += 1
                yield x
        return g
    return f(1)

def test_nested(a, b, c):
    """
    >>> obj = test_nested(1, 2, 3)
    >>> [i() for i in obj]
    [1, 2, 3, 4]
    """
    def one():
        return a
    def two():
        return b
    def three():
        return c
    def new_closure(a, b):
        def sum():
            return a + b
        return sum
    yield one
    yield two
    yield three
    yield new_closure(a, c)


def tolist(func):
    def wrapper(*args, **kwargs):
        return list(func(*args, **kwargs))
    return wrapper

@tolist
def test_decorated(*args):
    """
    >>> test_decorated(1, 2, 3)
    [1, 2, 3]
    """
    for i in args:
        yield i


def test_return(a):
    """
    >>> d = dict()
    >>> obj = test_return(d)
    >>> next(obj)
    1
    >>> next(obj)
    Traceback (most recent call last):
    StopIteration
    >>> d['i_was_here']
    True
    """
    yield 1
    a['i_was_here'] = True
    return


def test_return_in_finally(a):
    """
    >>> d = dict()
    >>> obj = test_return_in_finally(d)
    >>> next(obj)
    1
    >>> next(obj)
    Traceback (most recent call last):
    StopIteration
    >>> d['i_was_here']
    True

    >>> d = dict()
    >>> obj = test_return_in_finally(d)
    >>> next(obj)
    1
    >>> obj.send(2)
    Traceback (most recent call last):
    StopIteration
    >>> d['i_was_here']
    True

    >>> obj = test_return_in_finally(None)
    >>> next(obj)
    1
    >>> next(obj)
    Traceback (most recent call last):
    StopIteration

    >>> obj = test_return_in_finally(None)
    >>> next(obj)
    1
    >>> obj.send(2)
    Traceback (most recent call last):
    StopIteration
    """
    yield 1
    try:
        a['i_was_here'] = True
    finally:
        return


def test_return_none_in_finally(a):
    """
    >>> d = dict()
    >>> obj = test_return_none_in_finally(d)
    >>> next(obj)
    1
    >>> next(obj)
    Traceback (most recent call last):
    StopIteration
    >>> d['i_was_here']
    True

    >>> obj = test_return_none_in_finally(None)
    >>> next(obj)
    1
    >>> next(obj)
    Traceback (most recent call last):
    StopIteration
    """
    yield 1
    try:
        a['i_was_here'] = True
    finally:
        return None


def test_copied_yield(foo):
    """
    >>> class Manager(object):
    ...    def __enter__(self):
    ...        return self
    ...    def __exit__(self, type, value, tb):
    ...        pass
    >>> list(test_copied_yield(Manager()))
    [1]
    """
    with foo:
        yield 1

def test_nested_yield():
    """
    >>> obj = test_nested_yield()
    >>> next(obj)
    1
    >>> obj.send(2)
    2
    >>> obj.send(3)
    3
    >>> obj.send(4)
    Traceback (most recent call last):
    StopIteration
    """
    yield (yield (yield 1))

def test_inside_lambda():
    """
    >>> obj = test_inside_lambda()()
    >>> next(obj)
    1
    >>> next(obj)
    2
    >>> next(obj)
    Traceback (most recent call last):
    StopIteration
    """
    return lambda:((yield 1), (yield 2))

def test_nested_gen(int n):
    """
    >>> [list(a) for a in test_nested_gen(5)]
    [[], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3]]
    """
    for a in range(n):
        yield (b for b in range(a))

def test_lambda(n):
    """
    >>> [i() for i in test_lambda(3)]
    [0, 1, 2]
    """
    for i in range(n):
        yield lambda : i


def test_with_gil_section():
    """
    >>> list(test_with_gil_section())
    [0, 1, 2]
    """
    cdef int i
    with nogil:
        for i in range(3):
            with gil:
                yield i


def test_double_with_gil_section():
    """
    >>> list(test_double_with_gil_section())
    [0, 1, 2, 3]
    """
    cdef int i,j
    with nogil:
        for i in range(2):
            with gil:
                with nogil:
                    for j in range(2):
                        with gil:
                            yield i*2+j
                with nogil:
                    pass
            with gil:
                pass


def test_generator_abc():
    """
    >>> isinstance(test_generator_abc(), Generator)
    True

    >>> try:
    ...     from collections.abc import Generator
    ... except ImportError:
    ...     try:
    ...         from collections import Generator
    ...     except ImportError:
    ...         Generator = object  # easy win

    >>> isinstance(test_generator_abc(), Generator)
    True
    >>> isinstance((lambda:(yield))(), Generator)
    True
    """
    yield 1


def test_generator_frame(a=1):
    """
    >>> gen = test_generator_frame()
    >>> import types
    >>> isinstance(gen.gi_frame, types.FrameType) or gen.gi_frame
    True
    >>> gen.gi_frame is gen.gi_frame  # assert that it's cached
    True
    >>> gen.gi_frame.f_code is not None
    True
    >>> code_obj = gen.gi_frame.f_code
    >>> code_obj.co_argcount
    1
    >>> code_obj.co_varnames
    ('a', 'b')
    """
    b = a + 1
    yield b


# GH Issue 3265 - **kwds could cause a crash in some cases due to not
# handling NULL pointers (in testing it shows as a REFNANNY error).
# This was on creation of the generator and
# doesn't really require it to be iterated through:

def some_function():
    return 0


def test_generator_kwds1(**kwargs):
    """
    >>> for a in test_generator_kwds1():
    ...     print(a)
    0
    """
    yield some_function(**kwargs)


def test_generator_kwds2(**kwargs):
    """
    >>> for a in test_generator_kwds2():
    ...     print(a)
    0
    """
    yield 0


def test_generator_kwds3(**kwargs):
    """
    This didn't actually crash before but is still worth a try
    >>> len(list(test_generator_kwds3()))
    0
    >>> for a in test_generator_kwds3(a=1):
    ...    print(a)
    a
    """
    yield from kwargs.keys()


def test_generator_frame(a=1):
    """
    >>> gen = test_generator_frame()
    >>> import types
    >>> isinstance(gen.gi_frame, types.FrameType) or gen.gi_frame
    True
    >>> gen.gi_frame is gen.gi_frame  # assert that it's cached
    True
    >>> gen.gi_frame.f_code is not None
    True
    >>> code_obj = gen.gi_frame.f_code
    >>> code_obj.co_argcount
    1
    >>> code_obj.co_varnames
    ('a', 'b')
    """
    b = a + 1
    yield b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/generators_GH1731.pyx0000644000175100001770000000272000000000000021350 0ustar00runnerdocker00000000000000# mode: run
# ticket: 1731


def cygen():
    yield 1


def test_from_cython(g):
    """
    >>> def pygen(): yield 1
    >>> test_from_cython(pygen)
    Traceback (most recent call last):
    ZeroDivisionError: integer division or modulo by zero

    >>> test_from_cython(cygen)
    Traceback (most recent call last):
    ZeroDivisionError: integer division or modulo by zero
    """
    try:
        1 / 0
    except:
        for _ in g():
            pass
        raise


def test_from_python():
    """
    >>> def test(g):
    ...     try:
    ...         1 / 0
    ...     except:
    ...         for _ in g():
    ...             pass
    ...         raise

    >>> def pygen():
    ...     yield 1
    >>> test(pygen)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: ...division ...by zero

    >>> test(cygen)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: ...division ...by zero
    """


def test_from_console():
    """
    >>> def pygen(): yield 1
    >>> try:  # doctest: +ELLIPSIS
    ...     1 / 0
    ... except:
    ...     for _ in pygen():
    ...         pass
    ...     raise
    Traceback (most recent call last):
    ZeroDivisionError: ...division ...by zero

    >>> try:  # doctest: +ELLIPSIS
    ...     1 / 0
    ... except:
    ...     for _ in cygen():
    ...         pass
    ...     raise
    Traceback (most recent call last):
    ZeroDivisionError: ...division ...by zero
    """
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/generators_in_refcycles.pyx0000644000175100001770000000134200000000000023202 0ustar00runnerdocker00000000000000
import sys
def _next(it):
    if sys.version_info[0] >= 3:
        return next(it)
    else:
        return it.next()

def test_reference_cycle_cleanup():
    """
    >>> import gc
    >>> delegator, gen, deleted = test_reference_cycle_cleanup()

    >>> _next(delegator(gen()))
    123
    >>> _ = gc.collect(); print(sorted(deleted))
    ['bar', 'foo']
    """
    deleted = []
    class Destructed(object):
        def __init__(self, name):
            self.name = name

        def __del__(self):
            deleted.append(self.name)

    def delegator(c):
        d = Destructed('foo')
        yield from c

    def gen():
        d = Destructed('bar')
        while True:
            yield 123

    return delegator, gen, deleted
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/generators_pep479.pyx0000644000175100001770000000601700000000000021571 0ustar00runnerdocker00000000000000# mode: run
# tag: generators, pep479

from __future__ import generator_stop

import sys
if sys.version_info[0] >= 3:
    # additionally test exception chaining
    __doc__ = u"""
>>> g = test_raise_StopIteration_value()
>>> next(g)
1
>>> try: next(g)
... except RuntimeError as exc:
...     print(type(exc.__context__) is StopIteration or type(exc.__context__), exc.__context__)
... else:
...     print("NOT RAISED!")
True huhu
"""


def test_raise_StopIteration():
    """
    >>> g = test_raise_StopIteration()
    >>> next(g)
    1
    >>> next(g)
    Traceback (most recent call last):
    RuntimeError: generator raised StopIteration
    """
    yield 1
    raise StopIteration


def test_raise_StopIteration_value():
    """
    >>> g = test_raise_StopIteration_value()
    >>> next(g)
    1
    >>> next(g)
    Traceback (most recent call last):
    RuntimeError: generator raised StopIteration
    """
    yield 1
    raise StopIteration('huhu')


def test_return():
    """
    >>> g = test_return()
    >>> next(g)
    1
    >>> next(g)
    Traceback (most recent call last):
    StopIteration
    """
    yield 1
    return


def test_return_value():
    """
    >>> g = test_return_value()
    >>> next(g)
    1
    >>> next(g)
    Traceback (most recent call last):
    StopIteration: 2
    """
    yield 1
    return 2


def test_propagate_StopIteration(it):
    """
    >>> results = []
    >>> for x in test_propagate_StopIteration(iter([])):
    ...     results.append(x)
    Traceback (most recent call last):
    RuntimeError: generator raised StopIteration
    >>> results
    []

    >>> for x in test_propagate_StopIteration(iter([1, 2])):
    ...     results.append(x)
    Traceback (most recent call last):
    RuntimeError: generator raised StopIteration
    >>> results
    [1, 2]
    """
    while True:
       yield next(it)


def test_catch_StopIteration(it):
    """
    >>> for x in test_catch_StopIteration(iter([])):
    ...     print(x)

    >>> for x in test_catch_StopIteration(iter([1, 2])):
    ...     print(x)
    1
    2
    """
    try:
        while True:
           yield next(it)
    except StopIteration:
        pass
    else:
        print("NOT RAISED!")


def test_yield_from(it):
    """
    >>> for x in test_yield_from(iter([])):
    ...     print(x)

    >>> for x in test_yield_from(iter([1, 2])):
    ...     print(x)
    1
    2
    """
    yield from it


def test_yield_from_gen():
    """
    >>> for x in test_yield_from_gen():
    ...     print(x)
    1
    RETURN: 2
    """
    x = yield from test_return_value()
    print("RETURN: %s" % x)


def test_genexpr(it):
    """
    >>> list(test_genexpr(iter([])))
    []
    >>> list(test_genexpr(iter([1, 2])))
    [1]

    >>> list(test_genexpr(iter([1])))
    Traceback (most recent call last):
    RuntimeError: generator raised StopIteration

    >>> list(test_genexpr(iter([1, 2, 3])))
    Traceback (most recent call last):
    RuntimeError: generator raised StopIteration

    >>> list(test_genexpr(iter([1, 2])))
    [1]
    """
    return (x for x in it if next(it))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/generators_py.py0000644000175100001770000001751500000000000021006 0ustar00runnerdocker00000000000000# mode: run
# tag: generators

import sys
import cython


def very_simple():
    """
    >>> x = very_simple()
    >>> next(x)
    1
    >>> next(x)
    Traceback (most recent call last):
    StopIteration
    >>> next(x)
    Traceback (most recent call last):
    StopIteration
    >>> x = very_simple()
    >>> x.send(1)
    Traceback (most recent call last):
    TypeError: can't send non-None value to a just-started generator
    """
    yield 1


def simple():
    """
    >>> x = simple()
    >>> list(x)
    [1, 2, 3]
    """
    yield 1
    yield 2
    yield 3

def simple_seq(seq):
    """
    >>> x = simple_seq("abc")
    >>> list(x)
    ['a', 'b', 'c']
    """
    for i in seq:
        yield i

def simple_send():
    """
    >>> x = simple_send()
    >>> next(x)
    >>> x.send(1)
    1
    >>> x.send(2)
    2
    >>> x.send(3)
    3
    """
    i = None
    while True:
        i = yield i

def raising():
    """
    >>> x = raising()
    >>> next(x)
    Traceback (most recent call last):
    KeyError: 'foo'
    >>> next(x)
    Traceback (most recent call last):
    StopIteration
    """
    yield {}['foo']

def with_outer(*args):
    """
    >>> x = with_outer(1, 2, 3)
    >>> list(x())
    [1, 2, 3]
    """
    def generator():
        for i in args:
            yield i
    return generator


def test_close():
    """
    >>> x = test_close()
    >>> x.close()
    >>> x = test_close()
    >>> next(x)
    >>> x.close()
    >>> next(x)
    Traceback (most recent call last):
    StopIteration
    """
    while True:
        yield

def test_ignore_close():
    """
    >>> x = test_ignore_close()
    >>> x.close()
    >>> x = test_ignore_close()
    >>> next(x)
    >>> x.close()
    Traceback (most recent call last):
    RuntimeError: generator ignored GeneratorExit
    """
    try:
        yield
    except GeneratorExit:
        yield

def check_throw():
    """
    >>> x = check_throw()
    >>> x.throw(ValueError)
    Traceback (most recent call last):
    ValueError
    >>> next(x)
    Traceback (most recent call last):
    StopIteration
    >>> x = check_throw()
    >>> next(x)
    >>> x.throw(ValueError)
    >>> next(x)
    >>> x.throw(IndexError, "oops")
    Traceback (most recent call last):
    IndexError: oops
    >>> next(x)
    Traceback (most recent call last):
    StopIteration
    """
    while True:
        try:
            yield
        except ValueError:
            pass


def check_yield_in_except():
    """
    >>> if sys.version_info[0] == 2: sys.exc_clear()
    >>> try:
    ...     raise TypeError("RAISED !")
    ... except TypeError as orig_exc:
    ...     assert isinstance(orig_exc, TypeError), orig_exc
    ...     g = check_yield_in_except()
    ...     print(orig_exc is sys.exc_info()[1] or sys.exc_info())
    ...     next(g)
    ...     print(orig_exc is sys.exc_info()[1] or sys.exc_info())
    ...     next(g)
    ...     print(orig_exc is sys.exc_info()[1] or sys.exc_info())
    True
    True
    True
    >>> next(g)
    Traceback (most recent call last):
    StopIteration
    """
    try:
        yield
        raise ValueError
    except ValueError as exc:
        assert sys.exc_info()[1] is exc, sys.exc_info()
        yield
        if cython.compiled or sys.version_info[0] > 2:
            assert sys.exc_info()[1] is exc, sys.exc_info()


def yield_in_except_throw_exc_type():
    """
    >>> g = yield_in_except_throw_exc_type()
    >>> next(g)
    >>> g.throw(TypeError)
    Traceback (most recent call last):
    TypeError
    >>> next(g)
    Traceback (most recent call last):
    StopIteration
    """
    try:
        raise ValueError
    except ValueError as exc:
        assert sys.exc_info()[1] is exc, sys.exc_info()
        yield
        assert sys.exc_info()[1] is exc, sys.exc_info()


def yield_in_except_throw_instance():
    """
    >>> g = yield_in_except_throw_instance()
    >>> next(g)
    >>> g.throw(TypeError())
    Traceback (most recent call last):
    TypeError
    >>> next(g)
    Traceback (most recent call last):
    StopIteration
    """
    try:
        raise ValueError
    except ValueError as exc:
        assert sys.exc_info()[1] is exc, sys.exc_info()
        yield
        assert sys.exc_info()[1] is exc, sys.exc_info()


def test_swap_assignment():
    """
    >>> gen = test_swap_assignment()
    >>> next(gen)
    (5, 10)
    >>> next(gen)
    (10, 5)
    """
    x,y = 5,10
    yield (x,y)
    x,y = y,x   # no ref-counting here
    yield (x,y)


class Foo(object):
    """
    >>> obj = Foo()
    >>> list(obj.simple(1, 2, 3))
    [1, 2, 3]
    """
    def simple(self, *args):
        for i in args:
            yield i

def test_nested(a, b, c):
    """
    >>> obj = test_nested(1, 2, 3)
    >>> [i() for i in obj]
    [1, 2, 3, 4]
    """
    def one():
        return a
    def two():
        return b
    def three():
        return c
    def new_closure(a, b):
        def sum():
            return a + b
        return sum
    yield one
    yield two
    yield three
    yield new_closure(a, c)


def tolist(func):
    def wrapper(*args, **kwargs):
        return list(func(*args, **kwargs))
    return wrapper

@tolist
def test_decorated(*args):
    """
    >>> test_decorated(1, 2, 3)
    [1, 2, 3]
    """
    for i in args:
        yield i

def test_return(a):
    """
    >>> d = dict()
    >>> obj = test_return(d)
    >>> next(obj)
    1
    >>> next(obj)
    Traceback (most recent call last):
    StopIteration
    >>> d['i_was_here']
    True
    """
    yield 1
    a['i_was_here'] = True
    return

def test_copied_yield(foo):
    """
    >>> class Manager(object):
    ...    def __enter__(self):
    ...        return self
    ...    def __exit__(self, type, value, tb):
    ...        pass
    >>> list(test_copied_yield(Manager()))
    [1]
    """
    with foo:
        yield 1

def test_nested_yield():
    """
    >>> obj = test_nested_yield()
    >>> next(obj)
    1
    >>> obj.send(2)
    2
    >>> obj.send(3)
    3
    >>> obj.send(4)
    Traceback (most recent call last):
    StopIteration
    """
    yield (yield (yield 1))

def test_sum_of_yields(n):
    """
    >>> g = test_sum_of_yields(3)
    >>> next(g)
    (0, 0)
    >>> g.send(1)
    (0, 1)
    >>> g.send(1)
    (1, 2)
    """
    x = 0
    x += yield (0, x)
    x += yield (0, x)
    yield (1, x)

def test_nested_gen(n):
    """
    >>> [list(a) for a in test_nested_gen(5)]
    [[], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3]]
    """
    for a in range(n):
        yield (b for b in range(a))

def test_lambda(n):
    """
    >>> [i() for i in test_lambda(3)]
    [0, 1, 2]
    """
    for i in range(n):
        yield lambda : i

def test_generator_cleanup():
    """
    >>> g = test_generator_cleanup()
    >>> del g
    >>> g = test_generator_cleanup()
    >>> next(g)
    1
    >>> del g
    cleanup
    """
    try:
        yield 1
    finally:
        print('cleanup')

def test_del_in_generator():
    """
    >>> [ s for s in test_del_in_generator() ]
    ['abcabcabc', 'abcabcabc']
    """
    x = len('abc') * 'abc'
    a = x
    yield x
    del x
    yield a
    del a

@cython.test_fail_if_path_exists("//IfStatNode", "//PrintStatNode")
def test_yield_in_const_conditional_false():
    """
    >>> list(test_yield_in_const_conditional_false())
    []
    """
    if False:
        print((yield 1))

@cython.test_fail_if_path_exists("//IfStatNode")
@cython.test_assert_path_exists("//PrintStatNode")
def test_yield_in_const_conditional_true():
    """
    >>> list(test_yield_in_const_conditional_true())
    None
    [1]
    """
    if True:
        print((yield 1))


def test_generator_scope():
    """
    Tests that the function is run at the correct time
    (i.e. when the generator is created, not when it's run)
    >>> list(test_generator_scope())
    inner running
    generator created
    [0, 10]
    """
    def inner(val):
        print("inner running")
        return [0, val]
    gen = (a for a in inner(10))
    print("generator created")
    return gen
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/generators_py35.py0000644000175100001770000000150500000000000021146 0ustar00runnerdocker00000000000000# mode: run
# tag: generators, pure3.5

from __future__ import generator_stop

# "generator_stop" was only added in Py3.5.


def with_outer_raising(*args):
    """
    >>> x = with_outer_raising(1, 2, 3)
    >>> try:
    ...     list(x())
    ... except RuntimeError:
    ...     print("OK!")
    ... else:
    ...     print("NOT RAISED!")
    OK!
    """
    def generator():
        for i in args:
            yield i
        raise StopIteration
    return generator


def anno_gen(x: 'int') -> 'float':
    """
    >>> gen = anno_gen(2)
    >>> next(gen)
    2.0
    >>> ret, arg = sorted(anno_gen.__annotations__.items())
    >>> print(ret[0]); print(str(ret[1]).strip("'"))  # strip makes it pass with/without PEP563
    return
    float
    >>> print(arg[0]); print(str(arg[1]).strip("'"))
    x
    int
    """
    yield float(x)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/genexpr_T491.pyx0000644000175100001770000000145200000000000020477 0ustar00runnerdocker00000000000000# ticket: t491

def test_genexpr():
    """
    >>> gen = test_genexpr()
    >>> list(gen)
    [0, 1, 2, 3, 4]
    """
    return (i for i in range(5))

def test_genexpr_typed():
    """
    >>> gen = test_genexpr_typed()
    >>> list(gen)
    [0, 1, 2, 3, 4]
    """
    cdef int i
    return (i for i in range(5))

def test_genexpr_funccall():
    """
    >>> test_genexpr_funccall()
    [0, 1, 2, 3, 4]
    """
    return list(i for i in range(5))

def test_genexpr_scope():
    """
    >>> test_genexpr_scope()
    ([0, 1, 2, 3, 4], 'abc')
    """
    i = 'abc'
    gen = (i for i in range(5))
    lst = list(gen)
    return lst, i

def test_genexpr_closure():
    """
    >>> gen = test_genexpr_closure()
    >>> list(gen)
    ['a', 'b', 'c']
    """
    abc = 'a' + 'b' + 'c'
    return (c for c in abc)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/genexpr_T715.pyx0000644000175100001770000000045500000000000020500 0ustar00runnerdocker00000000000000# mode: run
# ticket: t715
# tag: genexpr, comprehension

def t715(*items):
    """
    # Blocked by T724
    # >>> [list(i) for i in t715([1, 2, 3], [4, 5, 6])]
    # [[1, 2, 3], [4, 5, 6]]
    >>> [list(i) for i in t715([1, 2, 3])]
    [[1, 2, 3]]
    """
    return [(j for j in i) for i in items]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/genexpr_arg_order.py0000644000175100001770000001031200000000000021605 0ustar00runnerdocker00000000000000# mode: run
# tag: genexpr, py3, py2

from __future__ import print_function

# Tests that function arguments to generator expressions are
# evaluated in the correct order (even after optimization)
# WARNING: there may be an amount of luck in this working correctly (since it
# isn't strictly enforced). Therefore perhaps be prepared to disable these
# tests if they stop working and aren't easily fixed

import cython

@cython.cfunc
@cython.returns(cython.int)
def zero():
    print("In zero")
    return 0

@cython.cfunc
@cython.returns(cython.int)
def five():
    print("In five")
    return 5

@cython.cfunc
@cython.returns(cython.int)
def one():
    print("In one")
    return 1

# FIXME - I don't think this is easy to enforce unfortunately, but it is slightly wrong
#@cython.test_assert_path_exists("//ForFromStatNode")
#def genexp_range_argument_order():
#    """
#    >>> list(genexp_range_argument_order())
#    In zero
#    In five
#    [0, 1, 2, 3, 4]
#    """
#    return (a for a in range(zero(), five()))
#
#@cython.test_assert_path_exists("//ForFromStatNode")
#@cython.test_assert_path_exists(
#    "//InlinedGeneratorExpressionNode",
#    "//ComprehensionAppendNode")
#def list_range_argument_order():
#    """
#    >>> list_range_argument_order()
#    In zero
#    In five
#    [0, 1, 2, 3, 4]
#    """
#    return list(a for a in range(zero(), five()))

@cython.test_assert_path_exists("//ForFromStatNode")
def genexp_array_slice_order():
    """
    >>> list(genexp_array_slice_order())
    In zero
    In five
    [0, 1, 2, 3, 4]
    """
    # TODO ideally find a way to add the evaluation of x to this test too
    x = cython.declare(cython.int[20])
    x = list(range(20))
    return (a for a in x[zero():five()])

@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_assert_path_exists(
    "//InlinedGeneratorExpressionNode",
    "//ComprehensionAppendNode")
def list_array_slice_order():
    """
    >>> list(list_array_slice_order())
    In zero
    In five
    [0, 1, 2, 3, 4]
    """
    # TODO ideally find a way to add the evaluation of x to this test too
    x = cython.declare(cython.int[20])
    x = list(range(20))
    return list(a for a in x[zero():five()])

class IndexableClass:
    def __getitem__(self, idx):
        print("In indexer")
        return [ idx.start, idx.stop, idx.step ]

class NoisyAttributeLookup:
    @property
    def indexer(self):
        print("Getting indexer")
        return IndexableClass()

    @property
    def function(self):
        print("Getting function")
        def func(a, b, c):
            print("In func")
            return [a, b, c]
        return func

def genexp_index_order():
    """
    >>> list(genexp_index_order())
    Getting indexer
    In zero
    In five
    In one
    In indexer
    Made generator expression
    [0, 5, 1]
    """
    obj = NoisyAttributeLookup()
    ret = (a for a in obj.indexer[zero():five():one()])
    print("Made generator expression")
    return ret

@cython.test_assert_path_exists("//InlinedGeneratorExpressionNode")
def list_index_order():
    """
    >>> list_index_order()
    Getting indexer
    In zero
    In five
    In one
    In indexer
    [0, 5, 1]
    """
    obj = NoisyAttributeLookup()
    return list(a for a in obj.indexer[zero():five():one()])


def genexpr_fcall_order():
    """
    >>> list(genexpr_fcall_order())
    Getting function
    In zero
    In five
    In one
    In func
    Made generator expression
    [0, 5, 1]
    """
    obj = NoisyAttributeLookup()
    ret = (a for a in obj.function(zero(), five(), one()))
    print("Made generator expression")
    return ret

@cython.test_assert_path_exists("//InlinedGeneratorExpressionNode")
def list_fcall_order():
    """
    >>> list_fcall_order()
    Getting function
    In zero
    In five
    In one
    In func
    [0, 5, 1]
    """
    obj = NoisyAttributeLookup()
    return list(a for a in obj.function(zero(), five(), one()))

def call1():
    print("In call1")
    return ["a"]
def call2():
    print("In call2")
    return ["b"]

def multiple_genexps_to_call_order():
    """
    >>> multiple_genexps_to_call_order()
    In call1
    In call2
    """
    def takes_two_genexps(a, b):
        pass

    return takes_two_genexps((x for x in call1()), (x for x in call2()))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/genexpr_iterable_lookup_T600.pyx0000644000175100001770000000470100000000000023727 0ustar00runnerdocker00000000000000# mode: run
# ticket: t600
# tag: genexpr
# cython: language_level=3

cimport cython

#@cython.test_assert_path_exists('//ComprehensionNode')
#@cython.test_fail_if_path_exists('//SimpleCallNode')
def list_genexpr_iterable_lookup():
    """
    >>> x = (0,1,2,3,4,5)
    >>> [ x*2 for x in x if x % 2 == 0 ]  # leaks in Py2 but finds the right 'x'
    [0, 4, 8]

    >>> list_genexpr_iterable_lookup()
    [0, 4, 8]
    """
    x = (0,1,2,3,4,5)
    result = list( x*2 for x in x if x % 2 == 0 )
    assert x == (0,1,2,3,4,5)
    return result


#@cython.test_assert_path_exists('//ComprehensionNode')
#@cython.test_fail_if_path_exists('//SingleAssignmentNode//SimpleCallNode')
def genexpr_iterable_in_closure():
    """
    >>> genexpr_iterable_in_closure()
    ['aa', 'cc']
    """
    x = 'abc'
    def f():
        return x
    result = list( x*2 for x in x if x != 'b' )
    assert x == 'abc' # don't leak in Py3 code
    assert f() == 'abc' # don't leak in Py3 code

    # Py2 cleanup (pretty irrelevant to the actual test!)
    import sys
    if sys.version_info[0] == 2:
        result = map(bytes, result)
    return result


def genexpr_over_complex_arg(func, L):
    """
    >>> class wrapper(object):
    ...     value = 5
    >>> genexpr_over_complex_arg(list, wrapper())
    [5]
    """
    return func(d for d in set([type(L).value, L.__class__.value, L.value]))


def listcomp():
    """
    >>> listcomp()
    [0, 1, 5, 8]
    """
    data = [('red', 5), ('blue', 1), ('yellow', 8), ('black', 0)]
    data.sort(key=lambda r: r[1])
    keys = [r[1] for r in data]
    return keys


def genexpr_in_listcomp(L):
    """
    >>> genexpr_in_listcomp( [[1,2,3]]*2 )
    [[1, 2, 3], [1, 2, 3]]
    """
    return list(d for d in [list(d for d in d) for d in L])


@cython.test_assert_path_exists('//ForFromStatNode')
def genexpr_range_in_listcomp(L):
    """
    >>> genexpr_range_in_listcomp( [1,2,3] )
    [[0], [0, 1], [0, 1, 2]]
    """
    cdef int z,d
    return [list(d for d in range(z)) for z in L]


@cython.test_fail_if_path_exists('//ForInStatNode')
def genexpr_in_dictcomp_dictiter():
    """
    >>> sorted(genexpr_in_dictcomp_dictiter())
    [1, 5]
    """
    d = {1:2, 3:4, 5:6}
    return {k:d for k,d in d.iteritems() if d != 4}


def genexpr_over_array_slice():
    """
    >>> list(genexpr_over_array_slice())
    [0.0, 1.0, 2.0, 3.0, 4.0, 5.0]
    """
    cdef double x[10]
    for i in range(10):
        x[i] = i
    cdef int n = 5
    return (n for n in x[:n+1])
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4087222
Cython-3.0.8/tests/run/getattr3call.pyx0000644000175100001770000000175400000000000020704 0ustar00runnerdocker00000000000000
class test(object):
    a = 1
t = test()

def getattr2_literal_unicode(a):
    """
    >>> getattr2_literal_unicode(t)
    1
    >>> getattr2_literal_unicode(object())
    Traceback (most recent call last):
    AttributeError: 'object' object has no attribute 'a'
    """
    return getattr(a, u"a")

def getattr3_literal_unicode(a, b):
    """
    >>> getattr3_literal_unicode(t, 2)
    (1, 2)
    """
    return getattr(a, u"a", b), getattr(a, u"b", b)

def getattr2_simple(a, b):
    """
    >>> getattr2_simple(t, 'a')
    1
    >>> getattr2_simple(t, 'b')
    Traceback (most recent call last):
    AttributeError: 'test' object has no attribute 'b'
    """
    return getattr(a, b)

def getattr3_explicit(a, b, c):
    """
    >>> getattr3_explicit(t, 'a', 2)
    1
    >>> getattr3_explicit(t, 'b', 2)
    2
    """
    return getattr3(a, b, c)

def getattr3_args(a, b, c):
    """
    >>> getattr3_args(t, 'a', 2)
    1
    >>> getattr3_args(t, 'b', 2)
    2
    """
    return getattr(a, b, c)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/gil_in_var_initialization_tests.pyx0000644000175100001770000001154600000000000024755 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp, cpp11

#cython: test_fail_if_c_code_has = __Pyx_RefNannySetupContext\("call_a_method_with_an_error_return"
##cython: test_fail_if_c_code_has = /int __pyx_f_31gil_in_var_initialization_tests_1C_call_a_method_with_an_error_return\(.+{/:/__pyx_vtab/PyGILState_Ensure
#cython: test_fail_if_c_code_has = __Pyx_RefNannySetupContext\("call_me"
##cython: test_fail_if_c_code_has = /void __pyx_f_31gil_in_var_initialization_tests_1D_call_me\(.+{/:/get_left_edge\(/PyGILState_Ensure

# patterns above look for unwanted __Pyx_RefNannySetupContext and PyGILState_Ensure calls within
# the introductory part of the two functions (defined by looking at the function name, looking for
# a { to know we're at the function definition, and looking for a distinctive early line in the
# function.
# The second ones are disabled because they are tripped up by the annotated HTML output, where
# the code is jumbled up so they get caught by some GIL use in some unrelated error handling.

from libcpp cimport bool

# What we're testing in this file is that certain bits of code don't acquire the GIL
# at any point during the function.
#
# To do this we create a C++ thread that runs with the GIL permanently held, and
# which is waiting for a condition variable to be set. We run the relevant Cython
# function and then set the condition variable.
#
# If the Cython function requires the GIL it will be blocked by the C++ thread and
# so be unable to set the condition variable.
#
# This isn't specifically a C++ test, but the C++ standard library concurrency tools
# are a convenient way of getting condition variables and mutexes.

cdef extern from *:
    """
    #include 
    #include 
    #include 
    #include 

    static bool waiting = false;
    static bool triggered = false;
    static std::condition_variable condition_variable;
    static std::mutex mutex;

    void reset_cpp_state() {
        std::unique_lock lock(mutex);
        waiting = false;
        triggered = false;
    }

    bool block_and_wait_for_trigger() {
        std::unique_lock lock(mutex);
        waiting = true;
        triggered = false;
        condition_variable.notify_all();
        // Note - I'm using a 5 second timeout here to avoid the test
        // being "deadlock forever". This could occasionally give false
        // failures if things are running really slowly
        return condition_variable.wait_for(
            lock,
            std::chrono::seconds(5),
            []() {
                return triggered;
            });
    }

    void wait_for_waiting() {
        std::unique_lock lock(mutex);
        condition_variable.wait(
            lock,
            []() {
                return waiting;
            });
    }

    void set_triggered() {
        std::unique_lock lock(mutex);
        triggered = true;
        condition_variable.notify_all();
    }

    using bool_future = std::future;

    std::future run_block_and_wait_with_gil() {
        reset_cpp_state();
        return std::async(std::launch::async,
            [](){
                PyGILState_STATE gstate;
                gstate = PyGILState_Ensure();

                auto result = block_and_wait_for_trigger();

                PyGILState_Release(gstate);

                return result;
            });
    }
    """
    void wait_for_waiting() nogil
    void set_triggered() nogil
    cppclass bool_future:
        bool get() nogil
    bool_future run_block_and_wait_with_gil() nogil

cdef class C:
    cdef int some_c_method(self) except -1 nogil:
        return 0

    cdef int call_a_method_with_an_error_return(self) except -1 nogil:
        return self.some_c_method()

def test_method_with_error_return():
    """
    >>> test_method_with_error_return()
    """
    future = run_block_and_wait_with_gil()
    c = C()
    with nogil:
        wait_for_waiting()  # make sure the C++ thread has started and is holding the GIL
        c.call_a_method_with_an_error_return()
        set_triggered()
    assert future.get()


cdef inline float[:] _get_left_edge(float[::1] arr) nogil:
    return arr[:3]

cdef class D:
    cdef float _a
    def __cinit__(self, float a):
        self._a = a

    cdef void call_me(self, float[::1] my_arr) noexcept nogil:
        cdef Py_ssize_t idx
        cdef float[:] my_arr2 = _get_left_edge(my_arr)
        for idx in range(my_arr2.shape[0]):
            my_arr2[idx] = self._a

def test_method_with_memoryview_handling():
    """
    >>> test_method_with_memoryview_handling()
    """
    cdef float[10] static_arr
    cdef float[::1] view_of_static_arr = static_arr
    future = run_block_and_wait_with_gil()
    d = D(5.)
    with nogil:
        wait_for_waiting()  # make sure the C++ thread has started and is holding the GIL
        d.call_me(view_of_static_arr)
        set_triggered()
    assert future.get()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/hasattr.pyx0000644000175100001770000000157200000000000017757 0ustar00runnerdocker00000000000000# mode: run

class Foo:
    @property
    def foo(self):
        return None
    @property
    def bar(self):
        raise AttributeError
    @property
    def baz(self):
        return int(1)/int(0)


unicode_foo = u"foo"


def wrap_hasattr(obj, name):
    """
    >>> wrap_hasattr(None, "abc")
    False
    >>> wrap_hasattr(list, "append")
    True
    >>> wrap_hasattr(Foo(), "foo")
    True
    >>> wrap_hasattr(Foo(), unicode_foo)
    True
    >>> wrap_hasattr(Foo(), "spam")
    False
    >>> wrap_hasattr(Foo(), "bar")
    False
    >>> Foo().baz   #doctest: +ELLIPSIS
    Traceback (most recent call last):
       ...
    ZeroDivisionError: ...
    >>> wrap_hasattr(Foo(), "baz")
    False
    >>> hasattr(Foo(), None)   #doctest: +ELLIPSIS
    Traceback (most recent call last):
       ...
    TypeError: ...attribute name must be string...
    """
    return hasattr(obj, name)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/hash_T326.pyx0000644000175100001770000000107300000000000017746 0ustar00runnerdocker00000000000000# mode: run
# ticket: t326
# tag: hash


cdef class A:
    """
    >>> hash(A(5))
    5
    >>> hash(A(-1))
    -2
    >>> hash(A(-2))
    -2
    >>> hash(A(100))
    Traceback (most recent call last):
    ...
    TypeError: That's kind of a round number...
    """
    cdef long a
    def __init__(self, a):
        self.a = a
    def __hash__(self):
        if self.a == 100:
            raise TypeError, u"That's kind of a round number..."
        else:
            return self.a


cpdef long __hash__(long x):
    """
    >>> __hash__(-1)
    -1
    """
    return x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/if.pyx0000644000175100001770000000151200000000000016701 0ustar00runnerdocker00000000000000def f(a, b):
    """
    >>> f(0,0)
    0
    >>> f(1,2)
    2
    >>> f(1,-1)
    1
    """
    x = 0
    if a:
        x = 1
    if a+b:
        x = 2
    return x

def g(a, b):
    """
    >>> g(1,2)
    1
    >>> g(0,2)
    2
    >>> g(0,0)
    0
    """
    x = 0
    if a:
        x = 1
    elif b:
        x = 2
    return x

def h(a, b):
    """
    >>> h(1,2)
    1
    >>> h(0,2)
    2
    >>> h(0,0)
    3
    """
    x = 0
    if a:
        x = 1
    elif b:
        x = 2
    else:
        x = 3
    return x

try:
    import __builtin__  as builtins
except ImportError:
    import builtins

def i(a, b):
    """
    >>> i(1,2)
    1
    >>> i(2,2)
    2
    >>> i(2,1)
    0
    """
    x = 0
    if builtins.str(a).upper() == u"1":
        x = 1
    if builtins.str(a+b).lower() not in (u"1", u"3"):
        x = 2
    return x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/if_and_or.pyx0000644000175100001770000000303000000000000020220 0ustar00runnerdocker00000000000000# mode: run
# tag: if, and, or

def if_x(x):
    """
    >>> if_x(0)
    2
    >>> if_x(1)
    1
    """
    if x:
        return 1
    else:
        return 2

def if_not(x):
    """
    >>> if_not(0)
    1
    >>> if_not(1)
    2
    """
    if not x:
        return 1
    else:
        return 2


def if_and(a, b):
    """
    >>> if_and(3, 0)
    2
    >>> if_and(0, 3)
    2
    >>> if_and(0, 0)
    2
    >>> if_and(3, 3)
    1
    """
    if a and b:
        return 1
    else:
        return 2


def if_not_and(a, b):
    """
    >>> if_not_and(3, 0)
    1
    >>> if_not_and(0, 3)
    1
    >>> if_not_and(0, 0)
    1
    >>> if_not_and(3, 3)
    2
    """
    if not (a and b):
        return 1
    else:
        return 2


def if_or(a, b):
    """
    >>> if_or(3, 0)
    1
    >>> if_or(0, 3)
    1
    >>> if_or(0, 0)
    2
    >>> if_or(3, 3)
    1
    """
    if a or b:
        return 1
    else:
        return 2


def if_not_or(a, b):
    """
    >>> if_not_or(3, 0)
    2
    >>> if_not_or(0, 3)
    2
    >>> if_not_or(0, 0)
    1
    >>> if_not_or(3, 3)
    2
    """
    if not (a or b):
        return 1
    else:
        return 2


def if_and_or(a, b, c, d):
    """
    >>> if_and_or(3, 0, 0, 3)
    1
    >>> if_and_or(0, 3, 0, 3)
    1
    >>> if_and_or(0, 3, 3, 0)
    1
    >>> if_and_or(0, 3, 3, 0)
    1
    >>> if_and_or(0, 0, 0, 0)
    2
    >>> if_and_or(0, 3, 0, 0)
    2
    >>> if_and_or(0, 0, 3, 0)
    2
    >>> if_and_or(0, 0, 0, 3)
    2
    """
    if (a or b) and (c or d):
        return 1
    else:
        return 2
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/if_const.pyx0000644000175100001770000001015200000000000020107 0ustar00runnerdocker00000000000000
cimport cython

DEF INT_VAL = 1

def _not_constant_but_False():
    return False

@cython.test_fail_if_path_exists("//PrimaryCmpNode",
                                 "//IfStatNode")
def int_bool_result():
    """
    >>> int_bool_result()
    True
    """
    if 5:
        return True
    else:
        return False

@cython.test_fail_if_path_exists("//IfStatNode")
def constant_if_elif_else():
    """
    >>> constant_if_elif_else()
    True
    """
    if 0:
        return False
    elif 5:
        return True
    else:
        return False

@cython.test_fail_if_path_exists("//PrintStatNode")
@cython.test_assert_path_exists("//IfStatNode",
                                "//IfClauseNode")
def non_constant_if_elif_else1():
    """
    >>> non_constant_if_elif_else1()
    True
    """
    if _not_constant_but_False():
        return False
    elif 5:
        return True
    else:
        print(False)

@cython.test_fail_if_path_exists("//PrintStatNode")
@cython.test_assert_path_exists("//IfStatNode",
                                "//IfClauseNode")
def non_constant_if_elif_else2():
    """
    >>> non_constant_if_elif_else2()
    True
    """
    if _not_constant_but_False():
        return False
    elif 0:
        print(False)
    else:
        return True

@cython.test_fail_if_path_exists("//PrimaryCmpNode",
                                 "//IfStatNode")
def if_not_compare_true():
    """
    >>> if_not_compare_true()
    False
    """
    if not 0 == 0:
        return True
    else:
        return False

@cython.test_fail_if_path_exists("//PrimaryCmpNode",
                                 "//IfStatNode")
def if_compare_true():
    """
    >>> if_compare_true()
    True
    """
    if 0 == 0:
        return True
    else:
        return False

@cython.test_fail_if_path_exists("//PrimaryCmpNode",
                                 "//IfStatNode")
def if_compare_false():
    """
    >>> if_compare_false()
    False
    """
    if 0 == 1:
        return True
    else:
        return False

@cython.test_fail_if_path_exists("//PrimaryCmpNode",
                                 "//IfStatNode")
def if_compare_or_true():
    """
    >>> if_compare_or_true()
    True
    """
    if 0 == 1 or 1 == 1:
        return True
    else:
        return False

@cython.test_fail_if_path_exists("//PrimaryCmpNode",
                                 "//IfStatNode")
def if_compare_or_false():
    """
    >>> if_compare_or_false()
    False
    """
    if 0 == 1 or 1 == 0:
        return True
    else:
        return False

@cython.test_fail_if_path_exists("//PrimaryCmpNode",
                                 "//IfStatNode")
def if_compare_and_true():
    """
    >>> if_compare_and_true()
    True
    """
    if 0 == 0 and 1 == 1:
        return True
    else:
        return False

@cython.test_fail_if_path_exists("//PrimaryCmpNode",
                                 "//IfStatNode")
def if_compare_and_false():
    """
    >>> if_compare_and_false()
    False
    """
    if 1 == 1 and 1 == 0:
        return True
    else:
        return False

@cython.test_fail_if_path_exists("//PrimaryCmpNode",
                                 "//IfStatNode")
def if_compare_cascaded():
    """
    >>> if_compare_cascaded()
    True
    """
    if 0 < 1 < 2 < 3:
        return True
    else:
        return False

@cython.test_fail_if_path_exists("//CoerceToBooleanNode",
                                 "//ListNode",
                                 "//IfStatNode")
def list_bool_result_true():
    """
    >>> list_bool_result_true()
    True
    """
    if [1,2,3]:
        return True
    else:
        return False

@cython.test_fail_if_path_exists("//CoerceToBooleanNode",
                                 "//ListNode",
                                 "//IfStatNode")
def list_bool_result_false():
    """
    >>> list_bool_result_false()
    False
    """
    if []:
        return True
    else:
        return False

@cython.test_fail_if_path_exists("//PrimaryCmpNode",
                                 "//IfStatNode")
def compile_time_DEF_if():
    """
    >>> compile_time_DEF_if()
    True
    """
    if INT_VAL != 0:
        return True
    else:
        return False
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/if_else_expr.pyx0000644000175100001770000002213600000000000020754 0ustar00runnerdocker00000000000000# mode: run
# tag: condexpr
# ticket: 5197

cimport cython

cdef class Foo:
    cdef dict data

    def __repr__(self):
        return ''


cpdef test_type_cast(Foo obj, cond):
    """
    # Regression test: obj must be cast to (PyObject *) here
    >>> test_type_cast(Foo(), True)
    []
    >>> test_type_cast(Foo(), False)
    
    """
    return [obj] if cond else obj


cdef func(Foo foo, dict data):
    return foo, data


@cython.test_fail_if_path_exists('//PyTypeTestNode')
def test_cpp_pyobject_cast(Foo obj1, Foo obj2, cond):
    """
    >>> test_cpp_pyobject_cast(Foo(), Foo(), True)
    (, None)
    """
    return func(obj1 if cond else obj2, obj1.data if cond else obj2.data)


def test_charptr_coercion(x):
    """
    >>> print(test_charptr_coercion(True))
    abc
    >>> print(test_charptr_coercion(False))
    def
    """
    cdef char* s = b'abc' if x else b'def'
    return s.decode('ascii')


def test_syntax():
    """
    >>> test_syntax()
    (0, 0, 0)
    """
    # Py3 allows the 'else' keyword to directly follow a number
    x = 0 if 1else 1
    y = 0 if 1.0else 1
    z = 0 if 1.else 1
    return x, y, z


from libc cimport math

def test_cfunc_ptrs(double x, bint round_down):
    """
    >>> test_cfunc_ptrs(2.5, round_down=True)
    2.0
    >>> test_cfunc_ptrs(2.5, round_down=False)
    3.0
    """
    return (math.floor if round_down else math.ceil)(x)


def performance_gh5197(patternsList):
    """
    >>> performance_gh5197([])  # do not actually run anything, just see that things work at all
    """
    # Coercing the types in nested conditional expressions used to slow down exponentially.
    # See https://github.com/cython/cython/issues/5197
    import re
    matched=[]
    for _ in range(len(patternsList)):
        try:
            matched.append(patternsList[_].split('|')[-1].split('/')[-1] + 'pattr1' if re.search('^SomeString.*EndIng$')\
                else patternsList[_].split('|a')[-1].split('/a')[-1] + 'pattr2' if re.search('^SomeOtherString.?Number.*EndIng$')\
                    else patternsList[_].split('|a')[-1].split('/a')[-1] + 'pattr2' if re.search('^SomeOtherString.?Number.*EndIng$')\
                        else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                            else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                    else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                        else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                            else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                    else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                        else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                            else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                    else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                        else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                            else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                                else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                                    else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                                        else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                                            else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                                                else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                                                    else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                                                        # else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                                                        #     else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                                                        #         else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                                                        #             else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                                                        #                 else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                                                        #                     else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                                                        #                         else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1] if re.search('^SomeOtherString.?Number.*EndIng$')\
                                                                                                                                    else patternsList[_].split('|b')[-1].split('/b')[-1] + 'pattr2' + patternsList[_].split('/')[-1].split('//')[-1]  )
        except Exception as e:
            matched.append('Error at Indx:%s-%s' %(_, patternsList[_]))

cdef accept_int(int x):
    return x

def test_mixed_int_bool_coercion(x):
    """
    https://github.com/cython/cython/issues/5731

    >>> test_mixed_int_bool_coercion(None)
    0
    >>> test_mixed_int_bool_coercion(5)
    5
    """
    return accept_int(False if x is None else x)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/if_else_expr_cpp.pyx0000644000175100001770000000134700000000000021617 0ustar00runnerdocker00000000000000# mode: run
# tag: condexpr, cpp

cdef extern from "if_else_expr_cpp_helper.h":
    cdef cppclass Holder:
        int value
        Holder()
        Holder(int value)

    cdef Holder v1
    cdef Holder v2
    cdef Holder& get_v1()
    cdef Holder& get_v2()

cdef reset() :
    v1.value = 1
    v2.value = 2

def test_one_ref(bint b):
    """
    >>> test_one_ref(False)
    1
    >>> test_one_ref(True)
    100
    """
    reset()
    return (Holder(100) if b else get_v1()).value

def test_both_ref(bint b):
    """
    >>> test_both_ref(False)
    (1, 100)
    >>> test_both_ref(True)
    (100, 2)
    """
    reset()
    try:
        (get_v1() if b else get_v2()).value = 100
        return v1.value, v2.value
    finally:
        reset()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/if_else_expr_cpp_helper.h0000644000175100001770000000032600000000000022561 0ustar00runnerdocker00000000000000class Holder {
public:
    int value;
    Holder() : value(-1) { }
    Holder(int value) : value(value) { }
};

Holder v1(1);
Holder v2(2);

Holder& get_v1() {
    return v1;
}

Holder& get_v2() {
    return v2;
}
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/ifelseexpr_T267.pyx0000644000175100001770000000145600000000000021202 0ustar00runnerdocker00000000000000# mode: run
# tag: condexpr
# ticket: t267

cimport cython

def ident(x): return x

def constants(x):
    """
    >>> constants(4)
    1
    >>> constants(5)
    10
    """
    a = 1 if x < 5 else 10
    return a

def temps(x):
    """
    >>> temps(4)
    1
    >>> temps(5)
    10
    """
    return ident(1) if ident(x) < ident(5) else ident(10)


def nested(x):
    """
    >>> nested(1)
    1
    >>> nested(2)
    2
    >>> nested(3)
    3
    """
    a = 1 if x == 1 else (2 if x == 2 else 3)
    return a


@cython.test_fail_if_path_exists('//CondExprNode')
def const_true(a,b):
    """
    >>> const_true(1,2)
    1
    """
    return a if 1 == 1 else b

@cython.test_fail_if_path_exists('//CondExprNode')
def const_false(a,b):
    """
    >>> const_false(1,2)
    2
    """
    return a if 1 != 1 else b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/import_error_T734.py0000644000175100001770000000034500000000000021362 0ustar00runnerdocker00000000000000# mode: run
# ticket: t734

def test_import_error():
    """
    >>> test_import_error()   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ImportError: cannot import name ...xxx...
    """
    from sys import xxx
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/import_star.pyx0000644000175100001770000000200400000000000020643 0ustar00runnerdocker00000000000000# mode: run

cdef object executable, version_info
cdef long hexversion

ctypedef struct MyStruct:
    int x, y, z

# conversion code for this struct will be generated but not used
# (there used to be a problem getting Cython conversion code generated here)
cdef MyStruct _no_such_name_ = MyStruct(1, 2, 3)

from libc.math cimport M_PI

# Danger ahead!
from sys import *


def test_cdefed_objects():
    """
    >>> ex, vi = test_cdefed_objects()
    >>> assert ex is not None
    >>> assert vi is not None
    """
    return executable, version_info


def test_cdefed_cvalues():
    """
    >>> hexver = test_cdefed_cvalues()
    >>> assert hexver is not None
    >>> assert hexver > 0x02020000
    """
    return hexversion


def test_non_cdefed_names():
    """
    >>> mod, pth = test_non_cdefed_names()
    >>> assert mod is not None
    >>> assert pth is not None
    """
    return modules, path


def test_cimported_pi():
    """
    >>> pi = test_cimported_pi()
    >>> 3.14 < pi < 3.15
    True
    """
    return M_PI
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/importas.pyx0000644000175100001770000000175400000000000020151 0ustar00runnerdocker00000000000000# mode: run
# tag: all_language_levels

__doc__ = u"""
>>> try: sys
... except NameError: pass
... else: print("sys was defined!")
>>> try: distutils
... except NameError: pass
... else: print("distutils was defined!")

>>> import sys as sous
>>> import distutils.core as corey
>>> from copy import deepcopy as copey
>>> import distutils.command as commie

>>> sous is _sous
True
>>> corey is _corey
True
>>> copey is _copey
True
>>> _commie is commie
True

>>> _sous is not None
True
>>> _corey is not None
True
>>> _copey is not None
True
>>> _commie is not None
True

>>> print(_sous.__name__)
sys
>>> print(sous.__name__)
sys
>>> print(_corey.__name__)
distutils.core
>>> print(corey.__name__)
distutils.core
>>> print(_copey.__name__)
deepcopy
>>> print(copey.__name__)
deepcopy
>>> print(_commie.__name__)
distutils.command
>>> print(commie.__name__)
distutils.command
"""

import sys as _sous
import distutils.core as _corey
from copy import deepcopy as _copey
import distutils.command as _commie
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/importas_from_package.srctree0000644000175100001770000000476500000000000023503 0ustar00runnerdocker00000000000000# language_level=2
PYTHON -m Cython.Build.Cythonize -2if "**/*.pyx"
PYTHON -c "import pkg.imports_py2"  # cython2
PYTHON test.py  # cython2

# language_level=3
PYTHON -m Cython.Build.Cythonize -3if "**/*.pyx"
PYTHON test.py  # cython3


######## pkg/__init__.py ########

######## pkg/imported.py ########

######## pkg/sub/__init__.py ########

######## pkg/sub/subimported.py ########

######## pkg/imports_py2.pyx ########
# cython: language_level=2

import sub as _sub
import imported as _imported
import sub.subimported as _subimported
import sub2.imports2 as _imports2

assert "pkg" not in globals()
assert "sub" not in globals()
assert "imported" not in globals()
assert "imports2" not in globals()
assert _sub.__name__ == "pkg.sub", _sub.__name__
assert _imported.__name__ == "pkg.imported", _imported.__name__
assert _subimported.__name__ == "pkg.sub.subimported", _subimported.__name__
assert _imports2.__name__ == "pkg.sub2.imports2", _imports2.__name__
assert _imports2._corey.__name__ == "distutils.core", _imports2._corey.__name__


######## pkg/imports.pyx ########

import sys as _sous
import distutils.core as _corey
from copy import deepcopy as _copey
import distutils.command as _commie

######## pkg/sub2/__init__.py ########

######## pkg/sub2/imports2.pyx ########

import sys as _sous
import distutils.core as _corey
from copy import deepcopy as _copey
import distutils.command as _commie


######## test.py ########

import pkg.imports as pkg_imports

import sys as _sous
import distutils.core as _corey
from copy import deepcopy as _copey
import distutils.command as _commie


assert not hasattr(pkg_imports, "sys")
assert not hasattr(pkg_imports, "distutils")
assert not hasattr(pkg_imports, "pkg")
assert not hasattr(pkg_imports, "imported")

assert pkg_imports._sous is _sous, pkg_imports._sous
assert pkg_imports._corey is _corey, pkg_imports._corey
assert pkg_imports._copey is _copey, pkg_imports.copey
assert pkg_imports._commie is _commie, pkg_imports._commie

assert pkg_imports._sous is not None, pkg_imports._sous
assert pkg_imports._corey is not None, pkg_imports._corey
assert pkg_imports._copey is not None, pkg_imports._copey
assert pkg_imports._commie is not None, pkg_imports._commie

assert pkg_imports._sous.__name__ == "sys", pkg_imports._sous.__name__
assert pkg_imports._corey.__name__ == "distutils.core", pkg_imports._corey.__name__
assert pkg_imports._copey.__name__ == "deepcopy", pkg_imports._copey.__name__
assert pkg_imports._commie.__name__ == "distutils.command", pkg_imports._commie.__name__
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/importfrom.pyx0000644000175100001770000000271100000000000020503 0ustar00runnerdocker00000000000000from distutils import cmd, core, version

def import1():
    """
    >>> import1() == (cmd, core, version)
    True
    """
    from distutils import (

        cmd,

core,                    version)
    return cmd, core, version


def import2():
    """
    >>> import2() == (cmd, core, version)
    True
    """
    from distutils import (cmd,

core,


                           version
)
    return cmd, core, version


def import3():
    """
    >>> import3() == (cmd, core, version)
    True
    """
    from distutils import (cmd, core,version)
    return cmd, core, version

def import4():
    """
    >>> import4() == (cmd, core, version)
    True
    """
    from distutils import cmd, core, version
    return cmd, core, version



def typed_imports():
    """
    >>> typed_imports()
    True
    True
    an integer is required
    Expected type, got int
    """

    import sys
    import types
    cdef long maxunicode
    cdef type t

    from sys import maxunicode
    print(maxunicode == sys.maxunicode)
    from types import ModuleType as t
    print(t is types.ModuleType)

    try:
        from sys import version_info as maxunicode
    except TypeError, e:
        if getattr(sys, "pypy_version_info", None):
            # translate message
            if e.args[0].startswith("int() argument must be"):
                e = "an integer is required"
        print(e)

    try:
        from sys import maxunicode as t
    except TypeError, e:
        print(e)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/in_list_with_side_effects_T544.pyx0000644000175100001770000000100300000000000024215 0ustar00runnerdocker00000000000000# ticket: t544

def count(i=[0]):
    i[0] += 1
    return i[0]

def test(x):
    """
    >>> def py_count(i=[0]):
    ...     i[0] += 1
    ...     return i[0]
    >>> 1 in (py_count(), py_count(), py_count(), py_count())
    True
    >>> 4 in (py_count(), py_count(), py_count(), py_count())
    False
    >>> 12 in (py_count(), py_count(), py_count(), py_count())
    True

    >>> test(1)
    True
    >>> test(4)
    False
    >>> test(12)
    True
    """
    return x in (count(), count(), count(), count())
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/include.pyx0000644000175100001770000000015200000000000017725 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> D
2
>>> XYZ
5
"""

D = 1

include "testinclude.pxi"
include "includes/includefile.pxi"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/include_multiple_modules.srctree0000644000175100001770000000113700000000000024223 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace

############# setup.py #############

from Cython.Build.Dependencies import cythonize
from distutils.core import setup

setup(
    ext_modules = cythonize(["a.pyx", "b.pyx", "include_both.pyx"]),
    )

############# a.pyx ###############

cdef public f():
    pass
    
############# b.pyx ###############

cdef public g():
    pass
    
############# include_both.pyx ####

# This is just checking that a and b don't duplicate any names
# and thus it's possible to include them both in one place

cdef extern from "a.h":
    pass
    
cdef extern from "b.h":
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.2367241
Cython-3.0.8/tests/run/includes/0000755000175100001770000000000000000000000017350 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/includes/a.h0000644000175100001770000000001200000000000017732 0ustar00runnerdocker00000000000000int a = 1;././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/includes/all.pyx0000644000175100001770000000045400000000000020665 0ustar00runnerdocker00000000000000__doc__ = """
    >>> test()
    1, 2, 3, 4, 5
"""

# Make sure all of these happen in order.

cdef extern from "a.h":
    cdef int a

from b cimport b

cdef extern from "c.h":
    cdef int c

cimport indirect_d

cdef extern from "e.h":
    cdef int e

def test():
    print a, b, c, indirect_d.d, e
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/includes/b.h0000644000175100001770000000001400000000000017735 0ustar00runnerdocker00000000000000int b = a+1;././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/includes/b.pxd0000644000175100001770000000004700000000000020307 0ustar00runnerdocker00000000000000cdef extern from "b.h":
    cdef int b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/includes/c.h0000644000175100001770000000001400000000000017736 0ustar00runnerdocker00000000000000int c = b+1;././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/includes/d.h0000644000175100001770000000001400000000000017737 0ustar00runnerdocker00000000000000int d = c+1;././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/includes/d.pxd0000644000175100001770000000004700000000000020311 0ustar00runnerdocker00000000000000cdef extern from "d.h":
    cdef int d
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/includes/e.h0000644000175100001770000000001400000000000017740 0ustar00runnerdocker00000000000000int e = d+1;././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/includes/includefile.pxi0000644000175100001770000000004600000000000022355 0ustar00runnerdocker00000000000000# this file will be included

XYZ = 5
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/includes/indirect_d.pxd0000644000175100001770000000002100000000000022162 0ustar00runnerdocker00000000000000from d cimport d
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/index.pyx0000644000175100001770000002310200000000000017411 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> index_object(100, 100)       # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: 'int' object ...
"""

cdef Py_ssize_t maxsize

import sys
if sys.version_info < (2,5):
    __doc__ = __doc__.replace(u"'int' object ...", u'unsubscriptable object')
    maxsize = min(sys.maxint, 2**31-1)
else:
    maxsize = getattr(sys, 'maxsize', getattr(sys, 'maxint', None))

py_maxsize = maxsize

import cython

def index_tuple(tuple t, int i):
    """
    (minor PyPy error formatting bug here, hence ELLIPSIS)

    >>> index_tuple((1,1,2,3,5), 0)
    1
    >>> index_tuple((1,1,2,3,5), 3)
    3
    >>> index_tuple((1,1,2,3,5), -1)
    5
    >>> index_tuple((1,1,2,3,5), 100)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    IndexError: ... index out of range
    >>> index_tuple((1,1,2,3,5), -7)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    IndexError: ... index out of range
    >>> index_tuple(None, 0)
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not subscriptable
    """
    return t[i]

def index_list(list L, int i):
    """
    >>> index_list([2,3,5,7,11,13,17,19], 0)
    2
    >>> index_list([2,3,5,7,11,13,17,19], 5)
    13
    >>> index_list([2,3,5,7,11,13,17,19], -1)
    19
    >>> index_list([2,3,5,7,11,13,17,19], 100)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    IndexError: ... index out of range
    >>> index_list([2,3,5,7,11,13,17,19], -10)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    IndexError: ... index out of range
    >>> index_list(None, 0)
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not subscriptable
    """
    return L[i]

def index_object(object o, int i):
    """
    (minor PyPy error formatting bug here, hence ELLIPSIS)

    >>> index_object([2,3,5,7,11,13,17,19], 1)
    3
    >>> index_object([2,3,5,7,11,13,17,19], -1)
    19
    >>> index_object((1,1,2,3,5), 2)
    2
    >>> index_object((1,1,2,3,5), -2)
    3
    >>> index_object("abcdef...z", 0)
    'a'
    >>> index_object("abcdef...z", -1)
    'z'
    >>> index_object("abcdef...z", 100)
    Traceback (most recent call last):
    IndexError: string index out of range
    >>> try: index_object(None, 0)
    ... except TypeError: pass
    """
    return o[i]


def del_index_list(list L, Py_ssize_t index):
    """
    >>> del_index_list(list(range(4)), 0)
    [1, 2, 3]
    >>> del_index_list(list(range(4)), 1)
    [0, 2, 3]
    >>> del_index_list(list(range(4)), -1)
    [0, 1, 2]
    >>> del_index_list(list(range(4)), py_maxsize)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    IndexError: list... index out of range
    >>> del_index_list(list(range(4)), -py_maxsize)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    IndexError: list... index out of range
    """
    del L[index]
    return L


def set_index_list(list L, Py_ssize_t index):
    """
    >>> set_index_list(list(range(4)), 0)
    [5, 1, 2, 3]
    >>> set_index_list(list(range(4)), 1)
    [0, 5, 2, 3]
    >>> set_index_list(list(range(4)), -1)
    [0, 1, 2, 5]
    >>> set_index_list(list(range(4)), py_maxsize)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    IndexError: list... index out of range
    >>> set_index_list(list(range(4)), -py_maxsize)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    IndexError: list... index out of range
    """
    L[index] = 5
    return L


# These make sure that our fast indexing works with large and unsigned types.

def test_unsigned_long():
    """
    >>> test_unsigned_long()
    """
    cdef int i
    cdef unsigned long ix
    cdef D = {}
    for i from 0 <= i < sizeof(unsigned long) * 8:
        ix = (1) << i
        D[ix] = True
    for i from 0 <= i < sizeof(unsigned long) * 8:
        ix = (1) << i
        assert D[ix] is True
        del D[ix]
    assert len(D) == 0

def test_unsigned_short():
    """
    >>> test_unsigned_short()
    """
    cdef int i
    cdef unsigned short ix
    cdef D = {}
    for i from 0 <= i < sizeof(unsigned short) * 8:
        ix = (1) << i
        D[ix] = True
    for i from 0 <= i < sizeof(unsigned short) * 8:
        ix = (1) << i
        assert D[ix] is True
        del D[ix]
    assert len(D) == 0

def test_long_long():
    """
    >>> test_long_long()
    """
    cdef int i
    cdef long long ix
    cdef D = {}
    for i from 0 <= i < sizeof(long long) * 8:
        ix = (1) << i
        D[ix] = True
    for i from 0 <= i < sizeof(long long) * 8:
        ix = (1) << i
        assert D[ix] is True
        del D[ix]

    L = [1, 2, 3]
    try:
        ix = py_maxsize + 1
    except OverflowError:
        pass  # can't test this here
    else:
        try: L[ix] = 5
        except IndexError: pass
        else: assert False, "setting large index failed to raise IndexError"

        try: del L[ix]
        except IndexError: pass
        else: assert False, "deleting large index failed to raise IndexError"

    try:
        ix = -py_maxsize - 2
    except OverflowError:
        pass  # can't test this here
    else:
        try: L[ix] = 5
        except IndexError: pass
        else: assert False, "setting large index failed to raise IndexError"

        try: del L[ix]
        except IndexError: pass
        else: assert False, "deleting large index failed to raise IndexError"

    assert len(D) == 0


def test_ulong_long():
    """
    >>> test_ulong_long()
    """
    cdef unsigned long long ix

    L = [1, 2, 3]
    try:
        ix = py_maxsize + 1
    except OverflowError:
        pass  # can't test this here
    else:
        try: L[ix] = 5
        except IndexError: pass
        else: assert False, "setting large index failed to raise IndexError"

        try: del L[ix]
        except IndexError: pass
        else: assert False, "deleting large index failed to raise IndexError"


@cython.boundscheck(False)
def test_boundscheck_unsigned(list L, tuple t, object o, unsigned long ix):
    """
    >>> test_boundscheck_unsigned([1, 2, 4], (1, 2, 4), [1, 2, 4], 2)
    (4, 4, 4)
    >>> test_boundscheck_unsigned([1, 2, 4], (1, 2, 4), "", 2)
    Traceback (most recent call last):
    ...
    IndexError: string index out of range
    """
    return L[ix], t[ix], o[ix]

@cython.boundscheck(False)
def test_boundscheck_signed(list L, tuple t, object o, long ix):
    """
    >>> test_boundscheck_signed([1, 2, 4], (1, 2, 4), [1, 2, 4], 2)
    (4, 4, 4)
    >>> test_boundscheck_signed([1, 2, 4], (1, 2, 4), "", 2)
    Traceback (most recent call last):
    ...
    IndexError: string index out of range
    """
    return L[ix], t[ix], o[ix]

@cython.wraparound(False)
def test_wraparound_signed(list L, tuple t, object o, long ix):
    """
    >>> test_wraparound_signed([1, 2, 4], (1, 2, 4), [1, 2, 4], 2)
    (4, 4, 4)
    >>> test_wraparound_signed([1, 2, 4], (1, 2, 4), "", 2)
    Traceback (most recent call last):
    ...
    IndexError: string index out of range
    """
    return L[ix], t[ix], o[ix]

def large_literal_index(object o):
    """
    >>> large_literal_index({1000000000000000000000000000000: True})
    True
    """
    return o[1000000000000000000000000000000]


class LargeIndexable(object):
    expected = None

    def __len__(self):
        raise OverflowError

    def __getitem__(self, index):
        return index

    def __setitem__(self, index, value):
        assert index == value == self.expected
        self.expected = None

    def __delitem__(self, index):
        assert self.expected == index
        self.expected = None


def test_large_indexing(obj):
    """
    >>> obj = LargeIndexable()
    >>> zero, pone, none, pmaxsize, nmaxsize = test_large_indexing(obj)
    >>> # , p2maxsize, n2maxsize
    >>> zero
    0
    >>> pone
    1
    >>> none
    -1
    >>> pmaxsize == py_maxsize
    True
    >>> nmaxsize == -py_maxsize
    True

    #>>> p2maxsize == py_maxsize*2
    #True
    #>>> n2maxsize == -py_maxsize*2
    #True
    """
    return (
        obj[0], obj[1], obj[-1],
        obj[maxsize], obj[-maxsize],
        #obj[maxsize*2], obj[-maxsize*2]     # FIXME!
    )


def del_large_index(obj, Py_ssize_t index):
    """
    >>> obj = LargeIndexable()
    >>> del_large_index(obj, 0)
    >>> del_large_index(obj, 1)
    >>> del_large_index(obj, -1)
    >>> del_large_index(obj, py_maxsize)
    >>> del_large_index(obj, -py_maxsize)
    """
    obj.expected = index
    del obj[index]
    assert obj.expected is None


def set_large_index(obj, Py_ssize_t index):
    """
    >>> obj = LargeIndexable()
    >>> set_large_index(obj, 0)
    >>> set_large_index(obj, 1)
    >>> set_large_index(obj, -1)
    >>> set_large_index(obj, py_maxsize)
    >>> set_large_index(obj, -py_maxsize)
    """
    obj.expected = index
    obj[index] = index
    assert obj.expected is None


class DoesntLikePositiveIndices(object):
    def __getitem__(self, idx):
        if idx >= 0:
            raise RuntimeError("Positive index")
        return "Good"

    def __setitem__(self, idx, value):
        if idx >= 0:
            raise RuntimeError("Positive index")

    def __delitem__(self, idx):
        if idx >= 0:
            raise RuntimeError("Positive index")

    def __len__(self):
        return 500

def test_call_with_negative_numbers():
    """
    The key point is that Cython shouldn't default to PySequence_*Item
    since that invisibly adjusts negative numbers to be len(o)-idx.
    >>> test_call_with_negative_numbers()
    'Good'
    """
    cdef int idx = -5
    indexme = DoesntLikePositiveIndices()
    del indexme[idx]
    indexme[idx] = "something"
    return indexme[idx]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/inhcmethcall.pyx0000644000175100001770000000045200000000000020740 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> p = Norwegian()
>>> p.describe()
Norwegian
Parrot
"""

cdef class Parrot:

  cdef void _describe(self):
    print u"Parrot"

  def describe(self):
    self._describe()

cdef class Norwegian(Parrot):

  cdef void _describe(self):
    print u"Norwegian"
    Parrot._describe(self)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/inherited_final_method.pyx0000644000175100001770000000105500000000000022771 0ustar00runnerdocker00000000000000# mode: run
# tag: exttype, final

cimport cython


cdef class BaseClass:
    """
    >>> obj = BaseClass()
    >>> obj.call_base()
    True
    """
    cdef method(self):
        return True

    def call_base(self):
        return self.method()


@cython.final
cdef class Child(BaseClass):
    """
    >>> obj = Child()
    >>> obj.call_base()
    True
    >>> obj.call_child()
    True
    """
    cdef method(self):
        return True

    def call_child(self):
        # original bug: this requires a proper cast for self
        return self.method()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/initial_file_path.srctree0000644000175100001770000000453400000000000022605 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import my_test_package as p; assert not p.__file__.rstrip('co').endswith('.py'), p.__file__; p.test()"
PYTHON -c "import my_test_package.a as a; a.test()"
PYTHON -c "import my_test_package.another as p; assert not p.__file__.rstrip('co').endswith('.py'), p.__file__; p.test()"
PYTHON -c "import my_test_package.another.a as a; a.test()"

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup

setup(
    ext_modules = cythonize(["my_test_package/**/*.py"]),
)

######## my_test_package/__init__.py ########

# cython: set_initial_path=SOURCEFILE

initial_path = __path__
initial_file = __file__

try:
    from . import a
    import_error = None
except ImportError as e:
    import_error = e
    import traceback
    traceback.print_exc()

def test():
    print("FILE: ", initial_file)
    print("PATH: ", initial_path)
    assert initial_path[0].endswith('my_test_package'), initial_path
    assert initial_file.endswith('__init__.py'), initial_file
    assert import_error is None, import_error

######## my_test_package/another/__init__.py ########

# cython: set_initial_path=SOURCEFILE

initial_path = __path__
initial_file = __file__

try:
    from . import a
    import_error = None
except ImportError as e:
    import_error = e
    import traceback
    traceback.print_exc()

def test():
    print("FILE: ", initial_file)
    print("PATH: ", initial_path)
    assert initial_path[0].endswith('another'), initial_path
    assert initial_file.endswith('__init__.py'), initial_file
    assert import_error is None, import_error

######## my_test_package/a.py ########

# cython: set_initial_path=SOURCEFILE

initial_file = __file__

try:
    initial_path = __path__
except NameError:
    got_name_error = True
else:
    got_name_error = False

def test():
    assert initial_file.endswith('a.py'), initial_file
    assert got_name_error, "looks like __path__ was set at module init time: " + initial_path

######## my_test_package/another/a.py ########

# cython: set_initial_path=SOURCEFILE

initial_file = __file__

try:
    initial_path = __path__
except NameError:
    got_name_error = True
else:
    got_name_error = False

def test():
    assert initial_file.endswith('a.py'), initial_file
    assert got_name_error, "looks like __path__ was set at module init time: " + initial_path
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/inline.pyx0000644000175100001770000000020300000000000017555 0ustar00runnerdocker00000000000000def test(x):
    """
    >>> test(3)
    3
    """
    return retinput(x)

cdef inline int retinput(int x):
    o = x
    return o
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/inlined_context_manager.pyx0000644000175100001770000000061700000000000023170 0ustar00runnerdocker00000000000000# mode: run

cimport cython

@cython.final
cdef class TypedContextManager(object):
    cdef double __enter__(self): # not callable from Python !
        return 2.0
    # FIXME: inline __exit__() as well
    def __exit__(self, exc_type, exc_value, exc_tb):
        return 0

def with_statement():
    """
    >>> with_statement()
    2.0
    """
    with TypedContextManager() as x:
        return x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/inlined_generator_expressions.pyx0000644000175100001770000001471100000000000024442 0ustar00runnerdocker00000000000000
cimport cython

## def range_tuple_genexp(int N):
##     """
##     >>> range_tuple_genexp(5)
##     (0, 1, 2, 3, 4)
##     """
##     return tuple(i for i in range(N))


@cython.test_assert_path_exists('//ForFromStatNode',
                                "//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode',
                                 '//ForInStatNode')
def range_sum(int N):
    """
    >>> sum(range(10))
    45
    >>> range_sum(10)
    45
    """
    result = sum(i for i in range(N))
    return result


@cython.test_assert_path_exists('//ForFromStatNode',
                                "//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode',
                                 '//CoerceFromPyTypeNode//InlinedGeneratorExpressionNode',
                                 '//ForInStatNode')
def range_sum_typed(int N):
    """
    >>> sum(range(10))
    45
    >>> range_sum_typed(10)
    45
    """
    cdef int result = sum(i for i in range(N))
    return result


@cython.test_assert_path_exists('//ForFromStatNode',
                                "//InlinedGeneratorExpressionNode",
                                "//ReturnStatNode//InlinedGeneratorExpressionNode",
                                "//ReturnStatNode//CoerceToPyTypeNode//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode',
                                 '//CoerceFromPyTypeNode//InlinedGeneratorExpressionNode',
                                 '//TypecastNode//InlinedGeneratorExpressionNode',
                                 '//ForInStatNode')
def return_range_sum_cast(int N):
    """
    >>> sum(range(10))
    45
    >>> return_range_sum_cast(10)
    45
    """
    return sum(i for i in range(N))


@cython.test_assert_path_exists('//ForFromStatNode',
                                "//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode',
                                 '//ForInStatNode')
def return_range_sum(int N):
    """
    >>> sum(range(10))
    45
    >>> return_range_sum(10)
    45
    """
    return sum(i for i in range(N))


@cython.test_assert_path_exists('//ForFromStatNode',
                                "//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode',
                                 '//ForInStatNode')
def return_range_sum_squares(int N):
    """
    >>> sum([i*i for i in range(10)])
    285
    >>> return_range_sum_squares(10)
    285

    >>> print(sum([i*i for i in range(10000)]))
    333283335000
    >>> print(return_range_sum_squares(10000))
    333283335000
    """
    return sum(i*i for i in range(N))


@cython.test_assert_path_exists('//ForInStatNode',
                                "//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode')
def return_sum_squares(seq):
    """
    >>> sum([i*i for i in range(10)])
    285
    >>> return_sum_squares(range(10))
    285

    >>> print(sum([i*i for i in range(10000)]))
    333283335000
    >>> print(return_sum_squares(range(10000)))
    333283335000
    """
    return sum(i*i for i in seq)


@cython.test_assert_path_exists('//ForInStatNode',
                                "//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode')
def return_sum_squares_start(seq, int start):
    """
    >>> sum([i*i for i in range(10)], -1)
    284
    >>> return_sum_squares_start(range(10), -1)
    284

    >>> print(sum([i*i for i in range(10000)], 9))
    333283335009
    >>> print(return_sum_squares_start(range(10000), 9))
    333283335009
    """
    return sum((i*i for i in seq), start)


@cython.test_assert_path_exists(
    '//ForInStatNode',
    "//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists(
    '//SimpleCallNode',
    "//InlinedGeneratorExpressionNode//CoerceToPyTypeNode")
def return_typed_sum_squares_start(seq, int start):
    """
    >>> sum([i*i for i in range(10)], -1)
    284
    >>> return_typed_sum_squares_start(range(10), -1)
    284

    >>> print(sum([i*i for i in range(1000)], 9))
    332833509
    >>> print(return_typed_sum_squares_start(range(1000), 9))
    332833509
    """
    cdef int i
    return sum((i*i for i in seq), start)


@cython.test_assert_path_exists('//ForInStatNode',
                                "//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode')
def return_sum_of_listcomp_consts_start(seq, int start):
    """
    >>> sum([1 for i in range(10) if i > 3], -1)
    5
    >>> return_sum_of_listcomp_consts_start(range(10), -1)
    5

    >>> print(sum([1 for i in range(10000) if i > 3], 9))
    10005
    >>> print(return_sum_of_listcomp_consts_start(range(10000), 9))
    10005
    """
    return sum([1 for i in seq if i > 3], start)


@cython.test_assert_path_exists('//ForInStatNode',
                                "//InlinedGeneratorExpressionNode",
                                # the next test is for a deficiency
                                # (see InlinedGeneratorExpressionNode.coerce_to()),
                                # hope this breaks one day
                                "//CoerceFromPyTypeNode//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode')
def return_typed_sum_of_listcomp_consts_start(seq, int start):
    """
    >>> sum([1 for i in range(10) if i > 3], -1)
    5
    >>> return_typed_sum_of_listcomp_consts_start(range(10), -1)
    5

    >>> print(sum([1 for i in range(10000) if i > 3], 9))
    10005
    >>> print(return_typed_sum_of_listcomp_consts_start(range(10000), 9))
    10005
    """
    return sum([1 for i in seq if i > 3], start)


@cython.test_assert_path_exists(
    '//ForInStatNode',
    "//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists(
    '//SimpleCallNode',
    "//InlinedGeneratorExpressionNode//CoerceToPyTypeNode")
def return_typed_sum_cond_exp(seq):
    """
    >>> return_typed_sum_cond_exp([1,2,3,4])
    2
    """
    cdef int i
    return sum( 0 if i%2 else 1
                     for i in seq )


@cython.test_assert_path_exists(
    '//ForInStatNode',
    "//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists(
    '//SimpleCallNode',
    "//InlinedGeneratorExpressionNode//CoerceToPyTypeNode")
def return_typed_sum_cond_exp_in(seq):
    """
    >>> return_typed_sum_cond_exp_in([1,2,3,4,5,6,7,8,9])
    3
    """
    cdef int i
    return sum( 0 if i%3 in (0,1) else 1
                     for i in seq )
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/inlinepxd.pxd0000644000175100001770000000007000000000000020246 0ustar00runnerdocker00000000000000
cdef inline int my_add(int a, int b):
    return a + b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/inlinepxd.pyx0000644000175100001770000000135000000000000020275 0ustar00runnerdocker00000000000000# mode: run
# tag: inline, pxd

# cython: wraparound = False

__doc__ = u"""
>>> f()
3
>>> g()
6
>>> h()
6
>>> i()
6
>>> j()
6
"""

cimport inlinepxd_support
from inlinepxd_support cimport my_add as my_add3

def f():
    return my_add(1, 2)

def g():
    return inlinepxd_support.my_add(1, 2, 3)

def h():
    return my_add3(1, 2, 3)

def i():
    return my_add3(5)

def j():
    return my_add3(2, 4)

def test_wraparound():
    """
    >>> test_wraparound()
    1.0
    """
    # the wraparound directive from this scope should not affect the inline pxd
    a = [ 0.0, 1.0 ]
    return inlinepxd_support.index(a)


def test_call_inlined(L):
    """
    >>> test_call_inlined([1, 2, 3])
    3
    """
    return inlinepxd_support.call_index(L)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/inlinepxd_support.pxd0000644000175100001770000000051100000000000022042 0ustar00runnerdocker00000000000000
cdef inline int my_add(int a, int b=1, int c=0):
    return a + b + c

cdef inline index(list L):
    # This function should *not* be affected by directives set in the outer scope, such as "wraparound".
    # See https://github.com/cython/cython/issues/1071
    return L[-1]

cdef inline call_index(list L):
    return index(L)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/inop.pyx0000644000175100001770000002510100000000000017250 0ustar00runnerdocker00000000000000
cimport cython

def f(a,b):
    """
    >>> f(1,[1,2,3])
    True
    >>> f(5,[1,2,3])
    False
    >>> f(2,(1,2,3))
    True
    """
    cdef object result = a in b
    return result

def g(a,b):
    """
    >>> g(1,[1,2,3])
    1
    >>> g(5,[1,2,3])
    0
    >>> g(2,(1,2,3))
    1
    """
    cdef int result = a in b
    return result

def h(b):
    """
    >>> h([1,2,3,4])
    True
    >>> h([1,3,4])
    False
    """
    cdef object result = 2 in b
    return result

def j(b):
    """
    >>> j([1,2,3,4])
    1
    >>> j([1,3,4])
    0
    """
    cdef int result = 2 in b
    return result

@cython.test_fail_if_path_exists("//SwitchStatNode")
def k(a):
    """
    >>> k(1)
    1
    >>> k(5)
    0
    """
    cdef int result = a in [1,2,3,4]
    return result

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def m_list(int a):
    """
    >>> m_list(2)
    1
    >>> m_list(5)
    0
    """
    cdef int result = a in [1,2,3,4]
    return result

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def m_tuple(int a):
    """
    >>> m_tuple(2)
    1
    >>> m_tuple(5)
    0
    """
    cdef int result = a in (1,2,3,4)
    return result

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def m_set(int a):
    """
    >>> m_set(2)
    1
    >>> m_set(5)
    0
    """
    cdef int result = a in {1,2,3,4}
    return result

cdef bytes bytes_string = b'ab\0cde\0f\0g'
py_bytes_string = bytes_string

@cython.test_assert_path_exists("//PrimaryCmpNode")
@cython.test_fail_if_path_exists("//SwitchStatNode", "//BoolBinopNode")
def m_bytes(char a, bytes bytes_string):
    """
    >>> m_bytes(ord('f'), py_bytes_string)
    1
    >>> m_bytes(ord('X'), py_bytes_string)
    0
    >>> 'f'.encode('ASCII') in None    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...iterable...
    >>> m_bytes(ord('f'), None)
    Traceback (most recent call last):
    TypeError: argument of type 'NoneType' is not iterable
    """
    cdef int result = a in bytes_string
    return result

@cython.test_assert_path_exists("//PrimaryCmpNode")
@cython.test_fail_if_path_exists("//SwitchStatNode", "//BoolBinopNode")
def m_bytes_unsigned(unsigned char a, bytes bytes_string):
    """
    >>> m_bytes(ord('f'), py_bytes_string)
    1
    >>> m_bytes(ord('X'), py_bytes_string)
    0
    >>> 'f'.encode('ASCII') in None    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...iterable...
    >>> m_bytes(ord('f'), None)
    Traceback (most recent call last):
    TypeError: argument of type 'NoneType' is not iterable
    """
    cdef int result = a in bytes_string
    return result

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def m_bytes_literal(char a):
    """
    >>> m_bytes_literal(ord('f'))
    1
    >>> m_bytes_literal(ord('X'))
    0
    """
    cdef int result = a in b'ab\0cde\0f\0g'
    return result

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def m_bytes_literal_unsigned(unsigned char a):
    """
    >>> m_bytes_literal(ord('f'))
    1
    >>> m_bytes_literal(ord('X'))
    0
    """
    cdef int result = a in b'ab\0cde\0f\0g'
    return result

cdef unicode unicode_string = u'abc\0defg\u1234\uF8D2'
py_unicode_string = unicode_string

@cython.test_assert_path_exists("//PrimaryCmpNode")
@cython.test_fail_if_path_exists("//SwitchStatNode", "//BoolBinopNode")
def m_unicode(Py_UNICODE a, unicode unicode_string):
    """
    >>> m_unicode(ord('f'), py_unicode_string)
    1
    >>> m_unicode(ord('X'), py_unicode_string)
    0
    >>> m_unicode(ord(py_klingon_character), py_unicode_string)
    1

    >>> 'f' in None   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...iterable...
    >>> m_unicode(ord('f'), None)
    Traceback (most recent call last):
    TypeError: argument of type 'NoneType' is not iterable
    """
    cdef int result = a in unicode_string
    return result

cdef unicode klingon_character = u'\uF8D2'
py_klingon_character = klingon_character

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def m_unicode_literal(Py_UNICODE a):
    """
    >>> m_unicode_literal(ord('f'))
    1
    >>> m_unicode_literal(ord('X'))
    0
    >>> m_unicode_literal(ord(py_klingon_character))
    1
    """
    cdef int result = a in u'abc\0defg\u1234\uF8D2'
    return result

cdef unicode wide_unicode_character = u'\U0010FEDC'
py_wide_unicode_character = wide_unicode_character
wide_unicode_character_surrogate1 = 0xDBFF
wide_unicode_character_surrogate2 = 0xDEDC

@cython.test_fail_if_path_exists("//SwitchStatNode")
@cython.test_assert_path_exists("//PrimaryCmpNode")
def m_wide_unicode_literal(Py_UCS4 a):
    """
    >>> m_unicode_literal(ord('f'))
    1
    >>> m_unicode_literal(ord('X'))
    0
    >>> import sys
    >>> if sys.maxunicode == 65535:
    ...     m_wide_unicode_literal(wide_unicode_character_surrogate1)
    ...     m_wide_unicode_literal(wide_unicode_character_surrogate2)
    ... else:
    ...     m_wide_unicode_literal(ord(py_wide_unicode_character))
    ...     1
    1
    1
    """
    cdef int result = a in u'abc\0defg\u1234\uF8D2\U0010FEDC'
    return result

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def conditional_int(int a):
    """
    >>> conditional_int(1)
    1
    >>> conditional_int(0)
    2
    >>> conditional_int(5)
    2
    """
    return 1 if a in (1,2,3,4) else 2

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def conditional_object(int a):
    """
    >>> conditional_object(1)
    1
    >>> conditional_object(0)
    '2'
    >>> conditional_object(5)
    '2'
    """
    return 1 if a in (1,2,3,4) else '2'

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def conditional_bytes(char a):
    """
    >>> conditional_bytes(ord('a'))
    1
    >>> conditional_bytes(ord('X'))
    '2'
    >>> conditional_bytes(0)
    '2'
    """
    return 1 if a in b'abc' else '2'

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def conditional_unicode(Py_UNICODE a):
    """
    >>> conditional_unicode(ord('a'))
    1
    >>> conditional_unicode(ord('X'))
    '2'
    >>> conditional_unicode(0)
    '2'
    """
    return 1 if a in u'abc' else '2'

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def conditional_none(int a):
    """
    >>> conditional_none(1)
    >>> conditional_none(0)
    1
    >>> conditional_none(5)
    1
    """
    return None if a in {1,2,3,4} else 1

@cython.test_assert_path_exists(
    "//BoolBinopNode",
    "//BoolBinopNode//PrimaryCmpNode"
)
@cython.test_fail_if_path_exists("//ListNode")
def n(a):
    """
    >>> n('d *')
    1
    >>> n('xxx')
    0
    """
    cdef int result = a.lower() in [u'a *',u'b *',u'c *',u'd *']
    return result

def p(a):
    """
    >>> p(1)
    0
    >>> p('a')
    1
    """
    cdef dict d = {u'a': 1, u'b': 2}
    cdef int result = a in d
    return result

def q(a):
    """
    >>> q(1)
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not iterable
        >>> l = [1,2,3,4]
    >>> l2 = [l[1:],l[:-1],l]
    >>> 2 in l in l2
    True
    """
    cdef dict d = None
    cdef int result = a in d # should fail with a TypeError
    return result

def r(a):
    """
    >>> r(2)
    1
    """
    cdef object l = [1,2,3,4]
    cdef object l2 = [l[1:],l[:-1],l]
    cdef int result = a in l in l2
    return result

def s(a):
    """
    >>> s(2)
    1
    """
    cdef int result = a in [1,2,3,4] in [[1,2,3],[2,3,4],[1,2,3,4]]
    return result

#@cython.test_assert_path_exists("//ReturnStatNode//BoolNode")
#@cython.test_fail_if_path_exists("//SwitchStatNode")
def constant_empty_sequence(a):
    """
    >>> constant_empty_sequence(1)
    False
    >>> constant_empty_sequence(5)
    False
    """
    return a in ()

@cython.test_fail_if_path_exists("//ReturnStatNode//BoolNode")
@cython.test_assert_path_exists("//PrimaryCmpNode")
def constant_empty_sequence_side_effect(a):
    """
    >>> l =[]
    >>> def a():
    ...     l.append(1)
    ...     return 1

    >>> constant_empty_sequence_side_effect(a)
    False
    >>> l
    [1]
    """
    return a() in ()

def test_error_non_iterable(x):
    """
    >>> test_error_non_iterable(1)   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...iterable...
    """
    return x in 42

def test_error_non_iterable_cascaded(x):
    """
    >>> test_error_non_iterable_cascaded(1)   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...iterable...
    """
    return 1 == x in 42

def test_inop_cascaded(x):
    """
    >>> test_inop_cascaded(1)
    False
    >>> test_inop_cascaded(2)
    True
    >>> test_inop_cascaded(3)
    False
    """
    return 1 != x in [2]

### The following tests are copied from CPython's test_grammar.py.
### They look stupid, but the nice thing about them is that Cython
### treats '1' as a C integer constant that triggers Python object
### coercion for the 'in' operator here, whereas the left side of
### the cascade can be evaluated entirely in C space.

def test_inop_cascaded_one():
    """
    >>> test_inop_cascaded_one()
    False
    """
    return 1 < 1 > 1 == 1 >= 1 <= 1 != 1 in 1 not in 1 is 1 is not 1

def test_inop_cascaded_int_orig(int x):
    """
    >>> test_inop_cascaded_int_orig(1)
    False
    """
    return 1 < 1 > 1 == 1 >= 1 <= 1 != x in 1 not in 1 is 1 is not 1

def test_inop_cascaded_one_err():
    """
    >>> test_inop_cascaded_one_err()   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError:... itera...
    """
    return 1 == 1 >= 1 <= 1 in 1 not in 1 is 1 is not 1

def test_inop_cascaded_int_orig_err(int x):
    """
    >>> test_inop_cascaded_int_orig_err(1)   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError:... itera...
    """
    return 1 == 1 >= 1 <= 1 == x in 1 not in 1 is 1 is not 1

###

def test_inop_cascaded_int(int x):
    """
    >>> test_inop_cascaded_int(1)
    False
    >>> test_inop_cascaded_int(2)
    True
    >>> test_inop_cascaded_int(3)
    False
    """
    return 1 != x in [1,2]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/inplace.pyx0000644000175100001770000001157000000000000017723 0ustar00runnerdocker00000000000000cimport cython

def f(a,b):
    """
    >>> str(f(5, 7))
    '29509034655744'
    """
    a += b
    a *= b
    a **= b
    return a

def g(int a, int b):
    """
    >>> g(13, 4)
    32
    """
    a -= b
    a /= b
    a <<= b
    return a

def h(double a, double b):
    """
    >>> h(56, 7)
    105.0
    """
    a /= b
    a += b
    a *= b
    return a

from libc cimport stdlib

def arrays():
    """
    >>> arrays()
    19
    """
    cdef char* buf = stdlib.malloc(10)
    cdef int i = 2
    cdef object j = 2
    buf[2] = 0
    buf[i] += 2
    buf[2] *= 10
    buf[j] -= 1
    print buf[2]
    stdlib.free(buf)

cdef class A:
    cdef attr
    cdef int attr2
    cdef char* buf
    def __init__(self):
        self.attr = 3
        self.attr2 = 3

class B:
    attr = 3

def attributes():
    """
    >>> attributes()
    26 26 26
    """
    cdef A a = A()
    b = B()
    a.attr += 10
    a.attr *= 2
    a.attr2 += 10
    a.attr2 *= 2
    b.attr += 10
    b.attr *= 2
    print a.attr, a.attr2, b.attr

def get_2(): return 2
cdef int identity(int value): return value

def smoketest():
    """
    >>> smoketest()
    10
    """
    cdef char* buf = stdlib.malloc(10)
    cdef A a = A()
    a.buf = buf
    a.buf[identity(1)] = 0
    (a.buf + identity(4) - (2*get_2() - 1))[get_2() - 2*identity(1)] += 10
    print a.buf[1]
    stdlib.free(buf)


def side_effect(x):
    print u"side effect", x
    return x

cdef int c_side_effect(int x):
    print u"c side effect", x
    return x

def test_side_effects():
    """
    >>> test_side_effects()
    side effect 1
    c side effect 2
    side effect 3
    c side effect 4
    ([0, 11, 102, 3, 4], [0, 1, 2, 13, 104])
    """
    cdef object a = list(range(5))
    a[side_effect(1)] += 10
    a[c_side_effect(2)] += 100
    cdef int i
    cdef int[5] b
    for i from 0 <= i < 5:
        b[i] = i
    b[side_effect(3)] += 10
    b[c_side_effect(4)] += 100
    return a, [b[i] for i from 0 <= i < 5]

@cython.cdivision(True)
def test_inplace_cdivision(int a, int b):
    """
    >>> test_inplace_cdivision(13, 10)
    3
    >>> test_inplace_cdivision(13, -10)
    3
    >>> test_inplace_cdivision(-13, 10)
    -3
    >>> test_inplace_cdivision(-13, -10)
    -3
    """
    a %= b
    return a

@cython.cdivision(False)
def test_inplace_pydivision(int a, int b):
    """
    >>> test_inplace_pydivision(13, 10)
    3
    >>> test_inplace_pydivision(13, -10)
    -7
    >>> test_inplace_pydivision(-13, 10)
    7
    >>> test_inplace_pydivision(-13, -10)
    -3
    """
    a %= b
    return a

def test_complex_inplace(double complex x, double complex y):
    """
    >>> test_complex_inplace(1, 1)
    (2+0j)
    >>> test_complex_inplace(2, 3)
    (15+0j)
    >>> test_complex_inplace(2+3j, 4+5j)
    (-16+62j)
    """
    x += y
    x *= y
    return x


# The following is more subtle than one might expect.

cdef struct Inner:
    int x

cdef struct Aa:
    int value
    Inner inner

cdef struct NestedA:
    Aa a

cdef struct ArrayOfA:
    Aa[10] a

def nested_struct_assignment():
    """
    >>> nested_struct_assignment()
    """
    cdef NestedA nested
    nested.a.value = 2
    nested.a.value += 3
    assert nested.a.value == 5

    nested.a.inner.x = 5
    nested.a.inner.x += 10
    assert nested.a.inner.x == 15

def nested_array_assignment():
    """
    >>> nested_array_assignment()
    c side effect 0
    c side effect 1
    """
    cdef ArrayOfA array
    array.a[0].value = 2
    array.a[c_side_effect(0)].value += 3
    assert array.a[0].value == 5

    array.a[1].inner.x = 5
    array.a[c_side_effect(1)].inner.x += 10
    assert array.a[1].inner.x == 15

cdef class VerboseDict(object):
    cdef name
    cdef dict dict
    def __init__(self, name, **kwds):
        self.name = name
        self.dict = kwds
    def __getitem__(self, key):
        print self.name, "__getitem__", key
        return self.dict[key]
    def __setitem__(self, key, value):
        print self.name, "__setitem__", key, value
        self.dict[key] = value
    def __repr__(self):
        return repr(self.name)

def deref_and_increment(o, key):
    """
    >>> deref_and_increment({'a': 1}, 'a')
    side effect a
    >>> v = VerboseDict('v', a=10)
    >>> deref_and_increment(v, 'a')
    side effect a
    v __getitem__ a
    v __setitem__ a 11
    """
    o[side_effect(key)] += 1

def double_deref_and_increment(o, key1, key2):
    """
    >>> v = VerboseDict('v', a=10)
    >>> w = VerboseDict('w', vkey=v)
    >>> double_deref_and_increment(w, 'vkey', 'a')
    side effect vkey
    w __getitem__ vkey
    side effect a
    v __getitem__ a
    v __setitem__ a 11
    """
    o[side_effect(key1)][side_effect(key2)] += 1

def conditional_inplace(value, a, condition, b):
    """
    >>> conditional_inplace([1, 2, 3], [100], True, [200])
    [1, 2, 3, 100]
    >>> conditional_inplace([1, 2, 3], [100], False, [200])
    [1, 2, 3, 200]
    """
    value += a if condition else b
    return value
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/int128.pyx0000644000175100001770000001417000000000000017334 0ustar00runnerdocker00000000000000# mode: run

cdef extern from *:
    ctypedef long long int128_t "__int128_t"
    ctypedef unsigned long long uint128_t "__uint128_t"


def bigint(x):
    print(str(x).rstrip('L'))


def unsigned_conversion(x):
    """
    >>> bigint(unsigned_conversion(0))
    0
    >>> bigint(unsigned_conversion(2))
    2

    >>> unsigned_conversion(-2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    OverflowError: can't convert negative value to ...uint128_t
    >>> unsigned_conversion(-2**120)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    OverflowError: can't convert negative value to ...uint128_t
    >>> unsigned_conversion(-2**127)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    OverflowError: can't convert negative value to ...uint128_t
    >>> unsigned_conversion(-2**128)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    OverflowError: can't convert negative value to ...uint128_t

    >>> bigint(unsigned_conversion(2**20))
    1048576
    >>> bigint(unsigned_conversion(2**30-1))
    1073741823
    >>> bigint(unsigned_conversion(2**30))
    1073741824
    >>> bigint(unsigned_conversion(2**30+1))
    1073741825

    >>> bigint(2**60)
    1152921504606846976
    >>> bigint(unsigned_conversion(2**60-1))
    1152921504606846975
    >>> bigint(unsigned_conversion(2**60))
    1152921504606846976
    >>> bigint(unsigned_conversion(2**60+1))
    1152921504606846977
    >>> bigint(2**64)
    18446744073709551616
    >>> bigint(unsigned_conversion(2**64))
    18446744073709551616

    >>> bigint(2**120)
    1329227995784915872903807060280344576
    >>> bigint(unsigned_conversion(2**120))
    1329227995784915872903807060280344576
    >>> bigint(2**128-1)
    340282366920938463463374607431768211455
    >>> bigint(unsigned_conversion(2**128-1))
    340282366920938463463374607431768211455
    >>> bigint(unsigned_conversion(2**128))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    OverflowError: ... to convert...
    >>> bigint(unsigned_conversion(2**128+1))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    OverflowError: ... to convert...
    >>> bigint(unsigned_conversion(2**129-1))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    OverflowError: ... to convert...
    >>> bigint(unsigned_conversion(2**129))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    OverflowError: ... to convert...
    """
    cdef uint128_t n = x
    return n


def signed_conversion(x):
    """
    >>> bigint(signed_conversion(0))
    0
    >>> bigint(signed_conversion(2))
    2
    >>> bigint(signed_conversion(-2))
    -2

    >>> bigint(signed_conversion(2**20))
    1048576
    >>> bigint(signed_conversion(2**32))
    4294967296
    >>> bigint(2**64)
    18446744073709551616
    >>> bigint(signed_conversion(2**64))
    18446744073709551616
    >>> bigint(signed_conversion(-2**64))
    -18446744073709551616

    >>> bigint(2**118)
    332306998946228968225951765070086144
    >>> bigint(signed_conversion(2**118))
    332306998946228968225951765070086144
    >>> bigint(signed_conversion(-2**118))
    -332306998946228968225951765070086144

    >>> bigint(2**120)
    1329227995784915872903807060280344576
    >>> bigint(signed_conversion(2**120))
    1329227995784915872903807060280344576
    >>> bigint(signed_conversion(-2**120))
    -1329227995784915872903807060280344576

    >>> bigint(2**127-1)
    170141183460469231731687303715884105727
    >>> bigint(signed_conversion(2**127-2))
    170141183460469231731687303715884105726
    >>> bigint(signed_conversion(2**127-1))
    170141183460469231731687303715884105727
    >>> bigint(signed_conversion(2**127))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    OverflowError: ... to convert...
    >>> bigint(signed_conversion(-2**127+1))
    -170141183460469231731687303715884105727
    >>> bigint(signed_conversion(-2**127))
    -170141183460469231731687303715884105728
    >>> bigint(signed_conversion(-2**127-1))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    OverflowError: ... to convert...
    >>> bigint(signed_conversion(-2**127-2))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    OverflowError: ... to convert...
    >>> bigint(signed_conversion(-2**128+1))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    OverflowError: ... to convert...
    >>> bigint(signed_conversion(-2**128))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    OverflowError: ... to convert...
    """
    cdef int128_t n = x
    return n


def get_int_distribution(shuffle=True):
    """
    >>> L = get_int_distribution()
    >>> bigint(L[0])
    682
    >>> bigint(L[ len(L) // 2 ])
    5617771410183435
    >>> bigint(L[-1])
    52818775009509558395695966805
    >>> len(L)
    66510
    """
    # Large integers that cover 1-4 (30 bits) or 1-7 (15 bits) PyLong digits.
    # Uses only integer calculations to avoid rounding issues.
    pow2 = [2**exp for exp in range(98)]
    ints = [
        n // 3
        for i in range(11, len(pow2) - 1)
        # Take a low but growing number of integers from each power-of-2 range.
        for n in range(pow2[i], pow2[i+1], pow2[i - 8] - 1)
    ]
    return ints * 3  # longer list, but keeps median in the middle


def intsum(L):
    """
    >>> L = get_int_distribution()
    >>> bigint(intsum(L))
    61084913298497804284622382871263
    >>> bigint(sum(L))
    61084913298497804284622382871263

    >>> from random import shuffle
    >>> shuffle(L)
    >>> bigint(intsum(L))
    61084913298497804284622382871263
    """
    cdef uint128_t i, x = 0
    for i in L:
        x += i
    return x


def intxor(L):
    """
    >>> L = get_int_distribution()
    >>> bigint(intxor(L))
    31773794341658093722410838161
    >>> bigint(intxor(L * 2))
    0
    >>> import operator
    >>> from functools import reduce
    >>> bigint(reduce(operator.xor, L))
    31773794341658093722410838161
    >>> bigint(reduce(operator.xor, L * 2))
    0

    >>> from random import shuffle
    >>> shuffle(L)
    >>> bigint(intxor(L))
    31773794341658093722410838161
    >>> bigint(intxor(L * 2))
    0
    """
    cdef uint128_t i, x = 0
    for i in L:
        x ^= i
    return x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/int_float_builtins_as_casts_T400.pyx0000644000175100001770000001701400000000000024566 0ustar00runnerdocker00000000000000# ticket: t400

cimport cython

@cython.test_assert_path_exists("//SingleAssignmentNode/TypecastNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def double_to_short_int(double x):
    """
    >>> double_to_short_int(4.1)
    4
    >>> double_to_short_int(4)
    4
    >>> double_to_short_int('4')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    cdef short r = int(x)
    return r

@cython.test_assert_path_exists("//SingleAssignmentNode/TypecastNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def double_to_pyssizet_int(double x):
    """
    >>> double_to_pyssizet_int(4.1)
    4
    >>> double_to_pyssizet_int(4)
    4
    >>> double_to_pyssizet_int('4')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    cdef Py_ssize_t r = int(x)
    return r

@cython.test_assert_path_exists("//SingleAssignmentNode/TypecastNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def int_to_pyssizet_int(int x):
    """
    >>> int_to_pyssizet_int(4.1)
    4
    >>> int_to_pyssizet_int(4)
    4
    >>> int_to_pyssizet_int('4')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    cdef Py_ssize_t r = int(x)
    return r

## @cython.test_assert_path_exists("//SingleAssignmentNode/TypecastNode")
## @cython.test_fail_if_path_exists("//SimpleCallNode")
## def double_to_pyssizet_float(double x):
##     """
##     >>> double_to_pyssizet_float(4.1)
##     4
##     >>> double_to_pyssizet_float(4)
##     4
##     """
##     cdef Py_ssize_t r = float(x)
##     return r

@cython.test_assert_path_exists("//SingleAssignmentNode/TypecastNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def int_to_short_int(int x):
    """
    >>> int_to_short_int(4)
    4
    >>> int_to_short_int('4')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...integer...
    """
    cdef short r = int(x)
    return r

@cython.test_assert_path_exists("//SingleAssignmentNode/TypecastNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def short_to_float_float(short x):
    """
    >>> short_to_float_float(4)
    4.0
    >>> short_to_float_float('4')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...integer...
    """
    cdef float r = float(x)
    return r

@cython.test_assert_path_exists("//SingleAssignmentNode/TypecastNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def short_to_double_float(short x):
    """
    >>> short_to_double_float(4)
    4.0
    >>> short_to_double_float('4')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...integer...
    """
    cdef double r = float(x)
    return r

@cython.test_assert_path_exists("//SingleAssignmentNode/TypecastNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def short_to_double_int(short x):
    """
    >>> short_to_double_int(4)
    4.0
    >>> short_to_double_int('4')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...integer...
    """
    cdef double r = int(x)
    return r

@cython.test_fail_if_path_exists("//SimpleCallNode")
def float_to_float_float(float x):
    """
    >>> 4.05 < float_to_float_float(4.1) < 4.15
    True
    >>> float_to_float_float(4)
    4.0
    >>> float_to_float_float('4')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    cdef float r = float(x)
    return r

@cython.test_fail_if_path_exists("//SimpleCallNode",
                                 "//SingleAssignmentNode//TypecastNode")
def double_to_double_float(double x):
    """
    >>> 4.05 < double_to_double_float(4.1) < 4.15
    True
    >>> double_to_double_float(4)
    4.0
    >>> double_to_double_float('4')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    cdef double r = float(x)
    return r

# tests that cannot be optimised

@cython.test_fail_if_path_exists("//TypecastNode")
@cython.test_assert_path_exists("//PythonCapiCallNode")
def double_to_py_int(double x):
    """
    >>> double_to_py_int(4.1)
    4
    >>> double_to_py_int(4)
    4
    >>> double_to_py_int('4')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    return int(x)

@cython.test_fail_if_path_exists("//SingleAssignmentNode//TypecastNode")
@cython.test_assert_path_exists("//PythonCapiCallNode")
def double_to_double_int(double x):
    """
    >>> double_to_double_int(4.1)
    4.0
    >>> double_to_double_int(4)
    4.0
    >>> double_to_double_int('4')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    cdef double r = int(x)
    return r


@cython.test_fail_if_path_exists("//SingleAssignmentNode//TypecastNode")
@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
    "//PythonCapiCallNode/PythonCapiFunctionNode/@cname = 'truncf'",
)
def float_to_float_int(float x):
    """
    >>> float_to_float_int(4.1)
    4.0
    >>> float_to_float_int(4)
    4.0
    >>> float_to_float_int('4')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    cdef float r = int(x)
    return r


@cython.test_fail_if_path_exists("//SingleAssignmentNode//TypecastNode")
@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
    "//PythonCapiCallNode/PythonCapiFunctionNode/@cname = 'truncf'",
)
def float_to_double_int(float x):
    """
    >>> float_to_double_int(4.1)
    4.0
    >>> float_to_double_int(4)
    4.0
    >>> float_to_double_int('4')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    cdef double r = int(x)
    return r


@cython.test_fail_if_path_exists("//SingleAssignmentNode//TypecastNode")
@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
    "//PythonCapiCallNode/PythonCapiFunctionNode/@cname = 'trunc'",
)
def double_to_float_int(double x):
    """
    >>> double_to_float_int(4.1)
    4.0
    >>> double_to_float_int(4)
    4.0
    >>> double_to_float_int('4')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    cdef float r = int(x)
    return r


@cython.test_fail_if_path_exists("//SimpleCallNode")
@cython.test_assert_path_exists("//PythonCapiCallNode")
def object_float(x):
    """
    >>> 4.05 < object_float(4.1) < 4.15
    True
    >>> object_float(2**100) == float(2**100)
    True
    >>> object_float(2.5**100) == float(2.5**100)
    True
    >>> object_float(4)
    4.0
    >>> object_float('4')
    4.0
    >>> object_float('4.0')
    4.0
    >>> object_float('4'.encode('ascii'))
    4.0
    >>> object_float('4.0'.encode('ascii'))
    4.0
    """
    return float(x)

@cython.test_fail_if_path_exists("//SimpleCallNode")
@cython.test_assert_path_exists("//PythonCapiCallNode")
def object_int(x):
    """
    >>> object_int(4)
    4
    >>> object_int(2**100) == 2**100 or object_int(2**100)
    True
    >>> object_int(-(2**100)) == -(2**100) or object_int(-(2**100))
    True
    >>> object_int(4.1)
    4
    >>> object_int(4.0)
    4
    >>> object_int('4')
    4
    >>> object_int('4'.encode('ascii'))
    4
    """
    return int(x)


@cython.test_fail_if_path_exists("//SimpleCallNode",
                                 "//CoerceFromPyTypeNode")
def no_args_int_cint():
    """
    >>> no_args_int_cint()
    0
    """
    cdef int x = int()
    return x


@cython.test_fail_if_path_exists("//SimpleCallNode",
                                 "//CoerceFromPyTypeNode")
def no_args_float_cdouble():
    """
    >>> no_args_float_cdouble()
    (0.0, 0.0)
    """
    cdef double xd = float()
    cdef float xf = float()
    return xd, xf
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/int_float_builtins_as_casts_T400_long_double.pyx0000644000175100001770000000074200000000000027137 0ustar00runnerdocker00000000000000# ticket: t400

cimport cython


@cython.test_fail_if_path_exists("//SingleAssignmentNode//TypecastNode")
@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
    "//PythonCapiCallNode/PythonCapiFunctionNode/@cname = '__Pyx_truncl'",
)
def long_double_to_float_int(long double x):
    """
    >>> long_double_to_float_int(4.1)
    4.0
    >>> long_double_to_float_int(-4.1)
    -4.0
    >>> long_double_to_float_int(4)
    4.0
    """
    cdef float r = int(x)
    return r
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/int_literals.pyx0000644000175100001770000001105000000000000020772 0ustar00runnerdocker00000000000000# mode: run
# tag: syntax

from __future__ import absolute_import

cimport cython
from cython cimport typeof

import sys


def valid_underscore_literals():
    """
    >>> valid_underscore_literals()
    """
    # Copied from CPython's test_grammar.py
    assert 0_0_0 == 0
    assert 4_2 == 42
    assert 1_0000_0000 == 100000000
    assert 0b1001_0100 == 0b10010100
    assert 0xffff_ffff == 0xffffffff
    assert 0o5_7_7 == 0o577
    assert 1_00_00.5 == 10000.5
    assert 1e1_0 == 1e10
    assert .1_4 == .14
    assert 1_0 == 1_0L == 1_0LL == 1_0UL == 1_0ULL
    assert typeof(1_0ULL) == "unsigned long long"


@cython.test_assert_path_exists(
    '//IntNode[@longness = "LL"]',
    '//IntNode[@longness = "L"]',
    )
@cython.test_fail_if_path_exists('//IntNode[@longness = ""]')
def c_longs():
    """
    >>> c_longs() == (1, 1, -1, 18446744073709551615)  or  c_longs()
    True
    """
    cdef long a = 1L
    cdef unsigned long ua = 1UL
    cdef long long aa = 0xFFFFFFFFFFFFFFFFLL
    cdef unsigned long long uaa = 0xFFFFFFFFFFFFFFFFULL
    return a, ua, int(aa), uaa

@cython.test_assert_path_exists(
    '//IntNode[@longness = "LL"]',
    '//IntNode[@longness = "L"]',
    )
@cython.test_fail_if_path_exists('//IntNode[@longness = ""]')
def negative_c_longs():
    """
    >>> negative_c_longs() == (-1, -9223285636854775809)  or  negative_c_longs()
    True
    """
    cdef long a = -1L
    cdef long long aa = -9223285636854775809LL
    return a, aa

def py_longs():
    """
    >>> py_longs() == (
    ...     1, 1, 100000000000000000000000000000000, -100000000000000000000000000000000
    ...     )  or  py_longs()
    True
    """
    return 1, 1L, 100000000000000000000000000000000, -100000000000000000000000000000000

@cython.test_fail_if_path_exists("//NumBinopNode", "//IntBinopNode")
@cython.test_assert_path_exists("//ReturnStatNode/IntNode")
def py_huge_calculated_long():
    """
    >>> py_huge_calculated_long() == (
    ...     1606938044258990275541962092341162602522202993782792835301376
    ...     )  or  py_huge_calculated_long()
    True
    """
    return 1 << 200

@cython.test_fail_if_path_exists("//NumBinopNode", "//IntBinopNode")
@cython.test_assert_path_exists("//ReturnStatNode/IntNode")
def py_huge_computation_small_result():
    """
    >>> py_huge_computation_small_result()
    2
    """
    return (1 << 200) >> 199

@cython.test_fail_if_path_exists("//NumBinopNode", "//IntBinopNode")
#@cython.test_assert_path_exists("//ReturnStatNode/IntNode")
def py_huge_computation_small_result_neg():
    """
    >>> py_huge_computation_small_result_neg() == (
    ...    -2535301200456458802993406410752, -2535301200456458802993406410752
    ...    )  or  py_huge_computation_small_result_neg()
    True
    """
    return -(2 ** 101), (-2) ** 101

def large_literal():
    """
    >>> type(large_literal()) is int
    True
    """
    if sys.version_info[0] >= 3 or sys.maxint > 0xFFFFFFFFFFFF:
        return 0xFFFFFFFFFFFF
    else:
        return 0xFFFFFFF

def c_long_types():
    """
    >>> c_long_types()
    long
    long
    long long
    unsigned long
    unsigned long
    unsigned long long
    """
    print typeof(1)
    print typeof(1L)
    print typeof(1LL)
    print typeof(1U)
    print typeof(1UL)
    print typeof(1ULL)

# different ways to write an integer in Python

def c_oct():
    """
    >>> c_oct()
    (1, -17, 63)
    """
    cdef int a = 0o01
    cdef int b = -0o21
    cdef int c = 0o77
    return a,b,c

def c_oct_py2_legacy():
    """
    >>> c_oct_py2_legacy()
    (1, -17, 63)
    """
    cdef int a = 001
    cdef int b = -021
    cdef int c = 077
    return a,b,c

def py_oct():
    """
    >>> py_oct()
    (1, -17, 63)
    """
    return 0o01, -0o21, 0o77

def py_oct_py2_legacy():
    """
    >>> py_oct_py2_legacy()
    (1, -17, 63)
    """
    return 001, -021, 077

def c_hex():
    """
    >>> c_hex()
    (1, -33, 255)
    """
    cdef int a = 0x01
    cdef int b = -0x21
    cdef int c = 0xFF
    return a,b,c

def py_hex():
    """
    >>> py_hex()
    (1, -33, 255)
    """
    return 0x01, -0x21, 0xFF

def c_bin():
    """
    >>> c_bin()
    (1, -2, 15)
    """
    cdef int a = 0b01
    cdef int b = -0b10
    cdef int c = 0b1111
    return a,b,c

def py_bin():
    """
    >>> py_bin()
    (1, -2, 15)
    """
    return 0b01, -0b10, 0b1111

def big_value():
    """
    >>> big_value() == (10**10000)
    True
    """
    # Not quite a literal, but Cython expands the binop and inserts the literal
    # into the C source. Which means it must be converted to a hex string to avoid
    # hitting Python's integer conversion limits
    return 10**10000
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/intern_T431.pyx0000644000175100001770000000062500000000000020321 0ustar00runnerdocker00000000000000# ticket: t431

__doc__ = u"""
>>> s == s_interned
True
>>> s == s_interned_dynamic
True
>>> s == 'abc' == s_interned == s_interned_dynamic
True
"""

import sys
if sys.version_info[0] < 3:
    __doc__ += u"""
>>> intern(s) is s_interned
True
>>> intern('abc') is s_interned
True
>>> intern('abc') is s_interned_dynamic
True
"""

s = 'abc'

s_interned = intern(s)

s_interned_dynamic = intern('a'+'b'+'c')
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/internal_cdef_class.pyx0000644000175100001770000000076100000000000022272 0ustar00runnerdocker00000000000000
cimport cython


@cython.internal
cdef class InternalType:
    """
    NOTE: this doesn't fail because it is never tested !
    >>> i = InternalType
    """

cdef class PublicType:
    """
    >>> p = PublicType
    """

def test():
    """
    >>> p,i = test()

    >>> p = PublicType

    >>> i = InternalType         # doctest: +ELLIPSIS
    Traceback (most recent call last):
    NameError: ...name 'InternalType' is not defined
    """
    p = PublicType
    i = InternalType
    return p,i
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/ipow_crash_T562.pyx0000644000175100001770000000056100000000000021164 0ustar00runnerdocker00000000000000# ticket: t562

class IPOW:
    """
    >>> IPOW().__ipow__('a')
    a
    >>> x = IPOW()
    >>> x **= 'z'
    z
    """
    def __ipow__(self, other):
        print ("%s" % other)

cdef class CrashIPOW:
    """
    >>> CrashIPOW().__ipow__('a')
    a
    >>> x = CrashIPOW()
    >>> x **= 'z'
    z
    """
    def __ipow__(self, other):
        print ("%s" % other)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/ishimoto2.pyx0000644000175100001770000000026300000000000020222 0ustar00runnerdocker00000000000000
class C:
    """
    >>> C().xxx(5)
    5
    >>> C().xxx()
    'a b'
    >>> C().xxx(42)
    42
    >>> C().xxx()
    'a b'
    """
    def xxx(self, p="a b"):
        return p
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/ishimoto3.pyx0000644000175100001770000000036400000000000020225 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> c1 = C1()
    >>> c2 = C2(c1)
    >>> c1 is c2.getc1()
    True
"""

cdef class C1:
    pass

cdef class C2:
    cdef C1 c1

    def __init__(self, arg):
        self.c1 = arg

    def getc1(self):
        return self.c1
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/isinstance.pyx0000644000175100001770000001274300000000000020453 0ustar00runnerdocker00000000000000
cimport cython
from cpython.bool cimport bool

cdef class A:
    pass


a_as_obj = A


@cython.test_assert_path_exists('//SimpleCallNode//SimpleCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode//PythonCapiCallNode',
                                 '//PythonCapiCallNode//SimpleCallNode')
def test_non_optimised():
    """
    >>> test_non_optimised()
    True
    """
    # Non-optimized
    cdef object foo = A
    assert isinstance(A(), foo)
    return True


@cython.test_assert_path_exists('//PythonCapiCallNode',
                                '//PythonCapiCallNode//SimpleCallNode',
                                '//PythonCapiFunctionNode[@cname = "PyType_Check"]',
                                '//PythonCapiFunctionNode[@cname = "PyInt_Check"]',
                                '//PythonCapiFunctionNode[@cname = "PyFloat_Check"]',
                                '//PythonCapiFunctionNode[@cname = "PyBytes_Check"]',
                                '//PythonCapiFunctionNode[@cname = "PyUnicode_Check"]',
                                '//PythonCapiFunctionNode[@cname = "PyTuple_Check"]',
                                '//PythonCapiFunctionNode[@cname = "PyList_Check"]',
                                '//PythonCapiFunctionNode[@cname = "PyDict_Check"]',
                                '//PythonCapiFunctionNode[@cname = "PySet_Check"]',
                                '//PythonCapiFunctionNode[@cname = "PySlice_Check"]',
                                '//PythonCapiFunctionNode[@cname = "PyComplex_Check"]')
@cython.test_fail_if_path_exists('//SimpleCallNode//SimpleCallNode',
                                 '//SimpleCallNode//PythonCapiCallNode')
def test_optimised():
    """
    >>> test_optimised()
    True
    """
    # Optimized tests.
    cdef object new_type = type('a',(),{})
    assert isinstance(type('a',(),{}), type)
    assert isinstance(new_type, type)

    cdef object boolval = True
    assert isinstance(boolval, bool)
    assert isinstance(True, bool)

    cdef object intval = int()
    assert isinstance(intval, int)
    assert isinstance(int(), int)

    cdef object longval = long()
    assert isinstance(longval, long)
    assert isinstance(long(), long)

    cdef object floatval = float()
    assert isinstance(floatval, float)
    assert isinstance(float(), float)

    cdef object bytesval = bytes()
    assert isinstance(bytesval, bytes)
    assert isinstance(bytes(), bytes)

    cdef object strval = str()
    assert isinstance(strval, str)
    assert isinstance(str(), str)

    cdef object unicodeval = unicode()
    assert isinstance(unicodeval, unicode)
    assert isinstance(unicode(), unicode)

    cdef object tupleval = tuple()
    assert isinstance(tupleval, tuple)
    assert isinstance(tuple(), tuple)

    cdef object listval = list()
    assert isinstance(listval, list)
    assert isinstance(list(), list)

    cdef object dictval = dict()
    assert isinstance(dictval, dict)
    assert isinstance(dict(), dict)

    cdef object setval = set()
    assert isinstance(setval, set)
    assert isinstance(set(), set)

    cdef object sliceval = slice(0)
    assert isinstance(sliceval, slice)
    assert isinstance(slice(0), slice)

    cdef object complexval = complex()
    assert isinstance(complexval, complex)
    assert isinstance(complex(), complex)

    assert not isinstance(u"foo", int)
    assert isinstance(A, type)
    assert isinstance(A(), A)
    cdef type typed_type = A
    assert isinstance(A(), typed_type)
    cdef object untyped_type = A
    assert isinstance(A(), untyped_type)
    return True


@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode//SimpleCallNode',
                                 '//SimpleCallNode//PythonCapiCallNode',
                                 '//TupleNode//NameNode')
def test_optimised_tuple():
    """
    >>> test_optimised_tuple()
    True
    """
    assert isinstance(int(),   (int, long, float, bytes, str, unicode, tuple, list, dict, set, slice, type, A))
    assert isinstance(list(),  (int, long, float, bytes, str, unicode, tuple, list, dict, set, slice, type, A))
    assert isinstance(A(),  (int, long, float, bytes, str, unicode, tuple, list, dict, set, slice, type, A))
    assert isinstance(A(),  (int, long, float, bytes, str, unicode, tuple, list, dict, set, slice, type, A, a_as_obj))
    assert isinstance(A(),  (int, long, float, bytes, str, unicode, tuple, list, dict, set, slice, type, a_as_obj, A))
    assert isinstance(A(),  (int, long, float, bytes, str, unicode, a_as_obj, tuple, list, dict, set, slice, type, A))
    assert isinstance(0, (int, long))
    assert not isinstance(u"xyz", (int, long))
    return True


def test_custom():
    """
    >>> test_custom()
    True
    """
    assert isinstance(A(), A)
    return True

cdef class B:
    pass

cdef class C:
    pass


@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode//SimpleCallNode',
                                 '//SimpleCallNode//PythonCapiCallNode',
                                 '//TupleNode//NameNode')
def test_custom_tuple(obj):
    """
    >>> test_custom_tuple(A())
    True
    >>> test_custom_tuple(B())
    True
    >>> test_custom_tuple(C())
    False
    """
    return isinstance(obj, (A,B))


def test_nested(x):
    """
    >>> test_nested(1)
    True
    >>> test_nested(1.5)
    True
    >>> test_nested("a")
    False
    """
    cdef object a = (x, None)
    if isinstance(a[0], (int, float)):
        return True
    return False
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/isnonebool.pyx0000644000175100001770000000123400000000000020453 0ustar00runnerdocker00000000000000def test_and(a,b):
    """
    >>> test_and(None, None)
    True
    >>> test_and(None, 1)
    False
    >>> test_and(1, None)
    False
    """
    return a is None and b is None

def test_more(a,b):
    """
    >>> test_more(None, None)
    True
    >>> test_more(None, 1)
    True
    >>> test_more(1, None)
    False
    >>> test_more(None, 0)
    False
    """
    return a is None and (b is None or b == 1)

def test_more_c(a,b):
    """
    >>> test_more_c(None, None)
    True
    >>> test_more_c(None, 1)
    True
    >>> test_more_c(1, None)
    False
    >>> test_more_c(None, 0)
    False
    """
    return (a is None or 1 == 2) and (b is None or b == 1)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/isnot.pyx0000644000175100001770000000242100000000000017437 0ustar00runnerdocker00000000000000# mode: run
# tag: is_not

cimport cython

# Use a single global object for identity checks.
# PyPy can optimise away integer objects, for example, and may fail the 'is' test.
obj = object()


@cython.test_fail_if_path_exists('//NotNode')
def is_not(a, b):
    """
    >>> is_not(1, 2)
    True
    >>> x = obj
    >>> is_not(x, x)
    False
    """
    return a is not b


@cython.test_fail_if_path_exists('//NotNode')
def not_is_not(a, b):
    """
    >>> not_is_not(1, 2)
    False
    >>> x = obj
    >>> not_is_not(x, x)
    True
    """
    return not a is not b


@cython.test_fail_if_path_exists('//NotNode')
def not_is(a, b):
    """
    >>> not_is(1, 2)
    True
    >>> x = obj
    >>> not_is(x, x)
    False
    """
    return not a is b


@cython.test_fail_if_path_exists('//NotNode')
def is_not_None(a):
    """
    >>> is_not_None(1)
    True
    >>> is_not_None(None)
    False
    """
    return a is not None


@cython.test_fail_if_path_exists('//NotNode')
def not_is_not_None(a):
    """
    >>> not_is_not_None(1)
    False
    >>> not_is_not_None(None)
    True
    """
    return not a is not None


@cython.test_fail_if_path_exists('//NotNode')
def not_is_None(a):
    """
    >>> not_is_None(1)
    True
    >>> not_is_None(None)
    False
    """
    return not a is None
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/isolated_limited_api_tests.srctree0000644000175100001770000000351300000000000024523 0ustar00runnerdocker00000000000000# mode: run
# tag: limited-api

# This is a bare minimum test to test compilation of the limited
# API with the Py_LIMITED_API macro defined, with an example that's
# known and working. It should be dropped once the limited API is
# better tested

PYTHON setup.py build_ext --inplace
PYTHON run.py


##################### setup.py ################################

from setuptools import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("limited.pyx"),
)

##################### run.py ##################################

import limited

limited.fib(11)

assert limited.lsum(list(range(10))) == 90
assert limited.lsum(tuple(range(10))) == 90
assert limited.lsum(iter(range(10))) == 45

try:
    limited.raises()
except RuntimeError:
    pass

limited.C()
limited.D()
limited.E()

assert limited.decode(b'a', bytearray(b'b')) == "ab"

assert limited.cast_float(1) == 1.0
assert limited.cast_float("2.0") == 2.0
assert limited.cast_float(bytearray(b"3")) == 3.0


##################### limited.pyx #############################

# distutils: extra_compile_args = -DCYTHON_LIMITED_API=1 -DPy_LIMITED_API=0x030700f0

import cython

@cython.binding(False)
def fib(int n):
    cdef int a, b
    a, b = 0, 1
    while b < n:
        a, b = b, a + b
    return b

def lsum(values):
    cdef long result = 0
    for value in values:
        result += value
    if type(values) is list:
        for value in reversed(values):
            result += value
    elif type(values) is tuple:
        for value in reversed(values):
            result += value
    return result

@cython.binding(False)
def raises():
    raise RuntimeError()

def decode(bytes b, bytearray ba):
    return b.decode("utf-8") + ba.decode("utf-8")

def cast_float(object o):
    return float(o)

class C:
    pass

cdef class D:
    pass

cdef class E(D):
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/iter.pyx0000644000175100001770000000101700000000000017246 0ustar00runnerdocker00000000000000
def call_iter1(x):
    """
    >>> [ i for i in iter([1,2,3]) ]
    [1, 2, 3]
    >>> [ i for i in call_iter1([1,2,3]) ]
    [1, 2, 3]
    """
    return iter(x)

class Ints(object):
    def __init__(self):
        self.i = 0
    def __call__(self):
        self.i += 1
        if self.i > 10:
            raise ValueError
        return self.i

def call_iter2(x, sentinel):
    """
    >>> [ i for i in iter(Ints(), 3) ]
    [1, 2]
    >>> [ i for i in call_iter2(Ints(), 3) ]
    [1, 2]
    """
    return iter(x, sentinel)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/iteratorexception.pyx0000644000175100001770000000061300000000000022054 0ustar00runnerdocker00000000000000class IteratorAndIterateable:
    def next(self):
        raise ValueError
    def __next__(self):
        raise ValueError
    def __iter__(self):
        return self

def f():
    """
    >>> f()
    """
    try:
        for x in IteratorAndIterateable():
            pass
        assert False, u"Should not reach this point, iterator has thrown exception"
    except ValueError:
        pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/iterdict.pyx0000644000175100001770000003271100000000000020117 0ustar00runnerdocker00000000000000
cimport cython

dict_size = 4
d = dict(zip(range(10,dict_size+10), range(dict_size)))


def dict_iteritems(dict d):
    """
    >>> it = dict_iteritems(d)
    >>> type(it) is list
    False
    >>> sorted(it)
    [(10, 0), (11, 1), (12, 2), (13, 3)]
    """
    return d.iteritems()


def dict_iterkeys(dict d):
    """
    >>> it = dict_iterkeys(d)
    >>> type(it) is list
    False
    >>> sorted(it)
    [10, 11, 12, 13]
    """
    return d.iterkeys()


def dict_itervalues(dict d):
    """
    >>> it = dict_itervalues(d)
    >>> type(it) is list
    False
    >>> sorted(it)
    [0, 1, 2, 3]
    """
    return d.itervalues()


@cython.test_fail_if_path_exists(
    "//WhileStatNode")
def items(dict d):
    """
    >>> items(d)
    [(10, 0), (11, 1), (12, 2), (13, 3)]
    """
    l = []
    for k,v in d.items():
        l.append((k,v))
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def iteritems(dict d):
    """
    >>> iteritems(d)
    [(10, 0), (11, 1), (12, 2), (13, 3)]
    >>> iteritems({})
    []
    """
    l = []
    for k,v in d.iteritems():
        l.append((k,v))
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def optimistic_iteritems(d):
    """
    >>> optimistic_iteritems(d)
    [(10, 0), (11, 1), (12, 2), (13, 3)]
    >>> optimistic_iteritems({})
    []
    >>> class mydict(object):
    ...     def __init__(self, t): self.t = t
    ...     def iteritems(self): return self.t(d.items())
    >>> optimistic_iteritems(mydict(list))
    [(10, 0), (11, 1), (12, 2), (13, 3)]
    >>> optimistic_iteritems(mydict(tuple))
    [(10, 0), (11, 1), (12, 2), (13, 3)]
    >>> optimistic_iteritems(mydict(iter))
    [(10, 0), (11, 1), (12, 2), (13, 3)]
    """
    l = []
    for k,v in d.iteritems():
        l.append((k,v))
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def iteritems_dict():
    """
    >>> iteritems_dict()
    [(11, 1), (12, 2), (13, 3)]
    """
    l = []
    for k,v in {11 : 1, 12 : 2, 13 : 3}.iteritems():
        l.append((k,v))
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def iteritems_int(dict d):
    """
    >>> iteritems_int(d)
    [(10, 0), (11, 1), (12, 2), (13, 3)]
    >>> iteritems_int({})
    []
    >>> iteritems_int({'a': 1})
    Traceback (most recent call last):
    TypeError: an integer is required
    >>> iteritems_int({1: 'b'})
    Traceback (most recent call last):
    TypeError: an integer is required
    >>> iteritems_int({'a': 'b'})
    Traceback (most recent call last):
    TypeError: an integer is required
    """
    cdef int k,v
    l = []
    for k,v in d.iteritems():
        l.append((k,v))
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def optimistic_iteritems_int(d):
    """
    >>> optimistic_iteritems_int(d)
    [(10, 0), (11, 1), (12, 2), (13, 3)]
    >>> optimistic_iteritems_int({})
    []
    >>> class mydict(object):
    ...     def __init__(self, t): self.t = t
    ...     def iteritems(self): return self.t(d.items())
    >>> optimistic_iteritems_int(mydict(list))
    [(10, 0), (11, 1), (12, 2), (13, 3)]
    >>> optimistic_iteritems_int(mydict(tuple))
    [(10, 0), (11, 1), (12, 2), (13, 3)]
    >>> optimistic_iteritems_int(mydict(iter))
    [(10, 0), (11, 1), (12, 2), (13, 3)]

    >>> optimistic_iteritems_int({'a': 1})
    Traceback (most recent call last):
    TypeError: an integer is required
    >>> optimistic_iteritems_int({1: 'b'})
    Traceback (most recent call last):
    TypeError: an integer is required
    >>> optimistic_iteritems_int({'a': 'b'})
    Traceback (most recent call last):
    TypeError: an integer is required
    """
    cdef int k,v
    l = []
    for k,v in d.iteritems():
        l.append((k,v))
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def iteritems_tuple(dict d):
    """
    >>> iteritems_tuple(d)
    [(10, 0), (11, 1), (12, 2), (13, 3)]
    >>> iteritems_tuple({})
    []
    """
    l = []
    for t in d.iteritems():
        l.append(t)
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def iteritems_listcomp(dict d):
    cdef list l = [(k,v) for k,v in d.iteritems()]
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def iterkeys(dict d):
    """
    >>> iterkeys(d)
    [10, 11, 12, 13]
    >>> iterkeys({})
    []
    """
    l = []
    for k in d.iterkeys():
        l.append(k)
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def optimistic_iterkeys(d):
    """
    >>> optimistic_iterkeys(d)
    [10, 11, 12, 13]
    >>> optimistic_iterkeys({})
    []
    >>> class mydict(object):
    ...     def __init__(self, t): self.t = t
    ...     def iterkeys(self): return self.t(d)
    >>> optimistic_iterkeys(mydict(lambda x:x))
    [10, 11, 12, 13]
    >>> optimistic_iterkeys(mydict(lambda x:x.keys()))
    [10, 11, 12, 13]
    >>> optimistic_iterkeys(mydict(list))
    [10, 11, 12, 13]
    >>> optimistic_iterkeys(mydict(tuple))
    [10, 11, 12, 13]
    >>> optimistic_iterkeys(mydict(iter))
    [10, 11, 12, 13]
    """
    l = []
    for k in d.iterkeys():
        l.append(k)
    l.sort()
    return l

@cython.test_fail_if_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def optimistic_iterkeys_argerror(d):
    """
    >>> try: optimistic_iterkeys_argerror(d)
    ... except (TypeError, AttributeError): pass
    """
    for k in d.iterkeys(1):
        print k

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def iterkeys_int(dict d):
    """
    >>> iterkeys_int(d)
    [10, 11, 12, 13]
    >>> iterkeys_int({})
    []
    >>> iterkeys_int({'a': 'b'})
    Traceback (most recent call last):
    TypeError: an integer is required
    """
    cdef int k
    l = []
    for k in d.iterkeys():
        l.append(k)
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def iterdict(dict d):
    """
    >>> iterdict(d)
    [10, 11, 12, 13]
    >>> iterdict({})
    []
    """
    l = []
    for k in d:
        l.append(k)
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def iterdict_int(dict d):
    """
    >>> iterdict_int(d)
    [10, 11, 12, 13]
    >>> iterdict_int({})
    []
    >>> iterdict_int({'a': 'b'})
    Traceback (most recent call last):
    TypeError: an integer is required
    """
    cdef int k
    l = []
    for k in d:
        l.append(k)
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def iterdict_reassign(dict d):
    """
    >>> iterdict_reassign(d)
    [10, 11, 12, 13]
    >>> iterdict_reassign({})
    []
    """
    cdef dict d_new = {}
    l = []
    for k in d:
        d = d_new
        l.append(k)
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def iterdict_listcomp(dict d):
    """
    >>> iterdict_listcomp(d)
    [10, 11, 12, 13]
    >>> iterdict_listcomp({})
    []
    """
    cdef list l = [k for k in d]
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def itervalues(dict d):
    """
    >>> itervalues(d)
    [0, 1, 2, 3]
    >>> itervalues({})
    []
    """
    l = []
    for v in d.itervalues():
        l.append(v)
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def optimistic_itervalues(d):
    """
    >>> optimistic_itervalues(d)
    [0, 1, 2, 3]
    >>> optimistic_itervalues({})
    []
    >>> class mydict(object):
    ...     def __init__(self, t): self.t = t
    ...     def itervalues(self): return self.t(d.values())
    >>> optimistic_itervalues(mydict(lambda x:x))
    [0, 1, 2, 3]
    >>> optimistic_itervalues(mydict(list))
    [0, 1, 2, 3]
    >>> optimistic_itervalues(mydict(tuple))
    [0, 1, 2, 3]
    >>> optimistic_itervalues(mydict(iter))
    [0, 1, 2, 3]
    """
    l = []
    for v in d.itervalues():
        l.append(v)
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def itervalues_int(dict d):
    """
    >>> itervalues_int(d)
    [0, 1, 2, 3]
    >>> itervalues_int({})
    []
    >>> itervalues_int({'a': 'b'})
    Traceback (most recent call last):
    TypeError: an integer is required
    """
    cdef int v
    l = []
    for v in d.itervalues():
        l.append(v)
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def itervalues_listcomp(dict d):
    """
    >>> itervalues_listcomp(d)
    [0, 1, 2, 3]
    >>> itervalues_listcomp({})
    []
    """
    cdef list l = [v for v in d.itervalues()]
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def itervalues_kwargs(**d):
    """
    >>> itervalues_kwargs(a=1, b=2, c=3, d=4)
    [1, 2, 3, 4]
    >>> itervalues_kwargs()
    []
    """
    cdef list l = [v for v in d.itervalues()]
    l.sort()
    return l

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def iterdict_change_size(dict d):
    """
    >>> count, i = 0, -1
    >>> d = {1:2, 10:20}
    >>> for i in d:
    ...     d[i+1] = 5
    ...     count += 1
    ...     if count > 5:
    ...         break # safety
    Traceback (most recent call last):
    RuntimeError: dictionary changed size during iteration

    >>> iterdict_change_size({1:2, 10:20})
    Traceback (most recent call last):
    RuntimeError: dictionary changed size during iteration
    >>> print( iterdict_change_size({}) )
    DONE
    """
    cdef int count = 0
    i = -1
    for i in d:
        d[i+1] = 5
        count += 1
        if count > 5:
            break # safety
    return "DONE"

@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def optimistic_iterdict_change_size(d):
    """
    >>> count, i = 0, -1
    >>> d = {1:2, 10:20}
    >>> for i in d:
    ...     d[i+1] = 5
    ...     count += 1
    ...     if count > 5:
    ...         break # safety
    Traceback (most recent call last):
    RuntimeError: dictionary changed size during iteration

    >>> optimistic_iterdict_change_size({1:2, 10:20})
    Traceback (most recent call last):
    RuntimeError: dictionary changed size during iteration
    >>> print( optimistic_iterdict_change_size({}) )
    DONE
    >>> class mydict(object):
    ...     _d = {1:2, 10:20}
    ...     def iterkeys(self): return self._d
    ...     def __setitem__(self, key, value): self._d[key] = value
    >>> optimistic_iterdict_change_size(mydict())
    Traceback (most recent call last):
    RuntimeError: dictionary changed size during iteration
    """
    cdef int count = 0
    i = -1
    for i in d.iterkeys():
        d[i+1] = 5
        count += 1
        if count > 5:
            break # safety
    return "DONE"


@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode")
def values_of_expression(**kwargs):
    """
    >>> sorted(values_of_expression(a=3, b=4))
    [3, 4]
    """
    # this can be optimised even in Py2
    return [ arg for arg in dict(kwargs.items()).values() ]


def items_of_expression(*args, **kwargs):
    """
    >>> sorted(items_of_expression(a=3, b=4))
    [('a', 3), ('b', 4)]

    >>> sorted(items_of_expression([('a', 3)], b=4))
    [('a', 3), ('b', 4)]
    """
    return [item for item in dict(*args, **kwargs).items()]


def iteritems_of_expression(*args, **kwargs):
    """
    >>> sorted(iteritems_of_expression(a=3, b=4))
    [('a', 3), ('b', 4)]

    >>> sorted(iteritems_of_expression([('a', 3)], b=4))
    [('a', 3), ('b', 4)]
    """
    return [item for item in dict(*args, **kwargs).iteritems()]


def for_in_items_of_expression(*args, **kwargs):
    """
    >>> sorted(for_in_items_of_expression(a=3, b=4))
    [('a', 3), ('b', 4)]

    >>> sorted(for_in_items_of_expression([('a', 3)], b=4))
    [('a', 3), ('b', 4)]
    """
    result = []
    for k, v in dict(*args, **kwargs).items():
        result.append((k, v))
    return result


def for_in_iteritems_of_expression(*args, **kwargs):
    """
    >>> sorted(for_in_iteritems_of_expression(a=3, b=4))
    [('a', 3), ('b', 4)]

    >>> sorted(for_in_iteritems_of_expression([('a', 3)], b=4))
    [('a', 3), ('b', 4)]
    """
    result = []
    for k, v in dict(*args, **kwargs).iteritems():
        result.append((k, v))
    return result


cdef class NotADict:
    """
    >>> NotADict().listvalues()  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    ...
    TypeError: descriptor 'values' for 'mappingproxy' objects doesn't apply to a 'iterdict.NotADict' object
    """
    cdef long v
    def __cinit__(self):
        self.v = 1
    itervalues = type(object.__dict__).values

    def listvalues(self):
        return [v for v in self.itervalues()]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/jarausch1.pyx0000644000175100001770000000043000000000000020162 0ustar00runnerdocker00000000000000__doc__ = u"""
   >>> b == br'\\\\'
   True
   >>> s ==  r'\\\\'
   True
   >>> u == ur'\\\\'
   True
"""

import sys
if sys.version_info[0] < 3:
    __doc__ = __doc__.replace(u" br'", u" r'")
else:
    __doc__ = __doc__.replace(u" ur'", u" r'")

b = br'\\'
s =  r'\\'
u = ur'\\'
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/king1.pyx0000644000175100001770000000051500000000000017316 0ustar00runnerdocker00000000000000DEF USTUFF = u"Spam"

def uf():
    """
    >>> uf()
    It works!
    """
    IF USTUFF == u"Spam":
        print "It works!"
    ELSE:
        print "Doesn't work"

DEF BSTUFF = b"Spam"

def bf():
    """
    >>> bf()
    It works!
    """
    IF BSTUFF == b"Spam":
        print "It works!"
    ELSE:
        print "Doesn't work"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/knuth_man_or_boy_test.pyx0000644000175100001770000000245100000000000022702 0ustar00runnerdocker00000000000000# mode: run
# tag: closures

# Cython version of Knuth's "man or boy" test -- "It separates the man
# Algol 60 compilers from the boy Algol 60 compilers." Here's the
# original (from wikipedia):
#
# begin
#   real procedure A (k, x1, x2, x3, x4, x5);
#   value k; integer k;
#   begin
#     real procedure B;
#     begin k:= k - 1;
#           B:= A := A (k, B, x1, x2, x3, x4);
#     end;
#     if k <= 0 then A:= x4 + x5 else B;
#   end;
#   outreal (A (10, 1, -1, -1, 1, 0));
# end;
#
# and a table of values:
#
#   k           A
#   0           1
#   1           0
#   2   	-2
#   3   	0
#   4   	1
#   5   	0
#   6   	1
#   7   	-1
#   8   	-10
#   9   	-30
#   10   	-67
#
# Past 10 or so, we blow the C stack -- can't just set a higher recursion limit
# to get around that one.
#

def compute(val):
    if isinstance(val, int):
        return val
    else:
        return val()

def a(in_k, x1, x2, x3, x4, x5):
    """
    >>> import sys
    >>> old_limit = sys.getrecursionlimit()
    >>> sys.setrecursionlimit(1350 if not getattr(sys, 'pypy_version_info', None) else 2700)

    >>> a(10, 1, -1, -1, 1, 0)
    -67

    >>> sys.setrecursionlimit(old_limit)
    """
    k = [in_k]
    def b():
        k[0] -= 1
        return a(k[0], b, x1, x2, x3, x4)
    return compute(x4) + compute(x5) if k[0] <= 0 else b()

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/kostyrka.pyx0000644000175100001770000000020100000000000020144 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> t = TEST()
    >>> 1 in t
    True
"""

cdef class TEST:
    def __contains__(self, x):
        return 42
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/kostyrka2.pyx0000644000175100001770000000013500000000000020234 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> x = X()
    >>> x.slots
    ['']
"""

class X:
        slots = ["", ]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/kwargproblems.pyx0000644000175100001770000000057700000000000021174 0ustar00runnerdocker00000000000000
def test(**kw):
    """
    >>> d = {1 : 2}
    >>> test(**d)       # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...keywords must be strings...
    >>> d
    {1: 2}
    >>> d = {}
    >>> test(**d)
    {'arg': 3}
    >>> d
    {}
    >>> d = {'arg' : 2}
    >>> test(**d)
    {'arg': 3}
    >>> d
    {'arg': 2}
    """
    kw['arg'] = 3
    return kw
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/kwargs_passthrough.pyx0000644000175100001770000001203700000000000022234 0ustar00runnerdocker00000000000000import cython

#@cython.test_fail_if_path_exists('//MergedDictNode')
def wrap_passthrough(f):
    """
    >>> def f(a=1): return a
    >>> wrapped = wrap_passthrough(f)
    >>> wrapped(1)
    CALLED
    1
    >>> wrapped(a=2)
    CALLED
    2
    """
    def wrapper(*args, **kwargs):
        print("CALLED")
        return f(*args, **kwargs)
    return wrapper


@cython.test_fail_if_path_exists('//MergedDictNode')
def unused(*args, **kwargs):
    """
    >>> unused()
    ()
    >>> unused(1, 2)
    (1, 2)
    """
    return args


@cython.test_fail_if_path_exists('//MergedDictNode')
def used_in_closure(**kwargs):
    """
    >>> used_in_closure()
    >>> d = {}
    >>> used_in_closure(**d)
    >>> d  # must not be modified
    {}
    """
    def func():
        kwargs['test'] = 1
    return func()


@cython.test_fail_if_path_exists('//MergedDictNode')
def modify_in_closure(**kwargs):
    """
    >>> func = modify_in_closure()
    >>> func()

    >>> d = {}
    >>> func = modify_in_closure(**d)
    >>> func()
    >>> d  # must not be modified
    {}
    """
    def func():
        kwargs['test'] = 1
    return func


@cython.test_assert_path_exists('//MergedDictNode')
def wrap_passthrough_more(f):
    """
    >>> def f(a=1, test=2):
    ...     return a, test
    >>> wrapped = wrap_passthrough_more(f)
    >>> wrapped(1)
    CALLED
    (1, 1)
    >>> wrapped(a=2)
    CALLED
    (2, 1)
    """
    def wrapper(*args, **kwargs):
        print("CALLED")
        return f(*args, test=1, **kwargs)
    return wrapper


#@cython.test_fail_if_path_exists('//MergedDictNode')
def wrap_passthrough2(f):
    """
    >>> def f(a=1): return a
    >>> wrapped = wrap_passthrough2(f)
    >>> wrapped(1)
    CALLED
    1
    >>> wrapped(a=2)
    CALLED
    2
    """
    def wrapper(*args, **kwargs):
        print("CALLED")
        f(*args, **kwargs)
        return f(*args, **kwargs)
    return wrapper


#@cython.test_fail_if_path_exists('//MergedDictNode')
def wrap_modify(f):
    """
    >>> def f(a=1, test=2):
    ...     return a, test

    >>> wrapped = wrap_modify(f)
    >>> wrapped(1)
    CALLED
    (1, 1)
    >>> wrapped(a=2)
    CALLED
    (2, 1)
    >>> wrapped(a=2, test=3)
    CALLED
    (2, 1)
    """
    def wrapper(*args, **kwargs):
        print("CALLED")
        kwargs['test'] = 1
        return f(*args, **kwargs)
    return wrapper


#@cython.test_fail_if_path_exists('//MergedDictNode')
def wrap_modify_mix(f):
    """
    >>> def f(a=1, test=2):
    ...     return a, test

    >>> wrapped = wrap_modify_mix(f)
    >>> wrapped(1)
    CALLED
    (1, 1)
    >>> wrapped(a=2)
    CALLED
    (2, 1)
    >>> wrapped(a=2, test=3)
    CALLED
    (2, 1)

    >>> def py_modify(**kwargs):
    ...     print(sorted(kwargs.items()))
    ...     kwargs['new'] = len(kwargs)
    ...     return kwargs

    >>> wrapped_modify = wrap_modify_mix(py_modify)
    >>> sorted(wrapped_modify(a=1).items())
    CALLED
    [('a', 1)]
    [('a', 1), ('test', 1)]
    [('a', 1), ('new', 2), ('test', 1)]
    """
    def wrapper(*args, **kwargs):
        print("CALLED")
        f(*args, **kwargs)
        kwargs['test'] = 1
        return f(*args, **kwargs)
    return wrapper


@cython.test_assert_path_exists('//MergedDictNode')
def wrap_modify_func(f):
    """
    >>> def f(a=1, test=2):
    ...     return a, test

    >>> wrapped = wrap_modify_func(f)
    >>> wrapped(1)
    CALLED
    (1, 1)
    >>> wrapped(a=2)
    CALLED
    (2, 1)
    >>> wrapped(a=2, test=3)
    CALLED
    (2, 1)
    """
    def modify(kw):
        kw['test'] = 1
        return kw

    def wrapper(*args, **kwargs):
        print("CALLED")
        return f(*args, **modify(kwargs))
    return wrapper


def modify_in_function():
    """
    >>> modify_in_function()
    {'foo': 'bar'}
    {'foo': 'bar'}
    """
    def inner(**kwds):
        kwds['foo'] = 'modified'
    d = {'foo': 'bar'}
    print(d)
    inner(**d)
    print(d)


#@cython.test_assert_path_exists('//MergedDictNode')
def wrap_modify_func_mix(f):
    """
    >>> def f(a=1, test=2):
    ...     return a, test

    >>> wrapped = wrap_modify_func_mix(f)
    >>> wrapped(1)
    CALLED
    (1, 1)
    >>> wrapped(a=2)
    CALLED
    (2, 1)
    >>> wrapped(a=2, test=3)
    CALLED
    (2, 1)
    """
    def modify(kw):
        kw['test'] = 1
        return kw

    def wrapper(*args, **kwargs):
        print("CALLED")
        f(*args, **kwargs)
        return f(*args, **modify(kwargs))
    return wrapper


#@cython.test_fail_if_path_exists('//MergedDictNode')
def wrap_reassign(f):
    """
    >>> def f(a=1, test=2):
    ...     return a, test
    >>> wrapped = wrap_reassign(f)
    >>> wrapped(1)
    CALLED
    (1, 1)
    >>> wrapped(a=2)
    CALLED
    (1, 1)
    >>> wrapped(a=2, test=3)
    CALLED
    (1, 1)
    """
    def wrapper(*args, **kwargs):
        print("CALLED")
        kwargs = {'test': 1}
        return f(*args, **kwargs)
    return wrapper


#@cython.test_fail_if_path_exists('//MergedDictNode')
def kwargs_metaclass(**kwargs):
    """
    >>> K = kwargs_metaclass()
    >>> K = kwargs_metaclass(metaclass=type)
    """
    class K(**kwargs):
        pass
    return K
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/kwonlyargs.pyx0000644000175100001770000000722100000000000020506 0ustar00runnerdocker00000000000000def b(a, b, c):
    """
    >>> b(1,2,3)
    >>> b(1,2,3,4)
    Traceback (most recent call last):
    TypeError: b() takes exactly 3 positional arguments (4 given)
    """
    a, b, c = b, c, a

def c(a, b, c=1):
    """
    >>> c(1,2)
    >>> c(1,2,3)
    >>> c(1,2,3,4)
    Traceback (most recent call last):
    TypeError: c() takes at most 3 positional arguments (4 given)
    """
    a, b, c = b, c, a

def d(a, b, *, c = 88):
    """
    >>> d(1,2)
    >>> d(1,2, c=1)
    >>> d(1,2,3)
    Traceback (most recent call last):
    TypeError: d() takes exactly 2 positional arguments (3 given)
    >>> d(1,2, d=1)
    Traceback (most recent call last):
    TypeError: d() got an unexpected keyword argument 'd'
    """
    a, b, c = b, c, a

def e(a, b, c = 88, **kwds):
    """
    >>> e(1,2)
    >>> e(1,2, c=1)
    >>> e(1,2, d=1)
    >>> e(1,2, c=1, d=2, e=3)
    >>> e(1,2,3)
    >>> e(1,2,3,4)
    Traceback (most recent call last):
    TypeError: e() takes at most 3 positional arguments (4 given)
    """
    a, b, c = b, c, a

def f(a, b, *, c, d = 42):
    """
    >>> f(1,2, c=1)
    >>> f(1,2, c=1, d=2)
    >>> f(1,2,3)
    Traceback (most recent call last):
    TypeError: f() takes exactly 2 positional arguments (3 given)
    >>> f(1,2)
    Traceback (most recent call last):
    TypeError: f() needs keyword-only argument c
    >>> f(1,2, c=1, e=2)
    Traceback (most recent call last):
    TypeError: f() got an unexpected keyword argument 'e'
    """
    a, b, c, d = b, c, d, a

def g(a, b, *, c, d = 42, e = 17, f, **kwds):
    """
    >>> g(1,2, c=1, f=2)
    >>> g(1,2, c=1, e=0, f=2, d=11)
    >>> g(1,2, c=1, f=2, e=0, x=25)
    >>> g(1,2,3)
    Traceback (most recent call last):
    TypeError: g() takes exactly 2 positional arguments (3 given)
    >>> g(1,2)
    Traceback (most recent call last):
    TypeError: g() needs keyword-only argument c
    >>> g(1,2, c=1)
    Traceback (most recent call last):
    TypeError: g() needs keyword-only argument f
    """
    a, b, c, d, e, f = b, c, d, e, f, a

def h(a, b, *args, c, d = 42, e = 17, f, **kwds):
    """
    >>> h(1,2, c=1, f=2)
    >>> h(1,2, c=1, f=2, e=3)
    >>> h(1,2,3,4,5,6, c=1, f=2)
    >>> h(1,2,3,4,5,6, c=1, f=2, e=3, x=25, y=11)
    >>> h(1,2,3)
    Traceback (most recent call last):
    TypeError: h() needs keyword-only argument c
    >>> h(1,2, d=1)
    Traceback (most recent call last):
    TypeError: h() needs keyword-only argument c
    """
    a, b, c, d, e, f = b, c, d, e, f, a

def k(a, b, c=1, *args, d = 42, e = 17, f, **kwds):
    """
    >>> k(1,2, c=1, f=2)
    >>> k(1,2, c=1, f=2, e=3)
    >>> k(1,2,3,4,5,6, d=1, f=2)
    >>> k(1,2,3,4,5,6, d=1, f=2, e=3, x=25, y=11)
    >>> k(1,2,3)
    Traceback (most recent call last):
    TypeError: k() needs keyword-only argument f
    >>> k(1,2, d=1)
    Traceback (most recent call last):
    TypeError: k() needs keyword-only argument f
    """
    a, b, c, d, e, f = b, c, d, e, f, a

def l(*, a, b, c = 88):
    """
    >>> l(a=1, b=2)
    >>> l(a=1, b=2, c=1)
    >>> l(1,2,3)
    Traceback (most recent call last):
    TypeError: l() takes exactly 0 positional arguments (3 given)
    >>> l(1,2, d=1)
    Traceback (most recent call last):
    TypeError: l() takes exactly 0 positional arguments (2 given)
    >>> l(1,2,3)
    Traceback (most recent call last):
    TypeError: l() takes exactly 0 positional arguments (3 given)
    >>> l(1,2, d=1)
    Traceback (most recent call last):
    TypeError: l() takes exactly 0 positional arguments (2 given)
    """
    a, b, c = b, c, a

def m(a, *, b, c = 88):
    """
    >>> m(1, b=2)
    >>> m(a=1, b=2)
    >>> m(a=1, b=2, c=1)
    """
    a, b, c = b, c, a

def n(a, *, b, c = 88):
    a, b, c = b, c, a
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/kwonlyargscall.pyx0000644000175100001770000001224400000000000021343 0ustar00runnerdocker00000000000000# the calls:

def call0ab(f):
    """
    >>> call0ab(b)
    Traceback (most recent call last):
    TypeError: b() takes exactly 3 positional arguments (2 given)
    >>> call0ab(c)
    1 2 1
    >>> call0ab(d)
    1 2 88
    """
    f(a=1,b=2)

def call0abc(f):
    """
    >>> call0abc(b)
    1 2 3
    >>> call0abc(c)
    1 2 3
    >>> call0abc(d)
    1 2 3
    >>> call0abc(e)
    1 2 3 []
    >>> call0abc(f)
    1 2 3 42
    >>> call0abc(m)
    1 2 3
    """
    f(a=1,b=2,c=3)

def call2(f):
    """
    >>> call2(c)
    1 2 1
    >>> call2(d)
    1 2 88
    >>> call2(e)
    1 2 88 []
    >>> call2(f)
    Traceback (most recent call last):
    TypeError: f() needs keyword-only argument c
    >>> call2(g)
    Traceback (most recent call last):
    TypeError: g() needs keyword-only argument c
    >>> call2(m)
    Traceback (most recent call last):
    TypeError: m() needs keyword-only argument c
    """
    f(1,2)

def call3(f):
    """
    >>> call3(b)
    1 2 3
    >>> call3(c)
    1 2 3
    >>> call3(d)
    Traceback (most recent call last):
    TypeError: d() takes exactly 2 positional arguments (3 given)
    >>> call3(e)
    1 2 3 []
    >>> call3(f)
    Traceback (most recent call last):
    TypeError: f() takes exactly 2 positional arguments (3 given)
    >>> call3(g)
    Traceback (most recent call last):
    TypeError: g() takes exactly 2 positional arguments (3 given)
    >>> call3(h)
    Traceback (most recent call last):
    TypeError: h() needs keyword-only argument c
    >>> call3(k)
    Traceback (most recent call last):
    TypeError: k() needs keyword-only argument f
    >>> call3(m)
    Traceback (most recent call last):
    TypeError: m() takes at most 2 positional arguments (3 given)
    """
    f(1,2,3)

def call4(f):
    """
    >>> call4(b)
    Traceback (most recent call last):
    TypeError: b() takes exactly 3 positional arguments (4 given)
    >>> call4(c)
    Traceback (most recent call last):
    TypeError: c() takes at most 3 positional arguments (4 given)
    >>> call4(e)
    Traceback (most recent call last):
    TypeError: e() takes at most 3 positional arguments (4 given)
    """
    f(1,2,3,4)

def call2c(f):
    """
    >>> call2c(d)
    1 2 1
    >>> call2c(e)
    1 2 1 []
    >>> call2c(f)
    1 2 1 42
    >>> call2c(g)
    Traceback (most recent call last):
    TypeError: g() needs keyword-only argument f
    >>> call2c(m)
    1 2 1
    """
    f(1,2, c=1)

def call2d(f):
    """
    >>> call2d(d)
    Traceback (most recent call last):
    TypeError: d() got an unexpected keyword argument 'd'
    >>> call2d(e)
    1 2 88 [('d', 1)]
    >>> call2d(k)
    Traceback (most recent call last):
    TypeError: k() needs keyword-only argument f
    """
    f(1,2, d=1)

def call3d(f):
    """
    >>> call3d(h)
    Traceback (most recent call last):
    TypeError: h() needs keyword-only argument c
    """
    f(1,2,3, d=1)

def call2cd(f):
    """
    >>> call2cd(f)
    1 2 1 2
    >>> call2cd(m)
    Traceback (most recent call last):
    TypeError: m() got an unexpected keyword argument 'd'
    """
    f(1,2, c=1, d=2)

def call2ce(f):
    """
    >>> call2ce(f)
    Traceback (most recent call last):
    TypeError: f() got an unexpected keyword argument 'e'
    """
    f(1,2, c=1, e=2)

def call2cde(f):
    """
    >>> call2cde(e)
    1 2 1 [('d', 2), ('e', 3)]
    """
    f(1,2, c=1, d=2, e=3)

def call2cf(f):
    """
    >>> call2cf(g)
    1 2 1 42 17 2 []
    >>> call2cf(h)
    1 2 1 42 17 2 () []
    >>> call2cf(k)
    1 2 1 42 17 2 () []
    """
    f(1,2, c=1, f=2)

def call6cf(f):
    """
    >>> call6cf(h)
    1 2 1 42 17 2 (3, 4, 5, 6) []
    """
    f(1,2,3,4,5,6, c=1, f=2)

def call6df(f):
    """
    >>> call6df(k)
    1 2 3 1 17 2 (4, 5, 6) []
    """
    f(1,2,3,4,5,6, d=1, f=2)

def call2cfe(f):
    """
    >>> call2cfe(h)
    1 2 1 42 3 2 () []
    >>> call2cfe(k)
    1 2 1 42 3 2 () []
    """
    f(1,2, c=1, f=2, e=3)

def call2cefd(f):
    """
    >>> call2cefd(g)
    1 2 1 11 0 2 []
    """
    f(1,2, c=1, e=0, f=2, d=11)

def call2cfex(f):
    """
    >>> call2cfex(g)
    1 2 1 42 0 2 [('x', 25)]
    """
    f(1,2, c=1, f=2, e=0, x=25)

def call6argscfexy(f):
    args = (1,2,3,4,5,6)
    f(*args, c=1, f=2, e=3, x=25, y=11)

def call6cfexy(f):
    """
    >>> call6cfexy(h)
    1 2 1 42 3 2 (3, 4, 5, 6) [('x', 25), ('y', 11)]
    """
    f(1,2,3,4,5,6, c=1, f=2, e=3, x=25, y=11)

def call6dfexy(f):
    """
    >>> call6dfexy(k)
    1 2 3 1 3 2 (4, 5, 6) [('x', 25), ('y', 11)]
    """
    f(1,2,3,4,5,6, d=1, f=2, e=3, x=25, y=11)

# the called functions:

def b(a, b, c):
    print a,b,c

def c(a, b, c=1):
    print a,b,c

def d(a, b, *, c = 88):
    print a,b,c

def e(a, b, c = 88, **kwds):
    kwlist = list(kwds.items())
    kwlist.sort()
    print a,b,c, kwlist

def f(a, b, *, c, d = 42):
    print a,b,c,d

def g(a, b, *, c, d = 42, e = 17, f, **kwds):
    kwlist = list(kwds.items())
    kwlist.sort()
    print a,b,c,d,e,f, kwlist

def h(a, b, *args, c, d = 42, e = 17, f, **kwds):
    kwlist = list(kwds.items())
    kwlist.sort()
    print a,b,c,d,e,f, args, kwlist

def k(a, b, c=1, *args, d = 42, e = 17, f, **kwds):
    kwlist = list(kwds.items())
    kwlist.sort()
    print a,b,c,d,e,f, args, kwlist

def m(a, b=1, *, c):
    print a,b,c
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/lambda_T195.pyx0000644000175100001770000000414500000000000020252 0ustar00runnerdocker00000000000000# mode: run
# tag: lambda
# ticket: t195

__doc__ = u"""
#>>> py_identity = lambda x:x
#>>> py_identity(1) == cy_identity(1)
#True
"""

#cy_identity = lambda x:x


def make_identity():
    """
    >>> idcall = make_identity()
    >>> idcall(1)
    1
    >>> idcall(2)
    2
    """
    return lambda x:x

def make_const0(x):
    """
    >>> make_const0(1)()
    1
    """
    return lambda :x

def make_const1(x):
    """
    >>> make_const1(1)(2)
    1
    >>> make_const1(1)(2)
    1
    """
    return lambda _:x


def make_const_calc0():
    """
    >>> make_const_calc0()()
    11
    """
    return lambda : 1*2*3+5

def make_const_calc1():
    """
    >>> make_const_calc1()(2)
    11
    """
    return lambda _: 1*2*3+5

def make_const_calc1_xy(x):
    """
    >>> make_const_calc1_xy(8)(2)
    27
    """
    return lambda y: x*y+(1*2*3+5)

def make_lambda_lambda(x):
    """
    >>> make_lambda_lambda(1)(2)(4)
    7
    """
    return lambda y : \
           lambda z:x+y+z

def make_typed_lambda_lambda(int x):
    """
    >>> make_typed_lambda_lambda(1)(2)(4)
    7

    >>> partial_lambda = make_typed_lambda_lambda(1)(2)
    >>> partial_lambda(4)
    7
    >>> partial_lambda(5)
    8
    """
    return lambda int y : \
           lambda int z:x+y+z

def pass_lambda(f):
    """
    >>> def f(a, lfunc): return lfunc(a,2)
    >>> pass_lambda(f)
    12
    """
    return f(1, lambda a, b : a*10+b)

def pass_lambda_with_args(f):
    """
    >>> def f(a, lfunc): return lfunc(a,2,3)
    >>> pass_lambda_with_args(f)
    123
    """
    return f(1, lambda a, *args : (a*10 + args[0])*10 + args[1])

def pass_lambda_with_args_kwargs(f):
    """
    >>> def f(a, lfunc): return lfunc(a,2,3, b=4)
    >>> pass_lambda_with_args_kwargs(f)
    1234
    """
    return f(1, lambda a, *args, **kwargs : ((a*10 + args[0])*10 + args[1])*10 + kwargs['b'])

def pass_lambda_with_args_kwargs_kwonly_args(f):
    """
    >>> def f(a, lfunc): return lfunc(a,2,3, b=4, c=5)
    >>> pass_lambda_with_args_kwargs_kwonly_args(f)
    12345
    """
    return f(1, lambda a, *args, b, **kwargs : (((a*10 + args[0])*10 + args[1])*10 + b)*10 + kwargs['c'])
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/lambda_T723.pyx0000644000175100001770000000022500000000000020242 0ustar00runnerdocker00000000000000# mode: run
# ticket: t723
# tag: lambda

def t723(a):
    """
    >>> t723(2)()
    4
    >>> t723(2)(3)
    9
    """
    return lambda x=a: x * x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/lambda_class_T605.pyx0000644000175100001770000000130500000000000021426 0ustar00runnerdocker00000000000000# mode: run
# tag: lambda
# ticket: t605

cdef int cdef_CONST = 123
CONST = 456

cdef class Foo:
    """
    >>> obj = Foo()
    >>> obj.id(123)
    123
    >>> obj.cconst_mul(1)
    123
    >>> obj.const_mul(1)
    456
    >>> obj.foo[0](1)
    1
    """
    id = lambda self, x: x
    cconst_mul = lambda self, x: x * cdef_CONST
    const_mul = lambda self, x: x * CONST
    foo = (lambda x:x,)

class Bar:
    """
    >>> obj = Bar()
    >>> obj.id(123)
    123
    >>> obj.cconst_mul(1)
    123
    >>> obj.const_mul(1)
    456
    >>> obj.foo[0](1)
    1
    """
    id = lambda self, x: x
    cconst_mul = lambda self, x: x * cdef_CONST
    const_mul = lambda self, x: x * CONST
    foo = (lambda x:x,)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/lambda_module_T603.pyx0000644000175100001770000000067100000000000021611 0ustar00runnerdocker00000000000000# mode: run
# tag: lambda
# ticket: t603

# Module scope lambda functions

__doc__ = """
>>> pow2(16)
256
>>> with_closure(0)
0
>>> typed_lambda(1)(2)
3
>>> typed_lambda(1.5)(1.5)
2
>>> cdef_const_lambda()
123
>>> const_lambda()
321
"""

pow2 = lambda x: x * x
with_closure = lambda x:(lambda: x)()
typed_lambda = lambda int x : (lambda int y: x + y)

cdef int xxx = 123
cdef_const_lambda = lambda: xxx

yyy = 321
const_lambda = lambda: yyy
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/lambda_tests.pyx0000644000175100001770000002562200000000000020755 0ustar00runnerdocker00000000000000# mode: run
# tag: closures, lambda

# Battery of tests for closures in Cython. Based on the collection of
# compiler tests from P423/B629 at Indiana University, Spring 1999 and
# Fall 2000. Special thanks to R. Kent Dybvig, Dan Friedman, Kevin
# Millikin, and everyone else who helped to generate the original
# tests. Converted into a collection of Python/Cython tests by Craig
# Citro.
#
# Note: This set of tests is split (somewhat randomly) into several
# files, simply because putting all the tests in a single file causes
# gcc and g++ to buckle under the load.
#


def g0():
    """
    >>> g0()
    4000
    """
    return (lambda y_1: y_1)(4000)


def g1():
    """
    >>> g1()
    1
    """
    f_3 = (lambda x_2: x_2)
    return (f_3(0)+1)


def g2():
    """
    >>> g2()
    4
    """
    f_5 = (lambda y_4: y_4)
    return f_5(f_5(4))


def g3():
    """
    >>> g3()
    4
    """
    return (lambda f_7: f_7(f_7(4)))((lambda y_6: y_6))


def g5():
    """
    >>> g5()
    9000
    """
    def g4():
      a_8 = 4000
      return lambda b_9: ((a_8)+(b_9))
    return g4()(5000)


def g6():
    """
    >>> g6()
    9000
    """
    return (lambda a_10: (lambda b_11: (a_10)+(b_11)))(4000)(5000)


def g7():
    """
    >>> g7()
    2
    """
    return (lambda f_13: f_13(f_13(0)))((lambda x_12: (x_12+1)))


def g8():
    """
    >>> g8()
    0
    """
    f_16 = (lambda x_15, y_14: x_15)
    a_17 = f_16(0, 1)
    return f_16(a_17, a_17)


def g10():
    """
    >>> g10()
    3
    """
    f_19 = (lambda x_18: x_18)
    def g9():
      a_22 = 0
      b_21 = 1
      c_20 = 2
      return (f_19(a_22))+((f_19(b_21))+(f_19(c_20)))
    return (f_19(0))+(g9())


def g12():
    """
    >>> g12()
    2
    """
    def g11():
      x_23 = 1
      return lambda y_24: ((x_23)+(y_24))
    f_25 = g11()
    x_26 = 0
    return f_25(f_25(x_26))


def g14():
    """
    >>> g14()
    3050
    """
    def g13():
      t_29 = (lambda x_28: (x_28)+(50))
      return lambda f_30: (t_29(f_30(1000)))
    return g13()((lambda y_27: (y_27)+(2000)))


def g15():
    """
    >>> g15()
    3050
    """
    return (lambda t_33: (lambda f_34: t_33(f_34(1000))))((lambda x_32: (x_32)+(50)))((lambda y_31: (y_31)+(2000)))


def g17():
    """
    >>> g17()
    2050
    """
    def g16():
      t_35 = 50
      return lambda f_36: ((t_35)+(f_36()))
    return g16()((lambda : 2000))


def g18():
    """
    >>> g18()
    2050
    """
    return (lambda t_37: (lambda f_38: (t_37)+(f_38())))(50)((lambda : 2000))


def g20():
    """
    >>> g20()
    700
    """
    def g19():
      x_39 = 300
      return lambda y_40: ((x_39)+(y_40))
    return g19()(400)


def g21():
    """
    >>> g21()
    0
    """
    x_44 = 3
    f_43 = (lambda x_42, y_41: x_42)
    if (f_43(0, 0)):
      return f_43(f_43(0, 0), x_44)
    else:
      return 0


def g22():
    """
    >>> g22()
    False
    """
    f_46 = (lambda x_45: (x_45) if (((not ((x_45[0]) == 0))) if (isinstance(x_45, list)) else (False)) else (False))
    return f_46([0,[0,[]]])


def g23():
    """
    >>> g23()
    False
    """
    f_48 = (lambda x_47: (x_47) if (((not ((not ((x_47[0]) == 0))) if (isinstance(x_47, list)) else (False))) if (x_47) else (False)) else (False))
    return f_48(0)


def g24():
    """
    >>> g24()
    []
    """
    f_50 = (lambda x_49: (x_49) if ((True) if (isinstance(x_49, list)) else ((x_49 == []))) else ([]))
    return f_50(0)


def g25():
    """
    >>> g25()
    0
    """
    y_51 = 4
    f_54 = (lambda x_53, y_52: 0)
    return f_54(f_54(y_51, y_51), f_54(y_51, y_51))


def g26():
    """
    >>> g26()
    0
    """
    y_55 = 4
    f_58 = (lambda x_57, y_56: 0)
    return f_58(f_58(y_55, f_58(y_55, y_55)), f_58(y_55, f_58(y_55, y_55)))


def g27():
    """
    >>> g27()
    4
    """
    return (lambda y_59: (lambda f_61: f_61(f_61(y_59)))((lambda y_60: y_60)))(4)


def g28():
    """
    >>> g28()
    23
    """
    f_63 = (lambda x_62: x_62)
    return ((1) if (False) else (f_63(22))+1)


def g29():
    """
    >>> g29()
    5061
    """
    f_68 = (lambda x_65: ((not x_65)) if (x_65) else (x_65))
    f2_67 = (lambda x_64: (10)*(x_64))
    x_66 = 23
    return ((1) if (f_68(x_66 == 0)) else ((x_66)*(f2_67((x_66-1))))+1)


def g30():
    """
    >>> g30()
    1
    """
    one_69 = (lambda n_70: (1) if (n_70 == 0) else (one_69((n_70-1))))
    return one_69(13)


def g31():
    """
    >>> g31()
    True
    """
    even_72 = (lambda x_74: (True) if (x_74 == 0) else (odd_71((x_74-1))))
    odd_71 = (lambda x_73: (False) if (x_73 == 0) else (even_72((x_73-1))))
    return odd_71(13)


def g32():
    """
    >>> g32()
    False
    """
    even_76 = (lambda x_78: (True) if (x_78 == 0) else (odd_75((x_78-1))))
    odd_75 = (lambda x_77: (False) if (x_77 == 0) else (even_76((x_77-1))))
    return even_76(13)


def g34():
    """
    >>> g34()
    True
    """
    even_80 = (lambda x_79: x_79)
    def g33():
      even_82 = (lambda x_84: (True) if (x_84 == 0) else (odd_81((x_84-1))))
      odd_81 = (lambda x_83: (False) if (x_83 == 0) else (even_82((x_83-1))))
      return odd_81(13)
    return even_80(g33())


def g35():
    """
    >>> g35()
    120
    """
    fact_85 = (lambda n_86: (1) if (n_86 == 0) else ((n_86)*(fact_85((n_86-1)))))
    return fact_85(5)


def g38():
    """
    >>> g38()
    10
    """
    x_87 = 5
    a_90 = (lambda u_101, v_100, w_99: (b_89(v_100, w_99)) if (u_101 == 0) else (a_90((u_101)-(1), v_100, w_99)))
    def g37():
      def g36(q_93, r_92):
        p_94 = (q_93)*(r_92)
        e_96 = (lambda n_98: (c_88(p_94)) if (n_98 == 0) else (o_95((n_98)-(1))))
        o_95 = (lambda n_97: (c_88(x_87)) if (n_97 == 0) else (e_96((n_97)-(1))))
        return e_96((q_93)*(r_92))
      return g36
    b_89 = g37()
    c_88 = (lambda x_91: (5)*(x_91))
    return a_90(3, 2, 1)


def g39():
    """
    >>> g39()
    120
    """
    fact_104 = (lambda fact_103, n_102: (1) if (n_102 == 0) else ((fact_103(fact_103, (n_102-1)))*(n_102)))
    return fact_104(fact_104, 5)


def g40():
    """
    >>> g40()
    35
    """
    return (lambda x_105: (lambda y_106: (lambda z_107: (lambda w_108: (lambda u_109: (x_105)+((y_106)+((z_107)+((w_108)+(u_109)))))))))(5)(6)(7)(8)(9)


def g41():
    """
    >>> g41()
    6
    """
    sum_112 = (lambda sum_111, ls_110: (0) if ((ls_110 == [])) else (((ls_110[0]))+(sum_111(sum_111, (ls_110[1])))))
    return sum_112(sum_112, [1,[2,[3,[]]]])


def g46():
    """
    >>> g46()
    1500
    """
    def g45():
      def g44():
        def g42(a_113):
          def g43():
            (a_113)+(200 if True else None)
            return 1500
          return g43
        return g42
      return g44()(1000)
    return g45()()


def g53():
    """
    >>> g53()
    2600
    """
    def g52():
      def g51():
        def g50():
          def g47(a_114):
            def g48(b_115):
              a_114 = 200 if b_115 else None
              def g49(c_116):
                c_116 = 400 if 300 else None
                return (a_114)+((b_115)+(c_116))
              return g49
            return g48
          return g47
        return g50()(1000)
      return g51()(2000)
    return g52()(3000)


def g54():
    """
    >>> g54()
    5
    """
    return (lambda f_118: f_118(f_118(5)))((lambda x_117: x_117))


def g56():
    """
    >>> g56()
    8000
    """
    def g55():
      f_120 = (lambda x_119: (x_119)+(3000))
      return lambda y_121: (f_120(f_120(y_121)))
    return g55()(2000)


def g57():
    """
    >>> g57()
    120
    """
    fact_125 = (lambda fact_124, n_123, acc_122: (acc_122) if (n_123 == 0) else (fact_124(fact_124, (n_123-1), (n_123)*(acc_122))))
    return fact_125(fact_125, 5, 1)


def g58():
    """
    >>> g58()
    3
    """
    f_127 = (lambda x_126: (lambda : x_126()))
    return f_127((lambda : 3))()


def g59():
    """
    >>> g59()
    22
    """
    f_129 = (lambda x_132: (x_132)+((lambda y_133: (lambda z_134: (y_133)+(z_134)))(6)(7)))
    g_128 = (5)+((lambda w_131, u_130: (w_131)+(u_130))(8, 9))
    return g_128


def g60():
    """
    >>> g60()
    0
    """
    loop_135 = (lambda : (lambda : loop_135()))
    loop_135()
    return 0


def g63():
    """
    >>> g63()
    668
    """
    def g62():
      def g61():
        loop_137 = (lambda link_138: (lambda : link_138()))
        return loop_137((lambda : 668))
      return g61
    f_136 = g62()
    return f_136()()


def g64():
    """
    >>> g64()
    17
    """
    k_141 = (lambda x_140, y_139: x_140)
    b_142 = 17
    return k_141(k_141(k_141, 37), 37)(b_142, (b_142)*(b_142))


def g65():
    """
    >>> g65()
    37
    """
    f_145 = (lambda g_144, u_143: g_144((g_144(37)) if (u_143) else (u_143)))
    return f_145((lambda x_146: x_146), 75)


def g66():
    """
    >>> g66()
    4687
    """
    f_150 = (lambda h_148, u_147: h_148((h_148((u_147)+(37))) if (u_147) else (u_147)))
    w_149 = 62
    return f_150((lambda x_151: (w_149)-(x_151)), (75)*(w_149))


def g67():
    """
    >>> g67()
    True
    """
    t_153 = True
    f_152 = False
    bools_156 = [t_153,f_152]
    id_155 = (lambda x_154: (f_152) if ((not x_154)) else (t_153))
    even_158 = (lambda x_160: ((bools_156[0])) if (id_155(x_160 == 0)) else (odd_157((x_160)-(1))))
    odd_157 = (lambda y_159: (id_155((bools_156[1]))) if (y_159 == 0) else (even_158((y_159)-(1))))
    return odd_157(5)


def g68():
    """
    >>> g68()
    5
    """
    f_162 = (lambda x_164: (x_164)+(1))
    g_161 = (lambda y_163: f_162(f_162(y_163)))
    return (f_162(1))+(g_161(1))


def g69():
    """
    >>> g69()
    1521
    """
    y_165 = 3
    f_168 = (lambda x_171: (g_167((x_171)+(1))) if (x_171 == 0) else (f_168((x_171)-(y_165))))
    g_167 = (lambda x_170: h_166((x_170)*(x_170)))
    h_166 = (lambda x_169: x_169)
    return g_167(39)


def g70():
    """
    >>> g70()
    -1
    """
    f_173 = (lambda x_175: (x_175)+(1))
    g_172 = (lambda y_174: f_173(f_173(y_174)))
    f_173 = (lambda x_176: (x_176)-(1))
    return (f_173(1))+(g_172(1))


def g71():
    """
    >>> g71()
    [52, [17, [35, [17, 35]]]]
    """
    f_180 = (lambda : (a_179)+(b_178))
    a_179 = 17
    b_178 = 35
    h_177 = [(lambda : a_179),(lambda : b_178)]
    return [f_180(),[a_179,[b_178,[(h_177[0])(),(h_177[1])()]]]]


def g73():
    """
    >>> g73()
    120
    """
    x_183 = 5
    def g72():
      a_181 = 1
      return lambda : (a_181)
    th_182 = g72()
    fact_184 = (lambda n_186, th_185: (th_185()) if (n_186 == 0) else ((n_186)*(fact_184((n_186)-(1), th_185))))
    return fact_184(x_183, th_182)


def g74():
    """
    >>> g74()
    [120, -120]
    """
    negative_188 = (lambda n_187: (n_187 < 0))
    fact_190 = (lambda n_192: (1) if (n_192 == 0) else ((n_192)*(fact_190((n_192)-(1)))))
    call_fact_189 = (lambda n_191: (fact_190(n_191)) if ((not negative_188(n_191))) else ((0)-(fact_190((0)-(n_191)))))
    return [call_fact_189(5),call_fact_189(-5)]


def g75():
    """
    >>> g75()
    [[33, 55], [77, 99]]
    """
    return (lambda a_193: (lambda b_194: (lambda c_195: (lambda d_196: [[a_193,b_194],[c_195,d_196]]))))(33)(55)(77)(99)

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/language_level.srctree0000644000175100001770000000221300000000000022103 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import directive2; import directive3"
PYTHON -c "import infile2; import infile3"

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup

ext_modules = []

# Test language_level specified in the cythonize() call
ext_modules += cythonize("directive2.py", compiler_directives={'language_level': 2})
ext_modules += cythonize("directive3.py", compiler_directives={'language_level': 3})

# Test language_level specified in the source file. We give a
# conflicting directive to cythonize() to check that the language_level
# is correctly overridden when compiling
ext_modules += cythonize("infile2.py", compiler_directives={'language_level': 3})
ext_modules += cythonize("infile3.py", compiler_directives={'language_level': 2})

setup(ext_modules=ext_modules)

######## directive3.py ########

import sys
print("SUCCESS", file=sys.stdout)

######## directive2.py ########

print "SUCCESS"

######## infile3.py ########

# cython: language_level=3

import sys
print("SUCCESS", file=sys.stdout)

######## infile2.py ########

# cython: language_level=2

print "SUCCESS"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/large_consts_T237.pyx0000644000175100001770000000067100000000000021512 0ustar00runnerdocker00000000000000# ticket: t237
#def add_large_c():
#    cdef unsigned long long val = 2**30 + 2**30
#    return val

def add_large():
    """
    >>> add_large() == 2147483647 + 2147483647
    True

    #>>> add_large_c() == 2147483647 + 2147483647
    #True
    """
    return 2147483647 + 2147483647

def add_large_pow():
    """
    >>> add_large_pow() == 2**31 + 2**31
    True
    >>> add_large_pow() == 2**32
    True
    """
    return 2**31 + 2**31
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/large_integer_T5290.py0000644000175100001770000000367100000000000021535 0ustar00runnerdocker00000000000000# cython: test_assert_c_code_has = __pyx_int_large_0x16a76f60ab5d456a_xxx_1cd89e1a3713adcc1d
# cython: test_assert_c_code_has = __pyx_int_large2_0x16a76f60ab5d456a_xxx_1cd89e1a3713adcc1d

"""
>>> print(large_int1)
498767777577077770556777587772706774776460369770778448231270737072737774657965287074870267\
777936758056447717673778020572245677462377467777877973720727779047207424736977237577049760\
567712761768711777573771777179179717700370131327713044788007971447377173777866449271749747\
721187877247577877179557737776707777677777217729897579397557707379543777975071577397912797\
751172283795307837046127757551976278271387413977777777470074377477377099877743777277619817\
9733909687574772704167777795797966373977780709777877895072797
>>> large_int2 - large_int1 == 10**485  or  large_int2
True
"""

large_int1 = 4987677775770777705567775877727067747764603697707784482312707370727377746579652870748702677779367580564477176737780205722456774623774677778779737207277790472074247369772375770497605677127617687117775737717771791797177003701313277130447880079714473771737778664492717497477211878772475778771795577377767077776777772177298975793975577073795437779750715773979127977511722837953078370461277575519762782713874139777777774700743774773770998777437772776198179733909687574772704167777795797966373977780709777877895072797  # noqa
large_int2 = 4987677775770777705567775977727067747764603697707784482312707370727377746579652870748702677779367580564477176737780205722456774623774677778779737207277790472074247369772375770497605677127617687117775737717771791797177003701313277130447880079714473771737778664492717497477211878772475778771795577377767077776777772177298975793975577073795437779750715773979127977511722837953078370461277575519762782713874139777777774700743774773770998777437772776198179733909687574772704167777795797966373977780709777877895072797  # noqa
#                                     ^
#                                     Here ...77758... -> ...77759...
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/legacy_implicit_noexcept.pyx0000644000175100001770000000615700000000000023360 0ustar00runnerdocker00000000000000# cython: legacy_implicit_noexcept=True
# mode: run
# tag: warnings
import sys
import functools
import cython
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO

cdef int func_implicit(int a, int b):
    raise RuntimeError

cdef int func_noexcept(int a, int b) noexcept:
    raise RuntimeError

cdef int func_star(int a, int b) except *:
    raise RuntimeError

cdef int func_value(int a, int b) except -1:
    raise RuntimeError

cdef func_return_obj_implicit(int a, int b):
    raise RuntimeError

cdef int(*ptr_func_implicit)(int, int)
ptr_func_implicit = func_implicit

cdef int(*ptr_func_noexcept)(int, int) noexcept
ptr_func_noexcept = func_noexcept

@cython.cfunc
def func_pure_implicit() -> cython.int:
    raise RuntimeError

@cython.excetval(check=False)
@cython.cfunc
def func_pure_noexcept() -> cython.int:
    raise RuntimeError

def return_stderr(func):
    @functools.wraps(func)
    def testfunc():
        old_stderr = sys.stderr
        stderr = sys.stderr = StringIO()
        try:
            func()
        finally:
            sys.stderr = old_stderr
        return stderr.getvalue().strip()

    return testfunc

@return_stderr
def test_noexcept():
    """
    >>> print(test_noexcept())  # doctest: +ELLIPSIS
    RuntimeError
    Exception...ignored...
    """
    func_noexcept(3, 5)

@return_stderr
def test_ptr_noexcept():
    """
    >>> print(test_ptr_noexcept())  # doctest: +ELLIPSIS
    RuntimeError
    Exception...ignored...
    """
    ptr_func_noexcept(3, 5)

@return_stderr
def test_implicit():
    """
    >>> print(test_implicit())  # doctest: +ELLIPSIS
    RuntimeError
    Exception...ignored...
    """
    func_implicit(1, 2)

@return_stderr
def test_ptr_implicit():
    """
    >>> print(test_ptr_implicit())  # doctest: +ELLIPSIS
    RuntimeError
    Exception...ignored...
    """
    ptr_func_implicit(1, 2)

def test_star():
    """
    >>> test_star()
    Traceback (most recent call last):
    ...
    RuntimeError
    """
    func_star(1, 2)

def test_value():
    """
    >>> test_value()
    Traceback (most recent call last):
    ...
    RuntimeError
    """
    func_value(1, 2)


def test_return_obj_implicit():
    """
    >>> test_return_obj_implicit()
    Traceback (most recent call last):
    ...
    RuntimeError
    """
    func_return_obj_implicit(1, 2)

def test_pure_implicit():
    """
    >>> test_pure_implicit()
    Traceback (most recent call last):
    ...
    RuntimeError
    """
    func_pure_implicit()

def test_pure_noexcept():
    """
    >>> test_pure_noexcept()
    Traceback (most recent call last):
    ...
    RuntimeError
    """
    func_pure_noexcept()

_WARNINGS = """
12:5: Unraisable exception in function 'legacy_implicit_noexcept.func_implicit'.
12:36: Implicit noexcept declaration is deprecated. Function declaration should contain 'noexcept' keyword.
15:5: Unraisable exception in function 'legacy_implicit_noexcept.func_noexcept'.
24:43: Implicit noexcept declaration is deprecated. Function declaration should contain 'noexcept' keyword.
27:38: Implicit noexcept declaration is deprecated. Function declaration should contain 'noexcept' keyword.
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/legacy_implicit_noexcept_build.srctree0000644000175100001770000000115200000000000025354 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import bar"

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup

setup(
  ext_modules = cythonize("*.pyx", compiler_directives={'legacy_implicit_noexcept': True}),
)


######## bar.pyx ########

cdef int func_noexcept() noexcept:
    raise RuntimeError()

cdef int func_implicit():
    raise RuntimeError()

cdef int func_return_value() except -1:
    raise RuntimeError()

func_noexcept()
func_implicit()

try:
    func_return_value()
except RuntimeError:
    pass
else:
    assert False, 'Exception not raised'
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/lepage_1.pyx0000644000175100001770000000057300000000000017766 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> a = A(1,2,3)
    >>> a[0]
    1.0
    >>> a[1]
    2.0
    >>> a[2]
    3.0
"""

cdef class A:
    cdef double[3] x

    def __init__(self, *args):
        cdef int i, max
        max = len(args)
        if max > 3:
            max = 3
        for i from 0 <= i < max:
            self.x[i] = args[i]

    def __getitem__(self,i):
        return self.x[i]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/letnode_T766.pyx0000644000175100001770000000102000000000000020455 0ustar00runnerdocker00000000000000# mode: run
# ticket: t766
# tag: letnode

def test_letnode_range(int n):
    """
    >>> [i() for i in test_letnode_range(5)]
    [0, 1, 2, 3, 4]
    """
    ret = []
    for i in range(n):
        def bar(x=i):
            return x
        ret.append(bar)
    return ret

def test_letnode_enumerate(a):
    """
    >>> [i() for i in test_letnode_enumerate("abc")]
    [0, 1, 2]
    """
    cdef int n
    ret = []
    for n, i in enumerate(a):
        def bar(x=n):
            return x
        ret.append(bar)
    return ret
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/libc_math.pyx0000644000175100001770000000214400000000000020227 0ustar00runnerdocker00000000000000# mode: run

from libc.math cimport (M_E, M_LOG2E, M_LOG10E, M_LN2, M_LN10, M_PI, M_PI_2,
        M_PI_4, M_1_PI, M_2_PI, M_2_SQRTPI, M_SQRT2, M_SQRT1_2)
from libc.math cimport (acos, asin, atan, atan2, cos, modf, sin, sinf, sinl,
        tan, cosh, sinh, tanh, acosh, asinh, atanh, exp, log, log10, pow, sqrt)
cimport libc.math as libc_math


def test_pi():
    """
    >>> import math
    >>> test_pi() == math.pi
    True
    """
    return M_PI


def test_renamed_constants(math):
    """
    >>> import math
    >>> test_renamed_constants(math)
    """
    assert libc_math.M_E == libc_math.e == math.e
    assert libc_math.M_PI == libc_math.pi == math.pi


def test_sin(x):
    """
    >>> test_sin(0)
    0.0
    >>> from math import sin
    >>> [sin(k) == test_sin(k) for k in range(10)]
    [True, True, True, True, True, True, True, True, True, True]
    """
    return sin(x)


def test_sin_kwarg(x):
    """
    >>> test_sin_kwarg(0)
    0.0
    """
    return sin(x=x)


def test_modf(x):
    """
    >>> test_modf(2.5)
    (0.5, 2.0)
    """
    cdef double i
    cdef double f = modf(x, &i)
    return (f, i)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/libc_stdlib.pyx0000644000175100001770000000126700000000000020564 0ustar00runnerdocker00000000000000# mode: run

from libc.stdlib cimport abs as c_int_abs, qsort as libc_qsort


def libc_int_abs(int x):
    """
    >>> libc_int_abs(5)
    5
    >>> libc_int_abs(-5)
    5
    """
    return c_int_abs(x)


cdef int gt(const void* v1, const void* v2) noexcept nogil:
    return ((v1)[0] - (v2)[0])

cdef int lt(const void* v1, const void* v2) noexcept nogil:
    return - gt(v1, v2)

def qsort(values, direction='lt'):
    """
    >>> data = [1, 9, 3, 2, 5]
    >>> qsort(data, 'gt')
    [1, 2, 3, 5, 9]
    >>> qsort(data, 'lt')
    [9, 5, 3, 2, 1]
    """
    cdef int[5] carray = values[:5]
    libc_qsort(carray, 5, sizeof(int), lt if direction == 'lt' else gt)
    return carray
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/libc_time.pyx0000644000175100001770000000152400000000000020235 0ustar00runnerdocker00000000000000# tag: posix
from libc.stdlib  cimport getenv
from posix.stdlib cimport setenv, unsetenv
from libc.time    cimport *


def test_time():
    """
    >>> test_time()
    """
    cdef time_t t1, t2
    t1 = time(NULL)
    assert t1 != 0
    t1 = time(&t2)
    assert t1 == t2


def test_mktime():
    """
    >>> test_mktime()  # doctest:+ELLIPSIS
    (986138177, ...'Sun Apr  1 15:16:17 2001\\n')
    """
    cdef tm t, gmt
    cdef time_t tt
    cdef char *ct
    cdef char *tz

    tz = getenv("TZ")
    setenv("TZ", "UTC", 1)
    tzset()
    t.tm_sec = 17
    t.tm_min = 16
    t.tm_hour = 15
    t.tm_year = 101
    t.tm_mon = 3
    t.tm_mday = 1
    t.tm_isdst = 0
    tt = mktime(&t)
    assert tt != -1
    ct = ctime(&tt)
    assert ct != NULL
    if tz:
        setenv("TZ", tz, 1)
    else:
        unsetenv("TZ")
    tzset()
    return tt, ct
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/libcpp_algo.pyx0000644000175100001770000000127600000000000020565 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp

from libcpp cimport bool
from libcpp.algorithm cimport make_heap, sort_heap
from libcpp.vector cimport vector


# XXX should use std::greater, but I don't know how to wrap that.
cdef inline bool greater(const int &x, const int &y):
    return x > y


def heapsort(l, bool reverse=False):
    """
    >>> heapsort([3, 5, 1, 0, 2, 4])
    [0, 1, 2, 3, 4, 5]
    >>> heapsort([3, 5, 1, 0, 2, 4], reverse=True)
    [5, 4, 3, 2, 1, 0]
    """
    cdef vector[int] v = l

    if reverse:
        make_heap(v.begin(), v.end(), &greater)
        sort_heap(v.begin(), v.end(), &greater)
    else:
        make_heap(v.begin(), v.end())
        sort_heap(v.begin(), v.end())

    return v
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/libcpp_all.pyx0000644000175100001770000001122400000000000020405 0ustar00runnerdocker00000000000000# tag: cpp, no-cpp-locals

import cython

cimport libcpp

# cimport libcpp.atomic
cimport libcpp.deque
cimport libcpp.list
cimport libcpp.map
cimport libcpp.pair
cimport libcpp.queue
cimport libcpp.set
cimport libcpp.stack
cimport libcpp.vector
cimport libcpp.complex
cimport libcpp.limits

# from libcpp.atomic cimport *
from libcpp.deque  cimport *
from libcpp.list   cimport *
from libcpp.map    cimport *
from libcpp.pair   cimport *
from libcpp.queue  cimport *
from libcpp.set    cimport *
from libcpp.stack  cimport *
from libcpp.vector cimport *
from libcpp.complex cimport *
from libcpp.limits cimport *

# cdef libcpp.atomic.atomc[int]  a1 = atomic[int]()
cdef libcpp.deque.deque[int]   d1 = deque[int]()
cdef libcpp.list.list[int]     l1 = list[int]()
cdef libcpp.map.map[int,int]   m1 = map[int,int]()
cdef libcpp.pair.pair[int,int] p1 = pair[int,int](1,2)
cdef libcpp.queue.queue[int]   q1 = queue[int]()
cdef libcpp.set.set[int]       s1 = set[int]()
cdef libcpp.stack.stack[int]   t1 = stack[int]()
cdef libcpp.vector.vector[int] v1 = vector[int]()

cdef deque[int].iterator id1 = d1.begin()
cdef deque[int].iterator id2 = d1.end()
cdef deque[int].reverse_iterator rid1 = d1.rbegin()
cdef deque[int].reverse_iterator rid2 = d1.rend()

cdef list[int].iterator il1 = l1.begin()
cdef list[int].iterator il2 = l1.end()
cdef list[int].reverse_iterator ril1 = l1.rbegin()
cdef list[int].reverse_iterator ril2 = l1.rend()

cdef map[int,int].iterator im1 = m1.begin()
cdef map[int,int].iterator im2 = m1.end()
cdef map[int,int].reverse_iterator rim1 = m1.rbegin()
cdef map[int,int].reverse_iterator rim2 = m1.rend()
cdef pair[map[int,int].iterator, bint] pimb = m1.insert(p1)

cdef set[int].iterator is1 = s1.begin()
cdef set[int].iterator is2 = s1.end()
cdef set[int].reverse_iterator ris1 = s1.rbegin()
cdef set[int].reverse_iterator ris2 = s1.rend()
cdef pair[set[int].iterator, bint] pisb = s1.insert(4)

cdef vector[int].iterator iv1 = v1.begin()
cdef vector[int].iterator iv2 = v1.end()
cdef vector[int].reverse_iterator riv1 = v1.rbegin()
cdef vector[int].reverse_iterator riv2 = v1.rend()

def test_vector_coercion(*args):
    """
    >>> test_vector_coercion(1.75)
    [1.75]
    >>> test_vector_coercion(1, 10, 100)
    [1.0, 10.0, 100.0]
    """
    v = new vector[double]()
    for a in args:
        v.push_back(a)
    return [v[0][i] for i in range(v.size())]

def test_const_vector(*args):
    """
    >>> test_const_vector(1.75)
    [1.75]
    >>> test_const_vector(1, 10, 100)
    [1.0, 10.0, 100.0]
    """
    cdef vector[double] v
    for a in args:
        v.push_back(a)
    return const_vector_to_list(v)

cdef const_vector_to_list(const vector[double]& cv):
    cdef vector[double].const_iterator iter = cv.const_begin()
    cdef lst = []
    while iter != cv.const_end():
        lst.append(cython.operator.dereference(iter))
        cython.operator.preincrement(iter)
    return lst


cdef double dmax = numeric_limits[double].max()
cdef double dmin = numeric_limits[double].min()
cdef double deps = numeric_limits[double].epsilon()
cdef double dqnan = numeric_limits[double].quiet_NaN()
cdef double dsnan = numeric_limits[double].signaling_NaN()
cdef double dinf = numeric_limits[double].infinity()

cdef int imax = numeric_limits[int].max()
cdef int imin = numeric_limits[int].min()
cdef int ieps = numeric_limits[int].epsilon()
cdef int iqnan = numeric_limits[int].quiet_NaN()
cdef int isnan = numeric_limits[int].signaling_NaN()
cdef int iinf = numeric_limits[int].infinity()

#API checks for containers with std::allocator declared
from libcpp.memory cimport allocator

cdef libcpp.vector.vector[int,allocator[int]] vec_alloc_int = libcpp.vector.vector[int,allocator[int]](10,1)
assert vec_alloc_int.size() == 10

cdef libcpp.list.list[int,allocator[int]] list_alloc_int = libcpp.list.list[int,allocator[int]](10,1)
assert list_alloc_int.size() == 10

##Something about the default params breaks the auto-conversion...
def convert_to_vector(I):
    """
    >>> convert_to_vector([1,2,3,4])
    """
    cdef vector[int] x = I


def complex_operators():
    """
    >>> complex_operators()
    [-1.0, 0.0, 0.0, 2.0, 0.0, 2.0]
    """
    cdef libcpp.complex.complex[double] a = libcpp.complex.complex[double](0.0,1.0)
    cdef libcpp.complex.complex[double] r1=a*a
    cdef libcpp.complex.complex[double] r2=a*2.0
    cdef libcpp.complex.complex[double] r3=2.0*a
    return [r1.real(), r1.imag(), r2.real(), r2.imag(), r3.real(), r3.imag()]

def pair_comparison():
    """
    >>> pair_comparison()
    [False, True, False, True, False]
    """
    cdef pair[double, double] p1 = pair[double, double](1.0,2.0)
    cdef pair[double, double] p2 = pair[double, double](2.0,2.0)
    return [p1==p2,p1==p1,p1>p2,p1p2]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/line_profile_test.srctree0000644000175100001770000000711400000000000022644 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON test_profile.py

######## setup.py ###########

from distutils.extension import Extension
from distutils.core import setup
from Cython.Build import cythonize

extensions = [
    Extension("collatz", ["collatz.pyx"], define_macros=[('CYTHON_TRACE', '1')])
]

setup(
    ext_modules = cythonize(extensions)
)

######## test_profile.py ###########

try:
    import line_profiler
except ImportError:
    print("No line profiler, skipping test.")
    import sys
    sys.exit(0)


def assert_stats(profile, name):
    profile.print_stats()
    stats = profile.get_stats()
    assert len(stats.timings) > 0, "No profile stats."
    for key, timings in stats.timings.items():
        if key[-1] == name:
            assert len(timings) > 0
            break
    else:
        raise ValueError("No stats for %s." % name)


from collatz import collatz
func = collatz
profile = line_profiler.LineProfiler(func)
profile.runcall(func, 19)
assert_stats(profile, func.__name__)

from collatz import cp_collatz
func = cp_collatz
profile = line_profiler.LineProfiler(func)
profile.runcall(func, 19)
assert_stats(profile, func.__name__)

from collatz import run_generator, cy_generator
func = cy_generator
profile = line_profiler.LineProfiler(func)
profile.runcall(run_generator, 19)
assert_stats(profile, func.__name__)

from collatz import run_coro, cy_coro
func = cy_coro
profile = line_profiler.LineProfiler(func)
profile.runcall(run_coro, 19)
assert_stats(profile, func.__name__)

from collatz import PyClass
obj = PyClass()
func = obj.py_pymethod
profile = line_profiler.LineProfiler(func)
profile.runcall(func)
assert_stats(profile, func.__name__)

from collatz import CClass
obj = CClass()
func = obj.c_pymethod
profile = line_profiler.LineProfiler(func)
profile.runcall(func)
assert_stats(profile, func.__name__)

func = obj.cp_pymethod
profile = line_profiler.LineProfiler(func)
profile.runcall(func, 19)
assert_stats(profile, func.__name__)


######## collatz.pyx ###########
# cython: linetrace=True

cimport cython

@cython.binding(True)
def collatz(n):
    while n > 1:
        if n % 2 == 0:
            n //= 2
        else:
            n = 3*n+1


@cython.binding(True)
cpdef cp_collatz(n):
    while n > 1:
        if n % 2 == 0:
            n //= 2
        else:
            n = 3*n+1


@cython.binding(True)
def cy_generator(int n):
   x = 1
   for i in range(n):
       yield x + 2
       # waste some time to avoid 0 runtimes (line profiler cannot handle those)
       while (i + x) < n + 10:
           i += 2


@cython.binding(True)
def run_generator(n):
    assert len(list(cy_generator(n))) == n


@cython.binding(True)
async def cy_coro(int n):
    while n > 1:
        if n % 2 == 0:
            n //= 2
        else:
            n = 3*n+1
    x =  n  # make sure the computation does not get discarded


@cython.binding(True)
def run_coro(n):
    coro = cy_coro(n)
    try:
        coro.send(None)
    except StopIteration:
        assert True
    else:
        assert False, "Coroutine did not raise"


@cython.binding(True)
class PyClass(object):
    def py_pymethod(self):
        x = 1
        for i in range(10):
            a = x + 2
        return a * 3


@cython.binding(True)
cdef class CClass:
    def c_pymethod(self, c=2):
        for i in range(10):
            a = c + 1
        y = self.cmethod(c + a)
        return y * 4

    cpdef cp_pymethod(self, r):
        for i in range(10):
            a = r + 1
        z = self.c_pymethod(a) + self.cmethod(r)
        return z * 2

    cdef cmethod(self, s):
        for i in range(10):
            p = s + 3
        return p * 5
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/line_trace.pyx0000644000175100001770000003331300000000000020414 0ustar00runnerdocker00000000000000# cython: linetrace=True
# distutils: define_macros=CYTHON_TRACE_NOGIL=1
# mode: run
# tag: trace

import sys

from cpython.ref cimport PyObject, Py_INCREF, Py_XDECREF

cdef extern from "frameobject.h":
    ctypedef struct PyFrameObject:
        PyObject *f_trace

from cpython.pystate cimport (
    Py_tracefunc,
    PyTrace_CALL, PyTrace_EXCEPTION, PyTrace_LINE, PyTrace_RETURN,
    PyTrace_C_CALL, PyTrace_C_EXCEPTION, PyTrace_C_RETURN)

cdef extern from *:
    void PyEval_SetProfile(Py_tracefunc cfunc, PyObject *obj)
    void PyEval_SetTrace(Py_tracefunc cfunc, PyObject *obj)


map_trace_types = {
    PyTrace_CALL:        'call',
    PyTrace_EXCEPTION:   'exception',
    PyTrace_LINE:        'line',
    PyTrace_RETURN:      'return',
    PyTrace_C_CALL:      'ccall',
    PyTrace_C_EXCEPTION: 'cexc',
    PyTrace_C_RETURN:    'cret',
}.get


cdef int trace_trampoline(PyObject* _traceobj, PyFrameObject* _frame, int what, PyObject* _arg) except -1:
    """
    This is (more or less) what CPython does in sysmodule.c, function trace_trampoline().
    """
    cdef PyObject *tmp

    if what == PyTrace_CALL:
        if _traceobj is NULL:
            return 0
        callback = _traceobj
    elif _frame.f_trace:
        callback = _frame.f_trace
    else:
        return 0

    frame = _frame
    arg = _arg if _arg else None

    try:
        result = callback(frame, what, arg)
    except:
        PyEval_SetTrace(NULL, NULL)
        tmp = _frame.f_trace
        _frame.f_trace = NULL
        Py_XDECREF(tmp)
        raise

    if result is not None:
        # A bug in Py2.6 prevents us from calling the Python-level setter here,
        # or otherwise we would get miscalculated line numbers. Was fixed in Py2.7.
        tmp = _frame.f_trace
        Py_INCREF(result)
        _frame.f_trace = result
        Py_XDECREF(tmp)

    return 0


def _create_trace_func(trace):
    local_names = {}

    def _trace_func(frame, event, arg):
        if sys.version_info < (3,) and (
            'line_trace' not in frame.f_code.co_filename and
            '' not in frame.f_code.co_filename):
            # Prevent tracing into Py2 doctest functions.
            return None

        trace.append((map_trace_types(event, event), frame.f_lineno - frame.f_code.co_firstlineno))

        lnames = frame.f_code.co_varnames
        if frame.f_code.co_name in local_names:
            assert lnames == local_names[frame.f_code.co_name]
        else:
            local_names[frame.f_code.co_name] = lnames

        # Currently, the locals dict is empty for Cython code, but not for Python code.
        if frame.f_code.co_name.startswith('py_'):
            # Change this when we start providing proper access to locals.
            assert frame.f_locals, frame.f_code.co_name
        else:
            assert not frame.f_locals, frame.f_code.co_name

        return _trace_func
    return _trace_func


def _create_failing_call_trace_func(trace):
    func = _create_trace_func(trace)
    def _trace_func(frame, event, arg):
        if event == PyTrace_CALL:
            raise ValueError("failing call trace!")

        func(frame, event, arg)
        return _trace_func

    return _trace_func


def _create__failing_line_trace_func(trace):
    func = _create_trace_func(trace)
    def _trace_func(frame, event, arg):
        if event == PyTrace_LINE and trace:
            if trace and trace[0] == frame.f_code.co_name:
                # first line in the right function => fail!
                raise ValueError("failing line trace!")

        func(frame, event, arg)
        return _trace_func
    return _trace_func


def _create_disable_tracing(trace):
    func = _create_trace_func(trace)
    def _trace_func(frame, event, arg):
        if frame.f_lineno - frame.f_code.co_firstlineno == 2:
            PyEval_SetTrace(NULL, NULL)
            return None

        func(frame, event, arg)
        return _trace_func

    return _trace_func


def cy_add(a,b):
    x = a + b     # 1
    return x      # 2


def cy_add_with_nogil(a,b):
    cdef int z, x=a, y=b         # 1
    with nogil:                  # 2
        z = 0                    # 3
        z += cy_add_nogil(x, y)  # 4
    return z                     # 5


def global_name(global_name):
    # See GH #1836: accessing "frame.f_locals" deletes locals from globals dict.
    return global_name + 321


cdef int cy_add_nogil(int a, int b) except -1 nogil:
    x = a + b   # 1
    return x    # 2


def cy_try_except(func):
    try:
        return func()
    except KeyError as exc:
        raise AttributeError(exc.args[0])


# CPython 3.11 has an issue when these Python functions are implemented inside of doctests and the trace function fails.
# https://github.com/python/cpython/issues/94381
plain_python_functions = {}
exec("""
def py_add(a,b):
    x = a+b
    return x

def py_add_with_nogil(a,b):
    x=a; y=b                     # 1
    for _ in range(1):           # 2
        z = 0                    # 3
        z += py_add(x, y)        # 4
    return z

def py_return(retval=123): return retval
""", plain_python_functions)


def run_trace(func, *args, bint with_sys=False):
    """
    >>> py_add = plain_python_functions['py_add']
    >>> run_trace(py_add, 1, 2)
    [('call', 0), ('line', 1), ('line', 2), ('return', 2)]
    >>> run_trace(cy_add, 1, 2)
    [('call', 0), ('line', 1), ('line', 2), ('return', 2)]

    >>> run_trace(py_add, 1, 2, with_sys=True)
    [('call', 0), ('line', 1), ('line', 2), ('return', 2)]
    >>> run_trace(cy_add, 1, 2, with_sys=True)
    [('call', 0), ('line', 1), ('line', 2), ('return', 2)]

    >>> result = run_trace(cy_add_with_nogil, 1, 2)
    >>> result[:5]
    [('call', 0), ('line', 1), ('line', 2), ('line', 3), ('line', 4)]
    >>> result[5:9]
    [('call', 0), ('line', 1), ('line', 2), ('return', 2)]
    >>> result[9:]
    [('line', 2), ('line', 5), ('return', 5)]

    >>> result = run_trace(cy_add_with_nogil, 1, 2, with_sys=True)
    >>> result[:5]  # sys
    [('call', 0), ('line', 1), ('line', 2), ('line', 3), ('line', 4)]
    >>> result[5:9]  # sys
    [('call', 0), ('line', 1), ('line', 2), ('return', 2)]
    >>> result[9:]  # sys
    [('line', 2), ('line', 5), ('return', 5)]

    >>> py_add_with_nogil = plain_python_functions['py_add_with_nogil']
    >>> result = run_trace(py_add_with_nogil, 1, 2)
    >>> result[:5]  # py
    [('call', 0), ('line', 1), ('line', 2), ('line', 3), ('line', 4)]
    >>> result[5:9]  # py
    [('call', 0), ('line', 1), ('line', 2), ('return', 2)]
    >>> result[9:]  # py
    [('line', 2), ('line', 5), ('return', 5)]

    >>> run_trace(global_name, 123)
    [('call', 0), ('line', 2), ('return', 2)]
    >>> run_trace(global_name, 111)
    [('call', 0), ('line', 2), ('return', 2)]
    >>> run_trace(global_name, 111, with_sys=True)
    [('call', 0), ('line', 2), ('return', 2)]
    >>> run_trace(global_name, 111, with_sys=True)
    [('call', 0), ('line', 2), ('return', 2)]
    """
    trace = []
    trace_func = _create_trace_func(trace)
    if with_sys:
        sys.settrace(trace_func)
    else:
        PyEval_SetTrace(trace_trampoline, trace_func)
    try:
        func(*args)
    finally:
        if with_sys:
            sys.settrace(None)
        else:
            PyEval_SetTrace(NULL, NULL)
    return trace


def run_trace_with_exception(func, bint with_sys=False, bint fail=False):
    """
    >>> py_return = plain_python_functions["py_return"]
    >>> run_trace_with_exception(py_return)
    OK: 123
    [('call', 0), ('line', 1), ('line', 2), ('call', 0), ('line', 0), ('return', 0), ('return', 2)]
    >>> run_trace_with_exception(py_return, with_sys=True)
    OK: 123
    [('call', 0), ('line', 1), ('line', 2), ('call', 0), ('line', 0), ('return', 0), ('return', 2)]

    >>> run_trace_with_exception(py_return, fail=True)
    ValueError('failing line trace!')
    [('call', 0)]

    #>>> run_trace_with_exception(lambda: 123, with_sys=True, fail=True)
    #ValueError('huhu')
    #[('call', 0), ('line', 1), ('line', 2), ('call', 0), ('line', 0), ('return', 0), ('return', 2)]

    >>> def py_raise_exc(exc=KeyError('huhu')): raise exc
    >>> run_trace_with_exception(py_raise_exc)
    AttributeError('huhu')
    [('call', 0), ('line', 1), ('line', 2), ('call', 0), ('line', 0), ('exception', 0), ('return', 0), ('line', 3), ('line', 4), ('return', 4)]
    >>> run_trace_with_exception(py_raise_exc, with_sys=True)
    AttributeError('huhu')
    [('call', 0), ('line', 1), ('line', 2), ('call', 0), ('line', 0), ('exception', 0), ('return', 0), ('line', 3), ('line', 4), ('return', 4)]
    >>> run_trace_with_exception(py_raise_exc, fail=True)
    ValueError('failing line trace!')
    [('call', 0)]

    #>>> run_trace_with_exception(raise_exc, with_sys=True, fail=True)
    #ValueError('huhu')
    #[('call', 0), ('line', 1), ('line', 2), ('call', 0), ('line', 0), ('exception', 0), ('return', 0), ('line', 3), ('line', 4), ('return', 4)]
    """
    trace = ['cy_try_except' if fail else 'NO ERROR']
    trace_func = _create__failing_line_trace_func(trace) if fail else _create_trace_func(trace)
    if with_sys:
        sys.settrace(trace_func)
    else:
        PyEval_SetTrace(trace_trampoline, trace_func)
    try:
        try:
            retval = cy_try_except(func)
        except ValueError as exc:
            print("%s(%r)" % (type(exc).__name__, str(exc)))
        except AttributeError as exc:
            print("%s(%r)" % (type(exc).__name__, str(exc)))
        else:
            print('OK: %r' % retval)
    finally:
        if with_sys:
            sys.settrace(None)
        else:
            PyEval_SetTrace(NULL, NULL)
    return trace[1:]


def fail_on_call_trace(func, *args):
    """
    >>> py_add = plain_python_functions["py_add"]
    >>> fail_on_call_trace(py_add, 1, 2)
    Traceback (most recent call last):
    ValueError: failing call trace!

    >>> fail_on_call_trace(cy_add, 1, 2)
    Traceback (most recent call last):
    ValueError: failing call trace!
    """
    trace = []
    trace_func = _create_failing_call_trace_func(trace)
    PyEval_SetTrace(trace_trampoline, trace_func)
    try:
        func(*args)
    finally:
        PyEval_SetTrace(NULL, NULL)
    assert not trace


def fail_on_line_trace(fail_func, add_func, nogil_add_func):
    """
    >>> result = fail_on_line_trace(None, cy_add, cy_add_with_nogil)
    >>> len(result)
    17
    >>> result[:5]
    ['NO ERROR', ('call', 0), ('line', 1), ('line', 2), ('return', 2)]
    >>> result[5:10]
    [('call', 0), ('line', 1), ('line', 2), ('line', 3), ('line', 4)]
    >>> result[10:14]
    [('call', 0), ('line', 1), ('line', 2), ('return', 2)]
    >>> result[14:]
    [('line', 2), ('line', 5), ('return', 5)]

    >>> py_add = plain_python_functions["py_add"]
    >>> py_add_with_nogil = plain_python_functions['py_add_with_nogil']
    >>> result = fail_on_line_trace(None, py_add, py_add_with_nogil)
    >>> len(result)
    17
    >>> result[:5]  # py
    ['NO ERROR', ('call', 0), ('line', 1), ('line', 2), ('return', 2)]
    >>> result[5:10]  # py
    [('call', 0), ('line', 1), ('line', 2), ('line', 3), ('line', 4)]
    >>> result[10:14]  # py
    [('call', 0), ('line', 1), ('line', 2), ('return', 2)]
    >>> result[14:]  # py
    [('line', 2), ('line', 5), ('return', 5)]

    >>> result = fail_on_line_trace('cy_add_with_nogil', cy_add, cy_add_with_nogil)
    failing line trace!
    >>> result
    ['cy_add_with_nogil', ('call', 0), ('line', 1), ('line', 2), ('return', 2), ('call', 0)]

    >>> result = fail_on_line_trace('py_add_with_nogil', py_add, py_add_with_nogil)  # py
    failing line trace!
    >>> result  # py
    ['py_add_with_nogil', ('call', 0), ('line', 1), ('line', 2), ('return', 2), ('call', 0)]

    >>> result = fail_on_line_trace('cy_add_nogil', cy_add, cy_add_with_nogil)
    failing line trace!
    >>> result[:5]
    ['cy_add_nogil', ('call', 0), ('line', 1), ('line', 2), ('return', 2)]
    >>> result[5:]
    [('call', 0), ('line', 1), ('line', 2), ('line', 3), ('line', 4), ('call', 0)]

    >>> result = fail_on_line_trace('py_add', py_add, py_add_with_nogil)  # py
    failing line trace!
    >>> result[:5]  # py
    ['py_add', ('call', 0), ('line', 1), ('line', 2), ('return', 2)]
    >>> result[5:]  # py
    [('call', 0), ('line', 1), ('line', 2), ('line', 3), ('line', 4), ('call', 0)]
    """
    cdef int x = 1
    trace = ['NO ERROR']
    exception = None
    trace_func = _create__failing_line_trace_func(trace)
    PyEval_SetTrace(trace_trampoline, trace_func)
    try:
        x += 1
        add_func(1, 2)
        x += 1
        if fail_func:
            trace[0] = fail_func  # trigger error on first line
        x += 1
        nogil_add_func(3, 4)
        x += 1
    except Exception as exc:
        exception = str(exc)
    finally:
        PyEval_SetTrace(NULL, NULL)
    if exception:
        print(exception)
    else:
        assert x == 5
    return trace


def disable_trace(func, *args, bint with_sys=False):
    """
    >>> py_add = plain_python_functions["py_add"]
    >>> disable_trace(py_add, 1, 2)
    [('call', 0), ('line', 1)]
    >>> disable_trace(py_add, 1, 2, with_sys=True)
    [('call', 0), ('line', 1)]

    >>> disable_trace(cy_add, 1, 2)
    [('call', 0), ('line', 1)]
    >>> disable_trace(cy_add, 1, 2, with_sys=True)
    [('call', 0), ('line', 1)]

    >>> disable_trace(cy_add_with_nogil, 1, 2)
    [('call', 0), ('line', 1)]
    >>> disable_trace(cy_add_with_nogil, 1, 2, with_sys=True)
    [('call', 0), ('line', 1)]
    """
    trace = []
    trace_func = _create_disable_tracing(trace)
    if with_sys:
        sys.settrace(trace_func)
    else:
        PyEval_SetTrace(trace_trampoline, trace_func)
    try:
        func(*args)
    finally:
        if with_sys:
            sys.settrace(None)
        else:
            PyEval_SetTrace(NULL, NULL)
    return trace
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/list.pyx0000644000175100001770000001607200000000000017265 0ustar00runnerdocker00000000000000
cimport cython

def f(obj1, obj2, obj3, obj4, obj5):
    """
    >>> f(1, 2, 3, 4, 5)
    []
    """
    obj1 = []
    return obj1

def g(obj1, obj2, obj3, obj4, obj5):
    """
    >>> g(1, 2, 3, 4, 5)
    [2]
    """
    obj1 = [obj2]
    return obj1

def h(obj1, obj2, obj3, obj4, obj5):
    """
    >>> h(1, 2, 3, 4, 5)
    [2, 3]
    """
    obj1 = [obj2, obj3]
    return obj1

def j(obj1, obj2, obj3, obj4, obj5):
    """
    >>> j(1, 2, 3, 4, 5)
    [2, 3, 4]
    """
    obj1 = [obj2, obj3, obj4]
    return obj1

def k(obj1, obj2, obj3, obj4, obj5):
    """
    >>> k(1, 2, 3, 4, 5)
    [17, 42, 88]
    """
    obj1 = [17, 42, 88]
    return obj1

@cython.test_fail_if_path_exists("//SimpleCallNode")
def test_list_call(ob):
    """
    >>> def f():
    ...     yield 1
    ...     yield 2
    ...
    >>> list(f())
    [1, 2]
    """
    return list(ob)

def test_list_sort():
    """
    >>> test_list_sort()
    [1, 2, 3, 4]
    """
    cdef list l1
    l1 = [2,3,1,4]
    l1.sort()
    return l1

def test_list_sort_reversed():
    cdef list l1
    l1 = [2,3,1,4]
    l1.sort(reversed=True)
    return l1

def test_list_reverse():
    """
    >>> test_list_reverse()
    [1, 2, 3, 4]
    """
    cdef list l1
    l1 = [4,3,2,1]
    l1.reverse()
    return l1


@cython.test_assert_path_exists(
    '//SimpleCallNode//AttributeNode[@entry.cname = "__Pyx_PyList_Append"]',
)
def test_list_append():
    """
    >>> test_list_append()
    [1, 2, 3, 4]
    """
    cdef list l1 = [1,2]
    l1.append(3)
    l1.append(4)
    return l1


@cython.test_assert_path_exists(
    '//SimpleCallNode//NameNode[@entry.cname = "__Pyx_PyList_Append"]',
)
def test_list_append_unbound():
    """
    >>> test_list_append_unbound()
    [1, 2, 3, 4]
    """
    cdef list l1 = [1,2]
    list.append(l1, 3)
    list.append(l1, 4)
    return l1


@cython.test_assert_path_exists(
    '//SimpleCallNode//NameNode[@entry.cname = "__Pyx_PyList_Append"]',
)
def test_list_append_unbound_assigned():
    """
    >>> test_list_append_unbound_assigned()
    [1, 2, 3, 4]
    """
    append = list.append
    cdef list l1 = [1,2]
    append(l1, 3)
    append(l1, 4)
    return l1


def test_list_append_insert():
    """
    >>> test_list_append_insert()
    ['first', 'second']
    """
    cdef list l = []
    l.append("second")
    l.insert(0, "first")
    return l

def test_list_pop():
    """
    >>> test_list_pop()
    (2, [1])
    """
    cdef list l1
    l1 = [1,2]
    two = l1.pop()
    return two, l1

def test_list_pop0():
    """
    >>> test_list_pop0()
    (1, [2])
    """
    cdef list l1
    l1 = [1,2]
    one = l1.pop(0)
    return one, l1

def test_list_pop_all():
    """
    >>> test_list_pop_all()
    True
    """
    cdef list l1
    l1 = [1,2]
    i = 0
    try:
        l1.pop()
        i = 1
        l1.pop(-1)
        i = 2
        l1.pop(0)
        i = 3
    except IndexError:
        return i == 2
    return False


@cython.test_assert_path_exists(
    '//PythonCapiCallNode//PythonCapiFunctionNode[@cname = "__Pyx_ListComp_Append"]',
    '//PythonCapiCallNode//PythonCapiFunctionNode[@cname = "__Pyx_PyList_Append"]',
)
def test_list_extend(seq=None, x=4):
    """
    >>> test_list_extend()
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
    >>> test_list_extend([])
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
    >>> test_list_extend([1])
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1]
    >>> test_list_extend([1, 2])
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2]
    """
    cdef list l = [1,2,3]
    l.extend([])
    l.extend(())
    l.extend(set())  # not currently optimised (not worth the trouble)
    assert l == [1,2,3]
    assert len(l) == 3
    l.extend([4,x+1,6])
    l.extend([7,8,9,10,11,12,13,14,15,16])
    if seq is not None:
        l.extend(seq)
    return l


@cython.test_assert_path_exists(
    '//PythonCapiCallNode//PythonCapiFunctionNode[@cname = "__Pyx_ListComp_Append"]',
    '//PythonCapiCallNode//PythonCapiFunctionNode[@cname = "__Pyx_PyList_Append"]',
)
def test_list_extend_unbound(seq=None, x=4):
    """
    >>> test_list_extend_unbound()
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
    >>> test_list_extend_unbound([])
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
    >>> test_list_extend_unbound([1])
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1]
    >>> test_list_extend_unbound([1, 2])
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2]
    """
    cdef list l = [1,2,3]
    list.extend(l, [])
    list.extend(l, ())
    try:
        list.extend((), ())
    except TypeError:
        pass
    else:
        assert False, "TypeError not raised!"
    list.extend(l, set())  # not currently optimised (not worth the trouble)
    assert l == [1,2,3]
    assert len(l) == 3
    list.extend(l, [4,x+1,6])
    list.extend(l, [7,8,9,10,11,12,13,14,15,16])
    if seq is not None:
        list.extend(l, seq)
    return l

@cython.test_assert_path_exists(
    '//PythonCapiCallNode//PythonCapiFunctionNode[@cname = "__Pyx_ListComp_Append"]',
    '//PythonCapiCallNode//PythonCapiFunctionNode[@cname = "__Pyx_PyList_Append"]',
)
def test_list_extend_sideeffect(seq=None, exc=False):
    """
    >>> test_list_extend_sideeffect()
    ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], [4, 6, 7, 8])
    >>> test_list_extend_sideeffect([])
    ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], [4, 6, 7, 8])
    >>> test_list_extend_sideeffect([], exc=True)
    ([1, 2, 3, 10, 11, 12, 13, 14, 15, 16], [4, 7, 8])
    >>> test_list_extend_sideeffect([1])
    ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1], [4, 6, 7, 8])
    >>> test_list_extend_sideeffect([1], exc=True)
    ([1, 2, 3, 10, 11, 12, 13, 14, 15, 16, 1], [4, 7, 8])
    >>> test_list_extend_sideeffect([1, 2])
    ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2], [4, 6, 7, 8])
    """
    calls = []
    def sideeffect(value):
        calls.append(value)
        return value
    def fail(value):
        if exc:
            raise TypeError("HUHU")
        return value

    cdef list l = [1,2,3]
    l.extend([])
    l.extend(())
    l.extend(set())  # not currently optimised (not worth the trouble)
    assert l == [1,2,3]
    assert len(l) == 3

    # Must first build all items, then append them in order.
    # If building one value fails, none of them must be appended.
    try:
        l.extend([sideeffect(4), fail(5), sideeffect(6)])
    except TypeError as e:
        assert exc
        assert "HUHU" in str(e)
    else:
        assert not exc

    try:
        l.extend([sideeffect(7), sideeffect(8), fail(9)])
    except TypeError as e:
        assert exc
        assert "HUHU" in str(e)
    else:
        assert not exc

    l.extend([10,11,12,13,14,15,16])
    if seq is not None:
        l.extend(seq)
    return l, calls


def test_none_list_extend(list l):
    """
    >>> test_none_list_extend([])
    [1, 2, 3]
    >>> test_none_list_extend([0, 0, 0])
    [0, 0, 0, 1, 2, 3]
    >>> test_none_list_extend(None)
    123
    """
    try:
        l.extend([1,2,3])
    except AttributeError:
        return 123
    return l
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/list_comp_in_closure_T598.pyx0000644000175100001770000000457200000000000023260 0ustar00runnerdocker00000000000000# mode: run
# tag: closures
# ticket: t598
# cython: language_level=3

def list_comp_in_closure():
    """
    >>> list_comp_in_closure()
    [0, 4, 8]
    """
    x = 'abc'
    def f():
        return x
    result = [x*2 for x in range(5) if x % 2 == 0]
    assert x == 'abc' # don't leak in Py3 code
    assert f() == 'abc' # don't leak in Py3 code
    return result

def pytyped_list_comp_in_closure():
    """
    >>> pytyped_list_comp_in_closure()
    [0, 4, 8]
    """
    cdef object x
    x = 'abc'
    def f():
        return x
    result = [x*2 for x in range(5) if x % 2 == 0]
    assert x == 'abc' # don't leak in Py3 code
    assert f() == 'abc' # don't leak in Py3 code
    return result

def pytyped_list_comp_in_closure_repeated():
    """
    >>> pytyped_list_comp_in_closure_repeated()
    [0, 4, 8]
    """
    cdef object x
    x = 'abc'
    def f():
        return x
    for i in range(3):
        result = [x*2 for x in range(5) if x % 2 == 0]
    assert x == 'abc' # don't leak in Py3 code
    assert f() == 'abc' # don't leak in Py3 code
    return result

def genexpr_in_closure():
    """
    >>> genexpr_in_closure()
    [0, 4, 8]
    """
    x = 'abc'
    def f():
        return x
    result = list( x*2 for x in range(5) if x % 2 == 0 )
    assert x == 'abc' # don't leak in Py3 code
    assert f() == 'abc' # don't leak in Py3 code
    return result

def pytyped_genexpr_in_closure():
    """
    >>> pytyped_genexpr_in_closure()
    [0, 4, 8]
    """
    cdef object x
    x = 'abc'
    def f():
        return x
    result = list( x*2 for x in range(5) if x % 2 == 0 )
    assert x == 'abc' # don't leak in Py3 code
    assert f() == 'abc' # don't leak in Py3 code
    return result

def pytyped_genexpr_in_closure_repeated():
    """
    >>> pytyped_genexpr_in_closure_repeated()
    [0, 4, 8]
    """
    cdef object x
    x = 'abc'
    def f():
        return x
    for i in range(3):
        result = list( x*2 for x in range(5) if x % 2 == 0 )
    assert x == 'abc' # don't leak in Py3 code
    assert f() == 'abc' # don't leak in Py3 code
    return result

def genexpr_scope_in_closure():
    """
    >>> genexpr_scope_in_closure()
    [0, 4, 8]
    """
    i = 2
    x = 'abc'
    def f():
        return i, x
    result = list( x*i for x in range(5) if x % 2 == 0 )
    assert x == 'abc' # don't leak in Py3 code
    assert f() == (2,'abc') # don't leak in Py3 code
    return result
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/list_pop.pyx0000644000175100001770000001224700000000000020143 0ustar00runnerdocker00000000000000cimport cython

from libc.stdint cimport uint64_t

class A:
    def pop(self, *args):
        print args
        return None

cdef class B:
    """
    >>> B().call_pop()
    'B'
    """
    cdef pop(self):
        return "B"
    def call_pop(self):
        return self.pop()


@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def simple_pop(L):
    """
    >>> L = list(range(10))
    >>> simple_pop(L)
    9
    >>> simple_pop(L)
    8
    >>> L
    [0, 1, 2, 3, 4, 5, 6, 7]
    >>> while L:
    ...    _ = simple_pop(L)

    >>> L
    []
    >>> simple_pop(L)
    Traceback (most recent call last):
    IndexError: pop from empty list

    >>> simple_pop(A())
    ()
    """
    return L.pop()

@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def simple_pop_typed(list L):
    """
    >>> L = list(range(10))
    >>> simple_pop_typed(L)
    9
    >>> simple_pop_typed(L)
    8
    >>> L
    [0, 1, 2, 3, 4, 5, 6, 7]
    >>> while L:
    ...    _ = simple_pop_typed(L)

    >>> L
    []
    >>> simple_pop_typed(L)
    Traceback (most recent call last):
    IndexError: pop from empty list
    """
    return L.pop()


@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def index_pop(L, int i):
    """
    >>> L = list(range(10))
    >>> index_pop(L, 2)
    2
    >>> index_pop(L, -10)
    Traceback (most recent call last):
    IndexError: pop index out of range
    >>> index_pop(L, -2)
    8
    >>> L
    [0, 1, 3, 4, 5, 6, 7, 9]
    >>> index_pop(L, 100)
    Traceback (most recent call last):
    IndexError: pop index out of range
    >>> index_pop(L, -100)
    Traceback (most recent call last):
    IndexError: pop index out of range

    >>> while L:
    ...    _ = index_pop(L, 0)

    >>> L
    []

    >>> index_pop(L, 0)
    Traceback (most recent call last):
    IndexError: pop from empty list

    >>> index_pop(A(), 3)
    (3,)
    """
    return L.pop(i)

@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def index_pop_typed(list L, int i):
    """
    >>> L = list(range(10))
    >>> index_pop_typed(L, 2)
    2
    >>> index_pop_typed(L, -2)
    8
    >>> L
    [0, 1, 3, 4, 5, 6, 7, 9]
    >>> index_pop_typed(L, 100)
    Traceback (most recent call last):
    IndexError: pop index out of range
    >>> index_pop_typed(L, -100)
    Traceback (most recent call last):
    IndexError: pop index out of range

    >>> index_pop_typed(None, 0)
    Traceback (most recent call last):
    AttributeError: 'NoneType' object has no attribute 'pop'

    >>> while L:
    ...    _ = index_pop_typed(L, 0)

    >>> L
    []

    >>> index_pop_typed(L, 0)
    Traceback (most recent call last):
    IndexError: pop from empty list
    """
    return L.pop(i)


@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def index_pop_list_object_index(list L, i):
    """
    >>> L = list(range(10))
    >>> index_pop_list_object_index(L, 2)
    2
    >>> index_pop_list_object_index(L, -2)
    8
    >>> L
    [0, 1, 3, 4, 5, 6, 7, 9]
    >>> index_pop_list_object_index(L, 100)
    Traceback (most recent call last):
    IndexError: pop index out of range
    >>> index_pop_list_object_index(L, -100)
    Traceback (most recent call last):
    IndexError: pop index out of range

    >>> index_pop_list_object_index(None, 0)
    Traceback (most recent call last):
    AttributeError: 'NoneType' object has no attribute 'pop'
    >>> index_pop_list_object_index([1], None)    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> index_pop_list_object_index([1], 'abc')   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...

    >>> while L:
    ...    _ = index_pop_list_object_index(L, 0)

    >>> L
    []

    >>> index_pop_list_object_index(L, 0)
    Traceback (most recent call last):
    IndexError: pop from empty list
    """
    return L.pop(i)


@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def index_pop_literal(list L):
    """
    >>> L = list(range(10))
    >>> index_pop_literal(L)
    0
    >>> L
    [1, 2, 3, 4, 5, 6, 7, 8, 9]

    >>> while L:
    ...    _ = index_pop_literal(L)

    >>> L
    []

    >>> index_pop_literal(L)
    Traceback (most recent call last):
    IndexError: pop from empty list
    """
    return L.pop(0)


@cython.test_fail_if_path_exists('//PythonCapiCallNode')
def crazy_pop(L):
    """
    >>> crazy_pop(list(range(10)))    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: pop... argument...
    >>> crazy_pop(A())
    (1, 2, 3)
    """
    return L.pop(1, 2, 3)


def method_name():
    """
    >>> method_name()
    'pop'
    """
    return [].pop.__name__


def object_pop_large_int():
    """
    >>> object_pop_large_int()
    {}
    """
    cdef object foo = {}
    cdef uint64_t bar = 201213467776703617ULL

    foo[bar] = None
    assert (bar) in foo
    foo.pop(bar)
    return foo
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/listcomp.pyx0000644000175100001770000001116700000000000020144 0ustar00runnerdocker00000000000000# mode: run
# tag: listcomp, comprehension

cimport cython


def smoketest():
    """
    >>> smoketest()
    [0, 4, 8]
    """
    x = 'abc'
    result = [x*2 for x in range(5) if x % 2 == 0]
    assert x != 'abc'
    return result


def list_genexp():
    """
    >>> list_genexp()
    [0, 4, 8]
    """
    x = 'abc'
    result = list(x*2 for x in range(5) if x % 2 == 0)
    assert x == 'abc'
    return result


def int_runvar():
    """
    >>> int_runvar()
    [0, 4, 8]
    """
    cdef int x
    print [x*2 for x in range(5) if x % 2 == 0]


cdef class A:
    def __repr__(self): return u"A"

def typed():
    """
    >>> typed()
    [A, A, A]
    """
    cdef A obj
    print [obj for obj in [A(), A(), A()]]


def inferred_type():
    """
    >>> inferred_type()
    ['A', 'A', 'A']
    """
    print [cython.typeof(obj) for obj in [A(), A(), A()]]


def not_inferred_type():
    """
    >>> not_inferred_type()
    ['Python object', 'Python object', 'Python object']
    """
    print [cython.typeof(obj) for obj in [1, A(), 'abc']]


def iterdict():
    """
    >>> iterdict()
    [1, 2, 3]
    """
    cdef dict d = dict(a=1,b=2,c=3)
    l = [d[key] for key in d]
    l.sort()
    print l


listcomp_result = [ i*i for i in range(5) ]
def global_listcomp():
    """
    >>> [ i*i for i in range(5) ]
    [0, 1, 4, 9, 16]
    >>> listcomp_result
    [0, 1, 4, 9, 16]
    """


class ListCompInClass(object):
    """
    >>> x = ListCompInClass()
    >>> x.listcomp
    [1, 2, 3]
    """
    listcomp = [i+1 for i in range(3)]


cdef class ListCompInCClass:
    """
    >>> x = ListCompInCClass()
    >>> x.listcomp
    [1, 2, 3]
    """
    listcomp = [i+1 for i in range(3)]


def nested_result():
    """
    >>> nested_result()
    [[], [-1], [-1, 0], [-1, 0, 1]]
    """
    result = [[a-1 for a in range(b)] for b in range(4)]
    return result


def listcomp_as_condition(sequence):
    """
    >>> listcomp_as_condition(['a', 'b', '+'])
    True
    >>> listcomp_as_condition('ab+')
    True
    >>> listcomp_as_condition('abc')
    False
    """
    if [1 for c in sequence if c in '+-*/<=>!%&|([^~,']:
        return True
    return False


@cython.test_fail_if_path_exists("//SimpleCallNode//ComprehensionNode")
@cython.test_assert_path_exists("//ComprehensionNode")
def sorted_listcomp(sequence):
    """
    >>> sorted_listcomp([])
    []
    >>> sorted_listcomp([1])
    [2]
    >>> sorted_listcomp([3,2,4])
    [3, 4, 5]
    """
    return sorted([ n+1 for n in sequence ])


@cython.test_fail_if_path_exists("//IfStatNode",
                                 "//ComprehensionAppendNode")
@cython.test_assert_path_exists("//ComprehensionNode")
def listcomp_const_condition_false():
    """
    >>> listcomp_const_condition_false()
    []
    """
    return [x*2 for x in range(3) if False]


@cython.test_fail_if_path_exists("//IfStatNode",
                                 "//ComprehensionAppendNode")
@cython.test_assert_path_exists("//ComprehensionNode")
def listcomp_const_condition_false_bool_test():
    """
    >>> listcomp_const_condition_false_bool_test()
    True
    """
    return not [l for l in [1] if False]


@cython.test_fail_if_path_exists("//IfStatNode",
                                 "//ComprehensionAppendNode")
@cython.test_assert_path_exists("//ComprehensionNode")
def listcomp_const_condition_false_assert():
    """
    >>> listcomp_const_condition_false_assert()
    """
    assert not [l for l in [1] if False]


@cython.test_fail_if_path_exists("//ComprehensionNode//IfStatNode",
                                 "//ComprehensionAppendNode")
@cython.test_assert_path_exists("//ComprehensionNode",
                                "//IfStatNode")
def listcomp_const_condition_false_if():
    """
    >>> listcomp_const_condition_false_if()
    True
    """
    if not [l for l in [1] if False]:
        return True
    return False


@cython.test_fail_if_path_exists("//ComprehensionNode//IfStatNode",
                                 "//ComprehensionAppendNode")
@cython.test_assert_path_exists("//ComprehensionNode",
                                "//IfStatNode")
def listcomp_const_condition_false_typed_error():
    """
    >>> listcomp_const_condition_false_typed_error()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    cdef str l
    if not [l for l in [1] if False]:
        return True
    return False


@cython.test_fail_if_path_exists("//IfStatNode")
@cython.test_assert_path_exists("//ComprehensionNode",
                                "//ComprehensionAppendNode")
def listcomp_const_condition_true():
    """
    >>> listcomp_const_condition_true()
    [0, 2, 4]
    """
    return [x*2 for x in range(3) if True]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/literal_lists.pyx0000644000175100001770000000320400000000000021155 0ustar00runnerdocker00000000000000__doc__ = """
    >>> test_chars(b'yo')
    (b'a', b'bc', b'yo')
    >>> try: test_chars(None)
    ... except TypeError: pass
"""

import sys

if sys.version_info[0] < 3:
    __doc__ = __doc__.replace(u"b'", u"'")

def repeated_literals():
    """
    >>> repeated_literals()
    p1: [4, 4]
    p2: [5, 5]
    """
    cdef int i
    cdef int* p1 = [4, 4]
    cdef int* p2 = [5, 5]

    print "p1: %s" % [ p1[i] for i in range(2) ]
    print "p2: %s" % [ p2[i] for i in range(2) ]

def test_ints(int x):
    """
    >>> test_ints(100)
    (100, 100, 100)
    """
    cdef list L = [1,2,3,x]
    cdef int* Li = [1,2,3,x]
    cdef int** Lii = [Li, &x]
    return L[3], Li[3], Lii[1][0]

def test_chars(foo):
    cdef char** ss = [b"a", b"bc", foo]
    return ss[0], ss[1], ss[2]

cdef struct MyStruct:
    int x
    int y
    double** data

cdef print_struct(MyStruct a):
    print a.x, a.y, a.data == NULL

def test_struct(int x, y):
    """
    >>> test_struct(-5, -10)
    -5 -10 True
    1 2 False
    """
    cdef MyStruct* aa = [[x,y, NULL], [x+1,y+1,NULL]]
    print_struct(aa[0])
    print_struct([1, 2, 1])

cdef int m_int = -1
cdef int* m_iarray = [4, m_int]
cdef int** m_piarray = [m_iarray, &m_int]
cdef char** m_carray = [b"a", b"bc"]
cdef MyStruct* m_structarray = [[m_int,0,NULL], [1,m_int+1,NULL]]

def test_module_level():
    """
    >>> test_module_level()
    4 -1
    4 -1
    True True
    1 0 True
    """
    print m_iarray[0], m_iarray[1]
    print m_piarray[0][0], m_piarray[1][0]
    print m_carray[0] == b"a", m_carray[1] == b"bc"
    print_struct(m_structarray[1])


# Make sure it's still naturally an object.

[0,1,2,3].append(4)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/literals.pyx0000644000175100001770000000377400000000000020136 0ustar00runnerdocker00000000000000# mode: run

def foo():
    """
    >>> foo()
    """
    a = 42
    a1 = 0123
    an1 = -0123
    assert a1 == -an1
    a2 = 0xabc
    an2 = -0xabc
    assert a2 == -an2
    a3 = 0xDEF
    an3 = -0xDEF
    assert a3 == -an3
    a4 = 1234567890L
    an4 = -1234567890L
    assert a4 == -an4
    a5 = 0o123
    an5 = -0o123
    assert a5 == -an5
    assert a5 == a1
    a6 = 0b101
    an6 = -0b101
    assert a6 == -an6 == 5

    b = 42.88e17
    b0a = 1.
    b0b = .1
    b0c = 1.1
    b0d = 1.e1
    b0e = .1e1
    b0f = 1.1e1
    b0g = 1.1e-1
    b0h = 1e1

    b1 = 3j
    b2 = 3.1415J

    b3 = c'X'
    c = "spanish inquisition"
    d = "this" "parrot" "is" "resting"
    e = 'single quoted string'
    f = '"this is quoted"'
    g = '''Triple single quoted string.'''
    h = """Triple double quoted string."""
    g1 = '''Two line triple
single quoted string.'''
    h1 = """Two line triple
double quoted string."""
    i = 'This string\
 has an ignored newline.'
    j = 'One-char escapes: \'\"\\\a\b\f\n\r\t\v'
    k = b'Oct and hex escapes: \1 \12 \123 \x45 \xaf \xAF'
    l = r'''This is\
a \three \line
raw string with some backslashes.'''
    m = 'Three backslashed ordinaries: \c\g\+'
    n = '''Triple single quoted string
with ' and " quotes'''
    o = """Triple double quoted string
with ' and " quotes"""
    p = "name_like_string"
    q = "NameLikeString2"
    r = "99_percent_un_namelike"
    s = "Not an \escape"
    t = b'this' b'parrot' b'is' b'resting'
    u = u'this' u'parrot' u'is' u'resting'


def test_float(x):
    """
    >>> test_float(1./3)
    True
    """
    return x == 1./3

def test_complex(x):
    """
    >>> test_complex(1j/3)
    True
    """
    return x == 0.3333333333333333j

def test_large_int(double x):
    """
    >>> test_large_int(0)
    2e+100
    """
    a = x + 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    a += 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    return a
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/literalslice.pyx0000644000175100001770000000156200000000000020764 0ustar00runnerdocker00000000000000__doc__ = u"""
  >>> test_str(1)
  'b'

  >>> test_unicode_ascii(2)
  u'c'
  >>> test_unicode(2) == u'\u00e4'
  True

  >>> test_int_list(2)
  3
  >>> test_str_list(1)
  'bcd'

  >>> test_int_tuple(2)
  3
  >>> test_str_tuple(0)
  'a'
  >>> test_mix_tuple(1)
  'abc'
  >>> test_mix_tuple(0)
  1
"""

import sys
IS_PY3 = sys.version_info[0] >= 3
if IS_PY3:
    __doc__ = __doc__.replace(u" u'", u" '")
else:
    __doc__ = __doc__.replace(u" b'", u" '")

def test_str(n):
    return "abcd"[n]

def test_unicode_ascii(n):
    return u"abcd"[n]

def test_unicode(n):
    return u"\u00fc\u00f6\u00e4"[n]

def test_int_list(n):
    return [1,2,3,4][n]

def test_str_list(n):
    return ["a","bcd","efg","xyz"][n]

def test_int_tuple(n):
    return (1,2,3,4)[n]

def test_str_tuple(n):
    return ("a","bcd","efg","xyz")[n]

def test_mix_tuple(n):
    return (1, "abc", u"\u00fc", 1.1)[n]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4127223
Cython-3.0.8/tests/run/locals.pyx0000644000175100001770000000513100000000000017561 0ustar00runnerdocker00000000000000# mode: run
# tag: builtins, locals, dir

def get_locals(x, *args, **kwds):
    """
    >>> sorted( get_locals(1,2,3, k=5).items() )
    [('args', (2, 3)), ('kwds', {'k': 5}), ('x', 1), ('y', 'hi'), ('z', 5)]
    >>> sorted( get_locals(1).items() )  # args and kwds should *always* be present even if not passed
    [('args', ()), ('kwds', {}), ('x', 1), ('y', 'hi'), ('z', 5)]
    """
    cdef int z = 5
    y = "hi"
    return locals()

def get_vars(x, *args, **kwds):
    """
    >>> sorted( get_vars(1,2,3, k=5).items() )
    [('args', (2, 3)), ('kwds', {'k': 5}), ('x', 1), ('y', 'hi'), ('z', 5)]
    >>> sorted( get_vars(1).items() )
    [('args', ()), ('kwds', {}), ('x', 1), ('y', 'hi'), ('z', 5)]
    """
    cdef int z = 5
    y = "hi"
    return vars()

def get_dir(x, *args, **kwds):
    """
    >>> sorted( get_dir(1,2,3, k=5) )
    ['args', 'kwds', 'x', 'y', 'z']
    >>> sorted( get_dir(1) )
    ['args', 'kwds', 'x', 'y', 'z']
    """
    cdef int z = 5
    y = "hi"
    return dir()

def in_locals(x, *args, **kwds):
    """
    >>> in_locals('z')
    True
    >>> in_locals('args')
    True
    >>> in_locals('X')
    False
    >>> in_locals('kwds')
    True
    """
    cdef int z = 5
    y = "hi"
    return x in locals()

def in_dir(x, *args, **kwds):
    """
    >>> in_dir('z')
    True
    >>> in_dir('args')
    True
    >>> in_dir('X')
    False
    >>> in_dir('kwds')
    True
    """
    cdef int z = 5
    y = "hi"
    return x in dir()

def in_vars(x, *args, **kwds):
    """
    >>> in_vars('z')
    True
    >>> in_vars('args')
    True
    >>> in_vars('X')
    False
    >>> in_vars('kwds')
    True
    """
    cdef int z = 5
    y = "hi"
    return x in vars()

def sorted(it):
    l = list(it)
    l.sort()
    return l

def locals_ctype():
    """
    >>> locals_ctype()
    False
    """
    cdef int *p = NULL
    return 'p' in locals()

def locals_ctype_inferred():
    """
    >>> locals_ctype_inferred()
    False
    """
    cdef int *p = NULL
    b = p
    return 'b' in locals()


def pass_on_locals(f):
    """
    >>> def print_locals(l, **kwargs):
    ...     print(sorted(l))

    >>> pass_on_locals(print_locals)
    ['f']
    ['f']
    ['f']
    """
    f(locals())
    f(l=locals())
    f(l=locals(), a=1)


def buffers_in_locals(object[char, ndim=1] a):
    """
    >>> sorted(buffers_in_locals(b'abcdefg'))
    ['a', 'b']
    """
    cdef object[unsigned char, ndim=1] b = a

    return locals()

def set_comp_scope():
    """
    locals should be evaluated in the outer scope
    >>> list(set_comp_scope())
    ['something']
    """
    something = 1
    return { b for b in locals().keys() }

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/locals_T732.pyx0000644000175100001770000000245500000000000020306 0ustar00runnerdocker00000000000000# mode: run
# ticket: t731
# tag: locals, vars, dir

cimport cython

LOCALS = locals()
GLOBALS = globals()
DIR_SAME = sorted(dir()) == sorted(globals().keys())


def test_module_locals_and_dir():
    """
    >>> LOCALS is GLOBALS
    True
    >>> DIR_SAME
    True
    """


def test_class_locals_and_dir():
    """
    >>> klass = test_class_locals_and_dir()
    >>> 'visible' in klass.locs and 'not_visible' not in klass.locs
    True
    >>> [n for n in klass.names if n not in {"__qualname__", "__annotations__"}]
    ['__module__', 'visible']
    """
    not_visible = 1234
    class Foo:
        visible = 4321
        names = dir()
        locs = locals()
    return Foo


@cython.test_fail_if_path_exists('//SortedDictKeysNode')
def test_class_dir_contains():
    """
    >>> klass = test_class_dir_contains()
    True
    False
    True
    False
    True
    False
    True
    True
    True
    """
    not_visible = 1234
    class Foo:
        visible = 4321
        print('visible' in dir())
        print('not_visible' in dir())
        print('not_visible' not in dir())
        print('locs' in dir())
        print('visible' in locals())
        print('locs' in locals())
        locs = locals()
        print('visible' in dir())
        print('locs' in dir())
        print('locs' in locals())
    return Foo
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/locals_expressions_T430.pyx0000644000175100001770000000156300000000000022742 0ustar00runnerdocker00000000000000# ticket: t430

__doc__ = u"""
>>> sorted( get_locals(1,2,3, k=5) .items())
[('args', (2, 3)), ('kwds', {'k': 5}), ('x', 1), ('y', 'hi'), ('z', 5)]

>>> sorted(get_locals_items(1,2,3, k=5))
[('args', (2, 3)), ('kwds', {'k': 5}), ('x', 1), ('y', 'hi'), ('z', 5)]

>>> sorted(get_locals_items_listcomp(1,2,3, k=5))
[('args', (2, 3)), ('kwds', {'k': 5}), ('x', 1), ('y', 'hi'), ('z', 5)]
"""

def get_locals(x, *args, **kwds):
    cdef int z = 5
    y = "hi"
    return locals()

def get_locals_items(x, *args, **kwds):
    cdef int z = 5
    y = "hi"
    return locals().items()

def get_locals_items_listcomp(x, *args, **kwds):
    # FIXME: 'item' should *not* appear in locals() yet, as locals()
    # is evaluated before assigning to item !
    cdef int z = 5
    y = "hi"
    return [ item for item in locals().items() ]

def sorted(it):
    l = list(it)
    l.sort()
    return l
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/locals_rebind_T429.pyx0000644000175100001770000000100100000000000021616 0ustar00runnerdocker00000000000000# ticket: t429

__doc__ = u"""
>>> sorted( get_locals(1,2,3, k=5) .items())
[('args', (2, 3)), ('kwds', {'k': 5}), ('x', 1), ('y', 'hi'), ('z', 5)]

"""

def get_locals(x, *args, **kwds):
    cdef int z = 5
    y = "hi"
    return locals()

def get_locals_rebound(x, *args, **kwds):
    """
    >>> get_locals_rebound(1,2,3)
    'REBOUND'
    """
    cdef int z = 5
    locals = _locals
    y = "hi"
    return locals()

def _locals(): return "REBOUND"

def sorted(it):
    l = list(it)
    l.sort()
    return l
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/longintrepr.pyx0000644000175100001770000000257500000000000020660 0ustar00runnerdocker00000000000000# mode: run

# Test longintrepr declarations by implementing a simple function

from cpython.longintrepr cimport *
cimport cython

@cython.cdivision(True)
def lshift(long a, unsigned long n):
    """
    Return a * 2^n as Python long.

    >>> print(lshift(3, 1))
    6
    >>> print(lshift(1, 30))
    1073741824
    >>> print(lshift(-12345, 115))
    512791237748899576593671817473776680960
    >>> print(-12345 << 115)
    -512791237748899576593671817473776680960
    >>> [i for i in range(100) if (65535 << i) != lshift(65535, i)]
    []
    >>> print(lshift(0, 12345))
    0
    >>> print(lshift(2**62, 0))   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError...
    """
    if not a:
        return _PyLong_New(0)
    cdef unsigned long apos = a if a > 0 else -a
    if (apos >> 1) >= PyLong_BASE:
        raise OverflowError

    cdef unsigned long index = n // PyLong_SHIFT
    cdef unsigned long shift = n % PyLong_SHIFT

    cdef digit d = apos
    cdef digit low = (d << shift) & PyLong_MASK
    cdef digit high = (d >> (PyLong_SHIFT - shift))

    if high == 0:
        ret = _PyLong_New(index + 1)
        ret.ob_digit[index] = low
    else:
        ret = _PyLong_New(index + 2)
        ret.ob_digit[index] = low
        ret.ob_digit[index + 1] = high

    while index >= 1:
        index -= 1
        ret.ob_digit[index] = 0

    return ret
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/longlongindex.pyx0000644000175100001770000000050300000000000021151 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> D = set_longlong(2**40, 2**50, 2, "yelp")
    >>> D[2**40]
    'yelp'
    >>> D[2**50]
    'yelp'
    >>> D[2]
    'yelp'
"""

ctypedef long long foo

def set_longlong(long long ob, foo x, long y, val):
    cdef object tank = {}
    tank[ob] = val
    tank[x] = val
    tank[y] = val
    return tank
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/lvalue_refs.pyx0000644000175100001770000000237200000000000020617 0ustar00runnerdocker00000000000000# tag: cpp, no-cpp-locals

from libcpp.vector cimport vector

__doc__ = u"""
   >>> test_lvalue_ref_assignment()
"""

ctypedef double*  dp
ctypedef double** dpp

cdef void foo(vector[dpp] &bar, vector[vector[dp]] &baz) nogil:
    bar[0] = &baz[0][0]

def test_lvalue_ref_assignment():
    cdef vector[dpp]        bar
    cdef vector[vector[dp]] baz
    cdef vector[double]     data = [0.0]
    cdef dp                 bongle = &data[0]

    bar.resize(1)
    bar[0] = NULL
    baz.resize(1)
    baz[0].resize(1)
    baz[0][0] = bongle

    foo(bar, baz)

    assert bar[0] == &baz[0][0]
    assert bar[0][0] == bongle

cdef void assign_to_basic_reference(int& ref):
    ref = 123

def test_assign_to_basic_ref():
    """
    >>> test_assign_to_basic_ref()
    123
    """
    cdef int x=0
    assign_to_basic_reference(x)
    print x

# not *strictly* lvalue refs but this file seems the closest applicable place for it.
# GH 3754 - std::vector operator[] returns a reference, and this causes problems if
# the reference is passed into Cython __Pyx_GetItemInt
def test_ref_used_for_indexing():
    """
    >>> test_ref_used_for_indexing()
    'looked up correctly'
    """
    cdef vector[int] idx = [1,2,3]
    d = {1: "looked up correctly", 2:"oops"}
    return d[idx[0]]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/mangle_c_keywords.pyx0000644000175100001770000000040400000000000021776 0ustar00runnerdocker00000000000000# Tests that illegal member and vtab entries are mangled.
cdef class A:
    """
    >>> a = A(100)
    >>> a.case()
    100
    """
    def __init__(self, value):
        self.switch = value
    cdef int switch
    cpdef case(self):
        return self.switch
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/matrix_multiplier.pyx0000644000175100001770000000603700000000000022064 0ustar00runnerdocker00000000000000
import sys

if sys.version_info >= (3, 5):
    __doc__ = """\
Note: support for providing Python special methods despite missing the C-level slot
is currently not supported.

>>> a, b = ExtMatMult(1), ExtMatMult(2)
>>> print(test_matmul(a, b))
ExtMatMult(1) @ ExtMatMult(2)
>>> print(test_matmul(a, 22))
ExtMatMult(1) @ 22
>>> print(test_matmul(11, b))
11 @ ExtMatMult(2)
>>> print(test_imatmul(a, b))
ExtMatMult('ExtMatMult(1) @ ExtMatMult(2)')
>>> print(test_imatmul(a, b))
ExtMatMult("ExtMatMult('ExtMatMult(1) @ ExtMatMult(2)') @ ExtMatMult(2)")

>>> x = y = 1
>>> x @ y
Traceback (most recent call last):
TypeError: unsupported operand type(s) for @: 'int' and 'int'

PyPy exception message has '@' rather than '@='
>>> x @= y  # doctest: +ELLIPSIS
Traceback (most recent call last):
TypeError: unsupported operand type(s) for @...: 'int' and 'int'

>>> y = MatMult(22)
>>> x @= y
>>> print(x)
1 @ MatMult(22)

>>> x = MatMult(22)
>>> print(x @ 1)
MatMult(22) @ 1
>>> print(1 @ x)
1 @ MatMult(22)
>>> x @= 1
>>> print(x)
MatMult('MatMult(22) @ 1')
"""


class MatMult(object):
    def __init__(self, myself):
        self.myself = myself

    def __matmul__(self, other):
        return '%r @ %r' % (self, other)

    def __rmatmul__(self, other):
        return '%r @ %r' % (other, self)

    def __imatmul__(self, other):
        self.myself = '%r @ %r' % (self, other)
        return self

    def __repr__(self):
        return 'MatMult(%r)' % self.myself


cdef class ExtMatMult:
    """
    Note: support for providing Python special methods despite missing the C-level slot
    is currently not supported.
    """
    cdef object myself
    def __init__(self, myself):
        self.myself = myself

    def __matmul__(self, other):
        return '%r @ %r' % (self, other)

    def __rmatmul__(self, other):
        return '%r @ %r' % (other, self)

    def __imatmul__(self, other):
        self.myself = '%r @ %r' % (self, other)
        return self

    def __repr__(self):
        return 'ExtMatMult(%r)' % self.myself


def test_matmul(a, b):
    """
    >>> print(test_matmul(MatMult(1), MatMult(2)))
    MatMult(1) @ MatMult(2)
    >>> print(test_matmul(MatMult(1), 22))
    MatMult(1) @ 22
    >>> print(test_matmul(11, MatMult(2)))
    11 @ MatMult(2)
    >>> print(test_matmul(MatMult('abc'), MatMult('def')))
    MatMult('abc') @ MatMult('def')

    >>> test_matmul(1, 2)
    Traceback (most recent call last):
    TypeError: unsupported operand type(s) for @: 'int' and 'int'
    """
    return a @ b


def test_imatmul(a, b):
    """
    >>> print(test_imatmul(MatMult(1), MatMult(2)))
    MatMult('MatMult(1) @ MatMult(2)')
    >>> print(test_imatmul(MatMult('abc'), MatMult('def')))
    MatMult("MatMult('abc') @ MatMult('def')")
    >>> print(test_imatmul(11, MatMult('def')))
    11 @ MatMult('def')
    >>> print(test_imatmul(MatMult('abc'), 11))
    MatMult("MatMult('abc') @ 11")

    >>> test_imatmul(1, 2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: unsupported operand type(s) for @...: 'int' and 'int'
    """
    a @= b
    return a
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/memoryview_namespace_T775.pyx0000644000175100001770000000057100000000000023254 0ustar00runnerdocker00000000000000
cdef int[10] data
cdef int[:] myslice = data

def test_memoryview_namespace():
    """
    >>> test_memoryview_namespace()
    """
    namespace = dir(__import__(__name__))
    assert 'array' not in namespace, namespace
    assert 'memoryview' not in namespace, namespace
    assert '_memoryviewslice' not in namespace, namespace
    assert 'Enum' not in namespace, namespace
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/memview_vector.pyx0000644000175100001770000000043500000000000021341 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp

from libcpp.vector cimport vector

def memview_test(L, int i, int x):
    """
    >>> memview_test(range(10), 7, 100)
    [0, 1, 2, 3, 4, 5, 6, 100, 8, 9]
    """
    cdef vector[int] v = L
    cdef int[::1] mv =  &v[0]
    mv[i] = x
    return v
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/menten1.pyx0000644000175100001770000000023700000000000017655 0ustar00runnerdocker00000000000000def loops():
    """
    >>> loops()
    5
    """
    cdef int k
    for i from 0 <= i < 5:
        for j from 0 <= j < 2:
            k = i + j
    return k
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/metaclass.pyx0000644000175100001770000001063300000000000020263 0ustar00runnerdocker00000000000000
cimport cython

class Base(type):
    def __new__(cls, name, bases, attrs):
        attrs['metaclass_was_here'] = True
        return type.__new__(cls, name, bases, attrs)

@cython.test_assert_path_exists("//PyClassMetaclassNode", "//Py3ClassNode")
class Foo(object):
    """
    >>> obj = Foo()
    >>> obj.metaclass_was_here
    True
    """
    __metaclass__ = Base


def non_type_metaclass(name, bases, namespace):
    namespace['BASES'] = [b.__name__ for b in bases]
    namespace['NAME'] = name
    return type(name, bases, namespace)

class FunctionAsPy2Metaclass(object):
    """
    >>> obj = FunctionAsPy2Metaclass()
    >>> obj.NAME
    'FunctionAsPy2Metaclass'
    >>> obj.BASES
    ['object']
    >>> obj.x
    1
    """
    __metaclass__ = non_type_metaclass
    x = 1


class ODict(dict):
    def __init__(self):
        dict.__init__(self)
        self._order = []
        dict.__setitem__(self, '_order', self._order)

    def __setitem__(self, key, value):
        dict.__setitem__(self, key, value)
        self._order.append(key)

class Py3MetaclassPlusAttr(type):
    def __new__(cls, name, bases, attrs, **kwargs):
        assert isinstance(attrs, ODict), str(type(attrs))
        for key, value in kwargs.items():
            attrs[key] = value
        attrs['metaclass_was_here'] = True
        return type.__new__(cls, name, bases, attrs)

    def __init__(self, cls, attrs, obj, **kwargs):
        pass

    @staticmethod
    def __prepare__(*args, **kwargs):
        return ODict()

@cython.test_fail_if_path_exists("//PyClassMetaclassNode")
@cython.test_assert_path_exists("//Py3ClassNode")
class Py3ClassMCOnly(object, metaclass=Py3MetaclassPlusAttr):
    """
    >>> obj = Py3ClassMCOnly()
    >>> obj.bar
    321
    >>> obj.metaclass_was_here
    True
    >>> [n for n in obj._order if n not in {"__qualname__", "__annotations__"}]
    ['__module__', '__doc__', 'bar', 'metaclass_was_here']
    """
    bar = 321

class Py3InheritedMetaclass(Py3ClassMCOnly):
    """
    >>> obj = Py3InheritedMetaclass()
    >>> obj.bar
    345
    >>> obj.metaclass_was_here
    True
    >>> [n for n in obj._order if n not in {"__qualname__", "__annotations__"}]
    ['__module__', '__doc__', 'bar', 'metaclass_was_here']
    """
    bar = 345

class Py3Base(type):
    def __new__(cls, name, bases, attrs, **kwargs):
        assert isinstance(attrs, ODict), str(type(attrs))
        for key, value in kwargs.items():
            attrs[key] = value
        return type.__new__(cls, name, bases, attrs)

    def __init__(self, cls, attrs, obj, **kwargs):
        pass

    @staticmethod
    def __prepare__(*args, **kwargs):
        return ODict()

@cython.test_fail_if_path_exists("//PyClassMetaclassNode")
@cython.test_assert_path_exists("//Py3ClassNode")
class Py3Foo(object, metaclass=Py3Base, foo=123):
    """
    >>> obj = Py3Foo()
    >>> obj.foo
    123
    >>> obj.bar
    321
    >>> [n for n in obj._order if n not in {"__qualname__", "__annotations__"}]
    ['__module__', '__doc__', 'bar', 'foo']
    """
    bar = 321

@cython.test_assert_path_exists("//PyClassMetaclassNode", "//Py3ClassNode")
class Py3FooInherited(Py3Foo, foo=567):
    """
    >>> obj = Py3FooInherited()
    >>> obj.foo
    567
    >>> obj.bar
    321
    >>> [n for n in obj._order if n not in {"__qualname__", "__annotations__"}]
    ['__module__', '__doc__', 'bar', 'foo']
    """
    bar = 321

kwargs = {'foo': 123, 'bar': 456}

@cython.test_assert_path_exists("//PyClassMetaclassNode", "//Py3ClassNode")
class Py3Mixed(metaclass=Py3Base, **kwargs):
    """
    >>> Py3Mixed.foo
    123
    >>> Py3Mixed.bar
    456
    """

kwargs['metaclass'] = Py3Base

@cython.test_assert_path_exists("//PyClassMetaclassNode")
class Py3Kwargs(**kwargs):
    """
    >>> Py3Kwargs.foo
    123
    >>> Py3Kwargs.bar
    456
    """

class Base3(type):
    def __new__(cls, name, bases, attrs, **kwargs):
        kwargs['b'] = 2
        return type.__new__(cls, name, bases, attrs)

    def __init__(self, *args, **kwargs):
        self.kwargs = kwargs

    @staticmethod
    def __prepare__(*args, **kwargs):
        kwargs['a'] = 1
        return {}

kwargs = {'c': 0}

@cython.test_assert_path_exists("//PyClassMetaclassNode", "//Py3ClassNode")
class Foo3(metaclass=Base3, a=0, b=0, **kwargs):
    """
    >>> sorted(Foo3.kwargs.items())
    [('a', 0), ('b', 0), ('c', 0)]
    """

class PyClassWithNew(object):
    """
    >>> PyClassWithNew(389)
    389
    """
    def __new__(self, arg):
        return arg
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/method_module_name_T422.pyx0000644000175100001770000000066600000000000022654 0ustar00runnerdocker00000000000000# ticket: t422

"""
>>> Foo.incr.__module__ is not None
True
>>> Foo.incr.__module__ == Foo.__module__ == bar.__module__
True
>>> Simpleton.incr.__module__ == Simpleton.__module__ == bar.__module__
True

"""
class Foo(object):
   def incr(self,x):
       return x+1

def bar():
    pass


class Simpleton:
   def __str__(self):
       return "A simpleton"

   def incr(self,x):
       """Increment x by one.
       """
       return x+1

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/methodmangling_T5.py0000644000175100001770000002222200000000000021461 0ustar00runnerdocker00000000000000# mode: run
# ticket: t5

# A small number of extra tests checking:
# 1) this works correctly with pure-Python-mode decorators - methodmangling_pure.py.
# 2) this works correctly with cdef classes - methodmangling_cdef.pyx
# 3) with "error_on_unknown_names" - methodmangling_unknown_names.py

class CyTest(object):
    """
    >>> cy = CyTest()
    >>> '_CyTest__private' in dir(cy)
    True
    >>> cy._CyTest__private()
    8
    >>> '__private' in dir(cy)
    False
    >>> '_CyTest__x' in dir(cy)
    True

    >>> '__x' in dir(cy)
    False
    >>> cy._CyTest__y
    2

    >>> '_CyTest___more_than_two' in dir(cy)
    True
    >>> '___more_than_two' in dir(cy)
    False
    >>> '___more_than_two_special___' in dir(cy)
    True
    """
    __x = 1
    ___more_than_two = 3
    ___more_than_two_special___ = 4

    def __init__(self):
        self.__y = 2

    def __private(self): return 8

    def get(self):
        """
        >>> CyTest().get()
        (1, 1, 8)
        """
        return self._CyTest__x, self.__x, self.__private()

    def get_inner(self):
        """
        >>> CyTest().get_inner()
        (1, 1, 8)
        """
        def get(o):
            return o._CyTest__x, o.__x, o.__private()
        return get(self)

class CyTestSub(CyTest):
    """
    >>> cy = CyTestSub()
    >>> '_CyTestSub__private' in dir(cy)
    True
    >>> cy._CyTestSub__private()
    9
    >>> '_CyTest__private' in dir(cy)
    True
    >>> cy._CyTest__private()
    8
    >>> '__private' in dir(cy)
    False

    >>> '_CyTestSub__x' in dir(cy)
    False
    >>> '_CyTestSub__y' in dir(cy)
    True
    >>> '_CyTest__x' in dir(cy)
    True
    >>> '__x' in dir(cy)
    False
    """
    __y = 2
    def __private(self): return 9

    def get(self):
        """
        >>> CyTestSub().get()
        (1, 2, 2, 9)
        """
        return self._CyTest__x, self._CyTestSub__y, self.__y, self.__private()

    def get_inner(self):
        """
        >>> CyTestSub().get_inner()
        (1, 2, 2, 9)
        """
        def get(o):
            return o._CyTest__x, o._CyTestSub__y, o.__y, o.__private()
        return get(self)

class _UnderscoreTest(object):
    """
    >>> ut = _UnderscoreTest()
    >>> '__x' in dir(ut)
    False
    >>> '_UnderscoreTest__x' in dir(ut)
    True
    >>> ut._UnderscoreTest__x
    1
    >>> ut.get()
    1
    >>> ut._UnderscoreTest__UnderscoreNested().ret1()
    1
    >>> ut._UnderscoreTest__UnderscoreNested.__name__
    '__UnderscoreNested'
    >>> ut._UnderscoreTest__prop
    1
    """
    __x = 1

    def get(self):
        return self.__x

    class __UnderscoreNested(object):
        def ret1(self):
            return 1

    @property
    def __prop(self):
        return self.__x

class C:
    error = """Traceback (most recent call last):
...
TypeError:
"""
    __doc__ = """
>>> instance = C()

Instance methods have their arguments mangled
>>> instance.method1(__arg=1) # doctest: +IGNORE_EXCEPTION_DETAIL
{error}
>>> instance.method1(_C__arg=1)
1
>>> instance.method2(__arg=1) # doctest: +IGNORE_EXCEPTION_DETAIL
{error}
>>> instance.method2(_C__arg=1)
1

Works when optional argument isn't passed
>>> instance.method2()
None

Where args are in the function's **kwargs dict, names aren't mangled
>>> instance.method3(__arg=1) # doctest:
1
>>> instance.method3(_C__arg=1) # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
KeyError:

Lambda functions behave in the same way:
>>> instance.method_lambda(__arg=1) # doctest: +IGNORE_EXCEPTION_DETAIL
{error}
>>> instance.method_lambda(_C__arg=1)
1

Class methods - have their arguments mangled
>>> instance.class_meth(__arg=1) # doctest: +IGNORE_EXCEPTION_DETAIL
{error}
>>> instance.class_meth(_C__arg=1)
1
>>> C.class_meth(__arg=1) # doctest: +IGNORE_EXCEPTION_DETAIL
{error}
>>> C.class_meth(_C__arg=1)
1

Static methods - have their arguments mangled
>>> instance.static_meth(__arg=1) # doctest: +IGNORE_EXCEPTION_DETAIL
{error}
>>> instance.static_meth(_C__arg=1)
1
>>> C.static_meth(__arg=1) # doctest: +IGNORE_EXCEPTION_DETAIL
{error}
>>> C.static_meth(_C__arg=1)
1

Functions assigned to the class don't have their arguments mangled
>>> instance.class_assigned_function(__arg=1)
1
>>> instance.class_assigned_function(_C__arg=1) # doctest: +IGNORE_EXCEPTION_DETAIL
{error}

Functions assigned to an instance don't have their arguments mangled
>>> instance.instance_assigned_function = free_function2
>>> instance.instance_assigned_function(__arg=1)
1
>>> instance.instance_assigned_function(_C__arg=1) # doctest: +IGNORE_EXCEPTION_DETAIL
{error}

Locals are reported as mangled
>>> list(sorted(k for k in instance.get_locals(1).keys()))
['_C__arg', 'self']
""".format(error=error)

    def method1(self, __arg):
        print(__arg)

    def method2(self, __arg=None):
        # __arg is optional
        print(__arg)

    def method3(self, **kwargs):
        print(kwargs['__arg'])

    method_lambda = lambda self, __arg: __arg

    def get_locals(self, __arg):
        return locals()

    @classmethod
    def class_meth(cls, __arg):
        print(__arg)

    @staticmethod
    def static_meth(__arg, dummy_arg=None):
        # dummy_arg is to mask https://github.com/cython/cython/issues/3090
        print(__arg)

def free_function1(x, __arg):
    print(__arg)

def free_function2(__arg, dummy_arg=None):
    # dummy_arg is to mask https://github.com/cython/cython/issues/3090
    print(__arg)

C.class_assigned_function = free_function1

__global_arg = True

_D__arg1 = None
_D__global_arg = False  # define these because otherwise Cython gives a compile-time error
       # while Python gives a runtime error (which is difficult to test)
def can_find_global_arg():
    """
    >>> can_find_global_arg()
    True
    """
    return __global_arg

def cant_find_global_arg():
    """
    Gets _D_global_arg instead
    >>> cant_find_global_arg()
    False
    """
    class D:
        def f(self):
            return __global_arg
    return D().f()

class CMultiplyNested:
    def f1(self, __arg, name=None, return_closure=False):
        """
        >>> inst = CMultiplyNested()
        >>> for name in [None, '__arg', '_CMultiplyNested__arg', '_D__arg']:
        ...    try:
        ...        print(inst.f1(1,name))
        ...    except TypeError:
        ...        print("TypeError") # not concerned about exact details
        ...    # now test behaviour is the same in closures
        ...    closure = inst.f1(1, return_closure=True)
        ...    try:
        ...        if name is None:
        ...            print(closure(2))
        ...        else:
        ...            print(closure(**{ name: 2}))
        ...    except TypeError:
        ...        print("TypeError")
        2
        2
        TypeError
        TypeError
        TypeError
        TypeError
        2
        2
        """
        class D:
            def g(self, __arg):
                return __arg
        if return_closure:
            return D().g
        if name is not None:
            return D().g(**{ name: 2 })
        else:
            return D().g(2)

    def f2(self, __arg1):
        """
        This finds the global name '_D__arg1'
        It's tested in this way because without the global
        Python gives a runtime error and Cython a compile error
        >>> print(CMultiplyNested().f2(1))
        None
        """
        class D:
            def g(self):
                return __arg1
        return D().g()

    def f3(self, arg, name):
        """
        >>> inst = CMultiplyNested()
        >>> inst.f3(1, None)
        2
        >>> inst.f3(1, '__arg') # doctest: +IGNORE_EXCEPTION_DETAIL
        Traceback (most recent call last):
        ...
        TypeError:
        >>> inst.f3(1, '_CMultiplyNested__arg')
        2
        """
        def g(__arg, dummy=1):
            return __arg
        if name is not None:
            return g(**{ name: 2})
        else:
            return g(2)

    def f4(self, __arg):
        """
        >>> CMultiplyNested().f4(1)
        1
        """
        def g():
            return __arg
        return g()

    def f5(self, __arg):
        """
        Default values are found in the outer scope correctly
        >>> CMultiplyNested().f5(1)
        1
        """
        def g(x=__arg):
            return x
        return g()

    def f6(self, __arg1):
        """
        This will find the global name _D__arg1
        >>> print(CMultiplyNested().f6(1))
        None
        """
        class D:
            def g(self, x=__arg1):
                return x
        return D().g()

    def f7(self, __arg):
        """
        Lookup works in generator expressions
        >>> list(CMultiplyNested().f7(1))
        [1]
        """
        return (__arg for x in range(1))

class __NameWithDunder:
    """
    >>> __NameWithDunder.__name__
    '__NameWithDunder'
    """
    pass

class Inherits(__NameWithDunder):
    """
    Compile check that it can find the base class
    >>> x = Inherits()
    """
    pass

def regular_function(__x, dummy=None):
    # as before, dummy stops Cython creating a 1 arg, non-keyword call
    return __x

class CallsRegularFunction:
    def call(self):
        """
        >>> CallsRegularFunction().call()
        1
        """
        return regular_function(__x=1)  # __x shouldn't be mangled as an argument elsewhere
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/methodmangling_cdef.pxd0000644000175100001770000000011400000000000022231 0ustar00runnerdocker00000000000000cdef class InPxd:
    cdef public int __y
    cdef int __private_cdef(self)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/methodmangling_cdef.pyx0000644000175100001770000000356000000000000022266 0ustar00runnerdocker00000000000000# mode: run

def call_cdt_private_cdef(CDefTest o):
    return o._CDefTest__private_cdef()

cdef __c_func():
    return "cdef function"

cdef __c_var = "Shouldn't see this"

cdef class CDefTest:
    """
    >>> cd = CDefTest()
    >>> '_CDefTest__private' in dir(cd)
    True
    >>> cd._CDefTest__private()
    8
    >>> call_cdt_private_cdef(cd)
    8
    >>> '__private' in dir(cd)
    False
    >>> '_CDefTest__x' in dir(cd)
    True

    >>> '__x' in dir(cd)
    False
    >>> cd._CDefTest__y
    2
    """
    __x = 1
    cdef public int __y

    def __init__(self):
        self.__y = 2

    def __private(self): return 8

    cdef __private_cdef(self): return 8

    def get(self):
        """
        >>> CDefTest().get()
        (1, 1, 8)
        """
        return self._CDefTest__x, self.__x, self.__private()

    def get_inner(self):
        """
        >>> CDefTest().get_inner()
        (1, 1, 8)
        """
        def get(o):
            return o._CDefTest__x, o.__x, o.__private()
        return get(self)

    def get_c_func(self):
        """
        Should still be able to access C function with __names
        >>> CDefTest().get_c_func()
        'cdef function'
        """
        return __c_func()

    def get_c_func2(self):
        """
        Should find mangled name before C __name
        >>> CDefTest().get_c_func2()
        'lambda'
        """
        _CDefTest__c_func = lambda: "lambda"
        return __c_func()

    def get_c_var(self):
        """
        >>> CDefTest().get_c_var()
        'c var'
        """
        global __c_var
        __c_var = "c var"
        return __c_var

def call_inpdx_private_cdef(InPxd o):
    return o._InPxd__private_cdef()

cdef class InPxd:
    """
    >>> InPxd()._InPxd__y
    2
    >>> call_inpdx_private_cdef(InPxd())
    8
    """
    def __init__(self):
        self.__y = 2

    cdef int __private_cdef(self): return 8
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/methodmangling_pure.py0000644000175100001770000000364100000000000022150 0ustar00runnerdocker00000000000000# mode: run
# cython: language_level=3

# This file tests that methodmangling is applied correctly to
# pure Python decorated classes.

import cython

if cython.compiled:
    # don't run in Python mode since a significant number of the tests
    # are only for Cython features

    def declare(**kwargs):
        return kwargs['__x']

    class RegularClass:
        @cython.locals(__x=cython.int)
        def f1(self, __x, dummy=None):
            """
            Is the locals decorator correctly applied
            >>> c = RegularClass()
            >>> c.f1(1)
            1
            >>> c.f1("a")
            Traceback (most recent call last):
            ...
            TypeError: an integer is required
            >>> c.f1(_RegularClass__x = 1)
            1
            """
            return __x

        def f2(self, x):
            """
            Is the locals decorator correctly applied
            >>> c = RegularClass()
            >>> c.f2(1)
            1
            >>> c.f2("a")
            Traceback (most recent call last):
            ...
            TypeError: an integer is required
            """
            __x = cython.declare(cython.int, x)

            return __x

        def f3(self, x):
            """
            Is the locals decorator correctly applied
            >>> c = RegularClass()
            >>> c.f3(1)
            1
            >>> c.f3("a")
            Traceback (most recent call last):
            ...
            TypeError: an integer is required
            """
            cython.declare(__x=cython.int)
            __x = x

            return __x

        def f4(self, x):
            """
            We shouldn't be tripped up by a function called
            "declare" that is nothing to do with cython
            >>> RegularClass().f4(1)
            1
            """
            return declare(__x=x)
else:
    __doc__ = """
    >>> True
    True
    """  # stops Python2 from failing
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/methodmangling_unknown_names.py0000644000175100001770000000127400000000000024057 0ustar00runnerdocker00000000000000# mode: run
# tag: allow_unknown_names, pure2.0, pure3.0

class Test(object):
    def run(self):
        """
        >>> Test().run()
        NameError1
        NameError2
        found mangled
        """
        try:
            print(__something)
        except NameError:
            print("NameError1")  # correct - shouldn't exist
        globals()['__something'] = 'found unmangled'
        try:
            print(__something)
        except NameError:
            print("NameError2")  # correct - shouldn't exist
        globals()['_Test__something'] = 'found mangled'
        try:
            print(__something)  # should print this
        except NameError:
            print("NameError3")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/mod__name__.pyx0000644000175100001770000000034100000000000020516 0ustar00runnerdocker00000000000000
module_name = __name__

def in_module():
    """
    >>> print(in_module())
    mod__name__
    """
    return module_name

def in_function():
    """
    >>> print(in_function())
    mod__name__
    """
    return __name__
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/mod__spec__.pyx0000644000175100001770000000173600000000000020541 0ustar00runnerdocker00000000000000# mode: run
# tag: pep489

import os.path

module_spec = __spec__
module_file = __file__


def check_spec(spec=__spec__):
    """
    >>> check_spec()
    """
    assert __spec__ is not None
    assert __spec__ is spec

    assert __name__
    assert __name__ == spec.name

    assert spec.loader is not None
    assert spec.loader is __loader__

    assert not spec.parent
    assert not __package__

    assert spec.origin
    assert spec.origin == module_file
    assert spec.origin == __file__
    assert os.path.basename(spec.origin).startswith(__name__)


# validate that ModuleSpec is already complete at module initialisation time
check_spec()
check_spec(__spec__)
check_spec(module_spec)


def file_in_module():
    """
    >>> print(file_in_module())
    mod__spec__
    """
    return os.path.basename(module_file).split('.', 1)[0]


def file_in_function():
    """
    >>> print(file_in_function())
    mod__spec__
    """
    return os.path.basename(__file__).split('.', 1)[0]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/modbody.pyx0000644000175100001770000000031700000000000017742 0ustar00runnerdocker00000000000000
def f():
    """
    >>> f()
    >>> g
    42
    >>> x == 'spam'
    True
    >>> y == 'eggs'
    True
    >>> z == 'spameggs'
    True
    """
    pass

g = 42
x = u"spam"
y = u"eggs"
if g:
    z = x + y
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/modop.pyx0000644000175100001770000001057500000000000017432 0ustar00runnerdocker00000000000000import sys


def modobj(obj2, obj3):
    """
    >>> modobj(9,2)
    1
    >>> modobj('%d', 5)
    '5'
    >>> modobj(1, 0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: integer... by zero
    """
    obj1 = obj2 % obj3
    return obj1


def mod_10_obj(int2):
    """
    >>> mod_10_obj(0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ZeroDivisionError: ... by zero
    >>> 10 % 1
    0
    >>> mod_10_obj(1)
    0
    >>> mod_10_obj(3)
    1
    >>> 10 % -1
    0
    >>> mod_10_obj(-1)
    0
    >>> mod_10_obj(-10)
    0
    """
    int1 = 10 % int2
    return int1


def mod_obj_10(int2):
    """
    >>> 0 % 10
    0
    >>> mod_obj_10(0)
    0
    >>> 1 % 10
    1
    >>> mod_obj_10(1)
    1
    >>> (-1) % 10
    9
    >>> mod_obj_10(-1)
    9
    >>> 9 % 10
    9
    >>> mod_obj_10(9)
    9
    >>> 10 % 10
    0
    >>> mod_obj_10(10)
    0
    >>> (-10) % 10
    0
    >>> mod_obj_10(-10)
    0
    >>> (-12) % 10
    8
    >>> mod_obj_10(-12)
    8
    >>> 10002 % 10
    2
    >>> mod_obj_10(10002)
    2
    >>> int((2**25) % 10)
    2
    >>> int(mod_obj_10(2**25))
    2
    >>> int((-2**25) % 10)
    8
    >>> int(mod_obj_10(-2**25))
    8
    >>> int((-2**31-1) % 10)
    1
    >>> int(mod_obj_10(int(-2**31-1)))
    1
    >>> int((2**50) % 10)
    4
    >>> int(mod_obj_10(2**50))
    4
    >>> int((-2**50) % 10)
    6
    >>> int(mod_obj_10(-2**50))
    6
    >>> int((-2**63-1) % 10)
    1
    >>> int(mod_obj_10(-2**63-1))
    1
    >>> int((2**200) % 10)
    6
    >>> int(mod_obj_10(2**200))
    6
    >>> int((-2**200) % 10)
    4
    >>> int(mod_obj_10(-2**200))
    4
    """
    int1 = int2 % 10
    return int1


def mod_obj_17(int2):
    """
    >>> 0 % 17
    0
    >>> mod_obj_17(0)
    0
    >>> 1 % 17
    1
    >>> mod_obj_17(1)
    1
    >>> (-1) % 17
    16
    >>> mod_obj_17(-1)
    16
    >>> 9 % 17
    9
    >>> mod_obj_17(16)
    16
    >>> 17 % 17
    0
    >>> mod_obj_17(17)
    0
    >>> (-17) % 17
    0
    >>> mod_obj_17(-17)
    0
    >>> (-18) % 17
    16
    >>> mod_obj_17(-18)
    16
    >>> 10002 % 17
    6
    >>> mod_obj_17(10002)
    6
    >>> int((2**25) % 17)
    2
    >>> int(mod_obj_17(2**25))
    2
    >>> int((-2**25) % 17)
    15
    >>> int(mod_obj_17(-2**25))
    15
    >>> int((-2**31-1) % 17)
    7
    >>> int(mod_obj_17(int(-2**31-1)))
    7
    >>> int((2**50) % 17)
    4
    >>> int(mod_obj_17(2**50))
    4
    >>> int((-2**50) % 17)
    13
    >>> int(mod_obj_17(-2**50))
    13
    >>> int((-2**63-1) % 17)
    7
    >>> int(mod_obj_17(-2**63-1))
    7
    >>> int((2**200) % 17)
    1
    >>> int(mod_obj_17(2**200))
    1
    >>> int((-2**200) % 17)
    16
    >>> int(mod_obj_17(-2**200))
    16
    """
    int1 = int2 % 17
    return int1


def mod_int_17(int int2):
    """
    >>> 0 % 17
    0
    >>> mod_int_17(0)
    0
    >>> 1 % 17
    1
    >>> mod_int_17(1)
    1
    >>> (-1) % 17
    16
    >>> mod_int_17(-1)
    16
    >>> 9 % 17
    9
    >>> mod_int_17(16)
    16
    >>> 17 % 17
    0
    >>> mod_int_17(17)
    0
    >>> (-17) % 17
    0
    >>> mod_int_17(-17)
    0
    >>> (-18) % 17
    16
    >>> mod_int_17(-18)
    16
    >>> 10002 % 17
    6
    >>> mod_int_17(10002)
    6
    >>> int((2**25) % 17)
    2
    >>> int(mod_int_17(2**25))
    2
    >>> int((-2**25) % 17)
    15
    >>> int(mod_int_17(-2**25))
    15
    """
    int1 = int2 % 17
    return int1


def mod_obj_m2(int2):
    """
    >>> 0 % -2
    0
    >>> mod_obj_m2(0)
    0
    >>> 1 % -2
    -1
    >>> mod_obj_m2(1)
    -1
    >>> 9 % -2
    -1
    >>> mod_obj_m2(9)
    -1
    """
    int1 = int2 % -2
    return int1


def mod_obj_m2f(obj2):
    """
    >>> 0 % -2.0 == 0.0    # -0.0 in Py2.7+
    True
    >>> mod_obj_m2f(0)
    -0.0
    >>> 1 % -2.0
    -1.0
    >>> mod_obj_m2f(1)
    -1.0
    >>> 9 % -2.0
    -1.0
    >>> mod_obj_m2f(9)
    -1.0
    """
    result = obj2 % -2.0
    return result


def modint(int int2, int int3):
    """
    >>> modint(9,2)
    1
    """
    cdef int int1
    int1 = int2 % int3
    return int1


def modptr():
    """
    >>> print(modptr() if sys.version_info[0] < 3 else 'spameggs')
    spameggs
    """
    cdef char *str2, *str3
    str2 = "spam%s"
    str3 = "eggs"
    obj1 = str2 % str3  # '%' operator doesn't work on byte strings in Py3
    return obj1


def mod_bigint(obj):
    """
    >>> print(mod_bigint(3316000000000))
    319
    """
    result = obj % 999
    return result
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/module_init_error.srctree0000644000175100001770000000311400000000000022653 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import test_fail_in_init; test_fail_in_init.try_import()"
PYTHON -c "import test_fail_in_init_after_atexit; test_fail_in_init_after_atexit.try_import()"

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup

setup(
    ext_modules = cythonize("fail_in_init*.pyx")
)

######## test_fail_in_init.py ########

import sys

def try_import():
    try:
        import fail_in_init
    except ValueError:
        pass
    else:
        raise RuntimeError("expected ValueError from import")

    if (3, 3) <= sys.version_info < (3, 5):
        assert 'fail_in_init' not in sys.modules
    elif 'fail_in_init' in sys.modules:
        try:
            sys.modules['fail_in_init'].fail()
        except AttributeError:
            pass  # this is "ok enough"
        except ValueError:
            pass  # this is what we had expected
        else:
            raise RuntimeError("expected ValueError from call through sys.modules")

######## fail_in_init.pyx ########

def fail():
    raise ValueError("kaputt")

fail()

######## test_fail_in_init_after_atexit.py ########

def try_import():
    try:
        import fail_in_init_after_atexit
    except ValueError:
        pass
    else:
        raise RuntimeError("expected ValueError from import")

######## fail_in_init_after_atexit.pyx ########

X = 5

def callback():
    try:
        print(X)
    except NameError:
        pass  # NameError is acceptable, a crash is not

import atexit
atexit.register(callback)

def fail():
    raise ValueError("holla!")

fail()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/moduletryexcept.pyx0000644000175100001770000000345300000000000021546 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> a
2
>>> b
3
>>> exc[0].__class__.__name__
'AttributeError'
>>> exc[1].__class__.__name__
'KeyError'
>>> exc[2].__class__.__name__
'IndexError'
>>> exc[3].__class__.__name__
'ValueError'
>>> exc[3] is val
True

>>> except_as_deletes   # Py2 behaviour
False
>>> no_match_does_not_touch_target
True
"""

a = 0

try:
    raise KeyError
except AttributeError:
    a = 1
except KeyError:
    a = 2
except:
    a = 3

b = 0

try:
    raise IndexError
except AttributeError:
    b = 1
except KeyError:
    b = 2
except:
    b = 3

exc = [None]*4

try:
    raise AttributeError
except AttributeError as e:
    exc[0] = e
except KeyError       as e:
    exc[0] = e
except IndexError     as e:
    exc[0] = e
except:
    exc[0] = 'SOMETHING ELSE'

e = None
try:
    raise KeyError
except AttributeError as e:
    exc[1] = e
except KeyError       as e:
    exc[1] = e
except IndexError     as e:
    exc[1] = e
except:
    exc[1] = 'SOMETHING ELSE'

try:
    e
except NameError:
    except_as_deletes = True
else:
    except_as_deletes = False

e = 123
try:
    raise TypeError
except NameError as e:
    pass
except TypeError:
    pass
no_match_does_not_touch_target = (e == 123)

try:
    raise IndexError
except AttributeError as e:
    exc[2] = e
except KeyError       as e:
    exc[2] = e
except IndexError     as e:
    exc[2] = e
except:
    exc[2] = 'SOMETHING ELSE'

val = None
try:
    try:
        try:
            raise ValueError
        except AttributeError as e:
            exc[3] = e
        except KeyError       as e:
            exc[3] = e
        except IndexError     as e:
            exc[3] = e
        except:
            raise
    except (AttributeError,
            KeyError,
            IndexError,
            ValueError) as e:
        val = e
        raise e
except Exception as e:
    exc[3] = e
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/mulop.pyx0000644000175100001770000000675300000000000017453 0ustar00runnerdocker00000000000000# mode: run
# tag: multiply

import sys
IS_PY2 = sys.version_info[0] < 3


def print_long(x):
    if IS_PY2:
        x = str(x).rstrip('L')
    print(x)


def mul_10_obj(x):
    """
    >>> mul_10_obj(0)
    0
    >>> mul_10_obj(10)
    100
    >>> mul_10_obj(-10)
    -100
    >>> 10 * (2**14)
    163840
    >>> mul_10_obj(2**14)
    163840
    >>> mul_10_obj(-2**14)
    -163840
    >>> print_long(10 * (2**29))
    5368709120
    >>> print_long(mul_10_obj(2**29))
    5368709120
    >>> print_long(mul_10_obj(-2**29))
    -5368709120
    >>> print_long(10 * (2**30))
    10737418240
    >>> print_long(mul_10_obj(2**30))
    10737418240
    >>> print_long(mul_10_obj(-2**30))
    -10737418240
    >>> print_long(10 * (2**63))
    92233720368547758080
    >>> print_long(mul_10_obj(2**63))
    92233720368547758080
    >>> print_long(mul_10_obj(-2**63))
    -92233720368547758080
    >>> print_long(10 * (2**128))
    3402823669209384634633746074317682114560
    >>> print_long(mul_10_obj(2**128))
    3402823669209384634633746074317682114560
    >>> print_long(mul_10_obj(-2**128))
    -3402823669209384634633746074317682114560
    """
    result = 10 * x
    return result


def mul_obj_10(x):
    """
    >>> mul_obj_10(0)
    0
    >>> mul_obj_10(10)
    100
    >>> mul_obj_10(-10)
    -100
    >>> 10 * (2**14)
    163840
    >>> mul_obj_10(2**14)
    163840
    >>> mul_obj_10(-2**14)
    -163840
    >>> print_long(10 * (2**29))
    5368709120
    >>> print_long(mul_obj_10(2**29))
    5368709120
    >>> print_long(mul_obj_10(-2**29))
    -5368709120
    >>> print_long(10 * (2**30))
    10737418240
    >>> print_long(mul_obj_10(2**30))
    10737418240
    >>> print_long(mul_obj_10(-2**30))
    -10737418240
    >>> print_long(10 * (2**63))
    92233720368547758080
    >>> print_long(mul_obj_10(2**63))
    92233720368547758080
    >>> print_long(mul_obj_10(-2**63))
    -92233720368547758080
    >>> print_long(10 * (2**128))
    3402823669209384634633746074317682114560
    >>> print_long(mul_obj_10(2**128))
    3402823669209384634633746074317682114560
    >>> print_long(mul_obj_10(-2**128))
    -3402823669209384634633746074317682114560
    """
    result = x * 10
    return result


def mul_bigint_obj(x):
    """
    >>> mul_bigint_obj(0)
    0
    >>> print_long(mul_bigint_obj(1))
    536870912
    >>> print_long(mul_bigint_obj(2))
    1073741824
    >>> print_long(mul_bigint_obj(2**29))
    288230376151711744
    >>> print_long(mul_bigint_obj(-2**29))
    -288230376151711744
    >>> print_long(mul_bigint_obj(2**30))
    576460752303423488
    >>> print_long(mul_bigint_obj(-2**30))
    -576460752303423488
    >>> print_long(mul_bigint_obj(2**59))
    309485009821345068724781056
    >>> print_long(mul_bigint_obj(-2**59))
    -309485009821345068724781056
    """
    result = (2**29) * x
    return result


def mul_obj_float(x):
    """
    >>> mul_obj_float(-0.0)
    -0.0
    >>> mul_obj_float(0)
    0.0
    >>> mul_obj_float(1.0)
    2.0
    >>> mul_obj_float(-2.0)
    -4.0
    >>> mul_obj_float(-0.5)
    -1.0
    """
    result = x * 2.0
    return result


def mul_float_obj(x):
    """
    >>> mul_float_obj(0)
    0.0
    >>> mul_float_obj(2)
    4.0
    >>> mul_float_obj(-2)
    -4.0
    >>> 2.0 * (2**30-1)
    2147483646.0
    >>> mul_float_obj(2**30-1)
    2147483646.0
    >>> mul_float_obj(-(2**30-1))
    -2147483646.0
    >>> mul_float_obj(-0.0)
    -0.0
    >>> mul_float_obj(1.0)
    2.0
    >>> mul_float_obj(-2.0)
    -4.0
    >>> mul_float_obj(-0.5)
    -1.0
    """
    result = 2.0 * x
    return result
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/multass.pyx0000644000175100001770000000215100000000000017773 0ustar00runnerdocker00000000000000__doc__ = """
    >>> h()
    (1, b'test', 3, 1, b'test', 3)
"""

import sys
if sys.version_info[0] < 3:
    __doc__ = __doc__.replace(u" b'", u" '")

def f():
    """
    >>> f()
    (1, 2, 1, 2)
    """
    cdef object obj1a, obj2a, obj3a, obj1b, obj2b, obj3b
    obj1b, obj2b, obj3b = 1, 2, 3
    obj1a, obj2a = obj1b, obj2b
    return obj1a, obj2a, obj1b, obj2b

def g():
    """
    >>> g()
    (1, 1, 2, 2, 3, 3)
    """
    cdef object obj1a, obj2a, obj3a, obj1b, obj2b, obj3b
    obj1b, obj2b, obj3b = 1, 2, 3
    obj1a, [obj2a, obj3a] = [obj1b, (obj2b, obj3b)]
    return obj1a, obj1b, obj2a, obj2b, obj3a, obj3b

def h():
    cdef object obj1a, obj2a, obj3a, obj1b, obj2b, obj3b
    cdef int int1, int2
    cdef char *ptr1, *ptr2
    int2, ptr2, obj1b = 1, "test", 3
    int1, ptr1, obj1a = int2, ptr2, obj1b
    return int1, ptr1, obj1a, int2, ptr2, obj1b

def j():
    """
    >>> j()
    (2, 1, 4, 2, 6, 3)
    """
    cdef object obj1a, obj2a, obj3a, obj1b, obj2b, obj3b
    obj1b, obj2b, obj3b = 1, 2, 3
    obj1a, obj2a, obj3a = obj1b + 1, obj2b + 2, obj3b + 3
    return obj1a, obj1b, obj2a, obj2b, obj3a, obj3b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/new_as_nonkeyword.pyx0000644000175100001770000000075600000000000022047 0ustar00runnerdocker00000000000000cdef extern from *:
    int new(int new)

def new(x):
    """
    >>> new(3)
    3
    """
    cdef int new = x
    return new

def x(new):
    """
    >>> x(10)
    110
    >>> x(1)
    1
    """
    if new*new != new:
        return new + new**2
    return new

class A:
    def new(self, n):
        """
        >>> a = A()
        >>> a.new(3)
        6
        >>> a.new(5)
        120
        """
        if n <= 1:
            return 1
        else:
            return n * self.new(n-1)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/new_style_exceptions.pyx0000644000175100001770000000076500000000000022566 0ustar00runnerdocker00000000000000
import sys, types

def test(obj):
    """
    >>> test(Exception('hi'))
    Raising: Exception('hi',)
    Caught: Exception('hi',)
    """
    print u"Raising: %s%r" % (obj.__class__.__name__, obj.args)
    try:
        raise obj
    except:
        info = sys.exc_info()
        if sys.version_info >= (2,5):
            assert isinstance(info[0], type)
        else:
            assert isinstance(info[0], types.ClassType)
        print u"Caught: %s%r" % (info[1].__class__.__name__, info[1].args)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/no_gc.pyx0000644000175100001770000000206500000000000017374 0ustar00runnerdocker00000000000000"""
Check that the @cython.no_gc decorator disables generation of the
tp_clear and tp_traverse slots, that is, disables cycle collection.
"""

cimport cython
from cpython.ref cimport PyObject, Py_TYPE

# Force non-gc'd PyTypeObject when safety is guaranteed by user but not provable

cdef extern from *:
    ctypedef struct PyTypeObject:
        void (*tp_clear)(object)
        void (*tp_traverse)(object)


def is_tp_clear_null(obj):
    return (Py_TYPE(obj)).tp_clear is NULL

def is_tp_traverse_null(obj):
    return (Py_TYPE(obj)).tp_traverse is NULL


@cython.no_gc
cdef class DisableGC:
    """
    An extension type that has tp_clear and tp_traverse methods generated 
    to test that it actually clears the references to NULL.

    >>> uut = DisableGC()
    >>> is_tp_clear_null(uut)
    True
    >>> is_tp_traverse_null(uut)
    True
    """

    cdef public object requires_cleanup

    def __cinit__(self):
        self.requires_cleanup = (
                "Tuples to strings don't really need cleanup, cannot take part of cycles",)

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/no_gc_clear.pyx0000644000175100001770000000451200000000000020541 0ustar00runnerdocker00000000000000"""
Check that the @cython.no_gc_clear decorator disables generation of the
tp_clear slot so that __dealloc__ will still see the original reference
contents.

Discussed here: https://article.gmane.org/gmane.comp.python.cython.devel/14986
"""

cimport cython
from cpython.ref cimport PyObject, Py_TYPE

# Pull tp_clear for PyTypeObject as I did not find another way to access it
# from Cython code.

cdef extern from *:
    ctypedef struct PyTypeObject:
        void (*tp_clear)(object)

    ctypedef struct __pyx_CyFunctionObject:
        PyObject* func_closure


def is_tp_clear_null(obj):
    return (Py_TYPE(obj)).tp_clear is NULL


def is_closure_tp_clear_null(func):
    return is_tp_clear_null(
        (<__pyx_CyFunctionObject*>func).func_closure)


@cython.no_gc_clear
cdef class DisableTpClear:
    """
    An extension type that has a tp_clear method generated to test that it
    actually clears the references to NULL.

    >>> uut = DisableTpClear()
    >>> is_tp_clear_null(uut)
    True
    >>> uut.call_tp_clear()
    >>> type(uut.requires_cleanup) == list
    True
    >>> del uut
    """

    cdef public object requires_cleanup

    def __cinit__(self):
        self.requires_cleanup = [
                "Some object that needs cleaning in __dealloc__"]

    def call_tp_clear(self):
        cdef PyTypeObject *pto = Py_TYPE(self)
        if pto.tp_clear != NULL:
            pto.tp_clear(self)


cdef class ReallowTpClear(DisableTpClear):
    """
    >>> import gc
    >>> obj = ReallowTpClear()
    >>> is_tp_clear_null(obj)
    False

    >>> obj.attr = obj  # create hard reference cycle
    >>> del obj; _ignore = gc.collect()

    # Problem: cannot really validate that the cycle was cleaned up without using weakrefs etc...
    """
    cdef public object attr


def test_closure_without_clear(str x):
    """
    >>> c = test_closure_without_clear('abc')
    >>> is_tp_clear_null(c)
    False
    >>> is_closure_tp_clear_null(c)
    True
    >>> c('cba')
    'abcxyzcba'
    """
    def c(str s):
        return x + 'xyz' + s
    return c


def test_closure_with_clear(list x):
    """
    >>> c = test_closure_with_clear(list('abc'))
    >>> is_tp_clear_null(c)
    False
    >>> is_closure_tp_clear_null(c)
    False
    >>> c('cba')
    'abcxyzcba'
    """
    def c(str s):
        return ''.join(x) + 'xyz' + s
    return c
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/nogil.pxd0000644000175100001770000000005100000000000017363 0ustar00runnerdocker00000000000000cdef void voidexceptnogil_in_pxd() nogil
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/nogil.pyx0000644000175100001770000001302300000000000017413 0ustar00runnerdocker00000000000000# mode: run
# tag: perf_hints

from nogil_other cimport voidexceptnogil_in_other_pxd

try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO


def test(int x):
    """
    >>> test(5)
    47
    >>> test(11)
    53
    """
    with nogil:
        f(x)
        x = g(x)
    return x

cdef void f(int x) nogil:
        cdef int y
        y = x + 42
        g(y)

cdef int g(int x) nogil:
        cdef int y
        y = x + 42
        return y

cdef void release_gil_in_nogil() nogil:
    # This should generate valid code with/without the GIL
    with nogil:
        pass

cpdef void release_gil_in_nogil2() nogil:
    # This should generate valid code with/without the GIL
    with nogil:
        pass

def test_release_gil_in_nogil():
    """
    >>> test_release_gil_in_nogil()
    """
    with nogil:
        release_gil_in_nogil()
    with nogil:
        release_gil_in_nogil2()
    release_gil_in_nogil()
    release_gil_in_nogil2()

cdef void get_gil_in_nogil() nogil:
    with gil:
        pass

cpdef void get_gil_in_nogil2() nogil:
    with gil:
        pass

def test_get_gil_in_nogil():
    """
    >>> test_get_gil_in_nogil()
    """
    with nogil:
        get_gil_in_nogil()
    with nogil:
        get_gil_in_nogil2()
    get_gil_in_nogil()
    get_gil_in_nogil2()

cdef int with_gil_func() except -1 with gil:
    raise Exception("error!")

cdef int nogil_func() except -1 nogil:
    with_gil_func()

def test_nogil_exception_propagation():
    """
    >>> test_nogil_exception_propagation()
    Traceback (most recent call last):
       ...
    Exception: error!
    """
    with nogil:
        nogil_func()


cdef int write_unraisable() noexcept nogil:
    with gil:
        raise ValueError()


def test_unraisable():
    """
    >>> print(test_unraisable())  # doctest: +ELLIPSIS
    ValueError
    Exception...ignored...
    """
    import sys
    old_stderr = sys.stderr
    stderr = sys.stderr = StringIO()
    try:
        write_unraisable()
    finally:
        sys.stderr = old_stderr
    return stderr.getvalue().strip()


cdef int initialize_array() nogil:
    cdef int[4] a = [1, 2, 3, 4]
    return a[0] + a[1] + a[2] + a[3]

cdef int copy_array() nogil:
    cdef int[4] a
    a[:] = [0, 1, 2, 3]
    return a[0] + a[1] + a[2] + a[3]

cdef double copy_array2() nogil:
    cdef double[4] x = [1.0, 3.0, 5.0, 7.0]
    cdef double[4] y
    y[:] = x[:]
    return y[0] + y[1] + y[2] + y[3]

cdef double copy_array3() nogil:
    cdef double[4] x = [2.0, 4.0, 6.0, 8.0]
    cdef double[4] y
    y = x
    return y[0] + y[1] + y[2] + y[3]

cdef void copy_array_exception(int n) nogil:
    cdef double[5] a = [1,2,3,4,5]
    cdef double[6] b
    b[:n] = a

def test_initalize_array():
    """
    >>> test_initalize_array()
    10
    """
    return initialize_array()

def test_copy_array():
    """
    >>> test_copy_array()
    6
    """
    return copy_array()

def test_copy_array2():
    """
    >>> test_copy_array2()
    16.0
    """
    return copy_array2()

def test_copy_array3():
    """
    >>> test_copy_array3()
    20.0
    """
    return copy_array3()

def test_copy_array_exception(n):
    """
    >>> test_copy_array_exception(20)
    Traceback (most recent call last):
        ...
    ValueError: Assignment to slice of wrong length, expected 5, got 20
    """
    copy_array_exception(n)

def test_copy_array_exception_nogil(n):
    """
    >>> test_copy_array_exception_nogil(20)
    Traceback (most recent call last):
        ...
    ValueError: Assignment to slice of wrong length, expected 5, got 20
    """
    cdef int cn = n
    with nogil:
        copy_array_exception(cn)

# Should still get a warning even though it's declared in a pxd
cdef void voidexceptnogil_in_pxd() nogil:
    pass

def test_performance_hint_nogil():
    """
    >>> test_performance_hint_nogil()
    """
    with nogil:
        voidexceptnogil_in_pxd()
        # The function call should generate a performance hint, but the definition should
        # not (since it's in an external pxd we don't control)
        voidexceptnogil_in_other_pxd()


# Note that we're only able to check the first line of the performance hint
_PERFORMANCE_HINTS = """
20:9: Exception check after calling 'f' will always require the GIL to be acquired.
24:5: Exception check on 'f' will always require the GIL to be acquired.
34:5: Exception check on 'release_gil_in_nogil' will always require the GIL to be acquired.
39:6: Exception check on 'release_gil_in_nogil2' will always require the GIL to be acquired.
49:28: Exception check after calling 'release_gil_in_nogil' will always require the GIL to be acquired.
51:29: Exception check after calling 'release_gil_in_nogil2' will always require the GIL to be acquired.
55:5: Exception check on 'get_gil_in_nogil' will always require the GIL to be acquired.
59:6: Exception check on 'get_gil_in_nogil2' will always require the GIL to be acquired.
68:24: Exception check after calling 'get_gil_in_nogil' will always require the GIL to be acquired.
70:25: Exception check after calling 'get_gil_in_nogil2' will always require the GIL to be acquired.
133:5: Exception check on 'copy_array_exception' will always require the GIL to be acquired.
184:28: Exception check after calling 'copy_array_exception' will always require the GIL to be acquired.
187:5: Exception check on 'voidexceptnogil_in_pxd' will always require the GIL to be acquired.
195:30: Exception check after calling 'voidexceptnogil_in_pxd' will always require the GIL to be acquired.
198:36: Exception check after calling 'voidexceptnogil_in_other_pxd' will always require the GIL to be acquired.
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/nogil_conditional.pyx0000644000175100001770000001243100000000000022000 0ustar00runnerdocker00000000000000# mode: run

try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO


def test(int x):
    """
    >>> test(0)
    110
    """
    with nogil(True):
        x = f_nogil(x)
        with gil(True):
            x = f_gil(x)
    return x


cdef int f_nogil(int x) nogil:
    cdef int y
    y = x + 10
    return y


def f_gil(x):
    y = 0
    y = x + 100
    return y


cdef int with_gil_func() except? -1 with gil:
    raise Exception("error!")


cdef int nogil_func() except? -1 nogil:
    with_gil_func()


def test_nogil_exception_propagation():
    """
    >>> test_nogil_exception_propagation()
    Traceback (most recent call last):
       ...
    Exception: error!
    """
    with nogil:
        with gil:
            with nogil(True):
                nogil_func()


cdef int write_unraisable() noexcept nogil:
    with gil:
        raise ValueError()


def test_unraisable():
    """
    >>> print(test_unraisable())  # doctest: +ELLIPSIS
    ValueError
    Exception...ignored...
    """
    import sys
    old_stderr = sys.stderr
    stderr = sys.stderr = StringIO()
    try:
        write_unraisable()
    finally:
        sys.stderr = old_stderr
    return stderr.getvalue().strip()


def test_nested():
    """
    >>> test_nested()
    240
    """
    cdef int res = 0

    with nogil(True):
        res = f_nogil(res)
        with gil(1 < 2):
            res = f_gil(res)
            with nogil:
                res = f_nogil(res)

        with gil:
            res = f_gil(res)
            with nogil(True):
                res = f_nogil(res)
            with nogil:
                res = f_nogil(res)

    return res


DEF FREE_GIL = True
DEF FREE_GIL_FALSE = False


def test_nested_condition_false():
    """
    >>> test_nested_condition_false()
    220
    """
    cdef int res = 0

    with gil(FREE_GIL_FALSE):
        res = f_gil(res)
        with nogil(False):
            res = f_gil(res)

        with nogil(FREE_GIL):
            res = f_nogil(res)
            with gil(False):
                res = f_nogil(res)

    return res

def test_try_finally():
    """
    >>> test_try_finally()
    113
    """
    cdef int res = 0

    try:
        with nogil(True):
            try:
                res = f_nogil(res)
                with gil(1 < 2):
                    try:
                        res = f_gil(res)
                    finally:
                        res += 1
            finally:
                res = res + 1
    finally:
        res += 1

    return res


ctypedef fused number_or_object:
    int
    float
    object


def test_fused(number_or_object x) -> number_or_object:
    """
    >>> test_fused[int](1)
    2
    >>> test_fused[float](1.0)
    2.0
    >>> test_fused[object](1)
    2
    >>> test_fused[object](1.0)
    2.0
    """
    cdef number_or_object res = x

    with nogil(number_or_object is not object):
        res = res + 1

    return res


ctypedef fused int_or_object:
    int
    object


def test_fused_object(int_or_object x):
    """
    >>> test_fused_object[object]("spam")
    456
    >>> test_fused_object[int](1000)
    1000
    """
    cdef int res = 0

    if int_or_object is object:
        with nogil(False):
            res += len(x)

        try:
            with nogil(int_or_object is object):
                try:
                    with gil(int_or_object is object):
                        res = f_gil(res)
                    with gil:
                        res = f_gil(res)
                    with gil(False):
                        res = f_nogil(res)

                    with gil(int_or_object is not object):
                        res = f_nogil(res)
                    with nogil(False):
                        res = f_nogil(res)

                    res = f_nogil(res)
                finally:
                    res = res + 1

            with nogil(int_or_object is not object):
                res = f_gil(res)

            with gil(int_or_object is not object):
                res = f_gil(res)

                with nogil(int_or_object is object):
                    res = f_nogil(res)

        finally:
            res += 1
    else:
        res = x

    return res


def test_fused_int(int_or_object x):
    """
    >>> test_fused_int[object]("spam")
    4
    >>> test_fused_int[int](1000)
    1452
    """
    cdef int res = 0

    if int_or_object is int:
        res += x

        try:
            with nogil(int_or_object is int):
                try:
                    with gil(int_or_object is int):
                        res = f_gil(res)
                    with gil:
                        res = f_gil(res)
                    with gil(False):
                        res = f_nogil(res)

                    with gil(int_or_object is not int):
                        res = f_nogil(res)
                    with nogil(False):
                        res = f_nogil(res)

                    res = f_nogil(res)
                finally:
                    res = res + 1

            with nogil(int_or_object is not int):
                res = f_gil(res)

            with gil(int_or_object is not int):
                res = f_gil(res)

                with nogil(int_or_object is int):
                    res = f_nogil(res)

        finally:
            res += 1
    else:
        with nogil(False):
            res = len(x)

    return res
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/nogil_other.pxd0000644000175100001770000000010000000000000020557 0ustar00runnerdocker00000000000000cdef inline void voidexceptnogil_in_other_pxd() nogil:
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/non_const_as_const_arg.pyx0000644000175100001770000000036300000000000023030 0ustar00runnerdocker00000000000000cdef double f(const double a, const double b, const double c):
    return a + b - c

def test_non_const_as_const_arg():
    """
    >>> test_non_const_as_const_arg()
    1.0
    """
    cdef double a = 1., b = 1., c = 1.
    return f(a, b, c)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/non_dict_kwargs_T470.pyx0000644000175100001770000000156600000000000022205 0ustar00runnerdocker00000000000000# mode: run
# ticket: t470


def func(**kwargs):
    """
    >>> func(**{'a' : 7})
    True
    >>> func(**SubDict())
    True
    >>> func(**NonDict())
    True
    """
    return type(kwargs) is dict and kwargs['a'] == 7


class NonDict(object):
   def __getitem__(self, k):
       assert k == 'a'
       return 7
   def keys(self):
       return ['a']

def call_non_dict_test():
    """
    >>> call_non_dict_test()
    True
    """
    return func(**NonDict())

def call_non_dict_test_kw():
    """
    >>> call_non_dict_test_kw()
    True
    """
    return func(b=5, **NonDict())


class SubDict(dict):
    def __init__(self):
        self['a'] = 7

def call_sub_dict_test():
    """
    >>> call_sub_dict_test()
    True
    """
    return func(**SubDict())

def call_sub_dict_test_kw():
    """
    >>> call_sub_dict_test_kw()
    True
    """
    return func(b=5, **SubDict())
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/non_future_division.pyx0000644000175100001770000001026300000000000022376 0ustar00runnerdocker00000000000000# Py2.x mixed true-div/floor-div behaviour of '/' operator


def bigints(values):
    for x in values:
        print(repr(x).rstrip('L'))


def doit(x,y):
    """
    >>> doit(1,2)
    (0, 0)
    >>> doit(4,3)
    (1, 1)
    >>> doit(4,3.0)
    (1.3333333333333333, 1.0)
    >>> doit(4,2)
    (2, 2)
    """
    return x/y, x//y

def doit_inplace(x,y):
    """
    >>> doit_inplace(1,2)
    0
    """
    x /= y
    return x

def doit_inplace_floor(x,y):
    """
    >>> doit_inplace_floor(1,2)
    0
    """
    x //= y
    return x

def constants():
    """
    >>> constants()
    (0, 0, 2.5, 2.0, 2, 2)
    """
    return 1/2, 1//2, 5/2.0, 5//2.0, 5/2, 5//2


def py_mix(a):
    """
    >>> py_mix(1)
    (0, 0, 0.5, 0.0, 0, 0)
    >>> py_mix(1.0)
    (0.5, 0.0, 0.5, 0.0, 0.5, 0.0)
    >>> 2**53 / 2.0
    4503599627370496.0
    >>> bigints(py_mix(2**53))
    4503599627370496
    4503599627370496
    4503599627370496.0
    4503599627370496.0
    4503599627370496
    4503599627370496
    >>> bigints(py_mix(2**53 + 1))
    4503599627370496
    4503599627370496
    4503599627370496.0
    4503599627370496.0
    4503599627370496
    4503599627370496
    >>> py_mix(2**53 + 1.0)
    (4503599627370496.0, 4503599627370496.0, 4503599627370496.0, 4503599627370496.0, 4503599627370496.0, 4503599627370496.0)
    """
    return a/2, a//2, a/2.0, a//2.0, a/2, a//2


def py_mix_by_neg1(a):
    """
    >>> py_mix_by_neg1(0)
    (0, 0, -0.0, -0.0, 0, 0)
    >>> py_mix_by_neg1(-1)
    (1, 1, 1.0, 1.0, 1, 1)
    >>> py_mix_by_neg1(int(2**31-1))
    (-2147483647, -2147483647, -2147483647.0, -2147483647.0, -2147483647, -2147483647)
    >>> bigints(py_mix_by_neg1(int(-2**31-1)))
    2147483649
    2147483649
    2147483649.0
    2147483649.0
    2147483649
    2147483649
    >>> results = py_mix_by_neg1(int(2**63-1))
    >>> results[2] == results[3] == float(2**63-1) / -1.0 or results
    True
    >>> results[0] == results[1] == results[4] == results[5] == (2**63-1) // -1 or results
    True
    >>> results = py_mix_by_neg1(int(-2**63-1))
    >>> results[2] == results[3] == float(-2**63-1) / -1.0 or results
    True
    >>> results[0] == results[1] == results[4] == results[5] == (-2**63-1) // -1 or results
    True
    """
    return a/-1, a//-1, a/-1.0, a//-1.0, a/-1, a//-1


def py_mix_rev(a):
    """
    >>> py_mix_rev(4)
    (0, 0, 1.25, 1.0, 1, 1)
    >>> py_mix_rev(4.0)
    (0.25, 0.0, 1.25, 1.0, 1.25, 1.0)
    """
    return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a

def int_mix(int a):
    """
    >>> int_mix(1)
    (0, 0, 0.5, 0.0, 0, 0)
    """
    return a/2, a//2, a/2.0, a//2.0, a/2, a//2

def int_mix_rev(int a):
    """
    >>> int_mix_rev(4)
    (0, 0, 1.25, 1.0, 1, 1)
    """
    return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a

def float_mix(float a):
    """
    >>> float_mix(1.0)
    (0.5, 0.0, 0.5, 0.0, 0.5, 0.0)
    """
    return a/2, a//2, a/2.0, a//2.0, a/2, a//2

def float_mix_rev(float a):
    """
    >>> float_mix_rev(4.0)
    (0.25, 0.0, 1.25, 1.0, 1.25, 1.0)
    """
    return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a

def int_int(int a, int b):
    """
    >>> int_int(1, 2)
    (0, 2)
    """
    return a/b, b/a


def div_by_0(a):
    """
    >>> div_by_0(0)
    'OK'
    >>> div_by_0(0.0)
    'OK'
    """
    try:
        1/a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 1"
    try:
        1//a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 2"
    try:
        5.0/a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 3"
    try:
        5.0//a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 4"
    try:
        5/a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 5"
    try:
        5//a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 6"
    try:
        (2**15)/a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 7"
    try:
        (2**15)//a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 8"
    try:
        (2**30)/a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 9"
    try:
        (2**30)//a
    except ZeroDivisionError:
        pass
    else:
        return "FAIL 10"
    return 'OK'
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/nonecheck.pyx0000644000175100001770000001075500000000000020251 0ustar00runnerdocker00000000000000__doc__ = u"""
Tests accessing attributes of extension type variables
set to None
"""

cimport cython

cdef class MyClass:
    cdef int a, b
    def __init__(self, a, b):
        self.a = a
        self.b = b

@cython.nonecheck(True)
def getattr_(MyClass var):
    """
    >>> obj = MyClass(2, 3)
    >>> getattr_(obj)
    2
    >>> getattr_(None)
    Traceback (most recent call last):
    AttributeError: 'NoneType' object has no attribute 'a'
    >>> setattr_(obj)
    >>> getattr_(obj)
    10
    """
    print var.a

@cython.nonecheck(True)
def setattr_(MyClass var):
    """
    >>> obj = MyClass(2, 3)
    >>> setattr_(obj)
    >>> setattr_(None)
    Traceback (most recent call last):
    AttributeError: 'NoneType' object has no attribute 'a'
    """
    var.a = 10

@cython.nonecheck(True)
def getattr_nogil(MyClass var):
    """
    >>> getattr_nogil(None)
    Traceback (most recent call last):
    AttributeError: 'NoneType' object has no attribute 'a'
    """
    with nogil:
        var.a

@cython.nonecheck(True)
def setattr_nogil(MyClass var):
    """
    >>> setattr_nogil(None)
    Traceback (most recent call last):
    AttributeError: 'NoneType' object has no attribute 'a'
    """
    with nogil:
        var.a = 1

def some():
    return MyClass(4, 5)

@cython.nonecheck(True)
def checking(MyClass var):
    """
    >>> obj = MyClass(2, 3)
    >>> checking(obj)
    2
    2
    >>> checking(None)
    var is None
    """
    state = (var is None)
    if not state:
        print var.a
    if var is not None:
        print var.a
    else:
        print u"var is None"

@cython.nonecheck(True)
def check_and_assign(MyClass var):
    """
    >>> obj = MyClass(2, 3)
    >>> check_and_assign(obj)
    Traceback (most recent call last):
    AttributeError: 'NoneType' object has no attribute 'a'
    """
    if var is not None:
        print var.a
        var = None
        print var.a

@cython.nonecheck(True)
def check_buffer_get(object[int] buf):
    """
    >>> check_buffer_get(None)
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not subscriptable
    """
    return buf[0]

@cython.nonecheck(True)
def check_buffer_set(object[int] buf):
    """
    >>> check_buffer_set(None)
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not subscriptable
    """
    buf[0] = 1

@cython.nonecheck(True)
def test_memslice_get(double[:] buf):
    """
    >>> test_memslice_get(None)
    Traceback (most recent call last):
    TypeError: Cannot index None memoryview slice
    """
    return buf[0]

@cython.nonecheck(True)
def test_memslice_set(double[:] buf):
    """
    >>> test_memslice_set(None)
    Traceback (most recent call last):
    TypeError: Cannot index None memoryview slice
    """
    buf[0] = 1.0

@cython.nonecheck(True)
def test_memslice_copy(double[:] buf):
    """
    >>> test_memslice_copy(None)
    Traceback (most recent call last):
    AttributeError: Cannot access 'copy' attribute of None memoryview slice
    """
    cdef double[:] copy = buf.copy()

@cython.nonecheck(True)
def test_memslice_transpose(double[:] buf):
    """
    >>> test_memslice_transpose(None)
    Traceback (most recent call last):
    AttributeError: Cannot transpose None memoryview slice
    """
    cdef double[:] T = buf.T

@cython.nonecheck(True)
def test_memslice_shape(double[:] buf):
    """
    >>> test_memslice_shape(None)
    Traceback (most recent call last):
    AttributeError: Cannot access 'shape' attribute of None memoryview slice
    """
    cdef Py_ssize_t extent = buf.shape[0]

@cython.nonecheck(True)
def test_memslice_slice(double[:] buf):
    """
    >>> test_memslice_slice(None)
    Traceback (most recent call last):
    TypeError: Cannot slice None memoryview slice
    """
    cdef double[:] sliced = buf[1:]

@cython.nonecheck(True)
def test_memslice_slice2(double[:] buf):
    """
    Should this raise an error? It may not slice at all.
    >>> test_memslice_slice(None)
    Traceback (most recent call last):
    TypeError: Cannot slice None memoryview slice
    """
    cdef double[:] sliced = buf[:]

@cython.nonecheck(True)
def test_memslice_slice_assign(double[:] buf):
    """
    >>> test_memslice_slice_assign(None)
    Traceback (most recent call last):
    TypeError: Cannot assign to None memoryview slice
    """
    buf[...] = 2

@cython.nonecheck(True)
def test_memslice_slice_assign2(double[:] buf):
    """
    >>> test_memslice_slice_assign2(None)
    Traceback (most recent call last):
    TypeError: Cannot slice None memoryview slice
    """
    buf[:] = buf[::-1]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/nonlocal_T490.pyx0000644000175100001770000000442300000000000020634 0ustar00runnerdocker00000000000000def simple():
    """
    >>> simple()
    1
    2
    """
    x = 1
    y = 2
    def f():
        nonlocal x
        nonlocal x, y
        print(x)
        print(y)
    f()

def assign():
    """
    >>> assign()
    1
    """
    xx = 0
    def ff():
        nonlocal xx
        xx += 1
        print(xx)
    ff()

def nested():
    """
    >>> nested()
    1
    """
    x = 0
    def fx():
        def gx():
            nonlocal x
            x=1
            print(x)
        return gx
    fx()()

def arg(x):
    """
    >>> arg('x')
    xyy
    """
    def appendy():
        nonlocal x
        x += 'y'
    x+='y'
    appendy()
    print x
    return

def argtype(int n):
    """
    >>> argtype(0)
    1
    """
    def inc():
        nonlocal n
        n += 1
    inc()
    print n
    return

def ping_pong():
    """
    >>> f = ping_pong()
    >>> inc, dec = f(0)
    >>> inc()
    1
    >>> inc()
    2
    >>> dec()
    1
    >>> inc()
    2
    >>> dec()
    1
    >>> dec()
    0
    """
    def f(x):
        def inc():
            nonlocal x
            x += 1
            return x
        def dec():
            nonlocal x
            x -= 1
            return x
        return inc, dec
    return f

def methods():
    """
    >>> f = methods()
    >>> c = f(0)
    >>> c.inc()
    1
    >>> c.inc()
    2
    >>> c.dec()
    1
    >>> c.dec()
    0
    """
    def f(x):
        class c:
            def inc(self):
                nonlocal x
                x += 1
                return x
            def dec(self):
                nonlocal x
                x -= 1
                return x
        return c()
    return f

def class_body(int x, y):
    """
    >>> c = class_body(2,99)
    >>> c.z
    (3, 2)
    >>> c.x     #doctest: +ELLIPSIS
    Traceback (most recent call last):
    AttributeError: ...
    >>> c.y     #doctest: +ELLIPSIS
    Traceback (most recent call last):
    AttributeError: ...
    """
    class c(object):
        nonlocal x
        nonlocal y
        y = 2
        x += 1
        z = x,y
    return c()

def nested_nonlocals(x):
    """
    >>> g = nested_nonlocals(1)
    >>> h = g()
    >>> h()
    3
    """
    def g():
        nonlocal x
        x -= 2
        def h():
            nonlocal x
            x += 4
            return x
        return h
    return g
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/nononetypecheck.pyx0000644000175100001770000000014600000000000021501 0ustar00runnerdocker00000000000000cdef class Spam:
    pass

cdef f(Spam s):
    pass

def g():
    """
    >>> g()
    """
    f(None)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/notinop.pyx0000644000175100001770000001625400000000000020002 0ustar00runnerdocker00000000000000
cimport cython

def f(a,b):
    """
    >>> f(1,[1,2,3])
    False
    >>> f(5,[1,2,3])
    True
    >>> f(2,(1,2,3))
    False
    """
    result = a not in b
    return result

def g(a,b):
    """
    >>> g(1,[1,2,3])
    0
    >>> g(5,[1,2,3])
    1
    >>> g(2,(1,2,3))
    0
    """
    cdef int result
    result = a not in b
    return result

def h(b):
    """
    >>> h([1,2,3,4])
    False
    >>> h([1,3,4])
    True
    """
    result = 2 not in b
    return result

def j(b):
    """
    >>> j([1,2,3,4])
    0
    >>> j([1,3,4])
    1
    """
    cdef int result
    result = 2 not in b
    return result

@cython.test_fail_if_path_exists("//SwitchStatNode")
def k(a):
    """
    >>> k(1)
    0
    >>> k(5)
    1
    """
    cdef int result = a not in [1,2,3,4]
    return result

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def m_list(int a):
    """
    >>> m_list(2)
    0
    >>> m_list(5)
    1
    """
    cdef int result = a not in [1,2,3,4]
    return result

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def m_tuple(int a):
    """
    >>> m_tuple(2)
    0
    >>> m_tuple(5)
    1
    """
    cdef int result = a not in (1,2,3,4)
    return result

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//BoolBinopNode", "//PrimaryCmpNode")
def m_set(int a):
    """
    >>> m_set(2)
    0
    >>> m_set(5)
    1
    """
    cdef int result = a not in {1,2,3,4}
    return result

cdef bytes bytes_string = b'abcdefg'

@cython.test_assert_path_exists("//PrimaryCmpNode")
@cython.test_fail_if_path_exists("//SwitchStatNode", "//BoolBinopNode", "//BoolBinopNode")
def m_bytes(char a):
    """
    >>> m_bytes(ord('f'))
    0
    >>> m_bytes(ord('X'))
    1
    """
    cdef int result = a not in bytes_string
    return result

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//BoolBinopNode", "//PrimaryCmpNode")
def m_bytes_literal(char a):
    """
    >>> m_bytes_literal(ord('f'))
    0
    >>> m_bytes_literal(ord('X'))
    1
    """
    cdef int result = a not in b'abcdefg'
    return result

cdef unicode unicode_string = u'abcdefg\u1234\uF8D2'
py_unicode_string = unicode_string

cdef unicode klingon_character = u'\uF8D2'
py_klingon_character = klingon_character

@cython.test_assert_path_exists("//PrimaryCmpNode")
@cython.test_fail_if_path_exists("//SwitchStatNode", "//BoolBinopNode", "//BoolBinopNode")
def m_unicode(Py_UNICODE a, unicode unicode_string):
    """
    >>> m_unicode(ord('f'), py_unicode_string)
    0
    >>> m_unicode(ord('X'), py_unicode_string)
    1
    >>> m_unicode(ord(py_klingon_character), py_unicode_string)
    0
    >>> 'f' in None    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...iterable...
    >>> m_unicode(ord('f'), None)
    Traceback (most recent call last):
    TypeError: argument of type 'NoneType' is not iterable
    """
    cdef int result = a not in unicode_string
    return result

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//BoolBinopNode", "//PrimaryCmpNode")
def m_unicode_literal(Py_UNICODE a):
    """
    >>> m_unicode_literal(ord('f'))
    0
    >>> m_unicode_literal(ord('X'))
    1
    >>> m_unicode_literal(ord(py_klingon_character))
    0
    """
    cdef int result = a not in u'abcdefg\u1234\uF8D2'
    return result

@cython.test_assert_path_exists("//SwitchStatNode", "//BoolBinopNode")
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def m_tuple_in_or_notin(int a):
    """
    >>> m_tuple_in_or_notin(2)
    0
    >>> m_tuple_in_or_notin(3)
    1
    >>> m_tuple_in_or_notin(5)
    1
    """
    cdef int result = a not in (1,2,3,4) or a in (3,4)
    return result

@cython.test_assert_path_exists("//SwitchStatNode", "//BoolBinopNode")
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def m_tuple_notin_or_notin(int a):
    """
    >>> m_tuple_notin_or_notin(2)
    1
    >>> m_tuple_notin_or_notin(6)
    1
    >>> m_tuple_notin_or_notin(4)
    0
    """
    cdef int result = a not in (1,2,3,4) or a not in (4,5)
    return result

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//BoolBinopNode", "//PrimaryCmpNode")
def m_tuple_notin_and_notin(int a):
    """
    >>> m_tuple_notin_and_notin(2)
    0
    >>> m_tuple_notin_and_notin(6)
    0
    >>> m_tuple_notin_and_notin(5)
    1
    """
    cdef int result = a not in (1,2,3,4) and a not in (6,7)
    return result

@cython.test_assert_path_exists("//SwitchStatNode", "//BoolBinopNode")
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def m_tuple_notin_and_notin_overlap(int a):
    """
    >>> m_tuple_notin_and_notin_overlap(2)
    0
    >>> m_tuple_notin_and_notin_overlap(4)
    0
    >>> m_tuple_notin_and_notin_overlap(5)
    1
    """
    cdef int result = a not in (1,2,3,4) and a not in (3,4)
    return result

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//BoolBinopNode", "//PrimaryCmpNode")
def conditional_int(int a):
    """
    >>> conditional_int(1)
    2
    >>> conditional_int(0)
    1
    >>> conditional_int(5)
    1
    """
    return 1 if a not in (1,2,3,4) else 2

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//BoolBinopNode", "//PrimaryCmpNode")
def conditional_object(int a):
    """
    >>> conditional_object(1)
    '2'
    >>> conditional_object(0)
    1
    >>> conditional_object(5)
    1
    """
    return 1 if a not in (1,2,3,4) else '2'

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//BoolBinopNode", "//PrimaryCmpNode")
def conditional_bytes(char a):
    """
    >>> conditional_bytes(ord('a'))
    '2'
    >>> conditional_bytes(ord('X'))
    1
    >>> conditional_bytes(0)
    1
    """
    return 1 if a not in b'abc' else '2'

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//BoolBinopNode", "//PrimaryCmpNode")
def conditional_unicode(Py_UNICODE a):
    """
    >>> conditional_unicode(ord('a'))
    '2'
    >>> conditional_unicode(ord('X'))
    1
    >>> conditional_unicode(0)
    1
    """
    return 1 if a not in u'abc' else '2'

@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//BoolBinopNode", "//PrimaryCmpNode")
def conditional_none(int a):
    """
    >>> conditional_none(1)
    1
    >>> conditional_none(0)
    >>> conditional_none(5)
    """
    return None if a not in {1,2,3,4} else 1

def n(a):
    """
    >>> n('d *')
    0
    >>> n('xxx')
    1
    """
    cdef int result = a.lower() not in [u'a *',u'b *',u'c *',u'd *']
    return result

def p(a):
    """
    >>> p('a')
    0
    >>> p(1)
    1
    """
    cdef dict d = {u'a': 1, u'b': 2}
    cdef int result = a not in d
    return result

def q(a):
    """
    >>> q(1)
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not iterable
    """
    cdef dict d = None
    cdef int result = a not in d # should fail with a TypeError
    return result
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_ValueError_T172.pyx0000644000175100001770000000015500000000000022340 0ustar00runnerdocker00000000000000# ticket: t172
# tag: numpy

__doc__ = u"""
    >>> 1
    1
"""
cimport numpy
class ValueError(object): pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_attributes.pyx0000644000175100001770000000345700000000000021733 0ustar00runnerdocker00000000000000# mode: run
# tag: numpy

cimport cython

import numpy as np
cimport numpy as cnp

cnp.import_array()


@cython.test_assert_path_exists(
    "//ReturnStatNode",
    "//ReturnStatNode//IndexNode",
    "//ReturnStatNode//IndexNode//SimpleCallNode",
)
@cython.test_fail_if_path_exists(
    "//ReturnStatNode//AttributeNode",
)
def access_shape():
    """
    >>> print(access_shape())
    10
    """
    cdef cnp.ndarray[double, ndim=2, mode='c'] array_in = \
        1e10 * np.ones((10, 10))

    return array_in.shape[0]


@cython.test_assert_path_exists(
    "//ReturnStatNode",
    "//ReturnStatNode//SimpleCallNode",
)
@cython.test_fail_if_path_exists(
    "//ReturnStatNode//AttributeNode",
)
def access_size():
    """
    >>> print(access_size())
    100
    """
    cdef cnp.ndarray[double, ndim=2, mode='c'] array_in = \
        1e10 * np.ones((10, 10))

    return array_in.size


@cython.test_assert_path_exists(
    "//ReturnStatNode",
    "//ReturnStatNode//IndexNode",
    "//ReturnStatNode//IndexNode//SimpleCallNode",
)
@cython.test_fail_if_path_exists(
    "//ReturnStatNode//AttributeNode",
)
def access_strides():
    """
    >>> x, y = access_strides()
    >>> print(x)
    80
    >>> print(y)
    8
    """
    cdef cnp.ndarray[double, ndim=2, mode='c'] array_in = \
        1e10 * np.ones((10, 10), dtype=np.float64)

    return (array_in.strides[0], array_in.strides[1])


@cython.test_assert_path_exists(
    "//ReturnStatNode",
    "//ReturnStatNode//PrimaryCmpNode",
    "//ReturnStatNode//PrimaryCmpNode//SimpleCallNode",
)
@cython.test_fail_if_path_exists(
    "//ReturnStatNode//AttributeNode",
)
def access_data():
    """
    >>> access_data()
    True
    """
    cdef cnp.ndarray[double, ndim=2, mode='c'] array_in = \
        1e10 * np.ones((10, 10), dtype=np.float64)

    return array_in.data is not NULL
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_bufacc_T155.pyx0000644000175100001770000000042100000000000021472 0ustar00runnerdocker00000000000000# ticket: t155
# tag: numpy

"""
>>> myfunc()
0.5
"""

cimport numpy as np
import numpy as np

def myfunc():
    cdef np.ndarray[float, ndim=2] A = np.ones((1,1), dtype=np.float32)
    cdef int i

    for i from 0 <= i < A.shape[0]:
        A[i, :] /= 2
    return A[0,0]

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_cimport.pyx0000644000175100001770000000013100000000000021204 0ustar00runnerdocker00000000000000# tag: numpy

"""
>>> import sys
>>> 'numpy' in sys.modules
True
"""
cimport numpy as np
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_cimport_1.pyx0000644000175100001770000000103500000000000021430 0ustar00runnerdocker00000000000000# mode: run
# tag: warnings, numpy

cimport numpy as np
# np.import_array not called - should generate warning

cdef extern from *:
    """
    static void** _check_array_api(void) {
        return PyArray_API; /* should be non NULL */
    }
    """
    void** _check_array_api()

def check_array_api():
    """
    >>> check_array_api()
    True
    """
    return _check_array_api() != NULL


_WARNINGS = """
4:8: 'numpy.import_array()' has been added automatically since 'numpy' was cimported but 'numpy.import_array' was not called.
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_cimport_2.pyx0000644000175100001770000000065500000000000021440 0ustar00runnerdocker00000000000000# mode: run
# tag: warnings, numpy

cimport numpy as np
np.import_array()
# np.import_array is called - no warning necessary

cdef extern from *:
    """
    static void** _check_array_api(void) {
        return PyArray_API; /* should be non NULL */
    }
    """
    void** _check_array_api()

def check_array_api():
    """
    >>> check_array_api()
    True
    """
    return _check_array_api() != NULL


_WARNINGS = """
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_cimport_3.pyx0000644000175100001770000000020000000000000021423 0ustar00runnerdocker00000000000000# mode: compile
# tag: warnings, numpy

import numpy as np
# Numpy is only imported - no warning necessary

_WARNINGS = """
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_cimport_4.pyx0000644000175100001770000000074100000000000021436 0ustar00runnerdocker00000000000000# mode: run
# tag: warnings, numpy

cimport numpy
numpy.import_array # dummy call should stop Cython auto-generating call to import_array

cdef extern from *:
    """
    static void** _check_array_api(void) {
        return PyArray_API; /* should be non NULL if initialized */
    }
    """
    void** _check_array_api()

def check_array_api():
    """
    >>> check_array_api()
    True
    """
    return _check_array_api() == NULL # not initialized


_WARNINGS = """
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_cimport_5.pyx0000644000175100001770000000104400000000000021434 0ustar00runnerdocker00000000000000# mode: run
# tag: warnings, numpy

from numpy cimport ndarray
# np.import_array not called - should generate warning

cdef extern from *:
    """
    static void** _check_array_api(void) {
        return PyArray_API; /* should be non NULL */
    }
    """
    void** _check_array_api()

def check_array_api():
    """
    >>> check_array_api()
    True
    """
    return _check_array_api() != NULL


_WARNINGS = """
4:0: 'numpy.import_array()' has been added automatically since 'numpy' was cimported but 'numpy.import_array' was not called.
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_cimport_6.pyx0000644000175100001770000000067700000000000021450 0ustar00runnerdocker00000000000000# mode: run
# tag: warnings, numpy

from numpy cimport ndarray, import_array
import_array()
# np.import_array is called - no warning necessary

cdef extern from *:
    """
    static void** _check_array_api(void) {
        return PyArray_API; /* should be non NULL */
    }
    """
    void** _check_array_api()

def check_array_api():
    """
    >>> check_array_api()
    True
    """
    return _check_array_api() != NULL


_WARNINGS = """
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_import_array_error.srctree0000644000175100001770000000170500000000000024307 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext -i
PYTHON main.py

############# setup.py ############

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize('cimport_numpy.pyx'))

############# numpy.pxd ############

# A fake Numpy module. This defines a version of _import_array
# that always fails. The Cython-generated call to _import_array
# happens quite early (before the stringtab is initialized)
# and thus the error itself handling could cause a segmentation fault
# https://github.com/cython/cython/issues/4377

cdef extern from *:
    """
    #define NPY_FEATURE_VERSION
    static int _import_array(void) {
        PyErr_SetString(PyExc_ValueError, "Oh no!");
        return -1;
    }
    """
    int _import_array() except -1
    
############# cimport_numpy.pyx ###########

cimport numpy

############# main.py ####################

try:
    import cimport_numpy
except ImportError as e:
    print(e)
else:
    assert(False)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_math.pyx0000644000175100001770000000224100000000000020464 0ustar00runnerdocker00000000000000# tag: numpy
# tag: no-cpp
# Numpy <= 1.7.1 doesn't have a C++ guard in the header file.

cimport numpy.math as npmath


def test_fp_classif():
    """
    >>> test_fp_classif()
    """

    cdef double d_zero
    cdef float f_zero

    d_zero = -1 * 0.
    f_zero = -1 * 0.

    assert d_zero == npmath.NZERO
    assert f_zero == npmath.NZERO

    assert npmath.signbit(d_zero)
    assert npmath.signbit(f_zero)

    d_zero = 1 * 0.
    f_zero = 1 * 0.

    assert d_zero == npmath.PZERO
    assert f_zero == npmath.PZERO

    assert not npmath.signbit(d_zero)
    assert not npmath.signbit(f_zero)

    assert not npmath.isinf(d_zero)
    assert not npmath.isinf(f_zero)

    assert not npmath.isnan(d_zero)
    assert not npmath.isnan(f_zero)

    assert npmath.isinf(-npmath.INFINITY)
    assert npmath.isinf(npmath.INFINITY)
    assert npmath.isnan(npmath.NAN)

    assert npmath.signbit(npmath.copysign(1., -1.))


def test_nextafter():
    """
    >>> test_nextafter()
    """

    x = npmath.nextafter(npmath.EULER, 1)
    assert npmath.isfinite(x)
    assert x > npmath.EULER

    x = npmath.nextafter(npmath.PI_4, -1)
    assert npmath.isfinite(x)
    assert x < npmath.PI_4
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_parallel.pyx0000644000175100001770000000116200000000000021330 0ustar00runnerdocker00000000000000# tag: numpy
# tag: openmp

cimport cython
from cython.parallel import prange
cimport numpy as np


@cython.boundscheck(False)
def test_parallel_numpy_arrays():
    """
    >>> test_parallel_numpy_arrays()
    -5
    -4
    -3
    -2
    -1
    0
    1
    2
    3
    4
    """
    cdef Py_ssize_t i, length
    cdef np.ndarray[np.int_t] x

    try:
        import numpy
    except ImportError:
        for i in range(-5, 5):
            print i
        return

    x = numpy.zeros(10, dtype=numpy.int_)
    length = x.shape[0]

    for i in prange(length, nogil=True):
        x[i] = i - 5

    for i in x:
        print(i)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_pythran.pyx0000644000175100001770000000342300000000000021223 0ustar00runnerdocker00000000000000# mode: run
# tag: pythran, numpy, cpp
# cython: np_pythran=True

import numpy as np
cimport numpy as cnp

def diffuse():
    """
    >>> u = diffuse()
    >>> count_non_zero = np.sum(u > 0)
    >>> 850 < count_non_zero < (2**5) * (2**5) or count_non_zero
    True
    """
    lx, ly = (2**5, 2**5)
    u = np.zeros([lx, ly], dtype=np.double)
    u[lx // 2, ly // 2] = 1000.0
    _diffuse_numpy(u, 50)
    return u


def _diffuse_numpy(cnp.ndarray[double, ndim=2] u, int N):
    """
    Apply Numpy matrix for the Forward-Euler Approximation
    """
    cdef cnp.ndarray[double, ndim=2] temp = np.zeros_like(u)
    mu = 0.1

    for n in range(N):
        temp[1:-1, 1:-1] = u[1:-1, 1:-1] + mu * (
            u[2:, 1:-1] - 2 * u[1:-1, 1:-1] + u[0:-2, 1:-1] +
            u[1:-1, 2:] - 2 * u[1:-1, 1:-1] + u[1:-1, 0:-2])
        u[:, :] = temp[:, :]
        temp[:, :] = 0.0


def calculate_tax(cnp.ndarray[double, ndim=1] d):
    """
    >>> mu, sigma = 10.64, .35
    >>> np.random.seed(1234)
    >>> d = np.random.lognormal(mu, sigma, 10000)
    >>> avg = calculate_tax(d)
    >>> 0.243 < avg < 0.244 or avg  # 0.24342652180085891
    True
    """
    tax_seg1 = d[(d > 256303)] * 0.45 - 16164.53
    tax_seg2 = d[(d > 54057) & (d <= 256303)] * 0.42 - 8475.44
    seg3 = d[(d > 13769) & (d <= 54057)] - 13769
    seg4 = d[(d > 8820) & (d <= 13769)] - 8820
    prog_seg3 = seg3 * 0.0000022376 + 0.2397
    prog_seg4 = seg4 * 0.0000100727 + 0.14
    return (
        np.sum(tax_seg1) +
        np.sum(tax_seg2) +
        np.sum(seg3 * prog_seg3 + 939.57) +
        np.sum(seg4 * prog_seg4)
    ) / np.sum(d)

def access_shape():
    """
    >>> access_shape()
    10
    """
    cdef cnp.ndarray[double, ndim=2, mode='c'] array_in = \
                    1e10 * np.ones((10, 10))

    return array_in.shape[0]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_pythran_unit.pyx0000644000175100001770000000073700000000000022267 0ustar00runnerdocker00000000000000# mode: run
# tag: pythran, numpy, cpp
# cython: np_pythran=True

import numpy as np
cimport numpy as np

def trigo(np.ndarray[double, ndim=1] angles):

    """
    >>> a = np.array([0., np.pi, np.pi *2])
    >>> trigo(a)
    array([ 1., -1.,  1.])
    """
    return np.cos(angles)

def power(np.ndarray[double, ndim=1] values):

    """
    >>> a = np.array([0., 1., 2.])
    >>> res = power(a)
    >>> res[0], res[1], res[2]
    (0.0, 1.0, 8.0)
    """
    return values ** 3
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_subarray.pyx0000644000175100001770000000241300000000000021364 0ustar00runnerdocker00000000000000# tag: numpy

cimport numpy as np
cimport cython

import numpy as py_numpy

__doc__ = u"""

    >>> test_record_subarray()
    
"""

def test_record_subarray():
    cdef np.ndarray x = py_numpy.zeros((2,2),
                                       dtype=[('a', py_numpy.int32),
                                              ('b', py_numpy.float64, (3, 3))])
    cdef np.dtype descr   = x.dtype
    cdef np.dtype a_descr = descr.fields['a'][0]
    cdef np.dtype b_descr = descr.fields['b'][0]

    # Make sure the dtype looks like we expect
    assert descr.fields == {'a': (py_numpy.dtype('int32'), 0),
                            'b': (py_numpy.dtype(('=f8', (3, 3))), 4)}, descr.fields

    # Make sure that HASSUBARRAY is working
    assert not np.PyDataType_HASSUBARRAY(descr)
    assert not np.PyDataType_HASSUBARRAY(a_descr)
    assert np.PyDataType_HASSUBARRAY(b_descr)

    # Make sure the direct field access works
    assert b_descr.subarray.shape == (3, 3), b_descr.subarray.shape

    # Make sure the safe high-level helper function works
    assert np.PyDataType_SHAPE(descr) == (), np.PyDataType_SHAPE(descr)
    assert np.PyDataType_SHAPE(a_descr) == (), np.PyDataType_SHAPE(a_descr)
    assert np.PyDataType_SHAPE(b_descr) == (3, 3), np.PyDataType_SHAPE(b_descr)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/numpy_test.pyx0000644000175100001770000006556100000000000020530 0ustar00runnerdocker00000000000000# mode: run
# tag: numpy

cimport numpy as np
cimport cython

import numpy as np

import re


def little_endian():
    cdef int endian_detector = 1
    return (&endian_detector)[0] != 0


def testcase(f):
    # testcase decorator now does nothing (following changes to doctest)
    # but is a useful indicator of what functions are designed as tests
    return f


if little_endian():
    my_endian = '<'
    other_endian = '>'
else:
    my_endian = '>'
    other_endian = '<'


def assert_dtype_sizes():
    """
    >>> assert_dtype_sizes()
    """
    assert sizeof(np.int8_t) == 1
    assert sizeof(np.int16_t) == 2
    assert sizeof(np.int32_t) == 4
    assert sizeof(np.int64_t) == 8
    assert sizeof(np.uint8_t) == 1
    assert sizeof(np.uint16_t) == 2
    assert sizeof(np.uint32_t) == 4
    assert sizeof(np.uint64_t) == 8
    assert sizeof(np.float32_t) == 4
    assert sizeof(np.float64_t) == 8
    assert sizeof(np.complex64_t) == 8
    assert sizeof(np.complex128_t) == 16


@testcase
def test_enums():
    """
    >>> test_enums()
    """
    cdef np.NPY_CASTING nc = np.NPY_NO_CASTING
    assert nc != np.NPY_SAFE_CASTING


def ndarray_str(arr):
    u"""
    Work around display differences in NumPy 1.14.
    """
    return re.sub(ur'\[ +', '[', unicode(arr))


def basic():
    """
    >>> basic()
    [[0 1 2 3 4]
     [5 6 7 8 9]]
    2 0 9 5
    """
    cdef object[int, ndim=2] buf = np.arange(10, dtype='i').reshape((2, 5))
    print buf
    print buf[0, 2], buf[0, 0], buf[1, 4], buf[1, 0]


def three_dim():
    """
    >>> three_dim()  # doctest: +NORMALIZE_WHITESPACE
    [[[0.   1.   2.   3.]
      [4.   5.   6.   7.]]
    
     [[8.   9.  10.  11.]
      [12.  13.  14.  15.]]
    
     [[16.  17.  18.  19.]
      [20.  21.  22.  23.]]]
    6.0 0.0 13.0 8.0
    """
    cdef object[double, ndim=3] buf = np.arange(24, dtype='d').reshape((3,2,4))
    print ndarray_str(buf)
    print buf[0, 1, 2], buf[0, 0, 0], buf[1, 1, 1], buf[1, 0, 0]


def obj_array():
    """
    >>> obj_array()
    [a 1 {}]
    a 1 {}
    """
    cdef object[object, ndim=1] buf = np.array(["a", 1, {}])
    print str(buf).replace('"', '').replace("'", '')
    print buf[0], buf[1], buf[2]


def print_long_2d(np.ndarray[long, ndim=2] arr):
    """
    Test various forms of slicing, picking etc.
    >>> a = np.arange(10, dtype='l').reshape(2, 5)
    >>> print_long_2d(a)
    0 1 2 3 4
    5 6 7 8 9
    >>> print_long_2d(a[::-1, ::-1])
    9 8 7 6 5
    4 3 2 1 0
    >>> print_long_2d(a[1:2, 1:3])
    6 7
    >>> print_long_2d(a[::2, ::2])
    0 2 4
    >>> print_long_2d(a[::4, :])
    0 1 2 3 4
    >>> print_long_2d(a[:, 1:5:2])
    1 3
    6 8
    >>> print_long_2d(a[:, 5:1:-2])
    4 2
    9 7
    >>> print_long_2d(a[:, [3, 1]])
    3 1
    8 6
    >>> print_long_2d(a.T)
    0 5
    1 6
    2 7
    3 8
    4 9
    """
    cdef int i, j
    for i in range(arr.shape[0]):
        print u" ".join([unicode(arr[i, j]) for j in range(arr.shape[1])])


def put_range_long_1d(np.ndarray[long] arr):
    """
    Write to slices
    >>> b = np.arange(10, dtype='l').reshape(2, 5)
    >>> put_range_long_1d(b[:, 3])
    >>> print (b)
    [[0 1 2 0 4]
     [5 6 7 1 9]]
    >>> put_range_long_1d(b[::-1, 3])
    >>> print (b)
    [[0 1 2 1 4]
     [5 6 7 0 9]]
    >>> a = np.zeros(9, dtype='l')
    >>> put_range_long_1d(a[1::3])
    >>> print (a)
    [0 0 0 0 1 0 0 2 0]

    Write to picked subarrays. This should NOT change the original
    array as picking creates a new mutable copy.
    >>> a = np.zeros(10, dtype='l').reshape(2, 5)
    >>> put_range_long_1d(a[[0, 0, 1, 1, 0], [0, 1, 2, 4, 3]])
    >>> print (a)
    [[0 0 0 0 0]
     [0 0 0 0 0]]
    """
    # Writes 0,1,2,... to array and returns array
    cdef int value = 0, i
    for i in range(arr.shape[0]):
        arr[i] = value
        value += 1


def test_c_contig(np.ndarray[int, ndim=2, mode='c'] arr):
    """
    Test contiguous access modes:
    >>> c_arr = np.array(np.arange(12, dtype='i').reshape(3,4), order='C')
    >>> f_arr = np.array(np.arange(12, dtype='i').reshape(3,4), order='F')
    >>> test_c_contig(c_arr)
    0 1 2 3
    4 5 6 7
    8 9 10 11
    >>> test_c_contig(f_arr) #doctest: +ELLIPSIS
    Traceback (most recent call last):
       ...
    ValueError: ndarray is not C...contiguous
    >>> test_c_contig(c_arr[::2,::2]) #doctest: +ELLIPSIS
    Traceback (most recent call last):
       ...
    ValueError: ndarray is not C...contiguous
    """
    cdef int i, j
    for i in range(arr.shape[0]):
        print u" ".join([unicode(arr[i, j]) for j in range(arr.shape[1])])


def test_f_contig(np.ndarray[int, ndim=2, mode='fortran'] arr):
    """
    Test contiguous access modes:
    >>> c_arr = np.array(np.arange(12, dtype='i').reshape(3,4), order='C')
    >>> f_arr = np.array(np.arange(12, dtype='i').reshape(3,4), order='F')
    >>> test_f_contig(f_arr)
    0 1 2 3
    4 5 6 7
    8 9 10 11
    >>> test_f_contig(c_arr) #doctest: +ELLIPSIS
    Traceback (most recent call last):
       ...
    ValueError: ndarray is not Fortran contiguous
    """
    cdef int i, j
    for i in range(arr.shape[0]):
        print u" ".join([unicode(arr[i, j]) for j in range(arr.shape[1])])


# Exhaustive dtype tests -- increments element [1] by 1 (or 1+1j) for all dtypes
def inc1_bool(np.ndarray[unsigned char] arr):           arr[1] += 1
def inc1_byte(np.ndarray[char] arr):                    arr[1] += 1
def inc1_ubyte(np.ndarray[unsigned char] arr):          arr[1] += 1
def inc1_short(np.ndarray[short] arr):                  arr[1] += 1
def inc1_ushort(np.ndarray[unsigned short] arr):        arr[1] += 1
def inc1_int(np.ndarray[int] arr):                      arr[1] += 1
def inc1_uint(np.ndarray[unsigned int] arr):            arr[1] += 1
def inc1_long(np.ndarray[long] arr):                    arr[1] += 1
def inc1_ulong(np.ndarray[unsigned long] arr):          arr[1] += 1
def inc1_longlong(np.ndarray[long long] arr):           arr[1] += 1
def inc1_ulonglong(np.ndarray[unsigned long long] arr): arr[1] += 1

def inc1_float(np.ndarray[float] arr):                  arr[1] += 1
def inc1_double(np.ndarray[double] arr):                arr[1] += 1
def inc1_longdouble(np.ndarray[long double] arr):       arr[1] += 1

def inc1_cfloat(np.ndarray[float complex] arr):            arr[1] = arr[1] + 1 + 1j
def inc1_cdouble(np.ndarray[double complex] arr):          arr[1] = (arr[1] + 1) + 1j
def inc1_clongdouble(np.ndarray[long double complex] arr): arr[1] = arr[1] + (1 + 1j)

def inc1_cfloat_struct(np.ndarray[np.cfloat_t] arr):
    arr[1].real += 1
    arr[1].imag += 1

def inc1_cdouble_struct(np.ndarray[np.cdouble_t] arr):
    arr[1].real += 1
    arr[1].imag += 1

def inc1_clongdouble_struct(np.ndarray[np.clongdouble_t] arr):
    cdef long double x
    x = arr[1].real + 1
    arr[1].real = x
    arr[1].imag = arr[1].imag + 1

def inc1_object(np.ndarray[object] arr):
    o = arr[1]
    o += 1
    arr[1] = o # unfortunately, += segfaults for objects

def inc1_int_t(np.ndarray[np.int_t] arr):               arr[1] += 1
def inc1_longlong_t(np.ndarray[np.longlong_t] arr):     arr[1] += 1
def inc1_float_t(np.ndarray[np.float_t] arr):           arr[1] += 1
def inc1_double_t(np.ndarray[np.double_t] arr):         arr[1] += 1
def inc1_longdouble_t(np.ndarray[np.longdouble_t] arr): arr[1] += 1
def inc1_intp_t(np.ndarray[np.intp_t] arr):             arr[1] += 1
def inc1_uintp_t(np.ndarray[np.uintp_t] arr):           arr[1] += 1

# The tests below only work on platforms that has the given types
def inc1_int32_t(np.ndarray[np.int32_t] arr):           arr[1] += 1
def inc1_float64_t(np.ndarray[np.float64_t] arr):       arr[1] += 1


def test_dtype(dtype, inc1):
    """
    >>> test_dtype('?', inc1_bool)
    >>> test_dtype('b', inc1_byte)
    >>> test_dtype('B', inc1_ubyte)
    >>> test_dtype('h', inc1_short)
    >>> test_dtype('H', inc1_ushort)
    >>> test_dtype('i', inc1_int)
    >>> test_dtype('I', inc1_uint)
    >>> test_dtype('l', inc1_long)
    >>> test_dtype('L', inc1_ulong)

    >>> test_dtype('f', inc1_float)
    >>> test_dtype('d', inc1_double)
    >>> test_dtype('g', inc1_longdouble)
    >>> test_dtype('O', inc1_object)
    >>> test_dtype('F', inc1_cfloat) # numpy format codes differ from buffer ones here
    >>> test_dtype('D', inc1_cdouble)
    >>> test_dtype('G', inc1_clongdouble)
    >>> test_dtype('F', inc1_cfloat_struct)
    >>> test_dtype('D', inc1_cdouble_struct)
    >>> test_dtype('G', inc1_clongdouble_struct)

    >>> test_dtype(np.int_, inc1_int_t)
    >>> test_dtype(np.longlong, inc1_longlong_t)
    >>> test_dtype(np.float_, inc1_float_t)
    >>> test_dtype(np.double, inc1_double_t)
    >>> test_dtype(np.intp, inc1_intp_t)
    >>> test_dtype(np.uintp, inc1_uintp_t)

    >>> test_dtype(np.longdouble, inc1_longdouble_t)

    >>> test_dtype(np.int32, inc1_int32_t)
    >>> test_dtype(np.float64, inc1_float64_t)

    Endian tests:
    >>> test_dtype('%si' % my_endian, inc1_int)
    >>> test_dtype('%si' % other_endian, inc1_int)  #doctest: +ELLIPSIS
    Traceback (most recent call last):
       ...
    ValueError: ...
    """
    if dtype in ("g", np.longdouble,
                 "G", np.clongdouble):
        if sizeof(double) == sizeof(long double): # MSVC
            return
    if dtype in ('F', 'D', 'G'):
        a = np.array([0, 10+10j], dtype=dtype)
        inc1(a)
        if a[1] != (11 + 11j): print u"failed!", a[1]
    elif dtype == '?':
        # bool ndarrays coerce all values to 0 or 1
        a = np.array([0, 0], dtype=dtype)
        inc1(a)
        if a[1] != 1: print u"failed!"
        inc1(a)
        if a[1] != 1: print u"failed!"
    else:
        a = np.array([0, 10], dtype=dtype)
        inc1(a)
        if a[1] != 11: print u"failed!"


cdef struct DoubleInt:
    int x, y

def test_recordarray():
    """
    >>> test_recordarray()
    """
    cdef object[DoubleInt] arr
    arr = np.array([(5,5), (4, 6)], dtype=np.dtype('i,i'))
    cdef DoubleInt rec
    rec = arr[0]
    if rec.x != 5: print u"failed"
    if rec.y != 5: print u"failed"
    rec.y += 5
    arr[1] = rec
    arr[0].x -= 2
    arr[0].y += 3
    if arr[0].x != 3: print u"failed"
    if arr[0].y != 8: print u"failed"
    if arr[1].x != 5: print u"failed"
    if arr[1].y != 10: print u"failed"


cdef struct NestedStruct:
    DoubleInt a
    DoubleInt b

cdef struct BadDoubleInt:
    float x
    int y

cdef struct BadNestedStruct:
    DoubleInt a
    BadDoubleInt b

def test_nested_dtypes(obj):
    """
    >>> print(test_nested_dtypes(np.zeros((3,), dtype=np.dtype([\
            ('a', np.dtype('i,i')),\
            ('b', np.dtype('i,i'))\
        ]))))                              # doctest: +NORMALIZE_WHITESPACE
    array([((0, 0), (0, 0)), ((1, 2), (1, 4)), ((1, 2), (1, 4))],
          dtype=[('a', [('f0', '!i4'), ('f1', '!i4')]), ('b', [('f0', '!i4'), ('f1', '!i4')])])

    >>> print(test_nested_dtypes(np.zeros((3,), dtype=np.dtype([\
            ('a', np.dtype('i,f')),\
            ('b', np.dtype('i,i'))\
        ]))))
    Traceback (most recent call last):
        ...
    ValueError: Buffer dtype mismatch, expected 'int' but got 'float' in 'DoubleInt.y'
    """
    cdef object[NestedStruct] arr = obj
    arr[1].a.x = 1
    arr[1].a.y = 2
    arr[1].b.x = arr[0].a.y + 1
    arr[1].b.y = 4
    arr[2] = arr[1]
    return repr(arr).replace('<', '!').replace('>', '!')


def test_bad_nested_dtypes():
    """
    >>> test_bad_nested_dtypes()
    """
    cdef object[BadNestedStruct] arr


def test_good_cast():
    """
    >>> test_good_cast()
    True
    """
    # Check that a signed int can round-trip through casted unsigned int access
    cdef np.ndarray[unsigned int, cast=True] arr = np.array([-100], dtype='i')
    cdef unsigned int data = arr[0]
    return -100 == data


def test_bad_cast():
    """
    >>> test_bad_cast()
    Traceback (most recent call last):
        ...
    ValueError: Item size of buffer (1 byte) does not match size of 'int' (4 bytes)
    """
    # This should raise an exception
    cdef np.ndarray[int, cast=True] arr = np.array([1], dtype='b')


cdef packed struct PackedStruct:
    char a
    int b

cdef struct UnpackedStruct:
    char a
    int b

cdef struct PartiallyPackedStruct:
    char a
    int b
    PackedStruct sub
    int c

cdef packed struct PartiallyPackedStruct2:
    char a
    int b
    char c
    UnpackedStruct sub

def test_packed_align(np.ndarray[PackedStruct] arr):
    """
    >>> print(test_packed_align(np.zeros((1,), dtype=np.dtype('b,i', align=False))))
    [(22, 23)]
    >>> print(test_packed_align(np.zeros((1,), dtype=np.dtype('b,i', align=True)))) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    ValueError: ...
    """
    arr[0].a = 22
    arr[0].b = 23
    return list(arr)


def test_unpacked_align(np.ndarray[UnpackedStruct] arr):
    """
    The output changed in Python 3:
    >> print(test_unpacked_align(np.zeros((1,), dtype=np.dtype('b,i', align=True))))
    array([(22, 23)],
          dtype=[('f0', '|i1'), ('', '|V3'), ('f1', '!i4')])

    ->

    array([(22, 23)],
          dtype={'names':['f0','f1'], 'formats':['i1','!i4'], 'offsets':[0,4], 'itemsize':8, 'aligned':True})


    >>> print(test_unpacked_align(np.zeros((1,), dtype=np.dtype('b,i', align=True))))
    [(22, 23)]
    >>> print(test_unpacked_align(np.zeros((1,), dtype=np.dtype('b,i', align=False)))) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    ValueError: ...
    """
    arr[0].a = 22
    arr[0].b = 23
    # return repr(arr).replace('<', '!').replace('>', '!')
    return list(arr)


def test_partially_packed_align(np.ndarray[PartiallyPackedStruct] arr):
    arr[0].a = 22
    arr[0].b = 23
    arr[0].sub.a = 24
    arr[0].sub.b = 25
    arr[0].c = 26
    return repr(arr).replace('<', '!').replace('>', '!')


def test_partially_packed_align_2(np.ndarray[PartiallyPackedStruct2] arr):
    arr[0].a = 22
    arr[0].b = 23
    arr[0].c = 24
    arr[0].sub.a = 27
    arr[0].sub.b = 28
    return repr(arr).replace('<', '!').replace('>', '!')


def test_complextypes():
    """
    >>> test_complextypes()
    1,1
    1,1
    8,16
    """
    cdef np.complex64_t x64 = 1, y64 = 1j
    cdef np.complex128_t x128 = 1, y128 = 1j
    x64 = x64 + y64
    print "%.0f,%.0f" % (x64.real, x64.imag)
    x128 = x128 + y128
    print "%.0f,%.0f" % (x128.real, x128.imag)
    print "%d,%d" % (sizeof(x64), sizeof(x128))


cdef struct Point:
    np.float64_t x, y

def test_point_record():
    """
    >>> test_point_record()         # doctest: +NORMALIZE_WHITESPACE
    array([(0., 0.), (1., -1.), (2., -2.)],
          dtype=[('x', '!f8'), ('y', '!f8')])
    """
    cdef np.ndarray[Point] test
    Point_dtype = np.dtype([('x', np.float64), ('y', np.float64)])
    test = np.zeros(3, Point_dtype)
    cdef int i
    for i in range(3):
        test[i].x = i
        test[i].y = -i
    print re.sub(
        r'\.0+\b', '.', repr(test).replace('<', '!').replace('>', '!')
                                  .replace('( ', '(').replace(',  ', ', '))


# Test fused np.ndarray dtypes and runtime dispatch
@testcase
def test_fused_ndarray_floating_dtype(np.ndarray[cython.floating, ndim=1] a):
    """
    >>> import cython
    >>> sorted(test_fused_ndarray_floating_dtype.__signatures__)
    ['double', 'float']


    >>> test_fused_ndarray_floating_dtype[cython.double](np.arange(10, dtype=np.float64))
    ndarray[double,ndim=1] ndarray[double,ndim=1] 5.0 6.0
    >>> test_fused_ndarray_floating_dtype(np.arange(10, dtype=np.float64))
    ndarray[double,ndim=1] ndarray[double,ndim=1] 5.0 6.0

    >>> test_fused_ndarray_floating_dtype[cython.float](np.arange(10, dtype=np.float32))
    ndarray[float,ndim=1] ndarray[float,ndim=1] 5.0 6.0
    >>> test_fused_ndarray_floating_dtype(np.arange(10, dtype=np.float32))
    ndarray[float,ndim=1] ndarray[float,ndim=1] 5.0 6.0
    """
    cdef np.ndarray[cython.floating, ndim=1] b = a
    print cython.typeof(a), cython.typeof(b), a[5], b[6]


double_array = np.linspace(0, 1, 100)
int32_array = np.arange(100, dtype=np.int32)

cdef fused fused_external:
    np.int32_t
    np.int64_t
    np.float32_t
    np.float64_t


@testcase
def test_fused_external(np.ndarray[fused_external, ndim=1] a):
    """
    >>> import cython
    >>> sorted(test_fused_external.__signatures__)
    ['float32_t', 'float64_t', 'int32_t', 'int64_t']

    >>> test_fused_external["float64_t"](double_array)
    float64

    >>> test_fused_external["int32_t"](int32_array)
    int32

    >>> test_fused_external(np.arange(100, dtype=np.int64))
    int64
    """
    print a.dtype


cdef fused fused_buffers:
    np.ndarray[np.int32_t, ndim=1]
    np.int64_t[::1]

@testcase
def test_fused_buffers(fused_buffers arg):
    """
    >>> sorted(test_fused_buffers.__signatures__)
    ['int64_t[::1]', 'ndarray[int32_t,ndim=1]']
    """


cpdef _fused_cpdef_buffers(np.ndarray[fused_external] a):
    print a.dtype

@testcase
def test_fused_cpdef_buffers():
    """
    >>> test_fused_cpdef_buffers()
    int32
    int32
    """
    _fused_cpdef_buffers[np.int32_t](int32_array)

    cdef np.ndarray[np.int32_t] typed_array = int32_array
    _fused_cpdef_buffers(typed_array)


@testcase
def test_fused_ndarray_integral_dtype(np.ndarray[cython.integral, ndim=1] a):
    """
    >>> import cython
    >>> sorted(test_fused_ndarray_integral_dtype.__signatures__)
    ['int', 'long', 'short']

    >>> test_fused_ndarray_integral_dtype[cython.int](np.arange(10, dtype=np.dtype('i')))
    5 6
    >>> test_fused_ndarray_integral_dtype(np.arange(10, dtype=np.dtype('i')))
    5 6

    >>> test_fused_ndarray_integral_dtype[cython.long](np.arange(10, dtype='l'))
    5 6
    >>> test_fused_ndarray_integral_dtype(np.arange(10, dtype='l'))
    5 6
    """
    cdef np.ndarray[cython.integral, ndim=1] b = a
    # Don't print the types, the platform specific sizes can make the dispatcher
    # select different integer types with equal sizeof()
    print a[5], b[6]


cdef fused fused_dtype:
    float complex
    double complex
    object

@testcase
def test_fused_ndarray_other_dtypes(np.ndarray[fused_dtype, ndim=1] a):
    """
    >>> import cython
    >>> sorted(test_fused_ndarray_other_dtypes.__signatures__)
    ['double complex', 'float complex', 'object']
    >>> test_fused_ndarray_other_dtypes(np.arange(10, dtype=np.complex64))
    ndarray[float complex,ndim=1] ndarray[float complex,ndim=1] (5+0j) (6+0j)
    >>> test_fused_ndarray_other_dtypes(np.arange(10, dtype=np.complex128))
    ndarray[double complex,ndim=1] ndarray[double complex,ndim=1] (5+0j) (6+0j)
    >>> test_fused_ndarray_other_dtypes(np.arange(10, dtype=np.object_))
    ndarray[Python object,ndim=1] ndarray[Python object,ndim=1] 5 6
    """
    cdef np.ndarray[fused_dtype, ndim=1] b = a
    print cython.typeof(a), cython.typeof(b), a[5], b[6]


# Test fusing the array types together and runtime dispatch
cdef struct Foo:
    int a
    float b

cdef fused fused_FooArray:
    np.ndarray[Foo, ndim=1]

cdef fused fused_ndarray:
    np.ndarray[float, ndim=1]
    np.ndarray[double, ndim=1]
    np.ndarray[Foo, ndim=1]

def get_Foo_array():
    cdef Foo data[10]
    for i in range(10):
        data[i] = [0, 0]
    data[5].b = 9.0
    return np.asarray(data).copy()

def test_fused_ndarray(fused_ndarray a):
    """
    >>> import cython
    >>> sorted(test_fused_ndarray.__signatures__)
    ['ndarray[Foo,ndim=1]', 'ndarray[double,ndim=1]', 'ndarray[float,ndim=1]']

    >>> test_fused_ndarray(get_Foo_array())
    ndarray[Foo,ndim=1] ndarray[Foo,ndim=1]
    9.0
    >>> test_fused_ndarray(np.arange(10, dtype=np.float64))
    ndarray[double,ndim=1] ndarray[double,ndim=1]
    5.0
    >>> test_fused_ndarray(np.arange(10, dtype=np.float32))
    ndarray[float,ndim=1] ndarray[float,ndim=1]
    5.0
    """
    cdef fused_ndarray b = a
    print cython.typeof(a), cython.typeof(b)

    if fused_ndarray in fused_FooArray:
        print b[5].b
    else:
        print b[5]


cpdef test_fused_cpdef_ndarray(fused_ndarray a):
    """
    >>> import cython
    >>> sorted(test_fused_cpdef_ndarray.__signatures__)
    ['ndarray[Foo,ndim=1]', 'ndarray[double,ndim=1]', 'ndarray[float,ndim=1]']

    >>> test_fused_cpdef_ndarray(get_Foo_array())
    ndarray[Foo,ndim=1] ndarray[Foo,ndim=1]
    9.0
    >>> test_fused_cpdef_ndarray(np.arange(10, dtype=np.float64))
    ndarray[double,ndim=1] ndarray[double,ndim=1]
    5.0
    >>> test_fused_cpdef_ndarray(np.arange(10, dtype=np.float32))
    ndarray[float,ndim=1] ndarray[float,ndim=1]
    5.0
    """
    cdef fused_ndarray b = a
    print cython.typeof(a), cython.typeof(b)

    if fused_ndarray in fused_FooArray:
        print b[5].b
    else:
        print b[5]


def test_fused_cpdef_ndarray_cdef_call():
    """
    >>> test_fused_cpdef_ndarray_cdef_call()
    ndarray[Foo,ndim=1] ndarray[Foo,ndim=1]
    9.0
    """
    cdef np.ndarray[Foo, ndim=1] foo_array = get_Foo_array()
    test_fused_cpdef_ndarray(foo_array)


cdef fused int_type:
    np.int32_t
    np.int64_t

float64_array = np.arange(10, dtype=np.float64)
float32_array = np.arange(10, dtype=np.float32)
int32_array = np.arange(10, dtype=np.int32)
int64_array = np.arange(10, dtype=np.int64)

@testcase
def test_dispatch_non_clashing_declarations_repeating_types(np.ndarray[cython.floating] a1,
                                                            np.ndarray[int_type] a2,
                                                            np.ndarray[cython.floating] a3,
                                                            np.ndarray[int_type] a4):
    """
    >>> test_dispatch_non_clashing_declarations_repeating_types(float64_array, int32_array, float64_array, int32_array)
    1.0 2 3.0 4
    >>> test_dispatch_non_clashing_declarations_repeating_types(float64_array, int64_array, float64_array, int64_array)
    1.0 2 3.0 4
    >>> test_dispatch_non_clashing_declarations_repeating_types(float64_array, int32_array, float64_array, int64_array)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: Buffer dtype mismatch, expected 'int32_t'...
    >>> test_dispatch_non_clashing_declarations_repeating_types(float64_array, int64_array, float64_array, int32_array)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: Buffer dtype mismatch, expected 'int64_t'...
    """
    print a1[1], a2[2], a3[3], a4[4]


ctypedef np.int32_t typedeffed_type

cdef fused typedeffed_fused_type:
    typedeffed_type
    int
    long

@testcase
def test_dispatch_typedef(np.ndarray[typedeffed_fused_type] a):
    """
    >>> test_dispatch_typedef(int32_array)
    5
    """
    print a[5]


cdef extern from "types.h":
    ctypedef char actually_long_t

cdef fused confusing_fused_typedef:
    actually_long_t
    int
    unsigned long
    double complex
    unsigned char
    signed char

def test_dispatch_external_typedef(np.ndarray[confusing_fused_typedef] a):
    """
    >>> test_dispatch_external_typedef(np.arange(-5, 5, dtype=np.int_))
    -2
    """
    print a[3]


# test fused memoryview slices
cdef fused memslice_fused_dtype:
    float
    double
    int
    long
    float complex
    double complex
    object

@testcase
def test_fused_memslice_other_dtypes(memslice_fused_dtype[:] a):
    """
    >>> import cython
    >>> sorted(test_fused_memslice_other_dtypes.__signatures__)
    ['double', 'double complex', 'float', 'float complex', 'int', 'long', 'object']
    >>> test_fused_memslice_other_dtypes(np.arange(10, dtype=np.complex64))
    float complex[:] float complex[:] (5+0j) (6+0j)
    >>> test_fused_memslice_other_dtypes(np.arange(10, dtype=np.complex128))
    double complex[:] double complex[:] (5+0j) (6+0j)
    >>> test_fused_memslice_other_dtypes(np.arange(10, dtype=np.float32))
    float[:] float[:] 5.0 6.0
    >>> test_fused_memslice_other_dtypes(np.arange(10, dtype=np.dtype('i')))
    int[:] int[:] 5 6
    >>> test_fused_memslice_other_dtypes(np.arange(10, dtype=np.object_))
    object[:] object[:] 5 6
    """
    cdef memslice_fused_dtype[:] b = a
    print cython.typeof(a), cython.typeof(b), a[5], b[6]


cdef fused memslice_fused:
    float[:]
    double[:]
    int[:]
    long[:]
    float complex[:]
    double complex[:]
    object[:]

@testcase
def test_fused_memslice(memslice_fused a):
    """
    >>> import cython
    >>> sorted(test_fused_memslice.__signatures__)
    ['double complex[:]', 'double[:]', 'float complex[:]', 'float[:]', 'int[:]', 'long[:]', 'object[:]']
    >>> test_fused_memslice(np.arange(10, dtype=np.complex64))
    float complex[:] float complex[:] (5+0j) (6+0j)
    >>> test_fused_memslice(np.arange(10, dtype=np.complex128))
    double complex[:] double complex[:] (5+0j) (6+0j)
    >>> test_fused_memslice(np.arange(10, dtype=np.float32))
    float[:] float[:] 5.0 6.0
    >>> test_fused_memslice(np.arange(10, dtype=np.dtype('i')))
    int[:] int[:] 5 6
    >>> test_fused_memslice(np.arange(10, dtype=np.object_))
    object[:] object[:] 5 6
    """
    cdef memslice_fused b = a
    print cython.typeof(a), cython.typeof(b), a[5], b[6]


@testcase
def test_dispatch_memoryview_object():
    """
    >>> test_dispatch_memoryview_object()
    int[:] int[:] 5 6
    """
    cdef int[:] m = np.arange(10, dtype=np.dtype('i'))
    cdef int[:] m2 = m
    cdef int[:] m3 =  m
    test_fused_memslice(m3)


cdef fused ndim_t:
    double[:]
    double[:, :]
    double[:, :, :]

@testcase
def test_dispatch_ndim(ndim_t array):
    """
    >>> test_dispatch_ndim(np.empty(5, dtype=np.double))
    double[:] 1
    >>> test_dispatch_ndim(np.empty((5, 5), dtype=np.double))
    double[:, :] 2
    >>> test_dispatch_ndim(np.empty((5, 5, 5), dtype=np.double))
    double[:, :, :] 3

    Test indexing using Cython.Shadow
    >>> import cython
    >>> test_dispatch_ndim[cython.double[:]](np.empty(5, dtype=np.double))
    double[:] 1
    >>> test_dispatch_ndim[cython.double[:, :]](np.empty((5, 5), dtype=np.double))
    double[:, :] 2
    """
    print cython.typeof(array), np.asarray(array).ndim


@testcase
def test_copy_buffer(np.ndarray[double, ndim=1] a):
    """
    >>> a = test_copy_buffer(np.ones(10, dtype=np.double))
    >>> len(a)
    10
    >>> print(a.dtype)
    float64
    >>> a[0]
    1.0
    """
    a = a.copy()
    a = a.copy()
    a = a.copy()
    a = a.copy()
    a = a.copy()
    return a


@testcase
def test_broadcast_comparison(np.ndarray[double, ndim=1] a):
    """
    >>> a = np.ones(10, dtype=np.double)
    >>> a0, obj0, a1, obj1 = test_broadcast_comparison(a)
    >>> np.all(a0 == (a == 0)) or a0
    True
    >>> np.all(a1 == (a == 1)) or a1
    True
    >>> np.all(obj0 == (a == 0)) or obj0
    True
    >>> np.all(obj1 == (a == 1)) or obj1
    True

    >>> a = np.zeros(10, dtype=np.double)
    >>> a0, obj0, a1, obj1 = test_broadcast_comparison(a)
    >>> np.all(a0 == (a == 0)) or a0
    True
    >>> np.all(a1 == (a == 1)) or a1
    True
    >>> np.all(obj0 == (a == 0)) or obj0
    True
    >>> np.all(obj1 == (a == 1)) or obj1
    True
    """
    cdef object obj = a
    return a == 0, obj == 0, a == 1, obj == 1


@testcase
def test_c_api_searchsorted(np.ndarray arr, other):
    """
    >>> arr = np.random.randn(10)
    >>> other = np.random.randn(5)
    >>> result, expected = test_c_api_searchsorted(arr, other)
    >>> (result == expected).all()
    True
    """
    result = np.PyArray_SearchSorted(arr, other, np.NPY_SEARCHRIGHT, NULL)

    expected = arr.searchsorted(other, side="right")
    return result, expected
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/onelinesuite.py0000644000175100001770000000073400000000000020623 0ustar00runnerdocker00000000000000# mode: run
# tag: syntax

"""
>>> y  # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'y' is not defined
>>> z  # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'z' is not defined
>>> f()
17
"""

x = False

if x: y = 42; z = 88
def f(): return 17


def suite_in_func(x):
    """
    >>> suite_in_func(True)
    (42, 88)
    >>> suite_in_func(False)
    (0, 0)
    """
    y = z = 0
    if x: y = 42; z = 88
    return y, z
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/ooo_base_classes.pyx0000644000175100001770000000042500000000000021610 0ustar00runnerdocker00000000000000cdef class B(A):
  cpdef foo(self):
    """
    >>> B().foo()
    B
    """
    print "B"

cdef class A(object):
  cpdef foo(self):
    """
    >>> A().foo()
    A
    """
    print "A"

cdef class C(A):
  cpdef foo(self):
    """
    >>> C().foo()
    C
    """
    print "C"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/or.pyx0000644000175100001770000000246400000000000016732 0ustar00runnerdocker00000000000000a,b = 'a *','b *' # use non-interned strings

def or2_assign(a,b):
    """
    >>> or2_assign(2,3) == (2 or 3)
    True
    >>> or2_assign('a', 'b') == ('a' or 'b')
    True
    >>> or2_assign(a, b) == (a or b)
    True
    """
    c = a or b
    return c

def or2(a,b):
    """
    >>> or2(2,3) == (2 or 3)
    True
    >>> or2(0,2) == (0 or 2)
    True
    >>> or2('a', 'b') == ('a' or 'b')
    True
    >>> or2(a, b) == (a or b)
    True
    >>> or2('', 'b') == ('' or 'b')
    True
    >>> or2([], [1]) == ([] or [1])
    True
    >>> or2([], [a]) == ([] or [a])
    True
    """
    return a or b

def or3(a,b,c):
    """
    >>> or3(0,1,2) == (0 or 1 or 2)
    True
    >>> or3([],(),[1]) == ([] or () or [1])
    True
    """
    d = a or b or c
    return d

def or2_no_result(a,b):
    """
    >>> or2_no_result(2,3)
    >>> or2_no_result(0,2)
    >>> or2_no_result('a','b')
    >>> or2_no_result(a,b)
    >>> a or b
    'a *'
    """
    a or b

def or2_literal():
    """
    >>> or2_literal()
    5
    """
    return False or 5

cdef class A(object):
    def __repr__(self):
        return "A"

def test_GH2059_missing_cast():
    """
    >>> test_GH2059_missing_cast()
    (A, A)
    """
    cdef A a = A()
    cdef object o = None
    cdef A a_first = a or o
    cdef A a_second = o or a
    return a_first, a_second
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/overflow_check.pxi0000644000175100001770000001637600000000000021301 0ustar00runnerdocker00000000000000cimport cython

cdef object two = 2

cdef int size_in_bits_ = sizeof(INT) * 8
cdef bint is_signed_ = not ((-1) > 0)
cdef INT max_value_ = (two ** (size_in_bits_ - is_signed_) - 1)
cdef INT min_value_ = ~max_value_
cdef INT half_ = max_value_ // 2

# Python visible.
size_in_bits = size_in_bits_
is_signed = is_signed_
max_value = max_value_
min_value = min_value_
half = half_


import operator
from libc.math cimport sqrt

cpdef check(func, op, a, b):
    cdef INT res = 0, op_res = 0
    cdef bint func_overflow = False
    cdef bint assign_overflow = False
    try:
        res = func(a, b)
    except OverflowError:
        func_overflow = True
    try:
        op_res = op(a, b)
    except OverflowError:
        assign_overflow = True
    assert func_overflow == assign_overflow, "Inconsistent overflow: %s(%s, %s)" % (func, a, b)
    if not func_overflow:
        assert res == op_res, "Inconsistent values: %s(%s, %s) == %s != %s" % (func, a, b, res, op_res)

medium_values = (max_value_ / 2, max_value_ / 3, min_value_ / 2, sqrt(max_value_) - 1, sqrt(max_value_) + 1)
def run_test(func, op):
    cdef INT offset, b
    check(func, op, 300, 200)
    check(func, op, max_value_, max_value_)
    check(func, op, max_value_, min_value_)
    if not is_signed_ or not func is test_sub:
        check(func, op, min_value_, min_value_)

    for offset in range(5):
        check(func, op, max_value_ - 1, offset)
        check(func, op, min_value_ + 1, offset)
        if is_signed_:
            check(func, op, max_value_ - 1, 2 - offset)
            check(func, op, min_value_ + 1, 2 - offset)

    for offset in range(9):
        check(func, op, max_value_ / 2, offset)
        check(func, op, min_value_ / 3, offset)
        check(func, op, max_value_ / 4, offset)
        check(func, op, min_value_ / 5, offset)
        if is_signed_:
            check(func, op, max_value_ / 2, 4 - offset)
            check(func, op, min_value_ / 3, 4 - offset)
            check(func, op, max_value_ / -4, 3 - offset)
            check(func, op, min_value_ / -5, 3 - offset)

    for offset in range(-3, 4):
        for a in medium_values:
            for b in medium_values:
                check(func, op, a, b + offset)

@cython.overflowcheck(True)
def test_add(INT a, INT b):
    """
    >>> test_add(1, 2)
    3
    >>> test_add(max_value, max_value)   #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: value too large
    >>> run_test(test_add, operator.add)
    """
    return int(a + b)
    
@cython.overflowcheck(True)
def test_sub(INT a, INT b):
    """
    >>> test_sub(10, 1)
    9
    >>> test_sub(min_value, 1)   #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: value too large
    >>> run_test(test_sub, operator.sub)
    """
    return int(a - b)

@cython.overflowcheck(True)
def test_mul(INT a, INT b):
    """
    >>> test_mul(11, 13)
    143
    >>> test_mul(max_value / 2, max_value / 2)   #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: value too large
    >>> run_test(test_mul, operator.mul)
    """
    return int(a * b)

@cython.overflowcheck(True)
def test_nested_add(INT a, INT b, INT c):
    """
    >>> test_nested_add(1, 2, 3)
    6
    >>> expect_overflow(test_nested_add, half + 1, half + 1, half + 1)
    >>> expect_overflow(test_nested_add, half - 1, half - 1, half - 1)
    """
    return int(a + b + c)

def expect_overflow(func, *args):
    try:
        res = func(*args)
    except OverflowError:
        return
    assert False, "Expected OverflowError, got %s" % res

cpdef format(INT value):
    """
    >>> format(1)
    '1'
    >>> format(half - 1)
    'half - 1'
    >>> format(half)
    'half'
    >>> format(half + 2)
    'half + 2'
    >>> format(half + half - 3)
    'half + half - 3'
    >>> format(max_value)
    'max_value'
    """
    if value == max_value_:
        return "max_value"
    elif value == half_:
        return "half"
    elif max_value_ - value <= max_value_ // 4:
        return "half + half - %s" % (half_ + half_ - value)
    elif max_value_ - value <= half_:
        return "half + %s" % (value - half_)
    elif max_value_ - value <= half_ + max_value_ // 4:
        return "half - %s" % (half_ - value)
    else:
        return "%s" % value

cdef INT called(INT value):
    print("called(%s)" % format(value))
    return value

@cython.overflowcheck(True)
def test_nested(INT a, INT b, INT c, INT d):
    """
    >>> test_nested_func(1, 2, 3)
    called(5)
    6
    >>> expect_overflow(test_nested, half, half, 1, 1)
    >>> expect_overflow(test_nested, half, 1, half, half)
    >>> expect_overflow(test_nested, half, 2, half, 2)

    >>> print(format(test_nested(half, 2, 0, 1)))
    half + half - 0
    >>> print(format(test_nested(1, 0, half, 2)))
    half + half - 0
    >>> print(format(test_nested(half, 1, 1, half)))
    half + half - 0
    """
    return int(a * b + c * d)

@cython.overflowcheck(True)
def test_nested_func(INT a, INT b, INT c):
    """
    >>> test_nested_func(1, 2, 3)
    called(5)
    6
    >>> expect_overflow(test_nested_func, half + 1, half + 1, half + 1)
    >>> expect_overflow(test_nested_func, half - 1, half - 1, half - 1)
    called(half + half - 2)
    >>> print(format(test_nested_func(1, half - 1, half - 1)))
    called(half + half - 2)
    half + half - 1
    """
    return int(a + called(b + c))


@cython.overflowcheck(True)
def test_add_const(INT a):
    """
    >>> test_add_const(1)
    101
    >>> expect_overflow(test_add_const, max_value)
    >>> expect_overflow(test_add_const , max_value - 99)
    >>> test_add_const(max_value - 100) == max_value
    True
    """
    return int(a + 100)

@cython.overflowcheck(True)
def test_sub_const(INT a):
    """
    >>> test_sub_const(101)
    1
    >>> expect_overflow(test_sub_const, min_value)
    >>> expect_overflow(test_sub_const, min_value + 99)
    >>> test_sub_const(min_value + 100) == min_value
    True
    """
    return int(a - 100)

@cython.overflowcheck(True)
def test_mul_const(INT a):
    """
    >>> test_mul_const(2)
    200
    >>> expect_overflow(test_mul_const, max_value)
    >>> expect_overflow(test_mul_const, max_value // 99)
    >>> test_mul_const(max_value // 100) == max_value - max_value % 100
    True
    """
    return int(a * 100)

@cython.overflowcheck(True)
def test_lshift(INT a, int b):
    """
    >>> test_lshift(1, 10)
    1024
    >>> test_lshift(1, size_in_bits - 2) == 1 << (size_in_bits - 2)
    True
    >>> test_lshift(0, size_in_bits - 1)
    0
    >>> test_lshift(1, size_in_bits - 1) == 1 << (size_in_bits - 1) if not is_signed else True
    True
    >>> if is_signed: expect_overflow(test_lshift, 1, size_in_bits - 1)
    >>> expect_overflow(test_lshift, 0, size_in_bits)
    >>> expect_overflow(test_lshift, 1, size_in_bits)
    >>> expect_overflow(test_lshift, 0, size_in_bits + 1)
    >>> expect_overflow(test_lshift, 1, size_in_bits + 1)
    >>> expect_overflow(test_lshift, 1, 100)
    >>> expect_overflow(test_lshift, max_value, 1)
    >>> test_lshift(max_value, 0) == max_value
    True
    
    >>> check(test_lshift, operator.lshift, 10, 15)
    >>> check(test_lshift, operator.lshift, 10, 30)
    >>> check(test_lshift, operator.lshift, 100, 60)
    """
    return int(a << b)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/overflow_check_int.pyx0000644000175100001770000000012500000000000022154 0ustar00runnerdocker00000000000000# cython: overflowcheck.fold = True


ctypedef int INT

include "overflow_check.pxi"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/overflow_check_longlong.pyx0000644000175100001770000000013400000000000023201 0ustar00runnerdocker00000000000000# cython: overflowcheck.fold = False


ctypedef long long INT

include "overflow_check.pxi"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/overflow_check_uint.pyx0000644000175100001770000000013700000000000022344 0ustar00runnerdocker00000000000000# cython: overflowcheck.fold = False


ctypedef unsigned int INT

include "overflow_check.pxi"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/overflow_check_ulonglong.pyx0000644000175100001770000000014400000000000023367 0ustar00runnerdocker00000000000000# cython: overflowcheck.fold = True


ctypedef unsigned long long INT

include "overflow_check.pxi"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/owned_arg_refs.pyx0000644000175100001770000000223400000000000021271 0ustar00runnerdocker00000000000000
cdef class Owner:
    cdef object x

cdef call_me_with_owner(Owner owner, x):
    owner.x = "def" # overwrite external reference
    return x        # crashes if x is not owned by function or caller

def test_ext_type_attr():
    """
    >>> test_ext_type_attr()
    'abc5'
    """
    owner = Owner()
    owner.x = ''.join("abc%d" % 5) # non-interned object
    return call_me_with_owner(owner, owner.x)


cdef void call_me_without_gil(Owner owner, x) with gil:
    owner.x = "def" # overwrite external reference
    print x         # crashes if x is not owned by function or caller

def test_ext_type_attr_nogil():
    """
    >>> test_ext_type_attr_nogil()
    abc5
    """
    owner = Owner()
    owner.x = ''.join("abc%d" % 5) # non-interned object
    with nogil:
        call_me_without_gil(owner, owner.x)


# the following isn't dangerous as long as index access uses temps

cdef call_me_with_list(list l, x):
    l[:] = [(1,2), (3,4)] # overwrite external reference
    return x              # crashes if x is not owned by function or caller

def test_index():
    """
    >>> test_index()
    [3, 4]
    """
    l = [[1,2],[3,4]]
    return call_me_with_list(l, l[1])
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/packedstruct_T290.pyx0000644000175100001770000000035100000000000021515 0ustar00runnerdocker00000000000000# ticket: t290

"""
>>> f()
(9, 9)
"""

cdef packed struct MyCdefStruct:
    char a
    double b

ctypedef packed struct MyCTypeDefStruct:
    char a
    double b

def f():
    return (sizeof(MyCdefStruct), sizeof(MyCTypeDefStruct))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/parallel.pyx0000644000175100001770000000711100000000000020100 0ustar00runnerdocker00000000000000# tag: run
# tag: openmp

cimport cython.parallel
from cython.parallel import prange, threadid
cimport openmp
from libc.stdlib cimport malloc, free

openmp.omp_set_nested(1)

cdef int forward(int x) nogil:
    return x

def test_parallel():
    """
    >>> test_parallel()
    """
    cdef int maxthreads = openmp.omp_get_max_threads()
    cdef int *buf =  malloc(sizeof(int) * maxthreads)

    if buf == NULL:
        raise MemoryError

    with nogil, cython.parallel.parallel():
        buf[threadid()] = threadid()
        # Recognise threadid() also when it's used in a function argument.
        # See https://github.com/cython/cython/issues/3594
        buf[forward(cython.parallel.threadid())] = forward(threadid())

    for i in range(maxthreads):
        assert buf[i] == i

    free(buf)

cdef int get_num_threads() noexcept with gil:
    print "get_num_threads called"
    return 3

def test_num_threads():
    """
    >>> test_num_threads()
    1
    get_num_threads called
    3
    get_num_threads called
    3
    """
    cdef int dyn = openmp.omp_get_dynamic()
    cdef int num_threads
    cdef int *p = &num_threads

    openmp.omp_set_dynamic(0)

    with nogil, cython.parallel.parallel(num_threads=1):
        p[0] = openmp.omp_get_num_threads()

    print num_threads

    with nogil, cython.parallel.parallel(num_threads=get_num_threads()):
        p[0] = openmp.omp_get_num_threads()

    print num_threads

    cdef int i
    num_threads = 0xbad
    for i in prange(1, nogil=True, num_threads=get_num_threads()):
        p[0] = openmp.omp_get_num_threads()
        break

    openmp.omp_set_dynamic(dyn)

    return num_threads

'''
def test_parallel_catch():
    """
    >>> test_parallel_catch()
    True
    """
    cdef int i, j, num_threads
    exceptions = []

    for i in prange(100, nogil=True, num_threads=4):
        num_threads = openmp.omp_get_num_threads()

        with gil:
            try:
                for j in prange(100, nogil=True):
                    if i + j > 60:
                        with gil:
                            raise Exception("try and catch me if you can!")
            except Exception, e:
                exceptions.append(e)
                break

    print len(exceptions) == num_threads
    assert len(exceptions) == num_threads, (len(exceptions), num_threads)
'''


cdef void parallel_exception_checked_function(int* ptr, int id) except * nogil:
    # requires the GIL after each call
    ptr[0] = id;

cdef void parallel_call_exception_checked_function_impl(int* arr, int num_threads) nogil:
    # Inside a nogil function, parallel can't be sure that the GIL has been released.
    # Therefore Cython must release the GIL itself.
    # Otherwise, we can experience cause lock-ups if anything inside it acquires the GIL
    # (since if any other thread has finished, it will be holding the GIL).
    #
    # An equivalent test with prange is in "sequential_parallel.pyx"
    with cython.parallel.parallel(num_threads=num_threads):
        parallel_exception_checked_function(arr+threadid(), threadid())


def test_parallel_call_exception_checked_function():
    """
    test_parallel_call_exception_checked_function()
    """
    cdef int maxthreads = openmp.omp_get_max_threads()
    cdef int *buf =  malloc(sizeof(int) * maxthreads)

    if buf == NULL:
        raise MemoryError

    try:
        # Note we *don't* release the GIL here
        parallel_call_exception_checked_function_impl(buf, maxthreads)

        for i in range(maxthreads):
            assert buf[i] == i
    finally:
        free(buf)


OPENMP_PARALLEL = True
include "sequential_parallel.pyx"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/parallel_swap_assign_T425.pyx0000644000175100001770000001625600000000000023226 0ustar00runnerdocker00000000000000# ticket: t425

cimport cython

@cython.test_assert_path_exists(
    "//ParallelAssignmentNode",
    "//ParallelAssignmentNode/SingleAssignmentNode",
    "//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode/NameNode",
    "//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=False]/NameNode",
    )
@cython.test_fail_if_path_exists(
    "//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=True]",
    )
def swap(a,b):
    """
    >>> swap(1,2)
    (2, 1)
    """
    a,b = b,a
    return a,b


@cython.test_assert_path_exists(
    "//ParallelAssignmentNode",
    "//ParallelAssignmentNode/SingleAssignmentNode",
    "//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode/NameNode",
    "//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=False]/NameNode",
    )
@cython.test_fail_if_path_exists(
    "//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=True]",
    )
def swap5(a,b,c,d,e):
    """
    >>> swap5(1,2,3,4,5)
    (5, 4, 3, 2, 1)
    """
    a,b,c,d,e = e,d,c,b,a
    return a,b,c,d,e


@cython.test_assert_path_exists(
    "//ParallelAssignmentNode",
    "//ParallelAssignmentNode/SingleAssignmentNode",
    "//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode/NameNode",
    "//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=False]/NameNode",
    )
@cython.test_fail_if_path_exists(
    "//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=True]",
    )
cdef bint c_swap_cmp5(a, b, c, d, e):
    a,b,c,d,e = e,d,c,b,a
    return a > b > c > d > e

def swap_cmp5(a,b,c,d,e):
    """
    >>> swap_cmp5(1,2,3,4,5)
    True
    """
    return c_swap_cmp5(a,b,c,d,e)


@cython.test_assert_path_exists(
    "//ParallelAssignmentNode",
    "//ParallelAssignmentNode/SingleAssignmentNode",
    "//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode/NameNode",
    "//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=True]/NameNode",
    )
@cython.test_fail_if_path_exists(
    "//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=False]",
    )
def swap_py(a,b):
    """
    >>> swap_py(1,2)
    (1, 2)
    """
    a,a = b,a
    return a,b


cdef class A:
    cdef readonly object x
    cdef readonly object y
    def __init__(self, x, y):
        self.x, self.y = x, y

@cython.test_assert_path_exists(
    "//ParallelAssignmentNode",
    "//ParallelAssignmentNode/SingleAssignmentNode",
    "//ParallelAssignmentNode/SingleAssignmentNode/CoerceToTempNode",
    "//ParallelAssignmentNode/SingleAssignmentNode/CoerceToTempNode[@use_managed_ref=False]",
    "//ParallelAssignmentNode/SingleAssignmentNode//AttributeNode/NameNode",
    "//ParallelAssignmentNode/SingleAssignmentNode//AttributeNode[@use_managed_ref=False]/NameNode",
    )
@cython.test_fail_if_path_exists(
    "//ParallelAssignmentNode/SingleAssignmentNode/CoerceToTempNode[@use_managed_ref=True]",
    "//ParallelAssignmentNode/SingleAssignmentNode/AttributeNode[@use_managed_ref=True]",
    )
def swap_attr_values(A a, A b):
    """
    >>> a, b = A(1,2), A(3,4)
    >>> a.x, a.y, b.x, b.y
    (1, 2, 3, 4)
    >>> swap_attr_values(a,b)
    >>> a.x, a.y, b.x, b.y
    (3, 2, 1, 4)
    """
    a.x, a.y, b.x, b.y = a.y, b.x, b.y, a.x # shift by one
    a.x, a.y, b.x, b.y = b.x, b.y, a.x, a.y # shift by two
    a.x, a.y, b.x, b.y = b.y, b.x, a.y, a.x # reverse


cdef class B:
    cdef readonly A a1
    cdef readonly A a2
    def __init__(self, x1, y1, x2, y2):
        self.a1, self.a2 = A(x1, y1), A(x2, y2)

@cython.test_assert_path_exists(
    "//ParallelAssignmentNode",
    "//ParallelAssignmentNode/SingleAssignmentNode",
    "//ParallelAssignmentNode/SingleAssignmentNode/CoerceToTempNode",
    "//ParallelAssignmentNode/SingleAssignmentNode/CoerceToTempNode[@use_managed_ref=False]",
    "//ParallelAssignmentNode/SingleAssignmentNode//AttributeNode/NameNode",
    "//ParallelAssignmentNode/SingleAssignmentNode//AttributeNode[@use_managed_ref=False]/NameNode",
    )
@cython.test_fail_if_path_exists(
    "//ParallelAssignmentNode/SingleAssignmentNode/CoerceToTempNode[@use_managed_ref=True]",
    "//ParallelAssignmentNode/SingleAssignmentNode/AttributeNode[@use_managed_ref=True]",
    )
def swap_recursive_attr_values(B a, B b):
    """
    >>> a, b = B(1,2,3,4), B(5,6,7,8)
    >>> a.a1.x, a.a1.y, a.a2.x, a.a2.y
    (1, 2, 3, 4)
    >>> b.a1.x, b.a1.y, b.a2.x, b.a2.y
    (5, 6, 7, 8)
    >>> swap_recursive_attr_values(a,b)
    >>> a.a1.x, a.a1.y, a.a2.x, a.a2.y
    (2, 1, 4, 4)
    >>> b.a1.x, b.a1.y, b.a2.x, b.a2.y
    (6, 5, 8, 8)

    # compatibility test
    >>> class A:
    ...     def __init__(self, x, y):
    ...         self.x, self.y = x, y
    >>> class B:
    ...     def __init__(self, x1, y1, x2, y2):
    ...         self.a1, self.a2 = A(x1, y1), A(x2, y2)
    >>> a, b = B(1,2,3,4), B(5,6,7,8)
    >>> a.a1, a.a2 = a.a2, a.a1
    >>> b.a1, b.a2 = b.a2, b.a1
    >>> a.a1, a.a1.x, a.a2.y, a.a2, a.a1.y, a.a2.x = a.a2, a.a2.y, a.a1.x, a.a1, a.a2.x, a.a1.y
    >>> b.a1, b.a1.x, b.a2.y, b.a2, b.a1.y, b.a2.x = b.a2, b.a2.y, b.a1.x, b.a1, b.a2.x, b.a1.y
    >>> a.a1.x, a.a1.y, a.a2.x, a.a2.y
    (2, 1, 4, 4)
    >>> b.a1.x, b.a1.y, b.a2.x, b.a2.y
    (6, 5, 8, 8)
    """
    a.a1, a.a2 = a.a2, a.a1
    b.a1, b.a2 = b.a2, b.a1
    a.a1, a.a1.x, a.a2.y, a.a2, a.a1.y, a.a2.x = a.a2, a.a2.y, a.a1.x, a.a1, a.a2.x, a.a1.y
    b.a1, b.a1.x, b.a2.y, b.a2, b.a1.y, b.a2.x = b.a2, b.a2.y, b.a1.x, b.a1, b.a2.x, b.a1.y


@cython.test_assert_path_exists(
#    "//ParallelAssignmentNode",
#    "//ParallelAssignmentNode/SingleAssignmentNode",
#    "//ParallelAssignmentNode/SingleAssignmentNode//IndexNode",
#    "//ParallelAssignmentNode/SingleAssignmentNode//IndexNode[@use_managed_ref=False]",
    )
@cython.test_fail_if_path_exists(
#    "//ParallelAssignmentNode/SingleAssignmentNode//IndexNode[@use_managed_ref=True]",
    )
def swap_list_items(list a, int i, int j):
    """
    >>> l = [1,2,3,4]
    >>> swap_list_items(l, 1, 2)
    >>> l
    [1, 3, 2, 4]
    >>> swap_list_items(l, 3, 0)
    >>> l
    [4, 3, 2, 1]
    >>> swap_list_items(l, 0, 5)
    Traceback (most recent call last):
    IndexError: list index out of range
    >>> l
    [4, 3, 2, 1]
    """
    a[i], a[j] = a[j], a[i]


@cython.test_assert_path_exists(
    "//ParallelAssignmentNode",
    "//ParallelAssignmentNode/SingleAssignmentNode",
    "//ParallelAssignmentNode/SingleAssignmentNode//IndexNode",
    "//ParallelAssignmentNode/SingleAssignmentNode//IndexNode[@use_managed_ref=True]",
    )
@cython.test_fail_if_path_exists(
    "//ParallelAssignmentNode/SingleAssignmentNode//IndexNode[@use_managed_ref=False]",
    )
def swap_list_items_py1(list a, int i, int j):
    a[i], a[j] = a[j+1], a[i]


@cython.test_assert_path_exists(
    "//ParallelAssignmentNode",
    "//ParallelAssignmentNode/SingleAssignmentNode",
    "//ParallelAssignmentNode/SingleAssignmentNode//IndexNode",
    "//ParallelAssignmentNode/SingleAssignmentNode//IndexNode[@use_managed_ref=True]",
    )
@cython.test_fail_if_path_exists(
    "//ParallelAssignmentNode/SingleAssignmentNode//IndexNode[@use_managed_ref=False]",
    )
def swap_list_items_py2(list a, int i, int j):
    a[i], a[j] = a[i], a[i]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/partial_circular_import.srctree0000644000175100001770000000130400000000000024043 0ustar00runnerdocker00000000000000PYTHON -c 'if __import__("sys").version_info >= (3,7): import pkg.A'
PYTHON setup.py build_ext --inplace
PYTHON -c "import pkg.A"

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup

setup(
    ext_modules = cythonize("*/*.py"),
    )

######## pkg/__init__.py ########

######## pkg/A.py ########
from . import B

def verify(rel_B):
    import pkg.B as abs_B
    assert abs_B == rel_B
verify(B)

######## pkg/B.py ########
from . import C

def verify(rel_C):
    import pkg.C as abs_C
    assert abs_C == rel_C
verify(C)

######## pkg/C.py ########
from . import B

def verify(rel_B):
    import pkg.B as abs_B
    assert abs_B == rel_B

verify(B)

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/pass.pyx0000644000175100001770000000005600000000000017253 0ustar00runnerdocker00000000000000def f():
    """
    >>> f()
    """
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/pep442_tp_finalize.pyx0000644000175100001770000001521300000000000021710 0ustar00runnerdocker00000000000000# mode: run

from __future__ import print_function

cimport cython

import gc

cdef class nontrivial_del:
    def __init__(self):
        print("init")

    def __del__(self):
        print("del")

def test_del():
    """
    >>> test_del()
    start
    init
    del
    finish
    """
    print("start")
    d = nontrivial_del()
    d = None
    gc.collect()
    print("finish")


cdef class del_and_dealloc:
    def __init__(self):
        print("init")

    def __del__(self):
        print("del")

    def __dealloc__(self):
        print("dealloc")

def test_del_and_dealloc():
    """
    >>> test_del_and_dealloc()
    start
    init
    del
    dealloc
    finish
    """
    print("start")
    d = del_and_dealloc()
    d = None
    gc.collect()
    print("finish")

@cython.final
cdef class FinalClass:
    def __init__(self):
        print("init")
    def __del__(self):
        print("del")

def test_final_class():
    """
    >>> test_final_class()
    start
    init
    del
    finish
    """
    print("start")
    d = FinalClass()
    d = None
    gc.collect()
    print("finish")

@cython.final
cdef class FinalInherits(nontrivial_del):
    def __init__(self):
        super().__init__()
        print("FinalInherits init")
    # no __del__ but nontrivial_del should still be called
    def __dealloc__(self):
        pass  # define __dealloc__ so as not to fall back on base __dealloc__

def test_final_inherited():
    """
    >>> test_final_inherited()
    start
    init
    FinalInherits init
    del
    finish
    """
    print("start")
    d = FinalInherits()
    d = None
    gc.collect()
    print("finish")

cdef class DummyBase:
    pass

class RegularClass:
    __slots__ = ()
    def __del__(self):
        print("del")

@cython.final
cdef class FinalMultipleInheritance(DummyBase, RegularClass):
    def __init__(self):
        super().__init__()
        print("init")
    def __dealloc__(self):
        pass

def test_final_multiple_inheritance():
    """
    >>> test_final_multiple_inheritance()
    start
    init
    del
    finish
    """
    print("start")
    d = FinalMultipleInheritance()
    d = None
    gc.collect()
    print("finish")

cdef class del_with_exception:
    def __init__(self):
        print("init")

    def __del__(self):
        print("del")
        raise Exception("Error")

def test_del_with_exception():
    """
    >>> test_del_with_exception()
    start
    init
    del
    finish
    """
    print("start")
    d = nontrivial_del()
    d = None
    gc.collect()
    print("finish")


def test_nontrivial_del_with_exception():
    """
    >>> test_nontrivial_del_with_exception()
    start
    init
    del
    end
    """
    print("start")
    def inner():
        c = nontrivial_del()
        raise RuntimeError()

    try:
        inner()
    except RuntimeError:
        pass

    print("end")


cdef class parent:
    def __del__(self):
        print("del parent")

class child(parent):
    def __del__(self):
        print("del child")

def test_del_inheritance():
    """
    >>> test_del_inheritance()
    start
    del child
    finish
    """
    print("start")
    c = child()
    c = None
    gc.collect()
    print("finish")


cdef class cy_parent:
    def __del__(self):
        print("del cy_parent")

    def __dealloc__(self):
        print("dealloc cy_parent")

class py_parent:
    def __del__(self):
        print("del py_parent")

class multi_child(cy_parent, py_parent):
    def __del__(self):
        print("del child")

def test_multiple_inheritance():
    """
    >>> test_multiple_inheritance()
    start
    del child
    dealloc cy_parent
    finish
    """
    print("start")
    c = multi_child()
    c = None
    gc.collect()
    print("finish")


cdef class zombie_object:
    def __del__(self):
        global global_zombie_object
        print("del")
        global_zombie_object = self

    def __dealloc__(self):
        print("dealloc")

def test_zombie_object():
    """
    >>> test_zombie_object()
    start
    del
    del global
    del
    finish
    """
    global global_zombie_object
    print("start")
    i = zombie_object()
    i = None
    print("del global")
    del global_zombie_object
    gc.collect()
    print("finish")


# Same as above, but the member
# makes the class GC, so it
# is deallocated
cdef class gc_zombie_object:
    cdef object x

    def __del__(self):
        global global_gc_zombie_object
        print("del")
        global_gc_zombie_object = self

    def __dealloc__(self):
        print("dealloc")

def test_gc_zombie_object():
    """
    >>> test_gc_zombie_object()
    start
    del
    del global
    dealloc
    finish
    """
    global global_gc_zombie_object
    print("start")
    i = gc_zombie_object()
    i = None
    print("del global")
    del global_gc_zombie_object
    gc.collect()
    print("finish")


cdef class cdef_parent:
    pass

cdef class cdef_child(cdef_parent):
    def __del__(self):
        print("del")
    def __dealloc__(self):
        print("dealloc")

def test_cdef_parent_object():
    """
    >>> test_cdef_parent_object()
    start
    del
    dealloc
    finish
    """
    print("start")
    i = cdef_child()
    i = None
    gc.collect()
    print("finish")


cdef class cdef_nontrivial_parent:
    def __del__(self):
        print("del parent")
    def __dealloc__(self):
        print("dealloc parent")

cdef class cdef_nontrivial_child(cdef_nontrivial_parent):
    def __del__(self):
        print("del child")
    def __dealloc__(self):
        print("dealloc child")

def test_cdef_nontrivial_parent_object():
    """
    >>> test_cdef_nontrivial_parent_object()
    start
    del child
    dealloc child
    dealloc parent
    finish
    """
    print("start")
    i = cdef_nontrivial_child()
    i = None
    gc.collect()
    print("finish")


class python_child(cdef_nontrivial_parent):
    def __del__(self):
        print("del python child")
        super().__del__()

def test_python_child_object():
    """
    >>> test_python_child_object()
    Traceback (most recent call last):
    ...
    RuntimeError: End function
    """

    def func(tp):
        inst = tp()
        raise RuntimeError("End function")

    func(python_child)

def test_python_child_fancy_inherit():
    """
    >>> test_python_child_fancy_inherit()
    Traceback (most recent call last):
    ...
    RuntimeError: End function
    """

    # inherit using "true python" rather than Cython
    globs = { 'cdef_nontrivial_parent': cdef_nontrivial_parent }

    exec("""
class derived_python_child(cdef_nontrivial_parent):
    pass
""", globs)

    derived_python_child = globs['derived_python_child']

    def func(tp):
        inst = tp()
        raise RuntimeError("End function")

    func(derived_python_child)

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/pep442_tp_finalize_cimport.srctree0000644000175100001770000000233400000000000024274 0ustar00runnerdocker00000000000000"""
PYTHON setup.py build_ext -i
PYTHON runtests.py
"""

####### runtests.py #######

import gc
from testclasses import *
import baseclasses

def test_has_del():
    inst = HasIndirectDel()
    inst = None
    gc.collect()
    assert baseclasses.HasDel_del_called_count
    
def test_no_del():
    inst = NoIndirectDel()
    inst = None
    gc.collect()
    # The test here is that it doesn't crash
    
test_has_del()
test_no_del()

######## setup.py ########

from setuptools import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize('*.pyx'))

####### baseclasses.pxd ######

cdef class HasDel:
    pass
    
cdef class DoesntHaveDel:
    pass
    
####### baseclasses.pyx ######

HasDel_del_called_count = 0

cdef class HasDel:
    def __del__(self):
        global HasDel_del_called_count
        HasDel_del_called_count += 1
        
cdef class DoesntHaveDel:
    pass

######## testclasses.pyx ######

cimport cython
from baseclasses cimport HasDel, DoesntHaveDel

@cython.final
cdef class HasIndirectDel(HasDel):
    pass

@cython.final
cdef class NoIndirectDel(DoesntHaveDel):
    # But Cython can't tell that we don't have __del__ until runtime,
    # so has to generate code to call it (and not crash!)
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/pep448_extended_unpacking.pyx0000644000175100001770000003216500000000000023256 0ustar00runnerdocker00000000000000# mode: run
# tag: all_language_levels

cimport cython


class Iter(object):
    def __init__(self, it=()):
        self.it = iter(it)
    def __iter__(self):
        return self
    def __next__(self):
        return next(self.it)
    next = __next__


class Map(object):
    def __init__(self, mapping={}):
        self.mapping = mapping
    def __iter__(self):
        return iter(self.mapping)
    def keys(self):
        return self.mapping.keys()
    def __getitem__(self, key):
        return self.mapping[key]


#### tuples


@cython.test_fail_if_path_exists(
    "//TupleNode//TupleNode",
    "//MergedSequenceNode",
)
def unpack_tuple_literal():
    """
    >>> unpack_tuple_literal()
    (1, 2, 4, 5)
    """
    return (*(1, 2, *(4, 5)),)


def unpack_tuple_literal_mult():
    """
    >>> unpack_tuple_literal_mult()
    (1, 2, 4, 5, 4, 5, 1, 2, 4, 5, 4, 5, 1, 2, 4, 5, 4, 5)
    """
    return (*((1, 2, *((4, 5) * 2)) * 3),)


@cython.test_fail_if_path_exists(
    "//TupleNode//TupleNode",
    "//MergedSequenceNode",
)
def unpack_tuple_literal_empty():
    """
    >>> unpack_tuple_literal_empty()
    ()
    """
    return (*(*(), *()), *(), *(*(*(),),))


def unpack_tuple_simple(it):
    """
    >>> unpack_tuple_simple([])
    ()
    >>> unpack_tuple_simple(set())
    ()
    >>> unpack_tuple_simple(Iter())
    ()

    >>> unpack_tuple_simple([1])
    (1,)

    >>> unpack_tuple_simple([2, 1])
    (2, 1)
    >>> unpack_tuple_simple((2, 1))
    (2, 1)
    >>> sorted(unpack_tuple_simple(set([2, 1])))
    [1, 2]
    >>> unpack_tuple_simple(Iter([2, 1]))
    (2, 1)
    """
    return (*it,)


def unpack_tuple_from_iterable(it):
    """
    >>> unpack_tuple_from_iterable([1, 2, 3])
    (1, 2, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 1, 1, 2, 3)
    >>> unpack_tuple_from_iterable((1, 2, 3))
    (1, 2, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 1, 1, 2, 3)
    >>> sorted(unpack_tuple_from_iterable(set([1, 2, 3])))
    [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]

    >>> unpack_tuple_from_iterable([1, 2])
    (1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 1, 2)
    >>> sorted(unpack_tuple_from_iterable(set([1, 2])))
    [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2]
    >>> unpack_tuple_from_iterable(Iter([1, 2]))
    (1, 2, 1, 2, 1, 2, 1)

    >>> unpack_tuple_from_iterable([3])
    (1, 2, 3, 1, 3, 3, 3, 2, 1, 3)
    >>> unpack_tuple_from_iterable(set([3]))
    (1, 2, 3, 1, 3, 3, 3, 2, 1, 3)
    >>> unpack_tuple_from_iterable(Iter([3]))
    (1, 2, 3, 1, 2, 1)

    >>> unpack_tuple_from_iterable([])
    (1, 2, 1, 2, 1)
    >>> unpack_tuple_from_iterable(set([]))
    (1, 2, 1, 2, 1)
    >>> unpack_tuple_from_iterable([])
    (1, 2, 1, 2, 1)
    >>> unpack_tuple_from_iterable(Iter([1, 2, 3]))
    (1, 2, 1, 2, 3, 1, 2, 1)
    """
    return (1, 2, *it, 1, *(*it, *it), *it, 2, 1, *it)


def unpack_tuple_keep_originals(a, b, c):
    """
    >>> a = b = [1, 2]
    >>> c = [3, 4]
    >>> unpack_tuple_keep_originals(a, b, c)
    (1, 2, 1, 2, 2, 3, 4)
    >>> a
    [1, 2]
    >>> b
    [1, 2]
    >>> c
    [3, 4]

    >>> a = b = (1, 2)
    >>> c = (3, 4)
    >>> unpack_tuple_keep_originals(a, b, c)
    (1, 2, 1, 2, 2, 3, 4)
    >>> a
    (1, 2)
    >>> b
    (1, 2)
    >>> c
    (3, 4)
    """
    return (*a, *b, 2, *c)


def unpack_tuple_in_string_formatting(a, *args):
    """
    >>> print(unpack_tuple_in_string_formatting(1, 2))
    1 2
    >>> print(unpack_tuple_in_string_formatting(1, 'x'))
    1 'x'
    >>> unpack_tuple_in_string_formatting(1)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...format...
    >>> unpack_tuple_in_string_formatting(1, 2, 3)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...format...
    """
    return "%s %r" % (a, *args)


#### lists


@cython.test_fail_if_path_exists(
    "//ListNode//ListNode",
    "//MergedSequenceNode",
)
def unpack_list_literal():
    """
    >>> unpack_list_literal()
    [1, 2, 4, 5]
    """
    return [*[1, 2, *[4, 5]]]


def unpack_list_literal_mult():
    """
    >>> unpack_list_literal_mult()
    [1, 2, 4, 5, 4, 5, 1, 2, 4, 5, 4, 5, 1, 2, 4, 5, 4, 5]
    """
    return [*([1, 2, *([4, 5] * 2)] * 3)]


def unpack_list_tuple_mult():
    """
    >>> unpack_list_tuple_mult()
    [1, 1]
    """
    return [*(1,) * 2]


def unpack_list_tuple_bad_mult():
    """
    >>> unpack_list_tuple_bad_mult()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: ... 'float'
    """
    return [*(1,) * 1.5]


@cython.test_fail_if_path_exists(
    "//ListNode//ListNode",
    "//MergedSequenceNode",
)
def unpack_list_literal_empty():
    """
    >>> unpack_list_literal_empty()
    []
    """
    return [*[*[], *[]], *[], *[*[*[]]]]


def unpack_list_simple(it):
    """
    >>> unpack_list_simple([])
    []
    >>> unpack_list_simple(set())
    []
    >>> unpack_list_simple(Iter())
    []

    >>> unpack_list_simple([1])
    [1]

    >>> unpack_list_simple([2, 1])
    [2, 1]
    >>> unpack_list_simple((2, 1))
    [2, 1]
    >>> sorted(unpack_list_simple(set([2, 1])))
    [1, 2]
    >>> unpack_list_simple(Iter([2, 1]))
    [2, 1]
    """
    return [*it]


def unpack_list_from_iterable(it):
    """
    >>> unpack_list_from_iterable([1, 2, 3])
    [1, 2, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 1, 1, 2, 3]
    >>> unpack_list_from_iterable((1, 2, 3))
    [1, 2, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 1, 1, 2, 3]
    >>> sorted(unpack_list_from_iterable(set([1, 2, 3])))
    [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]

    >>> unpack_list_from_iterable([1, 2])
    [1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 1, 2]
    >>> sorted(unpack_list_from_iterable(set([1, 2])))
    [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2]
    >>> unpack_list_from_iterable(Iter([1, 2]))
    [1, 2, 1, 2, 1, 2, 1]

    >>> unpack_list_from_iterable([3])
    [1, 2, 3, 1, 3, 3, 3, 2, 1, 3]
    >>> unpack_list_from_iterable(set([3]))
    [1, 2, 3, 1, 3, 3, 3, 2, 1, 3]
    >>> unpack_list_from_iterable(Iter([3]))
    [1, 2, 3, 1, 2, 1]

    >>> unpack_list_from_iterable([])
    [1, 2, 1, 2, 1]
    >>> unpack_list_from_iterable(set([]))
    [1, 2, 1, 2, 1]
    >>> unpack_list_from_iterable([])
    [1, 2, 1, 2, 1]
    >>> unpack_list_from_iterable(Iter([1, 2, 3]))
    [1, 2, 1, 2, 3, 1, 2, 1]
    """
    return [1, 2, *it, 1, *[*it, *it], *it, 2, 1, *it]


def unpack_list_keep_originals(a, b, c):
    """
    >>> a = b = [1, 2]
    >>> c = [3, 4]
    >>> unpack_list_keep_originals(a, b, c)
    [1, 2, 1, 2, 2, 3, 4]
    >>> a
    [1, 2]
    >>> b
    [1, 2]
    >>> c
    [3, 4]
    """
    return [*a, *b, 2, *c]


def unpack_starred_arg_for_in_operator(x, l, m):
    """
    >>> l = [1,2,3]
    >>> m = [4,5,6]
    >>> x = 1
    >>> unpack_starred_arg_for_in_operator(x, l, m)
    True
    >>> x = 10
    >>> unpack_starred_arg_for_in_operator(x, l, m)
    False
    >>> unpack_starred_arg_for_in_operator(x, l, [])
    False
    >>> unpack_starred_arg_for_in_operator(x, [], [])
    False
    """
    return x in [*l, *m]


###### sets


@cython.test_fail_if_path_exists(
    "//SetNode//SetNode",
    "//MergedSequenceNode",
)
def unpack_set_literal():
    """
    >>> s = unpack_set_literal()
    >>> s == set([1, 2, 4, 5]) or s
    True
    """
    return {*{1, 2, *{4, 5}}}


def unpack_set_simple(it):
    """
    >>> s = unpack_set_simple([])
    >>> s == set([]) or s
    True

    >>> s = unpack_set_simple(set())
    >>> s == set([]) or s
    True

    >>> s = unpack_set_simple(Iter())
    >>> s == set([]) or s
    True

    >>> s = unpack_set_simple([1])
    >>> s == set([1]) or s
    True

    >>> s = unpack_set_simple([2, 1])
    >>> s == set([1, 2]) or s
    True

    >>> s = unpack_set_simple((2, 1))
    >>> s == set([1, 2]) or s
    True

    >>> s = unpack_set_simple(set([2, 1]))
    >>> s == set([1, 2]) or s
    True

    >>> s = unpack_set_simple(Iter([2, 1]))
    >>> s == set([1, 2]) or s
    True
    """
    return {*it}


def unpack_set_from_iterable(it):
    """
    >>> s = unpack_set_from_iterable([1, 2, 3])
    >>> s == set([1, 2, 3]) or s
    True

    >>> s = unpack_set_from_iterable([1, 2])
    >>> s == set([1, 2]) or s
    True

    >>> s = unpack_set_from_iterable(set([1, 2]))
    >>> s == set([1, 2]) or s
    True

    >>> s = unpack_set_from_iterable(Iter([1, 2]))
    >>> s == set([1, 2]) or s
    True

    >>> s = unpack_set_from_iterable([3])
    >>> s == set([1, 2, 3]) or s
    True

    >>> s = unpack_set_from_iterable(set([3]))
    >>> s == set([1, 2, 3]) or s
    True

    >>> s = unpack_set_from_iterable(Iter([3]))
    >>> s == set([1, 2, 3]) or s
    True

    >>> s = unpack_set_from_iterable([])
    >>> s == set([1, 2]) or s
    True

    >>> s = unpack_set_from_iterable(set([]))
    >>> s == set([1, 2]) or s
    True

    >>> s = unpack_set_from_iterable([])
    >>> s == set([1, 2]) or s
    True

    >>> s = unpack_set_from_iterable((1, 2, 3))
    >>> s == set([1, 2, 3]) or s
    True

    >>> s = unpack_set_from_iterable(set([1, 2, 3]))
    >>> s == set([1, 2, 3]) or s
    True

    >>> s = unpack_set_from_iterable(Iter([1, 2, 3]))
    >>> s == set([1, 2, 3]) or s
    True
    """
    return {1, 2, *it, 1, *{*it, *it}, *it, 2, 1, *it, *it}


def unpack_set_keep_originals(a, b, c):
    """
    >>> a = b = set([1, 2])
    >>> c = set([3, 4])
    >>> s = unpack_set_keep_originals(a, b, c)
    >>> s == set([1, 2, 3, 4]) or s
    True
    >>> a == set([1, 2]) or a
    True
    >>> b == set([1, 2]) or b
    True
    >>> c == set([3, 4]) or c
    True
    """
    return {*a, *b, 2, *c}


#### dicts


@cython.test_fail_if_path_exists(
    "//DictNode//DictNode",
    "//MergedDictNode",
)
def unpack_dict_literal():
    """
    >>> d = unpack_dict_literal()
    >>> d == dict(a=1, b=2, c=4, d=5) or d
    True
    """
    return {**{'a': 1, 'b': 2, **{'c': 4, 'd': 5}}}


@cython.test_fail_if_path_exists(
    "//DictNode//DictNode",
    "//MergedDictNode",
)
def unpack_dict_literal_empty():
    """
    >>> unpack_dict_literal_empty()
    {}
    """
    return {**{**{}, **{}}, **{}, **{**{**{}}}}


def unpack_dict_simple(it):
    """
    >>> d = unpack_dict_simple({})
    >>> d == {} or d
    True

    >>> d = unpack_dict_simple([])
    >>> d == {} or d
    True

    >>> d = unpack_dict_simple(set())
    >>> d == {} or d
    True

    >>> d = unpack_dict_simple(Iter())
    >>> d == {} or d
    True

    >>> d = unpack_dict_simple(Map())
    >>> d == {} or d
    True

    >>> d = unpack_dict_simple(dict(a=1))
    >>> d == dict(a=1) or d
    True

    >>> d = unpack_dict_simple(dict(a=1, b=2))
    >>> d == dict(a=1, b=2) or d
    True

    >>> d = unpack_dict_simple(Map(dict(a=1, b=2)))
    >>> d == dict(a=1, b=2) or d
    True
    """
    return {**it}


@cython.test_assert_path_exists('//MergedDictNode')
@cython.test_fail_if_path_exists(
    '//MergedDictNode//MergedDictNode',
)
def unpack_dict_from_iterable(it):
    """
    >>> d = unpack_dict_from_iterable(dict(a=1, b=2, c=3))
    >>> d == dict(a=1, b=2, c=3) or d
    True

    >>> d = unpack_dict_from_iterable(dict(a=1, b=2))
    >>> d == dict(a=1, b=2) or d
    True

    >>> d = unpack_dict_from_iterable(Map(dict(a=1, b=2)))
    >>> d == dict(a=1, b=2) or d
    True

    >>> d = unpack_dict_from_iterable(dict(a=3))
    >>> d == dict(a=3, b=5) or d
    True

    >>> d = unpack_dict_from_iterable(Map(dict(a=3)))
    >>> d == dict(a=3, b=5) or d
    True

    >>> d = unpack_dict_from_iterable({})
    >>> d == dict(a=4, b=5) or d
    True

    >>> d = unpack_dict_from_iterable(Map())
    >>> d == dict(a=4, b=5) or d
    True

    >>> d = unpack_dict_from_iterable(Iter())
    Traceback (most recent call last):
    TypeError: 'Iter' object is not a mapping

    >>> d = unpack_dict_from_iterable([])
    Traceback (most recent call last):
    TypeError: 'list' object is not a mapping

    >>> d = unpack_dict_from_iterable(dict(b=2, c=3))
    >>> d == dict(a=4, b=2, c=3) or d
    True

    >>> d = unpack_dict_from_iterable(Map(dict(b=2, c=3)))
    >>> d == dict(a=4, b=2, c=3) or d
    True

    >>> d = unpack_dict_from_iterable(dict(a=2, c=3))
    >>> d == dict(a=2, b=5, c=3) or d
    True

    >>> d = unpack_dict_from_iterable(Map(dict(a=2, c=3)))
    >>> d == dict(a=2, b=5, c=3) or d
    True
    """
    return {'a': 2, 'b': 3, **it, 'a': 1, **{**it, **it}, **it, 'a': 4, 'b': 5, **it, **it}


def unpack_dict_keep_originals(a, b, c):
    """
    >>> a = b = {1: 2}
    >>> c = {2: 3, 4: 5}
    >>> d = unpack_dict_keep_originals(a, b, c)
    >>> d == {1: 2, 2: 3, 4: 5} or d
    True
    >>> a
    {1: 2}
    >>> b
    {1: 2}
    >>> c == {2: 3, 4: 5} or c
    True
    """
    return {**a, **b, 2: 4, **c}


@cython.test_assert_path_exists(
    '//MergedDictNode',
    '//MergedDictNode//MergedDictNode',
    '//MergedDictNode//MergedDictNode//DictNode',
)
def unpack_in_call(f):
    """
    >>> def f(a=1, test=2, **kwargs):
    ...     return a, test, sorted(kwargs.items())
    >>> wrapped = unpack_in_call(f)
    >>> wrapped(1)
    (1, 1, [('more', 2)])
    >>> wrapped(test='overwritten')
    (1, 1, [('more', 2)])
    >>> wrapped(b=3)
    (1, 1, [('b', 3), ('more', 2)])
    >>> wrapped(more=4)
    Traceback (most recent call last):
    TypeError: function() got multiple values for keyword argument 'more'
    """
    def wrapper(*args, **kwargs):
        return f(*args, more=2, **{**kwargs, 'test': 1})
    return wrapper
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/pep448_test_extcall.pyx0000644000175100001770000003000300000000000022077 0ustar00runnerdocker00000000000000# mode: run
# tag: pep448

from __future__ import print_function

import sys

IS_PY3 = sys.version_info[0] >= 3

if IS_PY3:
    __doc__ = """
>>> def f(*, w): pass
>>> try: errors_call_no_args(f)
... except TypeError: pass
... else: print("FAILED!")

>>> def f(*, a, b, c, d, e): pass
>>> try: errors_call_no_args(f)
... except TypeError: pass
... else: print("FAILED!")

>>> def f(*, kw, b): pass
>>> try: errors_call_3args_2kwargs(f)
... except TypeError: pass
... else: print("FAILED!")

>>> def f(a, b=2, *, kw): pass
>>> try: errors_call_3args_1kwarg(f)
... except TypeError: pass
... else: print("FAILED!")

>>> def f(*, kw): pass
>>> try: errors_call_1arg_1kwarg(f)
... except TypeError: pass
... else: print("FAILED!")
"""

# test for method/function calls. adapted from CPython's "test_extcall.py".

def sortdict(d):
    return '{%s}' % ', '.join(['%r: %r' % item for item in sorted(d.items())])

# We're going the use these types for extra testing

try:
    from collections import UserList, UserDict
except ImportError:
    from UserList import UserList
    from UserDict import UserDict


# We're defining four helper functions

def e(a,b):
    print(a, b)

def f(*a, **k):
    print(a, sortdict(k))

def g(x, *y, **z):
    print(x, y, sortdict(z))

def h(j=1, a=2, h=3):
    print(j, a, h)


# Argument list examples

def call_f_positional():
    """
    >>> call_f_positional()
    () {}
    (1,) {}
    (1, 2) {}
    (1, 2, 3) {}
    (1, 2, 3, 4, 5) {}
    (1, 2, 3, 4, 5) {}
    (1, 2, 3, 4, 5) {}
    (1, 2, 3, 4, 5) {}
    (1, 2, 3, 4, 5, 6, 7) {}
    (1, 2, 3, 4, 5, 6, 7) {}
    (1, 2, 3, 4, 5, 6, 7) {}
    (1, 2) {}
    """
    f()
    f(1)
    f(1, 2)
    f(1, 2, 3)
    f(1, 2, 3, *(4, 5))
    f(1, 2, 3, *[4, 5])
    f(*[1, 2, 3], 4, 5)
    f(1, 2, 3, *UserList([4, 5]))
    f(1, 2, 3, *[4, 5], *[6, 7])
    f(1, *[2, 3], 4, *[5, 6], 7)
    f(*UserList([1, 2]), *UserList([3, 4]), 5, *UserList([6, 7]))
    f(1, *[] or () and {}, *() and [], *{} or [] and (), *{} and [] or (), 2)


# Here we add keyword arguments

def call_f_kwargs():
    """
    >>> call_f_kwargs()
    (1, 2, 3) {'a': 4, 'b': 5}
    (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
    (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
    (1, 2, 3, 4, 5) {'a': 6, 'b': 7, 'c': 8}
    (1, 2, 3, 4, 5) {'a': 8, 'b': 9, 'x': 6, 'y': 7}
    (1, 2, 3) {'a': 4, 'b': 5}
    (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
    (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
    (1, 2, 3, 4, 5) {'a': 8, 'b': 9, 'x': 6, 'y': 7}
    (1, 2) {'a': 3}
    """

    f(1, 2, 3, **{'a':4, 'b':5})
    f(1, 2, 3, *[4, 5], **{'a':6, 'b':7})
    f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b': 9})
    f(1, 2, 3, *[4, 5], **{'c': 8}, **{'a':6, 'b':7})
    f(1, 2, 3, *(4, 5), x=6, y=7, **{'a':8, 'b': 9})

    f(1, 2, 3, **UserDict(a=4, b=5))
    f(1, 2, 3, *(4, 5), **UserDict(a=6, b=7))
    f(1, 2, 3, x=4, y=5, *(6, 7), **UserDict(a=8, b=9))
    f(1, 2, 3, *(4, 5), x=6, y=7, **UserDict(a=8, b=9))

    f(1, *[] or () and {}, *() and [], *{} or [] and (), *{} and [] or (), 2,
      **{} and {} or {}, **{} or {} and {}, **{} and {}, a=3)


# Examples with invalid arguments (TypeErrors). We're also testing the function
# names in the exception messages.
#
# Verify clearing of SF bug #733667

def errors_f1():
    """
    >>> errors_f1()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    TypeError: ...got multiple values for keyword argument 'a'
    """
    f(1, 2, **{'a': -1, 'b': 5}, **{'a': 4, 'c': 6})


def errors_f2():
    """
    >>> errors_f2()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    TypeError: ...multiple values for keyword argument 'a'
    """
    f(1, 2, **{'a': -1, 'b': 5}, a=4, c=6)


def errors_e1():
    """
    >>> try: errors_e1()
    ... except TypeError: pass
    ... else: print("FAILED!")
    """
    e(c=4)


def errors_e2():
    """
    >>> try: errors_e2()
    ... except TypeError: pass
    ... else: print("FAILED!")
    """
    e(a=1, b=2, c=4)


def errors_g1():
    """
    >>> errors_g1()
    Traceback (most recent call last):
      ...
    TypeError: g() takes at least 1 positional argument (0 given)

    # TypeError: g() missing 1 required positional argument: 'x'
    """
    g()


def errors_g2():
    """
    >>> errors_g2()
    Traceback (most recent call last):
      ...
    TypeError: g() takes at least 1 positional argument (0 given)

    # TypeError: g() missing 1 required positional argument: 'x'
    """
    g(*())


def errors_g3():
    """
    >>> errors_g3()
    Traceback (most recent call last):
      ...
    TypeError: g() takes at least 1 positional argument (0 given)

    # TypeError: g() missing 1 required positional argument: 'x'
    """
    g(*(), **{})


def call_g_positional():
    """
    >>> call_g_positional()
    1 () {}
    1 (2,) {}
    1 (2, 3) {}
    1 (2, 3, 4, 5) {}
    """
    g(1)
    g(1, 2)
    g(1, 2, 3)
    g(1, 2, 3, *(4, 5))



def call_nonseq_positional1():
    """
    >>> call_nonseq_positional1()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
      ...
    TypeError: ...Nothing...

    # TypeError: g() argument after * must be a sequence, not Nothing
    """
    class Nothing(object): pass
    g(*Nothing())


def call_nonseq_positional2():
    """
    >>> call_nonseq_positional2()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
      ...
    TypeError: ...Nothing...

    # TypeError: g() argument after * must be a sequence, not Nothing
    """
    class Nothing(object):
        def __len__(self): return 5
    g(*Nothing())


def call_seqlike_positional1():
    """
    >>> call_seqlike_positional1()
    0 (1, 2) {}
    """
    class Nothing(object):
        def __len__(self): return 5
        def __getitem__(self, i):
            if i<3: return i
            else: raise IndexError(i)

    g(*Nothing())


def call_seqlike_positional2():
    """
    >>> call_seqlike_positional2()
    0 (1, 2, 3) {}
    """
    class Nothing:
        def __init__(self): self.c = 0
        def __iter__(self): return self
        def __next__(self):
            if self.c == 4:
                raise StopIteration
            c = self.c
            self.c += 1
            return c
        next = __next__

    g(*Nothing())


# Make sure that the function doesn't stomp the dictionary

def call_kwargs_unmodified1():
    """
    >>> call_kwargs_unmodified1()
    1 () {'a': 1, 'b': 2, 'c': 3, 'd': 4}
    True
    """
    d = {'a': 1, 'b': 2, 'c': 3}
    d2 = d.copy()
    g(1, d=4, **d)
    return d == d2


# What about willful misconduct?

def call_kwargs_unmodified2():
    """
    >>> call_kwargs_unmodified2()
    {}
    """
    def saboteur(**kw):
        kw['x'] = 'm'
        return kw

    d = {}
    kw = saboteur(a=1, **d)
    return d


def errors_args_kwargs_overlap():
    """
    >>> errors_args_kwargs_overlap()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
      ...
    TypeError: ...got multiple values for... argument 'x'
    """
    g(1, 2, 3, **{'x': 4, 'y': 5})


def errors_non_string_kwarg():
    """
    >>> errors_non_string_kwarg()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...keywords must be strings...
    """
    f(**{1:2})


def errors_unexpected_kwarg():
    """
    >>> errors_unexpected_kwarg()
    Traceback (most recent call last):
      ...
    TypeError: h() got an unexpected keyword argument 'e'
    """
    h(**{'e': 2})


def errors_call_nonseq():
    """
    >>> try: errors_call_nonseq()
    ... except TypeError: pass
    ... else: print("FAILED!")
    """
    h(*h)


def errors_call_builtin_nonseq():
    """
    >>> try: errors_call_builtin_nonseq()
    ... except TypeError: pass
    ... else: print("FAILED!")
    """
    dir(*h)


def errors_call_none_nonseq():
    """
    >>> try: errors_call_none_nonseq()
    ... except TypeError: pass
    ... else: print("FAILED!")
    """
    None(*h)


def errors_call_nonmapping_kwargs():
    """
    >>> try: errors_call_nonmapping_kwargs()
    ... except TypeError: pass
    ... else: print("FAILED!")
    """
    h(**h)


def errors_call_builtin_nonmapping_kwargs():
    """
    >>> try: errors_call_builtin_nonmapping_kwargs()
    ... except TypeError: pass
    ... else: print("FAILED!")
    """
    dir(**h)


def errors_call_none_nonmapping_kwargs():
    """
    >>> try: errors_call_none_nonmapping_kwargs()
    ... except TypeError: pass
    ... else: print("FAILED!")
    """
    None(**h)


'''  # compile time error in Cython
def errors_call_builtin_duplicate_kwarg():
    """
    >>> errors_call_builtin_duplicate_kwarg()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
      ...
    TypeError: ...got multiple values for keyword argument 'b'
    """
    dir(b=1, **{'b': 1})
'''


# Another helper function

def f2(*a, **b):
    return a, b


def call_many_kwargs():
    """
    call_many_kwargs()
    (3, 512, True)
    """
    d = {}
    for i in range(512):
        key = 'k%d' % i
        d[key] = i
    a, b = f2(1, *(2,3), **d)
    return len(a), len(b), b == d


def call_method(Foo):
    """
    >>> class Foo(object):
    ...     def method(self, arg1, arg2):
    ...         print(arg1+arg2)

    >>> call_method(Foo)
    3
    3
    5
    5
    """
    x = Foo()
    Foo.method(*(x, 1, 2))
    Foo.method(x, *(1, 2))
    if sys.version_info[0] >= 3:
        Foo.method(*(1, 2, 3))
        Foo.method(1, *[2, 3])
    else:
        print(5)
        print(5)


# A PyCFunction that takes only positional parameters should allow an
# empty keyword dictionary to pass without a complaint, but raise a
# TypeError if the dictionary is not empty

def call_builtin_empty_dict():
    """
    >>> call_builtin_empty_dict()
    """
    silence = id(1, *{})
    silence = id(1, **{})


def call_builtin_nonempty_dict():
    """
    >>> call_builtin_nonempty_dict() # doctest: +ELLIPSIS
    Traceback (most recent call last):
      ...
    TypeError: id() ... keyword argument...
    """
    return id(1, **{'foo': 1})


''' Cython: currently just passes empty kwargs into f() while CPython keeps the content

# A corner case of keyword dictionary items being deleted during
# the function call setup. See .

def call_kwargs_modified_while_building():
    """
    >>> call_kwargs_modified_while_building()
    1 2
    """
    class Name(str):
        def __eq__(self, other):
            try:
                 del x[self]
            except KeyError:
                 pass
            return str.__eq__(self, other)
        def __hash__(self):
            return str.__hash__(self)

    x = {Name("a"):1, Name("b"):2}
    def f(a, b):
        print(a,b)
    f(**x)
'''


# Too many arguments:

def errors_call_one_arg(f):
    """
    >>> def f(): pass
    >>> try: errors_call_one_arg(f)
    ... except TypeError: pass
    ... else: print("FAILED!")
    """
    f(1)

def errors_call_2args(f):
    """
    >>> def f(a): pass
    >>> try: errors_call_2args(f)
    ... except TypeError: pass
    ... else: print("FAILED!")
    """
    f(1, 2)

def errors_call_3args(f):
    """
    >>> def f(a, b=1): pass
    >>> try: errors_call_3args(f)
    ... except TypeError: pass
    ... else: print("FAILED!")
    """
    f(1, 2, 3)


def errors_call_1arg_1kwarg(f):
    # Py3 only
    f(1, kw=3)


def errors_call_3args_2kwargs(f):
    # Py3 only
    f(1, 2, 3, b=3, kw=3)


def errors_call_3args_1kwarg(f):
    # Py3 only
    f(2, 3, 4, kw=4)


# Too few and missing arguments:

def errors_call_no_args(f):
    """
    >>> def f(a): pass
    >>> try: errors_call_no_args(f)
    ... except TypeError: pass
    ... else: print("FAILED!")

    >>> def f(a, b): pass
    >>> try: errors_call_no_args(f)
    ... except TypeError: pass
    ... else: print("FAILED!")

    >>> def f(a, b, c): pass
    >>> try: errors_call_no_args(f)
    ... except TypeError: pass
    ... else: print("FAILED!")

    >>> def f(a, b, c, d, e): pass
    >>> try: errors_call_no_args(f)
    ... except TypeError: pass
    ... else: print("FAILED!")
    """
    f()


def errors_call_one_missing_kwarg(f):
    """
    >>> def f(a, b=4, c=5, d=5): pass
    >>> try: errors_call_one_missing_kwarg(f)
    ... except TypeError: pass
    ... else: print("FAILED!")
    """
    f(c=12, b=9)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/pep526_variable_annotations.py0000644000175100001770000002412400000000000023422 0ustar00runnerdocker00000000000000# cython: language_level=3
# mode: run
# tag: pure3.7, pep526, pep484, warnings

# for the benefit of the pure tests, don't require annotations
# to be evaluated
from __future__ import annotations

import cython

# Don't add FrozenSet to this list - it's necessary for one of the tests
# that it isn't a module global name
from typing import Dict, List, TypeVar, Optional, Generic, Tuple

try:
    import typing
    from typing import Set as _SET_
    from typing import ClassVar
except ImportError:
    pass  # this should allow Cython to interpret the directives even when the module doesn't exist


var = 1  # type: annotation
var: cython.int = 2
fvar: cython.float = 1.2
some_number: cython.int    # variable without initial value
some_list: List[cython.int] = []  # variable with initial value
another_list: list[cython.int] = []
t: Tuple[cython.int, ...] = (1, 2, 3)
t2: tuple[cython.int, ...]
body: Optional[List[str]]
descr_only : "descriptions are allowed but ignored"


some_number = 5
body = None


def f():
    """
    >>> f()
    (2, 1.5, [], (1, 2, 3))
    """
    var = 1  # type: annotation
    var: cython.int = 2
    fvar: cython.float = 1.5
    some_number: cython.int    # variable without initial value
    some_list: List[cython.int] = []  # variable with initial value
    t: Tuple[cython.int, ...] = (1, 2, 3)
    body: Optional[List[str]]
    descr_only: "descriptions are allowed but ignored"

    return var, fvar, some_list, t


class BasicStarship(object):
    """
    >>> bs = BasicStarship(5)
    >>> bs.damage
    5
    >>> bs.captain
    'Picard'
    >>> bs.stats
    {}
    >>> BasicStarship.stats
    {}
    """
    captain: str = 'Picard'               # instance variable with default
    damage: cython.int                    # instance variable without default
    stats: ClassVar[Dict[str, cython.int]] = {}  # class variable
    descr_only: "descriptions are allowed but ignored"

    def __init__(self, damage):
        self.damage = damage


@cython.cclass
class BasicStarshipExt(object):
    """
    >>> bs = BasicStarshipExt(5)
    >>> bs.test()
    (5, 'Picard', {})
    """
    captain: str = 'Picard'               # instance variable with default
    damage: cython.int                    # instance variable without default
    stats: ClassVar[Dict[str, cython.int]] = {}  # class variable
    descr_only: "descriptions are allowed but ignored"

    def __init__(self, damage):
        self.damage = damage

    def test(self):
        return self.damage, self.captain, self.stats


T = TypeVar('T')


# FIXME: this fails in Py3.7 now
#class Box(Generic[T]):
#    def __init__(self, content):
#        self.content: T = content
#
#box = Box(content=5)


class Cls(object):
    pass


c = Cls()
c.x: int = 0  # Annotates c.x with int.
c.y: int      # Annotates c.y with int.

d = {}
d['a']: int = 0  # Annotates d['a'] with int.
d['b']: int      # Annotates d['b'] with int.

(x): int      # Annotates x with int, (x) treated as expression by compiler.
(y): int = 0  # Same situation here.


@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode",
)
def iter_declared_dict(d):
    """
    >>> d = {1.1: 2.5, 3.3: 4.5}
    >>> iter_declared_dict(d)
    7.0

    # specialized "compiled" test in module-level __doc__
    """
    typed_dict : Dict[cython.float, cython.float] = d
    s = 0.0
    for key in typed_dict:
        s += d[key]
    return s


@cython.test_assert_path_exists(
    "//WhileStatNode",
    "//WhileStatNode//DictIterationNextNode",
)
def iter_declared_dict_arg(d : Dict[cython.float, cython.float]):
    """
    >>> d = {1.1: 2.5, 3.3: 4.5}
    >>> iter_declared_dict_arg(d)
    7.0

    # module level "compiled" test in __doc__ below
    """
    s = 0.0
    for key in d:
        s += d[key]
    return s


def literal_list_ptr():
    """
    >>> literal_list_ptr()
    4
    """
    a : cython.p_int = [1, 2, 3, 4, 5]
    return a[3]


def test_subscripted_types():
    """
    >>> test_subscripted_types()
    dict object
    dict object
    list object
    list object
    list object
    set object
    """
    a1: typing.Dict[cython.int, cython.float] = {}
    a2: dict[cython.int, cython.float] = {}
    b1: List[cython.int] = []
    b2: list[cython.int] = []
    b3: List = []  # doesn't need to be subscripted
    c: _SET_[object] = set()

    print(cython.typeof(a1) + (" object" if not cython.compiled else ""))
    print(cython.typeof(a2) + (" object" if not cython.compiled else ""))
    print(cython.typeof(b1) + (" object" if not cython.compiled else ""))
    print(cython.typeof(b2) + (" object" if not cython.compiled else ""))
    print(cython.typeof(b3) + (" object" if not cython.compiled else ""))
    print(cython.typeof(c) + (" object" if not cython.compiled else ""))

# because tuple is specifically special cased to go to ctuple where possible
def test_tuple(a: typing.Tuple[cython.int, cython.float], b: typing.Tuple[cython.int, ...],
               c: Tuple[cython.int, object]  # cannot be a ctuple
               ):
    """
    >>> test_tuple((1, 1.0), (1, 1.0), (1, 1.0))
    int
    int
    float
    Python object
    (int, float)
    tuple object
    tuple object
    tuple object
    tuple object
    """
    x: typing.Tuple[int, float] = (a[0], a[1])  # note: Python int/float, not cython.int/float
    y: Tuple[cython.int, ...] = (1,2.)
    plain_tuple: Tuple = ()
    z = a[0]  # should infer to C int
    p = x[1]  # should infer to Python float -> C double

    print(cython.typeof(z))
    print("int" if cython.compiled and cython.typeof(x[0]) == "Python object" else cython.typeof(x[0]))  # FIXME: infer Python int
    if cython.compiled:
        print(cython.typeof(p))
    else:
        print('float' if cython.typeof(p) == 'float' else cython.typeof(p))
    print(cython.typeof(x[1]) if cython.compiled or cython.typeof(p) != 'float' else "Python object")  # FIXME: infer C double
    print(cython.typeof(a) if cython.compiled or cython.typeof(a) != 'tuple' else "(int, float)")
    print(cython.typeof(x) + (" object" if not cython.compiled else ""))
    print(cython.typeof(y) + (" object" if not cython.compiled else ""))
    print(cython.typeof(c) + (" object" if not cython.compiled else ""))
    print(cython.typeof(plain_tuple) + (" object" if not cython.compiled else ""))


# because tuple is specifically special cased to go to ctuple where possible
def test_tuple_without_typing(a: tuple[cython.int, cython.float], b: tuple[cython.int, ...],
               c: tuple[cython.int, object]  # cannot be a ctuple
               ):
    """
    >>> test_tuple_without_typing((1, 1.0), (1, 1.0), (1, 1.0))
    int
    int
    float
    Python object
    (int, float)
    tuple object
    tuple object
    tuple object
    tuple object
    """
    x: tuple[int, float] = (a[0], a[1])  # note: Python int/float, not cython.int/float
    y: tuple[cython.int, ...] = (1,2.)
    plain_tuple: tuple = ()
    z = a[0]  # should infer to C int
    p = x[1]  # should infer to Python float -> C double

    print(cython.typeof(z))
    print("int" if cython.compiled and cython.typeof(x[0]) == "Python object" else cython.typeof(x[0]))  # FIXME: infer Python int
    print(cython.typeof(p) if cython.compiled or cython.typeof(p) != 'float' else "float")  # FIXME: infer C double/PyFloat from Py type
    print(cython.typeof(x[1]) if cython.compiled or cython.typeof(p) != 'float' else "Python object")  # FIXME: infer C double
    print(cython.typeof(a) if cython.compiled or cython.typeof(a) != 'tuple' else "(int, float)")
    print(cython.typeof(x) + (" object" if not cython.compiled else ""))
    print(cython.typeof(y) + (" object" if not cython.compiled else ""))
    print(cython.typeof(c) + (" object" if not cython.compiled else ""))
    print(cython.typeof(plain_tuple) + (" object" if not cython.compiled else ""))


def test_use_typing_attributes_as_non_annotations():
    """
    >>> test_use_typing_attributes_as_non_annotations()
    typing.Tuple typing.Tuple[int]
    typing.Optional True
    typing.Optional True
    """
    x1 = typing.Tuple
    x2 = typing.Tuple[int]
    y1 = typing.Optional
    # It's important for the test that FrozenSet isn't available in the module namespace,
    # since one bug would have looked it up there rather than as an attribute of typing
    y2 = typing.Optional[typing.FrozenSet]
    z1 = Optional
    z2 = Optional[Dict]
    # The result of printing "Optional[type]" is slightly version-dependent
    # so accept both possible forms
    allowed_optional_frozenset_strings = [
        "typing.Union[typing.FrozenSet, NoneType]",
        "typing.Optional[typing.FrozenSet]"
    ]
    allowed_optional_dict_strings = [
        "typing.Union[typing.Dict, NoneType]",
        "typing.Optional[typing.Dict]"
    ]
    print(x1, x2)
    print(y1, str(y2) in allowed_optional_frozenset_strings  or  str(y2))
    print(z1, str(z2) in allowed_optional_dict_strings  or  str(z2))

def test_optional_ctuple(x: typing.Optional[tuple[float]]):
    """
    Should not be a C-tuple (because these can't be optional)
    >>> test_optional_ctuple((1.0,))
    tuple object
    """
    print(cython.typeof(x) + (" object" if not cython.compiled else ""))


try:
    import numpy.typing as npt
    import numpy as np
except ImportError:
    # we can't actually use numpy typing right now, it was just part
    # of a reproducer that caused a compiler crash. We don't need it
    # available to use it in annotations, so don't fail if it's not there
    pass

def list_float_to_numpy(z: List[float]) -> List[npt.NDArray[np.float64]]:
    # since we're not actually requiring numpy, don't make the return type match
    assert cython.typeof(z) == 'list'
    return [z[0]]

if cython.compiled:
    __doc__ = """
    # passing non-dicts to variables declared as dict now fails
    >>> class D(object):
    ...     def __getitem__(self, x): return 2
    ...     def __iter__(self): return iter([1, 2, 3])
    >>> iter_declared_dict(D())  # doctest:+IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    ...
    TypeError: Expected dict, got D
    >>> iter_declared_dict_arg(D())  # doctest:+IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    ...
    TypeError: Expected dict, got D
    """

_WARNINGS = """
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/pep526_variable_annotations_cy.pyx0000644000175100001770000000260500000000000024305 0ustar00runnerdocker00000000000000# mode: run

import cython

try:
    import typing
    from typing import List, Tuple
    from typing import Set as _SET_
except:
    pass  # this should allow Cython to interpret the directives even when the module doesn't exist

def test_subscripted_types():
    """
    >>> test_subscripted_types()
    dict object
    list object
    set object
    """
    cdef typing.Dict[int, float] a = {}
    cdef List[int] b = []
    cdef _SET_[object] c = set()

    print(cython.typeof(a))
    print(cython.typeof(b))
    print(cython.typeof(c))

cdef class TestClassVar:
    """
    >>> TestClassVar.cls
    5
    >>> TestClassVar.regular  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
        ...
    AttributeError:
    """
    cdef int regular
    cdef typing.ClassVar[int] cls
    cls = 5

# because tuple is specifically special cased to go to ctuple where possible
def test_tuple(typing.Tuple[int, float] a,  typing.Tuple[int, ...] b,
               Tuple[int, object] c  # cannot be a ctuple
               ):
    """
    >>> test_tuple((1, 1.0), (1, 1.0), (1, 1.0))
    int
    int
    tuple object
    tuple object
    """
    cdef typing.Tuple[int, float] x = (a[0], a[1])  # C int/float
    cdef Tuple[int, ...] y = (1,2.)
    z = a[0]  # should infer to C int

    print(cython.typeof(z))
    print(cython.typeof(x[0]))
    print(cython.typeof(y))
    print(cython.typeof(c))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/pep557_dataclasses.py0000644000175100001770000000277500000000000021523 0ustar00runnerdocker00000000000000# mode: run
# tag: pep557, pure3.7

import dataclasses
from typing import Sequence


@dataclasses.dataclass
class Color:
    """
    >>> list(Color.__dataclass_fields__.keys())
    ['red', 'green', 'blue', 'alpha']
    >>> Color(1, 2, 3)
    Color(red=1, green=2, blue=3, alpha=255)
    >>> Color(1, 2, 3, 4)
    Color(red=1, green=2, blue=3, alpha=4)
    >>> Color(green=1, blue=2, red=3, alpha=40)
    Color(red=3, green=1, blue=2, alpha=40)
    """
    red: int
    green: int
    blue: int
    alpha: int = 255


@dataclasses.dataclass
class NamedColor(Color):
    """
    >>> list(NamedColor.__dataclass_fields__.keys())
    ['red', 'green', 'blue', 'alpha', 'names']
    >>> NamedColor(1, 2, 3)
    NamedColor(red=1, green=2, blue=3, alpha=255, names=[])
    >>> NamedColor(1, 2, 3, 4)
    NamedColor(red=1, green=2, blue=3, alpha=4, names=[])
    >>> NamedColor(green=1, blue=2, red=3, alpha=40)
    NamedColor(red=3, green=1, blue=2, alpha=40, names=[])
    >>> NamedColor(1, 2, 3, names=["blackish", "very dark cyan"])
    NamedColor(red=1, green=2, blue=3, alpha=255, names=['blackish', 'very dark cyan'])
    """
    names: Sequence[str] = dataclasses.field(default_factory=list)


@dataclasses.dataclass(frozen=True)
class IceCream:
    """
    >>> IceCream("vanilla")
    IceCream(flavour='vanilla', num_toppings=2)
    >>> IceCream("vanilla") == IceCream("vanilla", num_toppings=3)
    False
    >>> IceCream("vanilla") == IceCream("vanilla", num_toppings=2)
    True
    """
    flavour: str
    num_toppings: int = 2
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/pep563_annotations.py0000644000175100001770000000231300000000000021552 0ustar00runnerdocker00000000000000# mode: run
# tag: pep563, pure3.7

from __future__ import annotations

def f(a: 1+2==3, b: list, c: this_cant_evaluate, d: "Hello from inside a string") -> "Return me!":
    """
    The absolute exact strings aren't reproducible according to the PEP,
    so be careful to avoid being too specific
    >>> stypes = (type(""), type(u"")) # Python 2 is a bit awkward here
    >>> eval(f.__annotations__['a'])
    True
    >>> isinstance(f.__annotations__['a'], stypes)
    True
    >>> print(f.__annotations__['b'])
    list
    >>> print(f.__annotations__['c'])
    this_cant_evaluate
    >>> isinstance(eval(f.__annotations__['d']), stypes)
    True
    >>> print(f.__annotations__['return'][1:-1]) # First and last could be either " or '
    Return me!
    >>> f.__annotations__['return'][0] == f.__annotations__['return'][-1]
    True
    """
    pass


def empty_decorator(cls):
    return cls


@empty_decorator
class DecoratedStarship(object):
    """
    >>> sorted(DecoratedStarship.__annotations__.items())
    [('captain', 'str'), ('damage', 'cython.int')]
    """
    captain: str = 'Picard'               # instance variable with default
    damage: cython.int                    # instance variable without default
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/pinard5.pyx0000644000175100001770000000051700000000000017651 0ustar00runnerdocker00000000000000cdef class Tri:
    def test(self):
        return 1

cdef class Curseur:
    cdef Tri tri
    def detail(self):
        return produire_fiches(self.tri)

cdef produire_fiches(Tri tri):
    return tri.test()

def test():
    """
    >>> test()
    1
    """
    cdef Curseur c
    c = Curseur()
    c.tri = Tri()
    return c.detail()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/pinard6.pyx0000644000175100001770000000007200000000000017646 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> x
    (1, 2)
"""

x = 1,
x = 1, 2,
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/pinard7.pyx0000644000175100001770000000051200000000000017646 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> c = build()
    >>> c.method()
    Traceback (most recent call last):
    AssertionError: 1
"""

cdef enum Mode:
    a = 1
    b = 2

cdef class Curseur:
    cdef Mode mode

    def method(self):
        assert False, self.mode

def build():
    cdef Curseur c
    c = Curseur()
    c.mode = a
    return c
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/pinard8.pyx0000644000175100001770000000056200000000000017654 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> f = Fiche()
    >>> f[0] = 1
    >>> f.geti()
    1

    >>> f[1] = None
    >>> f.geti()
    0

    >>> f[0] = 1
    >>> f.geti()
    1
"""

cdef class Fiche:
    cdef int i

    def __setitem__(self, element, valeur):
        self.i = 0
        if valeur is None:
            return
        self.i = 1

    def geti(self):
        return self.i
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/pointers.pyx0000644000175100001770000000350200000000000020147 0ustar00runnerdocker00000000000000cimport cython

cdef char* c_string = b'abcdefg'
cdef void* void_ptr = c_string

cdef int i = 42
cdef int* int_ptr = &i

cdef float x = 42.2
cdef float* float_ptr = &x

def compare():
    """
    >>> compare()
    True
    True
    True
    False
    False
    True
    True
    """
    print c_string == c_string
    print c_string == void_ptr
    print c_string is void_ptr
    print c_string != void_ptr
    print c_string is not void_ptr
    print void_ptr != int_ptr
    print void_ptr != float_ptr

def if_tests():
    """
    >>> if_tests()
    True
    True
    """
    if c_string == void_ptr:
        print True
    if c_string != void_ptr:
        print False
    if int_ptr != void_ptr:
        print True

def bool_binop():
    """
    >>> bool_binop()
    True
    """
    if c_string == void_ptr and c_string == c_string and int_ptr != void_ptr and void_ptr != float_ptr:
        print True

def bool_binop_truth(int x):
    """
    >>> bool_binop_truth(1)
    True
    True
    >>> bool_binop_truth(0)
    True
    """
    if c_string and void_ptr and int_ptr and (c_string == c_string or int_ptr != void_ptr):
        print True
    if c_string and x or not (void_ptr or int_ptr and float_ptr) or x:
        print True


def binop_voidptr(int x, long y, char* z):
    """
    >>> binop_voidptr(1, 3, b'abc')
    'void *'
    """
    result = &x and &y and z
    return cython.typeof(result)


def cond_expr_voidptr(int x, long y, char* z):
    """
    >>> cond_expr_voidptr(0, -1, b'abc')
    ('void *', 0)
    >>> cond_expr_voidptr(-1, 0, b'abc')
    ('void *', -1)
    >>> cond_expr_voidptr(-1, 0, b'')
    ('void *', 0)
    >>> cond_expr_voidptr(0, -1, b'')
    ('void *', -1)
    """
    result = &x if len(z) else &y
    assert sizeof(long) >= sizeof(int)
    assert -1 == (-1L)
    return cython.typeof(result), (result)[0]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/posix_resource.pyx0000644000175100001770000000115000000000000021352 0ustar00runnerdocker00000000000000# tag: posix

from posix.unistd cimport *
from posix.resource cimport *


def test_getpriority():
    """
    >>> test_getpriority()
    0
    """
    ret = getpriority(PRIO_PROCESS, getpid())
    # DISABLED - does not work on current test server
    return 0  # ret


def test_getrlimit():
    """
    >>> test_getrlimit()
    0
    True
    """
    cdef rlimit rlim
    rlim.rlim_cur = 0

    ret = getrlimit(RLIMIT_CPU, &rlim)
    print(ret)
    return rlim.rlim_cur != 0


def test_getrusage():
    """
    >>> test_getrusage()
    0
    """
    cdef rusage r
    ret = getrusage(RUSAGE_SELF, &r)
    return ret
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/posix_test.pyx0000644000175100001770000000477400000000000020521 0ustar00runnerdocker00000000000000# tag: posix
from libc.stdio   cimport *
from posix.unistd cimport *
from posix.fcntl  cimport *


cdef int noisy_function() except -1:
    cdef int ret = 0
    ret = printf(b"012%s6789\n", "345")
    assert ret == 11  # printf()
    ret = printf(b"012%d6789\n", 345)
    assert ret == 11  # printf()
    ret = printf(b"0123456789\n")
    assert ret == 11  # printf()
    ret = fflush(stdout)
    assert ret == 0  # fflush()
    ret = fprintf(stdout, b"012%d6789\n", 345)
    assert ret == 11  # fprintf()
    ret = fflush(stdout)
    assert ret == 0  # fflush()
    ret = write(STDOUT_FILENO, b"0123456789\n", 11)
    assert ret == 11  # write()
    return  0


def test_silent_stdout():
    """
    >>> test_silent_stdout()
    """
    cdef int ret
    cdef int stdout_save, dev_null
    stdout_save = dup(STDOUT_FILENO)
    assert stdout_save != -1
    dev_null = open(b"/dev/null", O_WRONLY, 0)
    assert dev_null != -1
    ret = dup2(dev_null, STDOUT_FILENO)
    assert ret == STDOUT_FILENO
    ret = close(dev_null)
    assert ret == 0
    try:
        noisy_function()
    finally:
        ret = dup2(stdout_save, STDOUT_FILENO)
        assert ret == STDOUT_FILENO
        ret = close(stdout_save)
        assert ret == 0


cdef class silent_fd:
    cdef int fd_save, fd

    def __cinit__(self, int fd=-1):
        self.fd_save = -1
        self.fd = STDOUT_FILENO
        if fd != -1:
            self.fd = fd

    def __enter__(self):
        cdef int ret = 0, dev_null = -1
        assert self.fd_save == -1
        dev_null = open(b"/dev/null", O_WRONLY, 0)
        assert dev_null != -1
        try:
            self.fd_save = dup(self.fd)
            assert self.fd_save != -1
            try:
                ret = dup2(dev_null, self.fd)
                assert ret != -1
            except:
                ret = close(self.fd_save)
                self.fd_save = -1
        finally:
            ret = close(dev_null)

    def __exit__(self, t, v, tb):
        cdef int ret = 0
        if self.fd_save != -1:
            ret = dup2(self.fd_save, self.fd)
            assert ret == self.fd
            ret = close(self.fd_save)
            assert ret == 0
            self.fd_save = -1
        return None


def test_silent_stdout_ctxmanager():
    """
    >> test_silent_stdout_ctxmanager()
    """
    with silent_fd():
        noisy_function()
    try:
        with silent_fd():
            noisy_function()
            raise RuntimeError
    except RuntimeError:
        pass
    with silent_fd(STDOUT_FILENO):
        noisy_function()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/posix_time.pyx0000644000175100001770000000140100000000000020460 0ustar00runnerdocker00000000000000# tag: posix

from posix.time cimport *

def test_itimer(sec, usec):
    """
    >>> test_itimer(10, 2)
    (10, 2)
    """
    cdef itimerval t, gtime

    t.it_interval.tv_sec = sec
    t.it_interval.tv_usec = usec
    t.it_value.tv_sec = sec
    t.it_value.tv_usec = usec
    ret = setitimer(ITIMER_REAL, &t, NULL)
    assert ret == 0
    ret = getitimer(ITIMER_REAL, >ime)
    assert ret == 0
    t.it_interval.tv_sec = 0
    t.it_interval.tv_usec = 0
    t.it_value.tv_sec = 0
    t.it_value.tv_usec = 0
    ret = setitimer(ITIMER_REAL, &t, NULL)
    return int(gtime.it_interval.tv_sec), int(gtime.it_interval.tv_usec)

def test_gettimeofday():
    """
    >>> test_gettimeofday()
    """
    cdef timeval t
    ret = gettimeofday(&t, NULL)
    assert ret == 0
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/posonly.py0000644000175100001770000004522300000000000017625 0ustar00runnerdocker00000000000000# cython: always_allow_keywords=True
# mode: run
# tag: posonly, pure3.8

import cython
import sys
import pickle

def test_optional_posonly_args1(a, b=10, /, c=100):
    """
    >>> test_optional_posonly_args1(1, 2, 3)
    6
    >>> test_optional_posonly_args1(1, 2, c=3)
    6
    >>> test_optional_posonly_args1(1, b=2, c=3)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_optional_posonly_args1() got ... keyword argument... 'b'
    >>> test_optional_posonly_args1(1, 2)
    103
    >>> test_optional_posonly_args1(1, b=2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_optional_posonly_args1() got ... keyword argument... 'b'
    """
    return a + b + c

def test_optional_posonly_args2(a=1, b=10, /, c=100):
    """
    >>> test_optional_posonly_args2(1, 2, 3)
    6
    >>> test_optional_posonly_args2(1, 2, c=3)
    6
    >>> test_optional_posonly_args2(1, b=2, c=3)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_optional_posonly_args2() got ... keyword argument... 'b'
    >>> test_optional_posonly_args2(1, 2)
    103
    >>> test_optional_posonly_args2(1, b=2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_optional_posonly_args2() got ... keyword argument... 'b'
    >>> test_optional_posonly_args2(1, c=2)
    13
    """
    return a + b + c

# TODO: this causes a line that is too long for old versions of Clang
#def many_args(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,
#              a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32,a33,a34,a35,a36,a37,a38,a39,a40,
#              a41,a42,a43,a44,a45,a46,a47,a48,a49,a50,a51,a52,a53,a54,a55,a56,a57,a58,a59,
#              a60,a61,a62,a63,a64,a65,a66,a67,a68,a69,a70,a71,a72,a73,a74,a75,a76,a77,a78,
#              a79,a80,a81,a82,a83,a84,a85,a86,a87,a88,a89,a90,a91,a92,a93,a94,a95,a96,a97,
#              a98,a99,a100,a101,a102,a103,a104,a105,a106,a107,a108,a109,a110,a111,a112,
#              a113,a114,a115,a116,a117,a118,a119,a120,a121,a122,a123,a124,a125,a126,a127,
#              a128,a129,a130,a131,a132,a133,a134,a135,a136,a137,a138,a139,a140,a141,a142,
#              a143,a144,a145,a146,a147,a148,a149,a150,a151,a152,a153,a154,a155,a156,a157,
#              a158,a159,a160,a161,a162,a163,a164,a165,a166,a167,a168,a169,a170,a171,a172,
#              a173,a174,a175,a176,a177,a178,a179,a180,a181,a182,a183,a184,a185,a186,a187,
#              a188,a189,a190,a191,a192,a193,a194,a195,a196,a197,a198,a199,a200,a201,a202,
#              a203,a204,a205,a206,a207,a208,a209,a210,a211,a212,a213,a214,a215,a216,a217,
#              a218,a219,a220,a221,a222,a223,a224,a225,a226,a227,a228,a229,a230,a231,a232,
#              a233,a234,a235,a236,a237,a238,a239,a240,a241,a242,a243,a244,a245,a246,a247,
#              a248,a249,a250,a251,a252,a253,a254,a255,a256,a257,a258,a259,a260,a261,a262,
#              a263,a264,a265,a266,a267,a268,a269,a270,a271,a272,a273,a274,a275,a276,a277,
#              a278,a279,a280,a281,a282,a283,a284,a285,a286,a287,a288,a289,a290,a291,a292,
#              a293,a294,a295,a296,a297,a298,a299,/,b,c=42,*,d):
#    """
#    >>> many_args(*range(299),b=1,c=2,d=3)
#    (298, 1, 2, 3)
#    >>> many_args(*range(299),b=1,d=3)
#    (298, 1, 42, 3)
#    >>> many_args(*range(300),d=3)
#    (298, 299, 42, 3)
#    """
#    return (a299, b, c, d)

#TODO: update this test for Python 3.8 final
@cython.binding(True)
def func_introspection1(a, b, c, /, d, e=1, *, f, g=2):
    """
    >>> if sys.version_info[0] < 3:
    ...     assert func_introspection2.__code__.co_argcount == 7, func_introspection2.__code__.co_argcount
    ... else:
    ...     assert func_introspection2.__code__.co_argcount == 5, func_introspection2.__code__.co_argcount
    >>> func_introspection1.__defaults__
    (1,)
    """

@cython.binding(True)
def func_introspection2(a, b, c=1, /, d=2, e=3, *, f, g=4):
    """
    >>> if sys.version_info[0] < 3:
    ...     assert func_introspection2.__code__.co_argcount == 7, func_introspection2.__code__.co_argcount
    ... else:
    ...     assert func_introspection2.__code__.co_argcount == 5, func_introspection2.__code__.co_argcount
    >>> func_introspection2.__defaults__
    (1, 2, 3)
    """

def test_pos_only_call_via_unpacking(a, b, /):
    """
    >>> test_pos_only_call_via_unpacking(*[1,2])
    3
    """
    return a + b

def test_use_positional_as_keyword1(a, /):
    """
    >>> test_use_positional_as_keyword1(1)
    >>> test_use_positional_as_keyword1(a=1)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_use_positional_as_keyword1() ... keyword argument...
    """

def test_use_positional_as_keyword2(a, /, b):
    """
    >>> test_use_positional_as_keyword2(1, 2)
    >>> test_use_positional_as_keyword2(1, b=2)
    >>> test_use_positional_as_keyword2(a=1, b=2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_use_positional_as_keyword2() ... positional...argument...
    """

def test_use_positional_as_keyword3(a, b, /):
    """
    >>> test_use_positional_as_keyword3(1, 2)
    >>> test_use_positional_as_keyword3(a=1, b=2) # doctest:+ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_use_positional_as_keyword3() got ... keyword argument...
    """

def test_positional_only_and_arg_invalid_calls(a, b, /, c):
    """
    >>> test_positional_only_and_arg_invalid_calls(1, 2, 3)
    >>> test_positional_only_and_arg_invalid_calls(1, 2, c=3)
    >>> test_positional_only_and_arg_invalid_calls(1, 2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_and_arg_invalid_calls() ... positional argument...
    >>> test_positional_only_and_arg_invalid_calls(1)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_and_arg_invalid_calls() ... positional arguments...
    >>> test_positional_only_and_arg_invalid_calls(1,2,3,4)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_and_arg_invalid_calls() takes ... positional arguments ...4 ...given...
    """

def test_positional_only_and_optional_arg_invalid_calls(a, b, /, c=3):
    """
    >>> test_positional_only_and_optional_arg_invalid_calls(1, 2)
    >>> test_positional_only_and_optional_arg_invalid_calls(1)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_and_optional_arg_invalid_calls() ... positional argument...
    >>> test_positional_only_and_optional_arg_invalid_calls()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_and_optional_arg_invalid_calls() ... positional arguments...
    >>> test_positional_only_and_optional_arg_invalid_calls(1, 2, 3, 4)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_and_optional_arg_invalid_calls() takes ... positional arguments ...4 ...given...
    """

def test_positional_only_and_kwonlyargs_invalid_calls(a, b, /, c, *, d, e):
    """
    >>> test_positional_only_and_kwonlyargs_invalid_calls(1, 2, 3, d=1, e=2)
    >>> test_positional_only_and_kwonlyargs_invalid_calls(1, 2, 3, e=2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_and_kwonlyargs_invalid_calls() ... keyword-only argument...d...
    >>> test_positional_only_and_kwonlyargs_invalid_calls(1, 2, 3)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_and_kwonlyargs_invalid_calls() ... keyword-only argument...d...
    >>> test_positional_only_and_kwonlyargs_invalid_calls(1, 2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_and_kwonlyargs_invalid_calls() ... positional argument...
    >>> test_positional_only_and_kwonlyargs_invalid_calls(1)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_and_kwonlyargs_invalid_calls() ... positional arguments...
    >>> test_positional_only_and_kwonlyargs_invalid_calls()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_and_kwonlyargs_invalid_calls() ... positional arguments...
    >>> test_positional_only_and_kwonlyargs_invalid_calls(1, 2, 3, 4, 5, 6, d=7, e=8)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_and_kwonlyargs_invalid_calls() takes ... positional arguments ...
    >>> test_positional_only_and_kwonlyargs_invalid_calls(1, 2, 3, d=1, e=4, f=56)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_and_kwonlyargs_invalid_calls() got an unexpected keyword argument 'f'
    """

def test_positional_only_invalid_calls(a, b, /):
    """
    >>> test_positional_only_invalid_calls(1, 2)
    >>> test_positional_only_invalid_calls(1)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_invalid_calls() ... positional argument...
    >>> test_positional_only_invalid_calls()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_invalid_calls() ... positional arguments...
    >>> test_positional_only_invalid_calls(1, 2, 3)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_invalid_calls() takes ... positional arguments ...3 ...given...
    """

def test_positional_only_with_optional_invalid_calls(a, b=2, /):
    """
    >>> test_positional_only_with_optional_invalid_calls(1)
    >>> test_positional_only_with_optional_invalid_calls()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_with_optional_invalid_calls() ... positional argument...
    >>> test_positional_only_with_optional_invalid_calls(1, 2, 3)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_positional_only_with_optional_invalid_calls() takes ... positional arguments ...3 ...given...
    """

def test_no_standard_args_usage(a, b, /, *, c):
    """
    >>> test_no_standard_args_usage(1, 2, c=3)
    >>> test_no_standard_args_usage(1, b=2, c=3)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_no_standard_args_usage() ... positional... argument...
    """

#def test_change_default_pos_only():
# TODO: probably remove this, since  __defaults__ is not writable in Cython?
#    """
#    >>> test_change_default_pos_only()
#    True
#    True
#    """
#    def f(a, b=2, /, c=3):
#        return a + b + c
#
#    print((2,3) == f.__defaults__)
#    f.__defaults__ = (1, 2, 3)
#    print(f(1, 2, 3) == 6)

def test_lambdas():
    """
    >>> test_lambdas()
    3
    3
    3
    3
    3
    """
    x = lambda a, /, b: a + b
    print(x(1,2))
    print(x(1,b=2))

    x = lambda a, /, b=2: a + b
    print(x(1))

    x = lambda a, b, /: a + b
    print(x(1, 2))

    x = lambda a, b, /, : a + b
    print(x(1, 2))

class TestPosonlyMethods(object):
    """
    >>> TestPosonlyMethods().f(1,2)
    (1, 2)
    >>> TestPosonlyMethods.f(TestPosonlyMethods(), 1, 2)
    (1, 2)
    >>> try:
    ...     TestPosonlyMethods.f(1,2)
    ... except TypeError:
    ...    print("Got type error")
    Got type error
    >>> TestPosonlyMethods().f(1, b=2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...f() got ... keyword argument... 'b'
    """
    def f(self, a, b, /):
        return a, b

class TestMangling(object):
    """
    >>> TestMangling().f()
    42
    >>> TestMangling().f2()
    42

    #>>> TestMangling().f3()
    #(42, 43)
    #>>> TestMangling().f4()
    #(42, 43, 44)

    >>> TestMangling().f2(1)
    1

    #>>> TestMangling().f3(1, _TestMangling__b=2)
    #(1, 2)
    #>>> TestMangling().f4(1, _TestMangling__b=2, _TestMangling__c=3)
    #(1, 2, 3)
    """
    def f(self, *, __a=42):
        return __a

    def f2(self, __a=42, /):
        return __a

# FIXME: https://github.com/cython/cython/issues/1382
#    def f3(self, __a=42, /, __b=43):
#        return (__a, __b)

#    def f4(self, __a=42, /, __b=43, *, __c=44):
#        return (__a, __b, __c)

def test_module_function(a, b, /):
    """
    >>> test_module_function(1, 2)
    >>> test_module_function()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_module_function() ... positional arguments...
    """

def test_closures1(x,y):
    """
    >>> test_closures1(1,2)(3,4)
    10
    >>> test_closures1(1,2)(3)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...g() ... positional argument...
    >>> test_closures1(1,2)(3,4,5)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...g() ... positional argument...
    """
    def g(x2, /, y2):
        return x + y + x2 + y2
    return g

def test_closures2(x, /, y):
    """
    >>> test_closures2(1,2)(3,4)
    10
    """
    def g(x2,y2):
        return x + y + x2 + y2
    return g


def test_closures3(x, /, y):
    """
    >>> test_closures3(1,2)(3,4)
    10
    >>> test_closures3(1,2)(3)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...g() ... positional argument...
    >>> test_closures3(1,2)(3,4,5)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...g() ... positional argument...
    """
    def g(x2, /, y2):
        return x + y + x2 + y2
    return g


def test_same_keyword_as_positional_with_kwargs(something, /, **kwargs):
    """
    >>> test_same_keyword_as_positional_with_kwargs(42, something=42)
    (42, {'something': 42})
    >>> test_same_keyword_as_positional_with_kwargs(something=42)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_same_keyword_as_positional_with_kwargs() ... positional argument...
    >>> test_same_keyword_as_positional_with_kwargs(42)
    (42, {})
    """
    return (something, kwargs)

def test_serialization1(a, b, /):
    """
    >>> pickled_posonly = pickle.dumps(test_serialization1)
    >>> unpickled_posonly = pickle.loads(pickled_posonly)
    >>> unpickled_posonly(1, 2)
    (1, 2)
    >>> unpickled_posonly(a=1, b=2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_serialization1() got ... keyword argument...
    """
    return (a, b)

def test_serialization2(a, /, b):
    """
    >>> pickled_optional = pickle.dumps(test_serialization2)
    >>> unpickled_optional = pickle.loads(pickled_optional)
    >>> unpickled_optional(1, 2)
    (1, 2)
    >>> unpickled_optional(a=1, b=2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_serialization2() ... positional... argument...
    """
    return (a, b)

def test_serialization3(a=1, /, b=2):
    """
    >>> pickled_defaults = pickle.dumps(test_serialization3)
    >>> unpickled_defaults = pickle.loads(pickled_defaults)
    >>> unpickled_defaults(1, 2)
    (1, 2)
    >>> unpickled_defaults(a=1, b=2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_serialization3() got ... keyword argument... 'a'
    """
    return (a, b)


async def test_async(a=1, /, b=2):
    """
    >>> test_async(a=1, b=2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_async() got ... keyword argument... 'a'
    """
    return a, b


def test_async_call(*args, **kwargs):
    """
    >>> test_async_call(1, 2)
    >>> test_async_call(1, b=2)
    >>> test_async_call(1)
    >>> test_async_call()
    """
    if sys.version_info < (3, 6):
        return
    try:
        coro = test_async(*args, **kwargs)
        coro.send(None)
    except StopIteration as e:
        result = e.value
    assert result == (1, 2), result


def test_generator(a=1, /, b=2):
    """
    >>> test_generator(a=1, b=2)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: test_generator() got ... keyword argument... 'a'
    >>> gen = test_generator(1, 2)
    >>> next(gen)
    (1, 2)
    >>> gen = test_generator(1, b=2)
    >>> next(gen)
    (1, 2)
    >>> gen = test_generator(1)
    >>> next(gen)
    (1, 2)
    >>> gen = test_generator()
    >>> next(gen)
    (1, 2)
    """
    yield a, b

def f_call_1_0_0(a,/):
    """
    >>> f_call_1_0_0(1)
    (1,)
    """
    return (a,)

def f_call_1_1_0(a, /, b):
    """
    >>> f_call_1_1_0(1,2)
    (1, 2)
    """
    return (a,b)

def f_call_1_1_1(a, /, b, *, c):
    """
    >>> f_call_1_1_1(1,2,c=3)
    (1, 2, 3)
    """
    return (a,b,c)

def f_call_1_1_1_star(a, /, b, *args, c):
    """
    >>> f_call_1_1_1_star(1,2,c=3)
    (1, 2, (), 3)
    >>> f_call_1_1_1_star(1,2,3,4,5,6,7,8,c=9)
    (1, 2, (3, 4, 5, 6, 7, 8), 9)
    """
    return (a,b,args,c)

def f_call_1_1_1_kwds(a, /, b, *, c, **kwds):
    """
    >>> f_call_1_1_1_kwds(1,2,c=3)
    (1, 2, 3, {})
    >>> f_call_1_1_1_kwds(1,2,c=3,d=4,e=5) == (1, 2, 3, {'d': 4, 'e': 5})
    True
    """
    return (a,b,c,kwds)

def f_call_1_1_1_star_kwds(a, /, b, *args, c, **kwds):
    """
    >>> f_call_1_1_1_star_kwds(1,2,c=3,d=4,e=5) == (1, 2, (), 3, {'d': 4, 'e': 5})
    True
    >>> f_call_1_1_1_star_kwds(1,2,3,4,c=5,d=6,e=7) == (1, 2, (3, 4), 5, {'d': 6, 'e': 7})
    True
    """
    return (a,b,args,c,kwds)

def f_call_one_optional_kwd(a, /, *, b=2):
    """
    >>> f_call_one_optional_kwd(1)
    (1, 2)
    >>> f_call_one_optional_kwd(1, b=3)
    (1, 3)
    """
    return (a,b)

def f_call_posonly_stararg(a, /, *args):
    """
    >>> f_call_posonly_stararg(1)
    (1, ())
    >>> f_call_posonly_stararg(1, 2, 3, 4)
    (1, (2, 3, 4))
    """
    return (a,args)

def f_call_posonly_kwarg(a, /, **kw):
    """
    >>> f_call_posonly_kwarg(1)
    (1, {})
    >>> all_args = f_call_posonly_kwarg(1, b=2, c=3, d=4)
    >>> all_args == (1, {'b': 2, 'c': 3, 'd': 4}) or all_args
    True
    """
    return (a,kw)

def f_call_posonly_stararg_kwarg(a, /, *args, **kw):
    """
    >>> f_call_posonly_stararg_kwarg(1)
    (1, (), {})
    >>> f_call_posonly_stararg_kwarg(1, 2)
    (1, (2,), {})
    >>> all_args = f_call_posonly_stararg_kwarg(1, b=3, c=4)
    >>> all_args == (1, (), {'b': 3, 'c': 4}) or all_args
    True
    >>> all_args = f_call_posonly_stararg_kwarg(1, 2, b=3, c=4)
    >>> all_args == (1, (2,), {'b': 3, 'c': 4}) or all_args
    True
    """
    return (a,args,kw)

def test_empty_kwargs(a, b, /):
    """
    >>> test_empty_kwargs(1, 2)
    (1, 2)
    >>> test_empty_kwargs(1, 2, **{})
    (1, 2)
    >>> test_empty_kwargs(1, 2, **{'c': 3})
    Traceback (most recent call last):
    TypeError: test_empty_kwargs() got an unexpected keyword argument 'c'
    """
    return (a,b)


@cython.cclass
class TestExtensionClass:
    """
    >>> t = TestExtensionClass()
    >>> t.f(1,2)
    (1, 2, 3)
    >>> t.f(1,2,4)
    (1, 2, 4)
    >>> t.f(1, 2, c=4)
    (1, 2, 4)
    >>> t.f(1, 2, 5, c=6)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...f() got multiple values for ...argument 'c'
    """
    def f(self, a, b, /, c=3):
        return (a,b,c)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/powop.pyx0000644000175100001770000000707700000000000017463 0ustar00runnerdocker00000000000000cimport cython

def f(obj2, obj3):
    """
    >>> f(1.0, 2.95)[0] == f(1.0, 2.95)[1]
    True
    """
    cdef float flt1, flt2, flt3
    flt2, flt3 = obj2, obj3

    flt1 = flt2 ** flt3
    obj1 = obj2 ** obj3
    return flt1, obj1


def g(i):
    """
    >>> g(4)
    1024
    """
    return i ** 5


def h(i):
    """
    >>> h(4)
    625
    """
    return 5 ** i


def constant_py():
    """
    >>> constant_py() == 2 ** 10
    True
    """
    result = (2) ** 10
    return result


def constant_long():
    """
    >>> constant_long() == 2 ** 36
    True
    """
    result = (2L) ** 36
    return result


def small_int_pow(long s):
    """
    >>> small_int_pow(3)
    (1, 3, 9, 27, 81)
    >>> small_int_pow(-5)
    (1, -5, 25, -125, 625)
    """
    return s**0, s**1, s**2, s**3, s**4


@cython.cpow(True)
def int_pow_cpow(short a, short b):
    """
    >>> int_pow_cpow(7, 2)
    49
    >>> int_pow_cpow(5, 3)
    125
    >>> int_pow_cpow(2, 10)
    1024
    """
    return a**b

@cython.cpow(False)
def int_pow(short a, short b):
    """
    >>> int_pow(7, 2)
    49.0
    >>> int_pow(5, 3)
    125.0
    >>> int_pow(2, 10)
    1024.0
    """
    return a**b


class I(int):
    """
    Copied from CPython's test_descr.py

    >>> I(2) ** I(3)
    I(8)
    >>> 2 ** I(3)
    I(8)
    >>> I(3).pow2()
    I(8)
    """
    def __repr__(self):
        return 'I(%s)' % int(self)
    def __pow__(self, other, mod=None):
        if mod is None:
            return I(pow(int(self), int(other)))
        else:
            return I(pow(int(self), int(other), int(mod)))
    def __rpow__(self, other, mod=None):
        if mod is None:
            return I(pow(int(other), int(self), mod))
        else:
            return I(pow(int(other), int(self), int(mod)))

    def pow2(self):
        return 2 ** self


def optimised_pow2(n):
    """
    >>> optimised_pow2(0)
    1
    >>> optimised_pow2(1)
    2
    >>> optimised_pow2(10)
    1024
    >>> optimised_pow2(30)
    1073741824
    >>> print(repr(optimised_pow2(31)).rstrip('L'))
    2147483648
    >>> print(repr(optimised_pow2(32)).rstrip('L'))
    4294967296
    >>> print(repr(optimised_pow2(60)).rstrip('L'))
    1152921504606846976
    >>> print(repr(optimised_pow2(63)).rstrip('L'))
    9223372036854775808
    >>> print(repr(optimised_pow2(64)).rstrip('L'))
    18446744073709551616
    >>> print(repr(optimised_pow2(100)).rstrip('L'))
    1267650600228229401496703205376
    >>> optimised_pow2(30000) == 2 ** 30000
    True
    >>> optimised_pow2(-1)
    0.5
    >>> optimised_pow2(0.5) == 2 ** 0.5
    True
    >>> optimised_pow2('test') # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...operand... **...
    """
    if isinstance(n, (int, long)) and 0 <= n < 1000:
        assert isinstance(2.0 ** n, float), 'float %s' % n
        assert isinstance(2 ** n, (int, long)), 'int %s' % n
    return 2 ** n


def optimised_pow2_inplace(n):
    """
    >>> optimised_pow2_inplace(0)
    1
    >>> optimised_pow2_inplace(1)
    2
    >>> optimised_pow2_inplace(10)
    1024
    >>> optimised_pow2_inplace(30)
    1073741824
    >>> print(repr(optimised_pow2_inplace(32)).rstrip('L'))
    4294967296
    >>> print(repr(optimised_pow2_inplace(100)).rstrip('L'))
    1267650600228229401496703205376
    >>> optimised_pow2_inplace(30000) == 2 ** 30000
    True
    >>> optimised_pow2_inplace(-1)
    0.5
    >>> optimised_pow2_inplace(0.5) == 2 ** 0.5
    True
    >>> optimised_pow2_inplace('test') # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...operand... **...
    """
    x = 2
    x **= n
    return x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/print.pyx0000644000175100001770000000135100000000000017440 0ustar00runnerdocker00000000000000def print_to_stdout(a, b):
    """
    >>> print_to_stdout(1, 'test')
    
    1
    1 test
    1 test
    1 test 42 spam
    """
    print
    print a
    print a,
    print b
    print a, b
    print a, b,
    print 42, u"spam"


try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO

def print_to_stringio(stream, a, b):
    """
    >>> stream = StringIO()
    >>> print_to_stringio(stream, 1, 'test')
    >>> print(stream.getvalue())
    
    1
    1 test
    1 test
    1 test 42 spam
    
    """
    print >> stream
    print >> stream, a
    print >> stream, a,
    print >> stream, b
    print >> stream, a, b
    print >> stream, a, b,
    print >> stream, 42, u"spam"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/print_function.pyx0000644000175100001770000000213400000000000021345 0ustar00runnerdocker00000000000000
# Py2.6 and later only!
from __future__ import print_function

def print_to_stdout(a, b):
    """
    >>> print_to_stdout(1, 'test')
    
    1
    1 test
    1 test
    1 test 42 spam
    """
    print()
    print(a)
    print(a, end=' ')
    print(b)
    print(a, b)
    print(a, b, end=' ')
    print(42, u"spam")

def print_assign(a, b):
    """
    >>> print_assign(1, 'test')
    
    1
    1 test
    1 test
    1 test 42 spam
    """
    x = print
    x()
    x(a)
    x(a, end=' ')
    x(b)
    x(a, b)
    x(a, b, end=' ')
    x(42, u"spam")


try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO

def print_to_stringio(stream, a, b):
    """
    >>> stream = StringIO()
    >>> print_to_stringio(stream, 1, 'test')
    >>> print(stream.getvalue())
    
    1
    1 test
    1 test
    1 test 42 spam
    
    """
    print(file=stream)
    print(a, file=stream)
    print(a, end=' ', file=stream)
    print(b, file=stream)
    print(a, b, file=stream)
    print(a, b, end=' ', file=stream)
    print(42, u"spam", file=stream)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/print_refcount.pyx0000644000175100001770000000156100000000000021350 0ustar00runnerdocker00000000000000# mode: run
import sys

def test_print_refcount():
    """
    >>> test_print_refcount()
    """
    old_stdout = sys.stdout
    class StdoutGuard:
        def __getattr__(self, attr):
            sys.stdout = old_stdout
            raise RuntimeError
    sys.stdout = StdoutGuard()
    try:
        print "Hello", "world!"
    except RuntimeError:
        pass
    finally:
        sys.stdout = old_stdout
    class TriggerSIGSEGV(object):
        pass

def test_printone_refcount():
    """
    >>> test_printone_refcount()
    """
    old_stdout = sys.stdout
    class StdoutGuard:
        def __getattr__(self, attr):
            sys.stdout = old_stdout
            raise RuntimeError
    sys.stdout = StdoutGuard()
    try:
        print "Oops!"
    except RuntimeError:
        pass
    finally:
        sys.stdout = old_stdout
    class TriggerSIGSEGV(object):
        pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/property_decorator_T593.py0000644000175100001770000000202200000000000022562 0ustar00runnerdocker00000000000000# mode: run
# ticket: t593
# tag: property, decorator

my_property = property

class Prop(object):
    """
    >>> p = Prop()
    >>> p.prop
    GETTING 'None'
    >>> p.prop = 1
    SETTING '1' (previously: 'None')
    >>> p.prop
    GETTING '1'
    1
    >>> p.prop = 2
    SETTING '2' (previously: '1')
    >>> p.prop
    GETTING '2'
    2
    >>> del p.prop
    DELETING (previously: '2')

    >>> p.my_prop
    GETTING 'my_prop'
    389

    >>> list(p.generator_prop)
    [42]
    """
    _value = None

    @property
    def prop(self):
        print("GETTING '%s'" % self._value)
        return self._value

    @prop.setter
    def prop(self, value):
        print("SETTING '%s' (previously: '%s')" % (value, self._value))
        self._value = value

    @prop.deleter
    def prop(self):
        print("DELETING (previously: '%s')" % self._value)
        self._value = None

    @my_property
    def my_prop(self):
        print("GETTING 'my_prop'")
        return 389

    @property
    def generator_prop(self):
        yield 42
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4167223
Cython-3.0.8/tests/run/pstats_profile_test.pyx0000644000175100001770000001243200000000000022403 0ustar00runnerdocker00000000000000# tag: pstats
# cython: profile = True

u"""
    >>> import os, tempfile, cProfile as profile, pstats
    >>> statsfile = tempfile.mkstemp()[1]
    >>> profile.runctx("test_profile(100)", locals(), globals(), statsfile)
    >>> s = pstats.Stats(statsfile)
    >>> short_stats = dict([(k[2], v[1]) for k,v in s.stats.items()])
    >>> short_stats['f_def']
    100
    >>> short_stats['f_cdef']
    100
    >>> short_stats['f_cpdef']
    300
    >>> short_stats['f_inline']
    100
    >>> short_stats['f_inline_prof']
    100
    >>> short_stats['f_noprof']
    Traceback (most recent call last):
    ...
    KeyError: 'f_noprof'
    >>> short_stats['f_raise']
    100

    >>> short_stats['withgil_prof']
    100
    >>> short_stats['withgil_noprof']
    Traceback (most recent call last):
    ...
    KeyError: 'withgil_noprof'

    >>> short_stats['nogil_prof']
    Traceback (most recent call last):
    ...
    KeyError: 'nogil_prof'
    >>> short_stats['nogil_noprof']
    Traceback (most recent call last):
    ...
    KeyError: 'nogil_noprof'

    >>> short_stats['f_raise']
    100

    >>> short_stats['m_def']
    200
    >>> short_stats['m_cdef']
    100
    >>> short_stats['m_cpdef'] - (200 if CPDEF_METHODS_COUNT_TWICE else 0)  # FIXME!
    300

    >>> try:
    ...    os.unlink(statsfile)
    ... except:
    ...    pass

    >>> sorted(callees(s, 'test_profile'))  #doctest: +NORMALIZE_WHITESPACE
    ['f_cdef', 'f_cpdef', 'f_def',
     'f_inline', 'f_inline_prof',
     'f_raise',
     'm_cdef', 'm_cpdef', 'm_def',
     'withgil_prof']

    >>> profile.runctx("test_generators()", locals(), globals(), statsfile)
    >>> s = pstats.Stats(statsfile)
    >>> short_stats = dict([(k[2], v[1]) for k,v in s.stats.items()])
    >>> short_stats['generator']
    3

    >>> short_stats['generator_exception']
    2

    >>> short_stats['genexpr']
    11

    >>> sorted(callees(s, 'test_generators'))
    ['call_generator', 'call_generator_exception', 'generator_expr']

    >>> list(callees(s, 'call_generator'))
    ['generator']

    >>> list(callees(s, 'generator'))
    []

    >>> list(callees(s, 'generator_exception'))
    []

    >>> list(callees(s, 'generator_expr'))
    ['genexpr']

    >>> list(callees(s, 'genexpr'))
    []

    >>> def python_generator():
    ...   yield 1
    ...   yield 2
    >>> def call_python_generator():
    ...   list(python_generator())

    >>> profile.runctx("call_python_generator()", locals(), globals(), statsfile)
    >>> python_stats = pstats.Stats(statsfile)
    >>> python_stats_dict = dict([(k[2], v[1]) for k,v in python_stats.stats.items()])

    >>> profile.runctx("call_generator()", locals(), globals(), statsfile)
    >>> cython_stats = pstats.Stats(statsfile)
    >>> cython_stats_dict = dict([(k[2], v[1]) for k,v in cython_stats.stats.items()])

    >>> python_stats_dict['python_generator'] == cython_stats_dict['generator']
    True

    >>> try:
    ...    os.unlink(statsfile)
    ... except:
    ...    pass
"""

cimport cython


# FIXME: With type specs, cpdef methods are currently counted twice.
# https://github.com/cython/cython/issues/2137
cdef extern from *:
    int CYTHON_USE_TYPE_SPECS

CPDEF_METHODS_COUNT_TWICE = CYTHON_USE_TYPE_SPECS


def callees(pstats, target_caller):
    pstats.calc_callees()
    for (_, _, caller), callees in pstats.all_callees.items():
      if caller == target_caller:
        for (file, line, callee) in callees.keys():
            if 'pyx' in file:
                yield callee


def test_profile(long N):
    cdef long i, n = 0
    cdef A a = A()
    for i in range(N):
        n += f_def(i)
        n += f_cdef(i)
        n += f_cpdef(i)
        n += (f_cpdef)(i)
        n += f_inline(i)
        n += f_inline_prof(i)
        n += f_noprof(i)
        n += nogil_noprof(i)
        n += nogil_prof(i)
        n += withgil_noprof(i)
        n += withgil_prof(i)
        n += a.m_def(i)
        n += (a).m_def(i)
        n += a.m_cpdef(i)
        n += (a).m_cpdef(i)
        n += a.m_cdef(i)
        try:
            n += f_raise(i+2)
        except RuntimeError:
            pass
    return n

def f_def(long a):
    return a

cdef long f_cdef(long a):
    return a

cpdef long f_cpdef(long a):
    return a

cdef inline long f_inline(long a):
    return a

@cython.profile(True)
cdef inline long f_inline_prof(long a):
    return a

@cython.profile(False)
cdef int f_noprof(long a):
    return a

cdef long f_raise(long) except -2:
    raise RuntimeError

@cython.profile(False)
cdef int withgil_noprof(long a) with gil:
    return (a)
@cython.profile(True)
cdef int withgil_prof(long a) with gil:
    return (a)

@cython.profile(False)
cdef int nogil_noprof(long a) nogil:
    return a
@cython.profile(True)
cdef int nogil_prof(long a) nogil:
    return a

cdef class A(object):
    def m_def(self, long a):
        return a
    cpdef m_cpdef(self, long a):
        return a
    cdef m_cdef(self, long a):
        return a

def test_generators():
    call_generator()
    call_generator_exception()
    generator_expr()

def call_generator():
    list(generator())

def generator():
    yield 1
    yield 2

def call_generator_exception():
    try:
        list(generator_exception())
    except ValueError:
        pass

def generator_exception():
    yield 1
    raise ValueError(2)

def generator_expr():
    e = (x for x in range(10))
    return sum(e)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pstats_profile_test_py.py0000644000175100001770000001371600000000000022731 0ustar00runnerdocker00000000000000# mode: run
# tag: pstats, pure3.6
# cython: profile = True
# distutils: define_macros = CYTHON_TRACE_NOGIL=1

u"""
    >>> import os, tempfile, cProfile as profile, pstats
    >>> statsfile = tempfile.mkstemp()[1]
    >>> profile.runctx("test_profile(100)", locals(), globals(), statsfile)
    >>> s = pstats.Stats(statsfile)
    >>> short_stats = dict([(k[2], v[1]) for k,v in s.stats.items()])
    >>> short_stats['f_def']
    100
    >>> short_stats['f_cdef']
    100
    >>> short_stats['f_cpdef'] + (0 if COMPILED else 100)
    300
    >>> short_stats['f_inline']
    100
    >>> short_stats['f_inline_prof']
    100
    >>> try:
    ...     assert short_stats['f_noprof']
    ... except KeyError:
    ...     assert COMPILED
    ... else:
    ...     assert not COMPILED

    >>> short_stats['f_raise']
    100

    >>> short_stats['withgil_prof']
    100
    >>> try:
    ...     assert short_stats['withgil_noprof']
    ... except KeyError:
    ...     assert COMPILED
    ... else:
    ...     assert not COMPILED

    >>> short_stats['nogil_prof']
    100

    >>> try:
    ...     assert short_stats['nogil_noprof']
    ... except KeyError:
    ...     assert COMPILED
    ... else:
    ...     assert not COMPILED

    >>> short_stats['f_raise']
    100

    >>> short_stats['m_def']
    200
    >>> short_stats['m_cdef']
    100

    >>> if COMPILED:
    ...     assert (short_stats['m_cpdef'] - 100) in (200, 400)  # FIXME!
    ... else:
    ...     assert short_stats['m_cpdef'] == 200

    >>> try:
    ...    os.unlink(statsfile)
    ... except:
    ...    pass

    >>> sorted(list(callees(s, 'test_profile')) + (
    ...        ['f_noprof', 'nogil_noprof', 'withgil_noprof'] if COMPILED else []))  #doctest: +NORMALIZE_WHITESPACE
    ['f_cdef', 'f_cpdef', 'f_def',
     'f_inline', 'f_inline_prof',
     'f_noprof',
     'f_raise',
     'm_cdef', 'm_cpdef', 'm_def',
     'nogil_noprof', 'nogil_prof',
     'withgil_noprof', 'withgil_prof']

    >>> profile.runctx("test_generators()", locals(), globals(), statsfile)
    >>> s = pstats.Stats(statsfile)
    >>> short_stats = dict([(k[2], v[1]) for k,v in s.stats.items()])
    >>> short_stats['generator']
    3

    >>> short_stats['generator_exception']
    2

    >>> sorted(callees(s, 'test_generators'))
    ['call_generator', 'call_generator_exception']

    >>> list(callees(s, 'call_generator'))
    ['generator']

    >>> list(callees(s, 'generator'))
    []

    >>> list(callees(s, 'generator_exception'))
    []

    >>> def python_generator():
    ...   yield 1
    ...   yield 2
    >>> def call_python_generator():
    ...   list(python_generator())

    >>> profile.runctx("call_python_generator()", locals(), globals(), statsfile)
    >>> python_stats = pstats.Stats(statsfile)
    >>> python_stats_dict = dict([(k[2], v[1]) for k,v in python_stats.stats.items()])

    >>> profile.runctx("call_generator()", locals(), globals(), statsfile)
    >>> cython_stats = pstats.Stats(statsfile)
    >>> cython_stats_dict = dict([(k[2], v[1]) for k,v in cython_stats.stats.items()])

    >>> python_stats_dict['python_generator'] == cython_stats_dict['generator']
    True

    >>> try:
    ...    os.unlink(statsfile)
    ... except:
    ...    pass
"""

import cython

COMPILED = cython.compiled


def callees(pstats, target_caller):
    pstats.calc_callees()
    for (_, _, caller), callees in pstats.all_callees.items():
        if caller == target_caller:
            for (file, line, callee) in callees.keys():
                if 'pstats_profile_test' in file:
                    yield callee


def test_profile(N: cython.long):
    i: cython.long
    n: cython.long = 0
    a: A = A()
    for i in range(N):
        n += f_def(i)
        n += f_cdef(i)
        n += f_cpdef(i)
        n += cython.cast(object, f_cpdef)(i)
        n += f_inline(i)
        n += f_inline_prof(i)
        n += f_noprof(i)
        n += nogil_noprof(i)
        n += nogil_prof(i)
        n += withgil_noprof(i)
        n += withgil_prof(i)
        n += a.m_def(i)
        n += cython.cast(object, a).m_def(i)
        n += a.m_cpdef(i)
        n += cython.cast(object, a).m_cpdef(i)
        n += a.m_cdef(i)
        try:
            n += f_raise(i+2)
        except RuntimeError:
            pass
    return n

def f_def(a: cython.long):
    return a

@cython.cfunc
def f_cdef(a: cython.long) -> cython.long:
    return a

@cython.ccall
def f_cpdef(a: cython.long) -> cython.long:
    return a

@cython.inline
@cython.cfunc
def f_inline(a: cython.long) -> cython.long:
    return a

@cython.profile(True)
@cython.inline
@cython.cfunc
def f_inline_prof(a: cython.long) -> cython.long:
    return a

@cython.profile(False)
@cython.inline
@cython.cfunc
def f_noprof(a: cython.long) -> cython.long:
    return a

@cython.inline
@cython.exceptval(-2)
@cython.cfunc
def f_raise(a: cython.long) -> cython.long:
    raise RuntimeError

@cython.profile(False)
@cython.with_gil
@cython.cfunc
def withgil_noprof(a: cython.long) -> cython.long:
    return (a)

@cython.profile(True)
@cython.with_gil
@cython.cfunc
def withgil_prof(a: cython.long) -> cython.long:
    return (a)

@cython.profile(False)
@cython.nogil
@cython.cfunc
def nogil_noprof(a: cython.long) -> cython.long:
    return a

@cython.profile(True)
@cython.nogil
@cython.cfunc
def nogil_prof(a: cython.long) -> cython.long:
    return a


@cython.cclass
class A(object):
    def m_def(self, a: cython.long):
        return a
    @cython.ccall
    def m_cpdef(self, a: cython.long):
        return a
    @cython.cfunc
    def m_cdef(self, a: cython.long):
        return a


def test_generators():
    call_generator()
    call_generator_exception()

def call_generator():
    list(generator())

def generator():
    yield 1
    yield 2

def call_generator_exception():
    try:
        list(generator_exception())
    except ValueError:
        pass

def generator_exception():
    yield 1
    raise ValueError(2)

# Generator expressions are inlined in Python 3.12 and no longer show uo in profiles.
#def generator_expr():
#    e = (x for x in range(10))
#    return sum(e)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pstats_profile_test_pycfunc.pyx0000644000175100001770000001227300000000000024135 0ustar00runnerdocker00000000000000# tag: pstats
# cython: profile = True
# cython: binding = False

__doc__ = u"""
    >>> import os, tempfile, cProfile as profile, pstats
    >>> statsfile = tempfile.mkstemp()[1]
    >>> profile.runctx("test_profile(100)", locals(), globals(), statsfile)
    >>> s = pstats.Stats(statsfile)
    >>> short_stats = dict([(k[2], v[1]) for k,v in s.stats.items()])
    >>> short_stats['f_def']
    100
    >>> short_stats['f_cdef']
    100
    >>> short_stats['f_cpdef']
    200
    >>> short_stats['f_cpdef (wrapper)']
    100
    >>> short_stats['f_inline']
    100
    >>> short_stats['f_inline_prof']
    100
    >>> short_stats['f_noprof']
    Traceback (most recent call last):
    ...
    KeyError: 'f_noprof'
    >>> short_stats['f_raise']
    100

    >>> short_stats['withgil_prof']
    100
    >>> short_stats['withgil_noprof']
    Traceback (most recent call last):
    ...
    KeyError: 'withgil_noprof'

    >>> short_stats['nogil_prof']
    Traceback (most recent call last):
    ...
    KeyError: 'nogil_prof'
    >>> short_stats['nogil_noprof']
    Traceback (most recent call last):
    ...
    KeyError: 'nogil_noprof'

    >>> short_stats['f_raise']
    100

    >>> short_stats['m_def']
    200
    >>> short_stats['m_cdef']
    100
    >>> short_stats['m_cpdef']
    200
    >>> short_stats['m_cpdef (wrapper)']
    100

    >>> try:
    ...    os.unlink(statsfile)
    ... except:
    ...    pass

    >>> sorted(callees(s, 'test_profile'))  #doctest: +NORMALIZE_WHITESPACE
    ['f_cdef', 'f_cpdef', 'f_cpdef (wrapper)', 'f_def',
     'f_inline', 'f_inline_prof',
     'f_raise',
     'm_cdef', 'm_cpdef', 'm_cpdef (wrapper)', 'm_def',
     'withgil_prof']

    >>> profile.runctx("test_generators()", locals(), globals(), statsfile)
    >>> s = pstats.Stats(statsfile)
    >>> short_stats = dict([(k[2], v[1]) for k,v in s.stats.items()])
    >>> short_stats['generator']
    3

    >>> short_stats['generator_exception']
    2

    >>> short_stats['genexpr']
    11

    >>> sorted(callees(s, 'test_generators'))
    ['call_generator', 'call_generator_exception', 'generator_expr']

    >>> list(callees(s, 'call_generator'))
    ['generator']

    >>> list(callees(s, 'generator'))
    []

    >>> list(callees(s, 'generator_exception'))
    []

    >>> list(callees(s, 'generator_expr'))
    ['genexpr']

    >>> list(callees(s, 'genexpr'))
    []

    >>> def python_generator():
    ...   yield 1
    ...   yield 2
    >>> def call_python_generator():
    ...   list(python_generator())

    >>> profile.runctx("call_python_generator()", locals(), globals(), statsfile)
    >>> python_stats = pstats.Stats(statsfile)
    >>> python_stats_dict = dict([(k[2], v[1]) for k,v in python_stats.stats.items()])

    >>> profile.runctx("call_generator()", locals(), globals(), statsfile)
    >>> cython_stats = pstats.Stats(statsfile)
    >>> cython_stats_dict = dict([(k[2], v[1]) for k,v in cython_stats.stats.items()])

    >>> python_stats_dict['python_generator'] == cython_stats_dict['generator']
    True

    >>> try:
    ...    os.unlink(statsfile)
    ... except:
    ...    pass
"""

cimport cython

def callees(pstats, target_caller):
    pstats.calc_callees()
    for (_, _, caller), callees in pstats.all_callees.items():
      if caller == target_caller:
        for (file, line, callee) in callees.keys():
            if 'pyx' in file:
                yield callee

def test_profile(long N):
    cdef long i, n = 0
    cdef A a = A()
    for i from 0 <= i < N:
        n += f_def(i)
        n += f_cdef(i)
        n += f_cpdef(i)
        n += (f_cpdef)(i)
        n += f_inline(i)
        n += f_inline_prof(i)
        n += f_noprof(i)
        n += nogil_noprof(i)
        n += nogil_prof(i)
        n += withgil_noprof(i)
        n += withgil_prof(i)
        n += a.m_def(i)
        n += (a).m_def(i)
        n += a.m_cpdef(i)
        n += (a).m_cpdef(i)
        n += a.m_cdef(i)
        try:
            n += f_raise(i+2)
        except RuntimeError:
            pass
    return n

def f_def(long a):
    return a

cdef long f_cdef(long a):
    return a

cpdef long f_cpdef(long a):
    return a

cdef inline long f_inline(long a):
    return a

@cython.profile(True)
cdef inline long f_inline_prof(long a):
    return a

@cython.profile(False)
cdef int f_noprof(long a):
    return a

cdef long f_raise(long) except -2:
    raise RuntimeError

@cython.profile(False)
cdef int withgil_noprof(long a) with gil:
    return (a)
@cython.profile(True)
cdef int withgil_prof(long a) with gil:
    return (a)

@cython.profile(False)
cdef int nogil_noprof(long a) nogil:
    return a
@cython.profile(True)
cdef int nogil_prof(long a) nogil:
    return a

cdef class A(object):
    def m_def(self, long a):
        return a
    cpdef m_cpdef(self, long a):
        return a
    cdef m_cdef(self, long a):
        return a

def test_generators():
    call_generator()
    call_generator_exception()
    generator_expr()

def call_generator():
    list(generator())

def generator():
    yield 1
    yield 2

def call_generator_exception():
    try:
        list(generator_exception())
    except ValueError:
        pass

def generator_exception():
    yield 1
    raise ValueError(2)

def generator_expr():
    e = (x for x in range(10))
    return sum(e)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/ptr_warning_T714.pyx0000644000175100001770000000026200000000000021355 0ustar00runnerdocker00000000000000# mode: run
# tag: werror
# ticket: t714

def test_ptr():
    """
    >>> test_ptr()
    123
    """
    cdef int a
    cdef int *ptr

    ptr = &a
    ptr[0] = 123
    return a
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/ptrdiff_t.pyx0000644000175100001770000000211200000000000020261 0ustar00runnerdocker00000000000000from cython cimport typeof

def test(ptrdiff_t i):
    """
    >>> int(test(0))
    0
    >>> int(test(1))
    1
    >>> int(test(2))
    2
    >>> int(test(-1))
    -1
    >>> int(test(-2))
    -2
    >>> int(test((1<<31)-1))
    2147483647
    """
    return i

cdef class A:
    """
    >>> try: test(1<<200)
    ... except (OverflowError, TypeError): print("ERROR")
    ERROR

    >>> a = A(1,2)
    >>> a.a == 1
    True
    >>> a.b == 2
    True
    >>> print(a.foo(5))
    5
    >>> try: a.foo(1<<200)
    ... except (OverflowError, TypeError): print("ERROR")
    ERROR
    """
    cdef public ptrdiff_t a
    cdef readonly ptrdiff_t b

    def __init__(self, ptrdiff_t a, object b):
        self.a = a
        self.b = b

    cpdef ptrdiff_t foo(self, ptrdiff_t x):
        cdef object o = x
        return o

def test_types():
    """
    >>> test_types()
    """
    cdef int a = 1, b = 2
    assert typeof(&a - &b) == "ptrdiff_t", typeof(&a - &b)
    assert typeof((&a - &b) + 1) == "ptrdiff_t", typeof((&a - &b) + 1)
    assert typeof(&a + (&b - &a)) == "int *", typeof(&a + (&b - &a))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/public_enum.pyx0000644000175100001770000000052100000000000020604 0ustar00runnerdocker00000000000000# mode: run

"""
>>> BAR == 3
True
>>> HONK == 3+2+1
True
>>> NONPUBLIC         # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'NONPUBLIC' is not defined
>>> NOWPUBLIC == 23 + 42
True
"""

cdef enum SECRET:
    NONPUBLIC = 23 + 42

cdef public enum FOO:
    BAR = 3
    HONK = 3+2+1
    NOWPUBLIC = NONPUBLIC
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/public_fused_types.srctree0000644000175100001770000001374400000000000023034 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import b"

######## setup.py ########


from Cython.Build import cythonize
from distutils.core import setup

setup(
  ext_modules = cythonize("*.pyx"),
)

######## a.pxd ########

cimport cython

cdef extern from "header.h":
    ctypedef int extern_int
    ctypedef long extern_long


cdef struct mystruct_t:
    extern_int a

ctypedef union myunion_t:
    extern_long a

cdef public class MyExt [ type MyExtType, object MyExtObject ]:
    cdef unsigned char a

ctypedef char *string_t
simple_t = cython.fused_type(int, float)
less_simple_t = cython.fused_type(int, float, string_t)
struct_t = cython.fused_type(mystruct_t, myunion_t, MyExt)
builtin_t = cython.fused_type(str, unicode, bytes)

ctypedef fused fusedbunch:
    int
    long
    complex
    string_t

ctypedef fused fused1:
    short
    string_t

cdef fused fused2:
    float
    double
    string_t

cdef struct_t add_simple(struct_t obj, simple_t simple)
cdef less_simple_t add_to_simple(struct_t obj, less_simple_t simple)
cdef public_optional_args(struct_t obj, simple_t simple = *)

cdef class TestFusedExtMethods(object):
    cdef cython.floating method(self, cython.integral x, cython.floating y)
    cpdef cpdef_method(self, cython.integral x, cython.floating y)

object_t = cython.fused_type(TestFusedExtMethods, object, list)

cpdef public_cpdef(cython.integral x, cython.floating y, object_t z)

######## header.h ########

typedef int extern_int;
typedef long extern_long;

######## a.pyx ########

cimport cython

cdef struct_t add_simple(struct_t obj, simple_t simple):
     obj.a =  (obj.a + simple)
     return obj

cdef less_simple_t add_to_simple(struct_t obj, less_simple_t simple):
    return obj.a + simple

cdef public_optional_args(struct_t obj, simple_t simple = 6):
    return obj.a, simple

cdef class TestFusedExtMethods(object):
    cdef cython.floating method(self, cython.integral x, cython.floating y):
        if cython.integral is int:
            x += 1

        if cython.floating is double:
            y += 2.0

        return x + y

    cpdef cpdef_method(self, cython.integral x, cython.floating y):
        return cython.typeof(x), cython.typeof(y)

    def def_method(self, fused1 x, fused2 y):
        if (fused1 is string_t and fused2 is not string_t or
            not fused1 is string_t and fused2 is string_t):
            return x, y
        else:
            return  x + y

cpdef public_cpdef(cython.integral x, cython.floating y, object_t z):
    if cython.integral is int:
        pass

    return cython.typeof(x), cython.typeof(y), cython.typeof(z)


######## b.pyx ########

cimport cython
cimport a as a_cmod
from a cimport *

cdef mystruct_t mystruct
cdef myunion_t myunion
cdef MyExt myext = MyExt()

mystruct.a = 5
myunion.a = 5
myext.a = 5

assert add_simple(mystruct, 5).a == 10
assert add_simple(myunion, 5.0).a == 10.0

assert add_to_simple(mystruct, 5.0) == 10.0
assert add_to_simple(myunion, b"spamhameggs") == b"ameggs"
assert add_to_simple(myext, 5) == 10

cdef mystruct_t (*f)(mystruct_t, int)
f = add_simple
assert f(mystruct, 5).a == 10

f =  add_simple
assert f(mystruct, 5).a == 10

f = add_simple[mystruct_t, int]
assert f(mystruct, 5).a == 10

assert public_optional_args(mystruct, 5) == (5, 5)
assert public_optional_args[mystruct_t, int](mystruct) == (5, 6)

assert public_optional_args[mystruct_t, float](mystruct) == (5, 6.0)
assert public_optional_args[mystruct_t, float](mystruct, 7.0) == (5, 7.0)


cdef TestFusedExtMethods obj = TestFusedExtMethods()

cdef int x = 4
cdef float y = 5.0
cdef long a = 6
cdef double b = 7.0

cdef double (*func)(TestFusedExtMethods, long, double)

func = obj.method

result = func(obj, a, b)
assert result == 15.0, result

func =  obj.method
assert func(obj, x, y) == 11.0

func = obj.method[long, double]
assert func(obj, a, y) == 13.0

assert obj.method(x,  a) == 13.0
assert obj.method[int, double](x, b) == 14.0


# Test inheritance
cdef class Subclass(TestFusedExtMethods):
    cdef cython.floating method(self, cython.integral x, cython.floating y):
        return -x -y

    cpdef cpdef_method(self, cython.integral x, cython.floating y):
        return x, y

cdef Subclass myobj = Subclass()
assert myobj.method[int, float](5, 5.0) == -10

cdef float (*meth)(Subclass, int, float)
meth = myobj.method
assert meth(myobj, 5, 5.0) == -10

meth = myobj.method[int, float]
assert meth(myobj, 5, 5.0) == -10


# Test cpdef functions and methods
cy = __import__("cython")
import a as a_mod

def ae(result, expected):
    "assert equals"
    if result != expected:
        print('result  :', result)
        print('expected:', expected)

    assert result == expected

ae(a_mod.public_cpdef[int, float, list](5, 6, [7]), ("int", "float", "list object"))

idx = cy.typeof(0), cy.typeof(0.0), cy.typeof([])
ae(a_mod.public_cpdef[idx](5, 6, [7]), ("int", "float", "list object"))

ae(a_mod.public_cpdef[cy.int, cy.double, cython.typeof(obj)](5, 6, obj), ("int", "double", "TestFusedExtMethods"))
ae(a_mod.public_cpdef[cy.int, cy.double, cython.typeof(obj)](5, 6, myobj), ("int", "double", "TestFusedExtMethods"))

ae(public_cpdef[int, float, list](5, 6, [7]), ("int", "float", "list object"))
ae(public_cpdef[int, double, TestFusedExtMethods](5, 6, obj), ("int", "double", "TestFusedExtMethods"))
ae(public_cpdef[int, double, TestFusedExtMethods](5, 6, myobj), ("int", "double", "TestFusedExtMethods"))

ae(obj.cpdef_method(10, 10.0), ("long", "double"))
ae(myobj.cpdef_method(10, 10.0), (10, 10.0))
ae(obj.cpdef_method[int, float](10, 10.0), ("int", "float"))
ae(myobj.cpdef_method[int, float](10, 10.0), (10, 10.0))

s = """\
import cython as cy

ae(obj.cpdef_method[cy.int, cy.float](10, 10.0), ("int", "float"))
ae(myobj.cpdef_method[cy.int, cy.float](10, 10.0), (10, 10.0))
"""

d = {'obj': obj, 'myobj': myobj, 'ae': ae}

exec(s, d)

# Test def methods
# ae(obj.def_method(12, 14.9), 26)
# ae(obj.def_method(13, "spam"), (13, "spam"))
# ae(obj.def_method[cy.short, cy.float](13, 16.3), 29)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pure.pyx0000644000175100001770000001435000000000000017262 0ustar00runnerdocker00000000000000# mode: run
# tag: warnings

import cython

def test_sizeof():
    """
    >>> test_sizeof()
    True
    True
    True
    True
    True
    """
    x = cython.declare(cython.bint)
    print sizeof(x) == sizeof(cython.bint)
    print sizeof(cython.char) <= sizeof(cython.short) <= sizeof(cython.int) <= sizeof(cython.long) <= sizeof(cython.longlong)
    print sizeof(cython.uint) == sizeof(cython.int)
    print sizeof(cython.p_int) == sizeof(cython.p_double)
    if cython.compiled:
        print sizeof(cython.char) < sizeof(cython.longlong)
    else:
        print sizeof(cython.char) == 1

def test_declare(n):
    """
    >>> test_declare(100)
    (100, 100)
    >>> test_declare(100.5)
    (100, 100)

    # CPython: "TypeError: an integer is required"
    >>> test_declare(None) # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: ...int...
    """
    x = cython.declare(cython.int)
    y = cython.declare(cython.int, n)
    if cython.compiled:
        cython.declare(xx=cython.int, yy=cython.long)
        i = sizeof(xx)
    ptr = cython.declare(cython.p_int, cython.address(y))
    return y, ptr[0]

@cython.locals(x=cython.double, n=cython.int)
def test_cast(x):
    """
    >>> test_cast(1.5)
    1
    >>> try: test_cast(None)
    ... except TypeError: pass
    """
    n = cython.cast(cython.int, x)
    return n

@cython.locals(as_list=list)
def test_cast_object(x, typecheck):
    """
    >>> test_cast_object([1, 2, 3], True)
    [1, 2, 3]
    >>> test_cast_object([1, 2, 3], False)
    [1, 2, 3]
    >>> test_cast_object((1, 2, 3), True)
    Traceback (most recent call last):
    ...
    TypeError: Expected list, got tuple
    >>> test_cast_object((1, 2, 3), False)
    (1, 2, 3)
    """
    if typecheck:
        as_list = cython.cast(list, x, typecheck=True)
    else:
        as_list = cython.cast(list, x, typecheck=False)
    return as_list

@cython.locals(x=cython.int, y=cython.p_int)
def test_address(x):
    """
    >>> test_address(39)
    39
    """
    y = cython.address(x)
    return y[0]

@cython.locals(x=cython.int)
@cython.locals(y=cython.bint)
def test_locals(x):
    """
    >>> test_locals(5)
    True
    """
    y = x
    return y

MyUnion = cython.union(n=cython.int, x=cython.double)
MyStruct = cython.struct(is_integral=cython.bint, data=MyUnion)
MyStruct2 = cython.typedef(MyStruct[2])

def test_struct(n, x):
    """
    >>> test_struct(389, 1.64493)
    (389, 1.64493)
    """
    a = cython.declare(MyStruct2)
    a[0] = MyStruct(True, data=MyUnion(n=n))
    a[1] = MyStruct(is_integral=False, data={'x': x})
    return a[0].data.n, a[1].data.x

import cython as cy
from cython import declare, cast, locals, address, typedef, p_void, compiled
from cython import declare as my_declare, locals as my_locals, p_void as my_void_star, typedef as my_typedef, compiled as my_compiled

@my_locals(a=cython.p_void)
def test_imports():
    """
    >>> test_imports()
    True
    """
    a = cython.NULL
    b = declare(p_void, cython.NULL)
    c = my_declare(my_void_star, cython.NULL)
    d = cy.declare(cy.p_void, cython.NULL)
    return a == d and compiled and my_compiled

MyStruct3 = typedef(MyStruct[3])
MyStruct4 = my_typedef(MyStruct[4])
MyStruct5 = cy.typedef(MyStruct[5])

def test_declare_c_types(n):
    """
    >>> test_declare_c_types(0)
    >>> test_declare_c_types(1)
    >>> test_declare_c_types(2)
    """
    #
    b00 = cython.declare(cython.bint, 0)
    b01 = cython.declare(cython.bint, 1)
    b02 = cython.declare(cython.bint, 2)
    #
    i00 = cython.declare(cython.uchar, n)
    i01 = cython.declare(cython.char, n)
    i02 = cython.declare(cython.schar, n)
    i03 = cython.declare(cython.ushort, n)
    i04 = cython.declare(cython.short, n)
    i05 = cython.declare(cython.sshort, n)
    i06 = cython.declare(cython.uint, n)
    i07 = cython.declare(cython.int, n)
    i08 = cython.declare(cython.sint, n)
    i09 = cython.declare(cython.slong, n)
    i10 = cython.declare(cython.long, n)
    i11 = cython.declare(cython.ulong, n)
    i12 = cython.declare(cython.slonglong, n)
    i13 = cython.declare(cython.longlong, n)
    i14 = cython.declare(cython.ulonglong, n)

    i20 = cython.declare(cython.Py_ssize_t, n)
    i21 = cython.declare(cython.size_t, n)
    #
    f00 = cython.declare(cython.float, n)
    f01 = cython.declare(cython.double, n)
    f02 = cython.declare(cython.longdouble, n)
    #
    #z00 = cython.declare(cython.complex, n+1j)
    #z01 = cython.declare(cython.floatcomplex, n+1j)
    #z02 = cython.declare(cython.doublecomplex, n+1j)
    #z03 = cython.declare(cython.longdoublecomplex, n+1j)


cdef class ExtType:
    """
    >>> x = ExtType()
    >>> x.forward_ref(x)
    'ExtType'
    """
    @cython.locals(x="ExtType")
    def forward_ref(self, x):
        return cython.typeof(x)


def ext_type_string_ref(x: "ExtType"):
    """
    >>> x = ExtType()
    >>> ext_type_string_ref(x)
    'ExtType'
    """
    return cython.typeof(x)


with cython.cdivision(True):

    @cython.cdivision(False)
    @cython.cdivision(True)
    def test_override_reset(x: cython.int):
        """
        >>> test_override_reset(-3)  # @cdivision(False)
        -2
        """
        return x / 2

    @cython.cdivision(True)
    @cython.cdivision(False)
    def test_override_set(x: cython.int):
        """
        >>> test_override_set(-5)  # @cdivision(True)
        -1
        """
        return x / 3

    @cython.cdivision(True)
    @cython.cdivision(False)
    @cython.cdivision(True)
    @cython.cdivision(False)
    @cython.cdivision(False)
    @cython.cdivision(False)
    @cython.cdivision(True)
    @cython.cdivision(False)
    @cython.cdivision(True)
    @cython.cdivision(True)
    @cython.cdivision(True)
    @cython.cdivision(False)
    def test_override_set_repeated(x: cython.int):
        """
        >>> test_override_set_repeated(-5)  # @cdivision(True)
        -1
        """
        return x / 3


_WARNINGS = """
181:27: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
193:4: Directive does not change previous value (cdivision=True)
213:4: Directive does not change previous value (cdivision=False)
214:4: Directive does not change previous value (cdivision=False)
218:4: Directive does not change previous value (cdivision=True)
219:4: Directive does not change previous value (cdivision=True)
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pure_cdef_class_dataclass.py0000644000175100001770000000453600000000000023264 0ustar00runnerdocker00000000000000# mode: run
# tag: dataclass, pure3.7

from __future__ import print_function

import cython

# cython.dataclasses implicitly implies cclass
@cython.dataclasses.dataclass(order=True, unsafe_hash=True)
class MyDataclass:
    """
    >>> sorted(list(MyDataclass.__dataclass_fields__.keys()))
    ['a', 'self']
    >>> inst1 = MyDataclass(2, ['a', 'b'])
    >>> print(inst1)
    MyDataclass(a=2, self=['a', 'b'])
    >>> inst2 = MyDataclass()
    >>> print(inst2)
    MyDataclass(a=1, self=[])
    >>> inst1 == inst2
    False
    >>> inst1 > inst2
    True
    >>> inst2 == MyDataclass()
    True
    >>> hash(inst1) != id(inst1)
    True
    >>> inst1.func_with_annotations(2.0)
    4.0
    """

    a: int = 1
    self: list = cython.dataclasses.field(default_factory=list, hash=False)  # test that arguments of init don't conflict

    def func_with_annotations(self, b: float):
        c: float = b
        return self.a * c


class DummyObj:
    def __repr__(self):
        return "DummyObj()"


@cython.dataclasses.dataclass
@cython.cclass
class NoInitFields:
    """
    >>> NoInitFields()
    NoInitFields(has_default=DummyObj(), has_factory='From a lambda', neither=None)
    >>> NoInitFields().has_default is NoInitFields().has_default
    True

    >>> NoInitFields(1)  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    TypeError: NoInitFields.__init__() takes 1 positional argument but 2 were given

    >>> NoInitFields(has_default=1)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...has_default...
    >>> NoInitFields(has_factory=1)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...has_factory...
    >>> NoInitFields(neither=1)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...neither...
    """
    has_default : object = cython.dataclasses.field(default=DummyObj(), init=False)
    has_factory : object = cython.dataclasses.field(default_factory=lambda: "From a lambda", init=False)
    # Cython will default-initialize to None
    neither : object = cython.dataclasses.field(init=False)

    def __post_init__(self):
        if not cython.compiled:
            # Cython will default-initialize this to None, while Python won't
            # and not initializing it will mess up repr
            assert not hasattr(self, "neither")
            self.neither = None
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pure_cdef_class_property_decorator_T264.pxd0000644000175100001770000000013000000000000026117 0ustar00runnerdocker00000000000000# mode: run
# ticket: t264
# tag: property, decorator

cdef class Prop:
    cdef _value
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pure_cdef_class_property_decorator_T264.py0000644000175100001770000000166100000000000025766 0ustar00runnerdocker00000000000000# mode: run
# ticket: t264
# tag: property, decorator

class Prop(object):
    """
    >>> p = Prop()
    >>> p.prop
    GETTING 'None'
    >>> p.prop = 1
    SETTING '1' (previously: 'None')
    >>> p.prop
    GETTING '1'
    1
    >>> p.prop = 2
    SETTING '2' (previously: '1')
    >>> p.prop
    GETTING '2'
    2
    >>> del p.prop
    DELETING '2'
    >>> p.prop
    GETTING 'None'
    """

    def __init__(self):
        self._value = None

    @property
    def prop(self):
        print("FAIL")
        return 0

    @prop.getter
    def prop(self):
        print("FAIL")

    @property
    def prop(self):
        print("GETTING '%s'" % self._value)
        return self._value

    @prop.setter
    def prop(self, value):
        print("SETTING '%s' (previously: '%s')" % (value, self._value))
        self._value = value

    @prop.deleter
    def prop(self):
        print("DELETING '%s'" % self._value)
        self._value = None
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pure_fused.pxd0000644000175100001770000000022500000000000020417 0ustar00runnerdocker00000000000000cimport cython

ctypedef fused NotInPy:
    int
    float

cdef class TestCls:
    @cython.locals(loc = NotInPy)
    cpdef cpfunc(self, NotInPy arg)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pure_fused.py0000644000175100001770000000300600000000000020254 0ustar00runnerdocker00000000000000# mode: run
# tag: fused, pure3.6

#cython: annotation_typing=True

import cython

InPy = cython.fused_type(cython.int, cython.float)

class TestCls:
    # although annotations as strings isn't recommended and generates a warning
    # it does allow the test to run on more (pure) Python versions
    def func1(self, arg: 'NotInPy'):
        """
        >>> TestCls().func1(1.0)
        'float'
        >>> TestCls().func1(2)
        'int'
        """
        loc: 'NotInPy' = arg
        return cython.typeof(arg)

    if cython.compiled:
        @cython.locals(arg=NotInPy, loc=NotInPy)  # NameError for 'NotInPy' in pure Python
        def func2(self, arg):
            """
            >>> TestCls().func2(1.0)
            'float'
            >>> TestCls().func2(2)
            'int'
            """
            loc = arg
            return cython.typeof(arg)

    def cpfunc(self, arg):
        """
        >>> TestCls().cpfunc(1.0)
        'float'
        >>> TestCls().cpfunc(2)
        'int'
        """
        loc = arg
        return cython.typeof(arg)

    def func1_inpy(self, arg: InPy):
        """
        >>> TestCls().func1_inpy(1.0)
        'float'
        >>> TestCls().func1_inpy(2)
        'int'
        """
        loc: InPy = arg
        return cython.typeof(arg)

    @cython.locals(arg = InPy, loc = InPy)
    def func2_inpy(self, arg):
        """
        >>> TestCls().func2_inpy(1.0)
        'float'
        >>> TestCls().func2_inpy(2)
        'int'
        """
        loc = arg
        return cython.typeof(arg)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pure_mode_cmethod_inheritance_T583.pxd0000644000175100001770000000071100000000000025034 0ustar00runnerdocker00000000000000cdef class Base:
    cpdef str noargs(self)
    cpdef str int_arg(self, int i)
    cpdef str _class(tp)

cdef class Derived(Base):
    cpdef str noargs(self)
    cpdef str int_arg(self, int i)
    cpdef str _class(tp)

cdef class DerivedDerived(Derived):
    cpdef str noargs(self)
    cpdef str int_arg(self, int i)
    cpdef str _class(tp)

cdef class Derived2(Base):
    cpdef str noargs(self)
    cpdef str int_arg(self, int i)
    cpdef str _class(tp)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pure_mode_cmethod_inheritance_T583.py0000644000175100001770000000270300000000000024674 0ustar00runnerdocker00000000000000class Base(object):
    '''
    >>> base = Base()
    >>> print(base.noargs())
    Base
    >>> print(base.int_arg(1))
    Base
    >>> print(base._class())
    Base
    '''
    def noargs(self):
        return "Base"
    def int_arg(self, i):
        return "Base"
    @classmethod
    def _class(tp):
        return "Base"


class Derived(Base):
    '''
    >>> derived = Derived()
    >>> print(derived.noargs())
    Derived
    >>> print(derived.int_arg(1))
    Derived
    >>> print(derived._class())
    Derived
    '''
    def noargs(self):
        return "Derived"
    def int_arg(self, i):
        return "Derived"
    @classmethod
    def _class(tp):
        return "Derived"


class DerivedDerived(Derived):
    '''
    >>> derived = DerivedDerived()
    >>> print(derived.noargs())
    DerivedDerived
    >>> print(derived.int_arg(1))
    DerivedDerived
    >>> print(derived._class())
    DerivedDerived
    '''
    def noargs(self):
        return "DerivedDerived"
    def int_arg(self, i):
        return "DerivedDerived"
    @classmethod
    def _class(tp):
        return "DerivedDerived"


class Derived2(Base):
    '''
    >>> derived = Derived2()
    >>> print(derived.noargs())
    Derived2
    >>> print(derived.int_arg(1))
    Derived2
    >>> print(derived._class())
    Derived2
    '''
    def noargs(self):
        return "Derived2"
    def int_arg(self, i):
        return "Derived2"
    @classmethod
    def _class(tp):
        return "Derived2"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pure_nogil_conditional.pyx0000644000175100001770000001224200000000000023033 0ustar00runnerdocker00000000000000# mode: run
# tag: pure, nogil

import cython

try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO


def test(x: cython.int):
    """
    >>> test(0)
    110
    """
    with cython.nogil(True):
        x = f_nogil(x)
        with cython.gil(True):
            x = f_gil(x)
    return x


@cython.nogil
@cython.cfunc
def f_nogil(x: cython.int) -> cython.int:
    y: cython.int
    y = x + 10
    return y


def f_gil(x):
    y = 0
    y = x + 100
    return y


@cython.with_gil
@cython.cfunc
def f_with_gil(x: cython.int) -> cython.int:
    return x + len([1, 2] * x)


def test_with_gil(x: cython.int):
    """
    >>> test_with_gil(3)
    9
    """
    with cython.nogil:
        result = f_with_gil(x)
    return result


@cython.nogil
@cython.exceptval(check=False)
@cython.cfunc
def write_unraisable() -> cython.int:
    with cython.gil:
        raise ValueError()


def test_unraisable():
    """
    >>> print(test_unraisable())  # doctest: +ELLIPSIS
    ValueError
    Exception...ignored...
    """
    import sys
    old_stderr = sys.stderr
    stderr = sys.stderr = StringIO()
    try:
        write_unraisable()
    finally:
        sys.stderr = old_stderr
    return stderr.getvalue().strip()


def test_nested():
    """
    >>> test_nested()
    240
    """
    res: cython.int = 0

    with cython.nogil(True):
        res = f_nogil(res)
        with cython.gil:
            res = f_gil(res)
            with cython.nogil:
                res = f_nogil(res)

        with cython.gil:
            res = f_gil(res)
            with cython.nogil(True):
                res = f_nogil(res)
            with cython.nogil:
                res = f_nogil(res)

    return res


def test_try_finally():
    """
    >>> test_try_finally()
    113
    """
    res: cython.int = 0

    try:
        with cython.nogil(True):
            try:
                res = f_nogil(res)
                with cython.gil:
                    try:
                        res = f_gil(res)
                    finally:
                        res += 1
            finally:
                res = res + 1
    finally:
        res += 1

    return res


number_or_object = cython.fused_type(cython.int, cython.float, object)


def test_fused(x: number_or_object) -> number_or_object:
    """
    >>> test_fused["int"](1)
    2
    >>> test_fused["float"](1.0)
    2.0
    >>> test_fused[object](1)
    2
    >>> test_fused[object](1.0)
    2.0
    """
    res: number_or_object = x

    with cython.nogil(number_or_object is not object):
        res = res + 1

    return res


int_or_object = cython.fused_type(cython.int, object)


def test_fused_object(x: int_or_object):
    """
    >>> import cython
    >>> test_fused_object[object]("spam")
    456
    >>> test_fused_object["int"](1000)
    1000
    """
    res: cython.int = 0

    if int_or_object is object:
        with cython.nogil(False):
            res += len(x)

        try:
            with cython.nogil(int_or_object is object):
                try:
                    with cython.gil(int_or_object is object):
                        res = f_gil(res)
                    with cython.gil:
                        res = f_gil(res)
                    with cython.gil(False):
                        res = f_nogil(res)

                    with cython.gil(int_or_object is not object):
                        res = f_nogil(res)
                    with cython.nogil(False):
                        res = f_nogil(res)

                    res = f_nogil(res)
                finally:
                    res = res + 1

            with cython.nogil(int_or_object is not object):
                res = f_gil(res)

            with cython.gil(int_or_object is not object):
                res = f_gil(res)

                with cython.nogil(int_or_object is object):
                    res = f_nogil(res)

        finally:
            res += 1
    else:
        res = x

    return res


def test_fused_int(x: int_or_object):
    """
    >>> import cython
    >>> test_fused_int[object]("spam")
    4
    >>> test_fused_int["int"](1000)
    1452
    """
    res: cython.int = 0

    if int_or_object is cython.int:
        res += x

        try:
            with cython.nogil(int_or_object is cython.int):
                try:
                    with cython.gil(int_or_object is int):
                        res = f_gil(res)
                    with cython.gil:
                        res = f_gil(res)
                    with cython.gil(False):
                        res = f_nogil(res)

                    with cython.gil(int_or_object is not int):
                        res = f_nogil(res)
                    with cython.nogil(False):
                        res = f_nogil(res)

                    res = f_nogil(res)
                finally:
                    res = res + 1

            with cython.nogil(int_or_object is not cython.int):
                res = f_gil(res)

            with cython.gil(int_or_object is not int):
                res = f_gil(res)

                with cython.nogil(int_or_object is int):
                    res = f_nogil(res)

        finally:
            res += 1
    else:
        with cython.nogil(False):
            res = len(x)

    return res
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pure_parallel.py0000644000175100001770000000213200000000000020741 0ustar00runnerdocker00000000000000# mode: run
# tag: openmp, pure3.6

import cython
from cython.parallel import prange, parallel


def prange_regression(n: cython.int, data: list):
    """
    >>> prange_regression(10, list(range(1, 4)))
    19
    """
    s: cython.int = 0
    i: cython.int
    d: cython.int[3] = data

    for i in prange(n, num_threads=3, nogil=True):
        s += d[i % 3]
    return s


def prange_with_gil(n: cython.int, x):
    """
    >>> sum(3*i for i in range(10))
    135
    >>> prange_with_gil(10, 3)
    135
    """
    i: cython.int
    s: cython.int = 0

    for i in prange(n, num_threads=3, nogil=True):
        with cython.gil:
            s += x * i

    return s


@cython.cfunc
def use_nogil(x, i: cython.int) -> cython.int:
    cx: cython.int = x
    with cython.nogil:
        return cx * i


def prange_with_gil_call_nogil(n: cython.int, x):
    """
    >>> sum(3*i for i in range(10))
    135
    >>> prange_with_gil(10, 3)
    135
    """
    i: cython.int
    s: cython.int = 0

    for i in prange(n, num_threads=3, nogil=True):
        with cython.gil:
            s += use_nogil(x, i)

    return s
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pure_pxd.srctree0000644000175100001770000000421700000000000020765 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import a; a.test(a)"

######## setup.py ########

from Cython.Build.Dependencies import cythonize

from distutils.core import setup

setup(
    ext_modules=cythonize("a.py"),
)


######## a.py ########

class ExtTypePass(object):
    pass


class ExtTypePxdDocstring(object):
    pass


class ExtTypeDocstring(object):
    """huhu!"""  # this should override the .pxd docstring


class ExtTypeAttributes(object):
    """
    >>> x = ExtTypeAttributes()
    >>> x.b
    [1, 2, 3]
    """
    def __init__(self):
        self.a = 123
        self.b = [1, 2, 3]


class TypedMethod():
    """
    >>> t = TypedMethod()
    >>> t.meth()
    97
    """
    def meth(self):
        x = bytearray(b'abcdefg')
        return x[0]


def func(a, b, c):
    """
    >>> func(1, 2, 3)
    6
    """
    return a + b + c

def sum_generator_expression(a):
    # GH-3477 - closure variables incorrectly captured in functions transformed to cdef
    return sum(i for i in range(a))

def run_sum_generator_expression(a):
    """
    >>> run_sum_generator_expression(5)
    10
    """
    return sum_generator_expression(a)


def test(module):
    import os.path
    assert not os.path.basename(__file__).endswith('.py'), __file__
    assert not os.path.basename(__file__).endswith('.pyc'), __file__
    assert not os.path.basename(__file__).endswith('.pyo'), __file__

    assert not ExtTypePass().__doc__, ExtTypePass().__doc__
    assert ExtTypeDocstring().__doc__ == "huhu!", ExtTypeDocstring().__doc__
    assert ExtTypePxdDocstring().__doc__ == "ho, ho, ho!", ExtTypePxdDocstring().__doc__
    assert '>>> ' in func.__doc__

    import doctest
    result = doctest.testmod(module, verbose=True)
    assert not result.failed, result.failed


######## a.pxd ########

cimport cython

cdef class ExtTypePass:
    pass


cdef class ExtTypePxdDocstring:
    """ho, ho, ho!"""


cdef class ExtTypeAttributes:
    cdef int a
    cdef readonly list b


cdef class TypedMethod:
    @cython.locals(x='char[:]')
    cpdef meth(self)


cpdef int func(x, int y, z) except? -1  # argument names should not matter, types should


cdef int sum_generator_expression(int a)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pure_py.py0000644000175100001770000003240000000000000017576 0ustar00runnerdocker00000000000000# mode: run

import sys
IS_PY2 = sys.version_info[0] < 3

import cython
from cython import sizeof

is_compiled = cython.compiled

NULL = 5
_NULL = NULL


def test_sizeof():
    """
    >>> test_sizeof()
    True
    True
    True
    True
    True
    """
    x = cython.declare(cython.bint)
    print(cython.sizeof(x) == cython.sizeof(cython.bint))
    print(sizeof(cython.char) <= sizeof(cython.short) <= sizeof(cython.int) <= sizeof(cython.long) <= sizeof(cython.longlong))
    print(cython.sizeof(cython.uint) == cython.sizeof(cython.int))
    print(cython.sizeof(cython.p_int) == cython.sizeof(cython.p_double))
    if cython.compiled:
        print(cython.sizeof(cython.char) < cython.sizeof(cython.longlong))
    else:
        print(cython.sizeof(cython.char) == 1)


def test_declare(n):
    """
    >>> test_declare(100)
    (100, 100, 100)
    >>> test_declare(100.5)
    (100, 100, 100)
    """
    x = cython.declare(cython.int)
    y = cython.declare(cython.int, n)
    z = cython.declare(int, n)  # C int
    if cython.compiled:
        cython.declare(xx=cython.int, yy=cython.long)
        i = cython.sizeof(xx)
    ptr = cython.declare(cython.p_int, cython.address(y))
    return y, z, ptr[0]


@cython.locals(x=cython.double, n=cython.int)
def test_cast(x):
    """
    >>> test_cast(1.5)
    1
    """
    n = cython.cast(cython.int, x)
    return n


@cython.locals(x=cython.int, y=cython.p_int)
def test_address(x):
    """
    >>> test_address(39)
    39
    """
    y = cython.address(x)
    return y[0]


@cython.wraparound(False)
def test_wraparound(x):
    """
    >>> test_wraparound([1, 2, 3])
    [1, 2, 1]
    """
    with cython.wraparound(True):
        x[-1] = x[0]
    return x


@cython.boundscheck(False)
def test_boundscheck(x):
    """
    >>> test_boundscheck([1, 2, 3])
    3
    >>> try: test_boundscheck([1, 2])
    ... except IndexError: pass
    """
    with cython.boundscheck(True):
        return x[2]


## CURRENTLY BROKEN - FIXME!!
## Is this test make sense? Implicit conversion in pure Python??

## @cython.locals(x=cython.int)
## @cython.locals(y=cython.bint)
## def test_locals(x):
##     """
##     >>> test_locals(5)
##     True
##     """
##     y = x
##     return y


def test_with_nogil(nogil, should_raise=False):
    """
    >>> raised = []
    >>> class nogil(object):
    ...     def __enter__(self):
    ...         pass
    ...     def __exit__(self, exc_class, exc, tb):
    ...         raised.append(exc)
    ...         return exc_class is None

    >>> test_with_nogil(nogil())
    WORKS
    True
    >>> raised
    [None]

    >>> test_with_nogil(nogil(), should_raise=True)
    Traceback (most recent call last):
    ValueError: RAISED!

    >>> raised[1] is None
    False
    """
    result = False
    should_raise_bool = True if should_raise else False  # help the type inference ...
    with nogil:
        print("WORKS")
        with cython.nogil:
            result = True
            if should_raise_bool:
                raise ValueError("RAISED!")
    return result


MyUnion = cython.union(n=cython.int, x=cython.double)
MyStruct = cython.struct(is_integral=cython.bint, data=MyUnion)
MyStruct2 = cython.typedef(MyStruct[2])
MyStruct3 = cython.typedef(MyStruct[3])

def test_struct(n, x):
    """
    >>> test_struct(389, 1.64493)
    (389, 1.64493, False)
    """
    a = cython.declare(MyStruct3)
    a[0] = MyStruct(is_integral=True, data=MyUnion(n=n))
    a[1] = MyStruct(is_integral=False, data={'x': x})
    if sys.version_info >= (3, 6):
        # dict is ordered => struct creation via keyword arguments above was deterministic!
        a[2] = MyStruct(False, MyUnion(x=x))
    else:
        a[2] = MyStruct(is_integral=False, data=MyUnion(x=x))
    return a[0].data.n, a[1].data.x, a[2].is_integral

import cython as cy
from cython import declare, cast, locals, address, typedef, p_void, compiled
from cython import declare as my_declare, locals as my_locals, p_void as my_void_star, typedef as my_typedef, compiled as my_compiled

@my_locals(a=cython.p_void)
def test_imports():
    """
    >>> test_imports()
    (True, True)
    """
    a = cython.NULL
    b = declare(p_void, cython.NULL)
    c = my_declare(my_void_star, cython.NULL)
    d = cy.declare(cy.p_void, cython.NULL)

    return a == d, compiled == my_compiled

## CURRENTLY BROKEN - FIXME!!

# MyStruct3 = typedef(MyStruct[3])
# MyStruct4 = my_typedef(MyStruct[4])
# MyStruct5 = cy.typedef(MyStruct[5])

def test_declare_c_types(n):
    """
    >>> test_declare_c_types(0)
    >>> test_declare_c_types(1)
    >>> test_declare_c_types(2)
    """
    #
    b00 = cython.declare(cython.bint, 0)
    b01 = cython.declare(cython.bint, 1)
    b02 = cython.declare(cython.bint, 2)
    #
    i00 = cython.declare(cython.uchar, n)
    i01 = cython.declare(cython.char, n)
    i02 = cython.declare(cython.schar, n)
    i03 = cython.declare(cython.ushort, n)
    i04 = cython.declare(cython.short, n)
    i05 = cython.declare(cython.sshort, n)
    i06 = cython.declare(cython.uint, n)
    i07 = cython.declare(cython.int, n)
    i08 = cython.declare(cython.sint, n)
    i09 = cython.declare(cython.slong, n)
    i10 = cython.declare(cython.long, n)
    i11 = cython.declare(cython.ulong, n)
    i12 = cython.declare(cython.slonglong, n)
    i13 = cython.declare(cython.longlong, n)
    i14 = cython.declare(cython.ulonglong, n)

    i20 = cython.declare(cython.Py_ssize_t, n)
    i21 = cython.declare(cython.size_t, n)
    #
    f00 = cython.declare(cython.float, n)
    f01 = cython.declare(cython.double, n)
    f02 = cython.declare(cython.longdouble, n)
    #
    #z00 = cython.declare(cython.complex, n+1j)
    #z01 = cython.declare(cython.floatcomplex, n+1j)
    #z02 = cython.declare(cython.doublecomplex, n+1j)
    #z03 = cython.declare(cython.longdoublecomplex, n+1j)


@cython.ccall
@cython.returns(cython.double)
def c_call(x):
    if x == -2.0:
        raise RuntimeError("huhu!")
    return x


def call_ccall(x):
    """
    Test that a declared return type is honoured when compiled.

    >>> result, return_type = call_ccall(1)

    >>> (not is_compiled and 'double') or return_type
    'double'
    >>> (is_compiled and 'int') or return_type
    'int'

    >>> (not is_compiled and 1.0) or result
    1.0
    >>> (is_compiled and 1) or result
    1

    >>> call_ccall(-2)
    Traceback (most recent call last):
    RuntimeError: huhu!
    """
    ret = c_call(x)
    return ret, cython.typeof(ret)


@cython.cfunc
@cython.inline
@cython.returns(cython.double)
def cdef_inline(x):
    if x == -2.0:
        raise RuntimeError("huhu!")
    return x + 1


def call_cdef_inline(x):
    """
    >>> result, return_type = call_cdef_inline(1)
    >>> (not is_compiled and 'float') or type(result).__name__
    'float'
    >>> (not is_compiled and 'double') or return_type
    'double'
    >>> (is_compiled and 'int') or return_type
    'int'
    >>> result == 2.0  or  result
    True

    >>> call_cdef_inline(-2)
    Traceback (most recent call last):
    RuntimeError: huhu!
    """
    ret = cdef_inline(x)
    return ret, cython.typeof(ret)


@cython.cfunc
@cython.nogil
@cython.locals(x=cython.int)
@cython.returns(cython.int)
def cdef_nogil(x):
    return x + 1


@cython.cfunc
@cython.nogil(True)
@cython.locals(x=cython.int)
@cython.returns(cython.int)
def cdef_nogil_true(x):
    return x + 1


@cython.cfunc
@cython.nogil(False)
@cython.locals(x=cython.int)
@cython.returns(cython.int)
def cdef_nogil_false(x):
    return x + 1


@cython.locals(x=cython.int, result=cython.int)
def test_cdef_nogil(x):
    """
    >>> test_cdef_nogil(5)
    18
    """
    with cython.nogil:
        result = cdef_nogil(x)
    with cython.nogil(True):
        result += cdef_nogil_true(x)
    result += cdef_nogil_false(x)
    return result


@cython.cfunc
@cython.inline
def has_inner_func(x):
    # the inner function must remain a Python function
    # (and inline must not be applied to it)
    @cython.test_fail_if_path_exists("//CFuncDefNode")
    def inner():
        return x
    return inner


def test_has_inner_func():
    """
    >>> test_has_inner_func()
    1
    """
    return has_inner_func(1)()


@cython.locals(counts=cython.int[10], digit=cython.int)
def count_digits_in_carray(digits):
    """
    >>> digits = '37692837651902834128342341'
    >>> ''.join(sorted(digits))
    '01112222333334445667788899'
    >>> count_digits_in_carray(map(int, digits))
    [1, 3, 4, 5, 3, 1, 2, 2, 3, 2]
    """
    counts = [0] * 10
    for digit in digits:
        assert 0 <= digit <= 9
        counts[digit] += 1
    return counts


@cython.test_assert_path_exists("//CFuncDeclaratorNode//IntNode[@base_10_value = '-1']")
@cython.ccall
@cython.returns(cython.long)
@cython.exceptval(-1)
def ccall_except(x):
    """
    >>> ccall_except(41)
    42
    >>> ccall_except(0)
    Traceback (most recent call last):
    ValueError
    """
    if x == 0:
        raise ValueError
    return x+1


@cython.test_assert_path_exists("//CFuncDeclaratorNode//IntNode[@base_10_value = '-1']")
@cython.cfunc
@cython.returns(cython.long)
@cython.exceptval(-1)
def cdef_except(x):
    if x == 0:
        raise ValueError
    return x+1


def call_cdef_except(x):
    """
    >>> call_cdef_except(41)
    42
    >>> call_cdef_except(0)
    Traceback (most recent call last):
    ValueError
    """
    return cdef_except(x)


@cython.test_assert_path_exists("//CFuncDeclaratorNode//IntNode[@base_10_value = '-1']")
@cython.ccall
@cython.returns(cython.long)
@cython.exceptval(-1, check=True)
def ccall_except_check(x):
    """
    >>> ccall_except_check(41)
    42
    >>> ccall_except_check(-2)
    -1
    >>> ccall_except_check(0)
    Traceback (most recent call last):
    ValueError
    """
    if x == 0:
        raise ValueError
    return x+1


@cython.test_fail_if_path_exists("//CFuncDeclaratorNode//IntNode[@base_10_value = '-1']")
@cython.test_assert_path_exists("//CFuncDeclaratorNode")
@cython.ccall
@cython.returns(cython.long)
@cython.exceptval(check=True)
def ccall_except_check_always(x):
    """
    >>> ccall_except_check_always(41)
    42
    >>> ccall_except_check_always(0)
    Traceback (most recent call last):
    ValueError
    """
    if x == 0:
        raise ValueError
    return x+1


@cython.test_fail_if_path_exists("//CFuncDeclaratorNode//IntNode[@base_10_value = '-1']")
@cython.test_assert_path_exists("//CFuncDeclaratorNode")
@cython.ccall
@cython.returns(cython.long)
@cython.exceptval(check=False)
def ccall_except_no_check(x):
    """
    >>> ccall_except_no_check(41)
    42
    >>> try: _ = ccall_except_no_check(0)  # no exception propagated!
    ... except ValueError: assert not is_compiled
    """
    if x == 0:
        raise ValueError
    return x+1


@cython.final
@cython.cclass
class CClass(object):
    """
    >>> c = CClass(2)
    >>> c.get_attr()
    int
    2
    """
    cython.declare(attr=cython.int)

    def __init__(self, attr):
        self.attr = attr

    def get_attr(self):
        print(cython.typeof(self.attr))
        return self.attr


class TestUnboundMethod:
    """
    >>> C = TestUnboundMethod
    >>> IS_PY2 or (C.meth is C.__dict__["meth"])
    True
    """
    def meth(self): pass

@cython.cclass
class Foo:
    a = cython.declare(cython.double)
    b = cython.declare(cython.double)
    c = cython.declare(cython.double)

    @cython.locals(a=cython.double, b=cython.double, c=cython.double)
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

@cython.cclass
class EmptyClass(object):
    def __init__(self, *args):
        pass

def same_type_cast():
    """
    >>> same_type_cast()
    True
    """

    f = EmptyClass()
    return f is cython.cast(EmptyClass, f)

def multi_args_init_cast():
    """
    >>> multi_args_init_cast()
    True
    """
    f = Foo(10, 20, 30)
    return cython.cast(Foo, f) is f

def multi_args_init_declare():
    """
    >>> multi_args_init_declare() is None
    True
    """
    f = cython.declare(Foo)

    if cython.compiled:
        f = None

    return f

EmptyClassSyn = cython.typedef(EmptyClass)

def empty_declare():
    """
    >>> empty_declare()
    []
    """

    r0 = cython.declare(EmptyClass)
    r1 = cython.declare(EmptyClassSyn)
    r2 = cython.declare(MyStruct)
    r3 = cython.declare(MyUnion)
    r4 = cython.declare(MyStruct2)
    r5 = cython.declare(cython.int[2])

    if cython.compiled:
        r0 = None
        r1 = None

    res = [
        r0 is None,
        r1 is None,
        r2 is not None,
        r3 is not None,
        r4 is not None,
        r5 is not None
    ]

    r2.is_integral = True
    assert r2.is_integral == True

    r3.x = 12.3
    assert r3.x == 12.3

    #It generates a correct C code, but raises an exception when interpreted
    if cython.compiled:
        r4[0].is_integral = True
        assert r4[0].is_integral == True

    r5[0] = 42
    assert r5[0] == 42

    return [i for i, x in enumerate(res) if not x]

def same_declare():
    """
    >>> same_declare()
    True
    """

    f = EmptyClass()
    f2 = cython.declare(EmptyClass, f)
    return f2 is f

def none_cast():
    """
    >>> none_cast() is None
    True
    """

    f = None
    return cython.cast(EmptyClass, f)

def none_declare():
    """
    >>> none_declare() is None
    True
    """

    f = None
    f2 = cython.declare(Foo, f)
    return f2

def array_init_with_list():
    """
    >>> array_init_with_list()
    [10, 42]
    """
    x = cython.declare(cython.int[20], list(range(20)))
    x[12] = 42

    return [x[10], x[12]]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pure_py3.py0000644000175100001770000000514700000000000017671 0ustar00runnerdocker00000000000000# mode: run
# tag: annotation_typing, pure3.0, mypy

import cython

is_compiled = cython.compiled

MyUnion = cython.union(n=cython.int, x=cython.double)
MyStruct = cython.struct(is_integral=cython.bint, data=MyUnion)
MyStruct2 = cython.typedef(MyStruct[2])  # type: cython.StructType


@cython.annotation_typing(False)
def test_annotation_typing(x: cython.int) -> cython.int:
    """
    >>> test_annotation_typing("Petits pains")
    'Petits pains'
    """
    return x


@cython.ccall  # cpdef => C return type
def test_return_type(n: cython.int) -> cython.double:
    """
    >>> test_return_type(389)
    389.0
    """
    assert cython.typeof(n) == 'int', cython.typeof(n)
    return n if is_compiled else float(n)


def test_struct(n: cython.int, x: cython.double) -> MyStruct2:
    """
    >>> test_struct(389, 1.64493)
    (389, 1.64493)
    >>> d = test_struct.__annotations__
    >>> sorted(d)
    ['n', 'return', 'x']
    """
    assert cython.typeof(n) == 'int', cython.typeof(n)
    if is_compiled:
        assert cython.typeof(x) == 'double', cython.typeof(x)  # C double
    else:
        assert cython.typeof(x) == 'float', cython.typeof(x)   # Python float

    a = cython.declare(MyStruct2)
    a[0] = MyStruct(is_integral=True, data=MyUnion(n=n))
    a[1] = MyStruct(is_integral=False, data={'x': x})
    return a[0].data.n, a[1].data.x


@cython.ccall
def c_call(x) -> cython.double:
    return x


def call_ccall(x):
    """
    Test that a declared return type is honoured when compiled.

    >>> result, return_type = call_ccall(1)

    >>> (not is_compiled and 'double') or return_type
    'double'
    >>> (is_compiled and 'int') or return_type
    'int'

    >>> (not is_compiled and 1.0) or result
    1.0
    >>> (is_compiled and 1) or result
    1
    """
    ret = c_call(x)
    return ret, cython.typeof(ret)


@cython.cfunc
@cython.inline
def cdef_inline(x) -> cython.double:
    return x + 1


def call_cdef_inline(x):
    """
    >>> result, return_type = call_cdef_inline(1)
    >>> (not is_compiled and 'float') or type(result).__name__
    'float'
    >>> (not is_compiled and 'double') or return_type
    'double'
    >>> (is_compiled and 'int') or return_type
    'int'
    >>> result == 2.0  or  result
    True
    """
    ret = cdef_inline(x)
    return ret, cython.typeof(ret)

@cython.cfunc
def test_cdef_return_object(x: object) -> object:
    """
    Test support of python object in annotations
    >>> test_cdef_return_object(3)
    3
    >>> test_cdef_return_object(None)
    Traceback (most recent call last):
        ...
    RuntimeError
    """
    if x:
        return x
    else:
        raise RuntimeError()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pure_py_cimports.py0000644000175100001770000000040000000000000021511 0ustar00runnerdocker00000000000000# mode: run
# tag: pure, import, cimport

from cython.cimports.libc import math
from cython.cimports.libc.math import ceil


def libc_math_ceil(x):
    """
    >>> libc_math_ceil(1.5)
    [2, 2]
    """
    return [int(n) for n in [ceil(x), math.ceil(x)]]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pure_pyx_cimports.pyx0000644000175100001770000000111700000000000022077 0ustar00runnerdocker00000000000000# mode: run
# tag: pure, import, cimport

cimport cython.cimports.libc.math as libc_math1

from cython.cimports.libc import math as libc_math2
from cython.cimports.libc.math import ceil as math_ceil

#from cython.cimports cimport libc    # FIXME: currently crashes during analysis when submodule cannot be found
from cython.cimports.libc cimport math
from cython.cimports.libc.math cimport ceil


def libc_math_ceil(x):
    """
    >>> libc_math_ceil(1.5)
    [2, 2, 2, 2, 2]
    """
    return [int(n) for n in [ceil(x), math.ceil(x), libc_math1.ceil(x), libc_math2.ceil(x), math_ceil(x)]]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/purecdef.py0000644000175100001770000000526000000000000017714 0ustar00runnerdocker00000000000000import cython
from cython import cfunc, cclass, ccall

@cython.test_assert_path_exists('//CFuncDefNode')
@cython.cfunc
def ftang():
    x = 0

@cython.test_assert_path_exists('//CFuncDefNode')
@cfunc
def fpure(a):
    return a*2

def test():
    """
    >>> test()
    4
    """
    ftang()
    return fpure(2)

with cfunc:
    @cython.test_assert_path_exists('//CFuncDefNode')
    def fwith1(a):
        return a*3

    @cython.test_assert_path_exists('//CFuncDefNode')
    def fwith2(a):
        return a*4

    @cython.test_assert_path_exists(
        '//CFuncDefNode',
        '//LambdaNode',
        '//GeneratorDefNode',
        '//GeneratorBodyDefNode',
    )
    def f_with_genexpr(a):
        f = lambda x: x+1
        return (f(x) for x in a)


with cclass:
    @cython.test_assert_path_exists('//CClassDefNode')
    class Egg(object):
        pass
    @cython.test_assert_path_exists('//CClassDefNode')
    class BigEgg(object):
        @cython.test_assert_path_exists('//CFuncDefNode')
        @cython.cfunc
        def f(self, a):
            return a*10

def test_with():
    """
    >>> test_with()
    (3, 4, 50)
    """
    return fwith1(1), fwith2(1), BigEgg().f(5)

@cython.test_assert_path_exists('//CClassDefNode')
@cython.cclass
class PureFoo(object):
    a = cython.declare(cython.double)

    def __init__(self, a):
        self.a = a

    def __call__(self):
        return self.a

    @cython.test_assert_path_exists('//CFuncDefNode')
    @cython.cfunc
    def puremeth(self, a):
        return a*2

def test_method():
    """
    >>> test_method()
    4
    True
    """
    x = PureFoo(2)
    print(x.puremeth(2))
    if cython.compiled:
        print(isinstance(x(), float))
    else:
        print(True)
    return

@cython.ccall
def ccall_sqr(x):
    return x*x

@cclass
class Overridable(object):
    @ccall
    def meth(self):
        return 0

def test_ccall():
    """
    >>> test_ccall()
    25
    >>> ccall_sqr(5)
    25
    """
    return ccall_sqr(5)

def test_ccall_method(x):
    """
    >>> test_ccall_method(Overridable())
    0
    >>> Overridable().meth()
    0
    >>> class Foo(Overridable):
    ...    def meth(self):
    ...        return 1
    >>> test_ccall_method(Foo())
    1
    >>> Foo().meth()
    1
    """
    return x.meth()

@cython.cfunc
@cython.returns(cython.p_int)
@cython.locals(xptr=cython.p_int)
def typed_return(xptr):
    return xptr

def test_typed_return():
    """
    >>> test_typed_return()
    """
    x = cython.declare(int, 5)
    assert typed_return(cython.address(x))[0] is x


def test_genexpr_in_cdef(l):
    """
    >>> gen = test_genexpr_in_cdef([1, 2, 3])
    >>> list(gen)
    [2, 3, 4]
    >>> list(gen)
    []
    """
    return f_with_genexpr(l)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pxd_argument_names.srctree0000644000175100001770000000174500000000000023022 0ustar00runnerdocker00000000000000# mode: run
# ticket: 1888

PYTHON setup.py build_ext --inplace
PYTHON -c "import a; a.test()"

######## setup.py ########

from Cython.Build.Dependencies import cythonize

from distutils.core import setup

setup(
    ext_modules=cythonize("a.pyx"),
)

######## a.pxd ########

cdef int do_stuff(int foo) except -1

######## a.pyx ########

cdef int do_stuff(int bar) except -1:
    if bar == 0:
        raise ValueError()
    return bar


cdef call_do_stuff(int x):
    # The keyword argument name is surprising, but actually correct.
    # The caller signature is defined by the .pxd file, not the implementation.
    return do_stuff(foo=x)


def test():
    assert do_stuff(1) == 1
    assert do_stuff(foo=1) == 1
    assert call_do_stuff(1) == 1

    try:
        do_stuff(0)
    except ValueError:
        pass
    else:
        assert False, "exception not raised"

    try:
        call_do_stuff(0)
    except ValueError:
        pass
    else:
        assert False, "exception not raised"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pxd_signature_excvalue.srctree0000644000175100001770000000215700000000000023710 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import foo"
PYTHON -c "import a; a.test()"

######## setup.py ########

from Cython.Build import cythonize
from distutils.core import setup

setup(
  ext_modules = cythonize("*.pyx"),
)

######## foo.pxd ########

cdef int bar(int i) except *

cdef int (*var_opt)(int) except? -1
cdef int (*var_orig)(int) except *

######## foo.pyx ########

cdef int bar(int i) except *:
    if i == 10:
        raise ValueError()
    return i + 1

var_opt = bar   # by 'accident' of optimisation
var_orig = bar  # by declaration

######## a.pyx ########

cimport cython
from foo cimport bar, var_orig, var_opt

def test():
    assert bar(-2) == -1
    try:
        bar(10)
    except ValueError:
        pass
    else:
        assert False, "exception not raised in bar()"

    assert var_orig(-2) == -1
    try:
        var_orig(10)
    except ValueError:
        pass
    else:
        assert False, "exception not raised in var_orig()"

    assert var_opt(-2) == -1
    try:
        var_opt(10)
    except ValueError:
        pass
    else:
        assert False, "exception not raised in var_opt()"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pxd_syntax.srctree0000644000175100001770000000202100000000000021327 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import a; a.test()"

######## setup.py ########

from Cython.Build.Dependencies import cythonize

from distutils.core import setup

setup(
    ext_modules = cythonize("a.pyx"),
)

######## a.pyx ########

cdef class ExtTypeDocstringPass:
    pass

cdef class ExtTypeDocstring:
    "huhu!"   # this should override the .pxd docstring

cdef class ExtTypePass:
    pass

cdef class ExtTypeDocstringPassString:
    pass

def test():
    assert not ExtTypePass().__doc__, ExtTypePass().__doc__
    assert ExtTypeDocstring().__doc__ == "huhu!", ExtTypeDocstring().__doc__
    assert ExtTypeDocstringPass().__doc__ == "hoho!", ExtTypeDocstringPass().__doc__
    assert ExtTypeDocstringPassString().__doc__ == "hoho!", ExtTypeDocstringPassString().__doc__

######## a.pxd ########

cdef class ExtTypePass:
    pass

cdef class ExtTypeDocstring:
    """
    hoho
    """

cdef class ExtTypeDocstringPass:
    "hoho!"
    pass

cdef class ExtTypeDocstringPassString:
    "hoho!"
    pass
    "more hoho"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/py2_super.pyx0000644000175100001770000000342700000000000020242 0ustar00runnerdocker00000000000000# mode: run
# tag: py3k_super

class A(object):
    def method(self):
        return 1

    @classmethod
    def class_method(cls):
        return 2

    @staticmethod
    def static_method():
        return 3

    def generator_test(self):
        return [1, 2, 3]


class B(A):
    """
    >>> obj = B()
    >>> obj.method()
    1
    >>> B.class_method()
    2
    >>> B.static_method(obj)
    3
    >>> list(obj.generator_test())
    [1, 2, 3]
    """
    def method(self):
        return super(B, self).method()

    @classmethod
    def class_method(cls):
        return super(B, cls).class_method()

    @staticmethod
    def static_method(instance):
        return super(B, instance).static_method()

    def generator_test(self):
        for i in super(B, self).generator_test():
            yield i


cdef class CClassBase(object):
    def method(self):
        return 'def'
    cpdef method_cp(self):
        return 'cpdef'

#     cdef method_c(self):
#         return 'cdef'
#     def call_method_c(self):
#         return self.method_c()

cdef class CClassSub(CClassBase):
    """
    >>> CClassSub().method()
    'def'
    >>> CClassSub().method_cp()
    'cpdef'
    """
#     >>> CClassSub().call_method_c()
#     'cdef'

    def method(self):
        return super(CClassSub, self).method()
    cpdef method_cp(self):
        return super(CClassSub, self).method_cp()

#     cdef method_c(self):
#         return super(CClassSub, self).method_c()

cdef class Base(object):
    """
    >>> Base().method()
    'Base'
    >>> Base.method(Base())
    'Base'
    """
    cpdef method(self):
        return "Base"

cdef class Sub(Base):
    """
    >>> Sub().method()
    'Sub'
    >>> Sub.method(Sub())
    'Sub'
    >>> Base.method(Sub())
    'Base'
    """
    cpdef method(self):
        return "Sub"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/py34_signature.pyx0000644000175100001770000000410100000000000021160 0ustar00runnerdocker00000000000000# cython: binding=True, language_level=3
# mode: run
# tag: cyfunction

import inspect

try:
    sig = inspect.Signature.from_callable
except AttributeError:
    sig = inspect.Signature.from_function


def signatures_match(f1, f2):
    if sig(f1) == sig(f2):
        return None  # nothing to show in doctest
    return sig(f1), sig(f2)


def b(a, b, c):
    """
    >>> def py_b(a, b, c): pass
    >>> signatures_match(b, py_b)
    """


def c(a, b, c=1):
    """
    >>> def py_c(a, b, c=1): pass
    >>> signatures_match(c, py_c)
    """


def d(a, b, *, c = 88):
    """
    >>> def py_d(a, b, *, c = 88): pass
    >>> signatures_match(d, py_d)
    """


def e(a, b, c = 88, **kwds):
    """
    >>> def py_e(a, b, c = 88, **kwds): pass
    >>> signatures_match(e, py_e)
    """


def f(a, b, *, c, d = 42):
    """
    >>> def py_f(a, b, *, c, d = 42): pass
    >>> signatures_match(f, py_f)
    """


def g(a, b, *, c, d = 42, e = 17, f, **kwds):
    """
    >>> def py_g(a, b, *, c, d = 42, e = 17, f, **kwds): pass
    >>> signatures_match(g, py_g)
    """


def h(a, b, *args, c, d = 42, e = 17, f, **kwds):
    """
    >>> def py_h(a, b, *args, c, d = 42, e = 17, f, **kwds): pass
    >>> signatures_match(h, py_h)
    """


def k(a, b, c=1, *args, d = 42, e = 17, f, **kwds):
    """
    >>> def py_k(a, b, c=1, *args, d = 42, e = 17, f, **kwds): pass
    >>> signatures_match(k, py_k)
    """


def l(*, a, b, c = 88):
    """
    >>> def py_l(*, a, b, c = 88): pass
    >>> signatures_match(l, py_l)
    """


def m(a, *, b, c = 88):
    """
    >>> def py_m(a, *, b, c = 88): pass
    >>> signatures_match(m, py_m)
    """
    a, b, c = b, c, a


def n(a, *, b, c = 88):
    """
    >>> def py_n(a, *, b, c = 88): pass
    >>> signatures_match(n, py_n)
    """


cpdef cp1(a, b):
    """
    >>> def py_cp1(a, b): pass
    >>> signatures_match(cp1, py_cp1)
    """


cpdef cp2(a, b=True):
    """
    >>> def py_cp2(a, b=True): pass

    >>> signatures_match(cp2, py_cp2)
    """


cpdef cp3(a=1, b=True):
    """
    >>> def py_cp3(a=1, b=True): pass

    >>> signatures_match(cp3, py_cp3)
    """
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/py35_asyncio_async_def.srctree0000644000175100001770000000311400000000000023472 0ustar00runnerdocker00000000000000# mode: run
# tag: asyncio, gh1685, gh2273

PYTHON setup.py build_ext -i
PYTHON main.py


######## setup.py ########

from Cython.Build import cythonize
from distutils.core import setup

setup(
    ext_modules = cythonize("*.pyx"),
)


######## main.py ########

import asyncio
import cy_test
import py_test
from contextlib import closing

async def main():
    await cy_test.say()

with closing(asyncio.new_event_loop()) as loop:
    print("Running Python coroutine ...")
    loop.run_until_complete(main())

    print("Running Cython coroutine ...")
    loop.run_until_complete(cy_test.say())

assert asyncio.iscoroutinefunction(cy_test.cy_async_def_example) == True
assert asyncio.iscoroutinefunction(cy_test.cy_async_def_example) == True
assert asyncio.iscoroutinefunction(py_test.py_async_def_example) == True
assert asyncio.iscoroutinefunction(py_test.py_async_def_example) == True
assert asyncio.iscoroutinefunction(cy_test.cy_def_example) == False
assert asyncio.iscoroutinefunction(py_test.py_def_example) == False

######## cy_test.pyx ########

import asyncio
from py_test import py_async

async def cy_async():
    print("- this one is from Cython")

async def say():
    await cb()

async def cb():
    print("awaiting:")
    await cy_async()
    await py_async()
    print("sleeping:")
    await asyncio.sleep(0.5)
    print("done!")

async def cy_async_def_example():
    return 1

def cy_def_example():
    return 1

######## py_test.py ########

async def py_async():
    print("- and this one is from Python")

async def py_async_def_example():
    return 1

def py_def_example():
    return 1
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/py35_pep492_interop.pyx0000644000175100001770000000744600000000000021762 0ustar00runnerdocker00000000000000# cython: language_level=3, binding=True
# mode: run
# tag: pep492, asyncfor, await


def run_async(coro, ignore_type=False):
    if not ignore_type:
        #assert coro.__class__ is types.GeneratorType
        assert coro.__class__.__name__ in ('coroutine', 'GeneratorWrapper'), coro.__class__.__name__

    buffer = []
    result = None
    while True:
        try:
            buffer.append(coro.send(None))
        except StopIteration as ex:
            result = ex.args[0] if ex.args else None
            break
    return buffer, result


def run_async__await__(coro):
    assert coro.__class__.__name__ in ('coroutine', 'GeneratorWrapper'), coro.__class__.__name__
    aw = coro.__await__()
    buffer = []
    result = None
    i = 0
    while True:
        try:
            if i % 2:
                buffer.append(next(aw))
            else:
                buffer.append(aw.send(None))
            i += 1
        except StopIteration as ex:
            result = ex.args[0] if ex.args else None
            break
    return buffer, result


async def await_pyobject(awaitable):
    """
    >>> async def simple():
    ...     return 10

    >>> buffer, result = run_async(await_pyobject(simple()))
    >>> result
    10

    >>> async def awaiting(awaitable):
    ...     return await awaitable

    >>> buffer, result = run_async(await_pyobject(awaiting(simple())))
    >>> result
    10
    """
    return await awaitable


def await_cyobject():
    """
    >>> async def run_await(awaitable):
    ...     return await awaitable

    >>> simple, awaiting = await_cyobject()

    >>> buffer, result = run_async(run_await(simple()))
    >>> result
    10

    >>> buffer, result = run_async(run_await(awaiting(simple())))
    >>> result
    10

    >>> buffer, result = run_async(run_await(awaiting(awaiting(simple()))))
    >>> result
    10

    >>> buffer, result = run_async(run_await(awaiting(run_await(awaiting(simple())))))
    >>> result
    10
    """

    async def simple():
        return 10

    async def awaiting(awaitable):
        return await awaitable

    return simple, awaiting


cimport cython

def yield_from_cyobject():
    """
    >>> async def py_simple_nonit():
    ...     return 10

    >>> async def run_await(awaitable):
    ...     return await awaitable

    >>> def run_yield_from(it):
    ...     return (yield from it)

    >>> simple_nonit, simple_it, awaiting, yield_from = yield_from_cyobject()

    >>> buffer, result = run_async(run_await(simple_it()))
    >>> result
    10
    >>> buffer, result = run_async(run_await(awaiting(simple_it())))
    >>> result
    10
    >>> buffer, result = run_async(awaiting(run_await(simple_it())), ignore_type=True)
    >>> result
    10
    >>> buffer, result = run_async(run_await(py_simple_nonit()))
    >>> result
    10

    >>> buffer, result = run_async(run_yield_from(awaiting(run_await(simple_it()))), ignore_type=True)
    >>> result
    10

    >>> buffer, result = run_async(run_yield_from(simple_it()), ignore_type=True)
    >>> result
    10
    >>> buffer, result = run_async(yield_from(simple_it()), ignore_type=True)
    >>> result
    10

    >>> next(run_yield_from(simple_nonit()))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> next(run_yield_from(py_simple_nonit()))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> next(yield_from(py_simple_nonit()))
    Traceback (most recent call last):
    TypeError: 'coroutine' object is not iterable
    """
    async def simple_nonit():
        return 10

    @cython.iterable_coroutine
    async def simple_it():
        return 10

    @cython.iterable_coroutine
    async def awaiting(awaitable):
        return await awaitable

    def yield_from(it):
        return (yield from it)

    return simple_nonit, simple_it, awaiting, yield_from
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/py3k_super.pyx0000644000175100001770000000411400000000000020410 0ustar00runnerdocker00000000000000# mode: run
# tag: py3k_super, gh3246

class A(object):
    def method(self):
        return 1

    @classmethod
    def class_method(cls):
        return 2

    @staticmethod
    def static_method():
        return 3

    def generator_test(self):
        return [1, 2, 3]


class B(A):
    """
    >>> obj = B()
    >>> obj.method()
    1
    >>> B.class_method()
    2
    >>> B.static_method(obj)
    3
    >>> list(obj.generator_test())
    [1, 2, 3]
    """
    def method(self):
        return super().method()

    @classmethod
    def class_method(cls):
        return super().class_method()

    @staticmethod
    def static_method(instance):
        return super().static_method()

    def generator_test(self):
        for i in super().generator_test():
            yield i


def test_class_cell_empty():
    """
    >>> test_class_cell_empty()
    Traceback (most recent call last):
    ...
    SystemError: super(): empty __class__ cell
    """
    class Base(type):
        def __new__(cls, name, bases, attrs):
            attrs['foo'](None)

    class EmptyClassCell(metaclass=Base):
        def foo(self):
            super()


cdef class CClassBase(object):
    def method(self):
        return 'def'

#     cpdef method_cp(self):
#         return 'cpdef'
#     cdef method_c(self):
#         return 'cdef'
#     def call_method_c(self):
#         return self.method_c()

cdef class CClassSub(CClassBase):
    """
    >>> CClassSub().method()
    'def'
    """
#     >>> CClassSub().method_cp()
#     'cpdef'
#     >>> CClassSub().call_method_c()
#     'cdef'

    def method(self):
        return super().method()

#     cpdef method_cp(self):
#         return super().method_cp()
#     cdef method_c(self):
#         return super().method_c()


def freeing_class_cell_temp_gh3246():
    # https://github.com/cython/cython/issues/3246
    """
    >>> abc = freeing_class_cell_temp_gh3246()
    >>> abc().a
    1
    """
    class SimpleBase(object):
        def __init__(self):
            self.a = 1

    class ABC(SimpleBase):
        def __init__(self):
            super().__init__()

    return ABC
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/py_classbody.py0000644000175100001770000000274500000000000020617 0ustar00runnerdocker00000000000000# mode: run
# tag: pyclass, global


pyvar = 2

class TestPyAttr(object):
    """
    >>> TestPyAttr.pyvar    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    AttributeError: ...TestPyAttr...has no attribute 'pyvar'...
    >>> TestPyAttr.pyval1
    3
    >>> TestPyAttr.pyval2
    2
    """
    pyvar = 3
    pyval1 = pyvar
    del pyvar
    pyval2 = pyvar


import cython
cdefvar = cython.declare(int, 10)

class TestCdefAttr(object):
    """
    >>> TestCdefAttr.cdefvar   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    AttributeError: ...TestCdefAttr...has no attribute 'cdefvar'...
    >>> TestCdefAttr.cdefval1
    11

    >>> #TestCdefAttr.cdefval2
    """
    cdefvar = 11
    cdefval1 = cdefvar
    del cdefvar
    # cdefval2 = cdefvar       # FIXME: doesn't currently work ...


class ForLoopInPyClass(object):
    """
    >>> ForLoopInPyClass.i    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    AttributeError: ...ForLoopInPyClass... has no attribute ...i...
    >>> ForLoopInPyClass.k
    0
    >>> ForLoopInPyClass.m
    1
    """
    for i in range(0):
        pass

    for k in range(1):
        pass

    for m in range(2):
        pass


def del_in_class(x):
    """
    >>> del_in_class(True)
    no error
    >>> del_in_class(False)
    NameError
    """
    try:
        class Test(object):
            if x:
                attr = 1
            del attr
    except NameError:
        print("NameError")
    else:
        print("no error")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/py_hash_t.pyx0000644000175100001770000000155600000000000020271 0ustar00runnerdocker00000000000000
cimport cython


class IntLike(object):
  def __init__(self, value):
    self.value = value
  def __index__(self):
    return self.value


def assign_py_hash_t(x):
    """
    >>> assign_py_hash_t(12)
    12
    >>> assign_py_hash_t(-12)
    -12

    >>> assign_py_hash_t(IntLike(-3))
    -3
    >>> assign_py_hash_t(IntLike(1 << 100))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: ...
    >>> assign_py_hash_t(IntLike(1.5))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    TypeError: __index__ ... (type ...float...)
    """
    cdef Py_hash_t h = x
    return h


def infer_hash_type(x):
    """
    >>> infer_hash_type(123)
    'Py_hash_t'
    """
    h = hash(x)
    return cython.typeof(h)


def assign_to_name(x):
    """
    >>> assign_to_name(321)
    321
    """
    Py_hash_t = x
    return Py_hash_t
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/py_ucs4_type.pyx0000644000175100001770000002476500000000000020751 0ustar00runnerdocker00000000000000# -*- coding: iso-8859-1 -*-
# mode: run
# tag: warnings


cimport cython

cdef Py_UCS4 char_ASCII = u'A'
cdef Py_UCS4 char_KLINGON = u'\uF8D2'

u_A = char_ASCII
u_KLINGON = char_KLINGON


def compare_ASCII():
    """
    >>> compare_ASCII()
    True
    False
    False
    """
    print(char_ASCII == u'A')
    print(char_ASCII == u'B')
    print(char_ASCII == u'\uF8D2')


def compare_klingon():
    """
    >>> compare_klingon()
    True
    False
    False
    """
    print(char_KLINGON == u'\uF8D2')
    print(char_KLINGON == u'A')
    print(char_KLINGON == u'B')


def single_uchar_compare():
    """
    >>> single_uchar_compare()
    """
    assert u'\u0100' < u'\u0101'
    assert u'\u0101' > u'\u0100'


from cpython.unicode cimport PyUnicode_FromOrdinal
import sys

u0 = u'\x00'
u1 = u'\x01'
umax = PyUnicode_FromOrdinal(sys.maxunicode)

def unicode_ordinal(Py_UCS4 i):
    """
    >>> ord(unicode_ordinal(0)) == 0
    True
    >>> ord(unicode_ordinal(1)) == 1
    True
    >>> ord(unicode_ordinal(sys.maxunicode)) == sys.maxunicode
    True

    >>> ord(unicode_ordinal(u0)) == 0
    True
    >>> ord(unicode_ordinal(u1)) == 1
    True
    >>> ord(unicode_ordinal(umax)) == sys.maxunicode
    True

    Value too small:
    >>> unicode_ordinal(-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: ...

    Value too large:
    >>> unicode_ordinal(1114111+1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: ...

    Less than one character:
    >>> unicode_ordinal(u0[:0])
    Traceback (most recent call last):
    ...
    ValueError: only single character unicode strings can be converted to Py_UCS4, got length 0

    More than one character:
    >>> unicode_ordinal(u0+u1)
    Traceback (most recent call last):
    ...
    ValueError: only single character unicode strings can be converted to Py_UCS4, got length 2
    """
    return i


def ord_py_ucs4(Py_UCS4 x):
    """
    >>> ord_py_ucs4(u0)
    0
    >>> ord_py_ucs4(u_A)
    65
    >>> ord_py_ucs4(u_KLINGON)
    63698
    """
    return ord(x)


@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode')
def unicode_type_methods(Py_UCS4 uchar):
    """
    >>> unicode_type_methods(ord('A'))
    [True, True, False, False, False, False, False, True, True]
    >>> unicode_type_methods(ord('a'))
    [True, True, False, False, True, False, False, False, False]
    >>> unicode_type_methods(ord('8'))
    [True, False, True, True, False, True, False, False, False]
    >>> unicode_type_methods(ord('\\t'))
    [False, False, False, False, False, False, True, False, False]
    """
    return [
        # character types
        uchar.isalnum(),
        uchar.isalpha(),
        uchar.isdecimal(),
        uchar.isdigit(),
        uchar.islower(),
        uchar.isnumeric(),
        uchar.isspace(),
        uchar.istitle(),
        uchar.isupper(),
        ]

#@cython.test_assert_path_exists('//PythonCapiCallNode')
#@cython.test_fail_if_path_exists('//SimpleCallNode')
def unicode_methods(Py_UCS4 uchar):
    """
    >>> unicode_methods(ord('A')) == ['a', 'A', 'A'] or unicode_methods(ord('A'))
    True
    >>> unicode_methods(ord('a')) == ['a', 'A', 'A'] or unicode_methods(ord('a'))
    True
    >>> unicode_methods(0x1E9E) == [u'\\xdf', u'\\u1e9e', u'\\u1e9e'] or unicode_methods(0x1E9E)
    True
    >>> unicode_methods(0x0130) in (
    ...     [u'i\\u0307', u'\\u0130', u'\\u0130'],  # Py3
    ...     [u'i', u'\\u0130', u'\\u0130'],  # Py2
    ... ) or unicode_methods(0x0130)
    True
    """
    # \u1E9E == 'LATIN CAPITAL LETTER SHARP S'
    # \u0130 == 'LATIN CAPITAL LETTER I WITH DOT ABOVE'
    return [
        # character conversion
        uchar.lower(),
        uchar.upper(),
        uchar.title(),
        ]


#@cython.test_assert_path_exists('//PythonCapiCallNode')
#@cython.test_fail_if_path_exists(
#    '//SimpleCallNode',
#    '//CoerceFromPyTypeNode',
#)
def unicode_method_return_type(Py_UCS4 uchar):
    """
    >>> unicode_method_return_type(ord('A'))
    [True, False]
    >>> unicode_method_return_type(ord('a'))
    [False, True]
    """
    cdef Py_UCS4 uc, ul
    uc, ul = uchar.upper(), uchar.lower()
    return [uc == uchar, ul == uchar]


@cython.test_assert_path_exists('//IntNode')
@cython.test_fail_if_path_exists('//SimpleCallNode',
                                 '//PythonCapiCallNode')
def len_uchar(Py_UCS4 uchar):
    """
    >>> len_uchar(ord('A'))
    1
    """
    return len(uchar)

def index_uchar(Py_UCS4 uchar, Py_ssize_t i):
    """
    >>> index_uchar(ord('A'), 0) == ('A', 'A', 'A')
    True
    >>> index_uchar(ord('A'), -1) == ('A', 'A', 'A')
    True
    >>> index_uchar(ord('A'), 1)
    Traceback (most recent call last):
    IndexError: string index out of range
    """
    return uchar[0], uchar[-1], uchar[i]

mixed_ustring = u'AbcDefGhIjKlmnoP'
lower_ustring = mixed_ustring.lower()
upper_ustring = mixed_ustring.lower()

@cython.test_assert_path_exists('//PythonCapiCallNode',
                                '//ForFromStatNode')
@cython.test_fail_if_path_exists('//SimpleCallNode',
                                 '//ForInStatNode')
def count_lower_case_characters(unicode ustring):
    """
    >>> count_lower_case_characters(mixed_ustring)
    10
    >>> count_lower_case_characters(lower_ustring)
    16
    """
    cdef Py_ssize_t count = 0
    for uchar in ustring:
         if uchar.islower():
             count += 1
    return count

@cython.test_assert_path_exists('//PythonCapiCallNode',
                                '//ForFromStatNode')
@cython.test_fail_if_path_exists('//SimpleCallNode',
                                 '//ForInStatNode')
def count_lower_case_characters_slice(unicode ustring):
    """
    >>> count_lower_case_characters_slice(mixed_ustring)
    10
    >>> count_lower_case_characters_slice(lower_ustring)
    14
    >>> sum([ 1 for uchar in lower_ustring[1:-1] if uchar.islower() ])
    14
    """
    cdef Py_ssize_t count = 0
    for uchar in ustring[1:-1]:
         if uchar.islower():
             count += 1
    return count

@cython.test_assert_path_exists('//PythonCapiCallNode',
                                '//ForFromStatNode')
@cython.test_fail_if_path_exists('//SimpleCallNode',
                                 '//ForInStatNode')
def count_lower_case_characters_slice_reversed(unicode ustring):
    """
    >>> count_lower_case_characters_slice_reversed(mixed_ustring)
    10
    >>> count_lower_case_characters_slice_reversed(lower_ustring)
    14
    >>> sum([ 1 for uchar in lower_ustring[-2:0:-1] if uchar.islower() ])
    14
    """
    cdef Py_ssize_t count = 0
    for uchar in ustring[-2:0:-1]:
         if uchar.islower():
             count += 1
    return count

def loop_object_over_latin1_unicode_literal():
    """
    >>> result = loop_object_over_latin1_unicode_literal()
    >>> print(result[:-1])
    abcdefg
    >>> ord(result[-1]) == 0xD7
    True
    """
    cdef object uchar
    chars = []
    for uchar in u'abcdefg\xD7':
        chars.append(uchar)
    return u''.join(chars)

def loop_object_over_unicode_literal():
    """
    >>> result = loop_object_over_unicode_literal()
    >>> print(result[:-1])
    abcdefg
    >>> ord(result[-1]) == 0xF8FD
    True
    """
    cdef object uchar
    chars = []
    for uchar in u'abcdefg\uF8FD':
        chars.append(uchar)
    return u''.join(chars)

@cython.test_assert_path_exists('//SwitchStatNode')
@cython.test_fail_if_path_exists('//ForInStatNode')
def iter_and_in():
    """
    >>> iter_and_in()
    a
    b
    e
    f
    h
    """
    for c in u'abcdefgh':
        if c in u'abCDefGh':
            print c


@cython.test_fail_if_path_exists('//ForInStatNode')
def iter_inferred():
    """
    >>> iter_inferred()
    a
    b
    c
    d
    e
    """
    uchars = list(u"abcde")
    uchars = u''.join(uchars)
    for c in uchars:
        print c


@cython.test_assert_path_exists('//SwitchStatNode',
                                '//ForFromStatNode')
@cython.test_fail_if_path_exists('//ForInStatNode')
def index_and_in():
    """
    >>> index_and_in()
    1
    3
    4
    7
    8
    """
    cdef int i
    for i in range(1,9):
        if u'abcdefgh'[-i] in u'abCDefGh':
            print i

# special test for narrow builds

high_uchar = u'\U00012345'
high_ustring0 = u'\U00012345\U00012346abc'
high_ustring1 = u'\U00012346\U00012345abc'
high_ustring_end = u'\U00012346abc\U00012344\U00012345'
high_ustring_no = u'\U00012346\U00012346abc'

def uchar_in(Py_UCS4 uchar, unicode ustring):
    """
    >>> uchar_in(high_uchar, high_ustring0)
    True
    >>> uchar_in(high_uchar, high_ustring1)
    True
    >>> uchar_in(high_uchar, high_ustring_end)
    True
    >>> uchar_in(high_uchar, high_ustring_no)
    False
    """
    assert uchar == 0x12345, ('%X' % uchar)
    return uchar in ustring


def uchar_lookup_in_dict(obj, Py_UCS4 uchar):
    """
    >>> d = {u_KLINGON: 1234, u0: 0, u1: 1, u_A: 2}
    >>> uchar_lookup_in_dict(d, u_KLINGON)
    (1234, 1234)
    >>> uchar_lookup_in_dict(d, u_A)
    (2, 2)
    >>> uchar_lookup_in_dict(d, u0)
    (0, 0)
    >>> uchar_lookup_in_dict(d, u1)
    (1, 1)
    """
    cdef dict d = obj
    dval = d[uchar]
    objval = obj[uchar]
    return dval, objval


def uchar_cast_to_int(Py_UCS4 uchar):
    """
    >>> ints = uchar_cast_to_int(u'3'); ints == (51, 3, 3, 3, 3) or ints
    True
    >>> ints = uchar_cast_to_int(u'0'); ints == (48, 0, 0, 0, 0) or ints
    True
    >>> uchar_cast_to_int(u'A')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: invalid literal for int() with base 10: ...A...
    """
    cdef object ustr_object = uchar
    cdef str ustr_str = str(uchar)
    cdef unicode ustr_unicode = uchar
    return uchar, int(ustr_object[0]), int(ustr_str[0]), int(ustr_unicode[0]), int(uchar)


def uchar_cast_to_float(Py_UCS4 uchar):
    """
    >>> floats = uchar_cast_to_float(u'3'); floats == (51, 3, 3, 3, 3) or floats
    True
    >>> floats = uchar_cast_to_float(u'0'); floats == (48, 0, 0, 0, 0) or floats
    True
    >>> uchar_cast_to_float(u'A')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: could not convert string to float: ...A...
    """
    cdef object ustr_object = uchar
    cdef str ustr_str = str(uchar)
    cdef unicode ustr_unicode = uchar
    return uchar, float(ustr_object[0]), float(ustr_str[0]), float(ustr_unicode[0]), float(uchar)


_WARNINGS = """
373:16: Item lookup of unicode character codes now always converts to a Unicode string. Use an explicit C integer cast to get back the previous integer lookup behaviour.
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/py_unicode_strings.pyx0000644000175100001770000000532300000000000022216 0ustar00runnerdocker00000000000000# mode: run
# tag: py_unicode_strings

import sys

from libc.string cimport memcpy

cdef assert_Py_UNICODE_equal(const Py_UNICODE* u1, const Py_UNICODE* u2):
    cdef size_t i = 0
    while u1[i] != 0 and u2[i] != 0 and u1[i] == u2[i]:
        i += 1
    assert u1[i] == u2[i], f"Mismatch at position {i}: {u1[i]} != {u2[i]} ({u1!r} != {u2!r})"


ctypedef Py_UNICODE* LPWSTR

cdef unicode uobj = u'unicode\u1234'
cdef unicode uobj1 = u'u'
cdef Py_UNICODE* c_pu_str = u"unicode\u1234"
cdef Py_UNICODE[42] c_pu_arr
cdef LPWSTR c_wstr = u"unicode\u1234"
cdef Py_UNICODE* c_pu_empty = u""
cdef char* c_empty = ""
cdef unicode uwide_literal = u'\U00020000\U00020001'
cdef Py_UNICODE* c_pu_wide_literal = u'\U00020000\U00020001'

memcpy(c_pu_arr, c_pu_str, sizeof(Py_UNICODE) * (len(uobj) + 1))


def test_c_to_python():
    """
    >>> test_c_to_python()
    """
    assert c_pu_arr == uobj
    assert c_pu_str == uobj
    assert c_wstr == uobj

    assert c_pu_arr[1:] == uobj[1:]
    assert c_pu_str[1:] == uobj[1:]
    assert c_wstr[1:] == uobj[1:]

    assert c_pu_arr[:1] == uobj[:1]
    assert c_pu_arr[:1] == uobj[:1]
    assert c_pu_str[:1] == uobj[:1]
    assert c_wstr[:1] == uobj[:1]

    assert c_pu_arr[1:7] == uobj[1:7]
    assert c_pu_str[1:7] == uobj[1:7]
    assert c_wstr[1:7] == uobj[1:7]

    cdef Py_UNICODE ch = uobj[1]  # Py_UCS4 is unsigned, Py_UNICODE is usually signed.
    assert c_pu_arr[1] == ch
    assert c_pu_str[1] == ch
    assert c_wstr[1] == ch

    assert len(c_pu_str) == 8
    assert len(c_pu_arr) == 8
    assert len(c_wstr) == 8

    assert sizeof(c_pu_arr) == sizeof(Py_UNICODE) * 42
    assert sizeof(c_pu_str) == sizeof(void*)

    assert c_pu_wide_literal == uwide_literal
    if sizeof(Py_UNICODE) >= 4:
        assert len(c_pu_wide_literal) == 2
    else:
        assert len(c_pu_wide_literal) == 4

    if sys.version_info >= (3, 3):
        # Make sure len(unicode) is not reverted to pre-3.3 behavior
        assert len(uwide_literal) == 2

    assert u'unicode'
    assert not u''
    assert c_pu_str
    assert c_pu_empty


def test_python_to_c():
    """
    >>> test_python_to_c()
    """
    cdef unicode u

    assert_Py_UNICODE_equal(c_pu_arr, uobj)
    assert_Py_UNICODE_equal(c_pu_str, uobj)
    assert_Py_UNICODE_equal(c_pu_str, uobj)
    u = uobj[1:]
    assert_Py_UNICODE_equal(c_pu_str + 1, u)
    assert_Py_UNICODE_equal(c_wstr + 1, u)
    u = uobj[:1]
    assert_Py_UNICODE_equal(u"u", u)
    u = uobj[1:7]
    assert_Py_UNICODE_equal(u"nicode", u)
    u = uobj[1]
    assert_Py_UNICODE_equal(u"n", u)

    assert_Py_UNICODE_equal(uwide_literal, c_pu_wide_literal)

    assert len(u"abc\0") == 4
    assert len(u"abc\0") == 3
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/py_unicode_type.pyx0000644000175100001770000001430200000000000021503 0ustar00runnerdocker00000000000000# -*- coding: iso-8859-1 -*-
# mode: run
# tag: warnings

cimport cython

cdef Py_UNICODE char_ASCII = u'A'
cdef Py_UNICODE char_KLINGON = u'\uF8D2'

u_A = char_ASCII
u_KLINGON = char_KLINGON


def compare_ASCII():
    """
    >>> compare_ASCII()
    True
    False
    False
    """
    print(char_ASCII == u'A')
    print(char_ASCII == u'B')
    print(char_ASCII == u'\uF8D2')


def compare_klingon():
    """
    >>> compare_klingon()
    True
    False
    False
    """
    print(char_KLINGON == u'\uF8D2')
    print(char_KLINGON == u'A')
    print(char_KLINGON == u'B')


from cpython.unicode cimport PyUnicode_FromOrdinal
import sys

u0 = u'\x00'
u1 = u'\x01'
umax = PyUnicode_FromOrdinal(sys.maxunicode)

def unicode_ordinal(Py_UNICODE i):
    """
    >>> ord(unicode_ordinal(0)) == 0
    True
    >>> ord(unicode_ordinal(1)) == 1
    True
    >>> ord(unicode_ordinal(sys.maxunicode)) == sys.maxunicode
    True

    >>> ord(unicode_ordinal(u0)) == 0
    True
    >>> ord(unicode_ordinal(u1)) == 1
    True
    >>> ord(unicode_ordinal(umax)) == sys.maxunicode
    True

    Value too small:
    >>> unicode_ordinal(-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: ...

    Value too large:
    >>> unicode_ordinal(sys.maxunicode+1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError: ...

    Less than one character:
    >>> unicode_ordinal(u0[:0])
    Traceback (most recent call last):
    ...
    ValueError: only single character unicode strings can be converted to Py_UNICODE, got length 0

    More than one character:
    >>> unicode_ordinal(u0+u1)
    Traceback (most recent call last):
    ...
    ValueError: only single character unicode strings can be converted to Py_UNICODE, got length 2
    """
    return i


def ord_pyunicode(Py_UNICODE x):
    """
    >>> ord_pyunicode(u0)
    0
    >>> ord_pyunicode(u_A)
    65
    >>> ord_pyunicode(u_KLINGON)
    63698
    """
    return ord(x)


@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode')
def unicode_type_methods(Py_UNICODE uchar):
    """
    >>> unicode_type_methods(ord('A'))
    [True, True, False, False, False, False, False, True, True]
    >>> unicode_type_methods(ord('a'))
    [True, True, False, False, True, False, False, False, False]
    >>> unicode_type_methods(ord('8'))
    [True, False, True, True, False, True, False, False, False]
    >>> unicode_type_methods(ord('\\t'))
    [False, False, False, False, False, False, True, False, False]
    """
    return [
        # character types
        uchar.isalnum(),
        uchar.isalpha(),
        uchar.isdecimal(),
        uchar.isdigit(),
        uchar.islower(),
        uchar.isnumeric(),
        uchar.isspace(),
        uchar.istitle(),
        uchar.isupper(),
        ]

#@cython.test_assert_path_exists('//PythonCapiCallNode')
#@cython.test_fail_if_path_exists('//SimpleCallNode')
def unicode_methods(Py_UNICODE uchar):
    """
    >>> unicode_methods(ord('A')) == ['a', 'A', 'A']
    True
    >>> unicode_methods(ord('a')) == ['a', 'A', 'A']
    True
    """
    return [
        # character conversion
        uchar.lower(),
        uchar.upper(),
        uchar.title(),
        ]

@cython.test_assert_path_exists('//IntNode')
@cython.test_fail_if_path_exists('//SimpleCallNode',
                                 '//PythonCapiCallNode')
def len_uchar(Py_UNICODE uchar):
    """
    >>> len_uchar(ord('A'))
    1
    """
    assert uchar  # just to avoid C compiler unused arg warning
    return len(uchar)

def index_uchar(Py_UNICODE uchar, Py_ssize_t i):
    """
    >>> index_uchar(ord('A'), 0) == ('A', 'A', 'A')
    True
    >>> index_uchar(ord('A'), -1) == ('A', 'A', 'A')
    True
    >>> index_uchar(ord('A'), 1)
    Traceback (most recent call last):
    IndexError: string index out of range
    """
    return uchar[0], uchar[-1], uchar[i]

mixed_ustring = u'AbcDefGhIjKlmnoP'
lower_ustring = mixed_ustring.lower()
upper_ustring = mixed_ustring.lower()

@cython.test_assert_path_exists('//PythonCapiCallNode',
                                '//ForFromStatNode')
@cython.test_fail_if_path_exists('//SimpleCallNode',
                                 '//ForInStatNode')
def count_lower_case_characters(unicode ustring):
    """
    >>> count_lower_case_characters(mixed_ustring)
    10
    >>> count_lower_case_characters(lower_ustring)
    16
    """
    cdef Py_ssize_t count = 0
    for uchar in ustring:
         if uchar.islower():
             count += 1
    return count

@cython.test_assert_path_exists('//PythonCapiCallNode',
                                '//ForFromStatNode')
@cython.test_fail_if_path_exists('//SimpleCallNode',
                                 '//ForInStatNode')
def count_lower_case_characters_slice(unicode ustring):
    """
    >>> count_lower_case_characters_slice(mixed_ustring)
    10
    >>> count_lower_case_characters_slice(lower_ustring)
    14
    """
    cdef Py_ssize_t count = 0
    for uchar in ustring[1:-1]:
         if uchar.islower():
             count += 1
    return count

@cython.test_assert_path_exists('//SwitchStatNode',
                                '//ForFromStatNode')
@cython.test_fail_if_path_exists('//ForInStatNode')
def iter_and_in():
    """
    >>> iter_and_in()
    a
    b
    e
    f
    h
    """
    for c in u'abcdefgh':
        if c in u'abCDefGh':
            print c

@cython.test_assert_path_exists('//SwitchStatNode')
@cython.test_fail_if_path_exists('//ForInStatNode')
def index_and_in():
    """
    >>> index_and_in()
    1
    3
    4
    7
    8
    """
    cdef int i
    for i in range(1,9):
        if u'abcdefgh'[-i] in u'abCDefGh':
            print i


def uchar_lookup_in_dict(obj, Py_UNICODE uchar):
    """
    >>> d = {u_KLINGON: 1234, u0: 0, u1: 1, u_A: 2}
    >>> uchar_lookup_in_dict(d, u_KLINGON)
    (1234, 1234)
    >>> uchar_lookup_in_dict(d, u_A)
    (2, 2)
    >>> uchar_lookup_in_dict(d, u0)
    (0, 0)
    >>> uchar_lookup_in_dict(d, u1)
    (1, 1)
    """
    cdef dict d = obj
    dval = d[uchar]
    objval = obj[uchar]
    return dval, objval


_WARNINGS = """
250:16: Item lookup of unicode character codes now always converts to a Unicode string. Use an explicit C integer cast to get back the previous integer lookup behaviour.
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pyarray.pyx0000644000175100001770000001021700000000000017774 0ustar00runnerdocker00000000000000# tag: array

import array  # Python builtin module  
from cpython cimport array  # array.pxd / arrayarray.h

a = array.array('f', [1.0, 2.0, 3.0])

def test_len(a):
    """
    >>> a = array.array('f', [1.0, 2.0, 3.0])
    >>> len(a)
    3
    >>> int(test_len(a))
    3
    >>> assert len(a) == test_len(a)
    """
    cdef array.array ca = a  # for C-fast array usage
    return len(ca)

def test_copy(a):
    """
    >>> a = array.array('f', [1.0, 2.0, 3.0])
    >>> test_copy(a)
    array('f', [1.0, 2.0, 3.0])
    """
    cdef array.array ca = a
    cdef array.array b
    b = array.copy(ca)
    assert a == b
    a[2] = 3.5
    assert b[2] != a[2]
    return b


def test_fast_access(a):
    """
    >>> a = array.array('f', [1.0, 2.0, 3.0])
    >>> test_fast_access(a)
    """
    
    cdef array.array ca = a
    
    cdef float value
    with nogil:
        value = ca.data.as_floats[1]
    assert value == 2.0, value

    #assert ca._c[:5] == b'\x00\x00\x80?\x00', repr(ca._c[:5])

    with nogil:
        ca.data.as_floats[1] += 2.0
    assert ca.data.as_floats[1] == 4.0


def test_fast_buffer_access(a):
    """
    >>> a = array.array('f', [1.0, 2.0, 3.0])
    >>> test_fast_buffer_access(a)
    """
    
    cdef array.array[float] ca = a
    
    cdef float value
    with nogil:
        value = ca[1]
    assert value == 2.0, value

    with nogil:
        ca[1] += 2.0
    assert ca[1] == 4.0


def test_new_zero(a):
    """
    >>> a = array.array('f', [1.0, 2.0, 3.0])
    >>> test_new_zero(a)
    array('f', [0.0, 0.0, 0.0])
    """
    cdef array.array cb = array.clone(a, len(a), True)
    assert len(cb) == len(a)
    return cb


def test_set_zero(a):
    """
    >>> a = array.array('f', [1.0, 2.0, 3.0])
    >>> test_set_zero(a)
    array('f', [0.0, 0.0, 0.0])
    """
    cdef array.array cb = array.copy(a)
    array.zero(cb)
    assert a[1] != 0.0, a
    assert cb[1] == 0.0, cb
    return cb

def test_resize(a):
    """
    >>> a = array.array('f', [1.0, 2.0, 3.0])
    >>> test_resize(a)
    """
    cdef array.array cb = array.copy(a)
    array.resize(cb, 10)
    for i in range(10):
        cb.data.as_floats[i] = i
    assert len(cb) == 10
    assert cb[9] == cb[-1] == cb.data.as_floats[9] == 9

def test_resize_smart(a):
    """
    >>> a = array.array('d', [1, 2, 3])
    >>> test_resize_smart(a)
    2
    """
    cdef array.array cb = array.copy(a)
    array.resize_smart(cb, 2)
    return len(cb)

def test_buffer():
    """
    >>> test_buffer()
    """
    cdef object a = array.array('i', [1, 2, 3])
    cdef object[int] ca = a
    assert ca[0] == 1
    assert ca[2] == 3

def test_buffer_typed():
    """
    >>> test_buffer_typed()
    """
    cdef array.array a = array.array('i', [1, 2, 3])
    cdef object[int] ca = a
    assert ca[0] == 1
    assert ca[2] == 3

def test_view():
    """
    >>> test_view()
    """
    cdef object a = array.array('i', [1, 2, 3])
    cdef int[:] ca = a
    assert ca[0] == 1
    assert ca[2] == 3

def test_view_typed():
    """
    >>> test_view_typed()
    """
    cdef array.array a = array.array('i', [1, 2, 3])
    cdef int[:] ca = a
    assert ca[0] == 1
    assert ca[2] == 3

def test_extend():
    """
    >>> test_extend()
    """
    cdef array.array ca = array.array('i', [1, 2, 3])
    cdef array.array cb = array.array('i', [4, 5])
    cdef array.array cf = array.array('f', [1.0, 2.0, 3.0])
    array.extend(ca, cb)
    assert list(ca) == [1, 2, 3, 4, 5], list(ca)
    try:
        array.extend(ca, cf)
    except TypeError:
        pass
    else:
        assert False, 'extending incompatible array types did not raise'

def test_likes(a):
    """
    >>> a = array.array('f', [1.0, 2.0, 3.0])
    >>> test_likes(a)
    array('f', [0.0, 0.0, 0.0])
    """
    cdef array.array z = array.clone(a, len(a), True)
    cdef array.array e = array.clone(a, len(a), False)
    assert len(e) == len(a)
    return z

def test_extend_buffer():
    """
    >>> test_extend_buffer()
    array('l', [15, 37, 389, 5077])
    """
    cdef array.array ca = array.array('l', [15, 37])
    cdef long[2] s
    s[0] = 389
    s[1] = 5077
    array.extend_buffer(ca,  &s, 2)

    assert ca.data.as_ulongs[3] == 5077
    assert len(ca) == 4
    return ca
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pycapsule.pyx0000644000175100001770000000150600000000000020313 0ustar00runnerdocker00000000000000# mode: run

import gc
from cpython cimport pycapsule

cdef int value = 5
cdef bint destructed = False

cdef void destructor(object obj) noexcept:
    # PyPy's GC does not guarantee immediate execution.
    global destructed
    destructed = True


def was_destructed():
    return destructed


def test_capsule():
    """
    >>> test_capsule()
    True
    >>> _ = gc.collect()
    >>> was_destructed()  # let's assume that gc.collect() is enough to assert this
    True
    """
    capsule = pycapsule.PyCapsule_New(&value, b"simple value", &destructor)

    assert pycapsule.PyCapsule_GetName(capsule) == b"simple value"
    assert pycapsule.PyCapsule_GetPointer(capsule, b"simple value") is &value
    assert pycapsule.PyCapsule_GetDestructor(capsule) is &destructor

    return pycapsule.PyCapsule_IsValid(capsule, b"simple value")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pyclass_annotations_pep526.py0000644000175100001770000000302500000000000023310 0ustar00runnerdocker00000000000000# cython: language_level=3
# mode: run
# tag: pure3.7, pep526, pep484

from __future__ import annotations

import sys

try:
    from typing import ClassVar
except ImportError:  # Py<=3.5
    ClassVar = {int: int}

class NotAStr:
    pass

class PyAnnotatedClass:
    """
    >>> PyAnnotatedClass.__annotations__["CLASS_VAR"]
    'ClassVar[int]'
    >>> PyAnnotatedClass.__annotations__["obj"]
    'str'
    >>> PyAnnotatedClass.__annotations__["literal"]
    "'int'"
    >>> PyAnnotatedClass.__annotations__["recurse"]
    "'PyAnnotatedClass'"
    >>> PyAnnotatedClass.__annotations__["default"]
    'bool'
    >>> PyAnnotatedClass.CLASS_VAR
    1
    >>> PyAnnotatedClass.default
    False
    >>> PyAnnotatedClass.obj
    Traceback (most recent call last):
      ...
    AttributeError: type object 'PyAnnotatedClass' has no attribute 'obj'
    """
    CLASS_VAR: ClassVar[int] = 1
    obj: str
    literal: "int"
    recurse: "PyAnnotatedClass"
    default: bool = False
    # https://github.com/cython/cython/issues/4196 and https://github.com/cython/cython/issues/4198
    not_object: float = 0.1  # Shouldn't try to create a c attribute
    lie_about_type: str = NotAStr  # Shouldn't generate a runtime type-check


class PyVanillaClass:
    """
    Before Py3.10, unannotated classes did not have '__annotations__'.

    >>> try:
    ...     a = PyVanillaClass.__annotations__
    ... except AttributeError:
    ...     assert sys.version_info < (3, 10)
    ... else:
    ...     assert sys.version_info >= (3, 10)
    ...     assert a == {}
    """
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pyclass_dynamic_bases.pyx0000644000175100001770000000132400000000000022643 0ustar00runnerdocker00000000000000# mode: run
# tag: pyclass

class A(object):
    x = 1

class B(object):
    x = 2


def cond_if_bases(x):
    """
    >>> c = cond_if_bases(True)
    >>> c().p
    5
    >>> c().x
    1
    >>> c = cond_if_bases(False)
    >>> c().p
    5
    >>> c().x
    2
    """
    class PyClass(A if x else B):
        p = 5
    return PyClass


def make_subclass(*bases):
    """
    >>> cls = make_subclass(list)
    >>> issubclass(cls, list) or cls.__mro__
    True

    >>> class Cls(object): pass
    >>> cls = make_subclass(Cls, list)
    >>> issubclass(cls, list) or cls.__mro__
    True
    >>> issubclass(cls, Cls) or cls.__mro__
    True
    """
    # GH-3338
    class MadeClass(*bases):
        pass
    return MadeClass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pyclass_scope_T671.py0000644000175100001770000000313100000000000021502 0ustar00runnerdocker00000000000000# mode: run
# ticket: t671

A = 1234

class SimpleAssignment(object):
    """
    >>> SimpleAssignment.A
    1234
    """
    A = A

class SimpleRewrite(object):
    """
    >>> SimpleRewrite.A
    4321
    """
    A = 4321
    A = A

def simple_inner(a):
    """
    >>> simple_inner(4321).A
    1234
    """
    A = a
    class X(object):
        A = A
    return X

def conditional(a, cond):
    """
    >>> conditional(4321, False).A
    1234
    >>> conditional(4321, True).A
    4321
    """
    class X(object):
        if cond:
            A = a
        A = A
    return X

def name_error():
    """
    >>> name_error() #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    NameError: ...B...
    """
    class X(object):
        B = B

def conditional_name_error(cond):
    """
    >>> conditional_name_error(True).B
    4321
    >>> conditional_name_error(False).B #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    NameError: ...B...
    """
    class X(object):
        if cond:
            B = 4321
        B = B
    return X

C = 1111
del C

def name_error_deleted():
    """
    >>> name_error_deleted() #doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    NameError: ...C...
    """
    class X(object):
        C = C

_set = set

def name_lookup_order():
    """
    >>> Scope = name_lookup_order()
    >>> Scope().set(2)
    42
    >>> Scope.test1 == _set()
    True
    >>> Scope.test2 == _set()
    True

    """
    class Scope(object):
        test1 = set()
        test2 = set()

        def set(self, x):
            return 42

    return Scope
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pyclass_special_methods.pyx0000644000175100001770000000165500000000000023214 0ustar00runnerdocker00000000000000# mode: run
# tag: pyclass, getattr

"""
Python bypasses __getattribute__ overrides for some special method lookups.
"""

lookups = []


class PyClass(object):
    """
    >>> del lookups[:]
    >>> obj = PyClass()
    >>> obj.test
    'getattribute(test)'
    >>> lookups
    ['getattribute(test)']
    """
    def __getattribute__(self, name):
        lookup = 'getattribute(%s)' % name
        lookups.append(lookup)
        return lookup

    def __getattr__(self, name):
        lookup = 'getattr(%s)' % name
        lookups.append(lookup)
        return lookup


def use_as_context_manager(obj):
    """
    >>> del lookups[:]
    >>> class PyCM(PyClass):
    ...     def __enter__(self): return '__enter__(%s)' % (self is obj or self)
    ...     def __exit__(self, *args): pass
    >>> obj = PyCM()
    >>> use_as_context_manager(obj)
    '__enter__(True)'
    >>> lookups
    []
    """
    with obj as x:
        pass
    return x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pycmp.pyx0000644000175100001770000000102500000000000017432 0ustar00runnerdocker00000000000000def f():
    """
    >>> f()
    """
    cdef int bool, int1, int2
    cdef object obj1, obj2
    int1 = 0
    int2 = 0
    obj1 = 1
    obj2 = 2
    bool = obj1 == obj2
    assert not bool
    bool = obj1 <> int2
    assert bool
    bool = int1 == obj2
    assert not bool
    bool = obj1 is obj2
    assert not bool
    bool = obj1 is not obj2
    assert bool

def g():
    """
    >>> g()
    """
    cdef int bool
    obj1 = 1
    obj2 = []
    bool = obj1 in obj2
    assert not bool
    bool = obj1 not in obj2
    assert bool
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pycontextvar.pyx0000644000175100001770000000277400000000000021064 0ustar00runnerdocker00000000000000# mode: run

from cpython.contextvars cimport (
    PyContextVar_New, PyContextVar_New_with_default,
    get_value, get_value_no_default,
)

NOTHING = object()
CVAR = PyContextVar_New("cvar", NULL)
CVAR_WITH_DEFAULT = PyContextVar_New_with_default("cvar_wd", "DEFAULT")


import contextvars
PYCVAR = contextvars.ContextVar("pycvar")

def disable_for_pypy737(f):
    import sys
    # will be fixed in PyPy 7.3.8
    if hasattr(sys, 'pypy_version_info') and sys.pypy_version_info < (7,3,8):
        return None
    return f


@disable_for_pypy737
def test_get_value(var, default=NOTHING):
    """
    >>> test_get_value(CVAR)
    >>> test_get_value(CVAR, "default")
    'default'
    >>> test_get_value(PYCVAR)
    >>> test_get_value(PYCVAR, "default")
    'default'
    >>> test_get_value(CVAR_WITH_DEFAULT)
    'DEFAULT'
    >>> test_get_value(CVAR_WITH_DEFAULT, "default")
    'DEFAULT'
    """
    return get_value(var, default) if default is not NOTHING else get_value(var)


@disable_for_pypy737
def test_get_value_no_default(var, default=NOTHING):
    """
    >>> test_get_value_no_default(CVAR)
    >>> test_get_value_no_default(CVAR, "default")
    'default'
    >>> test_get_value_no_default(PYCVAR)
    >>> test_get_value_no_default(PYCVAR, "default")
    'default'
    >>> test_get_value_no_default(CVAR_WITH_DEFAULT)
    >>> test_get_value_no_default(CVAR_WITH_DEFAULT, "default")
    'default'
    """
    return get_value_no_default(var, default) if default is not NOTHING else get_value_no_default(var)

__test__ = {}
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pyextattrref.pyx0000644000175100001770000000055400000000000021051 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> s = Spam(Eggs("ham"))
    >>> test(s)
    'ham'
"""

cdef class Eggs:
    cdef object ham
    def __init__(self, ham):
        self.ham = ham

cdef class Spam:
    cdef Eggs eggs
    def __init__(self, eggs):
        self.eggs = eggs

cdef object tomato(Spam s):
    food = s.eggs.ham
    return food

def test(Spam s):
    return tomato(s)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pyfunction_redefine_T489.pyx0000644000175100001770000000176100000000000023100 0ustar00runnerdocker00000000000000# ticket: t489

"""
>>> xxx
[0, 1, 2, 3]
"""

xxx = []
foo = 0
xxx.append(foo)
def foo():
    return 1
xxx.append(foo())
def foo():
    return 2
xxx.append(foo())
foo = 3
xxx.append(foo)

def closure_scope(a):
    """
    >>> closure_scope(0)
    [0, 1, 'X', -4, 3]
    """
    ret = []
    foo = a + 0
    ret.append(foo)
    def foo():
        return a + 1
    ret.append(foo())
    def foo():
        return 'X'
    ret.append(foo())
    def foo(b):
        return a - b
    ret.append(foo(4))
    foo = a + 3
    ret.append(foo)
    return ret

class ClassScope(object):
    """
    >>> obj = ClassScope()
    [0, 1, 2, 3]
    """
    x = []
    def __init__(self):
        r = []
        for x in self.x:
            if isinstance(x, int):
                r.append(x)
            else:
                r.append(x(self))
        print r
    foo = 0
    x.append(foo)
    def foo(self):
        return 1
    x.append(foo)
    def foo(self):
        return 2
    x.append(foo)
    foo = 3
    x.append(foo)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pyintop.pyx0000644000175100001770000003333300000000000020013 0ustar00runnerdocker00000000000000# mode: run

cimport cython


def bigint(x):
    # avoid 'L' postfix in Py2.x
    print(str(x).rstrip('L'))

def bigints(x):
    # avoid 'L' postfix in Py2.x
    print(str(x).replace('L', ''))


@cython.test_assert_path_exists('//IntBinopNode')
def or_obj(obj2, obj3):
    """
    >>> or_obj(2, 3)
    3
    """
    obj1 = obj2 | obj3
    return obj1


@cython.test_fail_if_path_exists('//IntBinopNode')
def or_int(obj2):
    """
    >>> or_int(0)
    16
    >>> or_int(1)
    17
    >>> or_int(16)
    16
    """
    obj1 = obj2 | 0x10
    return obj1


@cython.test_assert_path_exists('//IntBinopNode')
def xor_obj(obj2, obj3):
    """
    >>> xor_obj(2, 3)
    1
    """
    obj1 = obj2 ^ obj3
    return obj1


@cython.test_fail_if_path_exists('//IntBinopNode')
def xor_int(obj2):
    """
    >>> xor_int(0)
    16
    >>> xor_int(2)
    18
    >>> xor_int(16)
    0
    """
    obj1 = obj2 ^ 0x10
    return obj1


@cython.test_assert_path_exists('//IntBinopNode')
def and_obj(obj2, obj3):
    """
    >>> and_obj(2, 3)
    2
    """
    obj1 = obj2 & obj3
    return obj1


@cython.test_fail_if_path_exists('//IntBinopNode')
def and_int(obj2):
    """
    >>> and_int(0)
    0
    >>> and_int(1)
    0
    >>> and_int(18)
    16
    >>> and_int(-1)
    16
    """
    obj1 = obj2 & 0x10
    return obj1


@cython.test_assert_path_exists('//IntBinopNode')
def lshift_obj(obj2, obj3):
    """
    >>> lshift_obj(2, 3)
    16
    """
    obj1 = obj2 << obj3
    return obj1


@cython.test_assert_path_exists('//IntBinopNode')
def rshift_obj(obj2, obj3):
    """
    >>> rshift_obj(2, 3)
    0
    """
    obj1 = obj2 >> obj3
    return obj1


@cython.test_assert_path_exists('//IntBinopNode')
def rshift_int_obj(obj3):
    """
    >>> rshift_int_obj(3)
    0
    >>> rshift_int_obj(2)
    0
    >>> rshift_int_obj(1)
    1
    >>> rshift_int_obj(0)
    2
    >>> rshift_int_obj(-1)
    Traceback (most recent call last):
    ValueError: negative shift count
    """
    obj1 = 2 >> obj3
    return obj1


@cython.test_fail_if_path_exists('//IntBinopNode')
def rshift_int(obj2):
    """
    >>> rshift_int(0)
    0
    >>> rshift_int(2)
    0

    >>> rshift_int(27)
    3
    >>> (-27) >> 3
    -4
    >>> rshift_int(-27)
    -4

    >>> rshift_int(32)
    4
    >>> (-32) >> 3
    -4
    >>> rshift_int(-32)
    -4

    >>> (2**28) >> 3
    33554432
    >>> rshift_int(2**28)
    33554432
    >>> (-2**28) >> 3
    -33554432
    >>> rshift_int(-2**28)
    -33554432

    >>> (2**30) >> 3
    134217728
    >>> rshift_int(2**30)
    134217728
    >>> rshift_int(-2**30)
    -134217728

    >>> bigint((2**60) >> 3)
    144115188075855872
    >>> bigint(rshift_int(2**60))
    144115188075855872
    >>> bigint(rshift_int(-2**60))
    -144115188075855872
    """
    obj1 = obj2 >> 3
    return obj1


@cython.test_assert_path_exists(
    '//SingleAssignmentNode//IntBinopNode',
    '//SingleAssignmentNode//PythonCapiCallNode',
)
def lshift_int(obj):
    """
    >>> lshift_int(0)
    (0, 0, 0, 0)
    >>> bigints(lshift_int(1))
    (8, 2147483648, 9223372036854775808, 10633823966279326983230456482242756608)
    >>> bigints(lshift_int(-1))
    (-8, -2147483648, -9223372036854775808, -10633823966279326983230456482242756608)
    >>> bigints(lshift_int(2))
    (16, 4294967296, 18446744073709551616, 21267647932558653966460912964485513216)

    >>> bigints(lshift_int(27))
    (216, 57982058496, 249031044995078946816, 287113247089541828547222325020554428416)
    >>> (-27) << 3
    -216
    >>> bigints(lshift_int(-27))
    (-216, -57982058496, -249031044995078946816, -287113247089541828547222325020554428416)

    >>> bigints(lshift_int(32))
    (256, 68719476736, 295147905179352825856, 340282366920938463463374607431768211456)
    >>> (-32) << 3
    -256
    >>> bigints(lshift_int(-32))
    (-256, -68719476736, -295147905179352825856, -340282366920938463463374607431768211456)

    >>> bigint((2**28) << 3)
    2147483648
    >>> bigints(lshift_int(2**28))
    (2147483648, 576460752303423488, 2475880078570760549798248448, 2854495385411919762116571938898990272765493248)
    >>> bigint((-2**28) << 3)
    -2147483648
    >>> bigints(lshift_int(-2**28))
    (-2147483648, -576460752303423488, -2475880078570760549798248448, -2854495385411919762116571938898990272765493248)

    >>> bigint((2**30) << 3)
    8589934592
    >>> bigints(lshift_int(2**30))
    (8589934592, 2305843009213693952, 9903520314283042199192993792, 11417981541647679048466287755595961091061972992)
    >>> bigints(lshift_int(-2**30))
    (-8589934592, -2305843009213693952, -9903520314283042199192993792, -11417981541647679048466287755595961091061972992)

    >>> bigint((2**60) << 3)
    9223372036854775808
    >>> bigints(lshift_int(2**60))
    (9223372036854775808, 2475880078570760549798248448, 10633823966279326983230456482242756608, 12259964326927110866866776217202473468949912977468817408)
    >>> bigints(lshift_int(-2**60))
    (-9223372036854775808, -2475880078570760549798248448, -10633823966279326983230456482242756608, -12259964326927110866866776217202473468949912977468817408)
    """
    r1 = obj << 3
    r2 = obj << 31
    r3 = obj << 63
    r4 = obj << 123
    return r1, r2, r3, r4


@cython.test_assert_path_exists(
    '//IntBinopNode',
    '//IntBinopNode//IntBinopNode',
)
def mixed_obj(obj2, obj3):
    """
    >>> mixed_obj(2, 3)
    16
    """
    obj1 = obj2 << obj3 | obj2 >> obj3
    return obj1


@cython.test_assert_path_exists(
    '//IntBinopNode',
    '//IntBinopNode//PythonCapiCallNode',
)
@cython.test_fail_if_path_exists(
    '//IntBinopNode//IntBinopNode',
)
def mixed_int(obj2):
    """
    >>> mixed_int(0)
    16
    >>> mixed_int(2)
    18
    >>> mixed_int(16)
    0
    >>> mixed_int(17)
    1
    """
    obj1 = (obj2 ^ 0x10) | (obj2 & 0x01)
    return obj1


@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists(
    '//IntBinopNode',
    '//PrimaryCmpNode',
)
def equals(obj2):
    """
    >>> equals(2)
    True
    >>> equals(0)
    False
    >>> equals(-1)
    False
    """
    result = obj2 == 2
    return result


@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists(
    '//IntBinopNode',
    '//PrimaryCmpNode',
)
def not_equals(obj2):
    """
    >>> not_equals(2)
    False
    >>> not_equals(0)
    True
    >>> not_equals(-1)
    True
    """
    result = obj2 != 2
    return result


@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_assert_path_exists('//PrimaryCmpNode')
def equals_many(obj2):
    """
    >>> equals_many(-2)
    (False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)
    >>> equals_many(0)
    (True, False, False, False, False, False, False, False, False, False, False, False, False, False, False)
    >>> equals_many(1)
    (False, True, False, False, False, False, False, False, False, False, False, False, False, False, False)
    >>> equals_many(-1)
    (False, False, True, False, False, False, False, False, False, False, False, False, False, False, False)
    >>> equals_many(2**30)
    (False, False, False, True, False, False, False, False, False, False, False, False, False, False, False)
    >>> equals_many(-2**30)
    (False, False, False, False, True, False, False, False, False, False, False, False, False, False, False)
    >>> equals_many(2**30-1)
    (False, False, False, False, False, True, False, False, False, False, False, False, False, False, False)
    >>> equals_many(-2**30+1)
    (False, False, False, False, False, False, True, False, False, False, False, False, False, False, False)
    >>> equals_many(2**32)
    (False, False, False, False, False, False, False, True, False, False, False, False, False, False, False)
    >>> equals_many(-2**32)
    (False, False, False, False, False, False, False, False, True, False, False, False, False, False, False)
    >>> equals_many(2**45-1)
    (False, False, False, False, False, False, False, False, False, True, False, False, False, False, False)
    >>> equals_many(-2**45+1)
    (False, False, False, False, False, False, False, False, False, False, True, False, False, False, False)
    >>> equals_many(2**64)
    (False, False, False, False, False, False, False, False, False, False, False, True, False, False, False)
    >>> equals_many(-2**64)
    (False, False, False, False, False, False, False, False, False, False, False, False, True, False, False)
    >>> equals_many(2**64-1)
    (False, False, False, False, False, False, False, False, False, False, False, False, False, True, False)
    >>> equals_many(-2**64+1)
    (False, False, False, False, False, False, False, False, False, False, False, False, False, False, True)
    """
    cdef bint x, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o
    a = obj2 == 0
    x = 0 == obj2
    assert a == x
    b = obj2 == 1
    x = 1 == obj2
    assert b == x
    c = obj2 == -1
    x = -1 == obj2
    assert c == x
    d = obj2 == 2**30
    x = 2**30 == obj2
    assert d == x
    e = obj2 == -2**30
    x = -2**30 == obj2
    assert e == x
    f = obj2 == 2**30-1
    x = 2**30-1 == obj2
    assert f == x
    g = obj2 == -2**30+1
    x = -2**30+1 == obj2
    assert g == x
    h = obj2 == 2**32
    x = 2**32 == obj2
    assert h == x
    i = obj2 == -2**32
    x = -2**32 == obj2
    assert i == x
    j = obj2 == 2**45-1
    x = 2**45-1 == obj2
    assert j == x
    k = obj2 == -2**45+1
    x = -2**45+1 == obj2
    assert k == x
    l = obj2 == 2**64
    x = 2**64 == obj2
    assert l == x
    m = obj2 == -2**64
    x = -2**64 == obj2
    assert m == x
    n = obj2 == 2**64-1
    x = 2**64-1 == obj2
    assert n == x
    o = obj2 == -2**64+1
    x = -2**64+1 == obj2
    assert o == x
    return (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)


@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_assert_path_exists('//PrimaryCmpNode')
def not_equals_many(obj2):
    """
    >>> not_equals_many(-2)
    (False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)
    >>> not_equals_many(0)
    (True, False, False, False, False, False, False, False, False, False, False, False, False, False, False)
    >>> not_equals_many(1)
    (False, True, False, False, False, False, False, False, False, False, False, False, False, False, False)
    >>> not_equals_many(-1)
    (False, False, True, False, False, False, False, False, False, False, False, False, False, False, False)
    >>> not_equals_many(2**30)
    (False, False, False, True, False, False, False, False, False, False, False, False, False, False, False)
    >>> not_equals_many(-2**30)
    (False, False, False, False, True, False, False, False, False, False, False, False, False, False, False)
    >>> not_equals_many(2**30-1)
    (False, False, False, False, False, True, False, False, False, False, False, False, False, False, False)
    >>> not_equals_many(-2**30+1)
    (False, False, False, False, False, False, True, False, False, False, False, False, False, False, False)
    >>> not_equals_many(2**32)
    (False, False, False, False, False, False, False, True, False, False, False, False, False, False, False)
    >>> not_equals_many(-2**32)
    (False, False, False, False, False, False, False, False, True, False, False, False, False, False, False)
    >>> not_equals_many(2**45-1)
    (False, False, False, False, False, False, False, False, False, True, False, False, False, False, False)
    >>> not_equals_many(-2**45+1)
    (False, False, False, False, False, False, False, False, False, False, True, False, False, False, False)
    >>> not_equals_many(2**64)
    (False, False, False, False, False, False, False, False, False, False, False, True, False, False, False)
    >>> not_equals_many(-2**64)
    (False, False, False, False, False, False, False, False, False, False, False, False, True, False, False)
    >>> not_equals_many(2**64-1)
    (False, False, False, False, False, False, False, False, False, False, False, False, False, True, False)
    >>> not_equals_many(-2**64+1)
    (False, False, False, False, False, False, False, False, False, False, False, False, False, False, True)
    """
    cdef bint a, b, c, d, e, f, g, h, i, j, k, l, m, n, o
    a = obj2 != 0
    x = 0 != obj2
    assert a == x
    b = obj2 != 1
    x = 1 != obj2
    assert b == x
    c = obj2 != -1
    x = -1 != obj2
    assert c == x
    d = obj2 != 2**30
    x = 2**30 != obj2
    assert d == x
    e = obj2 != -2**30
    x = -2**30 != obj2
    assert e == x
    f = obj2 != 2**30-1
    x = 2**30-1 != obj2
    assert f == x
    g = obj2 != -2**30+1
    x = -2**30+1 != obj2
    assert g == x
    h = obj2 != 2**32
    x = 2**32 != obj2
    assert h == x
    i = obj2 != -2**32
    x = -2**32 != obj2
    assert i == x
    j = obj2 != 2**45-1
    x = 2**45-1 != obj2
    assert j == x
    k = obj2 != -2**45+1
    x = -2**45+1 != obj2
    assert k == x
    l = obj2 != 2**64
    x = 2**64 != obj2
    assert l == x
    m = obj2 != -2**64
    x = -2**64 != obj2
    assert m == x
    n = obj2 != 2**64-1
    x = 2**64-1 != obj2
    assert n == x
    o = obj2 != -2**64+1
    x = -2**64+1 != obj2
    assert o == x
    return tuple(not x for x in (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o))


@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists(
    '//IntBinopNode',
    '//PrimaryCmpNode',
)
def equals_zero(obj2):
    """
    >>> equals_zero(2)
    False
    >>> equals_zero(0)
    True
    >>> equals_zero(-1)
    False
    """
    result = obj2 == 0
    return result


def truthy(obj2):
    """
    >>> truthy(2)
    True
    >>> truthy(0)
    False
    >>> truthy(-1)
    True
    """
    if obj2:
        return True
    else:
        return False

@cython.test_fail_if_path_exists("//CoerceToBooleanNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def test_avoid_if_coercion(obj):
    if obj == 1:  # this should not go through a Python intermediate
        return True
    else:
        return False
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pylistsubtype.pyx0000644000175100001770000000101400000000000021240 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> l1 = Sub1([1,2,3])
    >>> len(l1)
    3

    >>> l2 = Sub2([1,2,3])
    >>> len(l2)
    3

    >>> isinstance(l1, list)
    True
    >>> isinstance(l2, list)
    True
    >>> isinstance(l1, Sub1)
    True
    >>> isinstance(l1, Sub2)
    True
    >>> isinstance(l2, Sub1)
    False
    >>> isinstance(l2, Sub2)
    True
"""

cdef extern from *:
    ctypedef class __builtin__.list [ object PyListObject ]:
        pass

cdef class Sub2(list):
    cdef char character

cdef class Sub1(Sub2):
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pynumber_subtype_conversion.pyx0000644000175100001770000000073100000000000024166 0ustar00runnerdocker00000000000000# mode: run
# tag: python, float, builtin


class MyFloat(float):
    """
    >>> x = MyFloat(1.0)
    >>> x
    1.0
    >>> float(x)
    12.0
    >>> x.float()
    12.0
    """
    def __float__(self):
        return 12.0

    def float(self):
        return float(self)


class MyInt(int):
    """
    >>> x = MyInt(1)
    >>> x
    1
    >>> int(x)
    2
    >>> x.int()
    2
    """
    def __int__(self):
        return 2

    def int(self):
        return int(self)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pynumop.pyx0000644000175100001770000000037100000000000020014 0ustar00runnerdocker00000000000000def f():
    """
    >>> f()
    6
    """
    obj1 = 1
    obj2 = 2
    obj3 = 3
    obj1 = obj2 * obj3
    return obj1

def g():
    """
    >>> g()
    2
    """
    obj1 = 12
    obj2 = 6
    obj3 = 3
    obj1 = obj2 / obj3
    return int(obj1)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pyobjcast_T313.pyx0000644000175100001770000000052000000000000021011 0ustar00runnerdocker00000000000000# ticket: t313
# Ensure casting still works to void*

"""
>>> o = f()
>>> print(o[0])
teststring
>>> print(o[1])
teststring
"""

cdef extern from *:
    ctypedef void PyObject

def f():
    cdef void* p1
    cdef PyObject* p2
    cdef object a = u"teststring"
    p1 = a
    p2 = a
    return (p1, p2)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pyparam_nogil.pyx0000644000175100001770000000045200000000000021146 0ustar00runnerdocker00000000000000
def if_list_nogil(list obj):
    """
    >>> if_list_nogil( [] )
    False
    >>> if_list_nogil( [1] )
    True
    >>> if_list_nogil(None)
    False
    """
    return _if_list_nogil(obj)

cdef bint _if_list_nogil(list obj) nogil:
    if obj:
        return True
    else:
        return False

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/python_bool_type.pyx0000644000175100001770000001173100000000000021704 0ustar00runnerdocker00000000000000
# tests copied from test/test_bool.py in Py2.7

cdef assertEqual(a,b):
    assert a == b, '%r != %r' % (a,b)

cdef assertIs(a,b):
    assert a is b, '%r is not %r' % (a,b)

cdef assertIsNot(a,b):
    assert a is not b, '%r is %r' % (a,b)

cdef assertNotIsInstance(a,b):
    assert not isinstance(a,b), 'isinstance(%r, %s)' % (a,b)


def test_int():
    """
    >>> test_int()
    """
    assertEqual(int(False), 0)
    assertIsNot(int(False), False)
    assertEqual(int(True), 1)
    assertIsNot(int(True), True)

def test_float():
    """
    >>> test_float()
    """
    assertEqual(float(False), 0.0)
    assertIsNot(float(False), False)
    assertEqual(float(True), 1.0)
    assertIsNot(float(True), True)

def test_repr():
    """
    >>> test_repr()
    """
    assertEqual(repr(False), 'False')
    assertEqual(repr(True), 'True')
    assertEqual(eval(repr(False)), False)
    assertEqual(eval(repr(True)), True)

def test_str():
    """
    >>> test_str()
    """
    assertEqual(str(False), 'False')
    assertEqual(str(True), 'True')

def test_math():
    """
    >>> test_math()
    """
    assertEqual(+False, 0)
    assertIsNot(+False, False)
    assertEqual(-False, 0)
    assertIsNot(-False, False)
    assertEqual(abs(False), 0)
    assertIsNot(abs(False), False)
    assertEqual(+True, 1)
    assertIsNot(+True, True)
    assertEqual(-True, -1)
    assertEqual(abs(True), 1)
    assertIsNot(abs(True), True)
    assertEqual(~False, -1)
    assertEqual(~True, -2)

    assertEqual(False+2, 2)
    assertEqual(True+2, 3)
    assertEqual(2+False, 2)
    assertEqual(2+True, 3)

    assertEqual(False+False, 0)
    assertIsNot(False+False, False)
    assertEqual(False+True, 1)
    assertIsNot(False+True, True)
    assertEqual(True+False, 1)
    assertIsNot(True+False, True)
    assertEqual(True+True, 2)

    assertEqual(True-True, 0)
    assertIsNot(True-True, False)
    assertEqual(False-False, 0)
    assertIsNot(False-False, False)
    assertEqual(True-False, 1)
    assertIsNot(True-False, True)
    assertEqual(False-True, -1)

    assertEqual(True*1, 1)
    assertEqual(False*1, 0)
    assertIsNot(False*1, False)

    assertEqual(True/1, 1)
    assertIsNot(True/1, True)
    assertEqual(False/1, 0)
    assertIsNot(False/1, False)

    for b in False, True:
        for i in 0, 1, 2:
            assertEqual(b**i, int(b)**i)
            assertIsNot(b**i, bool(int(b)**i))

    for a in False, True:
        for b in False, True:
            assertIs(a&b, bool(int(a)&int(b)))
            assertIs(a|b, bool(int(a)|int(b)))
            assertIs(a^b, bool(int(a)^int(b)))
            assertEqual(a&int(b), int(a)&int(b))
            assertIsNot(a&int(b), bool(int(a)&int(b)))
            assertEqual(a|int(b), int(a)|int(b))
            assertIsNot(a|int(b), bool(int(a)|int(b)))
            assertEqual(a^int(b), int(a)^int(b))
            assertIsNot(a^int(b), bool(int(a)^int(b)))
            assertEqual(int(a)&b, int(a)&int(b))
            assertIsNot(int(a)&b, bool(int(a)&int(b)))
            assertEqual(int(a)|b, int(a)|int(b))
            assertIsNot(int(a)|b, bool(int(a)|int(b)))
            assertEqual(int(a)^b, int(a)^int(b))
            assertIsNot(int(a)^b, bool(int(a)^int(b)))

    assertIs(1==1, True)
    assertIs(1==0, False)
    assertIs(0<1, True)
    assertIs(1<0, False)
    assertIs(0<=0, True)
    assertIs(1<=0, False)
    assertIs(1>0, True)
    assertIs(1>1, False)
    assertIs(1>=1, True)
    assertIs(0>=1, False)
    assertIs(0!=1, True)
    assertIs(0!=0, False)

    y = x = [1]
    assertIs(x is y, True)
    assertIs(x is not y, False)

    assertIs(1 in x, True)
    assertIs(0 in x, False)
    assertIs(1 not in x, False)
    assertIs(0 not in x, True)

    y = x = {1: 2}
    assertIs(x is y, True)
    assertIs(x is not y, False)

    assertIs(1 in x, True)
    assertIs(0 in x, False)
    assertIs(1 not in x, False)
    assertIs(0 not in x, True)

    assertIs(not True, False)
    assertIs(not False, True)

def test_convert():
    """
    >>> test_convert()
    """
    assertIs(bool(10), True)
    assertIs(bool(1), True)
    assertIs(bool(-1), True)
    assertIs(bool(0), False)
    assertIs(bool("hello"), True)
    assertIs(bool(""), False)
    assertIs(bool(), False)

def test_isinstance():
    """
    >>> test_isinstance()
    """
    assertIs(isinstance(True, bool), True)
    assertIs(isinstance(False, bool), True)
    assertIs(isinstance(True, int), True)
    assertIs(isinstance(False, int), True)
    assertIs(isinstance(1, bool), False)
    assertIs(isinstance(0, bool), False)

def test_issubclass():
    """
    >>> test_issubclass()
    """
    assertIs(issubclass(bool, int), True)
    assertIs(issubclass(int, bool), False)

def test_boolean():
    """
    >>> test_boolean()
    """
    assertEqual(True & 1, 1)
    assertNotIsInstance(True & 1, bool)
    assertIs(True & True, True)

    assertEqual(True | 1, 1)
    assertNotIsInstance(True | 1, bool)
    assertIs(True | True, True)

    assertEqual(True ^ 1, 0)
    assertNotIsInstance(True ^ 1, bool)
    assertIs(True ^ True, False)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/pytype.pyx0000644000175100001770000000060100000000000017633 0ustar00runnerdocker00000000000000from cpython.type cimport PyType_IsSubtype

class mylist(list): pass

def test_issubtype(a, b):
    """
    >>> test_issubtype(mylist, list)
    True
    >>> test_issubtype(mylist, dict)
    False

    >>> o = object()
    >>> test_issubtype(o, list)
    Traceback (most recent call last):
    ...
    TypeError: Cannot convert object to type
    """
    return PyType_IsSubtype(a, b)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/qualname.py0000644000175100001770000001040000000000000017712 0ustar00runnerdocker00000000000000# cython: binding=True
# mode: run
# tag: cyfunction, qualname, pure3.5

from __future__ import print_function

import cython
import sys


def test_qualname():
    """
    >>> test_qualname.__qualname__
    'test_qualname'
    >>> test_qualname.__qualname__ = 123 #doctest:+ELLIPSIS
    Traceback (most recent call last):
    TypeError: __qualname__ must be set to a ... object
    >>> test_qualname.__qualname__ = 'foo'
    >>> test_qualname.__qualname__
    'foo'
    """


def test_builtin_qualname():
    """
    >>> test_builtin_qualname()
    list.append
    len
    """
    if sys.version_info >= (3, 3):
        print([1, 2, 3].append.__qualname__)
        print(len.__qualname__)
    else:
        print('list.append')
        print('len')


def test_nested_qualname():
    """
    >>> outer, lambda_func, XYZ = test_nested_qualname()
    defining class XYZ XYZ qualname
    defining class Inner XYZ.Inner qualname

    >>> outer_result = outer()
    defining class Test test_nested_qualname..outer..Test qualname
    >>> outer_result.__qualname__
    'test_nested_qualname..outer..Test'
    >>> outer_result.test.__qualname__
    'test_nested_qualname..outer..Test.test'

    >>> outer_result().test.__qualname__
    'test_nested_qualname..outer..Test.test'

    >>> outer_result_test_result = outer_result().test()
    defining class XYZInner XYZinner qualname
    >>> outer_result_test_result.__qualname__
    'XYZinner'
    >>> outer_result_test_result.Inner.__qualname__
    'XYZinner.Inner'
    >>> outer_result_test_result.Inner.inner.__qualname__
    'XYZinner.Inner.inner'

    >>> lambda_func.__qualname__
    'test_nested_qualname..'

    >>> XYZ.__qualname__
    'XYZ'
    >>> XYZ.Inner.__qualname__
    'XYZ.Inner'
    >>> XYZ.Inner.inner.__qualname__
    'XYZ.Inner.inner'
    """
    def outer():
        class Test(object):
            print("defining class Test", __qualname__, __module__)
            def test(self):
                global XYZinner
                class XYZinner:
                    print("defining class XYZInner", __qualname__, __module__)
                    class Inner:
                        def inner(self):
                            pass

                return XYZinner
        return Test

    global XYZ
    class XYZ(object):
        print("defining class XYZ", __qualname__, __module__)
        class Inner(object):
            print("defining class Inner", __qualname__, __module__)
            def inner(self):
                pass

    return outer, lambda:None, XYZ


@cython.cclass
class CdefClass:
    """
    >>> print(CdefClass.qn, CdefClass.m)
    CdefClass qualname
    >>> print(CdefClass.__qualname__, CdefClass.__module__)
    CdefClass qualname

    #>>> print(CdefClass.l["__qualname__"], CdefClass.l["__module__"])
    #CdefClass qualname
    """
    qn = __qualname__
    m = __module__

    # TODO - locals and cdef classes is unreliable, irrespective of qualname
    # l = locals().copy()


# TODO - locals and cdef classes is unreliable, irrespective of qualname
#@cython.cclass
#class CdefOnlyLocals:
#    """
#    >>> print(CdefOnlyLocals.l["__qualname__"], CdefOnlyLocals.l["__module__"])
#    CdefOnlyLocals qualname
#    """
#    l = locals().copy()

@cython.cclass
class CdefModifyNames:
    """
    >>> print(CdefModifyNames.qn_reassigned, CdefModifyNames.m_reassigned)
    I'm not a qualname I'm not a module

    # TODO - enable when https://github.com/cython/cython/issues/4815 is fixed
    #>>> hasattr(CdefModifyNames, "qn_deleted")
    #False
    #>>> hasattr(CdefModifyNames, "m_deleted")
    #False

    #>>> print(CdefModifyNames.l["__qualname__"], CdefModifyNames.l["__module__"])
    #I'm not a qualname I'm not a module
    """
    __qualname__ = "I'm not a qualname"
    __module__ = "I'm not a module"
    qn_reassigned = __qualname__
    m_reassigned = __module__
    # TODO - locals and cdef classes is unreliable, irrespective of qualname
    #l = locals().copy()
    # TODO del inside cdef class scope is broken
    # https://github.com/cython/cython/issues/4815
    #del __qualname__
    #del __module__
    #try:
    #    qn_deleted = __qualname__
    #except NameError:
    #    pass
    #try:
    #    m_deleted = __module__
    #except NameError:
    #    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_addint.pyx0000644000175100001770000000057100000000000020073 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> def test(a, b):
    ...     return (a, b, add(a, b))

    >>> test(1, 2)
    (1, 2, 3)
    >>> [ repr(f) for f in test(17.25, 88.5) ]
    ['17.25', '88.5', '105.75']
    >>> test(u'eggs', u'spam')
    (u'eggs', u'spam', u'eggsspam')
"""

import sys
if sys.version_info[0] >= 3:
    __doc__ = __doc__.replace(u"u'", u"'")

def add(x, y):
    return x + y
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_argdefault.pyx0000644000175100001770000000107400000000000020745 0ustar00runnerdocker00000000000000def swallow(name = None, airspeed = None, coconuts = None):
    """
    >>> swallow(name = "Brian")
    This swallow is called Brian
    >>> swallow(airspeed = 42)
    This swallow is flying at 42 furlongs per fortnight
    >>> swallow(coconuts = 3)
    This swallow is carrying 3 coconuts
    """
    if name is not None:
        print u"This swallow is called", name
    if airspeed is not None:
        print u"This swallow is flying at", airspeed, u"furlongs per fortnight"
    if coconuts is not None:
        print u"This swallow is carrying", coconuts, u"coconuts"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_barbieri1.pyx0000644000175100001770000000062200000000000020465 0ustar00runnerdocker00000000000000__doc__ = u"""
  >>> try:
  ...     B()
  ... except Exception, e:
  ...     print("%s: %s" % (e.__class__.__name__, e))
  Exception: crash-me
"""

import sys
if sys.version_info[0] >= 3:
    __doc__ = __doc__.replace(u"Exception, e", u"Exception as e")

cdef class A:
    def __cinit__(self):
        raise Exception(u"crash-me")

cdef class B(A):
    def __cinit__(self):
        print "hello world"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_bishop3.pyx0000644000175100001770000000051300000000000020173 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> foo = Foo()
>>> fee = Fee()
>>> faa = Faa()
>>> fee.bof()
Fee bof 0
>>> faa.bof()
Foo bof 0
"""

cdef class Foo:
  cdef int val

  def __init__(self):
    self.val = 0


cdef class Fee(Foo):

  def bof(self):
    print u'Fee bof', self.val


cdef class Faa(Fee):

  def bof(self):
    print u'Foo bof', self.val
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_bowden1.pyx0000644000175100001770000000040700000000000020165 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> f(100)
101L
>>> g(3000000000)
3000000001L
"""

import sys
if sys.version_info[0] >= 3:
    __doc__ = __doc__.replace(u"L", u"")

def f(x):
    cdef unsigned long long ull
    ull = x
    return ull + 1

def g(unsigned long x):
    return x + 1
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_delgado_1.pyx0000644000175100001770000000050000000000000020437 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> try:
...     eggs().eat()
... except RuntimeError:
...    import sys
...    e = sys.exc_info()[1]
...    print("%s: %s" % (e.__class__.__name__, e))
RuntimeError: I don't like that
"""

cdef class eggs:

  def __dealloc__(self):
    pass

  def eat(self):
    raise RuntimeError(u"I don't like that")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_docstrings.pyx0000644000175100001770000000552100000000000021007 0ustar00runnerdocker00000000000000# Some comments first


# More comments

'A module docstring'

doctest = u"""# Python 3 gets all of these right ...
    >>> __doc__
    'A module docstring'

    >>> f.__doc__
    '\\n    This is a function docstring.\\n    '

    >>> C.__doc__
    '\\n    This is a class docstring.\\n    '
    >>> C.docstring_copy_C
    '\\n    This is a class docstring.\\n    '
    >>> CS.docstring_copy_C
    '\\n    This is a class docstring.\\n    '

    >>> CS.__doc__
    '\\n    This is a subclass docstring.\\n    '
    >>> CS.docstring_copy_CS
    '\\n    This is a subclass docstring.\\n    '
    >>> CSS.docstring_copy_CS
    '\\n    This is a subclass docstring.\\n    '
    >>> print(CSS.__doc__)
    None
    >>> CSS.docstring_copy_CSS
    'A module docstring'

    >>> T.__doc__
    '\\n    This is an extension type docstring.\\n    '
    >>> TS.__doc__
    '\\n    This is an extension subtype docstring.\\n    '
    >>> TSS.__doc__

Compare with standard Python:

    >>> def Pyf():
    ...     '''
    ...     This is a function docstring.
    ...     '''
    >>> Pyf.__doc__
    '\\n    This is a function docstring.\\n    '

    >>> class PyC(object):
    ...     '''
    ...     This is a class docstring.
    ...     '''
    ...     docstring_copy_C = __doc__
    >>> class PyCS(PyC):
    ...     '''
    ...     This is a subclass docstring.
    ...     '''
    ...     docstring_copy_CS = __doc__
    >>> class PyCSS(PyCS):
    ...     docstring_copy_CSS = __doc__

    >>> PyC.__doc__
    '\\n    This is a class docstring.\\n    '
    >>> PyC.docstring_copy_C
    '\\n    This is a class docstring.\\n    '
    >>> PyCS.docstring_copy_C
    '\\n    This is a class docstring.\\n    '
    >>> PyCSS.docstring_copy_C
    '\\n    This is a class docstring.\\n    '

    >>> PyCS.__doc__
    '\\n    This is a subclass docstring.\\n    '
    >>> PyCS.docstring_copy_CS
    '\\n    This is a subclass docstring.\\n    '
    >>> PyCSS.docstring_copy_CS
    '\\n    This is a subclass docstring.\\n    '

    >>> PyCSS.__doc__
    >>> PyCSS.docstring_copy_CSS
    'A module docstring'
"""

__test__ = {"test_docstrings" : doctest}

def f():
    """
    This is a function docstring.
    """


class C(object):
    """
    This is a class docstring.
    """
    docstring_copy_C = __doc__


class CS(C):
    """
    This is a subclass docstring.
    """
    docstring_copy_CS = __doc__


class CSS(CS):
    docstring_copy_CSS = __doc__


cdef class T:
    """
    This is an extension type docstring.
    """

cdef class TS(T):
    """
    This is an extension subtype docstring.
    """

cdef class TSS(TS):
    pass


def n():
    "This is not a docstring".lower()

class PyN(object):
    u"This is not a docstring".lower()

cdef class CN(object):
    b"This is not a docstring".lower()


def test_non_docstrings():
    """
    >>> n.__doc__
    >>> PyN.__doc__
    >>> CN.__doc__
    """
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_extcomplex2.pyx0000644000175100001770000000065500000000000021105 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> c = eggs()
    >>> c
    (17+42j)
    >>> spam(c)
    Real: 17.0
    Imag: 42.0
"""

cdef extern from "complexobject.h":

    struct Py_complex:
        double real
        double imag

    ctypedef class __builtin__.complex [object PyComplexObject]:
        cdef Py_complex cval

def spam(complex c):
    print u"Real:", c.cval.real
    print u"Imag:", c.cval.imag

def eggs():
    return complex(17, 42)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_extstarargs.pyx0000644000175100001770000000162100000000000021174 0ustar00runnerdocker00000000000000__doc__ = u"""
  >>> s = Swallow("Brian", 42)
  Name: Brian
  Airspeed: 42
  Extra args: ()
  Extra keywords: []

  >>> s = Swallow("Brian", 42, "African")
  Name: Brian
  Airspeed: 42
  Extra args: ('African',)
  Extra keywords: []

  >>> s = Swallow("Brian", airspeed = 42)
  Name: Brian
  Airspeed: 42
  Extra args: ()
  Extra keywords: []

  >>> s = Swallow("Brian", airspeed = 42, species = "African", coconuts = 3)
  Name: Brian
  Airspeed: 42
  Extra args: ()
  Extra keywords: [('coconuts', 3), ('species', 'African')]

  >>> s = Swallow("Brian", 42, "African", coconuts = 3)
  Name: Brian
  Airspeed: 42
  Extra args: ('African',)
  Extra keywords: [('coconuts', 3)]
"""

cdef class Swallow:

    def __init__(self, name, airspeed, *args, **kwds):
        print u"Name:", name
        print u"Airspeed:", airspeed
        print u"Extra args:", args
        print u"Extra keywords:", sorted(kwds.items())
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_forloop.pyx0000644000175100001770000000546500000000000020317 0ustar00runnerdocker00000000000000def go_py():
    """
    >>> go_py()
    Spam!
    Spam!
    Spam!
    Spam!
    """
    for i in range(4):
        print u"Spam!"

def go_py_ret():
    """
    >>> go_py_ret()
    2
    """
    for i in range(4):
        if i > 1:
            return i

def go_c():
    """
    >>> go_c()
    Spam!
    Spam!
    Spam!
    Spam!
    """
    cdef int i
    for i in range(4):
        print u"Spam!"

def go_c_enumerate():
    """
    >>> go_c_enumerate()
    True
    True
    True
    True
    """
    cdef int i,k
    for i,k in enumerate(range(4)):
        print i == k

def go_c_int(int a, int b):
    """
    >>> go_c_int(1,5)
    Spam!
    Spam!
    """
    cdef int i
    for i in range(a,b,2):
        print u"Spam!"

def go_c_all():
    """
    >>> go_c_all()
    Spam!
    Spam!
    Spam!
    """
    cdef int i
    for i in range(8,2,-2):
        print u"Spam!"

def go_c_all_exprs(x):
    """
    >>> go_c_all_exprs(1)
    Spam!
    >>> go_c_all_exprs(3)
    Spam!
    Spam!
    """
    cdef long i
    for i in range(4*x,2*x,-3):
        print u"Spam!"

def go_c_const_exprs():
    """
    >>> go_c_const_exprs()
    Spam!
    Spam!
    """
    cdef int i
    for i in range(4*2+1,2*2,-2-1):
        print u"Spam!"

def f(x):
    return 2*x

def go_c_calc(x):
    """
    >>> go_c_calc(2)
    Spam!
    Spam!
    """
    cdef long i
    for i in range(2*f(x),f(x), -2):
        print u"Spam!"

def go_c_calc_ret(x):
    """
    >>> go_c_calc_ret(2)
    6
    """
    cdef long i
    for i in range(2*f(x),f(x), -2):
        if i < 2*f(x):
            return i

def go_c_ret():
    """
    >>> go_c_ret()
    2
    """
    cdef int i
    for i in range(4):
        if i > 1:
            return i

def go_list():
    """
    >>> go_list()
    Spam!
    Spam!
    Spam!
    Spam!
    """
    cdef list l = list(range(4))
    for i in l:
        print u"Spam!"

def go_list_ret():
    """
    >>> go_list_ret()
    2
    """
    cdef list l = list(range(4))
    for i in l:
        if i > 1:
            return i

def go_tuple():
    """
    >>> go_tuple()
    Spam!
    Spam!
    Spam!
    Spam!
    """
    cdef tuple t = tuple(range(4))
    for i in t:
        print u"Spam!"

def go_tuple_ret():
    """
    >>> go_tuple_ret()
    2
    """
    cdef tuple t = tuple(range(4))
    for i in t:
        if i > 1:
            return i

def go_dict():
    """
    >>> go_dict()
    Spam!
    Spam!
    Spam!
    Spam!
    """
    cdef dict d = dict(zip(range(4), range(4)))
    for i in d:
        print u"Spam!"

def go_dict_ret():
    """
    >>> go_dict_ret()
    2
    >>> global_result
    6
    """
    cdef dict d = dict(zip(range(4), range(4)))
    for i in d:
        if i > 1 and i < 3:
            return i

# test global scope also
global_result = None
cdef int i
for i in range(4*2+1,2*2,-2-1):
    if i < 7:
        global_result = i
        break
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_hordijk1.pyx0000644000175100001770000000103100000000000020333 0ustar00runnerdocker00000000000000__doc__ = """
  >>> try:
  ...     s = Spam()
  ... except KeyError, e:
  ...     print("Exception: %s" % e)
  ... else:
  ...     print("Did not raise the expected exception")
  Exception: 'This is not a spanish inquisition'
"""

import sys
if sys.version_info[0] >= 3:
    __doc__ = __doc__.replace("Error, e", "Error as e")

cdef extern from "Python.h":
    ctypedef class __builtin__.list [object PyListObject]:
        pass

cdef class Spam(list):
    def __init__(self):
        raise KeyError("This is not a spanish inquisition")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_huss3.pyx0000644000175100001770000000100700000000000017670 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> try:
...     foo()
... except Exception, e:
...     print("%s: %s" % (e.__class__.__name__, e))
ValueError: 
>>> try:
...     bar()
... except Exception, e:
...     print("%s: %s" % (e.__class__.__name__, e))
"""

import sys
if sys.version_info[0] >= 3:
    __doc__ = __doc__.replace(u"Exception, e", u"Exception as e")

def bar():
    try:
        raise TypeError
    except TypeError:
        pass

def foo():
    try:
        raise ValueError
    except ValueError, e:
        bar()
        raise
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_jeff_epler_1.pyx0000644000175100001770000000017200000000000021146 0ustar00runnerdocker00000000000000def blowup(p):
    """
    >>> blowup([2, 3, 5])
    1
    """
    cdef int n, i
    n = 10
    i = 1
    return n % p[i]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_jiba1.pxd0000644000175100001770000000012200000000000017561 0ustar00runnerdocker00000000000000cdef class Parrot:
	cdef void describe(self)

cdef class Norwegian(Parrot):
	pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_jiba1.pyx0000644000175100001770000000066500000000000017622 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> test()
    This parrot is resting.
    Lovely plumage!
"""


cdef class Parrot:

    cdef void describe(self):
        print u"This parrot is resting."

    def describe_python(self):
        self.describe()

cdef class Norwegian(Parrot):

    cdef void describe(self):
        print u"Lovely plumage!"

def test():
    cdef Parrot p1, p2
    p1 = Parrot()
    p2 = Norwegian()
    p1.describe()
    p2.describe()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_lepage_3.pyx0000644000175100001770000000034100000000000020302 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> g = Grail()
>>> g("spam", 42, ["tomato", "sandwich"])
Grail called with: spam 42 ['tomato', 'sandwich']
"""

cdef class Grail:

    def __call__(self, x, y, z):
        print u"Grail called with:", x, y, z
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_mang1.pyx0000644000175100001770000000050500000000000017630 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> import re
    >>> t
    (u'2',)
    >>> t == re.search('(\\d+)', '-2.80 98\\n').groups()
    True
"""

import sys
if sys.version_info[0] >= 3:
    __doc__ = __doc__.replace(u"(u'", u"('")

# this is a string constant test, not a test for 're'

import re
t = re.search(u'(\d+)', u'-2.80 98\n').groups()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_mcintyre1.pyx0000644000175100001770000000041400000000000020537 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> b = Bicycle()
    >>> b.fall_off()
    Falling off extremely hard
    >>> b.fall_off("somewhat")
    Falling off somewhat hard
"""

class Bicycle:

    def fall_off(self, how_hard = u"extremely"):
        print u"Falling off", how_hard, u"hard"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_mitch_chapman_2.pyx0000644000175100001770000000027000000000000021640 0ustar00runnerdocker00000000000000def boolExpressionsFail():
    """
    >>> boolExpressionsFail()
    'Not 2b'
    """
    dict = {1: 1}
    if not "2b" in dict:
        return "Not 2b"
    else:
        return "2b?"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_primes.pyx0000644000175100001770000000073600000000000020132 0ustar00runnerdocker00000000000000def primes(int kmax):
    """
    >>> primes(20)
    [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]
    """
    cdef int n, k, i
    cdef int[1000] p
    result = []
    if kmax > 1000:
        kmax = 1000
    k = 0
    n = 2
    while k < kmax:
        i = 0
        while i < k and n % p[i] <> 0:
            i = i + 1
        if i == k:
            p[k] = n
            k = k + 1
            result.append(n)
        n = n + 1
    return result
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_print.pyx0000644000175100001770000000023400000000000017760 0ustar00runnerdocker00000000000000def frighten():
    """
    >>> frighten()
    NOBODY expects the Spanish Inquisition!
    """
    print u"NOBODY", u"expects", u"the Spanish Inquisition!"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_pyclass.pyx0000644000175100001770000000034400000000000020304 0ustar00runnerdocker00000000000000class Spam:

    def __init__(self, w):
        self.weight = w

    def serve(self):
        print self.weight, u"tons of spam!"

def order():
    """
    >>> order()
    42 tons of spam!
    """
    s = Spam(42)
    s.serve()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_pyclassdefault.pyx0000644000175100001770000000121600000000000021650 0ustar00runnerdocker00000000000000__doc__ = u"""
  >>> c = CoconutCarrier()
  >>> c.swallow(name = "Brian")
  This swallow is called Brian
  >>> c.swallow(airspeed = 42)
  This swallow is flying at 42 furlongs per fortnight
  >>> c.swallow(coconuts = 3)
  This swallow is carrying 3 coconuts
"""

class CoconutCarrier:

    def swallow(self, name = None, airspeed = None, coconuts = None):
        if name is not None:
            print u"This swallow is called", name
        if airspeed is not None:
            print u"This swallow is flying at", airspeed, u"furlongs per fortnight"
        if coconuts is not None:
            print u"This swallow is carrying", coconuts, u"coconuts"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_pythonapi.pyx0000644000175100001770000000064600000000000020646 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> x = spam()
    >>> print(repr(x))
    u'Ftang\\x00Ftang!'
"""

import sys
if sys.version_info[0] >= 3:
    __doc__ = __doc__.replace(u" u'", u" '")

cdef extern from "string.h":
    void memcpy(char *d, char *s, int n)

from cpython cimport PyUnicode_DecodeUTF8

def spam():
    cdef char[12] buf
    memcpy(buf, "Ftang\0Ftang!", sizeof(buf))
    return PyUnicode_DecodeUTF8(buf, sizeof(buf), NULL)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_spamtype.pyx0000644000175100001770000000107400000000000020471 0ustar00runnerdocker00000000000000__doc__ = """
    >>> s = Spam()
    >>> s.get_tons()
    17
    >>> s.set_tons(42)
    >>> s.get_tons()
    42
"""

import platform
if not hasattr(platform, 'python_implementation') or platform.python_implementation() == 'CPython':
    __doc__ += """
    >>> s = None
    42 tons of spam is history.
"""

cdef class Spam:

    cdef int tons

    def __cinit__(self):
        self.tons = 17

    def __dealloc__(self):
        print self.tons, u"tons of spam is history."

    def get_tons(self):
        return self.tons

    def set_tons(self, x):
        self.tons = x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_starargcall.pyx0000644000175100001770000000027400000000000021127 0ustar00runnerdocker00000000000000def spam(a, b, c):
    print u"Args:", a, b, c

def eggs():
    """
    >>> eggs()
    Args: 1 2 3
    Args: buckle my shoe
    """
    spam(*(1,2,3))
    spam(*[u"buckle",u"my",u"shoe"])
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_starargs.pyx0000644000175100001770000000156700000000000020464 0ustar00runnerdocker00000000000000def swallow(name, airspeed, *args, **kwds):
    """
    >>> swallow("Brian", 42)
    Name: Brian
    Airspeed: 42
    Extra args: ()
    Extra keywords: []
    >>> swallow("Brian", 42, "African")
    Name: Brian
    Airspeed: 42
    Extra args: ('African',)
    Extra keywords: []
    >>> swallow("Brian", airspeed = 42)
    Name: Brian
    Airspeed: 42
    Extra args: ()
    Extra keywords: []
    >>> swallow("Brian", airspeed = 42, species = "African", coconuts = 3)
    Name: Brian
    Airspeed: 42
    Extra args: ()
    Extra keywords: [('coconuts', 3), ('species', 'African')]
    >>> swallow("Brian", 42, "African", coconuts = 3)
    Name: Brian
    Airspeed: 42
    Extra args: ('African',)
    Extra keywords: [('coconuts', 3)]
    """
    print u"Name:", name
    print u"Airspeed:", airspeed
    print u"Extra args:", args
    print u"Extra keywords:", sorted(kwds.items())
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_starargsonly.pyx0000644000175100001770000000030700000000000021355 0ustar00runnerdocker00000000000000def spam(*args):
    """
    >>> spam()
    Args: ()
    >>> spam(42)
    Args: (42,)
    >>> spam("one", 2, "buckle my shoe")
    Args: ('one', 2, 'buckle my shoe')
    """
    print u"Args:", args
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_toofewargs.pyx0000644000175100001770000000033300000000000021004 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> s = Spam()
    Traceback (most recent call last):
    TypeError: __init__() takes exactly 3 positional arguments (0 given)
"""

cdef class Spam:

    def __init__(self, a, b, int c):
        pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_typecast.pyx0000644000175100001770000000035100000000000020460 0ustar00runnerdocker00000000000000cdef class ExtType:
    cdef c_method(self):
        return self

    def method(self):
        return 1

def call_method(ExtType et):
    """
    >>> call_method( ExtType() ).method()
    1
    """
    return et.c_method()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_uintindex.pyx0000644000175100001770000000043100000000000020632 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> print(idx_uint( ["buckle", "my", "shoe"], 2))
shoe
>>> print(idx_ulong(["buckle", "my", "shoe"], 2))
shoe
"""

def idx_ulong(seq, i):
    cdef unsigned long u
    u = i
    return seq[u]

def idx_uint(seq, i):
    cdef unsigned int u
    u = i
    return seq[u]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/r_vree_1.pyx0000644000175100001770000000131400000000000020005 0ustar00runnerdocker00000000000000import sys
if sys.version_info[0] < 3:
    __doc__ = u"""

    >>> test(0)
    0L
    >>> test(1)
    1L

    >>> sys.maxint + 1 > sys.maxint
    True
    >>> type(sys.maxint * 2 + 1) is long
    True

    >>> test(sys.maxint + 1) == sys.maxint + 1
    True
    >>> test(sys.maxint * 2 + 1) == sys.maxint * 2 + 1
    True

    >>> test(256 ** unsigned_long_size() - 1) > 0
    True
    >>> test(256 ** unsigned_long_size() - 1) > sys.maxint
    True
    """
else:
    __doc__ = u"""
    >>> test(0)
    0
    >>> test(1)
    1
    >>> test(256 ** unsigned_long_size() - 1) > 0
    True
    """

def test(k):
    cdef unsigned long m
    m = k
    return m

def unsigned_long_size():
    return sizeof(unsigned long)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/raise_memory_error_T650.pyx0000644000175100001770000000171300000000000022730 0ustar00runnerdocker00000000000000# ticket: t650

cimport cython


@cython.test_assert_path_exists(
    '//RaiseStatNode',
    '//RaiseStatNode[@builtin_exc_name = "MemoryError"]')
def raise_me_type():
    """
    >>> try: raise_me_type()
    ... except MemoryError: pass
    ... else: print('NOT RAISED!')
    """
    raise MemoryError


@cython.test_assert_path_exists(
    '//RaiseStatNode',
    '//RaiseStatNode[@builtin_exc_name = "MemoryError"]')
def raise_me_instance():
    """
    >>> try: raise_me_instance()
    ... except MemoryError: pass
    ... else: print('NOT RAISED!')
    """
    raise MemoryError()


def raise_me_instance_value():
    """
    >>> raise_me_instance_value()
    Traceback (most recent call last):
        ...
    MemoryError: oom
    """
    raise MemoryError("oom")


def raise_me_instance_value_separate():
    """
    >>> raise_me_instance_value_separate()
    Traceback (most recent call last):
        ...
    MemoryError: oom
    """
    raise MemoryError, "oom"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/range_optimisation_T203.pyx0000644000175100001770000000515400000000000022714 0ustar00runnerdocker00000000000000# ticket: t203

cdef int get_bound(int m):
    print u"get_bound(%s)"%m
    return m

def for_from_range(a, b):
    """
    >>> for_from_range(5, 10)
    range(5)
    at 0
    at 1
    at 2
    at 3
    at 4
    range(5, 10)
    at 5
    at 6
    at 7
    at 8
    at 9
    range(5, 10, 2)
    at 5
    at 7
    at 9
    9
    >>> for_from_range(-5, -10)
    range(-5)
    range(-5, -10)
    range(-5, -10, 2)
    100
    """
    cdef int i = 100
    print u"range(%s)" % a
    for i in range(a):
        print u"at", i
    print u"range(%s, %s)" % (a, b)
    for i in range(a, b):
        print u"at", i
    print u"range(%s, %s, %s)" % (a, b, 2)
    for i in range(a, b, 2):
        print u"at", i
    return i

def for_from_bound_reassignment(int bound, int fake_bound):
    """
    >>> for_from_bound_reassignment(5, 1)
    at 0
    at 1
    at 2
    at 3
    at 4
    5
    """
    cdef int i = 100
    for i from 0 <= i < bound:
        print u"at", i
        bound = fake_bound
    return i

def for_from_step_reassignment(int bound, int step, int fake_step):
    """
    >>> for_from_step_reassignment(15, 5, 2)
    at 0
    at 5
    at 10
    15
    """
    cdef int i = 100
    for i from 0 <= i < bound by step:
        print u"at", i
        step = fake_step
    return i

def for_from_target_reassignment(int bound, int factor):
    """
    >>> for_from_target_reassignment(10, 2)
    at 0
    at 1
    at 3
    at 7
    15
    """
    cdef int i = 100
    for i from 0 <= i < bound:
        print u"at", i
        i *= factor
    return i

def for_from_py_target_reassignment(int bound, int factor):
    """
    >>> for_from_py_target_reassignment(10, 2)
    at 0
    at 1
    at 3
    at 7
    15
    """
    cdef object i
    for i from 0 <= i < bound:
        print u"at", i
        i *= factor
    return i

def for_from_py_global_target_reassignment(int bound, int factor):
    """
    >>> for_from_py_global_target_reassignment(10, 2)
    at 0
    at 1
    at 3
    at 7
    15
    """
    global g_var
    for g_var from 0 <= g_var < bound:
        print u"at", g_var
        g_var *= factor
    return g_var

def for_in_target_reassignment(int bound, int factor):
    """
    >>> for_in_target_reassignment(10, 2)
    at 0
    at 1
    at 2
    at 3
    at 4
    at 5
    at 6
    at 7
    at 8
    at 9
    18
    """
    cdef int i = 100
    for i in range(bound):
        print u"at", i
        i *= factor
    return i

def test_func(int n):
    """
    >>> test_func(5)
    get_bound(5)
    at 0
    at 1
    at 2
    at 3
    at 4
    5
    """
    cdef int i = 100
    for i from 0 <= i < get_bound(n):
        print u"at", i
    return i
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/reduce_pickle.pyx0000644000175100001770000002001300000000000021076 0ustar00runnerdocker00000000000000# mode: run
# tag: pickle

import cython
import sys

if sys.version_info[0] < 3:
    __doc__ = """
    >>> import cPickle
    >>> a = A(5); a
    A(5)
    >>> cPickle.loads(cPickle.dumps(a))
    A(5)

    >>> b = B(0, 1); b
    B(x=0, y=1)
    >>> cPickle.loads(cPickle.dumps(b))
    B(x=0, y=1)
    """

cdef class A:
    """
    >>> a = A(3); a
    A(3)
    >>> import pickle
    >>> pickle.loads(pickle.dumps(a))
    A(3)
    """

    cdef int value

    def __init__(self, value):
        self.value = value

    def __repr__(self):
        return "A(%s)" % self.value

    def __reduce__(self):
        return A, (self.value,)

cdef class B:
    """
    >>> b = B(x=37, y=389); b
    B(x=37, y=389)
    >>> import pickle
    >>> pickle.loads(pickle.dumps(b))
    B(x=37, y=389)
    """

    cdef int x, y

    def __cinit__(self):
        self.x = self.y = -1

    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __repr__(self):
        return "%s(x=%s, y=%s)" % (self.__class__.__name__, self.x, self.y)

    def __reduce__(self):
        return makeObj, (type(self), {'x': self.x, 'y': self.y})

def makeObj(obj_type, kwds):
    return obj_type(**kwds)


cdef class C(B):
    """
    >>> import pickle
    >>> pickle.loads(pickle.dumps(C(x=37, y=389)))
    C(x=37, y=389)
    """
    pass


@cython.auto_pickle(True)  # Not needed, just to test the directive.
cdef class DefaultReduce(object):
    """
    >>> a = DefaultReduce(11, 'abc'); a
    DefaultReduce(i=11, s='abc')
    >>> import pickle
    >>> pickle.loads(pickle.dumps(a))
    DefaultReduce(i=11, s='abc')
    >>> pickle.loads(pickle.dumps(DefaultReduce(i=11, s=None)))
    DefaultReduce(i=11, s=None)
    """

    cdef readonly int i
    cdef readonly str s

    def __init__(self, i=0, s=None):
        self.i = i
        self.s = s

    def __repr__(self):
        return "DefaultReduce(i=%s, s=%r)" % (self.i, self.s)


cdef class DefaultReduceSubclass(DefaultReduce):
    """
    >>> a = DefaultReduceSubclass(i=11, s='abc', x=1.5); a
    DefaultReduceSubclass(i=11, s='abc', x=1.5)
    >>> import pickle
    >>> pickle.loads(pickle.dumps(a))
    DefaultReduceSubclass(i=11, s='abc', x=1.5)
    """

    cdef double x

    def __init__(self, **kwargs):
        self.x = kwargs.pop('x', 0)
        super(DefaultReduceSubclass, self).__init__(**kwargs)

    def __repr__(self):
        return "DefaultReduceSubclass(i=%s, s=%r, x=%s)" % (self.i, self.s, self.x)


cdef class result(DefaultReduceSubclass):
    """
    >>> a = result(i=11, s='abc', x=1.5); a
    result(i=11, s='abc', x=1.5)
    >>> import pickle
    >>> pickle.loads(pickle.dumps(a))
    result(i=11, s='abc', x=1.5)
    """

    def __repr__(self):
        return "result(i=%s, s=%r, x=%s)" % (self.i, self.s, self.x)


class DefaultReducePySubclass(DefaultReduce):
    """
    >>> a = DefaultReducePySubclass(i=11, s='abc', x=1.5); a
    DefaultReducePySubclass(i=11, s='abc', x=1.5)
    >>> import pickle
    >>> pickle.loads(pickle.dumps(a))
    DefaultReducePySubclass(i=11, s='abc', x=1.5)

    >>> a.self_reference = a
    >>> a2 = pickle.loads(pickle.dumps(a))
    >>> a2.self_reference is a2
    True
    """
    def __init__(self, **kwargs):
        self.x = kwargs.pop('x', 0)
        super(DefaultReducePySubclass, self).__init__(**kwargs)

    def __repr__(self):
        return "DefaultReducePySubclass(i=%s, s=%r, x=%s)" % (self.i, self.s, self.x)


cdef class NoReduceDueToIntPtr(object):
    """
    >>> import pickle
    >>> pickle.dumps(NoReduceDueToIntPtr())
    Traceback (most recent call last):
    ...
    TypeError: self.int_ptr cannot be converted to a Python object for pickling
    """
    cdef int* int_ptr

cdef class NoReduceDueToNontrivialCInit(object):
    """
    >>> import pickle
    >>> pickle.dumps(NoReduceDueToNontrivialCInit(None))
    Traceback (most recent call last):
    ...
    TypeError: no default __reduce__ due to non-trivial __cinit__
    """
    def __cinit__(self, arg):
        pass


cdef class NoMembers(object):
    """
    >>> import pickle
    >>> pickle.loads(pickle.dumps(NoMembers()))
    NoMembers()
    """
    def __repr__(self):
        return "NoMembers()"


cdef class NoPyMembers(object):
    """
    >>> import pickle
    >>> pickle.loads(pickle.dumps(NoPyMembers(2, 1.75)))
    NoPyMembers(ii=[2, 4, 8], x=1.75)
    """
    cdef int[3] ii
    cdef double x

    def __init__(self, i, x):
        self.ii[0] = i
        self.ii[1] = i * i
        self.ii[2] = i * i * i
        self.x = x

    def __repr__(self):
        return "%s(ii=%s, x=%s)" % (type(self).__name__, self.ii, self.x)

    def __eq__(self, other):
        return (
            isinstance(other, NoPyMembers) and
            ( other).ii[0] == self.ii[0] and
            ( other).ii[1] == self.ii[1] and
            ( other).ii[2] == self.ii[2] and
            ( other).x == self.x
        )


class NoPyMembersPySubclass(NoPyMembers):
    """
    >>> import pickle
    >>> pickle.loads(pickle.dumps(NoPyMembersPySubclass(2, 1.75, 'xyz')))
    NoPyMembersPySubclass(ii=[2, 4, 8], x=1.75, s='xyz')
    """
    def __init__(self, i, x, s):
        super(NoPyMembersPySubclass, self).__init__(i, x)
        self.s = s
    def __repr__(self):
        return (super(NoPyMembersPySubclass, self).__repr__()
                [:-1] + ', s=%r)' % self.s)


cdef struct MyStruct:
    int i
    double x

cdef class StructMemberDefault(object):
    """
    >>> import pickle
    >>> s = StructMemberDefault(1, 1.5); s
    StructMemberDefault(i=1, x=1.5)
    >>> pickle.dumps(s)   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...my_struct...
    """

    cdef MyStruct my_struct

    def __init__(self, i, x):
        self.my_struct.i = i
        self.my_struct.x = x

    def __repr__(self):
        return "%s(i=%s, x=%s)" % (
            type(self).__name__, self.my_struct.i, self.my_struct.x)

@cython.auto_pickle(True)  # Forced due to the (inherited) struct attribute.
cdef class StructMemberForcedPickle(StructMemberDefault):
    """
    >>> import pickle
    >>> s = StructMemberForcedPickle(1, 1.5); s
    StructMemberForcedPickle(i=1, x=1.5)
    >>> pickle.loads(pickle.dumps(s))
    StructMemberForcedPickle(i=1, x=1.5)
    """


cdef _unset = object()

# Test cyclic references.
cdef class Wrapper(object):
  """
  >>> import pickle
  >>> w = Wrapper(); w
  Wrapper(...)
  >>> w2 = pickle.loads(pickle.dumps(w)); w2
  Wrapper(...)
  >>> w2.ref is w2
  True

  >>> pickle.loads(pickle.dumps(Wrapper(DefaultReduce(1, 'xyz'))))
  Wrapper(DefaultReduce(i=1, s='xyz'))
  >>> L = [None]
  >>> L[0] = L
  >>> w = Wrapper(L)
  >>> pickle.loads(pickle.dumps(Wrapper(L)))
  Wrapper([[...]])

  >>> L[0] = w   # Don't print this one out...
  >>> w2 = pickle.loads(pickle.dumps(w))
  >>> w2.ref[0] is w2
  True
  """
  cdef public object ref
  def __init__(self, ref=_unset):
      if ref is _unset:
          self.ref = self
      else:
          self.ref = ref
  def __repr__(self):
      if self.ref is self:
          return "Wrapper(...)"
      else:
          return "Wrapper(%r)" % self.ref


# Non-regression test for pickling bound and unbound methods of non-extension
# classes
if sys.version_info[:2] >= (3, 5):
    # builtin methods not picklable for python <= 3.4
    class MyClass(object):
        """
        >>> import pickle
        >>> pickle.loads(pickle.dumps(MyClass.my_method)) is MyClass.my_method
        True
        >>> bound_method = pickle.loads(pickle.dumps(MyClass().my_method))
        >>> bound_method(1)
        1
        """
        def my_method(self, x):
            return x


# Pickled with Cython 0.29.28 (using MD5 for the checksum).
OLD_MD5_PICKLE = b'''\
creduce_pickle\n__pyx_unpickle_NoPyMembers\nq\x00\
(creduce_pickle\nNoPyMembers\nq\x01J\xf2K_\n(]q\x02\
(K\x0bKyM3\x05eG?\xf8\x00\x00\x00\x00\x00\x00tq\x03tq\x04Rq\x05.\
'''

try:
    from hashlib import md5
except ImportError:
    pass
else:
    def unpickle_old_0_29_28():
        """
        >>> import pickle
        >>> b = pickle.loads(OLD_MD5_PICKLE)
        >>> b == NoPyMembers(i=11, x=1.5) or b
        True
        """
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/ref2global.py0000644000175100001770000000061700000000000020137 0ustar00runnerdocker00000000000000# mode: run
# tag: global, nameerror

try:
    from heapq import *   # just to confuse the compiler
except ImportError:
    pass


def f(a):
    """
    Py<=3.3 gives 'global name ...', Py3.4+ only 'name ...'

    >>> f(1)   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    NameError: ...name 'definitely_unknown_name' is not defined
    """
    a = f
    a = definitely_unknown_name
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/ref2local.pyx0000644000175100001770000000011600000000000020153 0ustar00runnerdocker00000000000000def f():
    """
    >>> f()
    42
    """
    a = 42
    b = a
    return b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/refcount_in_meth.pyx0000644000175100001770000000245100000000000021636 0ustar00runnerdocker00000000000000#!/usr/bin/env python

__doc__=u"""
>>> t = RefCountInMeth()
>>> t.chk_meth()
True
>>> t.chk_nogil()
True
>>> t.chk_meth_if()
True
>>> t.chk_nogil_if()
True
"""

cimport cython
from cpython.ref cimport PyObject

@cython.always_allow_keywords(False)
def get_refcount(obj):
    return (obj).ob_refcnt

cdef class RefCountInMeth(object):
    cdef double value

    def __cinit__(self):
        self.value = 1.5

    cdef double c_get_value(self) nogil:
        return self.value

    cdef double c_get_value_if(self) nogil:
        cdef double v
        if 9>4:
            v = 2.3
        return self.value

    cdef int c_meth(self):
        cdef int v

        v = get_refcount(self)
        return v

    cdef int c_meth_if(self):
        cdef int v
        if 5>6:
            v = 7
        v = get_refcount(self)
        return v

    def chk_meth(self):
        cdef int a,b

        a = get_refcount(self)
        b = self.c_meth()
        return a==b

    def chk_meth_if(self):
        cdef int a,b

        a = get_refcount(self)
        b = self.c_meth_if()
        return a==b

    def chk_nogil(self):
        cdef double v
        v = self.c_get_value()
        return v==self.value

    def chk_nogil_if(self):
        cdef double v
        v = self.c_get_value_if()
        return v==self.value

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/reimport.pyx0000644000175100001770000000032700000000000020147 0ustar00runnerdocker00000000000000# mode: run
# tag: import

# reimports at module init time used to be a problem in Py3
import reimport

def test():
    """
    >>> test()
    True
    """
    import sys
    return reimport in sys.modules.values()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/reimport_failure.srctree0000644000175100001770000000114400000000000022503 0ustar00runnerdocker00000000000000# mode: run
# tag: pep489

"""
PYTHON setup.py build_ext -i
PYTHON tester.py
"""

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup

setup(
  ext_modules = cythonize("*.pyx"),
)


######## failure.pyx ########

if globals():  # runtime True to confuse dead code removal
    raise ImportError

cdef class C:
    cdef int a


######## tester.py ########

try:
    try:
        import failure  # 1
    except ImportError:
        import failure  # 2
except ImportError:
    pass
else:
    raise RuntimeError("ImportError was not raised on second import!")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/reimport_from_package.srctree0000644000175100001770000000245500000000000023500 0ustar00runnerdocker00000000000000# mode: run
# tag: pep489

PYTHON setup.py build_ext --inplace
PYTHON -c "import a"

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup

setup(
    ext_modules = cythonize("**/*.pyx"),
    )

######## a.pyx ########

import sys
import a
assert a in sys.modules.values(), sorted(sys.modules)
assert sys.modules['a'] is a, sorted(sys.modules)

from atest.package import module

######## atest/__init__.py ########

######## atest/package/__init__.py ########

######## atest/package/module.pyx ########

import sys
assert 'atest.package.module' in sys.modules

import a
import atest.package.module as module
assert module in sys.modules.values(), sorted(sys.modules)
assert sys.modules['atest.package.module'] is module, sorted(sys.modules)

if sys.version_info >= (3, 5):
    from . import pymodule
    assert module is pymodule.import_without_package()

######## atest/package/pymodule.py ########

from . import module
from ..package import module
import atest.package.module

import a

def import_without_package():
    import os.path
    import sys
    sys.path.insert(0, os.path.dirname(__file__))
    sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
    import module
    import package.module
    assert package.module is module
    return module
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4207222
Cython-3.0.8/tests/run/reimport_from_subinterpreter.srctree0000644000175100001770000000466300000000000025165 0ustar00runnerdocker00000000000000# mode: run
# tag: pep489, subinterpreter

PYTHON setup.py build_ext --inplace
PYTHON -c "import subtest; subtest.run_main()"
PYTHON -c "import subtest; subtest.run_sub()"
PYTHON -c "import subtest; subtest.run_main(); subtest.run_sub()"

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup

setup(
    ext_modules = cythonize("**/*.pyx"),
    )

######## subtest.pyx ########

cdef extern from *:
    """
    /* Copied from CPython's _testcapi.c module */
    static PyObject *run_in_subinterpreter(const char *code) {
        int r;
        PyThreadState *substate, *mainstate;

        mainstate = PyThreadState_Get();

        PyThreadState_Swap(NULL);

        substate = Py_NewInterpreter();
        if (substate == NULL) {
            /* Since no new thread state was created, there is no exception to
               propagate; raise a fresh one after swapping in the old thread
               state. */
            PyThreadState_Swap(mainstate);
            PyErr_SetString(PyExc_RuntimeError, "sub-interpreter creation failed");
            return NULL;
        }
        r = PyRun_SimpleString(code);
        Py_EndInterpreter(substate);

        PyThreadState_Swap(mainstate);
        return PyLong_FromLong(r);
    }
    """
    object run_in_subinterpreter(const char *code)


MAIN_HAS_IMPORTED = False

def run_main():
    global MAIN_HAS_IMPORTED
    MAIN_HAS_IMPORTED = True
    import package.subtest
    from package import subtest

def run_sub():
    assert 0 == run_in_subinterpreter(b'1+1')
    assert 0 == run_in_subinterpreter(b'2+2')

    # The subinterpreter does not add the current working directory to
    # sys.path, so we need to add it manually.
    pre = b'import sys; sys.path.insert(0, "."); '
    assert 0 == run_in_subinterpreter(pre + b'import package')
    assert 0 == run_in_subinterpreter(pre + b'import package')

    import sys
    result = run_in_subinterpreter(pre + b'import package.subtest')
    if not MAIN_HAS_IMPORTED:
        assert result == 0, result  # imports only in subinterpreters are ok
    elif sys.version_info >= (3, 5):
        assert result == -1, result  # re-import in a different subinterpreter fails in Py3.5+ (with PEP-489)
    else:
        assert result == 0, result  # re-import in a different subinterpreter reuses the module in Py<3.5


######## package/__init__.py ########

######## package/subtest.pyx ########

print("Module loaded: %s" % __name__)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/relative_cimport.srctree0000644000175100001770000000643200000000000022510 0ustar00runnerdocker00000000000000# mode: run
# tag: cimport

PYTHON setup.py build_ext --inplace
PYTHON -c "from py_pkg.py_a import test; test()"
PYTHON -c "from pkg.a import test; assert test() == (5, 7)"
PYTHON -c "from pkg.b import test; assert test() == (1, 2)"
PYTHON -c "from pkg.b_py2 import test; assert test() == (1, 2)"
PYTHON -c "from pkg.sub.c import test; assert test() == (1, 2)"
PYTHON -c "from pkg.sub.d import test; assert test() == 3"

# File structure:
# ├── setup.py
# ├── py_pkg/
# |   ├── __init__.py
# |   ├── py_a.pyx
# |   ├── py_b.pxd
# |   └── py_sub/
# |       ├── __init__.py
# |       ├── py_c.pxd
# |       └── py_d.pxd
# └── pkg/
#     ├── __init__.py
#     ├── a.pyx
#     ├── a.pxd
#     ├── b.pyx
#     ├── b_py2.pyx
#     └── sub/
#         ├── __init__.py
#         ├── __init__.pxd
#         ├── c.pyx
#         ├── c.pxd
#         ├── d.pyx
#         ├── tdef.pxd
#         └── reimport.pxd

######## setup.py ########

from distutils.core import setup
from Cython.Build import cythonize
from Cython.Distutils.extension import Extension

setup(
    ext_modules=cythonize('**/*.pyx'),
)


######## py_pkg/__init__.py ########

######## py_pkg/py_a.pyx ########

from .py_sub cimport py_c

def test():
    cdef py_c.py_b.py_b_int b = 1
    assert b == 1
    cdef py_c.py_c_int c = 2
    assert c == 2
    cdef py_c.py_d.py_d_int d = 3
    assert d == 3

######## py_pkg/py_b.pxd ########

ctypedef int py_b_int

######## py_pkg/py_sub/__init__.py ########

######## py_pkg/py_sub/py_c.pxd ########

from .. cimport py_b
from . cimport py_d

ctypedef int py_c_int

######## py_pkg/py_sub/py_d.pxd ########

ctypedef int py_d_int

######## pkg/__init__.py ########

######## pkg/sub/__init__.py ########

######## pkg/a.pyx ########

from .sub.reimport cimport myint
from .sub cimport c

cdef myint i = 5
assert i == 5
assert c.sum_func(1, 2) == 3

from .sub cimport myint as pkg_myint

cdef pkg_myint pi = 7
assert pi == 7

cdef class test_pxd:
    pass


def test():
    return (i, pi)


######## pkg/a.pxd ########

cdef class test_pxd:
    cdef public int x
    cdef public int y


######## pkg/b.pyx ########

from . cimport a
from .a cimport test_pxd

assert a.test_pxd is test_pxd

def test():
    cdef test_pxd obj = test_pxd()
    obj.x = 1
    obj.y = 2
    return (obj.x, obj.y)


######## pkg/b_py2.pyx ########

# cython: language_level=2

from . cimport a
from .a cimport test_pxd
cimport a as implicitly_relative_a  # <-- Py2 "feature"

assert a.test_pxd is test_pxd
assert implicitly_relative_a.test_pxd is test_pxd

def test():
    cdef test_pxd obj = test_pxd()
    obj.x = 1
    obj.y = 2
    return (obj.x, obj.y)


######## pkg/sub/c.pyx ########

from ..a cimport test_pxd


def test():
    cdef test_pxd obj = test_pxd()
    obj.x = 1
    obj.y = 2
    return (obj.x, obj.y)

cdef int sum_func(int n, int m):
    return n + m

######## pkg/sub/c.pxd ########

cdef int sum_func(int n, int m)

######## pkg/sub/d.pyx ########

from . cimport c

def test():
    return c.sum_func(1, 2)

######## pkg/sub/tdef.pxd ########

ctypedef int myint


######## pkg/sub/reimport.pxd ########

from .tdef cimport myint


######## pkg/sub/__init__.pxd ########

from .tdef cimport myint
from . cimport c
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/relative_cimport_compare.srctree0000644000175100001770000001452500000000000024220 0ustar00runnerdocker00000000000000# mode: run
# tag: cimport, pep489

PYTHON setup.py build_ext --inplace
PYTHON -c "import test_import"
PYTHON -c "import test_cimport"


######## setup.py ########

from distutils.core import setup
from Cython.Build import cythonize
from Cython.Distutils.extension import Extension

setup(
    ext_modules=cythonize('**/*.pyx'),
)

######## test_import.py ########
import sys
SUPPORTS_PEP_489 = sys.version_info > (3, 5)
if SUPPORTS_PEP_489:
    import cypkg.sub.submodule
    import cypkg.sub.sub2.sub2module
    import pypkg.module
    import pypkg.sub.submodule
    import pypkg.sub.sub2.sub2module

######## test_cimport.py ########
import sys
SUPPORTS_PEP_489 = sys.version_info > (3, 5)
if SUPPORTS_PEP_489:
    import module


######## module.pyx ########
cimport cypkg

cdef cypkg.a_type a1 = 3
assert a1 == 3
cdef cypkg.a.a_type a2 = 3
assert a2 == 3
cdef cypkg.b_type b1 = 4
assert b1 == 4
cdef cypkg.b.b_type b2 = 4
assert b2 == 4


cimport cypkg.sub
cdef cypkg.sub.a_type a3 = 3
assert a3 == 3
cdef cypkg.sub.a.a_type a4 = 3
assert a4 == 3
cdef cypkg.sub.b_type b3 = 4
assert b3 == 4
cdef cypkg.sub.b.b_type b4 = 4
assert b4 == 4


cimport cypkg.sub.sub2
cdef cypkg.sub.sub2.a_type a5 = 3
assert a5 == 3
cdef cypkg.sub.sub2.a.a_type a6 = 3
assert a6 == 3
cdef cypkg.sub.sub2.b_type b5 = 4
assert b5 == 4
cdef cypkg.sub.sub2.b.b_type b6 = 4
assert b6 == 4

import pypkg
assert pypkg.a_value == 3
assert pypkg.a.a_value == 3
assert pypkg.b_value == 4
assert pypkg.b.b_value == 4


import pypkg.sub
assert pypkg.sub.a_value == 3
assert pypkg.sub.a.a_value == 3
assert pypkg.sub.b_value == 4
assert pypkg.sub.b.b_value == 4


import cypkg.sub.sub2
assert pypkg.sub.sub2.a_value == 3
assert pypkg.sub.sub2.a.a_value == 3
assert pypkg.sub.sub2.b_value == 4
assert pypkg.sub.sub2.b.b_value == 4


######## cypkg/__init__.pxd ########

cimport cypkg.sub
cimport cypkg.sub.sub2

from cypkg.sub cimport a
from cypkg.sub.a cimport a_type
from cypkg.sub.sub2 cimport b
from cypkg.sub.sub2.b cimport b_type

from . cimport sub
from .sub cimport a
from .sub.a cimport a_type
from .sub.sub2 cimport b
from .sub.sub2.b cimport b_type

######## cypkg/__init__.pyx ########


######## cypkg/module.pyx ########

cimport cypkg
cimport cypkg.sub
cimport cypkg.sub.sub2
from cypkg.sub cimport a
from cypkg.sub.a cimport a_type
from cypkg.sub.sub2 cimport b
from cypkg.sub.sub2.b cimport b_type

from . cimport sub
from .sub cimport a
from .sub.a cimport a_type
from .sub.sub2 cimport b
from .sub.sub2.b cimport b_type


######## cypkg/sub/__init__.pxd ########

cimport cypkg
from cypkg.sub cimport a
from cypkg.sub.a cimport a_type
from cypkg.sub.sub2 cimport b
from cypkg.sub.sub2.b cimport b_type

from . cimport a
from .a cimport a_type

from .. cimport sub
from ..sub cimport a
from ..sub.a cimport a_type
from ..sub.sub2 cimport b
from ..sub.sub2.b cimport b_type

######## cypkg/sub/__init__.pyx ########

######## cypkg/sub/a.pxd ########

ctypedef int a_type

######## cypkg/sub/submodule.pyx ########

cimport cypkg
cimport cypkg.sub
from cypkg.sub cimport a
from cypkg.sub.a cimport a_type
from cypkg.sub.sub2 cimport b
from cypkg.sub.sub2.b cimport b_type

from . cimport a
from .a cimport a_type

from .. cimport sub
from ..sub cimport a
from ..sub.a cimport a_type
from ..sub.sub2 cimport b
from ..sub.sub2.b cimport b_type

######## cypkg/sub/sub2/__init__.pxd ########

cimport cypkg
cimport cypkg.sub
from cypkg.sub cimport a
from cypkg.sub.a cimport a_type
from cypkg.sub.sub2 cimport b
from cypkg.sub.sub2.b cimport b_type

from ..sub2 cimport b
from ..sub2.b cimport b_type

from ...sub cimport a
from ...sub.a cimport a_type

from ... cimport sub
from ...sub.sub2 cimport b
from ...sub.sub2.b cimport b_type

######## cypkg/sub/sub2/__init__.pyx ########

######## cypkg/sub/sub2/b.pxd ########

ctypedef int b_type


######## cypkg/sub/sub2/sub2module.pyx ########

cimport cypkg
cimport cypkg.sub
from cypkg.sub cimport a
from cypkg.sub.a cimport a_type
from cypkg.sub.sub2 cimport b
from cypkg.sub.sub2.b cimport b_type

from .. cimport sub2
from ..sub2 cimport b
from ..sub2.b cimport b_type

from ...sub cimport a
from ...sub.a cimport a_type

from ... cimport sub
from ...sub.sub2 cimport b
from ...sub.sub2.b cimport b_type

######## pypkg/__init__.py ########

import pypkg.sub
import pypkg.sub.sub2

from pypkg.sub import a
from pypkg.sub.a import a_value
from pypkg.sub.sub2 import b
from pypkg.sub.sub2.b import b_value

from . import sub
from .sub import a
from .sub.a import a_value
from .sub.sub2 import b
from .sub.sub2.b import b_value

######## pypkg/module.py ########

import pypkg
import pypkg.sub
import pypkg.sub.sub2
from pypkg.sub import a
from pypkg.sub.a import a_value
from pypkg.sub.sub2 import b
from pypkg.sub.sub2.b import b_value

from . import sub
from .sub import a
from .sub.a import a_value
from .sub.sub2 import b
from .sub.sub2.b import b_value

######## pypkg/sub/__init__.py ########

import pypkg
from pypkg.sub import a
from pypkg.sub.a import a_value
from pypkg.sub.sub2 import b
from pypkg.sub.sub2.b import b_value

from . import a
from .a import a_value

from .. import sub
from ..sub import a
from ..sub.a import a_value
from ..sub.sub2 import b
from ..sub.sub2.b import b_value

######## pypkg/sub/a.py ########

a_value = 3

######## pypkg/sub/submodule.py ########

import pypkg
import pypkg.sub
from pypkg.sub import a
from pypkg.sub.a import a_value
from pypkg.sub.sub2 import b
from pypkg.sub.sub2.b import b_value

from . import a
from .a import a_value

from .. import sub
from ..sub import a
from ..sub.a import a_value
from ..sub.sub2 import b
from ..sub.sub2.b import b_value

######## pypkg/sub/sub2/__init__.py ########

import pypkg
import pypkg.sub
from pypkg.sub import a
from pypkg.sub.a import a_value
from pypkg.sub.sub2 import b
from pypkg.sub.sub2.b import b_value

from ..sub2 import b
from ..sub2.b import b_value

from ...sub import a
from ...sub.a import a_value

from ... import sub
from ...sub.sub2 import b
from ...sub.sub2.b import b_value

######## pypkg/sub/sub2/b.py ########

b_value = 4


######## pypkg/sub/sub2/sub2module.py ########

import pypkg
import pypkg.sub
from pypkg.sub import a
from pypkg.sub.a import a_value
from pypkg.sub.sub2 import b
from pypkg.sub.sub2.b import b_value

from .. import sub2
from ..sub2 import b
from ..sub2.b import b_value

from ...sub import a
from ...sub.a import a_value

from ... import sub
from ...sub.sub2 import b
from ...sub.sub2.b import b_value
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/relative_import_leak.srctree0000644000175100001770000000335600000000000023343 0ustar00runnerdocker00000000000000PYTHON test_relative_import_leak.py

######## test_relative_import_leak.py ########

import os
import sys
from contextlib import contextmanager
from Cython.Compiler.Errors import CompileError
from Cython.Build.Dependencies import cythonize
if sys.version_info[0] < 3:
    from StringIO import StringIO
else:
    from io import StringIO

@contextmanager
def assert_stderr(expected_error):
    sys.path.append('other')
    sys.stderr = temp_stderr = StringIO()
    try:
        yield
    except CompileError:
        assert expected_error in temp_stderr.getvalue(), '"%s" not found in stderr' % expected_error
    else:
        assert False, 'The module was imported even when it should not be importable'
    finally:
        sys.stderr = sys.__stderr__
        temp_stderr.close()

pxd_file = os.path.join('pkg', 'bb.pxd')

pyx_file = os.path.join('pkg', 'aa.pyx')
with assert_stderr(pyx_file + ":1:0: '" + pxd_file + "' not found"):
    cythonize(pyx_file)

pyx_file = os.path.join('pkg', 'ab.pyx')
with assert_stderr(pyx_file + ":1:0: '" + pxd_file + "' not found"):
    cythonize(pyx_file)

pyx_file = os.path.join('pkg', 'pkg2', 'ac.pyx')
with assert_stderr(pyx_file + ":1:0: '" + pxd_file + "' not found"):
    cythonize(pyx_file)

pyx_file = os.path.join('pkg', 'pkg2', 'ad.pyx')
with assert_stderr(pyx_file + ":1:0: '" + pxd_file + "' not found"):
    cythonize(pyx_file)

######## pkg/__init__.py ########

######## pkg/aa.pyx ########
from . cimport bb

######## pkg/ab.pyx ########
from .bb cimport ULong

######## pkg/pkg2/__init__.py ########

######## pkg/pkg2/ac.pyx ########
from .. cimport bb

######## pkg/pkg2/ad.pyx ########
from ..bb cimport ULong

######## other/pkg/__init__.py ########

######## other/pkg/bb.pxd ########
ctypedef unsigned long ULong
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/relativeimport_T542.srctree0000644000175100001770000000256200000000000022724 0ustar00runnerdocker00000000000000# mode: run
# tag: import

"""
PYTHON setup.py build_ext -i
PYTHON test_relative_import.py
"""

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup

setup(
  ext_modules = cythonize("*/*.pyx"),
)


######## test_relative_import.py ########

from relimport.testmod import test_relative, test_absolute
a, bmod, afunc, bfunc = test_relative()

try:
    test_absolute()
except ImportError:
    pass
else:
    import sys
    assert False, "absolute import succeeded: %s" % sorted(sys.modules)

import relimport.a
import relimport.bmod
import relimport.testmod

assert relimport.a == a
assert relimport.bmod == bmod
assert afunc() == 'a', afunc
assert bfunc() == 'b', bfunc


######## relimport/__init__.py ########

######## relimport/a.pyx ########

def afunc(): return 'a'


######## relimport/bmod.pyx ########

def bfunc(): return 'b'


######## relimport/testmod.pyx ########
# cython: language_level=3

from relimport import a as global_a, bmod as global_bmod

from . import *

assert a is global_a, a
assert bmod is global_bmod, bmod

def test_relative():
    from . import a, bmod
    from . import (a, bmod)
    from . import (a, bmod,)
    from .a import afunc
    from .bmod import bfunc

    assert afunc() == 'a', afunc()
    assert bfunc() == 'b', bfunc()

    return a, bmod, afunc, bfunc

def test_absolute():
    import bmod
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/relativeimport_star_T542.pyx0000644000175100001770000000037400000000000023125 0ustar00runnerdocker00000000000000from distutils import core, version

__name__='distutils.core.cytest_relativeimport_T542' # fool Python we are in distutils
__package__='distutils.core' # fool Python we are in distutils

from . import *

__doc__ = """
>>> core.setup == setup
True
"""
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/reload_ext_module.pyx0000644000175100001770000000055500000000000022004 0ustar00runnerdocker00000000000000# mode: run
# tag: pep489, no-macos

# FIXME: don't know why this does not work on MacOS, but it's not worth failing the builds for now.


import reload_ext_module


def test_reload(module):
    """
    >>> module = test_reload(reload_ext_module)
    >>> module is reload_ext_module  # Py_mod_create enforces a singleton.
    True
    """
    return reload(module)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/reraise.py0000644000175100001770000000132500000000000017547 0ustar00runnerdocker00000000000000
def reraise():
    raise

def test_reraise():
    """
    >>> test_reraise()
    Traceback (most recent call last):
    ValueError: TEST
    """
    try:
        raise ValueError("TEST")
    except ValueError:
        raise

def test_reraise_indirect():
    """
    >>> test_reraise_indirect()
    Traceback (most recent call last):
    ValueError: TEST INDIRECT
    """
    try:
        raise ValueError("TEST INDIRECT")
    except ValueError:
        reraise()

def test_reraise_error():
    """
    >>> try: test_reraise_error()
    ... except (RuntimeError, TypeError): pass  # Py2, Py3, ...
    ... else: print("FAILED")
    """
    import sys
    if hasattr(sys, 'exc_clear'):  # Py2
        sys.exc_clear()
    raise
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/reraise_3args.pyx0000644000175100001770000000064100000000000021036 0ustar00runnerdocker00000000000000
import sys


class MyError(Exception):
    def __init__(self, name, var):
        self.name = name
        self.var = var


def reraise_explicitly():
    """
    >>> try: reraise_explicitly()
    ... except MyError: print("RAISED!")
    ... else: print("NOT RAISED!")
    RAISED!
    """
    try:
        raise MyError('Oh no!', 42)
    except MyError:
        tmp = sys.exc_info()

    raise tmp[0], tmp[1], tmp[2]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/return.pyx0000644000175100001770000000061200000000000017622 0ustar00runnerdocker00000000000000def f(a):
    """
    >>> f('test')
    """
    return
    return a
    return 42

cdef void g():
    return

cdef int h(a):
    cdef int i
    i = a
    return i

cdef const int p():
    return 1

def test_g():
    """
    >>> test_g()
    """
    g()

def test_h(i):
    """
    >>> test_h(5)
    5
    """
    return h(i)

def test_p():
    """
    >>> test_p()
    1
    """
    return p()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/reversed_iteration.pyx0000644000175100001770000005322400000000000022207 0ustar00runnerdocker00000000000000# mode: run
# tag: forin, builtins, reversed, enumerate

cimport cython

import sys
IS_PY3 = sys.version_info[0] >= 3
IS_32BIT_PY2 = not IS_PY3 and sys.maxint < 2**32


def unlongify(v):
    # on 32bit Py2.x platforms, 'unsigned int' coerces to a Python long => fix doctest output here.
    s = repr(v)
    if IS_32BIT_PY2:
        assert s.count('L') == s.count(',') + 1, s
        s = s.replace('L', '')
    return s


def _reversed(it):
    return list(it)[::-1]

@cython.test_assert_path_exists('//ForInStatNode',
                                '//ForInStatNode/IteratorNode',
                                '//ForInStatNode/IteratorNode[@reversed = True]',
                                )
@cython.test_fail_if_path_exists('//ForInStatNode/IteratorNode//SimpleCallNode')
def reversed_list(list l):
    """
    >>> [ i for i in _reversed([1,2,3,4]) ]
    [4, 3, 2, 1]
    >>> reversed_list([1,2,3,4])
    [4, 3, 2, 1]
    >>> reversed_list([])
    []
    >>> reversed_list(None)
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not iterable
    """
    result = []
    for item in reversed(l):
        result.append(item)
    return result

@cython.test_assert_path_exists('//ForInStatNode',
                                '//ForInStatNode/IteratorNode',
                                '//ForInStatNode/IteratorNode[@reversed = True]',
                                )
@cython.test_fail_if_path_exists('//ForInStatNode/IteratorNode//SimpleCallNode')
def reversed_tuple(tuple t):
    """
    >>> [ i for i in _reversed((1,2,3,4)) ]
    [4, 3, 2, 1]
    >>> reversed_tuple((1,2,3,4))
    [4, 3, 2, 1]
    >>> reversed_tuple(())
    []
    >>> reversed_tuple(None)
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not iterable
    """
    result = []
    for item in reversed(t):
        result.append(item)
    return result

@cython.test_assert_path_exists('//ForInStatNode',
                                '//ForInStatNode/IteratorNode',
                                '//ForInStatNode/IteratorNode[@reversed = True]',
                                )
@cython.test_fail_if_path_exists('//ForInStatNode/IteratorNode//SimpleCallNode')
def enumerate_reversed_list(list l):
    """
    >>> list(enumerate(_reversed([1,2,3])))
    [(0, 3), (1, 2), (2, 1)]
    >>> enumerate_reversed_list([1,2,3])
    [(0, 3), (1, 2), (2, 1)]
    >>> enumerate_reversed_list([])
    []
    >>> enumerate_reversed_list(None)
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not iterable
    """
    result = []
    cdef Py_ssize_t i
    for i, item in enumerate(reversed(l)):
        result.append((i, item))
    return result

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_range(int N):
    """
    >>> [ i for i in _reversed(range(5)) ]
    [4, 3, 2, 1, 0]
    >>> reversed_range(5)
    ([4, 3, 2, 1, 0], 0)

    >>> [ i for i in _reversed(range(0)) ]
    []
    >>> reversed_range(0)
    ([], 99)
    """
    cdef int i = 99
    result = []
    for i in reversed(range(N)):
        result.append(i)
    return result, i

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_range_step_pos(int a, int b):
    """
    >>> [ i for i in _reversed(range(0, 5, 1)) ]
    [4, 3, 2, 1, 0]
    >>> reversed_range_step_pos(0, 5)
    ([4, 3, 2, 1, 0], 0)

    >>> [ i for i in _reversed(range(5, 0, 1)) ]
    []
    >>> reversed_range_step_pos(5, 0)
    ([], 99)
    """
    cdef int i = 99
    result = []
    for i in reversed(range(a, b, 1)):
        result.append(i)
    return result, i

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_range_step_neg(int a, int b):
    """
    >>> [ i for i in _reversed(range(5, -1, -1)) ]
    [0, 1, 2, 3, 4, 5]
    >>> reversed_range_step_neg(5, -1)
    ([0, 1, 2, 3, 4, 5], 5)

    >>> [ i for i in _reversed(range(0, 5, -1)) ]
    []
    >>> reversed_range_step_neg(0, 5)
    ([], 99)
    """
    cdef int i = 99
    result = []
    for i in reversed(range(a, b, -1)):
        result.append(i)
    return result, i

@cython.test_assert_path_exists('//ForFromStatNode')
@cython.test_fail_if_path_exists('//ForInStatNode')
def reversed_range_step3(int a, int b):
    """
    >>> [ i for i in _reversed(range(-5, 0, 3)) ]
    [-2, -5]
    >>> reversed_range_step3(-5, 0)
    ([-2, -5], -5)

    >>> [ i for i in _reversed(range(0, 5, 3)) ]
    [3, 0]
    >>> reversed_range_step3(0, 5)
    ([3, 0], 0)

    >>> [ i for i in _reversed(range(5, 0, 3)) ]
    []
    >>> reversed_range_step3(5, 0)
    ([], 99)

    >>> [ i for i in _reversed(range(1, 1, 3)) ]
    []
    >>> reversed_range_step3(1, 1)
    ([], 99)
    """
    cdef int i = 99
    result = []
    for i in reversed(range(a, b, 3)):
        result.append(i)
    return result, i

@cython.test_assert_path_exists('//ForFromStatNode')
@cython.test_fail_if_path_exists('//ForInStatNode')
def reversed_range_step3_expr(int a, int b):
    """
    >>> [ i for i in _reversed(range(0, 5, 3)) ]
    [3, 0]
    >>> reversed_range_step3_expr(0, 5)
    ([3, 0], 0)
    """
    cdef int i = 99, c = 100
    result = []
    for i in reversed(range(c-c + a + c-c, c-c + b + c-c, 3)):
        result.append(i)
    return result, i

@cython.test_assert_path_exists('//ForFromStatNode')
@cython.test_fail_if_path_exists('//ForInStatNode')
def reversed_range_step3_neg(int a, int b):
    """
    >>> [ i for i in _reversed(range(0, -5, -3)) ]
    [-3, 0]
    >>> reversed_range_step3_neg(0, -5)
    ([-3, 0], 0)

    >>> [ i for i in _reversed(range(5, 0, -3)) ]
    [2, 5]
    >>> reversed_range_step3_neg(5, 0)
    ([2, 5], 5)

    >>> [ i for i in _reversed(range(0, 5, -3)) ]
    []
    >>> reversed_range_step3_neg(0, 5)
    ([], 99)

    >>> [ i for i in _reversed(range(1, 1, -3)) ]
    []
    >>> reversed_range_step3_neg(1, 1)
    ([], 99)
    """
    cdef int i = 99
    result = []
    for i in reversed(range(a, b, -3)):
        result.append(i)
    return result, i

@cython.test_assert_path_exists('//ForFromStatNode')
@cython.test_fail_if_path_exists('//ForInStatNode')
def reversed_range_step3_neg_expr(int a, int b):
    """
    >>> [ i for i in _reversed(range(5, 0, -3)) ]
    [2, 5]
    >>> reversed_range_step3_neg_expr(5, 0)
    ([2, 5], 5)
    """
    cdef int i = 99, c = 100
    result = []
    for i in reversed(range(c-c + a + c-c, c-c + b + c-c, -3)):
        result.append(i)
    return result, i

def reversed_range_step3_py_args(a, b):
    """
    >>> [ i for i in _reversed(range(-5, 0, 3)) ]
    [-2, -5]
    >>> reversed_range_step3_py_args(-5, 0)
    ([-2, -5], -5)

    >>> [ i for i in _reversed(range(0, 5, 3)) ]
    [3, 0]
    >>> reversed_range_step3_py_args(0, 5)
    ([3, 0], 0)

    >>> [ i for i in _reversed(range(5, 0, 3)) ]
    []
    >>> reversed_range_step3_py_args(5, 0)
    ([], 99)

    >>> [ i for i in _reversed(range(1, 1, 3)) ]
    []
    >>> reversed_range_step3_py_args(1, 1)
    ([], 99)

    >>> reversed_range_step3_py_args(set(), 1) # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...integer...

    >>> reversed_range_step3_py_args(1, set()) # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...integer...
    """
    i = 99
    result = []
    for i in reversed(range(a, b, 3)):
        result.append(i)
    return result, i

def reversed_range_step3_neg_py_args(a, b):
    """
    >>> [ i for i in _reversed(range(0, -5, -3)) ]
    [-3, 0]
    >>> reversed_range_step3_neg_py_args(0, -5)
    ([-3, 0], 0)

    >>> [ i for i in _reversed(range(5, 0, -3)) ]
    [2, 5]
    >>> reversed_range_step3_neg_py_args(5, 0)
    ([2, 5], 5)

    >>> [ i for i in _reversed(range(0, 5, -3)) ]
    []
    >>> reversed_range_step3_neg_py_args(0, 5)
    ([], 99)

    >>> [ i for i in _reversed(range(1, 1, -3)) ]
    []
    >>> reversed_range_step3_neg_py_args(1, 1)
    ([], 99)

    >>> reversed_range_step3_neg_py_args(set(), 1) # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...integer...

    >>> reversed_range_step3_neg_py_args(1, set()) # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...integer...
    """
    i = 99
    result = []
    for i in reversed(range(a, b, -3)):
        result.append(i)
    return result, i

def reversed_range_step3_py_obj_left(a, int b):
    """
    >>> reversed_range_step3_py_obj_left(set(), 0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...int...
    """
    cdef long i
    result = []
    for i in reversed(range(a, b, 3)):
        result.append(i)

def reversed_range_step3_py_obj_right(int a, b):
    """
    >>> reversed_range_step3_py_obj_right(0, set())  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...int...
    """
    cdef long i
    result = []
    for i in reversed(range(a, b, 3)):
        result.append(i)

def reversed_range_step3_neg_py_obj_left(a, int b):
    """
    >>> reversed_range_step3_neg_py_obj_left(set(), 0)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...int...
    """
    cdef long i
    result = []
    for i in reversed(range(a, b, -3)):
        result.append(i)

def reversed_range_step3_neg_py_obj_right(int a, b):
    """
    >>> reversed_range_step3_py_obj_right(0, set())  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...int...
    """
    cdef long i
    result = []
    for i in reversed(range(a, b, -3)):
        result.append(i)

@cython.test_fail_if_path_exists('//ForInStatNode')
def reversed_range_constant():
    """
    >>> [ i for i in _reversed(range(-12, -2, 4)) ]
    [-4, -8, -12]
    >>> reversed_range_constant()
    ([-4, -8, -12], -12)
    """
    cdef int i = 99
    result = []
    for i in reversed(range(1, 1, 4)):
        result.append(i)
    assert result == list(reversed(range(1, 1, 4))), result
    assert i == 99

    for i in reversed(range(1, 1, 1)):
        result.append(i)
    assert result == list(reversed(range(1, 1, 1))), result

    result = []
    for i in reversed(range(0, 1, 4)):
        result.append(i)
    assert result == list(reversed(range(0, 1, 4))), result

    result = []
    for i in reversed(range(0, 1, 1)):
        result.append(i)
    assert result == list(reversed(range(0, 1, 1))), result

    result = []
    for i in reversed(range(1, 8, 4)):
        result.append(i)
    assert result == list(reversed(range(1, 8, 4))), result

    result = []
    for i in reversed(range(1, 8, 1)):
        result.append(i)
    assert result == list(reversed(range(1, 8, 1))), result

    result = []
    for i in reversed(range(1, 9, 4)):
        result.append(i)
    assert result == list(reversed(range(1, 9, 4))), result

    result = []
    for i in reversed(range(1, 10, 4)):
        result.append(i)
    assert result == list(reversed(range(1, 10, 4))), result

    result = []
    for i in reversed(range(1, 11, 4)):
        result.append(i)
    assert result == list(reversed(range(1, 11, 4))), result

    result = []
    for i in reversed(range(1, 12, 4)):
        result.append(i)
    assert result == list(reversed(range(1, 12, 4))), result

    result = []
    for i in reversed(range(0, 8, 4)):
        result.append(i)
    assert result == list(reversed(range(0, 8, 4))), result

    result = []
    for i in reversed(range(0, 9, 4)):
        result.append(i)
    assert result == list(reversed(range(0, 9, 4))), result

    result = []
    for i in reversed(range(0, 10, 4)):
        result.append(i)
    assert result == list(reversed(range(0, 10, 4))), result

    result = []
    for i in reversed(range(0, 11, 4)):
        result.append(i)
    assert result == list(reversed(range(0, 11, 4))), result

    result = []
    for i in reversed(range(0, 12, 4)):
        result.append(i)
    assert result == list(reversed(range(0, 12, 4))), result

    i = 99
    result = []
    for i in reversed(range(-12, -2, 4)):
        result.append(i)
    assert result == list(reversed(range(-12, -2, 4))), result
    return result, i

@cython.test_assert_path_exists('//ForFromStatNode')
@cython.test_fail_if_path_exists('//ForInStatNode')
def reversed_range_constant_neg():
    """
    >>> [ i for i in _reversed(range(-2, -12, -4)) ]
    [-10, -6, -2]
    >>> reversed_range_constant_neg()
    """
    cdef int i = 99
    result = []
    for i in reversed(range(1, 1, -4)):
        result.append(i)
    assert result == list(reversed(range(1, 1, -4))), result
    assert i == 99

    result = []
    for i in reversed(range(1, 1, -1)):
        result.append(i)
    assert result == list(reversed(range(1, 1, -1))), result

    result = []
    for i in reversed(range(1, 0, -4)):
        result.append(i)
    assert result == list(reversed(range(1, 0, -4))), result

    result = []
    for i in reversed(range(1, 0, -1)):
        result.append(i)
    assert result == list(reversed(range(1, 0, -1))), result

    result = []
    for i in reversed(range(8, 1, -4)):
        result.append(i)
    assert result == list(reversed(range(8, 1, -4))), result

    result = []
    for i in reversed(range(8, 1, -1)):
        result.append(i)
    assert result == list(reversed(range(8, 1, -1))), result

    result = []
    for i in reversed(range(9, 1, -4)):
        result.append(i)
    assert result == list(reversed(range(9, 1, -4))), result

    result = []
    for i in reversed(range(9, 1, -1)):
        result.append(i)
    assert result == list(reversed(range(9, 1, -1))), result

    result = []
    for i in reversed(range(10, 1, -4)):
        result.append(i)
    assert result == list(reversed(range(10, 1, -4))), result

    result = []
    for i in reversed(range(11, 1, -4)):
        result.append(i)
    assert result == list(reversed(range(11, 1, -4))), result

    result = []
    for i in reversed(range(11, 1, -1)):
        result.append(i)
    assert result == list(reversed(range(11, 1, -1))), result

    result = []
    for i in reversed(range(12, 1, -4)):
        result.append(i)
    assert result == list(reversed(range(12, 1, -4))), result

    result = []
    for i in reversed(range(12, 1, -1)):
        result.append(i)
    assert result == list(reversed(range(12, 1, -1))), result

    result = []
    for i in reversed(range(8, 0, -4)):
        result.append(i)
    assert result == list(reversed(range(8, 0, -4))), result

    result = []
    for i in reversed(range(8, 0, -1)):
        result.append(i)
    assert result == list(reversed(range(8, 0, -1))), result

    result = []
    for i in reversed(range(9, 0, -4)):
        result.append(i)
    assert result == list(reversed(range(9, 0, -4))), result

    result = []
    for i in reversed(range(9, 0, -1)):
        result.append(i)
    assert result == list(reversed(range(9, 0, -1))), result

    result = []
    for i in reversed(range(10, 0, -4)):
        result.append(i)
    assert result == list(reversed(range(10, 0, -4))), result

    result = []
    for i in reversed(range(10, 0, -1)):
        result.append(i)
    assert result == list(reversed(range(10, 0, -1))), result

    result = []
    for i in reversed(range(11, 0, -4)):
        result.append(i)
    assert result == list(reversed(range(11, 0, -4))), result

    result = []
    for i in reversed(range(11, 0, -1)):
        result.append(i)
    assert result == list(reversed(range(11, 0, -1))), result

    result = []
    for i in reversed(range(12, 0, -4)):
        result.append(i)
    assert result == list(reversed(range(12, 0, -4))), result

    result = []
    for i in reversed(range(12, 0, -1)):
        result.append(i)
    assert result == list(reversed(range(12, 0, -1))), result

    result = []
    for i in reversed(range(-2, -12, -4)):
        result.append(i)
    assert result == list(reversed(range(-2, -12, -4))), result

    result = []
    for i in reversed(range(-2, -12, -1)):
        result.append(i)
    assert result == list(reversed(range(-2, -12, -1))), result

unicode_string = u"abcDEF"

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_unicode(unicode u):
    """
    >>> print(''.join(_reversed(unicode_string)))
    FEDcba
    >>> print(''.join(reversed_unicode(unicode_string)))
    FEDcba
    """
    result = []
    for c in reversed(u):
        result.append(c)
    return result

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_unicode_slice(unicode u):
    """
    >>> print(''.join(_reversed(unicode_string[1:-2])))
    Dcb
    >>> print(''.join(reversed_unicode_slice(unicode_string)))
    Dcb
    """
    result = []
    for c in reversed(u[1:-2]):
        result.append(c)
    return result

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_unicode_slice_neg_step(unicode u):
    """
    >>> print(''.join(_reversed(unicode_string[-2:1:-1])))
    cDE
    >>> print(''.join(reversed_unicode_slice_neg_step(unicode_string)))
    cDE
    """
    result = []
    for c in reversed(u[-2:1:-1]):
        result.append(c)
    return result

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_unicode_slice_pos_step(unicode u):
    """
    >>> print(''.join(_reversed(unicode_string[1:-2:1])))
    Dcb
    >>> print(''.join(reversed_unicode_slice_pos_step(unicode_string)))
    Dcb
    """
    result = []
    for c in reversed(u[1:-2:1]):
        result.append(c)
    return result

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_unicode_slice_start_pos_step(unicode u):
    """
    >>> print(''.join(_reversed(unicode_string[2::1])))
    FEDc
    >>> print(''.join(reversed_unicode_slice_start_pos_step(unicode_string)))
    FEDc
    """
    result = []
    for c in reversed(u[2::1]):
        result.append(c)
    return result

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_unicode_slice_start_neg_step(unicode u):
    """
    >>> print(''.join(_reversed(unicode_string[3::-1])))
    abcD
    >>> print(''.join(reversed_unicode_slice_start_neg_step(unicode_string)))
    abcD
    """
    result = []
    for c in reversed(u[3::-1]):
        result.append(c)
    return result

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_unicode_slice_end_pos_step(unicode u):
    """
    >>> print(''.join(_reversed(unicode_string[:-2:1])))
    Dcba
    >>> print(''.join(reversed_unicode_slice_end_pos_step(unicode_string)))
    Dcba
    """
    result = []
    for c in reversed(u[:-2:1]):
        result.append(c)
    return result

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_unicode_slice_end_neg_step(unicode u):
    """
    >>> print(''.join(_reversed(unicode_string[:-3:-1])))
    EF
    >>> print(''.join(reversed_unicode_slice_end_neg_step(unicode_string)))
    EF
    """
    result = []
    for c in reversed(u[:-3:-1]):
        result.append(c)
    return result

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_unicode_slice_neg_step_only(unicode u):
    """
    >>> print(''.join(_reversed(unicode_string[::-1])))
    abcDEF
    >>> print(''.join(reversed_unicode_slice_neg_step_only(unicode_string)))
    abcDEF
    """
    result = []
    for c in reversed(u[::-1]):
        result.append(c)
    return result

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_unicode_slice_pos_step_only(unicode u):
    """
    >>> print(''.join(_reversed(unicode_string[::1])))
    FEDcba
    >>> print(''.join(reversed_unicode_slice_pos_step_only(unicode_string)))
    FEDcba
    """
    result = []
    for c in reversed(u[::1]):
        result.append(c)
    return result

bytes_string = b'abcDEF'
join_bytes = b''.join

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_bytes(bytes s):
    """
    >>> b = IS_PY3 and bytes_string or map(ord, bytes_string)
    >>> list(_reversed(b))
    [70, 69, 68, 99, 98, 97]
    >>> reversed_bytes(bytes_string)
    [70, 69, 68, 99, 98, 97]
    """
    cdef char c
    result = []
    for c in reversed(s):
        result.append(c)
    return result

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_bytes_slice(bytes s):
    """
    >>> b = IS_PY3 and bytes_string or map(ord, bytes_string)
    >>> list(_reversed(b[1:-2]))
    [68, 99, 98]
    >>> reversed_bytes_slice(bytes_string)
    [68, 99, 98]
    """
    cdef char c
    result = []
    for c in reversed(s[1:-2]):
        result.append(c)
    return result

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_bytes_slice_step(bytes s):
    """
    >>> b = IS_PY3 and bytes_string or map(ord, bytes_string)
    >>> list(_reversed(b[-2:1:-1]))
    [99, 68, 69]
    >>> reversed_bytes_slice_step(bytes_string)
    [99, 68, 69]
    """
    cdef char c
    result = []
    for c in reversed(s[-2:1:-1]):
        result.append(c)
    return result

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_bytes_slice_step_only(bytes s):
    """
    >>> b = IS_PY3 and bytes_string or map(ord, bytes_string)
    >>> list(_reversed(b[::-1]))
    [97, 98, 99, 68, 69, 70]
    >>> reversed_bytes_slice_step_only(bytes_string)
    [97, 98, 99, 68, 69, 70]
    """
    cdef char c
    result = []
    for c in reversed(s[::-1]):
        result.append(c)
    return result


@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_unsigned(int a, int b):
    """
    >>> unlongify(reversed_unsigned(0, 5))
    '[4, 3, 2, 1, 0]'
    >>> unlongify(reversed_unsigned(1, 5))
    '[4, 3, 2, 1]'
    >>> reversed_unsigned(1, 1)
    []
    """
    cdef unsigned int i
    return [i for i in reversed(range(a, b))]

@cython.test_assert_path_exists('//ForFromStatNode')
def reversed_unsigned_by_3(int a, int b):
    """
    >>> unlongify(reversed_unsigned_by_3(0, 5))
    '[3, 0]'
    >>> unlongify(reversed_unsigned_by_3(0, 7))
    '[6, 3, 0]'
    """
    cdef unsigned int i
    return [i for i in reversed(range(a, b, 3))]

@cython.test_assert_path_exists('//ForFromStatNode')
def range_unsigned_by_neg_3(int a, int b):
    """
    >>> unlongify(range_unsigned_by_neg_3(-1, 6))
    '[6, 3, 0]'
    >>> unlongify(range_unsigned_by_neg_3(0, 7))
    '[7, 4, 1]'
    """
    cdef unsigned int i
    return [i for i in range(b, a, -3)]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/richcmp_str_equals.py0000644000175100001770000000073100000000000022004 0ustar00runnerdocker00000000000000# mode: run

class plop(object):
    def __init__(self):
        pass

class testobj(object):
    def __init__(self):
        pass

    def __eq__(self, other):
        return plop()

def test_equals(x):
    """
    >>> x = testobj()
    >>> result = test_equals(x)
    >>> isinstance(result, plop)
    True
    >>> test_equals('hihi')
    False
    >>> test_equals('coucou')
    True
    """
    eq = x == 'coucou'  # not every str equals returns a bool ...
    return eq
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/rodriguez_1.pyx0000644000175100001770000000043000000000000020533 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> b = B()
    >>> sorted(b.t.items())
    [(1, ((1, 2, 3),)), (2, (1, 2, 3))]
"""

class B:
    def __init__(self):
        self.t = {
            1 : (
                (1, 2, 3)
                ,
                )

            , 2 : ( 1, 2, 3)
            }
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/scanner_trace.srctree0000644000175100001770000000150000000000000021736 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace

######## setup.py ###########

from distutils.core import setup
from Cython.Build import cythonize

import Cython.Compiler.Scanning

Cython.Compiler.Scanning.trace_scanner = 1

setup(ext_modules=cythonize("*.pyx"))

try:
    from importlib.util import spec_from_file_location, module_from_spec
except ImportError:
    # Py<=3.4
    # Try to import from the current directory.
    import os, sys
    sys.path.insert(0, os.getcwd())
    import simple
else:
    # Py3.5+
    import glob
    ext_files = glob.glob("simple*.so") + glob.glob("simple*.pyd")
    assert ext_files
    spec = spec_from_file_location('simple', ext_files[0])
    simple = module_from_spec(spec)
    spec.loader.exec_module(simple)


assert simple.test() == 123


######## simple.pyx ###########

def test():
    return 123
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/self_in_ext_type_closure.pyx0000644000175100001770000000347400000000000023410 0ustar00runnerdocker00000000000000# mode: run
# ticket: t742

import cython

@cython.cclass
class ExtType(object):
    def const1(self):
        return 1

    def ext_method0(self):
        """
        >>> x = ExtType()
        >>> x.ext_method0()()
        1
        """
        def func():
            return self.const1()
        return func

    def ext_method1(self, a):
        """
        >>> x = ExtType()
        >>> x.ext_method1(2)()
        (1, 2)
        """
        def func():
            return self.const1(), a
        return func

    def ext_method1_def(self, a=2):
        """
        >>> x = ExtType()
        >>> x.ext_method1_def()()
        (1, 2)
        >>> x.ext_method1_def(3)()
        (1, 3)
        """
        def func():
            return self.const1(), a
        return func

    def ext_method_args(self, *args):
        """
        >>> x = ExtType()
        >>> x.ext_method_args(2)()
        (1, 2)
        """
        def func():
            return self.const1(), args[0]
        return func

    def ext_method_args_only(*args):
        """
        >>> x = ExtType()
        >>> x.ext_method_args_only(2)()
        (1, 2)
        """
        def func():
            return args[0].const1(), args[1]
        return func


@cython.cclass
class GenType(object):
    def const1(self):
        return 1

    def gen0(self):
        """
        >>> x = GenType()
        >>> tuple(x.gen0())
        (1, 2)
        """
        yield self.const1()
        yield 2

    def gen1(self, a):
        """
        >>> x = GenType()
        >>> tuple(x.gen1(2))
        (1, 2)
        """
        yield self.const1()
        yield a

    def gen_default(self, a=2):
        """
        >>> x = GenType()
        >>> tuple(x.gen_default())
        (1, 2)
        >>> tuple(x.gen_default(3))
        (1, 3)
        """
        yield self.const1()
        yield a
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/seq_mul.py0000644000175100001770000000640500000000000017566 0ustar00runnerdocker00000000000000# mode: run
# tag: list, mulop, pure3.0

import cython


@cython.test_fail_if_path_exists("//MulNode")
@cython.test_assert_path_exists("//ListNode[@mult_factor]")
def cint_times_list(n: cython.int):
    """
    >>> cint_times_list(3)
    []
    [None, None, None]
    [3, 3, 3]
    [1, 2, 3, 1, 2, 3, 1, 2, 3]
    """
    a = n * []
    b = n * [None]
    c = n * [n]
    d = n * [1, 2, 3]

    print(a)
    print(b)
    print(c)
    print(d)


@cython.test_fail_if_path_exists("//MulNode")
@cython.test_assert_path_exists("//ListNode[@mult_factor]")
def list_times_cint(n: cython.int):
    """
    >>> list_times_cint(3)
    []
    [None, None, None]
    [3, 3, 3]
    [1, 2, 3, 1, 2, 3, 1, 2, 3]
    """
    a = [] * n
    b = [None] * n
    c = [n] * n
    d = [1, 2, 3] * n

    print(a)
    print(b)
    print(c)
    print(d)


@cython.test_fail_if_path_exists("//MulNode")
@cython.test_assert_path_exists("//TupleNode[@mult_factor]")
def const_times_tuple(v: cython.int):
    """
    >>> const_times_tuple(4)
    ()
    (None, None)
    (4, 4)
    (1, 2, 3, 1, 2, 3)
    """
    a = 2 * ()
    b = 2 * (None,)
    c = 2 * (v,)
    d = 2 * (1, 2, 3)

    print(a)
    print(b)
    print(c)
    print(d)


@cython.test_fail_if_path_exists("//MulNode")
@cython.test_assert_path_exists("//TupleNode[@mult_factor]")
def cint_times_tuple(n: cython.int):
    """
    >>> cint_times_tuple(3)
    ()
    (None, None, None)
    (3, 3, 3)
    (1, 2, 3, 1, 2, 3, 1, 2, 3)
    """
    a = n * ()
    b = n * (None,)
    c = n * (n,)
    d = n * (1, 2, 3)

    print(a)
    print(b)
    print(c)
    print(d)


@cython.test_fail_if_path_exists("//MulNode")
@cython.test_assert_path_exists("//TupleNode[@mult_factor]")
def tuple_times_cint(n: cython.int):
    """
    >>> tuple_times_cint(3)
    ()
    (None, None, None)
    (3, 3, 3)
    (1, 2, 3, 1, 2, 3, 1, 2, 3)
    """
    a = () * n
    b = (None,) * n
    c = (n,) * n
    d = (1, 2, 3) * n

    print(a)
    print(b)
    print(c)
    print(d)


# TODO: enable in Cython 3.1 when we can infer unsafe C int operations as PyLong
#@cython.test_fail_if_path_exists("//MulNode")
def list_times_pyint(n: cython.longlong):
    """
    >>> list_times_cint(3)
    []
    [None, None, None]
    [3, 3, 3]
    [1, 2, 3, 1, 2, 3, 1, 2, 3]
    """
    py_n = n + 1  # might overflow => should be inferred as Python long!

    a = [] * py_n
    b = [None] * py_n
    c = py_n * [n]
    d = py_n * [1, 2, 3]

    print(a)
    print(b)
    print(c)
    print(d)


@cython.cfunc
def sideeffect(x) -> cython.int:
    global _sideeffect_value
    _sideeffect_value += 1
    return _sideeffect_value + x


def reset_sideeffect():
    global _sideeffect_value
    _sideeffect_value = 0


@cython.test_fail_if_path_exists("//MulNode")
@cython.test_assert_path_exists("//ListNode[@mult_factor]")
def complicated_cint_times_list(n: cython.int):
    """
    >>> complicated_cint_times_list(3)
    []
    [None, None, None, None]
    [3, 3, 3, 3]
    [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
    """
    reset_sideeffect()
    a = [] * sideeffect((lambda: n)())
    reset_sideeffect()
    b = sideeffect((lambda: n)()) * [None]
    reset_sideeffect()
    c = [n] * sideeffect((lambda: n)())
    reset_sideeffect()
    d = sideeffect((lambda: n)()) * [1, 2, 3]

    print(a)
    print(b)
    print(c)
    print(d)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/sequential_parallel.pyx0000644000175100001770000004632500000000000022344 0ustar00runnerdocker00000000000000# tag: run

cimport cython.parallel
from cython.parallel import prange, threadid
from cython.view cimport array
from libc.stdlib cimport malloc, calloc, free, abort
from libc.stdio cimport puts

import os
import sys

try:
    from builtins import next # Py3k
except ImportError:
    def next(it):
        return it.next()

#@cython.test_assert_path_exists(
#    "//ParallelWithBlockNode//ParallelRangeNode[@schedule = 'dynamic']",
#    "//GILStatNode[@state = 'nogil]//ParallelRangeNode")
def test_prange():
    """
    >>> test_prange()
    (9, 9, 45, 45)
    """
    cdef Py_ssize_t i, j, sum1 = 0, sum2 = 0

    with nogil, cython.parallel.parallel():
        for i in prange(10, schedule='dynamic'):
            sum1 += i

    for j in prange(10, nogil=True):
        sum2 += j

    return i, j, sum1, sum2

def test_descending_prange():
    """
    >>> test_descending_prange()
    5
    """
    cdef int i, start = 5, stop = -5, step = -2
    cdef int sum = 0

    for i in prange(start, stop, step, nogil=True):
        sum += i

    return sum

def test_prange_matches_range(int start, int stop, int step):
    """
    >>> test_prange_matches_range(0, 8, 3)
    >>> test_prange_matches_range(0, 9, 3)
    >>> test_prange_matches_range(0, 10, 3)

    >>> test_prange_matches_range(0, 10, -3)

    >>> test_prange_matches_range(0, -10, -3)
    >>> test_prange_matches_range(1, -10, -3)
    >>> test_prange_matches_range(2, -10, -3)
    >>> test_prange_matches_range(3, -10, -3)
    """
    cdef int i = -765432, range_last = -876543, prange_last = -987654
    prange_set = set()
    for i in prange(start, stop, step, nogil=True, num_threads=3):
        prange_last = i
        with gil:
            prange_set.add(i)
    range_set = set(range(start, stop, step))
    assert range_set == prange_set, "missing: %s extra %s" % (sorted(range_set-prange_set), sorted(prange_set - range_set))
    for ii in range(start, stop, step):
        range_last = ii
    if range_set:
        assert prange_last == i
        assert range_last == prange_last


def test_propagation():
    """
    >>> test_propagation()
    (9, 9, 9, 9, 450, 450)
    """
    cdef int i = 0, j = 0, x = 0, y = 0
    cdef int sum1 = 0, sum2 = 0

    for i in prange(10, nogil=True):
        for j in prange(10):
            sum1 += i

    with nogil, cython.parallel.parallel():
        for x in prange(10):
            for y in prange(10):
                sum2 += y

    return i, j, x, y, sum1, sum2

# DISABLED, not allowed in OpenMP 3.0 (fails on Windows)
#def test_unsigned_operands():
#    """
#    >>> test_unsigned_operands()
#    10
#    """
#    cdef int i
#    cdef int start = -5
#    cdef unsigned int stop = 5
#    cdef int step = 1
#
#    cdef int steps_taken = 0
#    cdef int *steps_takenp = &steps_taken
#
#    for i in prange(start, stop, step, nogil=True):
#        steps_taken += 1
#        if steps_takenp[0] > 10:
#            abort()
#
#    return steps_taken

def test_reassign_start_stop_step():
    """
    >>> test_reassign_start_stop_step()
    20
    """
    cdef int start = 0, stop = 10, step = 2
    cdef int i
    cdef int sum = 0

    for i in prange(start, stop, step, nogil=True):
        start = -2
        stop = 2
        step = 0

        sum += i

    return sum

def test_closure_parallel_privates():
    """
    >>> test_closure_parallel_privates()
    9 9
    45 45
    0 0 9 9
    """
    cdef int x

    def test_target():
        nonlocal x
        for x in prange(10, nogil=True):
            pass
        return x

    print test_target(), x

    def test_reduction():
        nonlocal x
        cdef int i

        x = 0
        for i in prange(10, nogil=True):
            x += i

        return x

    print test_reduction(), x

    def test_generator():
        nonlocal x
        cdef int i

        x = 0
        yield x
        x = 2

        for i in prange(10, nogil=True):
            x = i

        yield x

    g = test_generator()
    print next(g), x, next(g), x

def test_closure_parallel_with_gil():
    """
    >>> test_closure_parallel_with_gil()
    45
    45
    """
    cdef int sum = 0
    temp1 = 5
    temp2 = -5

    def test_reduction():
        nonlocal sum, temp1, temp2

        cdef int i

        for i in prange(10, nogil=True):
            with gil:
                sum += temp1 + temp2 + i
                # assert abs(sum - sum) == 0

        return sum

    print test_reduction()
    print sum

def test_pure_mode():
    """
    >>> test_pure_mode()
    0
    1
    2
    3
    4
    4
    3
    2
    1
    0
    0
    """
    import Cython.Shadow
    pure_parallel = sys.modules['cython.parallel']

    for i in pure_parallel.prange(5):
        print i

    for i in pure_parallel.prange(4, -1, -1, schedule='dynamic', nogil=True):
        print i

    with pure_parallel.parallel():
        print pure_parallel.threadid()

cdef extern from "types.h":
    ctypedef short actually_long_t
    ctypedef long actually_short_t

ctypedef int myint_t

def test_nan_init():
    """
    >>> test_nan_init()
    """
    cdef int mybool = 0
    cdef int err = 0
    cdef int *errp = &err

    cdef signed char a1 = 10
    cdef unsigned char a2 = 10
    cdef short b1 = 10
    cdef unsigned short b2 = 10
    cdef int c1 = 10
    cdef unsigned int c2 = 10
    cdef long d1 = 10
    cdef unsigned long d2 = 10
    cdef long long e1 = 10
    cdef unsigned long long e2 = 10

    cdef actually_long_t miss1 = 10
    cdef actually_short_t miss2 = 10
    cdef myint_t typedef1 = 10

    cdef float f = 10.0
    cdef double g = 10.0
    cdef long double h = 10.0

    cdef void *p =  10

    with nogil, cython.parallel.parallel():
        # First, trick the error checking to make it believe these variables
        # are initialized after this if

        if mybool: # mybool is always false!
            a1 = a2 = b1 = b2 = c1 = c2 = d1 = d2 = e1 = e2 = 0
            f = g = h = 0.0
            p = NULL
            miss1 = miss2 = typedef1 = 0

        if (a1 == 10 or a2 == 10 or
            b1 == 10 or b2 == 10 or
            c1 == 10 or c2 == 10 or
            d1 == 10 or d2 == 10 or
            e1 == 10 or e2 == 10 or
            f == 10.0 or g == 10.0 or h == 10.0 or
            p ==  10 or miss1 == 10 or miss2 == 10
            or typedef1 == 10):
            errp[0] = 1

    cdef int i
    for i in prange(10, nogil=True):
        # First, trick the error checking to make it believe these variables
        # are initialized after this if

        if mybool: # mybool is always false!
            a1 = a2 = b1 = b2 = c1 = c2 = d1 = d2 = e1 = e2 = 0
            f = g = h = 0.0
            p = NULL
            miss1 = miss2 = typedef1 = 0

        if (a1 == 10 or a2 == 10 or
            b1 == 10 or b2 == 10 or
            c1 == 10 or c2 == 10 or
            d1 == 10 or d2 == 10 or
            e1 == 10 or e2 == 10 or
            f == 10.0 or g == 10.0 or h == 10.0 or
            p ==  10 or miss1 == 10 or miss2 == 10
            or typedef1 == 10):
            errp[0] = 1

    if err:
        raise Exception("One of the values was not initialized to a maximum "
                        "or NaN value")

    c1 = 20
    with nogil, cython.parallel.parallel():
        c1 = 16


cdef void nogil_print(char *s) noexcept with gil:
    print s.decode('ascii')

def test_else_clause():
    """
    >>> test_else_clause()
    else clause executed
    """
    cdef int i

    for i in prange(5, nogil=True):
        pass
    else:
        nogil_print('else clause executed')

def test_prange_break():
    """
    >>> test_prange_break()
    """
    cdef int i

    for i in prange(10, nogil=True):
        if i == 8:
            break
    else:
        nogil_print('else clause executed')

def test_prange_continue():
    """
    >>> test_prange_continue()
    else clause executed
    0 0
    1 0
    2 2
    3 0
    4 4
    5 0
    6 6
    7 0
    8 8
    9 0
    """
    cdef int i
    cdef int *p =  calloc(10, sizeof(int))

    if p == NULL:
        raise MemoryError

    for i in prange(10, nogil=True):
        if i % 2 != 0:
            continue

        p[i] = i
    else:
        nogil_print('else clause executed')

    for i in range(10):
       print i, p[i]

    free(p)

def test_nested_break_continue():
    """
    >>> test_nested_break_continue()
    6 7 6 7
    8
    """
    cdef int i, j, result1 = 0, result2 = 0

    for i in prange(10, nogil=True, num_threads=2, schedule='static'):
        for j in prange(10, num_threads=2, schedule='static'):
            if i == 6 and j == 7:
                result1 = i
                result2 = j
                break
        else:
            continue

        break

    print i, j, result1, result2

    with nogil, cython.parallel.parallel(num_threads=2):
        for i in prange(10, schedule='static'):
            if i == 8:
                break
            else:
                continue

    print i

cdef int parallel_return() noexcept nogil:
    cdef int i

    for i in prange(10):
        if i == 8:
            return i
    else:
        return 1

    return 2

def test_return():
    """
    >>> test_return()
    8
    """
    print parallel_return()

def test_parallel_exceptions():
    """
    >>> test_parallel_exceptions()
    I am executed first
    ('propagate me',) 0
    """
    cdef int i, j, sum = 0

    mylist = []

    try:
        for i in prange(10, nogil=True):
            try:
                for j in prange(10):
                    with gil:
                        raise Exception("propagate me")

                    sum += i * j
                sum += i
            finally:
                with gil:
                    mylist.append("I am executed first")
    except Exception, e:
        print mylist[0]
        print e.args, sum

def test_parallel_exceptions_unnested():
    """
    >>> test_parallel_exceptions_unnested()
    ('I am executed first', 0)
    ('propagate me',) 0
    """
    cdef int i, sum = 0

    mylist = []

    try:
        with nogil, cython.parallel.parallel():
            try:
                for i in prange(10):
                    with gil:
                        raise Exception("propagate me")

                    sum += i
            finally:
                with gil:
                    mylist.append(("I am executed first", sum))
    except Exception, e:
        print mylist[0]
        print e.args, sum

cdef int parallel_exc_cdef() except -3:
    cdef int i, j
    for i in prange(10, nogil=True):
        for j in prange(10, num_threads=6):
            with gil:
                raise Exception("propagate me")

    return 0

cdef int parallel_exc_cdef_unnested() except -3:
    cdef int i
    for i in prange(10, nogil=True):
        with gil:
            raise Exception("propagate me")

    return 0

def test_parallel_exc_cdef():
    """
    >>> test_parallel_exc_cdef()
    Traceback (most recent call last):
        ...
    Exception: propagate me
    """
    parallel_exc_cdef_unnested()
    parallel_exc_cdef()

cpdef int parallel_exc_cpdef() except -3:
    cdef int i, j
    for i in prange(10, nogil=True):
        for j in prange(10, num_threads=6):
            with gil:
                raise Exception("propagate me")

    return 0

cpdef int parallel_exc_cpdef_unnested() except -3:
    cdef int i, j
    for i in prange(10, nogil=True):
        with gil:
            raise Exception("propagate me")

    return 0


def test_parallel_exc_cpdef():
    """
    >>> test_parallel_exc_cpdef()
    Traceback (most recent call last):
        ...
    Exception: propagate me
    """
    parallel_exc_cpdef_unnested()
    parallel_exc_cpdef()

cdef int parallel_exc_nogil_swallow() except -1:
    cdef int i, j
    for i in prange(10, nogil=True):
        try:
            for j in prange(10):
                with gil:
                    raise Exception("propagate me")
        finally:
            return i

    return 0

cdef int parallel_exc_nogil_swallow_unnested() except -1:
    cdef int i
    with nogil:
        try:
            for i in prange(10):
                with gil:
                    raise Exception("propagate me")
        finally:
            return i

    return 0

def test_parallel_exc_nogil_swallow():
    """
    >>> test_parallel_exc_nogil_swallow()
    execute me
    execute me
    """
    parallel_exc_nogil_swallow_unnested()
    print 'execute me'
    parallel_exc_nogil_swallow()
    print 'execute me'

def parallel_exc_replace():
    """
    >>> parallel_exc_replace()
    Traceback (most recent call last):
        ...
    Exception: propagate me instead
    """
    cdef int i, j
    for i in prange(10, nogil=True):
        with gil:
            try:
                for j in prange(10, nogil=True):
                    with gil:
                        raise Exception("propagate me")
            except Exception, e:
                raise Exception("propagate me instead")

    return 0


def parallel_exceptions2():
    """
    >>> parallel_exceptions2()
    Traceback (most recent call last):
       ...
    Exception: propagate me
    """
    cdef int i, j, k

    for i in prange(10, nogil=True):
        for j in prange(10):
            for k in prange(10):
                if i + j + k > 20:
                    with gil:
                        raise Exception("propagate me")
                        break
                    continue
                    return

def test_parallel_with_gil_return():
    """
    >>> test_parallel_with_gil_return()
    True
    45
    """
    cdef int i, sum = 0

    for i in prange(10, nogil=True):
        with gil:
            obj = i
            sum += obj

    print obj in range(10)

    with nogil, cython.parallel.parallel():
        with gil:
            return sum

def test_parallel_with_gil_continue_unnested():
    """
    >>> test_parallel_with_gil_continue_unnested()
    20
    """
    cdef int i, sum = 0

    for i in prange(10, nogil=True):
        with gil:
            if i % 2:
                continue

        sum += i

    print sum


cdef int inner_parallel_section() noexcept nogil:
    cdef int j, sum = 0
    for j in prange(10):
        sum += j
    return sum

def outer_parallel_section():
    """
    >>> outer_parallel_section()
    450
    """
    cdef int i, sum = 0
    for i in prange(10, nogil=True):
        sum += inner_parallel_section()
    return sum

cdef int nogil_cdef_except_clause() except -1 nogil:
    return 1

cdef void nogil_cdef_except_star() except * nogil:
    pass

def test_nogil_cdef_except_clause():
    """
    >>> test_nogil_cdef_except_clause()
    """
    cdef int i
    for i in prange(10, nogil=True):
        nogil_cdef_except_clause()
        nogil_cdef_except_star()

def test_num_threads_compile():
    cdef int i
    for i in prange(10, nogil=True, num_threads=2):
        pass

    with nogil, cython.parallel.parallel(num_threads=2):
        pass

    with nogil, cython.parallel.parallel(num_threads=2):
        for i in prange(10):
            pass

cdef int chunksize() noexcept nogil:
    return 3

def test_chunksize():
    """
    >>> test_chunksize()
    45
    45
    45
    """
    cdef int i, sum

    sum = 0
    for i in prange(10, nogil=True, num_threads=2, schedule='static', chunksize=chunksize()):
        sum += i
    print sum

    sum = 0
    for i in prange(10, nogil=True, num_threads=6, schedule='dynamic', chunksize=chunksize()):
        sum += i
    print sum

    sum = 0
    with nogil, cython.parallel.parallel():
        for i in prange(10, schedule='guided', chunksize=chunksize()):
            sum += i
    print sum


cdef class PrintOnDealloc(object):
    def __dealloc__(self):
        print "deallocating..."

def error():
    raise Exception("propagate me")

def test_clean_temps():
    """
    >>> test_clean_temps()
    deallocating...
    propagate me
    """
    cdef Py_ssize_t i

    try:
        for i in prange(100, nogil=True, num_threads=1):
            with gil:
                x = PrintOnDealloc() + error()
    except Exception, e:
        print e.args[0]


def test_pointer_temps(double x):
    """
    >>> test_pointer_temps(1.0)
    4.0
    """
    cdef Py_ssize_t i
    cdef double* f
    cdef double[:] arr = array(format="d", shape=(10,), itemsize=sizeof(double))
    arr[0] = 4.0
    arr[1] = 3.0

    for i in prange(10, nogil=True, num_threads=1):
        f = &arr[0]

    return f[0]


def test_prange_in_with(int x, ctx):
    """
    >>> from contextlib import contextmanager
    >>> @contextmanager
    ... def ctx(l): yield l
    >>> test_prange_in_with(4, ctx([0]))
    6
    """
    cdef int i
    with ctx as l:
        for i in prange(x, nogil=True):
            with gil:
                l[0] += i
        return l[0]


cdef extern from *:
    """
    #ifdef _OPENMP
    #define _get_addr(_x, _idx) &_x
    #else
    #define _get_addr(_x, _idx) (&_x+_idx)
    #endif
    #define address_of_temp(store, temp, idx) store = _get_addr(temp, idx)
    #define address_of_temp2(store, ignore, temp, idx) store = _get_addr(temp, idx)

    double get_value() {
        return 1.0;
    }
    """
    void address_of_temp(...) nogil
    void address_of_temp2(...) nogil
    double get_value() except -1.0 nogil  # will generate a temp for exception checking

def test_inner_private():
    """
    Determines if a temp variable is private by taking its address in multiple threads
    and seeing if they're the same (thread private variables should have different
    addresses
    >>> test_inner_private()
    ok
    """
    cdef double* not_parallel[2]
    cdef double* inner_vals[2]
    cdef double* outer_vals[2]
    cdef Py_ssize_t n, m

    for n in range(2):
        address_of_temp(not_parallel[n], get_value(), 0)
    assert not_parallel[0] == not_parallel[1], "Addresses should be the same since they come from the same temp"

    for n in prange(2, num_threads=2, schedule='static', chunksize=1, nogil=True):
        address_of_temp(outer_vals[n], get_value(), n)
        for m in prange(1):
            # second temp just ensures different numbering
            address_of_temp2(inner_vals[n], get_value(), get_value(), n)

    inner_are_the_same = inner_vals[0] == inner_vals[1]
    outer_are_the_same = outer_vals[0] == outer_vals[1]

    assert outer_are_the_same == False, "Temporary variables in outer loop should be private"
    assert inner_are_the_same == False,  "Temporary variables in inner loop should be private"

    print('ok')

cdef void prange_exception_checked_function(int* ptr, int id) except * nogil:
    # requires the GIL after each call
    ptr[0] = id;

cdef void prange_call_exception_checked_function_impl(int* arr, int N) nogil:
    # Inside a nogil function, prange can't be sure the GIL has been released.
    # Therefore Cython must release the GIL itself.
    # Otherwise, we can experience cause lock-ups if anything inside it acquires the GIL
    # (since if any other thread has finished, it will be holding the GIL).
    #
    # An equivalent test with prange is in "sequential_parallel.pyx"
    cdef int i
    for i in prange(N, num_threads=4, schedule='static', chunksize=1):
        prange_exception_checked_function(arr+i, i)

def test_prange_call_exception_checked_function():
    """
    >>> test_prange_call_exception_checked_function()
    """

    cdef int N = 10000
    cdef int* buf = malloc(sizeof(int)*N)
    if buf == NULL:
        raise MemoryError
    try:
        # Don't release the GIL
        prange_call_exception_checked_function_impl(buf, N)

        for i in range(N):
            assert buf[i] == i
    finally:
        free(buf)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/set.pyx0000644000175100001770000002243600000000000017106 0ustar00runnerdocker00000000000000
cimport cython


def cython_set():
    """
    >>> cython_set() is set
    True
    """
    assert set is cython.set
    return cython.set


def cython_frozenset():
    """
    >>> cython_frozenset() is frozenset
    True
    """
    assert frozenset is cython.frozenset
    return cython.frozenset


def cython_set_override():
    """
    >>> cython_set_override() is set
    True
    """
    set = 1
    return cython.set


def cython_frozenset_override():
    """
    >>> cython_frozenset_override() is frozenset
    True
    """
    frozenset = 1
    return cython.frozenset


def test_set_literal():
    """
    >>> type(test_set_literal()) is set
    True
    >>> sorted(test_set_literal())
    ['a', 'b', 1]
    """
    cdef set s1 = {1,'a',1,'b','a'}
    return s1


def test_set_add():
    """
    >>> type(test_set_add()) is set
    True
    >>> sorted(test_set_add())
    ['a', 1, (1, 2)]
    """
    cdef set s1
    s1 = set([1, (1, 2)])
    s1.add(1)
    s1.add('a')
    s1.add(1)
    s1.add((1,2))
    return s1


def test_set_contains(v):
    """
    >>> test_set_contains(1)
    True
    >>> test_set_contains(2)
    False
    >>> test_set_contains(frozenset([1, 2, 3]))
    True
    >>> test_set_contains(frozenset([1, 2]))
    False
    >>> test_set_contains(set([1, 2, 3]))
    True
    >>> test_set_contains(set([1, 2]))
    False
    >>> try: test_set_contains([1, 2])
    ... except TypeError: pass
    ... else: print("NOT RAISED!")
    """
    cdef set s1
    s1 = set()
    s1.add(1)
    s1.add('a')
    s1.add(frozenset([1, 2, 3]))
    return v in s1


def test_set_update(v=None):
    """
    >>> type(test_set_update()) is set
    True
    >>> sorted(test_set_update())
    ['a', 'b', 'c', 1, 2, (1, 2)]
    >>> sorted(test_set_update([]))
    ['a', 'b', 'c', 1, 2, (1, 2)]
    >>> try: test_set_update(object())
    ... except TypeError: pass
    ... else: print("NOT RAISED!")
    """
    cdef set s1
    s1 = set([1, (1, 2)])
    s1.update((1,))
    s1.update('abc')
    s1.update(set([1]))
    s1.update(frozenset((1,2)))
    if v is not None:
        s1.update(v)
    return s1


def test_set_multi_update():
    """
    >>> type(test_set_multi_update()) is set
    True
    >>> sorted(test_set_multi_update())
    ['a', 'b', 'c', 1, 2, 3]
    """
    cdef set s1 = set()
    s1.update('abc', set([1, 3]), frozenset([1, 2]))
    return s1


def test_object_update(v=None):
    """
    >>> type(test_object_update()) is set
    True
    >>> sorted(test_object_update())
    ['a', 'b', 'c', 1, 2, (1, 2)]
    >>> sorted(test_object_update([]))
    ['a', 'b', 'c', 1, 2, (1, 2)]
    >>> try: test_object_update(object())
    ... except TypeError: pass
    ... else: print("NOT RAISED!")
    """
    cdef object s1
    s1 = set([1, (1, 2)])
    s1.update((1,))
    s1.update('abc')
    s1.update(set([1]))
    s1.update(frozenset((1,2)))
    if v is not None:
        s1.update(v)
    return s1


def test_set_clear():
    """
    >>> type(test_set_clear()) is set
    True
    >>> list(test_set_clear())
    []
    """
    cdef set s1
    s1 = set([1])
    s1.clear()
    return s1


def test_set_clear_None():
    """
    >>> test_set_clear_None()
    Traceback (most recent call last):
    AttributeError: 'NoneType' object has no attribute 'clear'
    """
    cdef set s1 = None
    s1.clear()


def test_set_list_comp():
    """
    >>> type(test_set_list_comp()) is set
    True
    >>> sorted(test_set_list_comp())
    [0, 1, 2]
    """
    cdef set s1
    s1 = set([i%3 for i in range(5)])
    return s1


def test_frozenset_list_comp():
    """
    >>> type(test_frozenset_list_comp()) is frozenset
    True
    >>> sorted(test_frozenset_list_comp())
    [0, 1, 2]
    """
    cdef frozenset s1
    s1 = frozenset([i%3 for i in range(5)])
    return s1


def test_set_pop():
    """
    >>> type(test_set_pop()) is set
    True
    >>> list(test_set_pop())
    []
    """
    cdef set s1
    s1 = set()
    s1.add('2')
    two = s1.pop()
    return s1


@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode")
def test_object_pop(s):
    """
    >>> s = set([2])
    >>> test_object_pop(s)
    2
    >>> list(s)
    []
    """
    return s.pop()


def test_noop_pop():
    """
    >>> test_noop_pop()
    """
    set([0]).pop()


def test_noop_pop_exception():
    """
    >>> try: test_noop_pop_exception()
    ... except KeyError: pass
    ... else: print("KeyError expected but not raised!")
    """
    set([]).pop()


def test_set_discard():
    """
    >>> type(test_set_discard()) is set
    True
    >>> sorted(test_set_discard())
    ['12', 233]
    """
    cdef set s1
    s1 = set()
    s1.add('12')
    s1.add(3)
    s1.add(233)
    s1.discard('3')
    s1.discard(3)
    return s1


def test_set_sideeffect_unhashable_failure():
    """
    >>> test_set_sideeffect_unhashable_failure()
    [2, 4, 5]
    """
    L = []
    def sideeffect(x):
        L.append(x)
        return x
    def unhashable_value(x):
        L.append(x)
        return set()
    try:
        s = set([1,sideeffect(2),3,unhashable_value(4),sideeffect(5)])
    except TypeError: pass
    else: assert False, "expected exception not raised"
    return L


def test_set_sideeffect_unhashable_failure_literal():
    """
    >>> test_set_sideeffect_unhashable_failure_literal()
    [2, 4, 5]
    """
    L = []
    def sideeffect(x):
        L.append(x)
        return x
    def unhashable_value(x):
        L.append(x)
        return set()
    try:
        s = {1,sideeffect(2),3,unhashable_value(4),sideeffect(5)}
    except TypeError: pass
    else: assert False, "expected exception not raised"
    return L


def test_frozenset_sideeffect_unhashable_failure():
    """
    >>> test_frozenset_sideeffect_unhashable_failure()
    [2, 4, 5]
    """
    L = []
    def sideeffect(x):
        L.append(x)
        return x
    def unhashable_value(x):
        L.append(x)
        return set()
    try:
        s = frozenset([1,sideeffect(2),3,unhashable_value(4),sideeffect(5)])
    except TypeError: pass
    else: assert False, "expected exception not raised"
    return L


@cython.test_assert_path_exists("//SetNode")
@cython.test_fail_if_path_exists(
    "//SimpleCallNode",
    "//PythonCapiCallNode"
)
def test_set_of_list():
    """
    >>> s = test_set_of_list()
    >>> isinstance(s, set)
    True
    >>> sorted(s)
    [1, 2, 3]
    """
    return set([1, 2, 3])


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//SetNode")
def test_frozenset_of_list():
    """
    >>> s = test_frozenset_of_list()
    >>> isinstance(s, frozenset)
    True
    >>> sorted(s)
    [1, 2, 3]
    """
    return frozenset([1, 2, 3])


@cython.test_assert_path_exists("//SetNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def test_set_of_tuple():
    """
    >>> s = test_set_of_tuple()
    >>> isinstance(s, set)
    True
    >>> sorted(s)
    [1, 2, 3]
    """
    return set((1, 2, 3))


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//SetNode")
def test_frozenset_of_tuple():
    """
    >>> s = test_frozenset_of_tuple()
    >>> isinstance(s, frozenset)
    True
    >>> sorted(s)
    [1, 2, 3]
    """
    return frozenset((1, 2, 3))


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists(
    "//SimpleCallNode",
    "//SetNode"
)
def test_set_of_iterable(x):
    """
    >>> s = test_set_of_iterable([1, 2, 3])
    >>> isinstance(s, set)
    True
    >>> sorted(s)
    [1, 2, 3]
    """
    return set(x)


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists(
    "//SimpleCallNode",
    "//SetNode"
)
def test_frozenset_of_iterable(x):
    """
    >>> s = test_frozenset_of_iterable([1, 2, 3])
    >>> isinstance(s, frozenset)
    True
    >>> sorted(s)
    [1, 2, 3]

    >>> s = test_frozenset_of_iterable(frozenset([1, 2, 3]))
    >>> isinstance(s, frozenset)
    True
    >>> sorted(s)
    [1, 2, 3]
    """
    return frozenset(x)


@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists(
    "//SimpleCallNode",
    "//SetNode"
)
def test_empty_frozenset():
    """
    >>> s = test_empty_frozenset()
    >>> isinstance(s, frozenset)
    True
    >>> len(s)
    0
    >>> import sys
    >>> sys.version_info >= (3, 10) or s is frozenset()   # singleton (in Python < 3.10)!
    True
    """
    return frozenset()


@cython.test_fail_if_path_exists(
    '//ListNode//ListNode',
    '//ListNode//PythonCapiCallNode//PythonCapiCallNode',
    '//ListNode//SimpleCallNode//SimpleCallNode',
)
def test_singleton_empty_frozenset():
    """
    >>> import sys
    >>> test_singleton_empty_frozenset() if sys.version_info < (3, 10) else 1  # from CPython's test_set.py
    1
    """
    f = frozenset()
    efs = [frozenset(), frozenset([]), frozenset(()), frozenset(''),
           frozenset(), frozenset([]), frozenset(()), frozenset(''),
           frozenset(range(0)), frozenset(frozenset()),
           frozenset(f), f]
    return len(set(map(id, efs)))  # note, only a singleton in Python <3.10


def sorted(it):
    # Py3 can't compare different types
    chars = []
    nums = []
    tuples = []
    for item in it:
        if type(item) is int:
            nums.append(item)
        elif type(item) is tuple:
            tuples.append(item)
        else:
            chars.append(item)
    nums.sort()
    chars.sort()
    tuples.sort()
    return chars+nums+tuples
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/set_discard_remove.py0000644000175100001770000000177100000000000021763 0ustar00runnerdocker00000000000000
def set_discard():
    """
    >>> sorted(set_discard())
    [1, 2]
    """
    s = set([1,2,3])
    s.discard(3)
    return s


def set_discard_missing():
    """
    >>> sorted(set_discard_missing())
    [1, 2, 3]
    """
    s = set([1,2,3])
    s.discard(4)
    return s


def set_discard_set():
    """
    >>> s = set_discard_set()
    >>> len(s)
    1
    >>> sorted(s.pop())
    [1, 2]
    """
    s = set([frozenset([1,2]), frozenset([2,3])])
    s.discard(set([2,3]))
    return s


def set_remove():
    """
    >>> sorted(set_remove())
    [1, 2]
    """
    s = set([1,2,3])
    s.remove(3)
    return s


def set_remove_missing():
    """
    >>> sorted(set_remove_missing())
    Traceback (most recent call last):
    KeyError: 4
    """
    s = set([1,2,3])
    s.remove(4)
    return s


def set_remove_set():
    """
    >>> s = set_remove_set()
    >>> len(s)
    1
    >>> sorted(s.pop())
    [1, 2]
    """
    s = set([frozenset([1,2]), frozenset([2,3])])
    s.remove(set([2,3]))
    return s
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/set_item.pyx0000644000175100001770000000276400000000000020126 0ustar00runnerdocker00000000000000# mode: run
# tag: list, dict, setitem, delitem

def set_item(obj, key, value):
    """
    >>> set_item([1, 2, 3], 1, -1)
    [1, -1, 3]
    >>> set_item([1, 2, 3], -1, -1)
    [1, 2, -1]
    >>> set_item({}, 'abc', 5)
    {'abc': 5}
    >>> set_item({}, -1, 5)
    {-1: 5}
    >>> class D(dict): pass
    >>> set_item(D({}), 'abc', 5)
    {'abc': 5}
    >>> set_item(D({}), -1, 5)
    {-1: 5}
    """
    obj[key] = value
    return obj


def set_item_int(obj, int key, value):
    """
    >>> set_item_int([1, 2, 3], 1, -1)
    [1, -1, 3]
    >>> set_item_int([1, 2, 3], -1, -1)
    [1, 2, -1]
    >>> set_item_int({}, 1, 5)
    {1: 5}
    >>> set_item_int({}, -1, 5)
    {-1: 5}
    >>> class D(dict): pass
    >>> set_item_int(D({}), 1, 5)
    {1: 5}
    >>> set_item_int(D({}), -1, 5)
    {-1: 5}
    """
    obj[key] = value
    return obj


def del_item(obj, key):
    """
    >>> del_item([1, 2, 3], 1)
    [1, 3]
    >>> del_item([1, 2, 3], -3)
    [2, 3]
    >>> class D(dict): pass
    >>> del_item({'abc': 1, 'def': 2}, 'abc')
    {'def': 2}
    >>> del_item(D({'abc': 1, 'def': 2}), 'abc')
    {'def': 2}
    >>> del_item(D({-1: 1, -2: 2}), -1)
    {-2: 2}
    """
    del obj[key]
    return obj


def del_item_int(obj, int key):
    """
    >>> del_item_int([1, 2, 3], 1)
    [1, 3]
    >>> del_item_int([1, 2, 3], -3)
    [2, 3]
    >>> class D(dict): pass
    >>> del_item_int(D({-1: 1, 1: 2}), 1)
    {-1: 1}
    >>> del_item_int(D({-1: 1, -2: 2}), -1)
    {-2: 2}
    """
    del obj[key]
    return obj
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/set_iter.pyx0000644000175100001770000000370500000000000020127 0ustar00runnerdocker00000000000000# mode: run
# tag: set

cimport cython


@cython.test_assert_path_exists(
    "//SetIterationNextNode",
)
def set_iter_comp(set s):
    """
    >>> s = set([1, 2, 3])
    >>> sorted(set_iter_comp(s))
    [1, 2, 3]
    """
    return [x for x in s]


@cython.test_assert_path_exists(
    "//SetIterationNextNode",
)
def set_iter_comp_typed(set s):
    """
    >>> s = set([1, 2, 3])
    >>> sorted(set_iter_comp(s))
    [1, 2, 3]
    """
    cdef int x
    return [x for x in s]


@cython.test_assert_path_exists(
    "//SetIterationNextNode",
)
def frozenset_iter_comp(frozenset s):
    """
    >>> s = frozenset([1, 2, 3])
    >>> sorted(frozenset_iter_comp(s))
    [1, 2, 3]
    """
    return [x for x in s]


@cython.test_assert_path_exists(
    "//SetIterationNextNode",
)
def set_iter_comp_frozenset(set s):
    """
    >>> s = set([1, 2, 3])
    >>> sorted(set_iter_comp(s))
    [1, 2, 3]
    """
    return [x for x in frozenset(s)]


@cython.test_assert_path_exists(
    "//SetIterationNextNode",
)
def set_iter_modify(set s, int value):
    """
    >>> s = set([1, 2, 3])
    >>> sorted(set_iter_modify(s, 1))
    [1, 2, 3]
    >>> sorted(set_iter_modify(s, 2))
    [1, 2, 3]
    >>> sorted(set_iter_modify(s, 3))
    [1, 2, 3]
    >>> sorted(set_iter_modify(s, 4))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    RuntimeError: ...et changed size during iteration
    """
    for x in s:
        s.add(value)
    return s


@cython.test_fail_if_path_exists(
    "//SimpleCallNode//NameNode[@name = 'enumerate']",
)
@cython.test_assert_path_exists(
    "//AddNode",
    "//SetIterationNextNode",
)
def set_iter_enumerate(set s):
    """
    >>> s = set(['a', 'b', 'c'])
    >>> numbers, values = set_iter_enumerate(s)
    >>> sorted(numbers)
    [0, 1, 2]
    >>> sorted(values)
    ['a', 'b', 'c']
    """
    cdef int i
    numbers = []
    values = []
    for i, x in enumerate(s):
        numbers.append(i)
        values.append(x)
    return numbers, values
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/set_literals.py0000644000175100001770000000427200000000000020613 0ustar00runnerdocker00000000000000# Py2.7+ only

import sys


def test_set_literal():
    """
    >>> type(test_set_literal()) is set
    True
    >>> sorted(test_set_literal())
    ['a', 'b', 1]
    """
    s1 = {1, 'a', 1, 'b', 'a'}
    return s1


def test_set_add():
    """
    >>> type(test_set_add()) is set
    True
    >>> sorted(test_set_add())
    ['a', 1, (1, 2)]
    """
    s1 = {1, (1, 2)}
    s1.add(1)
    s1.add('a')
    s1.add(1)
    s1.add((1, 2))
    return s1


def test_set_comp():
    """
    >>> type(test_set_comp()) is set
    True
    >>> sorted(test_set_comp())
    [0, 1, 2]
    """
    s1 = {i % 3 for i in range(5)}
    return s1


def test_frozenset_set_comp():
    """
    >>> type(test_frozenset_set_comp()) is frozenset
    True
    >>> sorted(test_frozenset_set_comp())
    [0, 1, 2]
    """
    s1 = frozenset({i % 3 for i in range(5)})
    return s1


def test_set_sideeffect_unhashable_failure_literal():
    """
    >>> test_set_sideeffect_unhashable_failure_literal()
    [2, 4, 5]
    """
    L = []

    def sideeffect(x):
        L.append(x)
        return x

    def unhashable_value(x):
        L.append(x)
        return set()
    try:
        s = {1, sideeffect(2), 3, unhashable_value(4), sideeffect(5)}
    except TypeError: pass
    else: assert False, "expected exception not raised"
    return L


def test_set_comp_sideeffect_unhashable_failure():
    """
    >>> test_set_comp_sideeffect_unhashable_failure()
    (None, [2, 4])
    """
    L = []

    def value(x):
        return x

    def sideeffect(x):
        L.append(x)
        return x

    def unhashable_value(x):
        L.append(x)
        return set()
    s = None
    try:
        s = {f(i) for i, f in enumerate([value, sideeffect, value, unhashable_value, sideeffect], 1)}
    except TypeError: pass
    else: assert False, "expected exception not raised"
    return s, L


def sorted(it):
    # Py3 can't compare different types
    chars = []
    nums = []
    tuples = []
    for item in it:
        if type(item) is int:
            nums.append(item)
        elif type(item) is tuple:
            tuples.append(item)
        else:
            chars.append(item)
    nums.sort()
    chars.sort()
    tuples.sort()
    return chars+nums+tuples
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/set_new.py0000644000175100001770000000056400000000000017565 0ustar00runnerdocker00000000000000"""
>>> X = make_class_with_new(cynew)
>>> X.__new__ is cynew
True
>>> X().__new__ is cynew
True
>>> def pynew(cls): return object.__new__(cls)
>>> X = make_class_with_new(pynew)
>>> X.__new__ is pynew
True
>>> X().__new__ is pynew
True
"""

def make_class_with_new(n):
    class X(object):
        __new__ = n
    return X

def cynew(cls):
    return object.__new__(cls)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/setcomp.pyx0000644000175100001770000000235700000000000017765 0ustar00runnerdocker00000000000000
cimport cython

# Py2.3 doesn't have the set type, but Cython does :)
_set = set

def setcomp():
    """
    >>> type(setcomp()) is not list
    True
    >>> type(setcomp()) is _set
    True
    >>> sorted(setcomp())
    [0, 4, 8]
    """
    x = 'abc'
    result = { x*2
             for x in range(5)
             if x % 2 == 0 }
    assert x == 'abc' # do not leak
    return result

@cython.test_assert_path_exists(
    "//InlinedGeneratorExpressionNode",
    "//ComprehensionAppendNode")
def genexp_set():
    """
    >>> type(genexp_set()) is _set
    True
    >>> sorted(genexp_set())
    [0, 4, 8]
    """
    x = 'abc'
    result = set( x*2
                  for x in range(5)
                  if x % 2 == 0 )
    assert x == 'abc' # do not leak
    return result

cdef class A:
    def __repr__(self): return u"A"
    def __richcmp__(one, other, int op): return one is other
    def __hash__(self): return id(self) % 65536

def typed():
    """
    >>> list(typed())
    [A, A, A]
    """
    cdef A obj
    return {obj for obj in {A(), A(), A()}}

def iterdict():
    """
    >>> sorted(iterdict())
    [1, 2, 3]
    """
    cdef dict d = dict(a=1,b=2,c=3)
    return {d[key] for key in d}

def sorted(it):
    l = list(it)
    l.sort()
    return l
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/setjmp.pyx0000644000175100001770000000211200000000000017602 0ustar00runnerdocker00000000000000from libc.setjmp cimport *

cdef void check_nonzero(jmp_buf ctx, int x) nogil:
    if x == 0:
        longjmp(ctx, 1)

def nonzero(int x):
    """
    >>> nonzero(-1)
    True
    >>> nonzero(0)
    False
    >>> nonzero(1)
    True
    >>> nonzero(2)
    True

    """
    cdef jmp_buf ctx
    if setjmp(ctx) == 0:
        check_nonzero(ctx, x)
        return True
    else:
        return False


from libc.string cimport strcpy
cdef char[256] error_msg
cdef jmp_buf error_ctx
cdef void error(char msg[]) nogil:
    strcpy(error_msg,msg)
    longjmp(error_ctx, 1)

cdef void c_call(int x) nogil:
    if x<=0:
        error(b"expected a positive value")

def execute_c_call(int x):
    """
    >>> execute_c_call(+2)
    >>> execute_c_call(+1)
    >>> execute_c_call(+0)
    Traceback (most recent call last):
      ...
    RuntimeError: expected a positive value
    >>> execute_c_call(-1)
    Traceback (most recent call last):
      ...
    RuntimeError: expected a positive value
    """
    if not setjmp(error_ctx):
        c_call(x)
    else:
        raise RuntimeError(error_msg.decode())
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/shapes.h0000644000175100001770000000257400000000000017206 0ustar00runnerdocker00000000000000#ifndef SHAPES_H
#define SHAPES_H

namespace shapes {

    int constructor_count = 0;
    int destructor_count = 0;

    class Shape
    {
    public:
        virtual float area() const = 0;
        Shape() { constructor_count++; }
        virtual ~Shape() { destructor_count++; }
    };

    class Rectangle : public Shape
    {
    public:
    	Rectangle() { }
        Rectangle(int width, int height)
        {
            this->width = width;
            this->height = height;
        }

        float area() const { return width * height; }
        int width;
        int height;

        int method(int arg) {
            return width * height + arg;
        }

    };

    class Square : public Rectangle
    {
    public:
        Square(int side) : Rectangle(side, side) { this->side = side; }
        int side;
    };
    
    class Ellipse : public Shape {
    public:
        Ellipse(int a, int b) { this->a = a; this->b = b; }
        float area() const { return 3.1415926535897931f * a * b; }
        int a, b;
    };
    
    class Circle : public Ellipse {
    public:
        Circle(int radius) : Ellipse(radius, radius) { this->radius = radius; }
        int radius;
    };

    class Empty : public Shape {
    public:
        float area() const { return 0; }
    };

    class EmptyWithDocstring : public Shape {
    public:
        float area() const { return 0; }
    };

}

#endif
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/short_circuit_T404.pyx0000644000175100001770000000110000000000000021670 0ustar00runnerdocker00000000000000# ticket: t404

cdef long foo(long x):
    print "foo(%s)" % x
    return x

def test_or(long a, long b):
    """
    >>> test_or(1,2)
    foo(1)
    1
    >>> test_or(1,0)
    foo(1)
    1
    >>> test_or(0,2)
    foo(0)
    foo(2)
    2
    >>> test_or(0,0)
    foo(0)
    foo(0)
    0
    """
    print foo(a) or foo(b)

def test_and(long a, long b):
    """
    >>> test_and(1,2)
    foo(1)
    foo(2)
    2
    >>> test_and(1,0)
    foo(1)
    foo(0)
    0
    >>> test_and(0,2)
    foo(0)
    0
    >>> test_and(0,0)
    foo(0)
    0
    """
    print foo(a) and foo(b)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/simpcall.pyx0000644000175100001770000000132500000000000020111 0ustar00runnerdocker00000000000000# mode: run

def f(x, y):
    x = y


cdef void g(int i, float f, char *p):
    f = i


cdef h(int i, obj):
    i = obj


def z(a, b, c):
    """
    >>> z(1,9.2, b'test')
    """
    f(a, b)
    f(a, b,)
    g(1, 2.0, "spam")
    g(a, b, c)


def fail0(a, b):
    """
    >>> fail0(1,2)
    Traceback (most recent call last):
    TypeError: f() takes exactly 2 positional arguments (0 given)
    """
    f()


def fail1(a, b):
    """
    >>> fail1(1,2)
    Traceback (most recent call last):
    TypeError: f() takes exactly 2 positional arguments (1 given)
    """
    f(a)


def failtype():
    """
    >>> failtype()
    Traceback (most recent call last):
    TypeError: an integer is required
    """
    h(42, "eggs")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/size_t.pyx0000644000175100001770000000157000000000000017604 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> test(0)
0
>>> test(1)
1
>>> test(2)
2
>>> str(test((1<<32)-1))
'4294967295'

>>> try: test(-1)
... except (OverflowError, TypeError): print("ERROR")
ERROR

>>> test(1<<128) #doctest: +ELLIPSIS
Traceback (most recent call last):
    ...
OverflowError: ...

>>> a = A(1,2)
>>> a.a == 1
True
>>> a.b == 2
True
>>> a.foo(5)
5
>>> try: a.foo(-1)
... except (OverflowError, TypeError): print("ERROR")
ERROR
>>> a.foo(1 << 180) #doctest: +ELLIPSIS
Traceback (most recent call last):
    ...
OverflowError: ...
"""

# XXX This should generate a warning !!!
cdef extern from *:
    ctypedef unsigned long size_t

def test(size_t i):
    return i

cdef class A:
    cdef public size_t a
    cdef readonly size_t b

    def __init__(self, size_t a, object b):
        self.a = a
        self.b = b

    cpdef size_t foo(self, size_t x):
        cdef object o = x
        return o
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/sizeof.pyx0000644000175100001770000000046700000000000017612 0ustar00runnerdocker00000000000000cdef struct Spam:
    char *grail

def f():
    """
    >>> f()
    """
    cdef int i, j, k
    cdef char *p
    i = sizeof(p)
    i = sizeof(j + k)
    i = sizeof(int)
    i = sizeof(long int)
    i = sizeof(void*)
    i = sizeof(Spam)
    i = sizeof(Spam*)
    i = sizeof(Spam[5])
    i = sizeof(Spam (*)())
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/slice2.pyx0000644000175100001770000000560600000000000017474 0ustar00runnerdocker00000000000000# mode: run
# tag: list, slice, slicing

def test_full(seq):
    """
    >>> l = [1,2,3,4]
    >>> test_full(l)
    [1, 2, 3, 4]
    >>> l == test_full(l)
    True
    >>> l is test_full(l)
    False
    >>> try: test_full(42)
    ... except TypeError: pass
    """
    obj = seq[:]
    return obj

def test_start(seq, start):
    """
    >>> l = [1,2,3,4]
    >>> test_start(l, 2)
    [3, 4]
    >>> test_start(l, 3)
    [4]
    >>> test_start(l, 4)
    []
    >>> test_start(l, 8)
    []
    >>> test_start(l, -3)
    [2, 3, 4]
    >>> test_start(l, -4)
    [1, 2, 3, 4]
    >>> test_start(l, -8)
    [1, 2, 3, 4]
    >>> test_start(l, 0)
    [1, 2, 3, 4]
    >>> test_start(l, None)
    [1, 2, 3, 4]
    >>> try: test_start(42, 2, 3)
    ... except TypeError: pass
    """
    obj = seq[start:]
    return obj

def test_stop(seq, stop):
    """
    >>> l = [1,2,3,4]
    >>> test_stop(l, 3)
    [1, 2, 3]
    >>> test_stop(l, -1)
    [1, 2, 3]
    >>> test_stop(l, -3)
    [1]
    >>> test_stop(l, -4)
    []
    >>> test_stop(l, -8)
    []
    >>> test_stop(l, 0)
    []
    >>> test_stop(l, None)
    [1, 2, 3, 4]
    >>> try: test_stop(42, 3)
    ... except TypeError: pass
    """
    obj = seq[:stop]
    return obj

def test_step(seq, step):
    """
    >>> l = [1,2,3,4]
    >>> test_step(l, -1)
    [4, 3, 2, 1]
    >>> test_step(l, 1)
    [1, 2, 3, 4]
    >>> test_step(l, 2)
    [1, 3]
    >>> test_step(l, 3)
    [1, 4]
    >>> test_step(l, -3)
    [4, 1]
    >>> test_step(l, None)
    [1, 2, 3, 4]
    >>> try: test_step(l, 0)
    ... except ValueError: pass
    ...
    >>> try: test_step(42, 0)
    ... except TypeError: pass
    ...
    """
    obj = seq[::step]
    return obj

def test_start_and_stop(seq, start, stop):
    """
    >>> l = [1,2,3,4]
    >>> test_start_and_stop(l, 2, 3)
    [3]
    >>> test_start_and_stop(l, -3, -1)
    [2, 3]
    >>> test_start_and_stop(l, None, None)
    [1, 2, 3, 4]
    >>> try: test_start_and_stop(42, 2, 3)
    ... except TypeError: pass
    """
    obj = seq[start:stop]
    return obj

def test_start_stop_and_step(seq, start, stop, step):
    """
    >>> l = [1,2,3,4,5]
    >>> test_start_stop_and_step(l, 0, 5, 1)
    [1, 2, 3, 4, 5]
    >>> test_start_stop_and_step(l, 5, -1, -1)
    []
    >>> test_start_stop_and_step(l, 5, None, -1)
    [5, 4, 3, 2, 1]
    >>> test_start_stop_and_step(l, 2, 5, 2)
    [3, 5]
    >>> test_start_stop_and_step(l, -100, 100, 1)
    [1, 2, 3, 4, 5]
    >>> test_start_stop_and_step(l, None, None, None)
    [1, 2, 3, 4, 5]
    >>> try: test_start_stop_and_step(l, None, None, 0)
    ... except ValueError: pass
    ... 
    >>> try: test_start_stop_and_step(42, 1, 2, 3)
    ... except TypeError: pass
    """
    obj = seq[start:stop:step]
    return obj

class A(object):
    pass

def slice_of_temporary_smoketest():
    """
    >>> slice_of_temporary_smoketest()
    [3, 2]
    """
    x = A()
    x.a = [1, 2]
    x.a[:] = [3,2]
    return x.a
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/slice2_T636.py0000644000175100001770000000154000000000000020017 0ustar00runnerdocker00000000000000# mode: run
# ticket 636
# tag: slicing, getitem

class Sliceable(object):
    """
    >>> sl = Sliceable()

    >>> sl[1:2]
    (1, 2, None)
    >>> py_slice2(sl, 1, 2)
    (1, 2, None)

    >>> sl[1:None]
    (1, None, None)
    >>> py_slice2(sl, 1, None)
    (1, None, None)

    >>> sl[None:2]
    (None, 2, None)
    >>> py_slice2(sl, None, 2)
    (None, 2, None)

    >>> sl[None:None]
    (None, None, None)
    >>> py_slice2(sl, None, None)
    (None, None, None)
    """
    def __getitem__(self, sl):
        return (sl.start, sl.stop, sl.step)

def py_slice2(obj,a,b):
    """
    >>> [1,2,3][1:2]
    [2]
    >>> py_slice2([1,2,3], 1, 2)
    [2]

    >>> [1,2,3][None:2]
    [1, 2]
    >>> py_slice2([1,2,3], None, 2)
    [1, 2]

    >>> [1,2,3][None:None]
    [1, 2, 3]
    >>> py_slice2([1,2,3], None, None)
    [1, 2, 3]
    """
    return obj[a:b]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/slice2b.pyx0000644000175100001770000000040600000000000017627 0ustar00runnerdocker00000000000000cdef extern from *:
    ctypedef class __builtin__.list [ object PyListObject ]:
        pass

def slice_of_typed_value():

    """
    >>> slice_of_typed_value()
    [1, 2, 3]
    """
    cdef object a = []
    cdef list L = [1, 2, 3]
    a[:] = L
    return a
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/slice3.pyx0000644000175100001770000000210000000000000017457 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> class Test(object):
    ...     def __setitem__(self, key, value):
    ...         print((key, value))
    ...     def __getitem__(self, key):
    ...         print(key)
    ...         return self

    >>> ellipsis(Test())
    Ellipsis

    >>> full(Test())
    slice(None, None, None)

    >>> select(0, Test(), 10, 20, 30)
    slice(10, None, None)
    slice(None, 20, None)
    slice(None, None, 30)
    slice(10, 20, None)
    slice(10, None, 30)
    slice(None, 20, 30)
    slice(10, 20, 30)
    slice(1, 2, 3)

    >>> set(Test(), -11)
    (slice(1, 2, 3), -11)
"""

def ellipsis(o):
    obj1 = o[...]

def full(o):
    obj1 = o[::]

def set(o, v):
    cdef int int3, int4, int5
    int3, int4, int5 = 1,2,3
    o[int3:int4:int5] = v

def select(obj1, obj2, obj3, obj4, obj5):
    cdef int int3, int4, int5
    int3, int4, int5 = 1,2,3

    obj1 = obj2[obj3::]
    obj1 = obj2[:obj4:]
    obj1 = obj2[::obj5]
    obj1 = obj2[obj3:obj4:]
    obj1 = obj2[obj3::obj5]
    obj1 = obj2[:obj4:obj5]
    obj1 = obj2[obj3:obj4:obj5]
    obj1 = obj2[int3:int4:int5]

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/slice_charptr.pyx0000644000175100001770000000072200000000000021127 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> do_slice(b'abcdef', 2, 3)
    (b'c', b'cdef', b'ab', b'abcdef', b'cdef', b'ab', b'abcdef')
    >>> do_slice(b'abcdef', 0, 5)
    (b'abcde', b'abcdef', b'', b'abcdef', b'abcdef', b'', b'abcdef')
"""

import sys

if sys.version_info[0] < 3:
    __doc__ = __doc__.replace(u"(b'", u"('").replace(u" b'", u" '")

def do_slice(s, int i, int j):
    cdef char* ss = s
    return ss[i:j], ss[i:], ss[:i], ss[:], ss[i:None], ss[None:i], ss[None:None]

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/slice_ptr.pyx0000644000175100001770000000442300000000000020273 0ustar00runnerdocker00000000000000from libc.stdlib cimport malloc, free
from cpython.object cimport Py_EQ, Py_NE

def double_ptr_slice(x, L, int a, int b):
    """
    >>> L = list(range(10))
    >>> double_ptr_slice(5, L, 0, 10)
    >>> double_ptr_slice(6, L, 0, 10)
    >>> double_ptr_slice(None, L, 0, 10)
    >>> double_ptr_slice(0, L, 3, 7)
    >>> double_ptr_slice(5, L, 3, 7)
    >>> double_ptr_slice(9, L, 3, 7)

    >>> double_ptr_slice(EqualsEvens(), L, 0, 10)
    >>> double_ptr_slice(EqualsEvens(), L, 1, 10)
    """
    cdef double *L_c = NULL
    try:
        L_c = malloc( len(L) * sizeof(double))
        for i, a in enumerate(L):
            L_c[i] = L[i]
        assert (x in L_c[:b]) == (x in L[:b])
        assert (x not in L_c[:b]) == (x not in L[:b])
        assert (x in L_c[a:b]) == (x in L[a:b])
        assert (x not in L_c[a:b]) == (x not in L[a:b])
        assert (x in L_c[a:b:2]) == (x in L[a:b:2])
        assert (x not in L_c[a:b:2]) == (x not in L[a:b:2])
    finally:
        free(L_c)

def void_ptr_slice(py_x, L, int a, int b):
    """
    >>> L = list(range(10))
    >>> void_ptr_slice(5, L, 0, 10)
    >>> void_ptr_slice(6, L, 0, 10)
    >>> void_ptr_slice(None, L, 0, 10)
    >>> void_ptr_slice(0, L, 3, 7)
    >>> void_ptr_slice(5, L, 3, 7)
    >>> void_ptr_slice(9, L, 3, 7)
    """
    # I'm using the fact that small Python ints are cached.
    cdef void **L_c = NULL
    cdef void *x = py_x
    try:
        L_c = malloc( len(L) * sizeof(void*))
        for i, a in enumerate(L):
            L_c[i] = L[i]
        assert (x in L_c[:b]) == (py_x in L[:b])
        assert (x not in L_c[:b]) == (py_x not in L[:b])
        assert (x in L_c[a:b]) == (py_x in L[a:b])
        assert (x not in L_c[a:b]) == (py_x not in L[a:b])
        assert (x in L_c[a:b:2]) == (py_x in L[a:b:2])
        assert (x not in L_c[a:b:2]) == (py_x not in L[a:b:2])
    finally:
        free(L_c)

cdef class EqualsEvens:
    """
    >>> e = EqualsEvens()
    >>> e == 2
    True
    >>> e == 5
    False
    >>> [e == k for k in range(4)]
    [True, False, True, False]
    """
    def __richcmp__(self, other, int op):
        if op == Py_EQ:
            return other % 2 == 0
        elif op == Py_NE:
            return other % 2 == 1
        else:
            return False
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/special_method_docstrings.pyx0000644000175100001770000000210000000000000023514 0ustar00runnerdocker00000000000000cdef class A:
    """
    >>> A.__init__.__doc__
    'A.__init__ docstring'
    >>> A.__len__.__doc__
    'A.__len__ docstring'
    >>> A.__add__.__doc__
    'A.__add__ docstring'
    >>> A.__getattr__.__doc__
    'A.__getattr__ docstring'
    """
    def __init__(self):
        "A.__init__ docstring"
    def __len__(self):
        "A.__len__ docstring"
    def __add__(self, other):
        "A.__add__ docstring"
    def __getattr__(self, name):
        "A.__getattr__ docstring"

cdef class B(A):
    """
    >>> B.__init__.__doc__
    'A.__init__ docstring'
    >>> B.__len__.__doc__
    'B.__len__ docstring'
    >>> B.__add__.__doc__
    'A.__add__ docstring'
    >>> B.__getattr__.__doc__
    'A.__getattr__ docstring'
    """
    def __len__(self):
        "B.__len__ docstring"

class C(A):
    """
    >>> C.__init__.__doc__
    'A.__init__ docstring'
    >>> C.__len__.__doc__
    'C.__len__ docstring'
    >>> C.__add__.__doc__
    'A.__add__ docstring'
    >>> C.__getattr__.__doc__
    'A.__getattr__ docstring'
    """
    def __len__(self):
        "C.__len__ docstring"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/special_methods_T561.pyx0000644000175100001770000007341200000000000022175 0ustar00runnerdocker00000000000000# mode: run
# ticket: t561
# ticket: t3

# The patch in #561 changes code generation for most special methods
# to remove the Cython-generated wrapper and let PyType_Ready()
# generate its own wrapper.  (This wrapper would be used, for instance,
# when using the special method as a bound method.)

# To test this, we go through and verify that each affected special
# method works as a bound method.

# Special methods that are treated the same under Python 2 and 3 are
# tested here; see also special_methods_T561_py2.pyx and
# special_methods_T561_py3.pyx for tests of the differences between
# Python 2 and 3.

# Regarding ticket 3, we should additionally test that unbound method
# calls to these special methods (e.g. ExtType.__init__()) do not use
# a runtime lookup indirection.
#
# Additional tests added for 2 and 3 argument pow and ipow

import sys

from cpython.number cimport PyNumber_InPlacePower

__doc__ = u"""
    >>> # If you define either setitem or delitem, you get wrapper objects
    >>> # for both methods.  (This behavior is unchanged by #561.)
    >>> si_setitem = SetItem().__setitem__
    >>> si_setitem('foo', 'bar')
    SetItem setitem 'foo' 'bar'
    >>> si_delitem = SetItem().__delitem__
    >>> si_delitem('foo')
    Traceback (most recent call last):
    ...
    NotImplementedError: Subscript deletion not supported by special_methods_T561.SetItem
    >>> di_setitem = DelItem().__setitem__
    >>> di_setitem('foo', 'bar')
    Traceback (most recent call last):
    ...
    NotImplementedError: Subscript assignment not supported by special_methods_T561.DelItem
    >>> di_delitem = DelItem().__delitem__
    >>> di_delitem('foo')
    DelItem delitem 'foo'
    >>> sdi_setitem = SetDelItem().__setitem__
    >>> sdi_setitem('foo', 'bar')
    SetDelItem setitem 'foo' 'bar'
    >>> sdi_delitem = SetDelItem().__delitem__
    >>> sdi_delitem('foo')
    SetDelItem delitem 'foo'
    >>> g01 = object.__getattribute__(GetAttr(), '__getattribute__')
    >>> g01('attr')
    GetAttr getattr 'attr'
    >>> try: object.__getattribute__(GetAttribute(), '__getattr__')
    ... except AttributeError as err:
    ...      assert '__getattr__' in str(err), err
    ... else: print("NOT RAISED!")
    >>> g11 = object.__getattribute__(GetAttribute(), '__getattribute__')
    >>> g11('attr')
    GetAttribute getattribute 'attr'
    >>> # If you define either set or delete, you get wrapper objects
    >>> # for both methods.  (This behavior is unchanged by #561.)
    >>> s_set = Set().__set__
    >>> s_set('instance', 'val')
    Set set 'instance' 'val'
    >>> s_delete = Set().__delete__
    >>> s_delete('instance')
    Traceback (most recent call last):
    ...
    NotImplementedError: __delete__
    >>> d_set = Delete().__set__
    >>> d_set('instance', 'val')
    Traceback (most recent call last):
    ...
    NotImplementedError: __set__
    >>> d_delete = Delete().__delete__
    >>> d_delete('instance')
    Delete delete 'instance'
    >>> sd_set = SetDelete().__set__
    >>> sd_set('instance', 'val')
    SetDelete set 'instance' 'val'
    >>> sd_delete = SetDelete().__delete__
    >>> sd_delete('instance')
    SetDelete delete 'instance'
    >>> # If you define __long__, you get a wrapper object for __int__.
    >>> # (This behavior is unchanged by #561.)
    >>> Li = Long().__int__
    >>> Li()
    Long __long__
"""
if sys.version_info >= (2,5):
    __doc__ += u"""\
    >>> vs0 = VerySpecial(0)
    VS __init__ 0
    >>> vs0_index = vs0.__index__
    >>> vs0_index()
    VS __index__ 0
"""

cdef extern from *:
    # type specs require a bug fix in Py3.8+ for some of these tests.
    const int CYTHON_USE_TYPE_SPECS

if not CYTHON_USE_TYPE_SPECS or sys.version_info >= (3,8):
    __doc__ += u"""
    >>> # If you define either setattr or delattr, you get wrapper objects
    >>> # for both methods.  (This behavior is unchanged by #561.)
    >>> sa_setattr = SetAttr().__setattr__
    >>> sa_setattr('foo', 'bar')
    SetAttr setattr 'foo' 'bar'
    >>> sa_delattr = SetAttr().__delattr__
    >>> sa_delattr('foo')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    AttributeError: 'special_methods_T561.SetAttr' object has no attribute 'foo'...
    >>> da_setattr = DelAttr().__setattr__
    >>> da_setattr('foo', 'bar')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    AttributeError: 'special_methods_T561.DelAttr' object has no attribute 'foo'...
    >>> da_delattr = DelAttr().__delattr__
    >>> da_delattr('foo')
    DelAttr delattr 'foo'
    >>> sda_setattr = SetDelAttr().__setattr__
    >>> sda_setattr('foo', 'bar')
    SetDelAttr setattr 'foo' 'bar'
    >>> sda_delattr = SetDelAttr().__delattr__
    >>> sda_delattr('foo')
    SetDelAttr delattr 'foo'
"""


cdef class VerySpecial:
    """
    >>> vs0 = VerySpecial(0)
    VS __init__ 0
    >>> vs1 = VerySpecial(1)
    VS __init__ 1

    >>> vs0_add = vs0.__add__
    >>> vs0_add(vs1)
    VS __add__ 0 1
    >>> vs0_sub = vs0.__sub__
    >>> vs0_sub(vs1)
    VS __sub__ 0 1
    >>> vs0_mul = vs0.__mul__
    >>> vs0_mul(vs1)
    VS __mul__ 0 1
    >>> vs0_mod = vs0.__mod__
    >>> vs0_mod(vs1)
    VS __mod__ 0 1
    >>> vs0_divmod = vs0.__divmod__
    >>> vs0_divmod(vs1)
    VS __divmod__ 0 1
    >>> vs0_pow = vs0.__pow__
    >>> vs0_pow(vs1)
    VS __pow__ pow(0, 1, None)
    >>> vs0_pow(vs1, 13)
    VS __pow__ pow(0, 1, 13)
    >>> vs0_neg = vs0.__neg__
    >>> vs0_neg()
    VS __neg__ 0
    >>> vs0_pos = vs0.__pos__
    >>> vs0_pos()
    VS __pos__ 0
    >>> vs0_abs = vs0.__abs__
    >>> vs0_abs()
    VS __abs__ 0
    >>> vs0_invert = vs0.__invert__
    >>> vs0_invert()
    VS __invert__ 0
    >>> vs0_lshift = vs0.__lshift__
    >>> vs0_lshift(vs1)
    VS __lshift__ 0 << 1
    >>> vs0_rshift = vs0.__rshift__
    >>> vs0_rshift(vs1)
    VS __rshift__ 0 >> 1
    >>> vs0_and = vs0.__and__
    >>> vs0_and(vs1)
    VS __and__ 0 & 1
    >>> vs0_xor = vs0.__xor__
    >>> vs0_xor(vs1)
    VS __xor__ 0 ^ 1
    >>> vs0_or = vs0.__or__
    >>> vs0_or(vs1)
    VS __or__ 0 | 1
    >>> vs0_int = vs0.__int__
    >>> vs0_int()
    VS __int__ 0
    >>> vs0_float = vs0.__float__
    >>> vs0_float()
    VS __float__ 0
    >>> vs0_iadd = vs0.__iadd__
    >>> vs0_iadd(vs1)
    VS __iadd__ 0 += 1
    >>> vs0_isub = vs0.__isub__
    >>> vs0_isub(vs1)
    VS __isub__ 0 -= 1
    >>> vs0_imul = vs0.__imul__
    >>> vs0_imul(vs1)
    VS __imul__ 0 *= 1
    >>> vs0_imod = vs0.__imod__
    >>> vs0_imod(vs1)
    VS __imod__ 0 %= 1
    >>> vs0_ipow = vs0.__ipow__
    >>> vs0_ipow(vs1)
    VS __ipow__ 0 1
    >>> vs0_ilshift = vs0.__ilshift__
    >>> vs0_ilshift(vs1)
    VS __ilshift__ 0 <<= 1
    >>> vs0_irshift = vs0.__irshift__
    >>> vs0_irshift(vs1)
    VS __irshift__ 0 >>= 1
    >>> vs0_iand = vs0.__iand__
    >>> vs0_iand(vs1)
    VS __iand__ 0 &= 1
    >>> vs0_ixor = vs0.__ixor__
    >>> vs0_ixor(vs1)
    VS __ixor__ 0 ^= 1
    >>> vs0_ior = vs0.__ior__
    >>> vs0_ior(vs1)
    VS __ior__ 0 |= 1
    >>> vs0_floordiv = vs0.__floordiv__
    >>> vs0_floordiv(vs1)
    VS __floordiv__ 0 / 1
    >>> vs0_truediv = vs0.__truediv__
    >>> vs0_truediv(vs1)
    VS __truediv__ 0 / 1
    >>> vs0_ifloordiv = vs0.__ifloordiv__
    >>> vs0_ifloordiv(vs1)
    VS __ifloordiv__ 0 /= 1
    >>> vs0_itruediv = vs0.__itruediv__
    >>> vs0_itruediv(vs1)
    VS __itruediv__ 0 /= 1

    # If you define an arithmetic method, you get wrapper objects for
    # the reversed version as well.  (This behavior is unchanged by #561.)
    >>> vs0_radd = vs0.__radd__
    >>> vs0_radd(vs1)
    VS __add__ 1 0
    >>> vs0_rsub = vs0.__rsub__
    >>> vs0_rsub(vs1)
    VS __sub__ 1 0
    >>> vs0_rmul = vs0.__rmul__
    >>> vs0_rmul(vs1)
    VS __mul__ 1 0
    >>> vs0_rmod = vs0.__rmod__
    >>> vs0_rmod(vs1)
    VS __mod__ 1 0
    >>> vs0_rdivmod = vs0.__rdivmod__
    >>> vs0_rdivmod(vs1)
    VS __divmod__ 1 0
    >>> vs0_rpow = vs0.__rpow__
    >>> vs0_rpow(vs1)
    VS __pow__ pow(1, 0, None)
    >>> vs0_rlshift = vs0.__rlshift__
    >>> vs0_rlshift(vs1)
    VS __lshift__ 1 << 0
    >>> vs0_rrshift = vs0.__rrshift__
    >>> vs0_rrshift(vs1)
    VS __rshift__ 1 >> 0
    >>> vs0_rand = vs0.__rand__
    >>> vs0_rand(vs1)
    VS __and__ 1 & 0
    >>> vs0_rxor = vs0.__rxor__
    >>> vs0_rxor(vs1)
    VS __xor__ 1 ^ 0
    >>> vs0_ror = vs0.__ror__
    >>> vs0_ror(vs1)
    VS __or__ 1 | 0
    >>> vs0_rfloordiv = vs0.__rfloordiv__
    >>> vs0_rfloordiv(vs1)
    VS __floordiv__ 1 / 0
    >>> vs0_rtruediv = vs0.__rtruediv__
    >>> vs0_rtruediv(vs1)
    VS __truediv__ 1 / 0
    >>> vs0_getitem = vs0.__getitem__
    >>> vs0_getitem('foo')
    VS __getitem__ 0['foo']
    >>> vs0_contains = vs0.__contains__
    >>> vs0_contains(vs1)
    VS __contains__ 0 1
    False
    >>> vs0_len = vs0.__len__
    >>> vs0_len()
    VS __len__ 0
    0
    >>> vs0_repr = vs0.__repr__
    >>> vs0_repr()
    VS __repr__ 0
    >>> vs0_hash = vs0.__hash__
    >>> vs0_hash()
    VS __hash__ 0
    1000
    >>> vs0_call = vs0.__call__
    >>> vs0_call(vs1)
    VS __call__ 0(1)
    >>> vs0_str = vs0.__str__
    >>> vs0_str()
    VS __str__ 0

    # If you define __richcmp__, you get all of __lt__, __le__,
    # __eq__, __ne__, __gt__, __ge__ (this behavior is unchanged by #561).
    # (you don't get a __richcmp__ method, because it doesn't have a
    # Python signature)
    >>> vs0_lt = vs0.__lt__
    >>> vs0_lt(vs1)
    VS richcmp 0 1 (kind=0)
    >>> vs0_le = vs0.__le__
    >>> vs0_le(vs1)
    VS richcmp 0 1 (kind=1)
    >>> vs0_eq = vs0.__eq__
    >>> vs0_eq(vs1)
    VS richcmp 0 1 (kind=2)
    >>> vs0_ne = vs0.__ne__
    >>> vs0_ne(vs1)
    VS richcmp 0 1 (kind=3)
    >>> vs0_gt = vs0.__gt__
    >>> vs0_gt(vs1)
    VS richcmp 0 1 (kind=4)
    >>> vs0_ge = vs0.__ge__
    >>> vs0_ge(vs1)
    VS richcmp 0 1 (kind=5)
    >>> vs0_iter = vs0.__iter__
    >>> vs0_iter()
    VS __iter__ 0
    >>> vs0_next = vs0.__next__
    >>> vs0_next()
    VS next/__next__ 0

    >>> vs0_get = vs0.__get__
    >>> vs0_get('instance', 'owner')
    VS __get__ 0 'instance' 'owner'
    >>> vs0_init = vs0.__init__
    >>> vs0_init(0)
    VS __init__ 0
    """
    cdef readonly int value

    def __init__(self, v):
        self.value = v
        print "VS __init__ %d" % self.value

    def __add__(self, other):
        print "VS __add__ %d %d" % (self.value, other.value)

    def __sub__(self, other):
        print "VS __sub__ %d %d" % (self.value, other.value)

    def __mul__(self, other):
        print "VS __mul__ %d %d" % (self.value, other.value)

    def __div__(self, other):
        print "VS __div__ %d %d" % (self.value, other.value)

    def __mod__(self, other):
        print "VS __mod__ %d %d" % (self.value, other.value)

    def __divmod__(self, other):
        print "VS __divmod__ %d %d" % (self.value, other.value)

    def __pow__(self, other, mod):
        print "VS __pow__ pow(%d, %d, %r)" % (self.value, other.value, mod)

    def __lshift__(self, other):
        print "VS __lshift__ %d << %d" % (self.value, other.value)

    def __rshift__(self, other):
        print "VS __rshift__ %d >> %d" % (self.value, other.value)

    def __and__(self, other):
        print "VS __and__ %d & %d" % (self.value, other.value)

    def __xor__(self, other):
        print "VS __xor__ %d ^ %d" % (self.value, other.value)

    def __or__(self, other):
        print "VS __or__ %d | %d" % (self.value, other.value)

    def __floordiv__(self, other):
        print "VS __floordiv__ %d / %d" % (self.value, other.value)

    def __truediv__(self, other):
        print "VS __truediv__ %d / %d" % (self.value, other.value)

    def __neg__(self):
        print "VS __neg__ %d" % self.value

    def __pos__(self):
        print "VS __pos__ %d" % self.value

    def __abs__(self):
        print "VS __abs__ %d" % self.value

    def __nonzero__(self):
        print "VS __nonzero__ %d" % self.value

    def __invert__(self):
        print "VS __invert__ %d" % self.value

    def __int__(self):
        print "VS __int__ %d" % self.value

    def __long__(self):
        print "VS __long__ %d" % self.value

    def __float__(self):
        print "VS __float__ %d" % self.value

    def __oct__(self):
        print "VS __oct__ %d" % self.value

    def __hex__(self):
        print "VS __hex__ %d" % self.value

    def __iadd__(self, other):
        print "VS __iadd__ %d += %d" % (self.value, other.value)

    def __isub__(self, other):
        print "VS __isub__ %d -= %d" % (self.value, other.value)

    def __imul__(self, other):
        print "VS __imul__ %d *= %d" % (self.value, other.value)

    def __idiv__(self, other):
        print "VS __idiv__ %d /= %d" % (self.value, other.value)

    def __imod__(self, other):
        print "VS __imod__ %d %%= %d" % (self.value, other.value)

    def __ipow__(self, other):
        # We must declare mod as an argument, but we must not touch it
        # or we'll get a segfault.  See #562
        print "VS __ipow__ %d %d" % (self.value, other.value)

    def __ilshift__(self, other):
        print "VS __ilshift__ %d <<= %d" % (self.value, other.value)

    def __irshift__(self, other):
        print "VS __irshift__ %d >>= %d" % (self.value, other.value)

    def __iand__(self, other):
        print "VS __iand__ %d &= %d" % (self.value, other.value)

    def __ixor__(self, other):
        print "VS __ixor__ %d ^= %d" % (self.value, other.value)

    def __ior__(self, other):
        print "VS __ior__ %d |= %d" % (self.value, other.value)

    def __ifloordiv__(self, other):
        print "VS __ifloordiv__ %d /= %d" % (self.value, other.value)

    def __itruediv__(self, other):
        print "VS __itruediv__ %d /= %d" % (self.value, other.value)

    def __index__(self):
        print "VS __index__ %d" % self.value

    def __getitem__(self, index):
        print "VS __getitem__ %d[%r]" % (self.value, index)

    def __contains__(self, other):
        print "VS __contains__ %d %d" % (self.value, other.value)

    def __len__(self):
        print "VS __len__ %d" % (self.value)

    def __cmp__(self, other):
        print "VS __cmp__ %d %d" % (self.value, other.value)

    def __repr__(self):
        print "VS __repr__ %d" % self.value

    def __hash__(self):
        print "VS __hash__ %d" % self.value
        return self.value + 1000

    def __call__(self, other):
        print "VS __call__ %d(%d)" % (self.value, other.value)

    def __str__(self):
        print "VS __str__ %d" % self.value

    def __richcmp__(self, other, kind):
        print "VS richcmp %d %d (kind=%r)" % (self.value, other.value, kind)

    def __iter__(self):
        print "VS __iter__ %d" % self.value

    def __next__(self):
        print "VS next/__next__ %d" % self.value

    def __get__(self, inst, own):
        print "VS __get__ %d %r %r" % (self.value, inst, own)

cdef class SetItem:
    def __setitem__(self, index, value):
        print "SetItem setitem %r %r" % (index, value)

cdef class DelItem:
    def __delitem__(self, index):
        print "DelItem delitem %r" % index

cdef class SetDelItem:
    def __setitem__(self, index, value):
        print "SetDelItem setitem %r %r" % (index, value)

    def __delitem__(self, index):
        print "SetDelItem delitem %r" % index

cdef class GetAttr:
    def __getattr__(self, attr):
        print "GetAttr getattr %r" % attr

cdef class GetAttribute:
    def __getattribute__(self, attr):
        print "GetAttribute getattribute %r" % attr

cdef class SetAttr:
    def __setattr__(self, attr, val):
        print "SetAttr setattr %r %r" % (attr, val)

cdef class DelAttr:
    def __delattr__(self, attr):
        print "DelAttr delattr %r" % attr

cdef class SetDelAttr:
    def __setattr__(self, attr, val):
        print "SetDelAttr setattr %r %r" % (attr, val)

    def __delattr__(self, attr):
        print "SetDelAttr delattr %r" % attr

cdef class Set:
    def __set__(self, inst, val):
        print "Set set %r %r" % (inst, val)

cdef class Delete:
    def __delete__(self, inst):
        print "Delete delete %r" % inst

cdef class SetDelete:
    def __set__(self, inst, val):
        print "SetDelete set %r %r" % (inst, val)

    def __delete__(self, inst):
        print "SetDelete delete %r" % inst

cdef class Long:
    def __long__(self):
        print "Long __long__"

cdef class GetAttrGetItemRedirect:
    """
    >>> o = GetAttrGetItemRedirect()

    >>> assert o.item == o['item']
    >>> source, item_value = o.item
    >>> assert source == 'item', source

    >>> assert o['attr'] == o.attr
    >>> source, attr_value = o['attr']
    >>> assert source == 'attr', source

    >>> assert item_value is attr_value, repr((item_value, attr_value))
    """
    cdef object obj
    def __cinit__(self):
        self.obj = object()

    def __getattr__(self, name):
        if name == 'item':
            return self[name]
        return ('attr', self.obj)

    def __getitem__(self, key):
        if key == 'attr':
            return getattr(self, key)
        return ('item', self.obj)


# test unbound method usage in subtypes

cdef class VerySpecialSubType(VerySpecial):
    """
    >>> vs0 = VerySpecialSubType(0)
    VS __init__ 0
    >>> vs1 = VerySpecialSubType(1)
    VS __init__ 1

    >>> vs0_add = vs0.__add__
    >>> vs0_add(vs1)
    VS __add__ 0 1
    >>> vs0_sub = vs0.__sub__
    >>> vs0_sub(vs1)
    VS __sub__ 0 1
    >>> vs0_mul = vs0.__mul__
    >>> vs0_mul(vs1)
    VS __mul__ 0 1
    >>> vs0_mod = vs0.__mod__
    >>> vs0_mod(vs1)
    VS __mod__ 0 1
    >>> vs0_divmod = vs0.__divmod__
    >>> vs0_divmod(vs1)
    VS __divmod__ 0 1
    >>> vs0_pow = vs0.__pow__
    >>> vs0_pow(vs1)
    VS __pow__ pow(0, 1, None)
    >>> vs0_pow(vs1, 13)
    VS __pow__ pow(0, 1, 13)
    >>> vs0_neg = vs0.__neg__
    >>> vs0_neg()
    VS __neg__ 0
    >>> vs0_pos = vs0.__pos__
    >>> vs0_pos()
    VS __pos__ 0
    >>> vs0_abs = vs0.__abs__
    >>> vs0_abs()
    VS __abs__ 0
    >>> vs0_invert = vs0.__invert__
    >>> vs0_invert()
    VS __invert__ 0
    >>> vs0_lshift = vs0.__lshift__
    >>> vs0_lshift(vs1)
    VS __lshift__ 0 << 1
    >>> vs0_rshift = vs0.__rshift__
    >>> vs0_rshift(vs1)
    VS __rshift__ 0 >> 1
    >>> vs0_and = vs0.__and__
    >>> vs0_and(vs1)
    VS __and__ 0 & 1
    >>> vs0_xor = vs0.__xor__
    >>> vs0_xor(vs1)
    VS __xor__ 0 ^ 1
    >>> vs0_or = vs0.__or__
    >>> vs0_or(vs1)
    VS __or__ 0 | 1
    >>> vs0_int = vs0.__int__
    >>> vs0_int()
    VS __int__ 0
    >>> vs0_float = vs0.__float__
    >>> vs0_float()
    VS __float__ 0
    >>> vs0_iadd = vs0.__iadd__
    >>> vs0_iadd(vs1)
    VS __iadd__ 0 += 1
    >>> vs0_isub = vs0.__isub__
    >>> vs0_isub(vs1)
    VS __isub__ 0 -= 1
    >>> vs0_imul = vs0.__imul__
    >>> vs0_imul(vs1)
    VS __imul__ 0 *= 1
    >>> vs0_imod = vs0.__imod__
    >>> vs0_imod(vs1)
    VS __imod__ 0 %= 1
    >>> vs0_ipow = vs0.__ipow__
    >>> vs0_ipow(vs1)
    VS __ipow__ 0 1
    >>> vs0_ilshift = vs0.__ilshift__
    >>> vs0_ilshift(vs1)
    VS __ilshift__ 0 <<= 1
    >>> vs0_irshift = vs0.__irshift__
    >>> vs0_irshift(vs1)
    VS __irshift__ 0 >>= 1
    >>> vs0_iand = vs0.__iand__
    >>> vs0_iand(vs1)
    VS __iand__ 0 &= 1
    >>> vs0_ixor = vs0.__ixor__
    >>> vs0_ixor(vs1)
    VS __ixor__ 0 ^= 1
    >>> vs0_ior = vs0.__ior__
    >>> vs0_ior(vs1)
    VS __ior__ 0 |= 1
    >>> vs0_floordiv = vs0.__floordiv__
    >>> vs0_floordiv(vs1)
    VS __floordiv__ 0 / 1
    >>> vs0_truediv = vs0.__truediv__
    >>> vs0_truediv(vs1)
    VS __truediv__ 0 / 1
    >>> vs0_ifloordiv = vs0.__ifloordiv__
    >>> vs0_ifloordiv(vs1)
    VS __ifloordiv__ 0 /= 1
    >>> vs0_itruediv = vs0.__itruediv__
    >>> vs0_itruediv(vs1)
    VS __itruediv__ 0 /= 1

    # If you define an arithmetic method, you get wrapper objects for
    # the reversed version as well.  (This behavior is unchanged by #561.)
    >>> vs0_radd = vs0.__radd__
    >>> vs0_radd(vs1)
    VS __add__ 1 0
    >>> vs0_rsub = vs0.__rsub__
    >>> vs0_rsub(vs1)
    VS __sub__ 1 0
    >>> vs0_rmul = vs0.__rmul__
    >>> vs0_rmul(vs1)
    VS __mul__ 1 0
    >>> vs0_rmod = vs0.__rmod__
    >>> vs0_rmod(vs1)
    VS __mod__ 1 0
    >>> vs0_rdivmod = vs0.__rdivmod__
    >>> vs0_rdivmod(vs1)
    VS __divmod__ 1 0
    >>> vs0_rpow = vs0.__rpow__
    >>> vs0_rpow(vs1)
    VS __pow__ pow(1, 0, None)
    >>> vs0_rlshift = vs0.__rlshift__
    >>> vs0_rlshift(vs1)
    VS __lshift__ 1 << 0
    >>> vs0_rrshift = vs0.__rrshift__
    >>> vs0_rrshift(vs1)
    VS __rshift__ 1 >> 0
    >>> vs0_rand = vs0.__rand__
    >>> vs0_rand(vs1)
    VS __and__ 1 & 0
    >>> vs0_rxor = vs0.__rxor__
    >>> vs0_rxor(vs1)
    VS __xor__ 1 ^ 0
    >>> vs0_ror = vs0.__ror__
    >>> vs0_ror(vs1)
    VS __or__ 1 | 0
    >>> vs0_rfloordiv = vs0.__rfloordiv__
    >>> vs0_rfloordiv(vs1)
    VS __floordiv__ 1 / 0
    >>> vs0_rtruediv = vs0.__rtruediv__
    >>> vs0_rtruediv(vs1)
    VS __truediv__ 1 / 0
    >>> vs0_getitem = vs0.__getitem__
    >>> vs0_getitem('foo')
    VS __getitem__ 0['foo']
    >>> vs0_contains = vs0.__contains__
    >>> vs0_contains(vs1)
    VS __contains__ 0 1
    False
    >>> vs0_len = vs0.__len__
    >>> vs0_len()
    VS __len__ 0
    0
    >>> vs0_repr = vs0.__repr__
    >>> vs0_repr()
    VS __repr__ 0
    >>> vs0_hash = vs0.__hash__
    >>> vs0_hash()
    VS __hash__ 0
    1000
    >>> vs0_call = vs0.__call__
    >>> vs0_call(vs1)
    VS __call__ 0(1)
    >>> vs0_str = vs0.__str__
    >>> vs0_str()
    VS __str__ 0
    >>> vs0_lt = vs0.__lt__
    >>> vs0_lt(vs1)
    VS richcmp 0 1 (kind=0)
    >>> vs0_le = vs0.__le__
    >>> vs0_le(vs1)
    VS richcmp 0 1 (kind=1)
    >>> vs0_eq = vs0.__eq__
    >>> vs0_eq(vs1)
    VS richcmp 0 1 (kind=2)
    >>> vs0_ne = vs0.__ne__
    >>> vs0_ne(vs1)
    VS richcmp 0 1 (kind=3)
    >>> vs0_gt = vs0.__gt__
    >>> vs0_gt(vs1)
    VS richcmp 0 1 (kind=4)
    >>> vs0_ge = vs0.__ge__
    >>> vs0_ge(vs1)
    VS richcmp 0 1 (kind=5)
    >>> vs0_iter = vs0.__iter__
    >>> vs0_iter()
    VS __iter__ 0
    >>> vs0_next = vs0.__next__
    >>> vs0_next()
    VS next/__next__ 0
    >>> vs0_get = vs0.__get__
    >>> vs0_get('instance', 'owner')
    VS __get__ 0 'instance' 'owner'
    >>> vs0_init = vs0.__init__
    >>> vs0_init(0)
    VS __init__ 0
    """
    def __init__(self, v):
        VerySpecial.__init__(self, v)

    def __add__(self, other):
        return VerySpecial.__add__(self, other)

    def __sub__(self, other):
        return VerySpecial.__sub__(self, other)

    def __mul__(self, other):
        return VerySpecial.__mul__(self, other)

    def __div__(self, other):
        return VerySpecial.__div__(self, other)

    def __mod__(self, other):
        return VerySpecial.__mod__(self, other)

    def __divmod__(self, other):
        return VerySpecial.__divmod__(self, other)

    def __pow__(self, other, mod):
        return VerySpecial.__pow__(self, other, mod)

    def __lshift__(self, other):
        return VerySpecial.__lshift__(self, other)

    def __rshift__(self, other):
        return VerySpecial.__rshift__(self, other)

    def __and__(self, other):
        return VerySpecial.__and__(self, other)

    def __xor__(self, other):
        return VerySpecial.__xor__(self, other)

    def __or__(self, other):
        return VerySpecial.__or__(self, other)

    def __floordiv__(self, other):
        return VerySpecial.__floordiv__(self, other)

    def __truediv__(self, other):
        return VerySpecial.__truediv__(self, other)

    def __neg__(self):
        return VerySpecial.__neg__(self)

    def __pos__(self):
        return VerySpecial.__pos__(self)

    def __abs__(self):
        return VerySpecial.__abs__(self)

    def __nonzero__(self):
        return VerySpecial.__nonzero__(self)

    def __invert__(self):
        return VerySpecial.__invert__(self)

    def __int__(self):
        return VerySpecial.__int__(self)

    def __long__(self):
        return VerySpecial.__long__(self)

    def __float__(self):
        return VerySpecial.__float__(self)

    def __oct__(self):
        return VerySpecial.__oct__(self)

    def __hex__(self):
        return VerySpecial.__hex__(self)

    def __iadd__(self, other):
        return VerySpecial.__iadd__(self, other)

    def __isub__(self, other):
        return VerySpecial.__isub__(self, other)

    def __imul__(self, other):
        return VerySpecial.__imul__(self, other)

    def __idiv__(self, other):
        return VerySpecial.__idiv__(self, other)

    def __imod__(self, other):
        return VerySpecial.__imod__(self, other)

    def __ipow__(self, other):
        return VerySpecial.__ipow__(self, other)

    def __ilshift__(self, other):
        return VerySpecial.__ilshift__(self, other)

    def __irshift__(self, other):
        return VerySpecial.__irshift__(self, other)

    def __iand__(self, other):
        return VerySpecial.__iand__(self, other)

    def __ixor__(self, other):
        return VerySpecial.__ixor__(self, other)

    def __ior__(self, other):
        return VerySpecial.__ior__(self, other)

    def __ifloordiv__(self, other):
        return VerySpecial.__ifloordiv__(self, other)

    def __itruediv__(self, other):
        return VerySpecial.__itruediv__(self, other)

    def __index__(self):
        return VerySpecial.__index__(self)

    def __getitem__(self, index):
        return VerySpecial.__getitem__(self, index)

    def __contains__(self, other):
        return VerySpecial.__contains__(self, other)

    def __len__(self):
        return VerySpecial.__len__(self)

    def __cmp__(self, other):
        return VerySpecial.__cmp__(self, other)

    def __repr__(self):
        return VerySpecial.__repr__(self)

    def __hash__(self):
        return VerySpecial.__hash__(self)

    def __call__(self, arg):
        return VerySpecial.__call__(self, arg)

    def __str__(self):
        return VerySpecial.__str__(self)

# there is no __richcmp__ at the Python level
#    def __richcmp__(self, other, kind):
#        return VerySpecial.__richcmp__(self, other, kind)

    def __iter__(self):
        return VerySpecial.__iter__(self)

    def __next__(self):
        return VerySpecial.__next__(self)

    def __get__(self, inst, own):
        return VerySpecial.__get__(self, inst, own)


cdef class ReverseMethodsExist:
    """
    reverse methods (such as __radd__) don't work in Cython <3. However, if they
    are defined then it should be possible to look them up explicitly instead of
    looking up autogenerated wrapper (which points to the forward method)

    >>> o = ReverseMethodsExist()
    >>> o + o
    'add'
    >>> o.__add__(o)
    'add'
    >>> o.__radd__(o)
    'radd'
    >>> o.__rsub__(o)
    'rsub'
    """
    def __add__(self, other):
        return "add"
    def __radd__(self, other):
        return "radd"
    def __rsub__(self, other):
        return "rsub"


cdef class ArgumentTypeConversions:
    """
    The user can set the signature of special method arguments so that
    it doesn't match the C signature. This just tests that a few
    variations work

    >>> obj = ArgumentTypeConversions()
    >>> obj[1]
    1
    >>> obj["not a number!"]
    Traceback (most recent call last):
    ...
    TypeError: an integer is required
    >>> obj < obj
    In comparison 0
    True
    >>> obj == obj
    In comparison 2
    False

    Here I'm not sure how reproducible the flags are between Python versions.
    Therefore I'm just checking that they end with ".0"
    >>> memoryview(obj)  # doctest:+ELLIPSIS
    Traceback (most recent call last):
    ...
    RuntimeError: From __getbuffer__ with flags ....0
    """
    # force conversion of object to int
    def __getitem__(self, int x):
        return x

    # force conversion of comparison (int) to object
    def __richcmp__(self, other, object comparison):
        print "In comparison", comparison
        return not bool(comparison)

    # force conversion of flags (int) to double
    def __getbuffer__(self, Py_buffer *buffer, double flags):
        raise RuntimeError("From __getbuffer__ with flags {}".format(flags))


cdef class TwoArgPow:
    """
    >>> print(TwoArgPow('a')**2)
    a**2
    >>> print(pow(TwoArgPow('a'), 3))
    a**3
    >>> pow(TwoArgPow('a'), 'x', 'y')
    Traceback (most recent call last):
        ...
    TypeError: special_methods_T561.TwoArgPow.__pow__() takes 3 arguments but 2 were given
    """
    cdef str name

    def __init__(self, name):
        self.name = name

    def __pow__(self, other):
        return f"{self.name}**{other}"


cdef class TwoArgRPow:
    """
    >>> print(2**TwoArgRPow('a'))
    a**2
    >>> print(pow(3, TwoArgRPow('a')))
    a**3
    >>> pow('x', TwoArgRPow('a'), 'y')
    Traceback (most recent call last):
        ...
    TypeError: special_methods_T561.TwoArgRPow.__rpow__() takes 3 arguments but 2 were given
    """
    cdef str name

    def __init__(self, name):
        self.name = name

    def __rpow__(self, other):
        return f"{self.name}**{other}"


def ipow(a, b, c):
    # As far as DW can tell, calling through this C API call is the
    # only way to actually use ternary __ipow__
    return PyNumber_InPlacePower(a, b, c)


cdef class TwoArgIPow:
    """
    >>> a = TwoArgIPow('a')
    >>> a**=2
    >>> print(a)
    a**2
    """
    cdef str name

    def __init__(self, name):
        self.name = name

    def __ipow__(self, other):
        return f"{self.name}**{other}"

if sys.version_info >= (3, 8):
    # Due to a bug this check can't usefully work in Python <3.8
    __doc__ += """
>>> ipow(TwoArgIPow('a'), 'x', 'y')
Traceback (most recent call last):
    ...
TypeError: special_methods_T561.TwoArgIPow.__ipow__() takes 3 arguments but 2 were given
    """


cdef class TwoOrThreeArgPow:
    """
    >>> print(TwoOrThreeArgPow('a')**2)
    a**2[None]
    >>> print(pow(TwoOrThreeArgPow('a'), 3))
    a**3[None]
    >>> print(pow(TwoOrThreeArgPow('a'), 'x', 'y'))
    a**x[y]
    """
    cdef str name

    def __init__(self, name):
        self.name = name

    def __pow__(self, other, base=None):
        return f"{self.name}**{other}[{base}]"


cdef class TwoOrThreeArgRPow:
    """
    >>> print(2**TwoOrThreeArgRPow('a'))
    a**2[None]
    >>> print(pow(3, TwoOrThreeArgRPow('a')))
    a**3[None]
    >>> print(pow('x', TwoOrThreeArgRPow('a'), 'y'))
    a**x[y]
    """
    cdef str name

    def __init__(self, name):
        self.name = name

    def __rpow__(self, other, base=None):
        return f"{self.name}**{other}[{base}]"

# See special_methods_T561_py38 for some extra tests for ipow
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/special_methods_T561_py2.pyx0000644000175100001770000001010000000000000022750 0ustar00runnerdocker00000000000000# ticket: t561
# tag: py2
# This file tests the behavior of special methods under Python 2
# after #561.  (Only methods whose behavior differs between Python 2 and 3
# are tested here; see special_methods_T561.pyx for the rest of the tests.)

__doc__ = u"""
    >>> vs0 = VerySpecial(0)
    VS __init__ 0
    >>> vs1 = VerySpecial(1)
    VS __init__ 1
    >>> # Python 3 does not use __cmp__.
    >>> vs0_cmp = vs0.__cmp__
    >>> vs0_cmp(vs1)
    VS __cmp__ 0 1
    0
    >>> # Python 3 does not use __div__ or __idiv__.
    >>> vs0_div = vs0.__div__
    >>> vs0_div(vs1)
    VS __div__ 0 1
    >>> vs0_idiv = vs0.__idiv__
    >>> vs0_idiv(vs1)
    VS __idiv__ 0 /= 1
    >>> vs0_rdiv = vs0.__rdiv__
    >>> vs0_rdiv(vs1)
    VS __div__ 1 0
    >>> # Python 3 does not use __oct__ or __hex__.
    >>> vs0_oct = vs0.__oct__
    >>> vs0_oct()
    VS __oct__ 0
    >>> vs0_hex = vs0.__hex__
    >>> vs0_hex()
    VS __hex__ 0
    >>> # Python 3 does not use __nonzero__; if you define a __nonzero__
    >>> # method, Cython for Python 3 would give you a __bool__ method
    >>> # instead.
    >>> vs0_nonzero = vs0.__nonzero__
    >>> vs0_nonzero()
    VS __nonzero__ 0
    False
    >>> # If you define __next__, you get both __next__ and next (this behavior
    >>> # is unchanged by T561, but only happens in Python 2)
    >>> vs0_next = vs0.__next__
    >>> vs0_next()
    VS next/__next__ 0
    >>> vs0_next2 = vs0.next
    >>> vs0_next2()
    VS next/__next__ 0
    >>> # Cython supports getslice only for Python 2.
    >>> vs0_getslice = vs0.__getslice__
    >>> vs0_getslice(13, 42)
    VS __getslice__ 0 13 42
    >>> # Cython supports setslice and delslice only for Python 2.
    >>> # If you define either setslice or delslice, you get wrapper objects
    >>> # for both methods.  (This behavior is unchanged by #561.)
    >>> ss_setslice = SetSlice().__setslice__
    >>> ss_setslice(13, 42, 'foo')
    SetSlice setslice 13 42 'foo'
    >>> ss_delslice = SetSlice().__delslice__
    >>> ss_delslice(13, 42)
    Traceback (most recent call last):
    ...
    NotImplementedError: 2-element slice deletion not supported by special_methods_T561_py2.SetSlice
    >>> ds_setslice = DelSlice().__setslice__
    >>> ds_setslice(13, 42, 'foo')
    Traceback (most recent call last):
    ...
    NotImplementedError: 2-element slice assignment not supported by special_methods_T561_py2.DelSlice
    >>> ds_delslice = DelSlice().__delslice__
    >>> ds_delslice(13, 42)
    DelSlice delslice 13 42
    >>> sds_setslice = SetDelSlice().__setslice__
    >>> sds_setslice(13, 42, 'foo')
    SetDelSlice setslice 13 42 'foo'
    >>> sds_delslice = SetDelSlice().__delslice__
    >>> sds_delslice(13, 42)
    SetDelSlice delslice 13 42
    >>> # Python 3 does not use __long__.
    >>> Ll = Long().__long__
    >>> Ll()
    Long __long__
"""

cdef class VerySpecial:
    cdef readonly int value

    def __init__(self, v):
        self.value = v
        print "VS __init__ %d" % self.value

    def __getslice__(self, a, b):
        print "VS __getslice__ %d %d %d" % (self.value, a, b)

    def __next__(self):
        print "VS next/__next__ %d" % self.value

    def __nonzero__(self):
        print "VS __nonzero__ %d" % self.value

    def __oct__(self):
        print "VS __oct__ %d" % self.value

    def __hex__(self):
        print "VS __hex__ %d" % self.value

    def __cmp__(self, other):
        print "VS __cmp__ %d %d" % (self.value, other.value)

    def __div__(self, other):
        print "VS __div__ %d %d" % (self.value, other.value)

    def __idiv__(self, other):
        print "VS __idiv__ %d /= %d" % (self.value, other.value)

cdef class SetSlice:
    def __setslice__(self, a, b, value):
        print "SetSlice setslice %d %d %r" % (a, b, value)

cdef class DelSlice:
    def __delslice__(self, a, b):
        print "DelSlice delslice %d %d" % (a, b)

cdef class SetDelSlice:
    def __setslice__(self, a, b, value):
        print "SetDelSlice setslice %d %d %r" % (a, b, value)

    def __delslice__(self, a, b):
        print "SetDelSlice delslice %d %d" % (a, b)

cdef class Long:
    def __long__(self):
        print "Long __long__"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/special_methods_T561_py3.pyx0000644000175100001770000000572500000000000022772 0ustar00runnerdocker00000000000000# ticket: t561
# tag: py3
# This file tests the behavior of special methods under Python 3
# after #561.  (Only methods whose behavior differs between Python 2 and 3
# are tested here; see special_methods_T561.pyx for the rest of the tests.)

__doc__ = u"""
    >>> vs0 = VerySpecial(0)
    VS __init__ 0

    >>> # Python 3 does not use __cmp__, so any provided __cmp__ method is
    >>> # discarded under Python 3.
    >>> vs0_cmp = vs0.__cmp__  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__cmp__'...

    >>> # Python 3 does not use __div__ or __idiv__, so these methods are
    >>> # discarded under Python 3.
    >>> vs0_div = vs0.__div__  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__div__'...
    >>> vs0_rdiv = vs0.__rdiv__  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__rdiv__'...
    >>> vs0_idiv = vs0.__idiv__  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__idiv__'...

    >>> # Python 3 does not use __oct__ or __hex__, so these methods are
    >>> # discarded under Python 3.
    >>> vs0_oct = vs0.__oct__  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__oct__'...
    >>> vs0_hex = vs0.__hex__  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__hex__'...

    >>> # Python 3 does not use __long__; if you define __long__ but not
    >>> # __int__, the __long__ definition will be used for __int__.
    >>> Ll = Long().__long__  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    AttributeError: 'special_methods_T561_py3.Long' object has no attribute '__long__'...
    >>> Li = Long().__int__
    >>> Li()
    Long __long__

    >>> # As of Python 3, defining __nonzero__ gives you a __bool__ method instead.
    >>> vs0_bool = vs0.__bool__
    >>> vs0_bool()
    VS __nonzero__ 0
    False
"""

cdef class VerySpecial:
    cdef readonly int value

    def __init__(self, v):
        self.value = v
        print "VS __init__ %d" % self.value

    def __nonzero__(self):
        print "VS __nonzero__ %d" % self.value

    def __oct__(self):
        print "VS __oct__ %d" % self.value

    def __hex__(self):
        print "VS __hex__ %d" % self.value

    def __cmp__(self, other):
        print "VS __cmp__ %d %d" % (self.value, other.value)

    def __div__(self, other):
        print "VS __div__ %d %d" % (self.value, other.value)

    def __idiv__(self, other):
        print "VS __idiv__ %d /= %d" % (self.value, other.value)

cdef class Long:
    def __long__(self):
        print "Long __long__"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/special_methods_T561_py38.pyx0000644000175100001770000000220200000000000023045 0ustar00runnerdocker00000000000000# mode: run

from cpython.number cimport PyNumber_InPlacePower

def ipow(a, b, c):
    # As far as DW can tell, calling through this C API call is the
    # only way to actually use ternary __ipow__
    return PyNumber_InPlacePower(a, b, c)

# three-arg ipow can only work safely on Py3.8+
# and so tests are in a separate file

cdef class TwoOrThreeArgIPow:
    """
    >>> a = TwoOrThreeArgIPow('a')
    >>> a**=2
    >>> print(a)
    a**2[None]
    >>> print(ipow(TwoOrThreeArgIPow('a'), 'x', 'y'))
    a**x[y]
    """
    cdef str name

    def __init__(self, name):
        self.name = name

    def __ipow__(self, other, base=None):
        return f"{self.name}**{other}[{base}]"


cdef class ThreeArgIPow:
    """
    Note that it's not possible to detect if this is called in a 2-arg context
    since the Python interpreter just passes None
    >>> a = ThreeArgIPow('a')
    >>> a**=2
    >>> print(a)
    a**2[None]
    >>> print(ipow(ThreeArgIPow('a'), 'x', 'y'))
    a**x[y]
    """
    cdef str name

    def __init__(self, name):
        self.name = name

    def __ipow__(self, other, base):
        return f"{self.name}**{other}[{base}]"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/specialfloat.pyx0000644000175100001770000000542200000000000020755 0ustar00runnerdocker00000000000000DEF FLOAT = 12.5
DEF EMFLOAT = 5e-1
DEF EPFLOAT = 5e+1
DEF FLOAT_NAN = float('nan')
DEF FLOAT_INFP = float('+inf')
DEF FLOAT_INFN = float('-inf')

cdef double cdef_float_nan = float('nan')
cdef double cdef_float_infp = float('+inf')
cdef double cdef_float_infn = float('-inf')

float_nan = FLOAT_NAN
float_infp = FLOAT_INFP
float_infn = FLOAT_INFN

def f():
    """
    >>> f()
    12.5
    """
    cdef float f = FLOAT
    cdef object o = FLOAT
    assert f == o
    return f

def emfloat():
    """
    >>> emfloat()
    0.5
    """
    cdef float f = EMFLOAT
    assert f == 5e-1
    cdef object o = EMFLOAT
    assert o == 5e-1
    assert f == o
    return f

def epfloat():
    """
    >>> epfloat()
    50.0
    """
    cdef float f = EPFLOAT
    assert f == 5e+1
    cdef object o = EPFLOAT
    assert o == 5e+1
    assert f == o
    return f

def nan1():
    """
    >>> nan1()
    nan
    """
    cdef double f = FLOAT_NAN
    cdef object o = FLOAT_NAN
    assert str(f) == str(o)
    return f

def nan2():
    """
    >>> nan2()
    nan
    """
    cdef double f = float('nan')
    cdef object o = float('nan')
    assert str(f) == str(o)
    return f

def nan3():
    """
    >>> nan3()
    nan
    >>> float_nan
    nan
    """
    cdef float f = FLOAT_NAN
    cdef object o = FLOAT_NAN
    assert str(f) == str(o)
    return f

def infp1():
    """
    >>> infp1()
    inf
    >>> infp1() == float('inf')
    True
    """
    cdef double f = FLOAT_INFP
    cdef object o = FLOAT_INFP
    assert f == o
    return f

def infp2():
    """
    >>> infp2()
    inf
    >>> infp2() == float('inf')
    True
    """
    cdef double f = float('+inf')
    cdef object o = float('+inf')
    assert f == o
    return f

def infp3():
    """
    >>> infp3()
    inf
    >>> infp3() == float('inf')
    True
    >>> float_infp
    inf
    >>> float_infp == float('inf')
    True
    """
    cdef float f = FLOAT_INFP
    cdef object o = FLOAT_INFP
    assert f == o
    return f

def infn1():
    """
    >>> infn1()
    -inf
    >>> infn1() == float('-inf')
    True
    """
    cdef double f = FLOAT_INFN
    cdef object o = FLOAT_INFN
    assert f == o
    return f

def infn2():
    """
    >>> infn2()
    -inf
    >>> infn2() == float('-inf')
    True
    """
    cdef double f = float('-inf')
    cdef object o = float('-inf')
    assert f == o
    return f

def infn3():
    """
    >>> infn3()
    -inf
    >>> infn3() == float('-inf')
    True
    >>> float_infn
    -inf
    >>> float_infn == float('-inf')
    True
    """
    cdef float f = FLOAT_INFN
    cdef object o = FLOAT_INFN
    assert f == o
    return f

def global_floats():
    """
    >>> global_floats()[1:] == (float('+inf'), float('-inf'))
    True
    >>> global_floats()[0]
    nan
    """
    return (cdef_float_nan, cdef_float_infp, cdef_float_infn)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/ssize_t_T399.pyx0000644000175100001770000000234300000000000020516 0ustar00runnerdocker00000000000000# ticket: t399

__doc__ = u"""
>>> test(-2)
-2
>>> test(-1)
-1
>>> test(0)
0
>>> test(1)
1
>>> test(2)
2

>>> test(SSIZE_T_MAX) == SSIZE_T_MAX
True
>>> test(SSIZE_T_MIN) == SSIZE_T_MIN
True

>>> test(SSIZE_T_MAX+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
    ...
OverflowError: ...
>>> test(SSIZE_T_MIN-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
    ...
OverflowError: ...

>>> test(1<<128) #doctest: +ELLIPSIS
Traceback (most recent call last):
    ...
OverflowError: ...
>>> test(-(1<<128)) #doctest: +ELLIPSIS
Traceback (most recent call last):
    ...
OverflowError: ...

>>> a = A(1,2)
>>> a.a == 1
True
>>> a.b == 2
True
>>> a.foo(5)
5
>>> a.foo(1 << 180) #doctest: +ELLIPSIS
Traceback (most recent call last):
    ...
OverflowError: ...
"""

cdef extern from *:
    ctypedef long ssize_t # XXX This should generate a warning !!!
    ssize_t PY_SSIZE_T_MAX
    ssize_t PY_SSIZE_T_MIN

SSIZE_T_MAX = PY_SSIZE_T_MAX
SSIZE_T_MIN = PY_SSIZE_T_MIN

def test(ssize_t i):
    return i

cdef class A:
    cdef public ssize_t a
    cdef readonly ssize_t b

    def __init__(self, ssize_t a, object b):
        self.a = a
        self.b = b

    cpdef ssize_t foo(self, ssize_t x):
        cdef object o = x
        return o
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/starargs.pyx0000644000175100001770000000663200000000000020141 0ustar00runnerdocker00000000000000cdef sorteditems(d):
    return tuple(sorted(d.items()))


def spam(x, y, z):
    """
    >>> spam(1,2,3)
    (1, 2, 3)
    >>> spam(1,2)
    Traceback (most recent call last):
    TypeError: spam() takes exactly 3 positional arguments (2 given)
    >>> spam(1,2,3,4)
    Traceback (most recent call last):
    TypeError: spam() takes exactly 3 positional arguments (4 given)
    >>> spam(1,2,3, a=1)
    Traceback (most recent call last):
    TypeError: spam() got an unexpected keyword argument 'a'
    """
    return (x, y, z)

def grail(x, y, z, *a):
    """
    >>> grail(1,2,3)
    (1, 2, 3, ())
    >>> grail(1,2,3,4)
    (1, 2, 3, (4,))
    >>> grail(1,2,3,4,5,6,7,8,9)
    (1, 2, 3, (4, 5, 6, 7, 8, 9))
    >>> grail(1,2)
    Traceback (most recent call last):
    TypeError: grail() takes at least 3 positional arguments (2 given)
    >>> grail(1,2,3, a=1)
    Traceback (most recent call last):
    TypeError: grail() got an unexpected keyword argument 'a'
    """
    return (x, y, z, a)

def swallow(x, y, z, **k):
    """
    >>> swallow(1,2,3)
    (1, 2, 3, ())
    >>> swallow(1,2,3,4)
    Traceback (most recent call last):
    TypeError: swallow() takes exactly 3 positional arguments (4 given)
    >>> swallow(1,2,3, a=1, b=2)
    (1, 2, 3, (('a', 1), ('b', 2)))
    >>> swallow(1,2,3, x=1)
    Traceback (most recent call last):
    TypeError: swallow() got multiple values for keyword argument 'x'
    """
    return (x, y, z, sorteditems(k))

def creosote(x, y, z, *a, **k):
    """
    >>> creosote(1,2,3)
    (1, 2, 3, (), ())
    >>> creosote(1,2,3,4)
    (1, 2, 3, (4,), ())
    >>> creosote(1,2,3, a=1)
    (1, 2, 3, (), (('a', 1),))
    >>> creosote(1,2,3,4, a=1, b=2)
    (1, 2, 3, (4,), (('a', 1), ('b', 2)))
    >>> creosote(1,2,3,4, x=1)
    Traceback (most recent call last):
    TypeError: creosote() got multiple values for keyword argument 'x'
    """
    return (x, y, z, a, sorteditems(k))

def onlyt(*a):
    """
    >>> onlyt(1)
    (1,)
    >>> onlyt(1,2)
    (1, 2)
    >>> onlyt(a=1)
    Traceback (most recent call last):
    TypeError: onlyt() got an unexpected keyword argument 'a'
    >>> onlyt(1, a=2)
    Traceback (most recent call last):
    TypeError: onlyt() got an unexpected keyword argument 'a'
    >>> test_no_copy_args(onlyt)
    True
    """
    return a

def onlyk(**k):
    """
    >>> onlyk(a=1)
    (('a', 1),)
    >>> onlyk(a=1, b=2)
    (('a', 1), ('b', 2))
    >>> onlyk(1)
    Traceback (most recent call last):
    TypeError: onlyk() takes exactly 0 positional arguments (1 given)
    >>> onlyk(1, 2)
    Traceback (most recent call last):
    TypeError: onlyk() takes exactly 0 positional arguments (2 given)
    >>> onlyk(1, a=1, b=2)
    Traceback (most recent call last):
    TypeError: onlyk() takes exactly 0 positional arguments (1 given)
    """
    return sorteditems(k)

def tk(*a, **k):
    """
    >>> tk(a=1)
    (('a', 1),)
    >>> tk(a=1, b=2)
    (('a', 1), ('b', 2))
    >>> tk(1)
    (1,)
    >>> tk(1, 2)
    (1, 2)
    >>> tk(1, a=1, b=2)
    (1, ('a', 1), ('b', 2))
    """
    return a + sorteditems(k)

def t_kwonly(*a, k):
    """
    >>> test_no_copy_args(t_kwonly, k=None)
    True
    """
    return a


def test_no_copy_args(func, **kw):
    """
    func is a function such that func(*args, **kw) returns args.
    We test that no copy is made of the args tuple.
    This tests both the caller side and the callee side.
    """
    args = (1, 2, 3)
    return func(*args, **kw) is args
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/starimport_cimport.srctree0000644000175100001770000000147300000000000023101 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import star_cimport_test"

######## setup.py ########

from distutils.core import setup
from Cython.Distutils import build_ext
from Cython.Distutils.extension import Extension

setup(
    ext_modules = [
        Extension("star_cimport_ext",  ["star_cimport_ext.pyx"]),
        Extension("star_cimport_test", ["star_cimport_test.pyx"]),
        ],
    cmdclass={'build_ext': build_ext},
)

######## star_cimport_ext.pyx ########

cdef class test_pxd:
    pass

######## star_cimport_ext.pxd ########

cdef class test_pxd:
    pass

######## star_cimport.py ########

class test_py:
    pass

######## star_cimport_test.pyx ########

# Tests a Python star import followed by a cimport
from star_cimport import *
from star_cimport_ext cimport test_pxd

cdef test_pxd t = test_pxd()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/starred_target_T664.pyx0000644000175100001770000000060100000000000022036 0ustar00runnerdocker00000000000000# ticket: t664

def assign():
    """
    >>> assign()
    (1, [2, 3, 4, 5])
    """
    a, *b = 1, 2, 3, 4, 5
    return a, b

def assign3():
    """
    >>> assign3()
    (1, [2, 3, 4, 5], 6)
    """
    a, *b, c = 1, 2, 3, 4, 5, 6
    return a, b, c

def assign4():
    """
    >>> assign4()
    (1, [2, 3, 4], 5, 6)
    """
    a, *b, c, d = 1, 2, 3, 4, 5, 6
    return a, b, c, d
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/static_methods.pxd0000644000175100001770000000020500000000000021266 0ustar00runnerdocker00000000000000cdef class FromPxd:
    @staticmethod
    cdef static_cdef(int* x)

    @staticmethod
    cdef static_cdef_with_implicit_object(obj)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/static_methods.pyx0000644000175100001770000000444000000000000021320 0ustar00runnerdocker00000000000000cdef class A:
    @staticmethod
    def static_def(int x):
        """
        >>> A.static_def(2)
        ('def', 2)
        >>> A().static_def(2)
        ('def', 2)
        """
        return 'def', x

    @staticmethod
    cdef static_cdef(int* x):
        return 'cdef', x[0]

    @staticmethod
    cdef static_cdef2(int* x, int* y):
        return 'cdef2', x[0] + y[0]

    @staticmethod
    cdef static_cdef_untyped(a, b):
        return 'cdef_utyped', a, b

#     @staticmethod
#     cpdef static_cpdef(int x):
#         """
#         >>> A.static_def
#         >>> A.static_cpdef
#
#         >>> A().static_def
#         >>> A().static_cpdef
#
#         >>> A.static_cpdef(2)
#         ('cpdef', 2)
#         >>> A().static_cpdef(2)
#         ('cpdef', 2)
#         """
#         return 'cpdef', x

def call_static_def(int x):
    """
    >>> call_static_def(2)
    ('def', 2)
    """
    return A.static_def(x)

def call_static_cdef(int x):
    """
    >>> call_static_cdef(2)
    ('cdef', 2)
    """
    cdef int *x_ptr = &x
    return A.static_cdef(x_ptr)

def call_static_cdef2(int x, int y):
    """
    >>> call_static_cdef2(2, 3)
    ('cdef2', 5)
    """
    return A.static_cdef2(&x, &y)

def call_static_list_comprehension_GH1540(int x):
    """
    >>> call_static_list_comprehension_GH1540(5)
    [('cdef', 5), ('cdef', 5), ('cdef', 5)]
    """
    return [A.static_cdef(&x) for _ in range(3)]

# BROKEN
#def call_static_cdef_untyped(a, b):
#    """
#    >>> call_static_cdef_untyped(100, None)
#    ('cdef_untyped', 100, None)
#    """
#    return A.static_cdef_untyped(a, b)

# UNIMPLEMENTED
# def call_static_cpdef(int x):
#     """
#     >>> call_static_cpdef(2)
#     ('cpdef', 2)
#     """
#     return A.static_cpdef(x)

cdef class FromPxd:
    @staticmethod
    cdef static_cdef(int* x):
        return 'pxd_cdef', x[0]

    @staticmethod
    cdef static_cdef_with_implicit_object(obj):
        return obj+1

def call_static_pxd_cdef(int x):
    """
    >>> call_static_pxd_cdef(2)
    ('pxd_cdef', 2)
    """
    cdef int *x_ptr = &x
    return FromPxd.static_cdef(x_ptr)

def call_static_pxd_cdef_with_implicit_object(int x):
    """
    # https://github.com/cython/cython/issues/3174
    >>> call_static_pxd_cdef_with_implicit_object(2)
    3
    """
    return FromPxd.static_cdef_with_implicit_object(x)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/staticmethod.pyx0000644000175100001770000000515100000000000020776 0ustar00runnerdocker00000000000000cimport cython


class class1:
    u"""
    >>> class1.plus1(1)
    2
    >>> class1().plus1(1)
    2
    >>> class1.bplus1(1)
    2
    >>> class1().bplus1(1)
    2
    """
    @staticmethod
    def plus1(a):
        return a + 1

    @staticmethod
    @cython.binding(True)
    def bplus1(a):
        return a + 1


def nested_class():
    """
    >>> cls = nested_class()
    >>> cls.plus1(1)
    2
    >>> obj = cls()
    >>> obj.plus1(1)
    2
    """
    class class2(object):
        def __new__(cls): # implicit staticmethod
            return object.__new__(cls)

        @staticmethod
        def plus1(a):
            return a + 1
    return class2


cdef class BaseClass(object):
    """
    Test cdef static methods with super() and Python subclasses

    >>> obj = BaseClass()
    >>> obj.mystaticmethod(obj, 1)
    1
    >>> BaseClass.mystaticmethod(obj, 1)
    1
    >>> obj.mystaticmethod2(1, 2, 3)
    1 2 3
    >>> BaseClass.mystaticmethod2(1, 2, 3)
    1 2 3
    """

    @staticmethod
    def mystaticmethod(self, arg1):
        print arg1

    @staticmethod
    @cython.binding(True)
    def mystaticmethod2(a, b, c):
        print a, b, c


cdef class SubClass(BaseClass):
    """
    >>> obj = SubClass()
    >>> obj.mystaticmethod(obj, 1)
    1
    2
    >>> SubClass.mystaticmethod(obj, 1)
    1
    2
    """

    @staticmethod
    def mystaticmethod(self, arg1):
        print arg1
        super().mystaticmethod(self, arg1 + 1)


class SubSubClass(SubClass):
    """
    >>> obj = SubSubClass()
    >>> obj.mystaticmethod(obj, 1)
    1
    2
    3
    >>> SubSubClass.mystaticmethod(obj, 1)
    1
    2
    3
    """

    @staticmethod
    def mystaticmethod(self, arg1):
        print arg1
        super().mystaticmethod(self, arg1 + 1)


cdef class ArgsKwargs(object):
    @staticmethod
    def with_first_arg(arg1, *args, **kwargs):
        """
        >>> ArgsKwargs().with_first_arg(1, 2, 3, a=4, b=5)
        (1, 'pos', 2, 3, ('a', 4), ('b', 5))
        """
        return (arg1, 'pos') + args + tuple(sorted(kwargs.items()))

    @staticmethod
    def only_args_kwargs(*args, **kwargs):
        """
        >>> ArgsKwargs().only_args_kwargs()
        ()
        >>> ArgsKwargs().only_args_kwargs(1, 2, a=3)
        (1, 2, ('a', 3))
        """
        return args + tuple(sorted(kwargs.items()))

    @staticmethod
    def no_args():
        """
        >>> ArgsKwargs().no_args()
        OK!
        """
        print("OK!")


class StaticmethodSubclass(staticmethod):
    """
    >>> s = StaticmethodSubclass(None)
    >>> s.is_subtype()
    True
    """
    def is_subtype(self):
        return isinstance(self, staticmethod)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/str_ascii_auto_encoding.pyx0000644000175100001770000000042100000000000023157 0ustar00runnerdocker00000000000000#cython: c_string_type = str
#cython: c_string_encoding = ascii

"End of first directives"

include "unicode_ascii_auto_encoding.pyx"

auto_string_type = str

def check_auto_string_type():
    """
    >>> check_auto_string_type()
    """
    assert auto_string_type is str
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/str_char_coercion_T412.pyx0000644000175100001770000000246700000000000022515 0ustar00runnerdocker00000000000000# ticket: t412

cdef int   i = 'x'
cdef char  c = 'x'
cdef char* s = 'x'

def test_eq():
    """
    >>> test_eq()
    True
    True
    True
    True
    """
    print i ==  'x'
    print i == c'x'
    print c ==  'x'
    print c == c'x'
#    print s ==  'x' # error
#    print s == c'x' # error

def test_cascaded_eq():
    """
    >>> test_cascaded_eq()
    True
    True
    True
    True
    True
    True
    True
    True
    """
    print  'x' == i ==  'x'
    print  'x' == i == c'x'
    print c'x' == i ==  'x'
    print c'x' == i == c'x'

    print  'x' == c ==  'x'
    print  'x' == c == c'x'
    print c'x' == c ==  'x'
    print c'x' == c == c'x'

def test_cascaded_ineq():
    """
    >>> test_cascaded_ineq()
    True
    True
    True
    True
    True
    True
    True
    True
    """
    print  'a' <= i <=  'z'
    print  'a' <= i <= c'z'
    print c'a' <= i <=  'z'
    print c'a' <= i <= c'z'

    print  'a' <= c <=  'z'
    print  'a' <= c <= c'z'
    print c'a' <= c <=  'z'
    print c'a' <= c <= c'z'

def test_long_ineq():
    """
    >>> test_long_ineq()
    True
    """
    print 'a' < 'b' < 'c' < 'd' < c < 'y' < 'z'

def test_long_ineq_py():
    """
    >>> test_long_ineq_py()
    True
    True
    """
    print 'abcdef' < 'b' < 'c' < 'd' < 'y' < 'z'
    print 'a' < 'b' < 'cde' < 'd' < 'y' < 'z'
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/str_default_auto_encoding.pyx0000644000175100001770000000066700000000000023527 0ustar00runnerdocker00000000000000# cython: c_string_encoding=default
# cython: c_string_type=str

# NOTE: the directive order above is specifically meant to trigger (and confuse) the
# source encoding detector with "coding=default".

import sys
if sys.version_info[0] >= 3:
    __doc__ = r"""
        >>> as_objects("ab\xff") == "ab\xff"
        True
        >>> slice_as_objects("ab\xffd", 1, 4) == "b\xff"
        True
        """

include "str_ascii_auto_encoding.pyx"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/str_encoding_latin1.pyx0000644000175100001770000000133300000000000022232 0ustar00runnerdocker00000000000000#  -*- coding: latin-1 -*-

__doc__ = (u"""
>>> a == 'abc'
True
>>> isinstance(a, str)
True

>>> isinstance(s, str)
True
>>> len(s)
6
>>> s == 'ao'
True

>>> isinstance(add(), str)
True
>>> len(add())
9
>>> add() == 'abcao'
True

>>> isinstance(add_literal(), str)
True
>>> len(add_literal())
9
>>> add_literal() == 'abcao'
True

>>> isinstance(typed(), str)
True
>>> len(typed())
6
>>> typed() == ''
True

"""
# recoding/escaping is required to properly pass the literals to doctest
).encode('unicode_escape').decode('ASCII').replace(u'\\n', u'\n')

a = 'abc'
s = 'ao'
u = u'ao'

cdef str S = ''

def add():
    return a+s

def add_literal():
    return 'abc' + 'ao'

def typed():
    return S
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/str_subclass_kwargs.pyx0000644000175100001770000000123000000000000022365 0ustar00runnerdocker00000000000000def test_str_subclass_kwargs(k=None):
    """
    Test passing keywords with names that are not of type ``str``
    but a subclass:

    >>> class StrSubclass(str):
    ...     pass
    >>> class StrNoCompare(str):
    ...     def __eq__(self, other):
    ...         raise RuntimeError("do not compare me")
    ...     def __hash__(self):
    ...         return hash(str(self))
    >>> kwargs = {StrSubclass('k'): 'value'}
    >>> test_str_subclass_kwargs(**kwargs)
    'value'
    >>> kwargs = {StrNoCompare('k'): 'value'}
    >>> test_str_subclass_kwargs(**kwargs)
    Traceback (most recent call last):
    RuntimeError: do not compare me
    """
    return k
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/strconstinclass.pyx0000644000175100001770000000012100000000000021532 0ustar00runnerdocker00000000000000__doc__ = u"""
    >>> c = C()
    >>> c.x
    'foo'
"""

class C:
    x = "foo"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/strescapes.pyx0000644000175100001770000000235600000000000020466 0ustar00runnerdocker00000000000000__doc__ = u"""

>>> py_strings = [
... b'\\x1234',
... b'\\x0A12\\x0C34',
... b'\\x0A57',
... b'\\x0A',
... b'\\'',
... b"\\'",
... b"\\"",
... b'\\"',
... b'abc\\x12def',
... u'\\u1234',
... u'\\U00001234',
... b'\\u1234',
... b'\\U00001234',
... b'\\n\\r\\t',
... b':>',
... b'??>',
... b'\\0\\0\\0',
... ]

>>> for i, (py_string, (c_string, length)) in enumerate(zip(py_strings, c_strings)):
...     assert py_string == c_string, "%d: %r != %r" % (i, py_string, c_string)
...     assert len(py_string) == length, (
...         "%d: wrong length of %r, got %d, expected %d" % (
...             i, py_string, len(py_string), length))
...     assert len(c_string) == length, (
...         "%d: wrong length of %r, got %d, expected %d" % (
...             i, c_string, len(c_string), length))

"""

import sys
if sys.version_info[0] < 3:
    __doc__ = __doc__.replace(u" b'", u" '").replace(u' b"', u' "')
else:
    __doc__ = __doc__.replace(u" u'", u" '").replace(u' u"', u' "')

c_strings = [
(b'\x1234', 3),
(b'\x0A12\x0C34', 6),
(b'\x0A57', 3),
(b'\x0A', 1),
(b'\'', 1),
(b"\'", 1),
(b"\"", 1),
(b'\"', 1),
(b'abc\x12def', 7),
(u'\u1234', 1),
(u'\U00001234', 1),
(b'\u1234', 6),
(b'\U00001234', 10),
(b'\n\r\t', 3),
(b':>', 2),
(b'??>', 3),
(b'\0\0\0', 3),
]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/strfunction.pyx0000644000175100001770000000231700000000000020665 0ustar00runnerdocker00000000000000__doc__ = u"""
   >>> str('test')
   'test'
   >>> z
   'test'
"""

cimport cython

s = str
z = str('test')

def c(string):
    """
    >>> c('testing')
    'testing'
    """
    return str(string)

class subs(str):
    """
    >>> subs('testing a subtype')
    'testing a subtype'

    #   >>> csub('testing a subtype')
    #   'testing a subtype'
    #   >>> csubs('testing a subtype')
    #   'testing a subtype'
    """
    pass

def sub(string):
    """
    >>> sub('testing a subtype')
    'testing a subtype'
    """
    return subs(string)

#cdef class subs(str):
#    pass

#def csub(string):
#    return csubs(string)


@cython.test_fail_if_path_exists("//SimpleCallNode")
@cython.test_assert_path_exists("//PythonCapiCallNode")
def typed(str s):
    """
    >>> print(typed(None))
    None
    >>> type(typed(None)) is type(typed(None))
    True
    >>> print(typed('abc'))
    abc
    >>> type(typed('abc')) is type(typed('abc'))
    True
    """
    return str(s)


@cython.test_fail_if_path_exists(
    "//SimpleCallNode",
    "//PythonCapiCallNode",
)
def typed_not_none(str s not None):
    """
    >>> print(typed('abc'))
    abc
    >>> type(typed('abc')) is type(typed('abc'))
    True
    """
    return str(s)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/string_comparison.pyx0000644000175100001770000003663200000000000022056 0ustar00runnerdocker00000000000000
cimport cython

import sys
IS_PY3 = sys.version_info[0] >= 3

bstring1 = b"abcdefg"
bstring2 = b"1234567"

string1 = "abcdefg"
string2 = "1234567"

ustring1 = u"abcdefg"
ustring2 = u"1234567"

# unicode

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def unicode_eq(unicode s1, unicode s2):
    """
    >>> unicode_eq(ustring1, ustring1)
    True
    >>> unicode_eq(ustring1+ustring2, ustring1+ustring2)
    True
    >>> unicode_eq(ustring1, ustring2)
    False
    """
    return s1 == s2

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def unicode_neq(unicode s1, unicode s2):
    """
    >>> unicode_neq(ustring1, ustring1)
    False
    >>> unicode_neq(ustring1+ustring2, ustring1+ustring2)
    False
    >>> unicode_neq(ustring1, ustring2)
    True
    """
    return s1 != s2

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def unicode_literal_eq(unicode s):
    """
    >>> unicode_literal_eq(ustring1)
    True
    >>> unicode_literal_eq((ustring1+ustring2)[:len(ustring1)])
    True
    >>> unicode_literal_eq(ustring2)
    False
    """
    return s == u"abcdefg"

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def unicode_literal_neq(unicode s):
    """
    >>> unicode_literal_neq(ustring1)
    False
    >>> unicode_literal_neq((ustring1+ustring2)[:len(ustring1)])
    False
    >>> unicode_literal_neq(ustring2)
    True
    """
    return s != u"abcdefg"

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
    "//CascadedCmpNode"
)
@cython.test_fail_if_path_exists(
    "//CascadedCmpNode[@is_pycmp = True]",
    "//PrimaryCmpNode[@is_pycmp = True]",
)
def unicode_cascade(unicode s1, unicode s2):
    """
    >>> unicode_cascade(ustring1, ustring1)
    True
    >>> unicode_cascade(ustring1, (ustring1+ustring2)[:len(ustring1)])
    True
    >>> unicode_cascade(ustring1, ustring2)
    False
    """
    return s1 == s2 == u"abcdefg"

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def unicode_cascade_untyped_end(unicode s1, unicode s2):
    """
    >>> unicode_cascade_untyped_end(ustring1, ustring1)
    True
    >>> unicode_cascade_untyped_end(ustring1, (ustring1+ustring2)[:len(ustring1)])
    True
    >>> unicode_cascade_untyped_end(ustring1, ustring2)
    False
    """
    return s1 == s2 == u"abcdefg" == (ustring1) == ustring1

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def unicode_cascade_untyped_end_bool(unicode s1, unicode s2):
    """
    >>> unicode_cascade_untyped_end_bool(ustring1, ustring1)
    True
    >>> unicode_cascade_untyped_end_bool(ustring1, (ustring1+ustring2)[:len(ustring1)])
    True
    >>> unicode_cascade_untyped_end_bool(ustring1, ustring2)
    False
    """
    if s1 == s2 == u"abcdefg" == (ustring1) == ustring1:
        return True
    else:
        return False


# str

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def str_eq(str s1, str s2):
    """
    >>> str_eq(string1, string1)
    True
    >>> str_eq(string1+string2, string1+string2)
    True
    >>> str_eq(string1, string2)
    False
    """
    return s1 == s2

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def str_neq(str s1, str s2):
    """
    >>> str_neq(string1, string1)
    False
    >>> str_neq(string1+string2, string1+string2)
    False
    >>> str_neq(string1, string2)
    True
    """
    return s1 != s2

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def str_literal_eq(str s):
    """
    >>> str_literal_eq(string1)
    True
    >>> str_literal_eq((string1+string2)[:len(string1)])
    True
    >>> str_literal_eq(string2)
    False
    """
    return s == "abcdefg"

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def str_literal_neq(str s):
    """
    >>> str_literal_neq(string1)
    False
    >>> str_literal_neq((string1+string2)[:len(string1)])
    False
    >>> str_literal_neq(string2)
    True
    """
    return s != "abcdefg"

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
@cython.test_fail_if_path_exists(
    "//CascadedCmpNode[@is_pycmp = True]",
    "//PrimaryCmpNode[@is_pycmp = True]",
)
def str_cascade(str s1, str s2):
    """
    >>> str_cascade(string1, string1)
    True
    >>> str_cascade(string1, (string1+string2)[:len(string1)])
    True
    >>> str_cascade(string1, string2)
    False
    """
    return s1 == s2 == "abcdefg"

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def str_cascade_untyped_end(str s1, str s2):
    """
    >>> str_cascade_untyped_end(string1, string1)
    True
    >>> str_cascade_untyped_end(string1, (string1+string2)[:len(string1)])
    True
    >>> str_cascade_untyped_end(string1, string2)
    False
    """
    return s1 == s2 == "abcdefg" == (string1) == string1

# bytes

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def bytes_eq(bytes s1, bytes s2):
    """
    >>> bytes_eq(bstring1, bstring1)
    True
    >>> bytes_eq(bstring1+bstring2, bstring1+bstring2)
    True
    >>> bytes_eq(bstring1, bstring2)
    False
    """
    return s1 == s2

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def bytes_neq(bytes s1, bytes s2):
    """
    >>> bytes_neq(bstring1, bstring1)
    False
    >>> bytes_neq(bstring1+bstring2, bstring1+bstring2)
    False
    >>> bytes_neq(bstring1, bstring2)
    True
    """
    return s1 != s2

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def bytes_literal_eq(bytes s):
    """
    >>> bytes_literal_eq(bstring1)
    True
    >>> bytes_literal_eq((bstring1+bstring2)[:len(bstring1)])
    True
    >>> bytes_literal_eq(bstring2)
    False
    """
    return s == b"abcdefg"

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def bytes_literal_neq(bytes s):
    """
    >>> bytes_literal_neq(bstring1)
    False
    >>> bytes_literal_neq((bstring1+bstring2)[:len(bstring1)])
    False
    >>> bytes_literal_neq(bstring2)
    True
    """
    return s != b"abcdefg"

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
@cython.test_fail_if_path_exists(
    "//CascadedCmpNode[@is_pycmp = True]",
    "//PrimaryCmpNode[@is_pycmp = True]",
)
def bytes_cascade(bytes s1, bytes s2):
    """
    >>> bytes_cascade(bstring1, bstring1)
    True
    >>> bytes_cascade(bstring1, (bstring1+bstring2)[:len(bstring1)])
    True
    >>> bytes_cascade(bstring1, bstring2)
    False
    """
    return s1 == s2 == b"abcdefg"

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def bytes_cascade_untyped_end(bytes s1, bytes s2):
    """
    >>> bytes_cascade_untyped_end(bstring1, bstring1)
    True
    >>> bytes_cascade_untyped_end(bstring1, (bstring1+bstring2)[:len(bstring1)])
    True
    >>> bytes_cascade_untyped_end(bstring1, bstring2)
    False
    """
    return s1 == s2 == b"abcdefg" == (bstring1) == bstring1


# basestring

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def basestring_eq(basestring s1, basestring s2):
    """
    >>> basestring_eq(string1, string1)
    True
    >>> basestring_eq(string1, ustring1)
    True
    >>> basestring_eq(string1+string2, string1+string2)
    True
    >>> basestring_eq(string1+ustring2, ustring1+string2)
    True
    >>> basestring_eq(string1, string2)
    False
    >>> basestring_eq(string1, ustring2)
    False
    >>> basestring_eq(ustring1, string2)
    False
    """
    return s1 == s2

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def basestring_neq(basestring s1, basestring s2):
    """
    >>> basestring_neq(string1, string1)
    False
    >>> basestring_neq(string1+string2, string1+string2)
    False
    >>> basestring_neq(string1+ustring2, ustring1+string2)
    False
    >>> basestring_neq(string1, string2)
    True
    >>> basestring_neq(string1, ustring2)
    True
    >>> basestring_neq(ustring1, string2)
    True
    """
    return s1 != s2

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def basestring_str_literal_eq(basestring s):
    """
    >>> basestring_str_literal_eq(string1)
    True
    >>> basestring_str_literal_eq((string1+string2)[:len(string1)])
    True
    >>> basestring_str_literal_eq(string2)
    False
    """
    return s == "abcdefg"

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def basestring_unicode_literal_eq(basestring s):
    """
    >>> basestring_unicode_literal_eq(string1)
    True
    >>> basestring_unicode_literal_eq((string1+string2)[:len(string1)])
    True
    >>> basestring_unicode_literal_eq(string2)
    False
    """
    return s == u"abcdefg"

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def basestring_str_literal_neq(basestring s):
    """
    >>> basestring_str_literal_neq(string1)
    False
    >>> basestring_str_literal_neq((string1+string2)[:len(string1)])
    False
    >>> basestring_str_literal_neq(string2)
    True
    """
    return s != "abcdefg"

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def basestring_unicode_literal_neq(basestring s):
    """
    >>> basestring_unicode_literal_neq(string1)
    False
    >>> basestring_unicode_literal_neq((string1+string2)[:len(string1)])
    False
    >>> basestring_unicode_literal_neq(string2)
    True
    """
    return s != u"abcdefg"

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
    "//CascadedCmpNode[@is_pycmp = False]",
)
@cython.test_fail_if_path_exists(
    "//CascadedCmpNode[@is_pycmp = True]",
    "//PrimaryCmpNode[@is_pycmp = True]",
)
def basestring_cascade_str(basestring s1, basestring s2):
    """
    >>> basestring_cascade_str(string1, string1)
    True
    >>> basestring_cascade_str(string1, (string1+string2)[:len(string1)])
    True
    >>> basestring_cascade_str(string1, string2)
    False
    """
    return s1 == s2 == "abcdefg"

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
    "//CascadedCmpNode[@is_pycmp = False]",
)
@cython.test_fail_if_path_exists(
    "//CascadedCmpNode[@is_pycmp = True]",
    "//PrimaryCmpNode[@is_pycmp = True]",
)
def basestring_cascade_unicode(basestring s1, basestring s2):
    """
    >>> basestring_cascade_unicode(string1, string1)
    True
    >>> basestring_cascade_unicode(ustring1, string1)
    True
    >>> basestring_cascade_unicode(string1, ustring1)
    True
    >>> basestring_cascade_unicode(string1, (string1+string2)[:len(string1)])
    True
    >>> basestring_cascade_unicode(string1, string2)
    False
    >>> basestring_cascade_unicode(ustring1, string2)
    False
    >>> basestring_cascade_unicode(string1, ustring2)
    False
    """
    return s1 == s2 == u"abcdefg"

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def basestring_cascade_untyped_end(basestring s1, basestring s2):
    """
    >>> basestring_cascade_untyped_end(string1, string1)
    True
    >>> basestring_cascade_untyped_end(string1, (string1+string2)[:len(string1)])
    True
    >>> basestring_cascade_untyped_end(string1, string2)
    False
    """
    return s1 == s2 == "abcdefg" == (string1) == string1


# untyped/literal comparison

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def untyped_unicode_literal_eq_bool(s):
    """
    >>> untyped_unicode_literal_eq_bool(string1)
    True
    >>> untyped_unicode_literal_eq_bool(ustring1)
    True
    >>> untyped_unicode_literal_eq_bool((string1+string2)[:len(string1)])
    True
    >>> untyped_unicode_literal_eq_bool(string2)
    False
    >>> untyped_unicode_literal_eq_bool(ustring2)
    False
    """
    return True if s == u"abcdefg" else False

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def untyped_str_literal_eq_bool(s):
    """
    >>> untyped_str_literal_eq_bool(string1)
    True
    >>> untyped_str_literal_eq_bool(ustring1)
    True
    >>> untyped_str_literal_eq_bool((string1+string2)[:len(string1)])
    True
    >>> untyped_str_literal_eq_bool(string2)
    False
    >>> untyped_str_literal_eq_bool(ustring2)
    False
    """
    return True if s == "abcdefg" else False

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = True]",
    "//CascadedCmpNode",
    "//CascadedCmpNode[@is_pycmp = False]",
)
@cython.test_fail_if_path_exists(
    "//CascadedCmpNode[@is_pycmp = True]",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def untyped_unicode_cascade(s1, unicode s2):
    """
    >>> untyped_unicode_cascade(ustring1, ustring1)
    True
    >>> untyped_unicode_cascade(ustring1, (ustring1+ustring2)[:len(ustring1)])
    True
    >>> untyped_unicode_cascade(ustring1, ustring2)
    False
    """
    return s1 == s2 == u"abcdefg"

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = False]",
    "//CascadedCmpNode",
    "//CascadedCmpNode[@is_pycmp = False]",
)
@cython.test_fail_if_path_exists(
    "//CascadedCmpNode[@is_pycmp = True]",
    "//PrimaryCmpNode[@is_pycmp = True]",
)
def untyped_unicode_cascade_bool(s1, unicode s2):
    """
    >>> untyped_unicode_cascade_bool(ustring1, ustring1)
    True
    >>> untyped_unicode_cascade_bool(ustring1, (ustring1+ustring2)[:len(ustring1)])
    True
    >>> untyped_unicode_cascade_bool(ustring1, ustring2)
    False
    """
    return True if s1 == s2 == u"abcdefg" else False

@cython.test_assert_path_exists(
    "//PrimaryCmpNode",
    "//PrimaryCmpNode[@is_pycmp = True]",
    "//CascadedCmpNode",
#    "//CascadedCmpNode[@is_pycmp = False]",
)
@cython.test_fail_if_path_exists(
    "//CascadedCmpNode[@is_pycmp = True]",
    "//PrimaryCmpNode[@is_pycmp = False]",
)
def untyped_untyped_unicode_cascade_bool(s1, s2):
    """
    >>> untyped_untyped_unicode_cascade_bool(ustring1, ustring1)
    True
    >>> untyped_untyped_unicode_cascade_bool(ustring1, (ustring1+ustring2)[:len(ustring1)])
    True
    >>> untyped_untyped_unicode_cascade_bool(ustring1, ustring2)
    False
    >>> untyped_untyped_unicode_cascade_bool(string1, string2)
    False
    >>> untyped_untyped_unicode_cascade_bool(1, 2)
    False
    >>> untyped_untyped_unicode_cascade_bool(1, 1)
    False
    """
    return True if s1 == s2 == u"abcdefg" else False


# bytes/str comparison

@cython.test_assert_path_exists(
    '//CondExprNode',
    '//CondExprNode//PrimaryCmpNode',
    '//CondExprNode//PrimaryCmpNode[@operator = "=="]',
    '//CondExprNode//PrimaryCmpNode[@operator = "!="]',
)
def literal_compare_bytes_str():
    """
    >>> literal_compare_bytes_str()
    True
    """
    # we must not constant fold the subexpressions as the result is Py2/3 sensitive
    return b'abc' != 'abc' if IS_PY3 else b'abc' == 'abc'
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/strliterals.pyx0000644000175100001770000006361400000000000020666 0ustar00runnerdocker00000000000000__doc__ = ur"""
    >>> s1
    'abc\x11'
    >>> s1 == 'abc\x11'
    True
    >>> len(s1)
    4

    >>> s2
    'abc\\x11'
    >>> s2 == r'abc\x11'
    True
    >>> len(s2)
    7

    >>> s3
    'abc\\x11'
    >>> s3 == R'abc\x11'
    True
    >>> len(s3)
    7

    >>> s4
    b'abc\x11'
    >>> s4 == b'abc\x11'
    True
    >>> len(s4)
    4

    >>> s5
    b'abc\x11'
    >>> s5 == B'abc\x11'
    True
    >>> len(s5)
    4

    >>> s6
    b'abc\\x11'
    >>> s6 == br'abc\x11'
    True
    >>> len(s6)
    7

    >>> s7
    b'abc\\x11'
    >>> s7 == Br'abc\x11'
    True
    >>> len(s7)
    7

    >>> s8
    b'abc\\x11'
    >>> s8 == bR'abc\x11'
    True
    >>> len(s8)
    7

    >>> s9
    b'abc\\x11'
    >>> s9 == BR'abc\x11'
    True
    >>> len(s9)
    7

    >>> u1
    u'abc\x11'
    >>> u1 == u'abc\x11'
    True
    >>> len(u1)
    4

    >>> u2
    u'abc\x11'
    >>> u2 == U'abc\x11'
    True
    >>> len(u2)
    4

    >>> u3
    u'abc\\x11'
    >>> u3 == ur'abc\x11'
    True
    >>> len(u3)
    7

    >>> u4
    u'abc\\x11'
    >>> u4 == Ur'abc\x11'
    True
    >>> len(u4)
    7

    >>> u5
    u'abc\\x11'
    >>> u5 == uR'abc\x11'
    True
    >>> len(u5)
    7

    >>> u6
    u'abc\\x11'
    >>> u6 == UR'abc\x11'
    True
    >>> len(u6)
    7

    >>> sresc
    '\\12\\\'\\"\\\\'
    >>> sresc == r'\12\'\"\\'
    True
    >>> len(sresc)
    9

    >>> bresc
    b'\\12\\\'\\"\\\\'
    >>> bresc == br'\12\'\"\\'
    True
    >>> len(bresc)
    9

    >>> uresc
    u'\\12\\\'\\"\\\\'
    >>> uresc == ur'\12\'\"\\'
    True
    >>> len(uresc)
    9

    >>> bytes_uescape
    b'\\u1234\\U12345678\\u\\u1\\u12\\uX'
    >>> bytes_uescape == b'\\u1234\\U12345678\\u\\u1\\u12\\uX'
    True
    >>> len(bytes_uescape)
    28

    >>> (sys.version_info[0] >= 3 and sys.maxunicode == 1114111 and len(str_uescape) == 4 or
    ...  sys.version_info[0] >= 3 and sys.maxunicode == 65535   and len(str_uescape) == 5 or
    ...  sys.version_info[0] <  3 and len(str_uescape) == 28 or
    ...  len(str_uescape))
    True
    >>> (sys.version_info[0] >= 3 and str_uescape[0] == 'c' or
    ...  sys.version_info[0] <  3 and str_uescape[0] == '\\' or
    ...  str_uescape[0])
    True
    >>> print(str_uescape[-1])
    B
    >>> (sys.version_info[0] >= 3 and ord(str_uescape[-2]) == 0x2603 or
    ...  sys.version_info[0] <  3 and str_uescape[-12:-1]  == b'\\N{SNOWMAN}' or
    ...  sys.version_info[0] >= 3 and ord(str_uescape[-2]) or str_uescape[-12:-1])
    True

    >>> same_cname
    [b'abc\xf0_2', b'abc\xf0', b'abc\xf1', b'abc\xf2', b'abc\xf3', b'abc_2', b'abc_3']

    >>> newlines
    'Aaa\n'

    >>> len(long_escapes)
    3033
    >>> len(even_lots_of_slashes)
    3000
    >>> len(odd_lots_of_slashes)
    3001
    >>> len(lots_of_tabs_and_newlines)
    4321
"""

import sys
if sys.version_info[0] >= 3:
    __doc__ = __doc__.replace(u" u'", u" '").replace(u" U'", u" '").replace(u" ur'", u" r'").replace(u" uR'", u" R'").replace(u" Ur'", u" r'").replace(u" UR'", u" R'")
else:
    __doc__ = __doc__.replace(u" b'", u" '").replace(u" B'", u" '").replace(u" br'", u" r'").replace(u" bR'", u" R'").replace(u" Br'", u" r'").replace(u" BR'", u" R'").replace(u"[b'", u"['")

s1 = "abc\x11"
s2 = r"abc\x11"
s3 = R"abc\x11"
s4 = b"abc\x11"
s5 = B"abc\x11"
s6 = br"abc\x11"
s7 = Br"abc\x11"
s8 = bR"abc\x11"
s9 = BR"abc\x11"

# and in reversed order: r+b
s6_2 = rb"abc\x11"
s7_2 = rB"abc\x11"
s8_2 = Rb"abc\x11"
s9_2 = RB"abc\x11"

assert s6 == s6_2
assert s7 == s7_2
assert s8 == s8_2
assert s9 == s9_2

u1 = u"abc\x11"
u2 = U"abc\x11"
u3 = ur"abc\x11"
u4 = Ur"abc\x11"
u5 = uR"abc\x11"
u6 = UR"abc\x11"

sresc =  r'\12\'\"\\'
bresc = br'\12\'\"\\'
uresc = ur'\12\'\"\\'

bytes_uescape = b'\u1234\U12345678\u\u1\u12\uX'
str_uescape = '\u0063\U00012345\N{SNOWMAN}\x42'

same_cname = [b'abc\xf0_2', b'abc\xf0', b'abc\xf1', b'abc\xf2', b'abc\xf3', b'abc_2', b'abc_3']

newlines = "Aaa\n"

# T640, long literals with escapes
long_escapes = b"""\x31\x39\x37\x36\xe5\xb9\xb4\x39\xe6\x9c\x88\x39\xe6\x97\xa5\xef\xbc\x8c\xe5\x9c\xa8\xe6\xaf\x9b\xe6\xb3\xbd\xe4\xb8\x9c\xe9\x80\x9d\xe4\xb8\x96\xe4\xb9\x8b\xe5\x90\x8e\xef\xbc\x8c\xe4\xb8\xad\xe5\x9b\xbd\xe5\xbc\x80\xe5\xa7\x8b\xe7\x94\xb1\xe8\x87\xaa\xe7\x94\xb1\xe5\x8c\x96\xe7\x9f\xa5\xe8\xaf\x86\xe5\x88\x86\xe5\xad\x90\xe3\x80\x81\xe9\xa2\x86\xe5\xaf\xbc\xe9\x98\xb6\xe5\xb1\x82\xe7\x9a\x84\xe5\x85\xb7\xe6\x9c\x89\xe6\x94\xb9\xe9\x9d\xa9\xe6\x80\x9d\xe6\x83\xb3\xe7\x9a\x84\xe4\xba\xba\xe5\xa3\xab\xe5\x92\x8c\xe5\xb9\xbf\xe5\xa4\xa7\xe6\xb0\x91\xe9\x97\xb4\xe5\x85\xb1\xe5\x90\x8c\xe8\xbf\x9b\xe8\xa1\x8c\xe7\x9a\x84\xe2\x80\x9c\xe6\x80\x9d\xe6\x83\xb3\xe8\xa7\xa3\xe6\x94\xbe\xe2\x80\x9d\xe8\xbf\x90\xe5\x8a\xa8\xe3\x80\x82\x31\x39\x37\x38\xe5\xb9\xb4\xef\xbc\x8c\xe4\xb8\xad\xe5\x9b\xbd\xe5\x85\xb1\xe4\xba\xa7\xe5\x85\x9a\xe5\x8d\x81\xe4\xb8\x80\xe5\xb1\x8a\xe4\xb8\x89\xe4\xb8\xad\xe5\x85\xa8\xe4\xbc\x9a\xe6\x8f\x90\xe5\x87\xba\xe6\x94\xb9\xe9\x9d\xa9\xe5\xbc\x80\xe6\x94\xbe\xe7\x9a\x84\xe5\x9f\xba\xe6\x9c\xac\xe5\x9b\xbd\xe7\xad\x96\xef\xbc\x8c\xe4\xb8\xad\xe5\x9b\xbd\xe4\xba\xba\xe6\xb0\x91\xe5\xaf\xb9\xe5\x85\xb6\xe6\x9c\x89\xe8\x8e\xab\xe5\xa4\xa7\xe7\x9a\x84\xe6\x86\xa7\xe6\x86\xac\xef\xbc\x8c\xe5\xb8\x8c\xe6\x9c\x9b\xe6\x91\x86\xe8\x84\xb1\xe5\x8d\x81\xe5\xb9\xb4\xe6\x96\x87\xe9\x9d\xa9\xe7\x9a\x84\xe6\xb7\xb7\xe4\xb9\xb1\xe5\x8f\x8a\xe8\xbf\x87\xe5\x8e\xbb\xe7\x9a\x84\xe8\xb4\xab\xe7\xa9\xb7\xe3\x80\x82\x31\x39\x38\x35\xe5\xb9\xb4\xef\xbc\x8c\xe6\x94\xbf\xe5\xba\x9c\xe6\x89\xa9\xe5\xa4\xa7\xe4\xba\x86\xe4\xbc\x81\xe4\xb8\x9a\xe7\x9a\x84\xe8\x87\xaa\xe4\xb8\xbb\xe6\x9d\x83\xef\xbc\x8c\xe9\x81\xa3\xe8\xbf\x94\xe7\xa7\x81\xe8\x90\xa5\xe4\xbc\x81\xe4\xb8\x9a\xe4\xb8\xad\xe7\x9a\x84\xe5\x85\xac\xe6\x96\xb9\xe4\xbb\xa3\xe8\xa1\xa8\xef\xbc\x8c\xe5\xbc\x95\xe5\x85\xa5\xe5\xb8\x82\xe5\x9c\xba\xe7\xbb\x8f\xe6\xb5\x8e\xe4\xb8\xad\xe7\x9a\x84\xe8\xae\xb8\xe5\xa4\x9a\xe8\xa7\x82\xe5\xbf\xb5\xef\xbc\x8c\xe5\x8f\x91\xe5\xb1\x95\xe4\xb8\xba\xe7\xa4\xbe\xe4\xbc\x9a\xe4\xb8\xbb\xe4\xb9\x89\xe5\xb8\x82\xe5\x9c\xba\xe7\xbb\x8f\xe6\xb5\x8e\xef\xbc\x9b\xe4\xbd\x86\xe5\x90\x8c\xe6\x97\xb6\xe4\xba\xa6\xe5\x9c\xa8\xe5\x8e\x9f\xe6\x9c\x89\xe8\xae\xa1\xe5\x88\x92\xe7\xbb\x8f\xe6\xb5\x8e\xe7\x90\x86\xe8\xae\xba\xe9\x81\xad\xe5\x88\xb0\xe6\x8a\x9b\xe5\xbc\x83\xe7\x9a\x84\xe6\x83\x85\xe5\x86\xb5\xe4\xb8\x8b\xe5\xbc\x95\xe5\x8f\x91\xe4\xba\x86\xe5\x9b\xbd\xe5\x86\x85\xe6\xb0\x91\xe4\xbc\x97\xe7\x9a\x84\xe6\x80\x9d\xe6\x83\xb3\xe6\xb7\xb7\xe4\xb9\xb1\xe3\x80\x82\xe5\x8f\x8a\xe5\x90\x8e\xe5\x90\x84\xe5\x9c\xb0\xe5\x9b\xbd\xe8\x90\xa5\xe4\xbc\x81\xe4\xb8\x9a\xe5\x85\xb3\xe9\x97\xad\xef\xbc\x8c\xe5\x85\xa8\xe5\x9b\xbd\xe7\xba\xa6\xe6\x9c\x89\xe6\x95\xb0\xe7\x99\xbe\xe4\xb8\x87\xe5\xb7\xa5\xe4\xba\xba\xe5\xa4\xb1\xe4\xb8\x9a\xef\xbc\x8c\xe5\x9c\xa8\xe5\xbd\x93\xe6\x97\xb6\xe4\xb8\xad\xe5\x9b\xbd\xe6\x94\xbf\xe5\xba\x9c\xe5\x8f\x97\xe5\x88\xb0\xe4\xba\x86\xe6\x9e\x81\xe5\xa4\xa7\xe5\x86\xb2\xe5\x87\xbb\xe3\x80\x82\xe5\x90\x8c\xe6\x97\xb6\xe4\xba\xa6\xe5\xbc\x95\xe5\x8f\x91\xe8\xb4\xaa\xe6\xb1\xa1\xe8\x85\x90\xe8\xb4\xa5\xe7\x89\xa9\xe4\xbb\xb7\xe5\x8d\x87\xe6\xb6\xa8\xe7\xad\x89\xe9\x97\xae\xe9\xa2\x98\xef\xbc\x8c\xe5\x9c\xa8\xe6\xb0\x91\xe9\x97\xb4\xe9\x80\xa0\xe6\x88\x90\xe4\xb8\x80\xe5\xae\x9a\xe7\x9a\x84\xe4\xb8\x8d\xe6\xbb\xa1\xe3\x80\x82\x5b\x31\x5d\x5b\x32\x5d\x32\x30\xe4\xb8\x96\xe7\xba\xaa\x38\x30\xe5\xb9\xb4\xe4\xbb\xa3\xef\xbc\x8c\xe4\xb8\x96\xe7\x95\x8c\xe6\xad\xa3\xe5\xa4\x84\xe4\xba\x8e\xe5\x86\xb7\xe6\x88\x98\xe7\x9a\x84\xe6\x9c\x80\xe5\x90\x8e\xe9\x98\xb6\xe6\xae\xb5\xe3\x80\x82\x31\x39\x38\x35\xe5\xb9\xb4\xef\xbc\x8c\xe8\x8b\x8f\xe5\x85\xb1\xe4\xb8\xad\xe5\xa4\xae\xe6\x80\xbb\xe4\xb9\xa6\xe8\xae\xb0\xe6\x88\x88\xe5\xb0\x94\xe5\xb7\xb4\xe4\xb9\x94\xe5\xa4\xab\xe4\xb8\x8a\xe5\x8f\xb0\xef\xbc\x8c\xe6\x8e\xa8\xe8\xa1\x8c\xe4\xbb\xa5\xe4\xba\xba\xe9\x81\x93\xe4\xb8\xbb\xe4\xb9\x89\xe4\xb8\xba\xe6\xa0\xb8\xe5\xbf\x83\xe7\x9a\x84\xe2\x80\x9c\xe6\x96\xb0\xe6\x80\x9d\xe7\xbb\xb4\xe2\x80\x9d\xe8\xbf\x90\xe5\x8a\xa8\xef\xbc\x8c\xe5\x9c\xa8\xe7\xa4\xbe\xe4\xbc\x9a\xe4\xb8\xbb\xe4\xb9\x89\xe9\x98\xb5\xe8\x90\xa5\xe5\x86\x85\xe4\xba\xa7\xe7\x94\x9f\xe5\xb9\xbf\xe6\xb3\x9b\xe5\xbd\xb1\xe5\x93\x8d\xe3\x80\x82\xe8\xa2\xab\xe5\x8c\x97\xe4\xba\xac\xe6\x94\xbf\xe5\xba\x9c\xe7\xa7\xb0\xe2\x80\x9c\xe8\xb5\x84\xe4\xba\xa7\xe9\x98\xb6\xe7\xba\xa7\xe8\x87\xaa\xe7\x94\xb1\xe5\x8c\x96\xe2\x80\x9d\xe6\x80\x9d\xe6\x83\xb3\xe7\x9a\x84\xe8\xa5\xbf\xe6\x96\xb9\xe6\xb0\x91\xe4\xb8\xbb\xe6\x80\x9d\xe6\xbd\xae\xe4\xb9\x9f\xe5\x9c\xa8\xe4\xb8\xad\xe5\x9b\xbd\xe5\xbe\x97\xe5\x88\xb0\xe5\xb9\xbf\xe6\xb3\x9b\xe4\xbc\xa0\xe6\x92\xad\xe3\x80\x82\xe5\xbe\x88\xe5\xa4\x9a\xe4\xba\xba\xe8\xae\xa4\xe4\xb8\xba\xe9\x9a\x8f\xe7\x9d\x80\xe6\x94\xb9\xe9\x9d\xa9\xe5\xbc\x80\xe6\x94\xbe\xe4\xbb\xa5\xe5\x8f\x8a\xe5\xb8\x82\xe5\x9c\xba\xe7\xbb\x8f\xe6\xb5\x8e\xe7\x90\x86\xe5\xbf\xb5\xe7\x9a\x84\xe5\xbc\x95\xe5\x85\xa5\xef\xbc\x8c\xe5\xae\xa3\xe5\x91\x8a\xe4\xb8\xad\xe5\x9b\xbd\xe5\x85\xb1\xe4\xba\xa7\xe5\x85\x9a\xe8\x83\x8c\xe5\xbc\x83\xe4\xba\x86\xe9\xa9\xac\xe5\x88\x97\xe4\xb8\xbb\xe4\xb9\x89\xe7\x9a\x84\xe5\x9f\xba\xe6\x9c\xac\xe4\xbf\xa1\xe6\x9d\xa1\xef\xbc\x8c\xe4\xb8\xad\xe5\x9b\xbd\xe5\xb7\xb2\xe4\xb8\x8d\xe5\x86\x8d\xe6\x98\xaf\xe4\xb8\x80\xe4\xb8\xaa\xe7\xa4\xbe\xe4\xbc\x9a\xe4\xb8\xbb\xe4\xb9\x89\xe5\x9b\xbd\xe5\xae\xb6\xef\xbc\x8c\xe8\x80\x8c\xe6\x98\xaf\xe5\x85\xb7\xe6\x9c\x89\xe6\x9f\x90\xe7\xa7\x8d\xe8\xb5\x84\xe6\x9c\xac\xe4\xb8\xbb\xe4\xb9\x89\xe6\x80\xa7\xe8\xb4\xa8\xe7\x9a\x84\xe7\xa4\xbe\xe4\xbc\x9a\xe3\x80\x82\x31\x39\x38\x38\xe5\xb9\xb4\xef\xbc\x8c\xe5\x85\xac\xe5\xbc\x80\xe5\x91\xbc\xe5\x94\xa4\xe2\x80\x9c\xe8\x94\x9a\xe8\x93\x9d\xe8\x89\xb2\xe2\x80\x9d\xe8\xa5\xbf\xe6\x96\xb9\xe6\x96\x87\xe6\x98\x8e\xe7\x9a\x84\xe6\x94\xbf\xe8\xae\xba\xe7\x94\xb5\xe8\xa7\x86\xe7\x89\x87\xe3\x80\x8a\xe6\xb2\xb3\xe6\xae\x87\xe3\x80\x8b\xe5\x9c\xa8\xe4\xb8\xad\xe5\xa4\xae\xe7\x94\xb5\xe8\xa7\x86\xe5\x8f\xb0\xe5\x85\xac\xe5\xbc\x80\xe6\x92\xad\xe5\x87\xba\xef\xbc\x8c\xe5\x9c\xa8\xe5\x85\xa8\xe5\x9b\xbd\xe8\x8c\x83\xe5\x9b\xb4\xe5\x86\x85\xe5\xbc\x95\xe8\xb5\xb7\xe8\xbd\xb0\xe5\x8a\xa8\xef\xbc\x8c\xe6\x88\x90\xe4\xb8\xba\xe5\x85\xad\xe5\x9b\x9b\xe8\xbf\x90\xe5\x8a\xa8\xe7\x9a\x84\xe6\x80\x9d\xe6\x83\xb3\xe5\x89\x8d\xe5\xaf\xbc\xe3\x80\x82\xe9\x9a\x8f\xe7\x9d\x80\xe4\xb8\xad\xe5\x9b\xbd\xe7\x9a\x84\xe5\xbc\x80\xe6\x94\xbe\xef\xbc\x8c\xe4\xb8\xad\xe5\x9b\xbd\xe4\xba\xba\xe5\xbc\x80\xe5\xa7\x8b\xe6\x9b\xb4\xe5\xa4\x9a\xe5\x9c\xb0\xe6\x8e\xa5\xe8\xa7\xa6\xe8\xa5\xbf\xe6\x96\xb9\xe6\xb0\x91\xe4\xb8\xbb\xe4\xba\xba\xe6\x9d\x83\xe6\x80\x9d\xe6\x83\xb3\xef\xbc\x8c\xe5\xbe\x88\xe5\xa4\x9a\xe7\x9f\xa5\xe8\xaf\x86\xe5\x88\x86\xe5\xad\x90\xe5\xbc\x80\xe5\xa7\x8b\xe5\x85\xac\xe5\xbc\x80\xe6\x8f\x90\xe5\x80\xa1\xe4\xba\xba\xe6\x9d\x83\xe4\xb8\x8e\xe6\xb0\x91\xe4\xb8\xbb\xef\xbc\x8c\xe8\xae\xb8\xe5\xa4\x9a\xe5\xad\xa6\xe7\x94\x9f\xe6\x9b\xb4\xe6\x98\xaf\xe9\x80\x9a\xe8\xbf\x87\xe5\x90\x84\xe7\xa7\x8d\xe5\xbd\xa2\xe5\xbc\x8f\xe8\xa1\xa8\xe8\xbe\xbe\xe8\xbf\x99\xe6\x96\xb9\xe9\x9d\xa2\xe7\x9a\x84\xe8\xaf\x89\xe6\xb1\x82\xe3\x80\x82\xe4\xbb\x8e\xe4\xb8\x96\xe7\x95\x8c\xe8\x8c\x83\xe5\x9b\xb4\xe5\x86\x85\xe7\x9c\x8b\xef\xbc\x8c\xe5\x85\xad\xe5\x9b\x9b\xe8\xbf\x90\xe5\x8a\xa8\xe5\xb9\xb6\xe9\x9d\x9e\xe6\x98\xaf\xe4\xb8\x80\xe4\xb8\xaa\xe5\xad\xa4\xe7\xab\x8b\xe7\x9a\x84\xe4\xba\x8b\xe4\xbb\xb6\xef\xbc\x8c\xe8\x80\x8c\xe6\x98\xaf\xe5\xbd\x93\xe6\x97\xb6\xe6\x95\xb4\xe4\xb8\xaa\xe7\xa4\xbe\xe4\xbc\x9a\xe4\xb8\xbb\xe4\xb9\x89\xe9\x98\xb5\xe8\x90\xa5\xe5\x86\x85\xe6\xb0\x91\xe4\xb8\xbb\xe8\xbf\x90\xe5\x8a\xa8\xe7\x9a\x84\xe4\xb8\x80\xe4\xb8\xaa\xe9\x87\x8d\xe8\xa6\x81\xe7\x8e\xaf\xe8\x8a\x82\xe3\x80\x82\xe5\x9c\xa8\xe5\x85\xad\xe5\x9b\x9b\xe4\xba\x8b\xe4\xbb\xb6\xe5\x8f\x91\xe7\x94\x9f\xe7\x9a\x84\xe5\x90\x8c\xe4\xb8\x80\xe5\xa4\xa9\xef\xbc\x8c\xe6\xb3\xa2\xe5\x85\xb0\xe5\x9b\xa2\xe7\xbb\x93\xe5\xb7\xa5\xe4\xbc\x9a\xe5\x9c\xa8\xe5\xa4\xa7\xe9\x80\x89\xe4\xb8\xad\xe8\x8e\xb7\xe8\x83\x9c\xef\xbc\x8c\xe6\x8e\xa8\xe7\xbf\xbb\xe7\xa4\xbe\xe4\xbc\x9a\xe4\xb8\xbb\xe4\xb9\x89\xe5\x88\xb6\xe5\xba\xa6\xe3\x80\x82\xe9\x9a\x8f\xe5\x90\x8e\xe4\xb8\x8d\xe5\x88\xb0\xe4\xb8\x80\xe5\xb9\xb4\xef\xbc\x8c\xe4\xb8\x9c\xe6\xac\xa7\xe7\xa4\xbe\xe4\xbc\x9a\xe4\xb8\xbb\xe4\xb9\x89\xe5\x9b\xbd\xe5\xae\xb6\xe4\xb9\x9f\xe5\x85\x88\xe5\x90\x8e\xe5\x8f\x91\xe7\x94\x9f\xe5\x92\x8c\xe5\xb9\xb3\xe6\xbc\x94\xe5\x8f\x98\xef\xbc\x8c\xe4\xb8\xa4\xe5\xb9\xb4\xe5\x90\x8e\xe8\x8b\x8f\xe8\x81\x94\xe4\xba\xa6\xe5\xae\xa3\xe5\x91\x8a\xe8\xa7\xa3\xe4\xbd\x93\xef\xbc\x8c\xe7\xa4\xbe\xe4\xbc\x9a\xe4\xb8\xbb\xe4\xb9\x89\xe9\x98\xb5\xe8\x90\xa5\xe8\xa7\xa3\xe4\xbd\x93\xe3\x80\x82\xe8\xbf\x99\xe4\xba\x9b\xe5\xae\x9e\xe8\xa1\x8c\xe7\xa4\xbe\xe4\xbc\x9a\xe4\xb8\xbb\xe4\xb9\x89\xe5\x88\xb6\xe5\xba\xa6\xe7\x9a\x84\xe5\x9b\xbd\xe5\xae\xb6\xe5\x9c\xa8\xe4\xb8\x8d\xe5\x88\xb0\x35\xe5\xb9\xb4\xe7\x9a\x84\xe6\x97\xb6\xe9\x97\xb4\xe4\xb8\xad\xe5\x8f\x91\xe7\x94\x9f\xe4\xba\x86\xe6\x94\xbf\xe6\x9d\x83\xe8\xbd\xae\xe6\x9b\xbf\xef\xbc\x8c\xe5\xb9\xb6\xe6\x94\xb9\xe5\x8f\x98\xe4\xba\x86\xe5\x8e\x9f\xe6\x9c\x89\xe7\x9a\x84\xe6\x94\xbf\xe6\xb2\xbb\xe4\xbd\x93\xe5\x88\xb6\xe3\x80\x82\x31\x39\x38\x37\xe5\xb9\xb4\x31\xe6\x9c\x88\xef\xbc\x8c\xe5\x8e\x9f\xe6\x9c\xac\xe8\xa2\xab\xe9\x82\x93\xe5\xb0\x8f\xe5\xb9\xb3\xe9\x80\x89\xe5\xae\x9a\xe4\xb8\xba\xe6\x8e\xa5\xe7\x8f\xad\xe4\xba\xba\xe7\x9a\x84\xe8\x83\xa1\xe8\x80\x80\xe9\x82\xa6\xe8\xa2\xab\xe8\xbf\xab\xe4\xb8\x8b\xe5\x8f\xb0\xef\xbc\x8c\xe4\xbb\x96\xe8\xa2\xab\xe6\x8c\x87\xe8\xbf\x9d\xe5\x8f\x8d\xe4\xb8\xad\xe5\x9b\xbd\xe5\x85\xb1\xe4\xba\xa7\xe5\x85\x9a\xe7\x9a\x84\xe6\xb0\x91\xe4\xb8\xbb\xe9\x9b\x86\xe4\xb8\xad\xe5\x88\xb6\xef\xbc\x8c\xe7\xba\xb5\xe5\xae\xb9\xe8\xb5\x84\xe4\xba\xa7\xe9\x98\xb6\xe7\xba\xa7\xe8\x87\xaa\xe7\x94\xb1\xe5\x8c\x96\xef\xbc\x8c\xe6\xb2\xa1\xe6\x9c\x89\xe5\xaf\xb9\xe6\xb8\xb8\xe8\xa1\x8c\xe9\x87\x87\xe5\x8f\x96\xe6\x9c\x89\xe6\x95\x88\xe6\x8e\xaa\xe6\x96\xbd\xef\xbc\x8c\xe8\xa6\x81\xe5\xaf\xb9\x31\x39\x38\x36\xe5\xb9\xb4\xe5\xad\xa6\xe7\x94\x9f\xe8\xbf\x90\xe5\x8a\xa8\xe7\x9a\x84\xe5\xa4\xb1\xe6\x8e\xa7\xe8\xb4\x9f\xe8\xb4\xa3\xe3\x80\x82\xe5\x8f\x8a\xe5\x90\x8e\xe4\xb8\xad\xe5\x85\xb1\xe5\x85\x9a\xe5\x86\x85\xe5\x8f\x8d\xe6\x94\xb9\xe9\x9d\xa9\xe7\x9a\x84\xe2\x80\x9c\xe4\xbf\x9d\xe5\xae\x88\xe2\x80\x9d\xe5\x8a\xbf\xe5\x8a\x9b\xe6\x8e\x80\xe8\xb5\xb7\xe4\xb8\x80\xe8\x82\xa1\xe5\x8f\x8d\xe5\x8f\xb3\xe6\xb5\xaa\xe6\xbd\xae\xe3\x80\x82\x0a\x0a\xe6\xb3\x95\xe8\xbd\xae\xe5\x8a\x9f\xe5\x8f\x88\xe7\xa7\xb0\xe6\xb3\x95\xe8\xbd\xae\xe5\xa4\xa7\xe6\xb3\x95\xef\xbc\x8c\xe6\xb3\x95\xe8\xbd\xae\xe5\x8a\x9f\xe5\x8a\x9f\xe6\xb3\x95\xe6\x98\xaf\xe7\x94\xb1\xe4\xba\x94\xe5\xa5\x97\xe5\x8a\xa8\xe4\xbd\x9c\xe7\xbb\x84\xe6\x88\x90\xef\xbc\x8c\xe4\xbd\x86\xe4\xb8\x8d\xe5\x90\x8c\xe4\xba\x8e\xe4\xb8\x80\xe8\x88\xac\xe6\xb0\x94\xe5\x8a\x9f\xe7\x9a\x84\xe6\x98\xaf\xe7\x9d\x80\xe9\x87\x8d\xe5\xbf\x83\xe6\x80\xa7\xe7\x9a\x84\xe4\xbf\xae\xe7\x82\xbc\xef\xbc\x8c\xe5\x8d\xb3\xe2\x80\x9c\xe7\x9c\x9f\xe3\x80\x81\xe5\x96\x84\xe3\x80\x81\xe5\xbf\x8d\xe2\x80\x9d\xe7\x9a\x84\xe5\x8e\x9f\xe5\x88\x99\xe3\x80\x82\xe4\xb8\x80\xe4\xba\x9b\xe4\xba\xba\xe8\xae\xa4\xe4\xb8\xba\xe6\xb3\x95\xe8\xbd\xae\xe5\x8a\x9f\xe5\x80\x9f\xe7\x94\xa8\xe4\xba\x86\xe5\xbe\x88\xe5\xa4\x9a\xe4\xbd\x9b\xe6\x95\x99\xe8\xa7\x82\xe5\xbf\xb5\xef\xbc\x8c\xe5\xa6\x82\xe6\xb3\x95\xe8\xbd\xae\xe3\x80\x81\xe4\xb8\x9a\xe7\xad\x89\xef\xbc\x8c\xe5\x9b\xa0\xe8\x80\x8c\xe8\xa7\x86\xe4\xb9\x8b\xe4\xb8\xba\xe4\xb8\x80\xe7\xa7\x8d\xe5\xae\x97\xe6\x95\x99\xe3\x80\x82\xe4\xbd\x86\xe6\xb3\x95\xe8\xbd\xae\xe5\x8a\x9f\xe5\xad\xa6\xe5\x91\x98\xe8\xae\xa4\xe4\xb8\xba\xe2\x80\x9c\xe6\xb3\x95\xe8\xbd\xae\xe2\x80\x9d\xe5\x92\x8c\xe2\x80\x9c\xe4\xb8\x9a\xe2\x80\x9d\xe9\x83\xbd\xe4\xb8\x8d\xe6\x98\xaf\xe4\xbd\x9b\xe6\x95\x99\xe4\xb8\x93\xe7\x94\xa8\xe7\x9a\x84\xef\xbc\x8c\xe5\x85\xb6\xe4\xb8\xad\xe4\xb8\x9a\xe7\x9a\x84\xe6\xa6\x82\xe5\xbf\xb5\xe5\x9c\xa8\xe5\xa9\x86\xe7\xbd\x97\xe9\x97\xa8\xe6\x95\x99\xe6\x88\x96\xe6\x9b\xb4\xe6\x97\xa9\xe7\x9a\x84\xe4\xbf\xae\xe7\x82\xbc\xe6\x96\xb9\xe6\xb3\x95\xe5\x92\x8c\xe5\xae\x97\xe6\x95\x99\xe5\xb0\xb1\xe5\xb7\xb2\xe7\xbb\x8f\xe5\xad\x98\xe5\x9c\xa8\xe4\xba\x86\xe3\x80\x82\x0a\x0a\xe5\x8f\xb0\xe7\x8b\xac\xe5\x95\x8a\xe5\x8f\xb0\xe7\x8b\xac\xe4\xb8\x80\xe5\x8f\xb0\xe7\x8b\xac\xe7\xab\x8b\xe6\x9c\x8d\xe5\x8a\xa1\xe5\x99\xa8\x0a\x0a"""

even_lots_of_slashes = r"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"

odd_lots_of_slashes = r"0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"

lots_of_tabs_and_newlines = r'0\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n'
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/strmethods.pyx0000644000175100001770000000744600000000000020513 0ustar00runnerdocker00000000000000cimport cython

@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
def str_startswith(str s, sub, start=None, stop=None):
    """
    >>> str_startswith('a', 'a')
    True
    >>> str_startswith('ab', 'a')
    True
    >>> str_startswith('a', 'b')
    False
    >>> str_startswith('ab', 'b')
    False
    >>> str_startswith('a', ('a', 'b'))
    True
    >>> str_startswith('a', 'a', 1)
    False
    >>> str_startswith('a', 'a', 0, 0)
    False
    """

    if start is None:
      return s.startswith(sub)
    elif stop is None:
      return s.startswith(sub, start)
    else:
      return s.startswith(sub, start, stop)

@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
def str_endswith(str s, sub, start=None, stop=None):
    """
    >>> str_endswith('a', 'a')
    True
    >>> str_endswith('ba', 'a')
    True
    >>> str_endswith('a', 'b')
    False
    >>> str_endswith('ba', 'b')
    False
    >>> str_endswith('a', ('a', 'b'))
    True
    >>> str_endswith('a', 'a', 1)
    False
    >>> str_endswith('a', 'a', 0, 0)
    False
    """

    if start is None:
      return s.endswith(sub)
    elif stop is None:
      return s.endswith(sub, start)
    else:
      return s.endswith(sub, start, stop)


def object_as_name(object):
    """
    >>> object_as_name('abx')
    True
    >>> object_as_name('abc')
    False
    """
    return object.endswith("x")


def str_as_name(str):
    """
    >>> str_as_name('abx')
    True
    >>> str_as_name('abc')
    False
    """
    return str.endswith("x")


@cython.test_assert_path_exists(
    "//SimpleCallNode",
    "//SimpleCallNode//NoneCheckNode",
    "//SimpleCallNode//AttributeNode[@is_py_attr = false]")
def str_join(str s, args):
    """
    >>> print(str_join('a', list('bbb')))
    babab
    """
    result = s.join(args)
    assert cython.typeof(result) == 'basestring object', cython.typeof(result)
    return result


@cython.test_fail_if_path_exists(
    "//SimpleCallNode//NoneCheckNode",
)
@cython.test_assert_path_exists(
    "//SimpleCallNode",
    "//SimpleCallNode//AttributeNode[@is_py_attr = false]")
def literal_join(args):
    """
    >>> print(literal_join(list('abcdefg')))
    a|b|c|d|e|f|g
    """
    result = '|'.join(args)
    assert cython.typeof(result) == 'basestring object', cython.typeof(result)
    return result


# unicode.__mod__(format, values)

format1 = 'abc%sdef'
format2 = 'abc%sdef%sghi'

def mod_format(str s, values):
    """
    >>> mod_format(format1, 'sa') == 'abcsadef'  or  mod_format(format1, 'sa')
    True
    >>> mod_format(format2, ('XYZ', 'ABC')) == 'abcXYZdefABCghi'  or  mod_format(format2, ('XYZ', 'ABC'))
    True
    >>> mod_format(None, 'sa')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...NoneType...
    >>> class RMod(object):
    ...     def __rmod__(self, other):
    ...         return 123
    >>> mod_format(None, RMod())
    123
    """
    assert cython.typeof(s % values) == 'basestring object', cython.typeof(s % values)
    return s % values


def mod_format_literal(values):
    """
    >>> mod_format_literal('sa') == 'abcsadef'  or  mod_format(format1, 'sa')
    True
    >>> mod_format_literal(('sa',)) == 'abcsadef'  or  mod_format(format1, ('sa',))
    True
    >>> mod_format_literal(['sa']) == "abc['sa']def"  or  mod_format(format1, ['sa'])
    True
    """
    assert cython.typeof('abc%sdef' % values) == 'basestring object', cython.typeof('abc%sdef' % values)
    return 'abc%sdef' % values


def mod_format_tuple(*values):
    """
    >>> mod_format_tuple('sa') == 'abcsadef'  or  mod_format(format1, 'sa')
    True
    >>> mod_format_tuple()
    Traceback (most recent call last):
    TypeError: not enough arguments for format string
    """
    assert cython.typeof('abc%sdef' % values) == 'basestring object', cython.typeof('abc%sdef' % values)
    return 'abc%sdef' % values
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/struct_conversion.pyx0000644000175100001770000001211100000000000022071 0ustar00runnerdocker00000000000000cdef struct Point:
    double x
    double y
    int color

def test_constructor(x, y, int color):
    """
    >>> sorted(test_constructor(1,2,255).items())
    [('color', 255), ('x', 1.0), ('y', 2.0)]
    >>> try: test_constructor(1,None,255)
    ... except TypeError: pass
    """
    cdef Point p = Point(x, y, color)
    return p


def return_constructor(x, y, int color):
    """
    >>> sorted(return_constructor(1,2,255).items())
    [('color', 255), ('x', 1.0), ('y', 2.0)]
    >>> try: return_constructor(1, None, 255)
    ... except TypeError: pass
    """
    return Point(x, y, color)


def test_constructor_kwds(x, y, color):
    """
    >>> sorted(test_constructor_kwds(1.25, 2.5, 128).items())
    [('color', 128), ('x', 1.25), ('y', 2.5)]
    >>> test_constructor_kwds(1.25, 2.5, None)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError:... int...
    """
    cdef Point p = Point(x=x, y=y, color=color)
    return p


def return_constructor_kwds(double x, y, color):
    """
    >>> sorted(return_constructor_kwds(1.25, 2.5, 128).items())
    [('color', 128), ('x', 1.25), ('y', 2.5)]
    >>> return_constructor_kwds(1.25, 2.5, None)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError:... int...
    """
    return Point(x=x, y=y, color=color)


def test_dict_construction(x, y, color):
    """
    >>> sorted(test_dict_construction(4, 5, 64).items())
    [('color', 64), ('x', 4.0), ('y', 5.0)]
    >>> try: test_dict_construction("foo", 5, 64)
    ... except TypeError: pass
    """
    cdef Point p = {'color': color, 'x': x, 'y': y}
    return p

def test_list_construction(x, y, color):
    """
    >>> sorted(test_list_construction(4, 5, 64).items())
    [('color', 64), ('x', 4.0), ('y', 5.0)]
    >>> try: test_list_construction("foo", 5, 64)
    ... except TypeError: pass
    """
    cdef Point p = [x, y, color]
    return p

'''
# FIXME: make this work
def test_tuple_construction(x, y, color):
    """
    >>> sorted(test_tuple_construction(4, 5, 64).items())
    [('color', 64), ('x', 4.0), ('y', 5.0)]
    >>> try: test_tuple_construction("foo", 5, 64)
    ... except TypeError: pass
    """
    cdef Point p = (x, y, color)
    return p
'''

cdef union int_or_float:
    int n
    double x

def test_union_constructor(n,x):
    """
    >>> test_union_constructor(1, None)
    1
    >>> test_union_constructor(None, 2.0)
    2.0
    """
    cdef int_or_float u
    if n is None:
        u = int_or_float(x=x)
        return u.x
    else:
        u = int_or_float(n=n)
        return u.n

cdef struct with_pointers:
    bint is_integral
    int_or_float data
    void* ptr

def test_pointers(int n, double x):
    """
    >>> test_pointers(100, 2.71828)
    100
    2.71828
    True
    """
    cdef with_pointers a = [True, {'n': n}, NULL]
    cdef with_pointers b = with_pointers(False, {'x': x}, NULL)
    print a.data.n
    print b.data.x
    print a.ptr == b.ptr == NULL

cdef struct MyStruct:
    char c
    int i
    float f
    char *s

bhello = b"hello"  # must hold a C reference in PyPy

def test_obj_to_struct(MyStruct mystruct):
    """
    >>> test_obj_to_struct(dict(c=10, i=20, f=6.7, s=bhello))
    c=10 i=20 f=6.70 s=hello
    >>> test_obj_to_struct(None)
    Traceback (most recent call last):
       ...
    TypeError: Expected a mapping, got NoneType
    >>> test_obj_to_struct(dict(s=b"world"))
    Traceback (most recent call last):
       ...
    ValueError: No value specified for struct attribute 'c'
    >>> test_obj_to_struct(dict(c=b"world"))
    Traceback (most recent call last):
       ...
    TypeError: an integer is required
    """
    print 'c=%d i=%d f=%.2f s=%s' % (mystruct.c, mystruct.i, mystruct.f, mystruct.s.decode('ascii'))

cdef struct NestedStruct:
    MyStruct mystruct
    double d

def test_nested_obj_to_struct(NestedStruct nested):
    """
    >>> test_nested_obj_to_struct(dict(mystruct=dict(c=10, i=20, f=6.7, s=bhello), d=4.5))
    c=10 i=20 f=6.70 s=hello d=4.50
    >>> test_nested_obj_to_struct(dict(d=7.6))
    Traceback (most recent call last):
       ...
    ValueError: No value specified for struct attribute 'mystruct'
    >>> test_nested_obj_to_struct(dict(mystruct={}, d=7.6))
    Traceback (most recent call last):
       ...
    ValueError: No value specified for struct attribute 'c'
    """
    print 'c=%d i=%d f=%.2f s=%s d=%.2f' % (nested.mystruct.c,
                                            nested.mystruct.i,
                                            nested.mystruct.f,
                                            nested.mystruct.s.decode('UTF-8'),
                                            nested.d)

cdef struct OverriddenCname:
    int x "not_x"

def test_obj_to_struct_cnames(OverriddenCname s):
    """
    >>> test_obj_to_struct_cnames({ 'x': 1 })
    1
    """
    print(s.x)

def test_struct_to_obj_cnames():
    """
    >>> test_struct_to_obj_cnames()
    {'x': 2}
    """
    return OverriddenCname(2)

cdef struct ArrayFieldStruct:
    int arr[4]

def test_array_field_init():
    """
    >>> test_array_field_init()
    [1, 2, 3, 4]
    """
    cdef ArrayFieldStruct s = ArrayFieldStruct([1, 2, 3, 4])
    print(s.arr);
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/struct_conversion_extern.pyx0000644000175100001770000000105300000000000023461 0ustar00runnerdocker00000000000000"""
Note: this tests if the necessary utility code is included in the module env,
despite potentially being already created before.
"""

cdef extern from "struct_conversion_extern_header.h":
    cdef struct my_date_t:
        int year
        int month
        int day


def test_extern_struct():
    """
    >>> test_extern_struct()
    [('day', 24), ('month', 6), ('year', 2000)]
    """
    cdef my_date_t day = my_date_t(year=2000, month=6, day=24)
    cdef object d = day
    assert type(d) is dict
    assert d == day
    return sorted(day.items())
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/struct_conversion_extern_header.h0000644000175100001770000000010000000000000024370 0ustar00runnerdocker00000000000000struct my_date_t {
    int year;
    int month;
    int day;
};
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/subclasses.pyx0000644000175100001770000000230700000000000020455 0ustar00runnerdocker00000000000000cdef class Base0:
    pass

cdef class Base(Base0):
    pass

cdef class Foo(Base):
   cdef fooit(self):
       return 42

cdef class Bar(Foo):
   pass

cdef class Bam(Bar):
   pass

cdef class Zoo(Bam):
   pass


def fooit(Foo foo):
    """
    >>> zoo = Zoo()
    >>> for cl in (Zoo, Bam, Bar, Foo, Base, Base0): assert isinstance(zoo, cl)
    >>> fooit(zoo)
    42
    >>> bam = Bam()
    >>> for cl in (Bam, Bar, Foo, Base, Base0): assert isinstance(bam, cl)
    >>> fooit(bam)
    42
    >>> bar = Bar()
    >>> for cl in (Bar, Foo, Base, Base0): assert isinstance(bar, cl)
    >>> fooit(bar)
    42
    >>> foo = Foo()
    >>> for cl in (Foo, Base, Base0): assert isinstance(foo, cl)
    >>> fooit(foo)
    42
    >>> base = Base()
    >>> for cl in (Base, Base0): assert isinstance(base, cl)
    >>> fooit(base)
    Traceback (most recent call last):
    TypeError: Argument 'foo' has incorrect type (expected subclasses.Foo, got subclasses.Base)
    >>> base0 = Base0()
    >>> for cl in (Base0,): assert isinstance(base0, cl)
    >>> fooit(base0)
    Traceback (most recent call last):
    TypeError: Argument 'foo' has incorrect type (expected subclasses.Foo, got subclasses.Base0)
    """
    return foo.fooit()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/subop.pyx0000644000175100001770000000734100000000000017441 0ustar00runnerdocker00000000000000cimport cython


def bigint(x):
    print(str(x).rstrip('L'))


def mixed_test():
    """
    >>> mixed_test()
    (-1, -1)
    """
    cdef int int1, int2, int3
    obj1 = 1
    obj2 = 2
    obj3 = 3
    int2 = 2
    int3 = 3

    int1 = int2 - int3
    obj1 = obj2 - int3
    return int1, obj1


def pointer_test():
    """
    >>> pointer_test()
    0
    """
    cdef int int1, int2, int3
    cdef char *ptr1, *ptr2, *ptr3
    int2 = 2
    int3 = 3
    ptr2 = "test"
    ptr3 = ptr2

    ptr1 = ptr2 - int3
    int1 = ptr2 - ptr3
    return int1


@cython.test_fail_if_path_exists('//SubNode')
def sub_x_1(x):
    """
    >>> sub_x_1(0)
    -1
    >>> sub_x_1(1)
    0
    >>> sub_x_1(-1)
    -2
    >>> bigint(2**50 - 1)
    1125899906842623
    >>> bigint(sub_x_1(2**50))
    1125899906842623
    >>> sub_x_1(1.5)
    0.5
    >>> sub_x_1(-1.5)
    -2.5
    >>> try: sub_x_1("abc")
    ... except TypeError: pass
    """
    return x - 1


@cython.test_fail_if_path_exists('//SubNode')
def sub_x_1f(x):
    """
    >>> sub_x_1f(0)
    -1.0
    >>> sub_x_1f(1)
    0.0
    >>> sub_x_1f(-1)
    -2.0
    >>> 2**52 - 1.0
    4503599627370495.0
    >>> sub_x_1f(2**52)
    4503599627370495.0
    >>> sub_x_1f(2**60) == 2**60 - 1.0 or sub_x_1f(2**60)
    True
    >>> sub_x_1f(1.5)
    0.5
    >>> sub_x_1f(-1.5)
    -2.5
    >>> try: sub_x_1f("abc")
    ... except TypeError: pass
    """
    return x - 1.0


@cython.test_fail_if_path_exists('//SubNode')
def sub_x_large(x):
    """
    >>> sub_x_large(0)
    -1073741824
    >>> sub_x_large(1)
    -1073741823
    >>> sub_x_large(-1)
    -1073741825
    >>> bigint(2**50 - 2**30)
    1125898833100800
    >>> bigint(sub_x_large(2**50))
    1125898833100800
    >>> sub_x_large(2.0**30)
    0.0
    >>> sub_x_large(2.0**30 + 1)
    1.0
    >>> sub_x_large(2.0**30 - 1)
    -1.0
    >>> 2.0 ** 31 - 2**30
    1073741824.0
    >>> sub_x_large(2.0**31)
    1073741824.0
    >>> try: sub_x_large("abc")
    ... except TypeError: pass
    """
    return x - 2**30


@cython.test_fail_if_path_exists('//SubNode')
def sub_1_x(x):
    """
    >>> sub_1_x(0)
    1
    >>> sub_1_x(-1)
    2
    >>> sub_1_x(1)
    0
    >>> bigint(1 - 2**50)
    -1125899906842623
    >>> bigint(sub_1_x(2**50))
    -1125899906842623
    >>> sub_1_x(1.5)
    -0.5
    >>> sub_1_x(-1.5)
    2.5
    >>> try: sub_1_x("abc")
    ... except TypeError: pass
    """
    return 1 - x


@cython.test_fail_if_path_exists('//SubNode')
def sub_1f_x(x):
    """
    >>> sub_1f_x(0)
    1.0
    >>> sub_1f_x(-1)
    2.0
    >>> sub_1f_x(1)
    0.0
    >>> 1.0 - 2**52
    -4503599627370495.0
    >>> sub_1f_x(2**52)
    -4503599627370495.0
    >>> sub_1f_x(2**60) == 1.0 - 2**60 or sub_1f_x(2**60)
    True
    >>> sub_1f_x(1.5)
    -0.5
    >>> sub_1f_x(-1.5)
    2.5
    >>> try: sub_1f_x("abc")
    ... except TypeError: pass
    """
    return 1.0 - x


@cython.test_fail_if_path_exists('//SubNode')
def sub_large_x(x):
    """
    >>> sub_large_x(0)
    1073741824
    >>> sub_large_x(-1)
    1073741825
    >>> sub_large_x(1)
    1073741823
    >>> sub_large_x(2**30)
    0
    >>> bigint(2**30 - 2**31)
    -1073741824
    >>> bigint(sub_large_x(2**31))
    -1073741824
    >>> sub_large_x(2.0**30)
    0.0
    >>> sub_large_x(2.0**31)
    -1073741824.0
    >>> sub_large_x(2.0**30 + 1)
    -1.0
    >>> sub_large_x(2.0**30 - 1)
    1.0
    >>> try: sub_large_x("abc")
    ... except TypeError: pass
    """
    return 2**30 - x


def sub0(x):
    """
    >>> sub0(0)
    (0, 0)
    >>> sub0(1)
    (1, -1)
    >>> sub0(-1)
    (-1, 1)
    >>> sub0(99)
    (99, -99)
    >>> a, b = sub0(2**32)
    >>> bigint(a)
    4294967296
    >>> bigint(b)
    -4294967296
    >>> a, b = sub0(-2**32)
    >>> bigint(a)
    -4294967296
    >>> bigint(b)
    4294967296
    """
    return x - 0, 0 - x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/switch.pyx0000644000175100001770000002046200000000000017611 0ustar00runnerdocker00000000000000# mode: run
# cython: linetrace=True

cimport cython


@cython.test_fail_if_path_exists('//SwitchStatNode')
@cython.test_assert_path_exists('//IfStatNode')
def switch_simple_py(x):
    """
    >>> switch_simple_py(1)
    1
    >>> switch_simple_py(2)
    2
    >>> switch_simple_py(3)
    3
    >>> switch_simple_py(4)
    8
    >>> switch_simple_py(5)
    0
    """
    if x == 1:
        return 1
    elif 2 == x:
        return 2
    elif x in [3]:
        return 3
    elif x in (4,):
        return 8
    else:
        return 0
    return -1


@cython.test_fail_if_path_exists('//SwitchStatNode')
@cython.test_assert_path_exists('//IfStatNode')
def switch_py(x):
    """
    >>> switch_py(1)
    1
    >>> switch_py(2)
    2
    >>> switch_py(3)
    3
    >>> switch_py(4)
    4
    >>> switch_py(5)
    4
    >>> switch_py(6)
    0
    >>> switch_py(8)
    4
    >>> switch_py(10)
    10
    >>> switch_py(12)
    12
    >>> switch_py(13)
    0
    """
    if x == 1:
        return 1
    elif 2 == x:
        return 2
    elif x in [3]:
        return 3
    elif x in [4,5,7,8]:
        return 4
    elif x in (10,11):
        return 10
    elif x in (12,):
        return 12
    else:
        return 0
    return -1


@cython.test_assert_path_exists('//SwitchStatNode')
@cython.test_fail_if_path_exists('//IfStatNode')
def switch_simple_c(int x):
    """
    >>> switch_simple_c(1)
    1
    >>> switch_simple_c(2)
    2
    >>> switch_simple_c(3)
    3
    >>> switch_simple_c(4)
    8
    >>> switch_simple_c(5)
    0
    """
    if x == 1:
        return 1
    elif 2 == x:
        return 2
    elif x in [3]:
        return 3
    elif x in (4,):
        return 8
    else:
        return 0
    return -1


@cython.test_assert_path_exists('//SwitchStatNode')
@cython.test_fail_if_path_exists('//IfStatNode')
def switch_c(int x):
    """
    >>> switch_c(1)
    1
    >>> switch_c(2)
    2
    >>> switch_c(3)
    3
    >>> switch_c(4)
    4
    >>> switch_c(5)
    4
    >>> switch_c(6)
    0
    >>> switch_c(8)
    4
    >>> switch_c(10)
    10
    >>> switch_c(12)
    12
    >>> switch_c(13)
    0
    """
    if x == 1:
        return 1
    elif 2 == x:
        return 2
    elif x in [3]:
        return 3
    elif x in [4,5,7,8]:
        return 4
    elif x in (10,11):
        return 10
    elif x in (12,):
        return 12
    else:
        return 0
    return -1



@cython.test_assert_path_exists(
    '//SwitchStatNode',
    '//SwitchStatNode//SwitchStatNode',
)
@cython.test_fail_if_path_exists('//BoolBinopNode', '//PrimaryCmpNode')
def switch_in_switch(int x, int y):
    """
    >>> switch_in_switch(1, 1)
    (1, 1)
    >>> switch_in_switch(1, 2)
    (1, 2)
    >>> switch_in_switch(1, 4)
    (1, 3)

    >>> switch_in_switch(2, 1)
    (2, 1)
    >>> switch_in_switch(2, 2)
    (2, 2)
    >>> switch_in_switch(2, 3)
    (2, 3)
    >>> switch_in_switch(2, 4)
    (2, 4)
    >>> switch_in_switch(2, 20)
    (2, 4)

    >>> switch_in_switch(3, 0)
    False
    >>> switch_in_switch(3, 1)
    True
    >>> switch_in_switch(3, 2)
    True
    >>> switch_in_switch(3, 3)
    True
    >>> switch_in_switch(3, 4)
    False

    >>> switch_in_switch(20, 0)
    True
    >>> switch_in_switch(20, 1)
    False
    >>> switch_in_switch(20, 3)
    False
    >>> switch_in_switch(20, 4)
    True
    """
    if x == 1:
        if y == 1:
            return 1,1
        elif y == 2:
            return 1,2
        else:
            return 1,3
    elif x == 2:
        if y == 1:
            return 2,1
        elif y == 2:
            return 2,2
        elif y == 3:
            return 2,3
        else:
            return 2,4
    elif x == 3:
        return y in (1,2,3)
    else:
        return y not in (1,2,3)
    return 'FAILED'


@cython.test_assert_path_exists('//SwitchStatNode')
@cython.test_fail_if_path_exists('//IfStatNode')
def switch_or(int x):
    """
    >>> switch_or(0)
    0
    >>> switch_or(1)
    1
    >>> switch_or(2)
    1
    >>> switch_or(3)
    1
    >>> switch_or(4)
    0
    """
    if x == 1 or x == 2 or x == 3:
        return 1
    else:
        return 0
    return -1


@cython.test_assert_path_exists('//SwitchStatNode')
@cython.test_fail_if_path_exists('//IfStatNode')
def switch_in(int X):
    """
    >>> switch_in(0)
    0
    >>> switch_in(1)
    1
    >>> switch_in(2)
    0
    >>> switch_in(7)
    1
    >>> switch_in(8)
    0
    """
    if X in (1,3,5,7):
        return 1
    return 0


@cython.test_assert_path_exists('//SwitchStatNode')
@cython.test_fail_if_path_exists('//IfStatNode')
def switch_short(int x):
    """
    >>> switch_short(0)
    0
    >>> switch_short(1)
    1
    >>> switch_short(2)
    2
    >>> switch_short(3)
    0
    """
    if x == 1:
        return 1
    elif 2 == x:
        return 2
    else:
        return 0
    return -1


@cython.test_fail_if_path_exists('//SwitchStatNode')
@cython.test_assert_path_exists('//IfStatNode')
def switch_off(int x):
    """
    >>> switch_off(0)
    0
    >>> switch_off(1)
    1
    >>> switch_off(2)
    0
    """
    if x == 1:
        return 1
    else:
        return 0
    return -1



@cython.test_assert_path_exists('//SwitchStatNode')
@cython.test_fail_if_path_exists('//IfStatNode')
def switch_pass(int x):
    """
    >>> switch_pass(1)
    1
    """
    if x == 1:
        pass
    elif x == 2:
        pass
    else:
        pass
    return x


DEF t = (1,2,3,4,5,6)

@cython.test_assert_path_exists('//SwitchStatNode')
@cython.test_fail_if_path_exists('//IfStatNode')
def compile_time_tuple_constant(int x):
    """
    >>> compile_time_tuple_constant(1)
    True
    >>> compile_time_tuple_constant(0)
    False
    >>> compile_time_tuple_constant(7)
    False
    """
    if x in t:
        return True
    else:
        return False


cdef enum X:
    a = 1
    b
    c
    d
    e = 10
    f = 100

@cython.test_assert_path_exists('//SwitchStatNode')
@cython.test_fail_if_path_exists('//IfStatNode')
def enum_switch(X x):
    """
    >>> enum_switch(1)
    0
    >>> enum_switch(10)
    1
    >>> enum_switch(100)
    2
    """
    if x in [a, b, c, d]:
        return 0
    elif x == e:
        return 1
    else:
        return 2


@cython.test_assert_path_exists('//IfStatNode')
@cython.test_assert_path_exists('//IfStatNode//SwitchStatNode')
def enum_duplicates(X x):
    """
    >>> enum_duplicates(1)
    0
    >>> enum_duplicates(2)  # b
    0
    >>> enum_duplicates(10)
    1
    >>> enum_duplicates(100)
    3
    """
    if x in [a, b, c, d]:   # switch is ok here!
        return 0
    elif x == e:
        return 1
    elif x == b:  # duplicate => no switch here!
        return 2
    else:
        return 3


@cython.test_assert_path_exists('//SwitchStatNode')
@cython.test_fail_if_path_exists('//IfStatNode')
def int_enum_switch_mix(int x):
    """
    >>> int_enum_switch_mix(1)
    0
    >>> int_enum_switch_mix(10)
    1
    >>> int_enum_switch_mix(ord('X'))
    2
    >>> int_enum_switch_mix(99)
    3
    >>> int_enum_switch_mix(100)
    4
    """
    if x in [a, b, c, d]:
        return 0
    elif x == e:
        return 1
    elif x == 'X':  # ASCII(88)
        return 2
    elif x == 99:
        return 3
    else:
        return 4


@cython.test_fail_if_path_exists('//SwitchStatNode')
@cython.test_assert_path_exists('//IfStatNode')
def int_enum_duplicates_mix(int x):
    """
    >>> int_enum_duplicates_mix(88)
    0
    >>> int_enum_duplicates_mix(ord('X'))
    0
    >>> int_enum_duplicates_mix(99)
    2
    >>> int_enum_duplicates_mix(100)
    3
    """
    if x == 88:
        return 0
    elif x == 'X':  # ASCII(88) => redundant
        return 1
    elif x == 99:
        return 2
    else:
        return 3


@cython.test_assert_path_exists('//SwitchStatNode')
@cython.test_fail_if_path_exists('//BoolBinopNode', '//PrimaryCmpNode')
def int_in_bool_binop(int x):
    """
    >>> int_in_bool_binop(0)
    False
    >>> int_in_bool_binop(1)
    True
    >>> int_in_bool_binop(2)
    True
    >>> int_in_bool_binop(3)
    False
    """
    return x == 1 or x == 2


@cython.test_assert_path_exists('//SwitchStatNode')
@cython.test_fail_if_path_exists('//BoolBinopNode', '//PrimaryCmpNode')
def int_in_bool_binop_3(int x):
    """
    >>> int_in_bool_binop_3(0)
    False
    >>> int_in_bool_binop_3(1)
    True
    >>> int_in_bool_binop_3(2)
    True
    >>> int_in_bool_binop_3(3)
    False
    >>> int_in_bool_binop_3(4)
    True
    >>> int_in_bool_binop_3(5)
    False
    """
    return x == 1 or x == 2 or x == 4
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/switch_transform.pyx0000644000175100001770000000042200000000000021676 0ustar00runnerdocker00000000000000# cython: optimize.use_switch=False
# cython: linetrace=True

cdef extern from *:
    enum:
        ONE "1"
        ONE_AGAIN "1+0"

def is_not_one(int i):
    """
    >>> is_not_one(1)
    False
    >>> is_not_one(2)
    True
    """
    return i != ONE and i != ONE_AGAIN
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/tandemstats.pyx0000644000175100001770000000026200000000000020633 0ustar00runnerdocker00000000000000cdef int i, j, k
i = 17; j = 42; k = i * j
if j > k: i = 88
else: i = 99; j = k

def result():
    """
    >>> result() == (99, 17*42, 17*42)
    True
    """
    return (i,j,k)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/temp_alloc_T409.pyx0000644000175100001770000000037500000000000021150 0ustar00runnerdocker00000000000000# ticket: t409
# Extracted from sage/plot/plot3d/index_face_set.pyx:502
# Turns out to be a bug in implementation of PEP 3132 (Extended Iterable Unpacking)

def foo():
    """
    >>> foo()
    ([0, 0], [0, 0])
    """
    a = b = [0,0]
    return a, b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/temp_sideeffects_T654.pyx0000644000175100001770000000134600000000000022343 0ustar00runnerdocker00000000000000# ticket: t654

# function call arguments

# not really a bug, Cython warns about it now -- C argument evaluation order is undefined

arg_order = []

cdef int f():
    arg_order.append(1)
    return 1

def g():
    arg_order.append(2)
    return 2

cdef call2(int x, object o):
    return x, o

def test_c_call():
    """
    >>> arg_order
    []
    >>> test_c_call()
    (1, 2)
    >>> arg_order
    [1, 2]
    """
    return call2(f(), g())

# module globals

cdef object X = 1
cdef redefine_global():
    global X
    x,X = X,2
    return x

cdef call3(object x1, int o, object x2):
    return (x1, o, x2)

def test_global_redefine():
    """
    >>> test_global_redefine()
    (1, 1, 2)
    """
    return call3(X, redefine_global(), X)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/temps_corner1.pyx0000644000175100001770000000042600000000000021067 0ustar00runnerdocker00000000000000cdef class A:
    def numerator(self):
        return self

cdef int  bitsize(A a):
    return 1

coeffs = [A()]

class B:
    """
    >>> B().coeffs_bitsize()
    [2]
    """
    def coeffs_bitsize(self):
        r = [bitsize(c.numerator())+1 for c in coeffs]
        return r
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/test_asyncgen.py0000644000175100001770000010762100000000000020771 0ustar00runnerdocker00000000000000# cython: language_level=3, binding=True
# mode: run
# tag: pep525, asyncfor, await

from __future__ import generator_stop

import os
import sys
#import inspect
#import types
import unittest
import contextlib

#from unittest import mock

#from test.support import import_module

#asyncio = import_module("asyncio")

ZERO = 0

try:
    if sys.version_info[:2] == (3, 4):
        # asnycio in Py3.4 does not support awaitable coroutines (requires iterators instead)
        raise ImportError
    import asyncio
except ImportError:
    try:
        from unittest import skip
    except ImportError:
        def requires_asyncio(c):
            return None
    else:
        requires_asyncio = skip("tests require asyncio")
    asyncio = None
else:
    def requires_asyncio(c):
        return c


def needs_py36_asyncio(f):
    if sys.version_info >= (3, 6) or asyncio is None:
        # Py<3.4 doesn't have asyncio at all => avoid having to special case 2.6's unittest below
        return f

    from unittest import skip
    return skip("needs Python 3.6 or later")(f)

def not_pypy(f):
    if getattr(sys, "pypy_version_info", False):
        from unittest import skip
        return skip("cannot run on PyPy due to to finalizer")(f)
    return f

try:
    from types import coroutine as types_coroutine
except ImportError:
    def types_coroutine(func):
        from functools import wraps
        wrapped = wraps(func)

        # copied from types.py in Py3.6
        class _GeneratorWrapper(object):
            # TODO: Implement this in C.
            def __init__(self, gen):
                self.__wrapped = gen
                self.__isgen = hasattr(gen, 'gi_running')
                self.__name__ = getattr(gen, '__name__', None)
                self.__qualname__ = getattr(gen, '__qualname__', None)

            def send(self, val):
                return self.__wrapped.send(val)

            def throw(self, tp, *rest):
                return self.__wrapped.throw(tp, *rest)

            def close(self):
                return self.__wrapped.close()

            @property
            def gi_code(self):
                return self.__wrapped.gi_code

            @property
            def gi_frame(self):
                return self.__wrapped.gi_frame

            @property
            def gi_running(self):
                return self.__wrapped.gi_running

            @property
            def gi_yieldfrom(self):
                return self.__wrapped.gi_yieldfrom

            cr_code = gi_code
            cr_frame = gi_frame
            cr_running = gi_running
            cr_await = gi_yieldfrom

            def __next__(self):
                return next(self.__wrapped)
            next = __next__

            def __iter__(self):
                if self.__isgen:
                    return self.__wrapped
                return self

            __await__ = __iter__

        @wrapped
        def call(*args, **kwargs):
            return wrapped(_GeneratorWrapper(func(*args, **kwargs)))

        return call

try:
    from inspect import isawaitable as inspect_isawaitable
except ImportError:
    def inspect_isawaitable(o):
        return hasattr(o, '__await__')


# compiled exec()
def exec(code_string, l, g):
    from Cython.Compiler.Errors import CompileError
    from Cython.Shadow import inline
    try:
        from StringIO import StringIO
    except ImportError:
        from io import StringIO

    old_stderr = sys.stderr
    try:
        sys.stderr = StringIO()
        ns = inline(code_string, locals=l, globals=g, lib_dir=os.path.dirname(__file__))
    except CompileError as exc:
        raise SyntaxError(str(exc))
    finally:
        sys.stderr = old_stderr
    g.update(ns)


class AwaitException(Exception):
    pass


@types_coroutine
def awaitable(*, throw=False):
    if throw:
        yield ('throw',)
    else:
        yield ('result',)


def run_until_complete(coro):
    exc = False
    while True:
        try:
            if exc:
                exc = False
                fut = coro.throw(AwaitException)
            else:
                fut = coro.send(None)
        except StopIteration as ex:
            return ex.args[0]

        if fut == ('throw',):
            exc = True


def to_list(gen):
    async def iterate():
        res = []
        async for i in gen:
            res.append(i)
        return res

    return run_until_complete(iterate())


class AsyncGenSyntaxTest(unittest.TestCase):

    @contextlib.contextmanager
    def assertRaisesRegex(self, exc_type, regex):
        # the error messages usually don't match, so we just ignore them
        try:
            yield
        except exc_type:
            self.assertTrue(True)
        else:
            self.assertTrue(False)

    def test_async_gen_syntax_01(self):
        code = '''async def foo():
            await abc
            yield from 123
        '''

        with self.assertRaisesRegex(SyntaxError, 'yield from.*inside async'):
            exec(code, {}, {})

    def test_async_gen_syntax_02(self):
        code = '''async def foo():
            yield from 123
        '''

        with self.assertRaisesRegex(SyntaxError, 'yield from.*inside async'):
            exec(code, {}, {})

    def test_async_gen_syntax_03(self):
        code = '''async def foo():
            await abc
            yield
            return 123
        '''

        with self.assertRaisesRegex(SyntaxError, 'return.*value.*async gen'):
            exec(code, {}, {})

    def test_async_gen_syntax_04(self):
        code = '''async def foo():
            yield
            return 123
        '''

        with self.assertRaisesRegex(SyntaxError, 'return.*value.*async gen'):
            exec(code, {}, {})

    def test_async_gen_syntax_05(self):
        code = '''async def foo():
            if 0:
                yield
            return 12
        '''

        with self.assertRaisesRegex(SyntaxError, 'return.*value.*async gen'):
            exec(code, {}, {})


class AsyncGenTest(unittest.TestCase):

    if sys.version_info < (3, 3):
        @contextlib.contextmanager
        def assertRaisesRegex(self, exc_type, regex=None):
            # the error messages usually don't match, so we just ignore them
            try:
                yield
            except exc_type:
                self.assertTrue(True)
            else:
                self.assertTrue(False)

    def compare_generators(self, sync_gen, async_gen):
        def sync_iterate(g):
            res = []
            while True:
                try:
                    res.append(next(g))
                except StopIteration:
                    res.append('STOP')
                    break
                except Exception as ex:
                    res.append(str(type(ex)))
            return res

        def async_iterate(g):
            res = []
            while True:
                an = g.__anext__()
                try:
                    while True:
                        try:
                            next(an)
                        except StopIteration as ex:
                            if ex.args:
                                res.append(ex.args[0])
                                break
                            else:
                                res.append('EMPTY StopIteration')
                                break
                        except StopAsyncIteration:
                            raise
                        except Exception as ex:
                            res.append(str(type(ex)))
                            break
                except StopAsyncIteration:
                    res.append('STOP')
                    break
            return res

        sync_gen_result = sync_iterate(sync_gen)
        async_gen_result = async_iterate(async_gen)
        self.assertEqual(sync_gen_result, async_gen_result)
        return async_gen_result

    def test_async_gen_iteration_01(self):
        async def gen():
            await awaitable()
            a = yield 123
            self.assertIs(a, None)
            await awaitable()
            yield 456
            await awaitable()
            yield 789

        self.assertEqual(to_list(gen()), [123, 456, 789])

    def test_async_gen_iteration_02(self):
        async def gen():
            await awaitable()
            yield 123
            await awaitable()

        g = gen()
        ai = g.__aiter__()

        an = ai.__anext__()
        self.assertEqual(next(an), ('result',))

        try:
            next(an)
        except StopIteration as ex:
            self.assertEqual(ex.args[0], 123)
        else:
            self.fail('StopIteration was not raised')

        an = ai.__anext__()
        self.assertEqual(next(an), ('result',))

        try:
            next(an)
        except StopAsyncIteration as ex:
            self.assertFalse(ex.args)
        else:
            self.fail('StopAsyncIteration was not raised')

    def test_async_gen_exception_03(self):
        async def gen():
            await awaitable()
            yield 123
            await awaitable(throw=True)
            yield 456

        with self.assertRaises(AwaitException):
            to_list(gen())

    def test_async_gen_exception_04(self):
        async def gen():
            await awaitable()
            yield 123
            1 / ZERO

        g = gen()
        ai = g.__aiter__()

        an = ai.__anext__()
        self.assertEqual(next(an), ('result',))

        try:
            next(an)
        except StopIteration as ex:
            self.assertEqual(ex.args[0], 123)
        else:
            self.fail('StopIteration was not raised')

        with self.assertRaises(ZeroDivisionError):
            next(ai.__anext__())

    def test_async_gen_exception_05(self):
        async def gen():
            yield 123
            raise StopAsyncIteration

        with self.assertRaisesRegex(RuntimeError,
                                    'async generator.*StopAsyncIteration'):
            to_list(gen())

    def test_async_gen_exception_06(self):
        async def gen():
            yield 123
            raise StopIteration

        with self.assertRaisesRegex(RuntimeError,
                                    'async generator.*StopIteration'):
            to_list(gen())

    def test_async_gen_exception_07(self):
        def sync_gen():
            try:
                yield 1
                1 / ZERO
            finally:
                yield 2
                yield 3

            yield 100

        async def async_gen():
            try:
                yield 1
                1 / ZERO
            finally:
                yield 2
                yield 3

            yield 100

        self.compare_generators(sync_gen(), async_gen())

    def test_async_gen_exception_08(self):
        def sync_gen():
            try:
                yield 1
            finally:
                yield 2
                1 / ZERO
                yield 3

            yield 100

        async def async_gen():
            try:
                yield 1
                await awaitable()
            finally:
                await awaitable()
                yield 2
                1 / ZERO
                yield 3

            yield 100

        self.compare_generators(sync_gen(), async_gen())

    def test_async_gen_exception_09(self):
        def sync_gen():
            try:
                yield 1
                1 / ZERO
            finally:
                yield 2
                yield 3

            yield 100

        async def async_gen():
            try:
                await awaitable()
                yield 1
                1 / ZERO
            finally:
                yield 2
                await awaitable()
                yield 3

            yield 100

        self.compare_generators(sync_gen(), async_gen())

    def test_async_gen_exception_10(self):
        async def gen():
            yield 123
        with self.assertRaisesRegex(TypeError,
                                    "non-None value .* async generator"):
            gen().__anext__().send(100)

    def test_async_gen_exception_11(self):
        def sync_gen():
            yield 10
            yield 20

        def sync_gen_wrapper():
            yield 1
            sg = sync_gen()
            sg.send(None)
            try:
                sg.throw(GeneratorExit())
            except GeneratorExit:
                yield 2
            yield 3

        async def async_gen():
            yield 10
            yield 20

        async def async_gen_wrapper():
            yield 1
            asg = async_gen()
            await asg.asend(None)
            try:
                await asg.athrow(GeneratorExit())
            except GeneratorExit:
                yield 2
            yield 3

        self.compare_generators(sync_gen_wrapper(), async_gen_wrapper())

    def test_async_gen_api_01(self):
        async def gen():
            yield 123

        g = gen()

        self.assertEqual(g.__name__, 'gen')
        g.__name__ = '123' if sys.version_info[0] >= 3 else b'123'
        self.assertEqual(g.__name__, '123')

        self.assertIn('.gen', g.__qualname__)
        g.__qualname__ = '123' if sys.version_info[0] >= 3 else b'123'
        self.assertEqual(g.__qualname__, '123')

        #self.assertIsNone(g.ag_await)
        #self.assertIsInstance(g.ag_frame, types.FrameType)
        self.assertFalse(g.ag_running)
        #self.assertIsInstance(g.ag_code, types.CodeType)

        self.assertTrue(inspect_isawaitable(g.aclose()))


@requires_asyncio
class AsyncGenAsyncioTest(unittest.TestCase):

    def setUp(self):
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(None)

    def tearDown(self):
        self.loop.close()
        self.loop = None

    async def to_list(self, gen):
        res = []
        async for i in gen:
            res.append(i)
        return res

    def test_async_gen_asyncio_01(self):
        async def gen():
            yield 1
            await asyncio.sleep(0.01)
            yield 2
            await asyncio.sleep(0.01)
            return
            yield 3

        res = self.loop.run_until_complete(self.to_list(gen()))
        self.assertEqual(res, [1, 2])

    def test_async_gen_asyncio_02(self):
        async def gen():
            yield 1
            await asyncio.sleep(0.01)
            yield 2
            1 / ZERO
            yield 3

        with self.assertRaises(ZeroDivisionError):
            self.loop.run_until_complete(self.to_list(gen()))

    def test_async_gen_asyncio_03(self):
        loop = self.loop

        class Gen:
            async def __aiter__(self):
                yield 1
                await asyncio.sleep(0.01)
                yield 2

        res = loop.run_until_complete(self.to_list(Gen()))
        self.assertEqual(res, [1, 2])

    def test_async_gen_asyncio_anext_04(self):
        async def foo():
            yield 1
            await asyncio.sleep(0.01)
            try:
                yield 2
                yield 3
            except ZeroDivisionError:
                yield 1000
            await asyncio.sleep(0.01)
            yield 4

        async def run1():
            it = foo().__aiter__()

            self.assertEqual(await it.__anext__(), 1)
            self.assertEqual(await it.__anext__(), 2)
            self.assertEqual(await it.__anext__(), 3)
            self.assertEqual(await it.__anext__(), 4)
            with self.assertRaises(StopAsyncIteration):
                await it.__anext__()
            with self.assertRaises(StopAsyncIteration):
                await it.__anext__()

        async def run2():
            it = foo().__aiter__()

            self.assertEqual(await it.__anext__(), 1)
            self.assertEqual(await it.__anext__(), 2)
            try:
                it.__anext__().throw(ZeroDivisionError)
            except StopIteration as ex:
                self.assertEqual(ex.args[0], 1000)
            else:
                self.fail('StopIteration was not raised')
            self.assertEqual(await it.__anext__(), 4)
            with self.assertRaises(StopAsyncIteration):
                await it.__anext__()

        self.loop.run_until_complete(run1())
        self.loop.run_until_complete(run2())

    def test_async_gen_asyncio_anext_05(self):
        async def foo():
            v = yield 1
            v = yield v
            yield v * 100

        async def run():
            it = foo().__aiter__()

            try:
                it.__anext__().send(None)
            except StopIteration as ex:
                self.assertEqual(ex.args[0], 1)
            else:
                self.fail('StopIteration was not raised')

            try:
                it.__anext__().send(10)
            except StopIteration as ex:
                self.assertEqual(ex.args[0], 10)
            else:
                self.fail('StopIteration was not raised')

            try:
                it.__anext__().send(12)
            except StopIteration as ex:
                self.assertEqual(ex.args[0], 1200)
            else:
                self.fail('StopIteration was not raised')

            with self.assertRaises(StopAsyncIteration):
                await it.__anext__()

        self.loop.run_until_complete(run())

    def test_async_gen_asyncio_anext_06(self):
        DONE = 0

        # test synchronous generators
        def foo():
            try:
                yield
            except:
                pass
        g = foo()
        g.send(None)
        with self.assertRaises(StopIteration):
            g.send(None)

        # now with asynchronous generators

        async def gen():
            nonlocal DONE
            try:
                yield
            except:
                pass
            DONE = 1

        async def run():
            nonlocal DONE
            g = gen()
            await g.asend(None)
            with self.assertRaises(StopAsyncIteration):
                await g.asend(None)
            DONE += 10

        self.loop.run_until_complete(run())
        self.assertEqual(DONE, 11)

    def test_async_gen_asyncio_anext_tuple(self):
        async def foo():
            try:
                yield (1,)
            except ZeroDivisionError:
                yield (2,)

        async def run():
            it = foo().__aiter__()

            self.assertEqual(await it.__anext__(), (1,))
            with self.assertRaises(StopIteration) as cm:
                it.__anext__().throw(ZeroDivisionError)
            self.assertEqual(cm.exception.args[0], (2,))
            with self.assertRaises(StopAsyncIteration):
                await it.__anext__()

        self.loop.run_until_complete(run())

    def test_async_gen_asyncio_anext_stopiteration(self):
        async def foo():
            try:
                yield StopIteration(1)
            except ZeroDivisionError:
                yield StopIteration(3)

        async def run():
            it = foo().__aiter__()

            v = await it.__anext__()
            self.assertIsInstance(v, StopIteration)
            self.assertEqual(v.value, 1)
            with self.assertRaises(StopIteration) as cm:
                it.__anext__().throw(ZeroDivisionError)
            v = cm.exception.args[0]
            self.assertIsInstance(v, StopIteration)
            self.assertEqual(v.value, 3)
            with self.assertRaises(StopAsyncIteration):
                await it.__anext__()

        self.loop.run_until_complete(run())

    def test_async_gen_asyncio_aclose_06(self):
        async def foo():
            try:
                yield 1
                1 / ZERO
            finally:
                await asyncio.sleep(0.01)
                yield 12

        async def run():
            gen = foo()
            it = gen.__aiter__()
            await it.__anext__()
            await gen.aclose()

        with self.assertRaisesRegex(
                RuntimeError,
                "async generator ignored GeneratorExit"):
            self.loop.run_until_complete(run())

    def test_async_gen_asyncio_aclose_07(self):
        DONE = 0

        async def foo():
            nonlocal DONE
            try:
                yield 1
                1 / ZERO
            finally:
                await asyncio.sleep(0.01)
                await asyncio.sleep(0.01)
                DONE += 1
            DONE += 1000

        async def run():
            gen = foo()
            it = gen.__aiter__()
            await it.__anext__()
            await gen.aclose()

        self.loop.run_until_complete(run())
        self.assertEqual(DONE, 1)

    def test_async_gen_asyncio_aclose_08(self):
        DONE = 0

        fut = asyncio.Future(loop=self.loop)

        async def foo():
            nonlocal DONE
            try:
                yield 1
                await fut
                DONE += 1000
                yield 2
            finally:
                await asyncio.sleep(0.01)
                await asyncio.sleep(0.01)
                DONE += 1
            DONE += 1000

        async def run():
            gen = foo()
            it = gen.__aiter__()
            self.assertEqual(await it.__anext__(), 1)
            await gen.aclose()

        self.loop.run_until_complete(run())
        self.assertEqual(DONE, 1)

        # Silence ResourceWarnings
        fut.cancel()
        self.loop.run_until_complete(asyncio.sleep(0.01))

    @not_pypy
    @needs_py36_asyncio
    def test_async_gen_asyncio_gc_aclose_09(self):
        DONE = 0

        async def gen():
            nonlocal DONE
            try:
                while True:
                    yield 1
            finally:
                await asyncio.sleep(0.01)
                await asyncio.sleep(0.01)
                DONE = 1

        async def run():
            g = gen()
            await g.__anext__()
            await g.__anext__()
            del g

            await asyncio.sleep(0.2)

        self.loop.run_until_complete(run())
        self.assertEqual(DONE, 1)

    def test_async_gen_asyncio_aclose_10(self):
        DONE = 0

        # test synchronous generators
        def foo():
            try:
                yield
            except:
                pass
        g = foo()
        g.send(None)
        g.close()

        # now with asynchronous generators

        async def gen():
            nonlocal DONE
            try:
                yield
            except:
                pass
            DONE = 1

        async def run():
            nonlocal DONE
            g = gen()
            await g.asend(None)
            await g.aclose()
            DONE += 10

        self.loop.run_until_complete(run())
        self.assertEqual(DONE, 11)

    def test_async_gen_asyncio_aclose_11(self):
        DONE = 0

        # test synchronous generators
        def foo():
            try:
                yield
            except:
                pass
            yield
        g = foo()
        g.send(None)
        with self.assertRaisesRegex(RuntimeError, 'ignored GeneratorExit'):
            g.close()

        # now with asynchronous generators

        async def gen():
            nonlocal DONE
            try:
                yield
            except:
                pass
            yield
            DONE += 1

        async def run():
            nonlocal DONE
            g = gen()
            await g.asend(None)
            with self.assertRaisesRegex(RuntimeError, 'ignored GeneratorExit'):
                await g.aclose()
            DONE += 10

        self.loop.run_until_complete(run())
        self.assertEqual(DONE, 10)

    def test_async_gen_asyncio_aclose_12(self):
        DONE = 0

        async def target():
            await asyncio.sleep(0.01)
            1 / ZERO

        async def foo():
            nonlocal DONE
            task = self.loop.create_task(target())
            try:
                yield 1
            finally:
                try:
                    await task
                except ZeroDivisionError:
                    DONE = 1

        async def run():
            gen = foo()
            it = gen.__aiter__()
            await it.__anext__()
            await gen.aclose()

        self.loop.run_until_complete(run())
        self.assertEqual(DONE, 1)

    def test_async_gen_asyncio_asend_01(self):
        DONE = 0

        # Sanity check:
        def sgen():
            v = yield 1
            yield v * 2
        sg = sgen()
        v = sg.send(None)
        self.assertEqual(v, 1)
        v = sg.send(100)
        self.assertEqual(v, 200)

        async def gen():
            nonlocal DONE
            try:
                await asyncio.sleep(0.01)
                v = yield 1
                await asyncio.sleep(0.01)
                yield v * 2
                await asyncio.sleep(0.01)
                return
            finally:
                await asyncio.sleep(0.01)
                await asyncio.sleep(0.01)
                DONE = 1

        async def run():
            g = gen()

            v = await g.asend(None)
            self.assertEqual(v, 1)

            v = await g.asend(100)
            self.assertEqual(v, 200)

            with self.assertRaises(StopAsyncIteration):
                await g.asend(None)

        self.loop.run_until_complete(run())
        self.assertEqual(DONE, 1)

    def test_async_gen_asyncio_asend_02(self):
        DONE = 0

        async def sleep_n_crash(delay):
            await asyncio.sleep(delay)
            1 / ZERO

        async def gen():
            nonlocal DONE
            try:
                await asyncio.sleep(0.01)
                v = yield 1
                await sleep_n_crash(0.01)
                DONE += 1000
                yield v * 2
            finally:
                assert sys.exc_info()[0] == ZeroDivisionError
                await asyncio.sleep(0.01)
                await asyncio.sleep(0.01)
                DONE += 1

        async def run():
            g = gen()

            v = await g.asend(None)
            self.assertEqual(v, 1)

            await g.asend(100)

        with self.assertRaises(ZeroDivisionError):
            self.loop.run_until_complete(run())
        self.assertEqual(DONE, 1)

    def test_async_gen_asyncio_asend_03(self):
        DONE = 0

        async def sleep_n_crash(delay):
            fut = asyncio.ensure_future(asyncio.sleep(delay),
                                        loop=self.loop)
            self.loop.call_later(delay / 2, lambda: fut.cancel())
            return await fut

        async def gen():
            nonlocal DONE
            try:
                await asyncio.sleep(0.01)
                v = yield 1
                await sleep_n_crash(0.01)
                DONE += 1000
                yield v * 2
            finally:
                await asyncio.sleep(0.01)
                await asyncio.sleep(0.01)
                DONE = 1

        async def run():
            g = gen()

            v = await g.asend(None)
            self.assertEqual(v, 1)

            await g.asend(100)

        with self.assertRaises(asyncio.CancelledError):
            self.loop.run_until_complete(run())
        self.assertEqual(DONE, 1)

    def test_async_gen_asyncio_athrow_01(self):
        DONE = 0

        class FooEr(Exception):
            pass

        # Sanity check:
        def sgen():
            try:
                v = yield 1
            except FooEr:
                v = 1000
            yield v * 2
        sg = sgen()
        v = sg.send(None)
        self.assertEqual(v, 1)
        v = sg.throw(FooEr)
        self.assertEqual(v, 2000)
        with self.assertRaises(StopIteration):
            sg.send(None)

        async def gen():
            nonlocal DONE
            try:
                await asyncio.sleep(0.01)
                try:
                    v = yield 1
                except FooEr:
                    v = 1000
                    await asyncio.sleep(0.01)
                yield v * 2
                await asyncio.sleep(0.01)
                # return
            finally:
                await asyncio.sleep(0.01)
                await asyncio.sleep(0.01)
                DONE = 1

        async def run():
            g = gen()

            v = await g.asend(None)
            self.assertEqual(v, 1)

            v = await g.athrow(FooEr)
            self.assertEqual(v, 2000)

            with self.assertRaises(StopAsyncIteration):
                await g.asend(None)

        self.loop.run_until_complete(run())
        self.assertEqual(DONE, 1)

    def test_async_gen_asyncio_athrow_02(self):
        DONE = 0

        class FooEr(Exception):
            pass

        async def sleep_n_crash(delay):
            fut = asyncio.ensure_future(asyncio.sleep(delay),
                                        loop=self.loop)
            self.loop.call_later(delay / 2, lambda: fut.cancel())
            return await fut

        async def gen():
            nonlocal DONE
            try:
                await asyncio.sleep(0.01)
                try:
                    v = yield 1
                except FooEr:
                    await sleep_n_crash(0.01)
                yield v * 2
                await asyncio.sleep(0.01)
                # return
            finally:
                await asyncio.sleep(0.01)
                await asyncio.sleep(0.01)
                DONE = 1

        async def run():
            g = gen()

            v = await g.asend(None)
            self.assertEqual(v, 1)

            try:
                await g.athrow(FooEr)
            except asyncio.CancelledError:
                self.assertEqual(DONE, 1)
                raise
            else:
                self.fail('CancelledError was not raised')

        with self.assertRaises(asyncio.CancelledError):
            self.loop.run_until_complete(run())
        self.assertEqual(DONE, 1)

    def test_async_gen_asyncio_athrow_03(self):
        DONE = 0

        # test synchronous generators
        def foo():
            try:
                yield
            except:
                pass
        g = foo()
        g.send(None)
        with self.assertRaises(StopIteration):
            g.throw(ValueError)

        # now with asynchronous generators

        async def gen():
            nonlocal DONE
            try:
                yield
            except:
                pass
            DONE = 1

        async def run():
            nonlocal DONE
            g = gen()
            await g.asend(None)
            with self.assertRaises(StopAsyncIteration):
                await g.athrow(ValueError)
            DONE += 10

        self.loop.run_until_complete(run())
        self.assertEqual(DONE, 11)

    def test_async_gen_asyncio_athrow_tuple(self):
        async def gen():
            try:
                yield 1
            except ZeroDivisionError:
                yield (2,)

        async def run():
            g = gen()
            v = await g.asend(None)
            self.assertEqual(v, 1)
            v = await g.athrow(ZeroDivisionError)
            self.assertEqual(v, (2,))
            with self.assertRaises(StopAsyncIteration):
                await g.asend(None)

        self.loop.run_until_complete(run())

    def test_async_gen_asyncio_athrow_stopiteration(self):
        async def gen():
            try:
                yield 1
            except ZeroDivisionError:
                yield StopIteration(2)

        async def run():
            g = gen()
            v = await g.asend(None)
            self.assertEqual(v, 1)
            v = await g.athrow(ZeroDivisionError)
            self.assertIsInstance(v, StopIteration)
            self.assertEqual(v.value, 2)
            with self.assertRaises(StopAsyncIteration):
                await g.asend(None)

        self.loop.run_until_complete(run())

    @needs_py36_asyncio
    def test_async_gen_asyncio_shutdown_01(self):
        finalized = 0

        async def waiter(timeout):
            nonlocal finalized
            try:
                await asyncio.sleep(timeout)
                yield 1
            finally:
                await asyncio.sleep(0)
                finalized += 1

        async def wait():
            async for _ in waiter(1):
                pass

        t1 = self.loop.create_task(wait())
        t2 = self.loop.create_task(wait())

        self.loop.run_until_complete(asyncio.sleep(0.1))


        # Silence warnings
        t1.cancel()
        t2.cancel()

        with self.assertRaises(asyncio.CancelledError):
            self.loop.run_until_complete(t1)
        with self.assertRaises(asyncio.CancelledError):
            self.loop.run_until_complete(t2)

        self.loop.run_until_complete(self.loop.shutdown_asyncgens())

        self.assertEqual(finalized, 2)

    """
    def test_async_gen_expression_01(self):
        async def arange(n):
            for i in range(n):
                await asyncio.sleep(0.01)
                yield i

        def make_arange(n):
            # This syntax is legal starting with Python 3.7
            return (i * 2 async for i in arange(n))

        async def run():
            return [i async for i in make_arange(10)]

        res = self.loop.run_until_complete(run())
        self.assertEqual(res, [i * 2 for i in range(10)])

    def test_async_gen_expression_02(self):
        async def wrap(n):
            await asyncio.sleep(0.01)
            return n

        def make_arange(n):
            # This syntax is legal starting with Python 3.7
            return (i * 2 for i in range(n) if await wrap(i))

        async def run():
            return [i async for i in make_arange(10)]

        res = self.loop.run_until_complete(run())
        self.assertEqual(res, [i * 2 for i in range(1, 10)])
    """

    def test_asyncgen_nonstarted_hooks_are_cancellable(self):
        # See https://bugs.python.org/issue38013
        messages = []

        def exception_handler(loop, context):
            messages.append(context)

        async def async_iterate():
            yield 1
            yield 2

        async def main():
            # loop = asyncio.get_running_loop()
            loop = self.loop
            loop.set_exception_handler(exception_handler)

            async for i in async_iterate():
                break

        # asyncio.run(main())
        self.loop.run_until_complete(main())

        self.assertEqual([], messages)

    def test_async_gen_await_same_anext_coro_twice(self):
        async def async_iterate():
            yield 1
            yield 2

        async def run():
            it = async_iterate()
            nxt = it.__anext__()
            await nxt
            with self.assertRaisesRegex(
                    RuntimeError,
                    r"cannot reuse already awaited __anext__\(\)/asend\(\)"
            ):
                await nxt

            await it.aclose()  # prevent unfinished iterator warning

        self.loop.run_until_complete(run())

    def test_async_gen_await_same_aclose_coro_twice(self):
        async def async_iterate():
            yield 1
            yield 2

        async def run():
            it = async_iterate()
            nxt = it.aclose()
            await nxt
            with self.assertRaisesRegex(
                    RuntimeError,
                    r"cannot reuse already awaited aclose\(\)/athrow\(\)"
            ):
                await nxt

        self.loop.run_until_complete(run())

    def test_async_gen_aclose_twice_with_different_coros(self):
        # Regression test for https://bugs.python.org/issue39606
        async def async_iterate():
            yield 1
            yield 2

        async def run():
            it = async_iterate()
            await it.aclose()
            await it.aclose()

        self.loop.run_until_complete(run())

    def test_async_gen_aclose_after_exhaustion(self):
        # Regression test for https://bugs.python.org/issue39606
        async def async_iterate():
            yield 1
            yield 2

        async def run():
            it = async_iterate()
            async for _ in it:
                pass
            await it.aclose()

        self.loop.run_until_complete(run())

    """
    def test_async_gen_aclose_compatible_with_get_stack(self):
        async def async_generator():
            yield object()

        async def run():
            ag = async_generator()
            self.loop.create_task(ag.aclose())
            tasks = asyncio.all_tasks()
            for task in tasks:
                # No AttributeError raised
                task.get_stack()

        self.loop.run_until_complete(run())
    """


if __name__ == "__main__":
    unittest.main()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/test_call.py0000644000175100001770000000610300000000000020066 0ustar00runnerdocker00000000000000import unittest

# The test cases here cover several paths through the function calling
# code.  They depend on the METH_XXX flag that is used to define a C
# function, which can't be verified from Python.  If the METH_XXX decl
# for a C function changes, these tests may not cover the right paths.

class CFunctionCalls(unittest.TestCase):

    def test_varargs0(self):
        self.assertRaises(TypeError, {}.__contains__)

    def test_varargs1(self):
        {}.__contains__(0)

    def test_varargs2(self):
        self.assertRaises(TypeError, {}.__contains__, 0, 1)

    def test_varargs0_ext(self):
        try:
            {}.__contains__(*())
        except TypeError:
            pass

    def test_varargs1_ext(self):
        {}.__contains__(*(0,))

    def test_varargs2_ext(self):
        try:
            {}.__contains__(*(1, 2))
        except TypeError:
            pass
        else:
            raise RuntimeError

    def test_varargs0_kw(self):
        self.assertRaises(TypeError, {}.__contains__, x=2)

    def test_varargs1_kw(self):
        self.assertRaises(TypeError, {}.__contains__, x=2)

    def test_varargs2_kw(self):
        self.assertRaises(TypeError, {}.__contains__, x=2, y=2)

    def test_oldargs0_0(self):
        {}.keys()

    def test_oldargs0_1(self):
        self.assertRaises(TypeError, {}.keys, 0)

    def test_oldargs0_2(self):
        self.assertRaises(TypeError, {}.keys, 0, 1)

    def test_oldargs0_0_ext(self):
        {}.keys(*())

    def test_oldargs0_1_ext(self):
        try:
            {}.keys(*(0,))
        except TypeError:
            pass
        else:
            raise RuntimeError

    def test_oldargs0_2_ext(self):
        try:
            {}.keys(*(1, 2))
        except TypeError:
            pass
        else:
            raise RuntimeError

    ### Cython makes this a compile time error
    # def test_oldargs0_0_kw(self):
    #     try:
    #         {}.keys(x=2)
    #     except TypeError:
    #         pass
    #     else:
    #         raise RuntimeError

    def test_oldargs0_1_kw(self):
        self.assertRaises(TypeError, {}.keys, x=2)

    def test_oldargs0_2_kw(self):
        self.assertRaises(TypeError, {}.keys, x=2, y=2)

    def test_oldargs1_0(self):
        self.assertRaises(TypeError, [].count)

    def test_oldargs1_1(self):
        [].count(1)

    def test_oldargs1_2(self):
        self.assertRaises(TypeError, [].count, 1, 2)

    def test_oldargs1_0_ext(self):
        try:
            [].count(*())
        except TypeError:
            pass
        else:
            raise RuntimeError

    def test_oldargs1_1_ext(self):
        [].count(*(1,))

    def test_oldargs1_2_ext(self):
        try:
            [].count(*(1, 2))
        except TypeError:
            pass
        else:
            raise RuntimeError

    def test_oldargs1_0_kw(self):
        self.assertRaises(TypeError, [].count, x=2)

    def test_oldargs1_1_kw(self):
        self.assertRaises(TypeError, [].count, {}, x=2)

    def test_oldargs1_2_kw(self):
        self.assertRaises(TypeError, [].count, x=2, y=2)


if __name__ == "__main__":
    unittest.main()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/test_coroutines_pep492.pyx0000644000175100001770000021152500000000000022646 0ustar00runnerdocker00000000000000# cython: language_level=3, binding=True
# mode: run
# tag: pep492, pep530, asyncfor, await

###########
# This file is a copy of the corresponding test file in CPython.
# Please keep in sync and do not add non-upstream tests.
###########

import re
import gc
import sys
import copy
#import types
import pickle
import os.path
import inspect
import unittest
import warnings
import contextlib

from Cython.Compiler import Errors


try:
    from types import coroutine as types_coroutine
except ImportError:
    # duck typed types_coroutine() decorator copied from types.py in Py3.5
    class types_coroutine(object):
        def __init__(self, gen):
            self._gen = gen

        class _GeneratorWrapper(object):
            def __init__(self, gen):
                self.__wrapped__ = gen
                self.send = gen.send
                self.throw = gen.throw
                self.close = gen.close
                self.__name__ = getattr(gen, '__name__', None)
                self.__qualname__ = getattr(gen, '__qualname__', None)
            @property
            def gi_code(self):
                return self.__wrapped__.gi_code
            @property
            def gi_frame(self):
                return self.__wrapped__.gi_frame
            @property
            def gi_running(self):
                return self.__wrapped__.gi_running
            cr_code = gi_code
            cr_frame = gi_frame
            cr_running = gi_running
            def __next__(self):
                return next(self.__wrapped__)
            def __iter__(self):
                return self.__wrapped__
            __await__ = __iter__

        def __call__(self, *args, **kwargs):
            return self._GeneratorWrapper(self._gen(*args, **kwargs))

try:
    from sys import getrefcount
except ImportError:
    from cpython.ref cimport PyObject
    def getrefcount(obj):
        gc.collect()
        # PyPy needs to execute a bytecode to run the finalizers
        exec('', {}, {})
        return (obj).ob_refcnt


def no_pypy(f):
    import platform
    if platform.python_implementation() == 'PyPy':
        return unittest.skip("excluded in PyPy")


# compiled exec()
def exec(code_string, l, g):
    from Cython.Shadow import inline
    try:
        from StringIO import StringIO
    except ImportError:
        from io import StringIO

    old_stderr = sys.stderr
    try:
        sys.stderr = StringIO()
        ns = inline(code_string, locals=l, globals=g, lib_dir=os.path.dirname(__file__), language_level=3)
    finally:
        sys.stderr = old_stderr
    g.update(ns)


def compile(code_string, module, level):
    exec(code_string, {}, {})


class AsyncYieldFrom(object):
    def __init__(self, obj):
        self.obj = obj

    def __await__(self):
        yield from self.obj


class AsyncYield(object):
    def __init__(self, value):
        self.value = value

    def __await__(self):
        yield self.value


def run_async(coro):
    #assert coro.__class__ is types.GeneratorType
    assert coro.__class__.__name__.rsplit('.', 1)[-1] in ('coroutine', '_GeneratorWrapper'), coro.__class__.__name__

    buffer = []
    result = None
    while True:
        try:
            buffer.append(coro.send(None))
        except StopIteration as ex:
            result = ex.value if sys.version_info >= (3, 5) else ex.args[0] if ex.args else None
            break
    return buffer, result


def run_async__await__(coro):
    assert coro.__class__.__name__.rsplit('.', 1)[-1] in ('coroutine', '_GeneratorWrapper'), coro.__class__.__name__
    aw = coro.__await__()
    buffer = []
    result = None
    i = 0
    while True:
        try:
            if i % 2:
                buffer.append(next(aw))
            else:
                buffer.append(aw.send(None))
            i += 1
        except StopIteration as ex:
            result = ex.value if sys.version_info >= (3, 5) else ex.args[0] if ex.args else None
            break
    return buffer, result


@contextlib.contextmanager
def silence_coro_gc():
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        yield
        gc.collect()


@contextlib.contextmanager
def captured_stderr():
    try:
        # StringIO.StringIO() also accepts str in Py2, io.StringIO() does not
        from StringIO import StringIO
    except ImportError:
        from io import StringIO

    orig_stderr = sys.stderr
    try:
        sys.stderr = StringIO()
        yield sys.stderr
    finally:
        sys.stderr = orig_stderr


class AsyncBadSyntaxTest(unittest.TestCase):

    @contextlib.contextmanager
    def assertRaisesRegex(self, exc_type, regex):
        class Holder(object):
            exception = None

        holder = Holder()
        # the error messages usually don't match, so we just ignore them
        try:
            yield holder
        except exc_type as exc:
            holder.exception = exc
            self.assertTrue(True)
        else:
            self.assertTrue(False)

    def test_badsyntax_1(self):
        samples = [
            """def foo():
                await something()
            """,

            """await something()""",

            """async def foo():
                yield from []
            """,

            """async def foo():
                await await fut
            """,

            """async def foo(a=await something()):
                pass
            """,

            #"""async def foo(a:await something()):
            #    pass
            #""", # No longer an error with pep-563 (although still nonsense)
            # Some other similar tests have also been commented out

            """async def foo():
                def bar():
                 [i async for i in els]
            """,

            """async def foo():
                def bar():
                 [await i for i in els]
            """,

            """async def foo():
                def bar():
                 [i for i in els
                    async for b in els]
            """,

            """async def foo():
                def bar():
                 [i for i in els
                    for c in b
                    async for b in els]
            """,

            """async def foo():
                def bar():
                 [i for i in els
                    async for b in els
                    for c in b]
            """,

            """async def foo():
                def bar():
                 [i for i in els
                    for b in await els]
            """,

            """async def foo():
                def bar():
                 [i for i in els
                    for b in els
                        if await b]
            """,

            """async def foo():
                def bar():
                 [i for i in await els]
            """,

            """async def foo():
                def bar():
                 [i for i in els if await i]
            """,

            """def bar():
                 [i async for i in els]
            """,

            """def bar():
                 [await i for i in els]
            """,

            """def bar():
                 [i for i in els
                    async for b in els]
            """,

            """def bar():
                 [i for i in els
                    for c in b
                    async for b in els]
            """,

            """def bar():
                 [i for i in els
                    async for b in els
                    for c in b]
            """,

            """def bar():
                 [i for i in els
                    for b in await els]
            """,

            """def bar():
                 [i for i in els
                    for b in els
                        if await b]
            """,

            """def bar():
                 [i for i in await els]
            """,

            """def bar():
                 [i for i in els if await i]
            """,

            """async def foo():
                await
            """,

            """async def foo():
                   def bar(): pass
                   await = 1
            """,

            """async def foo():

                   def bar(): pass
                   await = 1
            """,

            """async def foo():
                   def bar(): pass
                   if 1:
                       await = 1
            """,

            """def foo():
                   async def bar(): pass
                   if 1:
                       await a
            """,

            """def foo():
                   async def bar(): pass
                   await a
            """,

            """def foo():
                   def baz(): pass
                   async def bar(): pass
                   await a
            """,

            """def foo():
                   def baz(): pass
                   # 456
                   async def bar(): pass
                   # 123
                   await a
            """,

            """async def foo():
                   def baz(): pass
                   # 456
                   async def bar(): pass
                   # 123
                   await = 2
            """,

            """def foo():

                   def baz(): pass

                   async def bar(): pass

                   await a
            """,

            """async def foo():

                   def baz(): pass

                   async def bar(): pass

                   await = 2
            """,

            """async def foo():
                   def async(): pass
            """,

            """async def foo():
                   def await(): pass
            """,

            """async def foo():
                   def bar():
                       await
            """,

            """async def foo():
                   return lambda async: await
            """,

            """async def foo():
                   return lambda a: await
            """,

            """await a()""",

            """async def foo(a=await b):
                   pass
            """,

            #"""async def foo(a:await b):
            #       pass
            #""",

            """def baz():
                   async def foo(a=await b):
                       pass
            """,

            """async def foo(async):
                   pass
            """,

            """async def foo():
                   def bar():
                        def baz():
                            async = 1
            """,

            """async def foo():
                   def bar():
                        def baz():
                            pass
                        async = 1
            """,

            """def foo():
                   async def bar():

                        async def baz():
                            pass

                        def baz():
                            42

                        async = 1
            """,

            """async def foo():
                   def bar():
                        def baz():
                            pass\nawait foo()
            """,

            """def foo():
                   def bar():
                        async def baz():
                            pass\nawait foo()
            """,

            """async def foo(await):
                   pass
            """,

            """def foo():

                   async def bar(): pass

                   await a
            """,

            """def foo():
                   async def bar():
                        pass\nawait a
            """]

        for code in samples:
            with self.subTest(code=code), self.assertRaisesRegex(Errors.CompileError, '.'):
                compile(code, "", "exec")

    def test_badsyntax_2(self):
        samples = [
            """def foo():
                await = 1
            """,

            """class Bar:
                def async(): pass
            """,

            """class Bar:
                async = 1
            """,

            """class async:
                pass
            """,

            """class await:
                pass
            """,

            """import math as await""",

            """def async():
                pass""",

            """def foo(*, await=1):
                pass"""

            """async = 1""",

            # FIXME: cannot currently request Py3 syntax in cython.inline()
            #"""print(await=1)"""
        ]

        for code in samples:
            with self.subTest(code=code):  # , self.assertRaisesRegex(Errors.CompileError, '.'):
                compile(code, "", "exec")

    def test_badsyntax_3(self):
        #with self.assertRaises(DeprecationWarning):
            with warnings.catch_warnings():
                warnings.simplefilter("error")
                compile("async = 1", "", "exec")

    def test_badsyntax_10(self):
        # Tests for issue 24619

        samples = [
            """async def foo():
                   def bar(): pass
                   await = 1
            """,

            """async def foo():

                   def bar(): pass
                   await = 1
            """,

            """async def foo():
                   def bar(): pass
                   if 1:
                       await = 1
            """,

            """def foo():
                   async def bar(): pass
                   if 1:
                       await a
            """,

            """def foo():
                   async def bar(): pass
                   await a
            """,

            """def foo():
                   def baz(): pass
                   async def bar(): pass
                   await a
            """,

            """def foo():
                   def baz(): pass
                   # 456
                   async def bar(): pass
                   # 123
                   await a
            """,

            """async def foo():
                   def baz(): pass
                   # 456
                   async def bar(): pass
                   # 123
                   await = 2
            """,

            """def foo():

                   def baz(): pass

                   async def bar(): pass

                   await a
            """,

            """async def foo():

                   def baz(): pass

                   async def bar(): pass

                   await = 2
            """,

            """async def foo():
                   def async(): pass
            """,

            """async def foo():
                   def await(): pass
            """,

            """async def foo():
                   def bar():
                       await
            """,

            """async def foo():
                   return lambda async: await
            """,

            """async def foo():
                   return lambda a: await
            """,

            """await a()""",

            """async def foo(a=await b):
                   pass
            """,

            #"""async def foo(a:await b):
            #       pass
            #""",

            """def baz():
                   async def foo(a=await b):
                       pass
            """,

            """async def foo(async):
                   pass
            """,

            """async def foo():
                   def bar():
                        def baz():
                            async = 1
            """,

            """async def foo():
                   def bar():
                        def baz():
                            pass
                        async = 1
            """,

            """def foo():
                   async def bar():

                        async def baz():
                            pass

                        def baz():
                            42

                        async = 1
            """,

            """async def foo():
                   def bar():
                        def baz():
                            pass\nawait foo()
            """,

            """def foo():
                   def bar():
                        async def baz():
                            pass\nawait foo()
            """,

            """async def foo(await):
                   pass
            """,

            """def foo():

                   async def bar(): pass

                   await a
            """,

            """def foo():
                   async def bar():
                        pass\nawait a
            """]

        for code in samples:
            # assertRaises() differs in Py2.6, so use our own assertRaisesRegex() instead
            with self.subTest(code=code), self.assertRaisesRegex(Errors.CompileError, '.'):
                exec(code, {}, {})

    if not hasattr(unittest.TestCase, 'subTest'):
        @contextlib.contextmanager
        def subTest(self, code, **kwargs):
            try:
                yield
            except Exception:
                print(code)
                raise

    def test_goodsyntax_1(self):
        # Tests for issue 24619

        def foo(await):
            async def foo(): pass
            async def foo():
                pass
            return await + 1
        self.assertEqual(foo(10), 11)

        def foo(await):
            async def foo(): pass
            async def foo(): pass
            return await + 2
        self.assertEqual(foo(20), 22)

        def foo(await):

            async def foo(): pass

            async def foo(): pass

            return await + 2
        self.assertEqual(foo(20), 22)

        def foo(await):
            """spam"""
            async def foo(): \
                pass
            # 123
            async def foo(): pass
            # 456
            return await + 2
        self.assertEqual(foo(20), 22)

        def foo(await):
            def foo(): pass
            def foo(): pass
            async def bar(): return await_
            await_ = await
            try:
                bar().send(None)
            except StopIteration as ex:
                return ex.args[0]
        self.assertEqual(foo(42), 42)

        async def f(z):
            async def g(): pass
            await z
        await = 1
        if sys.version_info >= (3,10,6):
            self.assertTrue(inspect.iscoroutinefunction(f))


class TokenizerRegrTest(unittest.TestCase):

    def test_oneline_defs(self):
        buf = []
        for i in range(500):
            buf.append('def i{i}(): return {i}'.format(i=i))
        buf = '\n'.join(buf)

        # Test that 500 consequent, one-line defs is OK
        ns = {}
        exec(buf, ns, ns)
        self.assertEqual(ns['i499'](), 499)

        # Test that 500 consequent, one-line defs *and*
        # one 'async def' following them is OK
        buf += '\nasync def foo():\n    return'
        ns = {}
        exec(buf, ns, ns)
        self.assertEqual(ns['i499'](), 499)
        self.assertEqual(type(ns['foo']()).__name__, 'coroutine')
        if sys.version_info >= (3,10,6):
            self.assertTrue(inspect.iscoroutinefunction(ns['foo']))


class CoroutineTest(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        # never mark warnings as "already seen" to prevent them from being suppressed
        from warnings import simplefilter
        simplefilter("always")

    @contextlib.contextmanager
    def assertRaises(self, exc_type):
        try:
            yield
        except exc_type:
            self.assertTrue(True)
        else:
            self.assertTrue(False)

    @contextlib.contextmanager
    def assertRaisesRegex(self, exc_type, regex):
        class Holder(object):
            exception = None

        holder = Holder()
        # the error messages usually don't match, so we just ignore them
        try:
            yield holder
        except exc_type as exc:
            holder.exception = exc
            self.assertTrue(True)
        else:
            self.assertTrue(False)

    @contextlib.contextmanager
    def assertWarnsRegex(self, exc_type, regex):
        from warnings import catch_warnings
        with catch_warnings(record=True) as log:
            yield

        first_match = None
        for warning in log:
            w = warning.message
            if not isinstance(w, exc_type):
                continue
            if first_match is None:
                first_match = w
            if re.search(regex, str(w)):
                self.assertTrue(True)
                return

        if first_match is None:
            self.assertTrue(False, "no warning was raised of type '%s'" % exc_type.__name__)
        else:
            self.assertTrue(False, "'%s' did not match '%s'" % (first_match, regex))

    if not hasattr(unittest.TestCase, 'assertRegex'):
        def assertRegex(self, value, regex):
            self.assertTrue(re.search(regex, str(value)),
                            "'%s' did not match '%s'" % (value, regex))

    if not hasattr(unittest.TestCase, 'assertIn'):
        def assertIn(self, member, container, msg=None):
            self.assertTrue(member in container, msg)

    if not hasattr(unittest.TestCase, 'assertIsNone'):
        def assertIsNone(self, value, msg=None):
            self.assertTrue(value is None, msg)

    if not hasattr(unittest.TestCase, 'assertIsNotNone'):
        def assertIsNotNone(self, value, msg=None):
            self.assertTrue(value is not None, msg)

    if not hasattr(unittest.TestCase, 'assertIsInstance'):
        def assertIsInstance(self, obj, cls, msg=None):
            self.assertTrue(isinstance(obj, cls), msg)

    def test_gen_1(self):
        def gen(): yield
        self.assertFalse(hasattr(gen, '__await__'))

    def test_func_attributes(self):
        async def foo():
            return 10

        f = foo()
        self.assertEqual(f.__name__, 'foo')
        self.assertEqual(f.__qualname__, 'CoroutineTest.test_func_attributes..foo')
        self.assertEqual(f.__module__, 'test_coroutines_pep492')

    def test_func_1(self):
        async def foo():
            return 10

        f = foo()
        self.assertEqual(f.__class__.__name__, 'coroutine')
        #self.assertIsInstance(f, types.CoroutineType)
        #self.assertTrue(bool(foo.__code__.co_flags & 0x80))
        #self.assertTrue(bool(foo.__code__.co_flags & 0x20))
        #self.assertTrue(bool(f.cr_code.co_flags & 0x80))
        #self.assertTrue(bool(f.cr_code.co_flags & 0x20))
        self.assertEqual(run_async(f), ([], 10))

        self.assertEqual(run_async__await__(foo()), ([], 10))

        def bar(): pass
        self.assertFalse(bool(bar.__code__.co_flags & 0x80))  # inspect.CO_COROUTINE

    # TODO
    def __test_func_2(self):
        async def foo():
            raise StopIteration

        with self.assertRaisesRegex(
                RuntimeError, "coroutine raised StopIteration"):

            run_async(foo())

    def test_func_3(self):
        async def foo():
            raise StopIteration

        with silence_coro_gc():
            self.assertRegex(repr(foo()), '^<[^\s]*coroutine object.* at 0x.*>$')

    def test_func_4(self):
        async def foo():
            raise StopIteration

        check = lambda: self.assertRaisesRegex(
            TypeError, "'coroutine' object is not iterable")

        with check():
            list(foo())

        with check():
            tuple(foo())

        with check():
            sum(foo())

        with check():
            iter(foo())

        with check():
            next(foo())

        with silence_coro_gc(), check():
            for i in foo():
                pass

        with silence_coro_gc(), check():
            [i for i in foo()]

    def test_func_5(self):
        @types_coroutine
        def bar():
            yield 1

        async def foo():
            await bar()

        check = lambda: self.assertRaisesRegex(
            TypeError, "'coroutine' object is not iterable")

        with check():
            for el in foo(): pass

        # the following should pass without an error
        for el in bar():
            self.assertEqual(el, 1)
        self.assertEqual([el for el in bar()], [1])
        self.assertEqual(tuple(bar()), (1,))
        self.assertEqual(next(iter(bar())), 1)

    def test_func_6(self):
        @types_coroutine
        def bar():
            yield 1
            yield 2

        async def foo():
            await bar()

        f = foo()
        self.assertEqual(f.send(None), 1)
        self.assertEqual(f.send(None), 2)
        with self.assertRaises(StopIteration):
            f.send(None)

    # TODO (or not? see test_func_8() below)
    def __test_func_7(self):
        async def bar():
            return 10

        def foo():
            yield from bar()

        with silence_coro_gc(), self.assertRaisesRegex(
            TypeError,
            "cannot 'yield from' a coroutine object in a non-coroutine generator"):

            list(foo())

    def test_func_8(self):
        @types_coroutine
        def bar():
            return (yield from foo())

        async def foo():
            return 'spam'

        self.assertEqual(run_async(bar()), ([], 'spam') )

    def test_func_9(self):
        async def foo(): pass

        gc.collect()
        with self.assertWarnsRegex(
            RuntimeWarning, "coroutine '.*test_func_9.*foo' was never awaited"):

            foo()
            gc.collect()

    def test_func_10(self):
        N = 0

        @types_coroutine
        def gen():
            nonlocal N
            try:
                a = yield
                yield (a ** 2)
            except ZeroDivisionError:
                N += 100
                raise
            finally:
                N += 1

        async def foo():
            await gen()

        coro = foo()
        aw = coro.__await__()
        self.assertTrue(aw is iter(aw))
        next(aw)
        self.assertEqual(aw.send(10), 100)
        with self.assertRaises(TypeError):   # removed from CPython test suite?
            type(aw).send(None, None)

        self.assertEqual(N, 0)
        aw.close()
        self.assertEqual(N, 1)
        with self.assertRaises(TypeError):   # removed from CPython test suite?
            type(aw).close(None)

        coro = foo()
        aw = coro.__await__()
        next(aw)
        with self.assertRaises(ZeroDivisionError):
            aw.throw(ZeroDivisionError, None, None)
        self.assertEqual(N, 102)
        with self.assertRaises(TypeError):   # removed from CPython test suite?
            type(aw).throw(None, None, None, None)

    def test_func_11(self):
        async def func(): pass
        coro = func()
        # Test that PyCoro_Type and _PyCoroWrapper_Type types were properly
        # initialized
        self.assertIn('__await__', dir(coro))
        self.assertIn('__iter__', dir(coro.__await__()))
        self.assertIn('coroutine_wrapper', repr(coro.__await__()))
        coro.close() # avoid RuntimeWarning

    def test_func_12(self):
        async def g():
            i = me.send(None)
            await None
        me = g()
        with self.assertRaisesRegex(ValueError,
                                    "coroutine already executing"):
            me.send(None)

    def test_func_13(self):
        async def g():
            pass
        with self.assertRaisesRegex(
            TypeError,
            "can't send non-None value to a just-started coroutine"):

            g().send('spam')

    def test_func_14(self):
        @types_coroutine
        def gen():
            yield
        async def coro():
            try:
                await gen()
            except GeneratorExit:
                await gen()
        c = coro()
        c.send(None)
        with self.assertRaisesRegex(RuntimeError,
                                    "coroutine ignored GeneratorExit"):
            c.close()

    def test_func_15(self):
        # See https://bugs.python.org/issue25887 for details

        async def spammer():
            return 'spam'
        async def reader(coro):
            return await coro

        spammer_coro = spammer()

        with self.assertRaisesRegex(StopIteration, 'spam'):
            reader(spammer_coro).send(None)

        with self.assertRaisesRegex(RuntimeError,
                                    'cannot reuse already awaited coroutine'):
            reader(spammer_coro).send(None)

    def test_func_16(self):
        # See https://bugs.python.org/issue25887 for details

        @types_coroutine
        def nop():
            yield
        async def send():
            await nop()
            return 'spam'
        async def read(coro):
            await nop()
            return await coro

        spammer = send()

        reader = read(spammer)
        reader.send(None)
        reader.send(None)
        with self.assertRaisesRegex(Exception, 'ham'):
            reader.throw(Exception('ham'))

        reader = read(spammer)
        reader.send(None)
        with self.assertRaisesRegex(RuntimeError,
                                    'cannot reuse already awaited coroutine'):
            reader.send(None)

        with self.assertRaisesRegex(RuntimeError,
                                    'cannot reuse already awaited coroutine'):
            reader.throw(Exception('wat'))

    def test_func_17(self):
        # See https://bugs.python.org/issue25887 for details

        async def coroutine():
            return 'spam'

        coro = coroutine()
        with self.assertRaisesRegex(StopIteration, 'spam'):
            coro.send(None)

        with self.assertRaisesRegex(RuntimeError,
                                    'cannot reuse already awaited coroutine'):
            coro.send(None)

        with self.assertRaisesRegex(RuntimeError,
                                    'cannot reuse already awaited coroutine'):
            coro.throw(Exception('wat'))

        # Closing a coroutine shouldn't raise any exception even if it's
        # already closed/exhausted (similar to generators)
        coro.close()
        coro.close()

    def test_func_18(self):
        # See https://bugs.python.org/issue25887 for details

        async def coroutine():
            return 'spam'

        coro = coroutine()
        await_iter = coro.__await__()
        it = iter(await_iter)

        with self.assertRaisesRegex(StopIteration, 'spam'):
            it.send(None)

        with self.assertRaisesRegex(RuntimeError,
                                    'cannot reuse already awaited coroutine'):
            it.send(None)

        with self.assertRaisesRegex(RuntimeError,
                                    'cannot reuse already awaited coroutine'):
            # Although the iterator protocol requires iterators to
            # raise another StopIteration here, we don't want to do
            # that.  In this particular case, the iterator will raise
            # a RuntimeError, so that 'yield from' and 'await'
            # expressions will trigger the error, instead of silently
            # ignoring the call.
            next(it)

        with self.assertRaisesRegex(RuntimeError,
                                    'cannot reuse already awaited coroutine'):
            it.throw(Exception('wat'))

        with self.assertRaisesRegex(RuntimeError,
                                    'cannot reuse already awaited coroutine'):
            it.throw(Exception('wat'))

        # Closing a coroutine shouldn't raise any exception even if it's
        # already closed/exhausted (similar to generators)
        it.close()
        it.close()

    def test_func_19(self):
        CHK = 0

        @types_coroutine
        def foo():
            nonlocal CHK
            yield
            try:
                yield
            except GeneratorExit:
                CHK += 1

        async def coroutine():
            await foo()

        coro = coroutine()

        coro.send(None)
        coro.send(None)

        self.assertEqual(CHK, 0)
        coro.close()
        self.assertEqual(CHK, 1)

        for _ in range(3):
            # Closing a coroutine shouldn't raise any exception even if it's
            # already closed/exhausted (similar to generators)
            coro.close()
            self.assertEqual(CHK, 1)

    def test_coro_wrapper_send_tuple(self):
        async def foo():
            return (10,)

        result = run_async__await__(foo())
        self.assertEqual(result, ([], (10,)))

    def test_coro_wrapper_send_stop_iterator(self):
        async def foo():
            return StopIteration(10)

        result = run_async__await__(foo())
        self.assertIsInstance(result[1], StopIteration)
        if sys.version_info >= (3, 3):
            self.assertEqual(result[1].value, 10)
        else:
            self.assertEqual(result[1].args[0], 10)

    def test_cr_await(self):
        @types_coroutine
        def a():
            #self.assertEqual(inspect.getcoroutinestate(coro_b), inspect.CORO_RUNNING)
            self.assertIsNone(coro_b.cr_await)
            yield
            #self.assertEqual(inspect.getcoroutinestate(coro_b), inspect.CORO_RUNNING)
            # FIXME: no idea why the following works in CPython:
            #self.assertIsNone(coro_b.cr_await)

        async def c():
            await a()

        async def b():
            self.assertIsNone(coro_b.cr_await)
            await c()
            self.assertIsNone(coro_b.cr_await)

        coro_b = b()
        #self.assertEqual(inspect.getcoroutinestate(coro_b), inspect.CORO_CREATED)
        self.assertIsNone(coro_b.cr_await)

        coro_b.send(None)
        #self.assertEqual(inspect.getcoroutinestate(coro_b), inspect.CORO_SUSPENDED)
        #self.assertEqual(coro_b.cr_await.cr_await.gi_code.co_name, 'a')
        self.assertIsNotNone(coro_b.cr_await.cr_await)
        self.assertEqual(coro_b.cr_await.cr_await.__name__, 'a')

        with self.assertRaises(StopIteration):
            coro_b.send(None)  # complete coroutine
        #self.assertEqual(inspect.getcoroutinestate(coro_b), inspect.CORO_CLOSED)
        self.assertIsNone(coro_b.cr_await)

    def test_corotype_1(self):
        async def f(): pass
        ct = type(f())
        self.assertIn('into coroutine', ct.send.__doc__)
        self.assertIn('inside coroutine', ct.close.__doc__)
        self.assertIn('in coroutine', ct.throw.__doc__)
        self.assertIn('of the coroutine', ct.__dict__['__name__'].__doc__)
        self.assertIn('of the coroutine', ct.__dict__['__qualname__'].__doc__)
        self.assertEqual(ct.__name__, 'coroutine')

        async def f(): pass
        c = f()
        self.assertIn('coroutine object', repr(c))
        c.close()

    def test_await_1(self):

        async def foo():
            await 1
        with self.assertRaisesRegex(TypeError, "object int can.t.*await"):
            run_async(foo())

    def test_await_2(self):
        async def foo():
            await []
        with self.assertRaisesRegex(TypeError, "object list can.t.*await"):
            run_async(foo())

    def test_await_3(self):
        async def foo():
            await AsyncYieldFrom([1, 2, 3])

        self.assertEqual(run_async(foo()), ([1, 2, 3], None))
        self.assertEqual(run_async__await__(foo()), ([1, 2, 3], None))

    def test_await_4(self):
        async def bar():
            return 42

        async def foo():
            return await bar()

        self.assertEqual(run_async(foo()), ([], 42))

    def test_await_5(self):
        class Awaitable(object):
            def __await__(self):
                return

        async def foo():
            return (await Awaitable())

        with self.assertRaisesRegex(
            TypeError, "__await__.*returned non-iterator of type"):

            run_async(foo())

    def test_await_6(self):
        class Awaitable(object):
            def __await__(self):
                return iter([52])

        async def foo():
            return (await Awaitable())

        self.assertEqual(run_async(foo()), ([52], None))

    def test_await_7(self):
        class Awaitable(object):
            def __await__(self):
                yield 42
                return 100

        async def foo():
            return (await Awaitable())

        self.assertEqual(run_async(foo()), ([42], 100))

    def test_await_8(self):
        class Awaitable(object):
            pass

        async def foo(): return await Awaitable()

        with self.assertRaisesRegex(
            TypeError, "object Awaitable can't be used in 'await' expression"):

            run_async(foo())

    def test_await_9(self):
        def wrap():
            return bar

        async def bar():
            return 42

        async def foo():
            b = bar()

            db = {'b':  lambda: wrap}

            class DB(object):
                b = staticmethod(wrap)

            return (await bar() + await wrap()() + await db['b']()()() +
                    await bar() * 1000 + await DB.b()())

        async def foo2():
            return -await bar()

        self.assertEqual(run_async(foo()), ([], 42168))
        self.assertEqual(run_async(foo2()), ([], -42))

    def test_await_10(self):
        async def baz():
            return 42

        async def bar():
            return baz()

        async def foo():
            return await (await bar())

        self.assertEqual(run_async(foo()), ([], 42))

    def test_await_11(self):
        def ident(val):
            return val

        async def bar():
            return 'spam'

        async def foo():
            return ident(val=await bar())

        async def foo2():
            return await bar(), 'ham'

        self.assertEqual(run_async(foo2()), ([], ('spam', 'ham')))

    def test_await_12(self):
        async def coro():
            return 'spam'

        class Awaitable(object):
            def __await__(self):
                return coro()

        async def foo():
            return await Awaitable()

        with self.assertRaisesRegex(
            TypeError, r"__await__\(\) returned a coroutine"):

            run_async(foo())

    def test_await_13(self):
        class Awaitable(object):
            def __await__(self):
                return self

        async def foo():
            return await Awaitable()

        with self.assertRaisesRegex(
            TypeError, "__await__.*returned non-iterator of type"):

            run_async(foo())

    def test_await_14(self):
        class Wrapper(object):
            # Forces the interpreter to use CoroutineType.__await__
            def __init__(self, coro):
                self.coro = coro
            def __await__(self):
                return self.coro.__await__()

        class FutureLike(object):
            def __await__(self):
                return (yield)

        class Marker(Exception):
            pass

        async def coro1():
            try:
                return await FutureLike()
            except ZeroDivisionError:
                raise Marker
        async def coro2():
            return await Wrapper(coro1())

        c = coro2()
        c.send(None)
        with self.assertRaisesRegex(StopIteration, 'spam'):
            c.send('spam')

        c = coro2()
        c.send(None)
        with self.assertRaises(Marker):
            c.throw(ZeroDivisionError)

    def test_await_15(self):
        @types_coroutine
        def nop():
            yield

        async def coroutine():
            await nop()

        async def waiter(coro):
            await coro

        coro = coroutine()
        coro.send(None)

        with self.assertRaisesRegex(RuntimeError,
                                    "coroutine is being awaited already"):
            waiter(coro).send(None)

    def test_await_16(self):
        # See https://bugs.python.org/issue29600 for details.

        async def f():
            return ValueError()

        async def g():
            try:
                raise KeyError
            except:
                return await f()

        _, result = run_async(g())
        if sys.version_info[0] >= 3:
            self.assertIsNone(result.__context__)

    # removed from CPython ?
    def __test_await_iterator(self):
        async def foo():
            return 123

        coro = foo()
        it = coro.__await__()
        self.assertEqual(type(it).__name__, 'coroutine_wrapper')

        with self.assertRaisesRegex(TypeError, "cannot instantiate 'coroutine_wrapper' type"):
            type(it)()  # cannot instantiate

        with self.assertRaisesRegex(StopIteration, "123"):
            next(it)

    def test_with_1(self):
        class Manager(object):
            def __init__(self, name):
                self.name = name

            async def __aenter__(self):
                await AsyncYieldFrom(['enter-1-' + self.name,
                                      'enter-2-' + self.name])
                return self

            async def __aexit__(self, *args):
                await AsyncYieldFrom(['exit-1-' + self.name,
                                      'exit-2-' + self.name])

                if self.name == 'B':
                    return True


        async def foo():
            async with Manager("A") as a, Manager("B") as b:
                await AsyncYieldFrom([('managers', a.name, b.name)])
                1/0

        f = foo()
        result, _ = run_async(f)

        self.assertEqual(
            result, ['enter-1-A', 'enter-2-A', 'enter-1-B', 'enter-2-B',
                     ('managers', 'A', 'B'),
                     'exit-1-B', 'exit-2-B', 'exit-1-A', 'exit-2-A']
        )

        async def foo():
            async with Manager("A") as a, Manager("C") as c:
                await AsyncYieldFrom([('managers', a.name, c.name)])
                1/0

        with self.assertRaises(ZeroDivisionError):
            run_async(foo())

    def test_with_2(self):
        class CM(object):
            def __aenter__(self):
                pass

        async def foo():
            async with CM():
                pass

        with self.assertRaisesRegex(AttributeError, '__aexit__'):
            run_async(foo())

    def test_with_3(self):
        class CM(object):
            def __aexit__(self):
                pass

        async def foo():
            async with CM():
                pass

        with self.assertRaisesRegex(AttributeError, '__aenter__'):
            run_async(foo())

    def test_with_4(self):
        class CM(object):
            def __enter__(self):
                pass

            def __exit__(self):
                pass

        async def foo():
            async with CM():
                pass

        with self.assertRaisesRegex(AttributeError, '__aexit__'):
            run_async(foo())

    def test_with_5(self):
        # While this test doesn't make a lot of sense,
        # it's a regression test for an early bug with opcodes
        # generation

        class CM(object):
            async def __aenter__(self):
                return self

            async def __aexit__(self, *exc):
                pass

        async def func():
            async with CM():
                assert (1, ) == 1

        with self.assertRaises(AssertionError):
            run_async(func())

    def test_with_6(self):
        class CM(object):
            def __aenter__(self):
                return 123

            def __aexit__(self, *e):
                return 456

        async def foo():
            async with CM():
                pass

        with self.assertRaisesRegex(
            TypeError, "object int can't be used in 'await' expression"):
            # it's important that __aexit__ wasn't called
            run_async(foo())

    def test_with_7(self):
        class CM(object):
            async def __aenter__(self):
                return self

            def __aexit__(self, *e):
                return 444

        async def foo():
            async with CM():
                1/0

        try:
            run_async(foo())
        except TypeError as exc:
            self.assertRegex(
                exc.args[0], "object int can't be used in 'await' expression")
            if sys.version_info[0] >= 3:
                self.assertTrue(exc.__context__ is not None)
                self.assertTrue(isinstance(exc.__context__, ZeroDivisionError))
        else:
            self.fail('invalid asynchronous context manager did not fail')


    def test_with_8(self):
        CNT = 0

        class CM(object):
            async def __aenter__(self):
                return self

            def __aexit__(self, *e):
                return 456

        async def foo():
            nonlocal CNT
            async with CM():
                CNT += 1


        with self.assertRaisesRegex(
            TypeError, "object int can't be used in 'await' expression"):

            run_async(foo())

        self.assertEqual(CNT, 1)

    def test_with_9(self):
        CNT = 0

        class CM(object):
            async def __aenter__(self):
                return self

            async def __aexit__(self, *e):
                1/0

        async def foo():
            nonlocal CNT
            async with CM():
                CNT += 1

        with self.assertRaises(ZeroDivisionError):
            run_async(foo())

        self.assertEqual(CNT, 1)

    def test_with_10(self):
        CNT = 0

        class CM(object):
            async def __aenter__(self):
                return self

            async def __aexit__(self, *e):
                1/0

        async def foo():
            nonlocal CNT
            async with CM():
                async with CM():
                    raise RuntimeError

        try:
            run_async(foo())
        except ZeroDivisionError as exc:
            pass  # FIXME!
            #if sys.version_info[0] >= 3:
            #    self.assertTrue(exc.__context__ is not None)
            #    self.assertTrue(isinstance(exc.__context__, ZeroDivisionError))
            #    self.assertTrue(isinstance(exc.__context__.__context__, RuntimeError))
        else:
            self.fail('exception from __aexit__ did not propagate')

    def test_with_11(self):
        CNT = 0

        class CM(object):
            async def __aenter__(self):
                raise NotImplementedError

            async def __aexit__(self, *e):
                1/0

        async def foo():
            nonlocal CNT
            async with CM():
                raise RuntimeError

        try:
            run_async(foo())
        except NotImplementedError as exc:
            if sys.version_info[0] >= 3:
                self.assertTrue(exc.__context__ is None)
        else:
            self.fail('exception from __aenter__ did not propagate')

    def test_with_12(self):
        CNT = 0

        class CM(object):
            async def __aenter__(self):
                return self

            async def __aexit__(self, *e):
                return True

        async def foo():
            nonlocal CNT
            async with CM() as cm:
                self.assertIs(cm.__class__, CM)
                raise RuntimeError

        run_async(foo())

    def test_with_13(self):
        CNT = 0

        class CM(object):
            async def __aenter__(self):
                1/0

            async def __aexit__(self, *e):
                return True

        async def foo():
            nonlocal CNT
            CNT += 1
            async with CM():
                CNT += 1000
            CNT += 10000

        with self.assertRaises(ZeroDivisionError):
            run_async(foo())
        self.assertEqual(CNT, 1)

    # old-style pre-Py3.5.2 protocol - no longer supported
    def __test_for_1(self):
        aiter_calls = 0

        class AsyncIter(object):
            def __init__(self):
                self.i = 0

            async def __aiter__(self):
                nonlocal aiter_calls
                aiter_calls += 1
                return self

            async def __anext__(self):
                self.i += 1

                if not (self.i % 10):
                    await AsyncYield(self.i * 10)

                if self.i > 100:
                    raise StopAsyncIteration

                return self.i, self.i


        buffer = []
        async def test1():
            with self.assertWarnsRegex(DeprecationWarning, "legacy"):
                async for i1, i2 in AsyncIter():
                    buffer.append(i1 + i2)

        yielded, _ = run_async(test1())
        # Make sure that __aiter__ was called only once
        self.assertEqual(aiter_calls, 1)
        self.assertEqual(yielded, [i * 100 for i in range(1, 11)])
        self.assertEqual(buffer, [i*2 for i in range(1, 101)])


        buffer = []
        async def test2():
            nonlocal buffer
            with self.assertWarnsRegex(DeprecationWarning, "legacy"):
                async for i in AsyncIter():
                    buffer.append(i[0])
                    if i[0] == 20:
                        break
                else:
                    buffer.append('what?')
            buffer.append('end')

        yielded, _ = run_async(test2())
        # Make sure that __aiter__ was called only once
        self.assertEqual(aiter_calls, 2)
        self.assertEqual(yielded, [100, 200])
        self.assertEqual(buffer, [i for i in range(1, 21)] + ['end'])


        buffer = []
        async def test3():
            nonlocal buffer
            with self.assertWarnsRegex(DeprecationWarning, "legacy"):
                async for i in AsyncIter():
                    if i[0] > 20:
                        continue
                    buffer.append(i[0])
                else:
                    buffer.append('what?')
            buffer.append('end')

        yielded, _ = run_async(test3())
        # Make sure that __aiter__ was called only once
        self.assertEqual(aiter_calls, 3)
        self.assertEqual(yielded, [i * 100 for i in range(1, 11)])
        self.assertEqual(buffer, [i for i in range(1, 21)] +
                                 ['what?', 'end'])

    def test_for_2(self):
        tup = (1, 2, 3)
        refs_before = getrefcount(tup)

        async def foo():
            async for i in tup:
                print('never going to happen')

        with self.assertRaisesRegex(
                TypeError, "async for' requires an object.*__aiter__.*tuple"):

            run_async(foo())

        self.assertEqual(getrefcount(tup), refs_before)

    def test_for_3(self):
        class I(object):
            def __aiter__(self):
                return self

        aiter = I()
        refs_before = getrefcount(aiter)

        async def foo():
            async for i in aiter:
                print('never going to happen')

        with self.assertRaisesRegex(
                TypeError,
                "async for' received an invalid object.*__aiter.*\: I"):

            run_async(foo())

        self.assertEqual(getrefcount(aiter), refs_before)

    def test_for_4(self):
        class I(object):
            def __aiter__(self):
                return self

            def __anext__(self):
                return ()

        aiter = I()
        refs_before = getrefcount(aiter)

        async def foo():
            async for i in aiter:
                print('never going to happen')

        with self.assertRaisesRegex(
                TypeError,
                "async for' received an invalid object.*__anext__.*tuple"):

            run_async(foo())

        self.assertEqual(getrefcount(aiter), refs_before)

    def test_for_5(self):
        class I(object):
            async def __aiter__(self):
                return self

            def __anext__(self):
                return 123

        async def foo():
            with self.assertWarnsRegex(DeprecationWarning, "legacy"):
                async for i in I():
                    print('never going to happen')

        with self.assertRaisesRegex(
                TypeError,
                "async for' received an invalid object.*__anext.*int"):

            run_async(foo())

    def test_for_6(self):
        I = 0

        class Manager(object):
            async def __aenter__(self):
                nonlocal I
                I += 10000

            async def __aexit__(self, *args):
                nonlocal I
                I += 100000

        class Iterable(object):
            def __init__(self):
                self.i = 0

            def __aiter__(self):
                return self

            async def __anext__(self):
                if self.i > 10:
                    raise StopAsyncIteration
                self.i += 1
                return self.i

        ##############

        manager = Manager()
        iterable = Iterable()
        mrefs_before = getrefcount(manager)
        irefs_before = getrefcount(iterable)

        async def main():
            nonlocal I

            async with manager:
                async for i in iterable:
                    I += 1
            I += 1000

        run_async(main())
        self.assertEqual(I, 111011)

        self.assertEqual(getrefcount(manager), mrefs_before)
        self.assertEqual(getrefcount(iterable), irefs_before)

        ##############

        async def main():
            nonlocal I

            async with Manager():
                async for i in Iterable():
                    I += 1
            I += 1000

            async with Manager():
                async for i in Iterable():
                    I += 1
            I += 1000

        run_async(main())
        self.assertEqual(I, 333033)

        ##############

        async def main():
            nonlocal I

            async with Manager():
                I += 100
                async for i in Iterable():
                    I += 1
                else:
                    I += 10000000
            I += 1000

            async with Manager():
                I += 100
                async for i in Iterable():
                    I += 1
                else:
                    I += 10000000
            I += 1000

        run_async(main())
        self.assertEqual(I, 20555255)

    # old-style pre-Py3.5.2 protocol - no longer supported
    def __test_for_7(self):
        CNT = 0
        class AI(object):
            async def __aiter__(self):
                1/0
        async def foo():
            nonlocal CNT
            with self.assertWarnsRegex(DeprecationWarning, "legacy"):
                async for i in AI():
                    CNT += 1
            CNT += 10
        with self.assertRaises(ZeroDivisionError):
            run_async(foo())
        self.assertEqual(CNT, 0)

    def test_for_8(self):
        CNT = 0
        class AI(object):
            def __aiter__(self):
                1/0
        async def foo():
            nonlocal CNT
            async for i in AI():
                CNT += 1
            CNT += 10
        with self.assertRaises(ZeroDivisionError):
            #run_async(foo())
            with warnings.catch_warnings():
                warnings.simplefilter("error")
                # Test that if __aiter__ raises an exception it propagates
                # without any kind of warning.
                run_async(foo())
        self.assertEqual(CNT, 0)

    # old-style pre-Py3.5.2 protocol - no longer supported
    def __test_for_9(self):
        # Test that DeprecationWarning can safely be converted into
        # an exception (__aiter__ should not have a chance to raise
        # a ZeroDivisionError.)
        class AI(object):
            async def __aiter__(self):
                1/0
        async def foo():
            async for i in AI():
                pass

        with self.assertRaises(DeprecationWarning):
            with warnings.catch_warnings():
                warnings.simplefilter("error")
                run_async(foo())

    # old-style pre-Py3.5.2 protocol - no longer supported
    def __test_for_10(self):
        # Test that DeprecationWarning can safely be converted into
        # an exception.
        class AI(object):
            async def __aiter__(self):
                pass
        async def foo():
            async for i in AI():
                pass

        with self.assertRaises(DeprecationWarning):
            with warnings.catch_warnings():
                warnings.simplefilter("error")
                run_async(foo())

    def test_for_11(self):
        class F(object):
            def __aiter__(self):
                return self
            def __anext__(self):
                return self
            def __await__(self):
                1 / 0

        async def main():
            async for _ in F():
                pass

        if sys.version_info[0] < 3:
            with self.assertRaises(ZeroDivisionError) as c:
                main().send(None)
        else:
            with self.assertRaisesRegex(TypeError,
                                        'an invalid object from __anext__') as c:
                main().send(None)

            err = c.exception
            self.assertIsInstance(err.__cause__, ZeroDivisionError)

    # old-style pre-Py3.5.2 protocol - no longer supported
    def __test_for_12(self):
        class F(object):
            def __aiter__(self):
                return self
            def __await__(self):
                1 / 0

        async def main():
            async for _ in F():
                pass

        if sys.version_info[0] < 3:
            with self.assertRaises(ZeroDivisionError) as c:
                main().send(None)
        else:
            with self.assertRaisesRegex(TypeError,
                                        'an invalid object from __aiter__') as c:
                main().send(None)

            err = c.exception
            self.assertIsInstance(err.__cause__, ZeroDivisionError)

    def test_for_tuple(self):
        class Done(Exception): pass

        class AIter(tuple):
            i = 0
            def __aiter__(self):
                return self
            async def __anext__(self):
                if self.i >= len(self):
                    raise StopAsyncIteration
                self.i += 1
                return self[self.i - 1]

        result = []
        async def foo():
            async for i in AIter([42]):
                result.append(i)
            raise Done

        with self.assertRaises(Done):
            foo().send(None)
        self.assertEqual(result, [42])

    def test_for_stop_iteration(self):
        class Done(Exception): pass

        class AIter(StopIteration):
            i = 0
            def __aiter__(self):
                return self
            async def __anext__(self):
                if self.i:
                    raise StopAsyncIteration
                self.i += 1
                if sys.version_info >= (3, 3):
                    return self.value
                else:
                    return self.args[0]

        result = []
        async def foo():
            async for i in AIter(42):
                result.append(i)
            raise Done

        with self.assertRaises(Done):
            foo().send(None)
        self.assertEqual(result, [42])

    def test_comp_1(self):
        async def f(i):
            return i

        async def run_list():
            return [await c for c in [f(1), f(41)]]

        async def run_set():
            return {await c for c in [f(1), f(41)]}

        async def run_dict1():
            return {await c: 'a' for c in [f(1), f(41)]}

        async def run_dict2():
            return {i: await c for i, c in enumerate([f(1), f(41)])}

        self.assertEqual(run_async(run_list()), ([], [1, 41]))
        self.assertEqual(run_async(run_set()), ([], {1, 41}))
        self.assertEqual(run_async(run_dict1()), ([], {1: 'a', 41: 'a'}))
        self.assertEqual(run_async(run_dict2()), ([], {0: 1, 1: 41}))

    def test_comp_2(self):
        async def f(i):
            return i

        async def run_list():
            return [s for c in [f(''), f('abc'), f(''), f(['de', 'fg'])]
                    for s in await c]

        self.assertEqual(
            run_async(run_list()),
            ([], ['a', 'b', 'c', 'de', 'fg']))

        async def run_set():
            return {d
                    for c in [f([f([10, 30]),
                                 f([20])])]
                    for s in await c
                    for d in await s}

        self.assertEqual(
            run_async(run_set()),
            ([], {10, 20, 30}))

        async def run_set2():
            return {await s
                    for c in [f([f(10), f(20)])]
                    for s in await c}

        self.assertEqual(
            run_async(run_set2()),
            ([], {10, 20}))

    def test_comp_3(self):
        async def f(it):
            for i in it:
                yield i

        async def run_list():
            return [i + 1 async for i in f([10, 20])]
        self.assertEqual(
            run_async(run_list()),
            ([], [11, 21]))

        async def run_set():
            return {i + 1 async for i in f([10, 20])}
        self.assertEqual(
            run_async(run_set()),
            ([], {11, 21}))

        async def run_dict():
            return {i + 1: i + 2 async for i in f([10, 20])}
        self.assertEqual(
            run_async(run_dict()),
            ([], {11: 12, 21: 22}))

        async def run_gen():
            gen = (i + 1 async for i in f([10, 20]))
            return [g + 100 async for g in gen]
        self.assertEqual(
            run_async(run_gen()),
            ([], [111, 121]))

    def test_comp_4(self):
        async def f(it):
            for i in it:
                yield i

        async def run_list():
            return [i + 1 async for i in f([10, 20]) if i > 10]
        self.assertEqual(
            run_async(run_list()),
            ([], [21]))

        async def run_set():
            return {i + 1 async for i in f([10, 20]) if i > 10}
        self.assertEqual(
            run_async(run_set()),
            ([], {21}))

        async def run_dict():
            return {i + 1: i + 2 async for i in f([10, 20]) if i > 10}
        self.assertEqual(
            run_async(run_dict()),
            ([], {21: 22}))

        async def run_gen():
            gen = (i + 1 async for i in f([10, 20]) if i > 10)
            return [g + 100 async for g in gen]
        self.assertEqual(
            run_async(run_gen()),
            ([], [121]))

    def test_comp_5(self):
        async def f(it):
            for i in it:
                yield i

        async def run_list():
            return [i + 1 for pair in ([10, 20], [30, 40]) if pair[0] > 10
                    async for i in f(pair) if i > 30]
        self.assertEqual(
            run_async(run_list()),
            ([], [41]))

    def test_comp_6(self):
        async def f(it):
            for i in it:
                yield i

        async def run_list():
            return [i + 1 async for seq in f([(10, 20), (30,)])
                    for i in seq]

        self.assertEqual(
            run_async(run_list()),
            ([], [11, 21, 31]))

    def test_comp_7(self):
        async def f():
            yield 1
            yield 2
            raise Exception('aaa')

        async def run_list():
            return [i async for i in f()]

        with self.assertRaisesRegex(Exception, 'aaa'):
            run_async(run_list())

    def test_comp_8(self):
        async def f():
            return [i for i in [1, 2, 3]]

        self.assertEqual(
            run_async(f()),
            ([], [1, 2, 3]))

    def test_comp_9(self):
        async def gen():
            yield 1
            yield 2
        async def f():
            l = [i async for i in gen()]
            return [i for i in l]

        self.assertEqual(
            run_async(f()),
            ([], [1, 2]))

    def test_comp_10(self):
        async def f():
            xx = {i for i in [1, 2, 3]}
            return {x: x for x in xx}

        self.assertEqual(
            run_async(f()),
            ([], {1: 1, 2: 2, 3: 3}))

    def test_copy(self):
        async def func(): pass
        coro = func()
        with self.assertRaises(TypeError):
            copy.copy(coro)

        aw = coro.__await__()
        try:
            with self.assertRaises(TypeError):
                copy.copy(aw)
        finally:
            aw.close()

    def test_pickle(self):
        async def func(): pass
        coro = func()
        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
            with self.assertRaises((TypeError, pickle.PicklingError)):
                pickle.dumps(coro, proto)

        aw = coro.__await__()
        try:
            for proto in range(pickle.HIGHEST_PROTOCOL + 1):
                with self.assertRaises((TypeError, pickle.PicklingError)):
                    pickle.dumps(aw, proto)
        finally:
            aw.close()

    @no_pypy
    def test_fatal_coro_warning(self):
        # Issue 27811
        async def func(): pass

        gc.collect()
        with warnings.catch_warnings(), captured_stderr() as stderr:
            warnings.filterwarnings("error")
            func()
            gc.collect()
        self.assertIn("was never awaited", stderr.getvalue())


class CoroAsyncIOCompatTest(unittest.TestCase):

    def test_asyncio_1(self):
        import asyncio

        class MyException(Exception):
            pass

        buffer = []

        class CM(object):
            async def __aenter__(self):
                buffer.append(1)
                await asyncio.sleep(0.01)
                buffer.append(2)
                return self

            async def __aexit__(self, exc_type, exc_val, exc_tb):
                await asyncio.sleep(0.01)
                buffer.append(exc_type.__name__)

        async def f():
            async with CM() as c:
                await asyncio.sleep(0.01)
                raise MyException
            buffer.append('unreachable')

        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        try:
            loop.run_until_complete(f())
        except MyException:
            pass
        finally:
            loop.close()
            asyncio.set_event_loop(None)

        self.assertEqual(buffer, [1, 2, 'MyException'])

    def test_asyncio_cython_crash_gh1999(self):
        async def await_future(loop):
            fut = loop.create_future()
            loop.call_later(1, lambda: fut.set_result(1))
            await fut

        async def delegate_to_await_future(loop):
            await await_future(loop)

        ns = {}
        __builtins__.exec("""
        async def call(loop, await_func):  # requires Py3.5+
            await await_func(loop)
        """.strip(), ns, ns)
        call = ns['call']

        import asyncio
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        try:
            loop.run_until_complete(call(loop, delegate_to_await_future))
        finally:
            loop.close()
            asyncio.set_event_loop(None)


class SysSetCoroWrapperTest(unittest.TestCase):

    def test_set_wrapper_1(self):
        async def foo():
            return 'spam'

        wrapped = None
        def wrap(gen):
            nonlocal wrapped
            wrapped = gen
            return gen

        self.assertIsNone(sys.get_coroutine_wrapper())

        sys.set_coroutine_wrapper(wrap)
        self.assertIs(sys.get_coroutine_wrapper(), wrap)
        try:
            f = foo()
            self.assertTrue(wrapped)

            self.assertEqual(run_async(f), ([], 'spam'))
        finally:
            sys.set_coroutine_wrapper(None)

        self.assertIsNone(sys.get_coroutine_wrapper())

        wrapped = None
        with silence_coro_gc():
            foo()
        self.assertFalse(wrapped)

    def test_set_wrapper_2(self):
        self.assertIsNone(sys.get_coroutine_wrapper())
        with self.assertRaisesRegex(TypeError, "callable expected, got int"):
            sys.set_coroutine_wrapper(1)
        self.assertIsNone(sys.get_coroutine_wrapper())

    def test_set_wrapper_3(self):
        async def foo():
            return 'spam'

        def wrapper(coro):
            async def wrap(coro):
                return await coro
            return wrap(coro)

        sys.set_coroutine_wrapper(wrapper)
        try:
            with silence_coro_gc(), self.assertRaisesRegex(
                RuntimeError,
                "coroutine wrapper.*\.wrapper at 0x.*attempted to "
                "recursively wrap .* wrap .*"):

                foo()
        finally:
            sys.set_coroutine_wrapper(None)

    def test_set_wrapper_4(self):
        @types_coroutine
        def foo():
            return 'spam'

        wrapped = None
        def wrap(gen):
            nonlocal wrapped
            wrapped = gen
            return gen

        sys.set_coroutine_wrapper(wrap)
        try:
            foo()
            self.assertIs(
                wrapped, None,
                "generator-based coroutine was wrapped via "
                "sys.set_coroutine_wrapper")
        finally:
            sys.set_coroutine_wrapper(None)


class CAPITest(unittest.TestCase):

    def test_tp_await_1(self):
        from _testcapi import awaitType as at

        async def foo():
            future = at(iter([1]))
            return (await future)

        self.assertEqual(foo().send(None), 1)

    def test_tp_await_2(self):
        # Test tp_await to __await__ mapping
        from _testcapi import awaitType as at
        future = at(iter([1]))
        self.assertEqual(next(future.__await__()), 1)

    def test_tp_await_3(self):
        from _testcapi import awaitType as at

        async def foo():
            future = at(1)
            return (await future)

        with self.assertRaisesRegex(
                TypeError, "__await__.*returned non-iterator of type 'int'"):
            self.assertEqual(foo().send(None), 1)


# disable some tests that only apply to CPython

# TODO?
if True or sys.version_info < (3, 5):
    SysSetCoroWrapperTest = None
    CAPITest = None

if sys.version_info < (3, 5):  # (3, 4, 4)
    CoroAsyncIOCompatTest = None
else:
    try:
        import asyncio
    except ImportError:
        CoroAsyncIOCompatTest = None

if __name__=="__main__":
    unittest.main()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/test_dataclasses.pxi0000644000175100001770000000107100000000000021611 0ustar00runnerdocker00000000000000from cython cimport cclass
from dataclasses import (
    dataclass, field,
    fields, FrozenInstanceError, InitVar, is_dataclass, asdict, astuple, replace
)
import unittest
from unittest.mock import Mock
import pickle
import inspect
from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional
from typing import get_type_hints
from collections import deque, OrderedDict, namedtuple
import sys

def skip_on_versions_below(version):
    def decorator(func):
        if sys.version_info >= version:
            return func
    return decorator
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/test_dataclasses.pyx0000644000175100001770000010561100000000000021636 0ustar00runnerdocker00000000000000# AUTO-GENERATED BY Tools/make_dataclass_tests.py
# DO NOT EDIT

# cython: language_level=3
include "test_dataclasses.pxi"

@dataclass
@cclass
class C_TestCase_test_no_fields:
    pass

@dataclass
@cclass
class C_TestCase_test_no_fields_but_member_variable:
    i = 0

@dataclass
@cclass
class C_TestCase_test_one_field_no_default:
    x: int

@dataclass
@cclass
class C_TestCase_test_named_init_params:
    x: int

@dataclass
@cclass
class C_TestCase_test_field_named_object:
    object: str

@dataclass(frozen=True)
@cclass
class C_TestCase_test_field_named_object_frozen:
    object: str

@dataclass
@cclass
class C0_TestCase_test_0_field_compare:
    pass

@dataclass(order=False)
@cclass
class C1_TestCase_test_0_field_compare:
    pass

@dataclass(order=True)
@cclass
class C_TestCase_test_0_field_compare:
    pass

@dataclass
@cclass
class C0_TestCase_test_1_field_compare:
    x: int

@dataclass(order=False)
@cclass
class C1_TestCase_test_1_field_compare:
    x: int

@dataclass(order=True)
@cclass
class C_TestCase_test_1_field_compare:
    x: int

@dataclass
@cclass
class C0_TestCase_test_simple_compare:
    x: int
    y: int

@dataclass(order=False)
@cclass
class C1_TestCase_test_simple_compare:
    x: int
    y: int

@dataclass(order=True)
@cclass
class C_TestCase_test_simple_compare:
    x: int
    y: int

@dataclass
@cclass
class B_TestCase_test_compare_subclasses:
    i: int

@dataclass
@cclass
class C_TestCase_test_compare_subclasses(B_TestCase_test_compare_subclasses):
    pass

@dataclass
@cclass
class C_TestCase_test_field_no_default:
    x: int = field()

@dataclass
@cclass
class C_TestCase_test_not_in_compare:
    x: int = 0
    y: int = field(compare=False, default=4)

class Mutable_TestCase_test_deliberately_mutable_defaults:

    def __init__(self):
        self.l = []

@dataclass
@cclass
class C_TestCase_test_deliberately_mutable_defaults:
    x: Mutable_TestCase_test_deliberately_mutable_defaults

@dataclass()
@cclass
class C_TestCase_test_no_options:
    x: int

@dataclass
@cclass
class Point_TestCase_test_not_tuple:
    x: int
    y: int

@dataclass
@cclass
class C_TestCase_test_not_tuple:
    x: int
    y: int

@dataclass
@cclass
class Point3D_TestCase_test_not_other_dataclass:
    x: int
    y: int
    z: int

@dataclass
@cclass
class Date_TestCase_test_not_other_dataclass:
    year: int
    month: int
    day: int

@dataclass
@cclass
class Point3Dv1_TestCase_test_not_other_dataclass:
    x: int = 0
    y: int = 0
    z: int = 0

@dataclass
@cclass
class C_TestCase_test_class_var_no_default:
    x: ClassVar[int]

@dataclass
@cclass
class C_TestCase_test_init_var:
    x: int = None
    init_param: InitVar[int] = None

    def __post_init__(self, init_param):
        if self.x is None:
            self.x = init_param * 2

@dataclass
@cclass
class Foo_TestCase_test_default_factory_derived:
    x: dict = field(default_factory=dict)

@dataclass
@cclass
class Bar_TestCase_test_default_factory_derived(Foo_TestCase_test_default_factory_derived):
    y: int = 1

@dataclass
@cclass
class Baz_TestCase_test_default_factory_derived(Foo_TestCase_test_default_factory_derived):
    pass

@dataclass
@cclass
class A_TestCase_test_intermediate_non_dataclass:
    x: int

@cclass
class B_TestCase_test_intermediate_non_dataclass(A_TestCase_test_intermediate_non_dataclass):
    y: int

@dataclass
@cclass
class C_TestCase_test_intermediate_non_dataclass(B_TestCase_test_intermediate_non_dataclass):
    z: int

class D_TestCase_test_intermediate_non_dataclass(C_TestCase_test_intermediate_non_dataclass):
    t: int

class NotDataClass_TestCase_test_is_dataclass:
    pass

@dataclass
@cclass
class C_TestCase_test_is_dataclass:
    x: int

@dataclass
@cclass
class D_TestCase_test_is_dataclass:
    d: C_TestCase_test_is_dataclass
    e: int

class A_TestCase_test_is_dataclass_when_getattr_always_returns:

    def __getattr__(self, key):
        return 0

class B_TestCase_test_is_dataclass_when_getattr_always_returns:
    pass

@dataclass
@cclass
class C_TestCase_test_helper_fields_with_class_instance:
    x: int
    y: float

class C_TestCase_test_helper_fields_exception:
    pass

@dataclass
@cclass
class C_TestCase_test_helper_asdict:
    x: int
    y: int

@dataclass
@cclass
class C_TestCase_test_helper_asdict_raises_on_classes:
    x: int
    y: int

@dataclass
@cclass
class C_TestCase_test_helper_asdict_copy_values:
    x: int
    y: List[int] = field(default_factory=list)

@dataclass
@cclass
class UserId_TestCase_test_helper_asdict_nested:
    token: int
    group: int

@dataclass
@cclass
class User_TestCase_test_helper_asdict_nested:
    name: str
    id: UserId_TestCase_test_helper_asdict_nested

@dataclass
@cclass
class User_TestCase_test_helper_asdict_builtin_containers:
    name: str
    id: int

@dataclass
@cclass
class GroupList_TestCase_test_helper_asdict_builtin_containers:
    id: int
    users: List[User_TestCase_test_helper_asdict_builtin_containers]

@dataclass
@cclass
class GroupTuple_TestCase_test_helper_asdict_builtin_containers:
    id: int
    users: Tuple[User_TestCase_test_helper_asdict_builtin_containers, ...]

@dataclass
@cclass
class GroupDict_TestCase_test_helper_asdict_builtin_containers:
    id: int
    users: Dict[str, User_TestCase_test_helper_asdict_builtin_containers]

@dataclass
@cclass
class Child_TestCase_test_helper_asdict_builtin_object_containers:
    d: object

@dataclass
@cclass
class Parent_TestCase_test_helper_asdict_builtin_object_containers:
    child: Child_TestCase_test_helper_asdict_builtin_object_containers

@dataclass
@cclass
class C_TestCase_test_helper_asdict_factory:
    x: int
    y: int

@dataclass
@cclass
class C_TestCase_test_helper_asdict_namedtuple:
    x: str
    y: T

@dataclass
@cclass
class C_TestCase_test_helper_asdict_namedtuple_key:
    f: dict

class T_TestCase_test_helper_asdict_namedtuple_derived(namedtuple('Tbase', 'a')):

    def my_a(self):
        return self.a

@dataclass
@cclass
class C_TestCase_test_helper_asdict_namedtuple_derived:
    f: T_TestCase_test_helper_asdict_namedtuple_derived

@dataclass
@cclass
class C_TestCase_test_helper_astuple:
    x: int
    y: int = 0

@dataclass
@cclass
class C_TestCase_test_helper_astuple_raises_on_classes:
    x: int
    y: int

@dataclass
@cclass
class C_TestCase_test_helper_astuple_copy_values:
    x: int
    y: List[int] = field(default_factory=list)

@dataclass
@cclass
class UserId_TestCase_test_helper_astuple_nested:
    token: int
    group: int

@dataclass
@cclass
class User_TestCase_test_helper_astuple_nested:
    name: str
    id: UserId_TestCase_test_helper_astuple_nested

@dataclass
@cclass
class User_TestCase_test_helper_astuple_builtin_containers:
    name: str
    id: int

@dataclass
@cclass
class GroupList_TestCase_test_helper_astuple_builtin_containers:
    id: int
    users: List[User_TestCase_test_helper_astuple_builtin_containers]

@dataclass
@cclass
class GroupTuple_TestCase_test_helper_astuple_builtin_containers:
    id: int
    users: Tuple[User_TestCase_test_helper_astuple_builtin_containers, ...]

@dataclass
@cclass
class GroupDict_TestCase_test_helper_astuple_builtin_containers:
    id: int
    users: Dict[str, User_TestCase_test_helper_astuple_builtin_containers]

@dataclass
@cclass
class Child_TestCase_test_helper_astuple_builtin_object_containers:
    d: object

@dataclass
@cclass
class Parent_TestCase_test_helper_astuple_builtin_object_containers:
    child: Child_TestCase_test_helper_astuple_builtin_object_containers

@dataclass
@cclass
class C_TestCase_test_helper_astuple_factory:
    x: int
    y: int

@dataclass
@cclass
class C_TestCase_test_helper_astuple_namedtuple:
    x: str
    y: T

@dataclass
@cclass
class C_TestCase_test_alternate_classmethod_constructor:
    x: int

    @classmethod
    def from_file(cls, filename):
        value_in_file = 20
        return cls(value_in_file)

@dataclass
@cclass
class C_TestCase_test_field_metadata_default:
    i: int

@dataclass
@cclass
class P_TestCase_test_dataclasses_pickleable:
    x: int
    y: int = 0

@dataclass
@cclass
class Q_TestCase_test_dataclasses_pickleable:
    x: int
    y: int = field(default=0, init=False)

@dataclass
@cclass
class R_TestCase_test_dataclasses_pickleable:
    x: int
    y: List[int] = field(default_factory=list)

@dataclass
@cclass
class C_TestInit_test_overwriting_init:
    x: int

    def __init__(self, x):
        self.x = 2 * x

@dataclass(init=True)
@cclass
class C_TestInit_test_overwriting_init_:
    x: int

    def __init__(self, x):
        self.x = 2 * x

@dataclass(init=False)
@cclass
class C_TestInit_test_overwriting_init__:
    x: int

    def __init__(self, x):
        self.x = 2 * x

@dataclass
@cclass
class C_TestRepr_test_overwriting_repr:
    x: int

    def __repr__(self):
        return 'x'

@dataclass(repr=True)
@cclass
class C_TestRepr_test_overwriting_repr_:
    x: int

    def __repr__(self):
        return 'x'

@dataclass(repr=False)
@cclass
class C_TestRepr_test_overwriting_repr__:
    x: int

    def __repr__(self):
        return 'x'

@dataclass(eq=False)
@cclass
class C_TestEq_test_no_eq:
    x: int

@dataclass(eq=False)
@cclass
class C_TestEq_test_no_eq_:
    x: int

    def __eq__(self, other):
        return other == 10

@dataclass
@cclass
class C_TestEq_test_overwriting_eq:
    x: int

    def __eq__(self, other):
        return other == 3

@dataclass(eq=True)
@cclass
class C_TestEq_test_overwriting_eq_:
    x: int

    def __eq__(self, other):
        return other == 4

@dataclass(eq=False)
@cclass
class C_TestEq_test_overwriting_eq__:
    x: int

    def __eq__(self, other):
        return other == 5

@dataclass(unsafe_hash=True)
@cclass
class C_TestHash_test_unsafe_hash:
    x: int
    y: str

@dataclass(frozen=True)
@cclass
class C_TestHash_test_0_field_hash:
    pass

@dataclass(unsafe_hash=True)
@cclass
class C_TestHash_test_0_field_hash_:
    pass

@dataclass(frozen=True)
@cclass
class C_TestHash_test_1_field_hash:
    x: int

@dataclass(unsafe_hash=True)
@cclass
class C_TestHash_test_1_field_hash_:
    x: int

class Base1_TestMakeDataclass_test_base:
    pass

class Base2_TestMakeDataclass_test_base:
    pass

@dataclass
@cclass
class Base1_TestMakeDataclass_test_base_dataclass:
    x: int

class Base2_TestMakeDataclass_test_base_dataclass:
    pass

@dataclass(frozen=True)
@cclass
class C_TestReplace_test:
    x: int
    y: int

@dataclass(frozen=True)
@cclass
class C_TestReplace_test_invalid_field_name:
    x: int
    y: int

@dataclass(frozen=True)
@cclass
class C_TestReplace_test_invalid_object:
    x: int
    y: int

@dataclass
@cclass
class C_TestReplace_test_no_init:
    x: int
    y: int = field(init=False, default=10)

@dataclass
@cclass
class C_TestReplace_test_classvar:
    x: int
    y: ClassVar[int] = 1000

@dataclass
@cclass
class C_TestReplace_test_initvar_is_specified:
    x: int
    y: InitVar[int]

    def __post_init__(self, y):
        self.x *= y

@dataclass
@cclass
class C_TestReplace_test_recursive_repr:
    f: object

@dataclass
@cclass
class C_TestReplace_test_recursive_repr_two_attrs:
    f: object
    g: object

@dataclass
@cclass
class C_TestReplace_test_recursive_repr_indirection:
    f: object

@dataclass
@cclass
class D_TestReplace_test_recursive_repr_indirection:
    f: object

@dataclass
@cclass
class C_TestReplace_test_recursive_repr_indirection_two:
    f: object

@dataclass
@cclass
class D_TestReplace_test_recursive_repr_indirection_two:
    f: object

@dataclass
@cclass
class E_TestReplace_test_recursive_repr_indirection_two:
    f: object

@dataclass
@cclass
class C_TestReplace_test_recursive_repr_misc_attrs:
    f: object
    g: int

class CustomError(Exception):
    pass

class TestCase(unittest.TestCase):

    def test_no_fields(self):
        C = C_TestCase_test_no_fields
        o = C()
        self.assertEqual(len(fields(C)), 0)

    def test_no_fields_but_member_variable(self):
        C = C_TestCase_test_no_fields_but_member_variable
        o = C()
        self.assertEqual(len(fields(C)), 0)

    def test_one_field_no_default(self):
        C = C_TestCase_test_one_field_no_default
        o = C(42)
        self.assertEqual(o.x, 42)

    def test_named_init_params(self):
        C = C_TestCase_test_named_init_params
        o = C(x=32)
        self.assertEqual(o.x, 32)

    def test_field_named_object(self):
        C = C_TestCase_test_field_named_object
        c = C('foo')
        self.assertEqual(c.object, 'foo')

    def test_field_named_object_frozen(self):
        C = C_TestCase_test_field_named_object_frozen
        c = C('foo')
        self.assertEqual(c.object, 'foo')

    def test_0_field_compare(self):
        C0 = C0_TestCase_test_0_field_compare
        C1 = C1_TestCase_test_0_field_compare
        for cls in [C0, C1]:
            with self.subTest(cls=cls):
                self.assertEqual(cls(), cls())
                for idx, fn in enumerate([lambda a, b: a < b, lambda a, b: a <= b, lambda a, b: a > b, lambda a, b: a >= b]):
                    with self.subTest(idx=idx):
                        with self.assertRaises(TypeError):
                            fn(cls(), cls())
        C = C_TestCase_test_0_field_compare
        self.assertLessEqual(C(), C())
        self.assertGreaterEqual(C(), C())

    def test_1_field_compare(self):
        C0 = C0_TestCase_test_1_field_compare
        C1 = C1_TestCase_test_1_field_compare
        for cls in [C0, C1]:
            with self.subTest(cls=cls):
                self.assertEqual(cls(1), cls(1))
                self.assertNotEqual(cls(0), cls(1))
                for idx, fn in enumerate([lambda a, b: a < b, lambda a, b: a <= b, lambda a, b: a > b, lambda a, b: a >= b]):
                    with self.subTest(idx=idx):
                        with self.assertRaises(TypeError):
                            fn(cls(0), cls(0))
        C = C_TestCase_test_1_field_compare
        self.assertLess(C(0), C(1))
        self.assertLessEqual(C(0), C(1))
        self.assertLessEqual(C(1), C(1))
        self.assertGreater(C(1), C(0))
        self.assertGreaterEqual(C(1), C(0))
        self.assertGreaterEqual(C(1), C(1))

    def test_simple_compare(self):
        C0 = C0_TestCase_test_simple_compare
        C1 = C1_TestCase_test_simple_compare
        for cls in [C0, C1]:
            with self.subTest(cls=cls):
                self.assertEqual(cls(0, 0), cls(0, 0))
                self.assertEqual(cls(1, 2), cls(1, 2))
                self.assertNotEqual(cls(1, 0), cls(0, 0))
                self.assertNotEqual(cls(1, 0), cls(1, 1))
                for idx, fn in enumerate([lambda a, b: a < b, lambda a, b: a <= b, lambda a, b: a > b, lambda a, b: a >= b]):
                    with self.subTest(idx=idx):
                        with self.assertRaises(TypeError):
                            fn(cls(0, 0), cls(0, 0))
        C = C_TestCase_test_simple_compare
        for idx, fn in enumerate([lambda a, b: a == b, lambda a, b: a <= b, lambda a, b: a >= b]):
            with self.subTest(idx=idx):
                self.assertTrue(fn(C(0, 0), C(0, 0)))
        for idx, fn in enumerate([lambda a, b: a < b, lambda a, b: a <= b, lambda a, b: a != b]):
            with self.subTest(idx=idx):
                self.assertTrue(fn(C(0, 0), C(0, 1)))
                self.assertTrue(fn(C(0, 1), C(1, 0)))
                self.assertTrue(fn(C(1, 0), C(1, 1)))
        for idx, fn in enumerate([lambda a, b: a > b, lambda a, b: a >= b, lambda a, b: a != b]):
            with self.subTest(idx=idx):
                self.assertTrue(fn(C(0, 1), C(0, 0)))
                self.assertTrue(fn(C(1, 0), C(0, 1)))
                self.assertTrue(fn(C(1, 1), C(1, 0)))

    def test_compare_subclasses(self):
        B = B_TestCase_test_compare_subclasses
        C = C_TestCase_test_compare_subclasses
        for idx, (fn, expected) in enumerate([(lambda a, b: a == b, False), (lambda a, b: a != b, True)]):
            with self.subTest(idx=idx):
                self.assertEqual(fn(B(0), C(0)), expected)
        for idx, fn in enumerate([lambda a, b: a < b, lambda a, b: a <= b, lambda a, b: a > b, lambda a, b: a >= b]):
            with self.subTest(idx=idx):
                with self.assertRaises(TypeError):
                    fn(B(0), C(0))

    def test_field_no_default(self):
        C = C_TestCase_test_field_no_default
        self.assertEqual(C(5).x, 5)
        with self.assertRaises(TypeError):
            C()

    def test_not_in_compare(self):
        C = C_TestCase_test_not_in_compare
        self.assertEqual(C(), C(0, 20))
        self.assertEqual(C(1, 10), C(1, 20))
        self.assertNotEqual(C(3), C(4, 10))
        self.assertNotEqual(C(3, 10), C(4, 10))

    def test_deliberately_mutable_defaults(self):
        Mutable = Mutable_TestCase_test_deliberately_mutable_defaults
        C = C_TestCase_test_deliberately_mutable_defaults
        lst = Mutable()
        o1 = C(lst)
        o2 = C(lst)
        self.assertEqual(o1, o2)
        o1.x.l.extend([1, 2])
        self.assertEqual(o1, o2)
        self.assertEqual(o1.x.l, [1, 2])
        self.assertIs(o1.x, o2.x)

    def test_no_options(self):
        C = C_TestCase_test_no_options
        self.assertEqual(C(42).x, 42)

    def test_not_tuple(self):
        Point = Point_TestCase_test_not_tuple
        self.assertNotEqual(Point(1, 2), (1, 2))
        C = C_TestCase_test_not_tuple
        self.assertNotEqual(Point(1, 3), C(1, 3))

    def test_not_other_dataclass(self):
        Point3D = Point3D_TestCase_test_not_other_dataclass
        Date = Date_TestCase_test_not_other_dataclass
        self.assertNotEqual(Point3D(2017, 6, 3), Date(2017, 6, 3))
        self.assertNotEqual(Point3D(1, 2, 3), (1, 2, 3))
        with self.assertRaises(TypeError):
            x, y, z = Point3D(4, 5, 6)
        Point3Dv1 = Point3Dv1_TestCase_test_not_other_dataclass
        self.assertNotEqual(Point3D(0, 0, 0), Point3Dv1())

    def test_class_var_no_default(self):
        C = C_TestCase_test_class_var_no_default
        self.assertNotIn('x', C.__dict__)

    def test_init_var(self):
        C = C_TestCase_test_init_var
        c = C(init_param=10)
        self.assertEqual(c.x, 20)

    @skip_on_versions_below((3, 10))
    def test_init_var_preserve_type(self):
        self.assertEqual(InitVar[int].type, int)
        self.assertEqual(repr(InitVar[int]), 'dataclasses.InitVar[int]')
        self.assertEqual(repr(InitVar[List[int]]), 'dataclasses.InitVar[typing.List[int]]')
        self.assertEqual(repr(InitVar[list[int]]), 'dataclasses.InitVar[list[int]]')
        self.assertEqual(repr(InitVar[int | str]), 'dataclasses.InitVar[int | str]')

    def test_default_factory_derived(self):
        Foo = Foo_TestCase_test_default_factory_derived
        Bar = Bar_TestCase_test_default_factory_derived
        self.assertEqual(Foo().x, {})
        self.assertEqual(Bar().x, {})
        self.assertEqual(Bar().y, 1)
        Baz = Baz_TestCase_test_default_factory_derived
        self.assertEqual(Baz().x, {})

    def test_intermediate_non_dataclass(self):
        A = A_TestCase_test_intermediate_non_dataclass
        B = B_TestCase_test_intermediate_non_dataclass
        C = C_TestCase_test_intermediate_non_dataclass
        c = C(1, 3)
        self.assertEqual((c.x, c.z), (1, 3))
        with self.assertRaises(AttributeError):
            c.y
        D = D_TestCase_test_intermediate_non_dataclass
        d = D(4, 5)
        self.assertEqual((d.x, d.z), (4, 5))

    def test_is_dataclass(self):
        NotDataClass = NotDataClass_TestCase_test_is_dataclass
        self.assertFalse(is_dataclass(0))
        self.assertFalse(is_dataclass(int))
        self.assertFalse(is_dataclass(NotDataClass))
        self.assertFalse(is_dataclass(NotDataClass()))
        C = C_TestCase_test_is_dataclass
        D = D_TestCase_test_is_dataclass
        c = C(10)
        d = D(c, 4)
        self.assertTrue(is_dataclass(C))
        self.assertTrue(is_dataclass(c))
        self.assertFalse(is_dataclass(c.x))
        self.assertTrue(is_dataclass(d.d))
        self.assertFalse(is_dataclass(d.e))

    def test_is_dataclass_when_getattr_always_returns(self):
        A = A_TestCase_test_is_dataclass_when_getattr_always_returns
        self.assertFalse(is_dataclass(A))
        a = A()
        B = B_TestCase_test_is_dataclass_when_getattr_always_returns
        b = B()
        b.__dataclass_fields__ = []
        for obj in (a, b):
            with self.subTest(obj=obj):
                self.assertFalse(is_dataclass(obj))
                with self.assertRaises(TypeError):
                    asdict(obj)
                with self.assertRaises(TypeError):
                    astuple(obj)
                with self.assertRaises(TypeError):
                    replace(obj, x=0)

    def test_helper_fields_with_class_instance(self):
        C = C_TestCase_test_helper_fields_with_class_instance
        self.assertEqual(fields(C), fields(C(0, 0.0)))

    def test_helper_fields_exception(self):
        with self.assertRaises(TypeError):
            fields(0)
        C = C_TestCase_test_helper_fields_exception
        with self.assertRaises(TypeError):
            fields(C)
        with self.assertRaises(TypeError):
            fields(C())

    def test_helper_asdict(self):
        C = C_TestCase_test_helper_asdict
        c = C(1, 2)
        self.assertEqual(asdict(c), {'x': 1, 'y': 2})
        self.assertEqual(asdict(c), asdict(c))
        self.assertIsNot(asdict(c), asdict(c))
        c.x = 42
        self.assertEqual(asdict(c), {'x': 42, 'y': 2})
        self.assertIs(type(asdict(c)), dict)

    def test_helper_asdict_raises_on_classes(self):
        C = C_TestCase_test_helper_asdict_raises_on_classes
        with self.assertRaises(TypeError):
            asdict(C)
        with self.assertRaises(TypeError):
            asdict(int)

    def test_helper_asdict_copy_values(self):
        C = C_TestCase_test_helper_asdict_copy_values
        initial = []
        c = C(1, initial)
        d = asdict(c)
        self.assertEqual(d['y'], initial)
        self.assertIsNot(d['y'], initial)
        c = C(1)
        d = asdict(c)
        d['y'].append(1)
        self.assertEqual(c.y, [])

    def test_helper_asdict_nested(self):
        UserId = UserId_TestCase_test_helper_asdict_nested
        User = User_TestCase_test_helper_asdict_nested
        u = User('Joe', UserId(123, 1))
        d = asdict(u)
        self.assertEqual(d, {'name': 'Joe', 'id': {'token': 123, 'group': 1}})
        self.assertIsNot(asdict(u), asdict(u))
        u.id.group = 2
        self.assertEqual(asdict(u), {'name': 'Joe', 'id': {'token': 123, 'group': 2}})

    def test_helper_asdict_builtin_containers(self):
        User = User_TestCase_test_helper_asdict_builtin_containers
        GroupList = GroupList_TestCase_test_helper_asdict_builtin_containers
        GroupTuple = GroupTuple_TestCase_test_helper_asdict_builtin_containers
        GroupDict = GroupDict_TestCase_test_helper_asdict_builtin_containers
        a = User('Alice', 1)
        b = User('Bob', 2)
        gl = GroupList(0, [a, b])
        gt = GroupTuple(0, (a, b))
        gd = GroupDict(0, {'first': a, 'second': b})
        self.assertEqual(asdict(gl), {'id': 0, 'users': [{'name': 'Alice', 'id': 1}, {'name': 'Bob', 'id': 2}]})
        self.assertEqual(asdict(gt), {'id': 0, 'users': ({'name': 'Alice', 'id': 1}, {'name': 'Bob', 'id': 2})})
        self.assertEqual(asdict(gd), {'id': 0, 'users': {'first': {'name': 'Alice', 'id': 1}, 'second': {'name': 'Bob', 'id': 2}}})

    def test_helper_asdict_builtin_object_containers(self):
        Child = Child_TestCase_test_helper_asdict_builtin_object_containers
        Parent = Parent_TestCase_test_helper_asdict_builtin_object_containers
        self.assertEqual(asdict(Parent(Child([1]))), {'child': {'d': [1]}})
        self.assertEqual(asdict(Parent(Child({1: 2}))), {'child': {'d': {1: 2}}})

    def test_helper_asdict_factory(self):
        C = C_TestCase_test_helper_asdict_factory
        c = C(1, 2)
        d = asdict(c, dict_factory=OrderedDict)
        self.assertEqual(d, OrderedDict([('x', 1), ('y', 2)]))
        self.assertIsNot(d, asdict(c, dict_factory=OrderedDict))
        c.x = 42
        d = asdict(c, dict_factory=OrderedDict)
        self.assertEqual(d, OrderedDict([('x', 42), ('y', 2)]))
        self.assertIs(type(d), OrderedDict)

    def test_helper_asdict_namedtuple(self):
        T = namedtuple('T', 'a b c')
        C = C_TestCase_test_helper_asdict_namedtuple
        c = C('outer', T(1, C('inner', T(11, 12, 13)), 2))
        d = asdict(c)
        self.assertEqual(d, {'x': 'outer', 'y': T(1, {'x': 'inner', 'y': T(11, 12, 13)}, 2)})
        d = asdict(c, dict_factory=OrderedDict)
        self.assertEqual(d, {'x': 'outer', 'y': T(1, {'x': 'inner', 'y': T(11, 12, 13)}, 2)})
        self.assertIs(type(d), OrderedDict)
        self.assertIs(type(d['y'][1]), OrderedDict)

    def test_helper_asdict_namedtuple_key(self):
        C = C_TestCase_test_helper_asdict_namedtuple_key
        T = namedtuple('T', 'a')
        c = C({T('an a'): 0})
        self.assertEqual(asdict(c), {'f': {T(a='an a'): 0}})

    def test_helper_asdict_namedtuple_derived(self):
        T = T_TestCase_test_helper_asdict_namedtuple_derived
        C = C_TestCase_test_helper_asdict_namedtuple_derived
        t = T(6)
        c = C(t)
        d = asdict(c)
        self.assertEqual(d, {'f': T(a=6)})
        self.assertIsNot(d['f'], t)
        self.assertEqual(d['f'].my_a(), 6)

    def test_helper_astuple(self):
        C = C_TestCase_test_helper_astuple
        c = C(1)
        self.assertEqual(astuple(c), (1, 0))
        self.assertEqual(astuple(c), astuple(c))
        self.assertIsNot(astuple(c), astuple(c))
        c.y = 42
        self.assertEqual(astuple(c), (1, 42))
        self.assertIs(type(astuple(c)), tuple)

    def test_helper_astuple_raises_on_classes(self):
        C = C_TestCase_test_helper_astuple_raises_on_classes
        with self.assertRaises(TypeError):
            astuple(C)
        with self.assertRaises(TypeError):
            astuple(int)

    def test_helper_astuple_copy_values(self):
        C = C_TestCase_test_helper_astuple_copy_values
        initial = []
        c = C(1, initial)
        t = astuple(c)
        self.assertEqual(t[1], initial)
        self.assertIsNot(t[1], initial)
        c = C(1)
        t = astuple(c)
        t[1].append(1)
        self.assertEqual(c.y, [])

    def test_helper_astuple_nested(self):
        UserId = UserId_TestCase_test_helper_astuple_nested
        User = User_TestCase_test_helper_astuple_nested
        u = User('Joe', UserId(123, 1))
        t = astuple(u)
        self.assertEqual(t, ('Joe', (123, 1)))
        self.assertIsNot(astuple(u), astuple(u))
        u.id.group = 2
        self.assertEqual(astuple(u), ('Joe', (123, 2)))

    def test_helper_astuple_builtin_containers(self):
        User = User_TestCase_test_helper_astuple_builtin_containers
        GroupList = GroupList_TestCase_test_helper_astuple_builtin_containers
        GroupTuple = GroupTuple_TestCase_test_helper_astuple_builtin_containers
        GroupDict = GroupDict_TestCase_test_helper_astuple_builtin_containers
        a = User('Alice', 1)
        b = User('Bob', 2)
        gl = GroupList(0, [a, b])
        gt = GroupTuple(0, (a, b))
        gd = GroupDict(0, {'first': a, 'second': b})
        self.assertEqual(astuple(gl), (0, [('Alice', 1), ('Bob', 2)]))
        self.assertEqual(astuple(gt), (0, (('Alice', 1), ('Bob', 2))))
        self.assertEqual(astuple(gd), (0, {'first': ('Alice', 1), 'second': ('Bob', 2)}))

    def test_helper_astuple_builtin_object_containers(self):
        Child = Child_TestCase_test_helper_astuple_builtin_object_containers
        Parent = Parent_TestCase_test_helper_astuple_builtin_object_containers
        self.assertEqual(astuple(Parent(Child([1]))), (([1],),))
        self.assertEqual(astuple(Parent(Child({1: 2}))), (({1: 2},),))

    def test_helper_astuple_factory(self):
        C = C_TestCase_test_helper_astuple_factory
        NT = namedtuple('NT', 'x y')

        def nt(lst):
            return NT(*lst)
        c = C(1, 2)
        t = astuple(c, tuple_factory=nt)
        self.assertEqual(t, NT(1, 2))
        self.assertIsNot(t, astuple(c, tuple_factory=nt))
        c.x = 42
        t = astuple(c, tuple_factory=nt)
        self.assertEqual(t, NT(42, 2))
        self.assertIs(type(t), NT)

    def test_helper_astuple_namedtuple(self):
        T = namedtuple('T', 'a b c')
        C = C_TestCase_test_helper_astuple_namedtuple
        c = C('outer', T(1, C('inner', T(11, 12, 13)), 2))
        t = astuple(c)
        self.assertEqual(t, ('outer', T(1, ('inner', (11, 12, 13)), 2)))
        t = astuple(c, tuple_factory=list)
        self.assertEqual(t, ['outer', T(1, ['inner', T(11, 12, 13)], 2)])

    def test_alternate_classmethod_constructor(self):
        C = C_TestCase_test_alternate_classmethod_constructor
        self.assertEqual(C.from_file('filename').x, 20)

    def test_field_metadata_default(self):
        C = C_TestCase_test_field_metadata_default
        self.assertFalse(fields(C)[0].metadata)
        self.assertEqual(len(fields(C)[0].metadata), 0)
        with self.assertRaises(TypeError):
            fields(C)[0].metadata['test'] = 3

    def test_dataclasses_pickleable(self):
        global P, Q, R
        P = P_TestCase_test_dataclasses_pickleable
        Q = Q_TestCase_test_dataclasses_pickleable
        R = R_TestCase_test_dataclasses_pickleable
        q = Q(1)
        q.y = 2
        samples = [P(1), P(1, 2), Q(1), q, R(1), R(1, [2, 3, 4])]
        for sample in samples:
            for proto in range(pickle.HIGHEST_PROTOCOL + 1):
                with self.subTest(sample=sample, proto=proto):
                    new_sample = pickle.loads(pickle.dumps(sample, proto))
                    self.assertEqual(sample.x, new_sample.x)
                    self.assertEqual(sample.y, new_sample.y)
                    self.assertIsNot(sample, new_sample)
                    new_sample.x = 42
                    another_new_sample = pickle.loads(pickle.dumps(new_sample, proto))
                    self.assertEqual(new_sample.x, another_new_sample.x)
                    self.assertEqual(sample.y, another_new_sample.y)

class TestFieldNoAnnotation(unittest.TestCase):
    pass

class TestInit(unittest.TestCase):

    def test_overwriting_init(self):
        C = C_TestInit_test_overwriting_init
        self.assertEqual(C(3).x, 6)
        C = C_TestInit_test_overwriting_init_
        self.assertEqual(C(4).x, 8)
        C = C_TestInit_test_overwriting_init__
        self.assertEqual(C(5).x, 10)

class TestRepr(unittest.TestCase):

    def test_overwriting_repr(self):
        C = C_TestRepr_test_overwriting_repr
        self.assertEqual(repr(C(0)), 'x')
        C = C_TestRepr_test_overwriting_repr_
        self.assertEqual(repr(C(0)), 'x')
        C = C_TestRepr_test_overwriting_repr__
        self.assertEqual(repr(C(0)), 'x')

class TestEq(unittest.TestCase):

    def test_no_eq(self):
        C = C_TestEq_test_no_eq
        self.assertNotEqual(C(0), C(0))
        c = C(3)
        self.assertEqual(c, c)
        C = C_TestEq_test_no_eq_
        self.assertEqual(C(3), 10)

    def test_overwriting_eq(self):
        C = C_TestEq_test_overwriting_eq
        self.assertEqual(C(1), 3)
        self.assertNotEqual(C(1), 1)
        C = C_TestEq_test_overwriting_eq_
        self.assertEqual(C(1), 4)
        self.assertNotEqual(C(1), 1)
        C = C_TestEq_test_overwriting_eq__
        self.assertEqual(C(1), 5)
        self.assertNotEqual(C(1), 1)

class TestOrdering(unittest.TestCase):
    pass

class TestHash(unittest.TestCase):

    def test_unsafe_hash(self):
        C = C_TestHash_test_unsafe_hash
        self.assertEqual(hash(C(1, 'foo')), hash((1, 'foo')))

    def test_0_field_hash(self):
        C = C_TestHash_test_0_field_hash
        self.assertEqual(hash(C()), hash(()))
        C = C_TestHash_test_0_field_hash_
        self.assertEqual(hash(C()), hash(()))

    def test_1_field_hash(self):
        C = C_TestHash_test_1_field_hash
        self.assertEqual(hash(C(4)), hash((4,)))
        self.assertEqual(hash(C(42)), hash((42,)))
        C = C_TestHash_test_1_field_hash_
        self.assertEqual(hash(C(4)), hash((4,)))
        self.assertEqual(hash(C(42)), hash((42,)))

class TestMakeDataclass(unittest.TestCase):
    pass

class TestReplace(unittest.TestCase):

    def test(self):
        C = C_TestReplace_test
        c = C(1, 2)
        c1 = replace(c, x=3)
        self.assertEqual(c1.x, 3)
        self.assertEqual(c1.y, 2)

    def test_invalid_field_name(self):
        C = C_TestReplace_test_invalid_field_name
        c = C(1, 2)
        with self.assertRaises(TypeError):
            c1 = replace(c, z=3)

    def test_invalid_object(self):
        C = C_TestReplace_test_invalid_object
        with self.assertRaises(TypeError):
            replace(C, x=3)
        with self.assertRaises(TypeError):
            replace(0, x=3)

    def test_no_init(self):
        C = C_TestReplace_test_no_init
        c = C(1)
        c.y = 20
        c1 = replace(c, x=5)
        self.assertEqual((c1.x, c1.y), (5, 10))
        with self.assertRaises(ValueError):
            replace(c, x=2, y=30)
        with self.assertRaises(ValueError):
            replace(c, y=30)

    def test_classvar(self):
        C = C_TestReplace_test_classvar
        c = C(1)
        d = C(2)
        self.assertIs(c.y, d.y)
        self.assertEqual(c.y, 1000)
        with self.assertRaises(TypeError):
            replace(c, y=30)
        replace(c, x=5)

    def test_initvar_is_specified(self):
        C = C_TestReplace_test_initvar_is_specified
        c = C(1, 10)
        self.assertEqual(c.x, 10)
        with self.assertRaises(ValueError):
            replace(c, x=3)
        c = replace(c, x=3, y=5)
        self.assertEqual(c.x, 15)

    def test_recursive_repr(self):
        C = C_TestReplace_test_recursive_repr
        c = C(None)
        c.f = c
        self.assertEqual(repr(c), 'C_TestReplace_test_recursive_repr(f=...)')

    def test_recursive_repr_two_attrs(self):
        C = C_TestReplace_test_recursive_repr_two_attrs
        c = C(None, None)
        c.f = c
        c.g = c
        self.assertEqual(repr(c), 'C_TestReplace_test_recursive_repr_two_attrs(f=..., g=...)')

    def test_recursive_repr_indirection(self):
        C = C_TestReplace_test_recursive_repr_indirection
        D = D_TestReplace_test_recursive_repr_indirection
        c = C(None)
        d = D(None)
        c.f = d
        d.f = c
        self.assertEqual(repr(c), 'C_TestReplace_test_recursive_repr_indirection(f=D_TestReplace_test_recursive_repr_indirection(f=...))')

    def test_recursive_repr_indirection_two(self):
        C = C_TestReplace_test_recursive_repr_indirection_two
        D = D_TestReplace_test_recursive_repr_indirection_two
        E = E_TestReplace_test_recursive_repr_indirection_two
        c = C(None)
        d = D(None)
        e = E(None)
        c.f = d
        d.f = e
        e.f = c
        self.assertEqual(repr(c), 'C_TestReplace_test_recursive_repr_indirection_two(f=D_TestReplace_test_recursive_repr_indirection_two(f=E_TestReplace_test_recursive_repr_indirection_two(f=...)))')

    def test_recursive_repr_misc_attrs(self):
        C = C_TestReplace_test_recursive_repr_misc_attrs
        c = C(None, 1)
        c.f = c
        self.assertEqual(repr(c), 'C_TestReplace_test_recursive_repr_misc_attrs(f=..., g=1)')

class TestAbstract(unittest.TestCase):
    pass

class TestKeywordArgs(unittest.TestCase):
    pass
if __name__ == '__main__':
    unittest.main()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4247222
Cython-3.0.8/tests/run/test_dictviews.pyx0000644000175100001770000001473700000000000021360 0ustar00runnerdocker00000000000000import unittest

class DictSetTest(unittest.TestCase):

    def test_constructors_not_callable(self):
        kt = type({}.viewkeys())
        self.assertRaises(TypeError, kt, {})
        self.assertRaises(TypeError, kt)
        it = type({}.viewitems())
        self.assertRaises(TypeError, it, {})
        self.assertRaises(TypeError, it)
        vt = type({}.viewvalues())
        self.assertRaises(TypeError, vt, {})
        self.assertRaises(TypeError, vt)

    def test_dict_keys(self):
        d = {1: 10, "a": "ABC"}
        keys = d.viewkeys()
        self.assertEqual(len(keys), 2)
        self.assertEqual(set(keys), set([1, "a"]))
        self.assertEqual(keys, set([1, "a"]))
        self.assertNotEqual(keys, set([1, "a", "b"]))
        self.assertNotEqual(keys, set([1, "b"]))
        self.assertNotEqual(keys, set([1]))
        self.assertNotEqual(keys, 42)
        self.assertIn(1, keys)
        self.assertIn("a", keys)
        self.assertNotIn(10, keys)
        self.assertNotIn("Z", keys)
        self.assertEqual(d.viewkeys(), d.viewkeys())
        e = {1: 11, "a": "def"}
        self.assertEqual(d.viewkeys(), e.viewkeys())
        del e["a"]
        self.assertNotEqual(d.viewkeys(), e.viewkeys())

    def test_dict_items(self):
        d = {1: 10, "a": "ABC"}
        items = d.viewitems()
        self.assertEqual(len(items), 2)
        self.assertEqual(set(items), set([(1, 10), ("a", "ABC")]))
        self.assertEqual(items, set([(1, 10), ("a", "ABC")]))
        self.assertNotEqual(items, set([(1, 10), ("a", "ABC"), "junk"]))
        self.assertNotEqual(items, set([(1, 10), ("a", "def")]))
        self.assertNotEqual(items, set([(1, 10)]))
        self.assertNotEqual(items, 42)
        self.assertIn((1, 10), items)
        self.assertIn(("a", "ABC"), items)
        self.assertNotIn((1, 11), items)
        self.assertNotIn(1, items)
        self.assertNotIn((), items)
        self.assertNotIn((1,), items)
        self.assertNotIn((1, 2, 3), items)
        self.assertEqual(d.viewitems(), d.viewitems())
        e = dict(d.copy())
        self.assertEqual(d.viewitems(), e.viewitems())
        e["a"] = "def"
        self.assertNotEqual(d.viewitems(), e.viewitems())

    def test_dict_mixed_keys_items(self):
        d = {(1, 1): 11, (2, 2): 22}
        e = {1: 1, 2: 2}
        self.assertEqual(d.viewkeys(), e.viewitems())
        self.assertNotEqual(d.viewitems(), e.viewkeys())

    def test_dict_values(self):
        d = {1: 10, "a": "ABC"}
        values = d.viewvalues()
        self.assertEqual(set(values), set([10, "ABC"]))
        self.assertEqual(len(values), 2)

    def test_dict_repr(self):
        d = {1: 10, "a": "ABC"}
        self.assertTrue(isinstance(repr(d), str))
        r = repr(d.viewitems())
        self.assertTrue(isinstance(r, str))
        self.assertTrue(r == "dict_items([('a', 'ABC'), (1, 10)])" or
                        r == "dict_items([(1, 10), ('a', 'ABC')])")
        r = repr(d.viewkeys())
        self.assertTrue(isinstance(r, str))
        self.assertTrue(r == "dict_keys(['a', 1])" or
                        r == "dict_keys([1, 'a'])")
        r = repr(d.viewvalues())
        self.assertTrue(isinstance(r, str))
        self.assertTrue(r == "dict_values(['ABC', 10])" or
                        r == "dict_values([10, 'ABC'])")

    def test_keys_set_operations(self):
        d1 = {'a': 1, 'b': 2}
        d2 = {'b': 3, 'c': 2}
        d3 = {'d': 4, 'e': 5}
        self.assertEqual(d1.viewkeys() & d1.viewkeys(), {'a', 'b'})
        self.assertEqual(d1.viewkeys() & d2.viewkeys(), {'b'})
        self.assertEqual(d1.viewkeys() & d3.viewkeys(), set())
        self.assertEqual(d1.viewkeys() & set(d1.viewkeys()), {'a', 'b'})
        self.assertEqual(d1.viewkeys() & set(d2.viewkeys()), {'b'})
        self.assertEqual(d1.viewkeys() & set(d3.viewkeys()), set())

        self.assertEqual(d1.viewkeys() | d1.viewkeys(), {'a', 'b'})
        self.assertEqual(d1.viewkeys() | d2.viewkeys(), {'a', 'b', 'c'})
        self.assertEqual(d1.viewkeys() | d3.viewkeys(), {'a', 'b', 'd', 'e'})
        self.assertEqual(d1.viewkeys() | set(d1.viewkeys()), {'a', 'b'})
        self.assertEqual(d1.viewkeys() | set(d2.viewkeys()), {'a', 'b', 'c'})
        self.assertEqual(d1.viewkeys() | set(d3.viewkeys()),
                         {'a', 'b', 'd', 'e'})

        self.assertEqual(d1.viewkeys() ^ d1.viewkeys(), set())
        self.assertEqual(d1.viewkeys() ^ d2.viewkeys(), {'a', 'c'})
        self.assertEqual(d1.viewkeys() ^ d3.viewkeys(), {'a', 'b', 'd', 'e'})
        self.assertEqual(d1.viewkeys() ^ set(d1.viewkeys()), set())
        self.assertEqual(d1.viewkeys() ^ set(d2.viewkeys()), {'a', 'c'})
        self.assertEqual(d1.viewkeys() ^ set(d3.viewkeys()),
                         {'a', 'b', 'd', 'e'})

    def test_items_set_operations(self):
        d1 = {'a': 1, 'b': 2}
        d2 = {'a': 2, 'b': 2}
        d3 = {'d': 4, 'e': 5}
        self.assertEqual(
            d1.viewitems() & d1.viewitems(), {('a', 1), ('b', 2)})
        self.assertEqual(d1.viewitems() & d2.viewitems(), {('b', 2)})
        self.assertEqual(d1.viewitems() & d3.viewitems(), set())
        self.assertEqual(d1.viewitems() & set(d1.viewitems()),
                         {('a', 1), ('b', 2)})
        self.assertEqual(d1.viewitems() & set(d2.viewitems()), {('b', 2)})
        self.assertEqual(d1.viewitems() & set(d3.viewitems()), set())

        self.assertEqual(d1.viewitems() | d1.viewitems(),
                         {('a', 1), ('b', 2)})
        self.assertEqual(d1.viewitems() | d2.viewitems(),
                         {('a', 1), ('a', 2), ('b', 2)})
        self.assertEqual(d1.viewitems() | d3.viewitems(),
                         {('a', 1), ('b', 2), ('d', 4), ('e', 5)})
        self.assertEqual(d1.viewitems() | set(d1.viewitems()),
                         {('a', 1), ('b', 2)})
        self.assertEqual(d1.viewitems() | set(d2.viewitems()),
                         {('a', 1), ('a', 2), ('b', 2)})
        self.assertEqual(d1.viewitems() | set(d3.viewitems()),
                         {('a', 1), ('b', 2), ('d', 4), ('e', 5)})

        self.assertEqual(d1.viewitems() ^ d1.viewitems(), set())
        self.assertEqual(d1.viewitems() ^ d2.viewitems(),
                         {('a', 1), ('a', 2)})
        self.assertEqual(d1.viewitems() ^ d3.viewitems(),
                         {('a', 1), ('b', 2), ('d', 4), ('e', 5)})




def test_main():
    try:
        from test import test_support as support
    except ImportError:
        from test import support
    support.run_unittest(DictSetTest)

if __name__ == "__main__":
    test_main()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/test_exceptions.pyx0000644000175100001770000014140700000000000021533 0ustar00runnerdocker00000000000000# Python test set -- part 5, built-in exceptions
# Copied from CPython 3.7.

# cython: language_level=3
# mode: run
# tag: generator, exception, tryfinally, tryexcept, test.support

import copy
import os
import sys
import unittest
import pickle
import weakref
import errno

from test.support import (captured_stderr, check_impl_detail, gc_collect,
                          # no_tracing, cpython_only,
                          script_helper, SuppressCrashReport)
try:
    from test.support.os_helper import TESTFN, unlink
    from test.support.warnings_helper import check_warnings
    from test.support.import_helper import import_module
except ImportError:
    # Python 3.9 and older
    from test.support import check_warnings, TESTFN, unlink, import_module

no_tracing = unittest.skip("For nested functions, Cython generates a C call without recursion checks.")

cpython_only = unittest.skip("Tests for _testcapi or Python error messages make no sense here.")


class NaiveException(Exception):
    def __init__(self, x):
        self.x = x

class SlottedNaiveException(Exception):
    __slots__ = ('x',)
    def __init__(self, x):
        self.x = x

class BrokenStrException(Exception):
    def __str__(self):
        raise Exception("str() is broken")

# XXX This is not really enough, each *operation* should be tested!

class ExceptionTests(unittest.TestCase):

    def raise_catch(self, exc, excname):
        try:
            raise exc("spam")
        except exc as err:
            buf1 = str(err)
        try:
            raise exc("spam")
        except exc as err:
            buf2 = str(err)
        self.assertEqual(buf1, buf2)
        self.assertEqual(exc.__name__, excname)

    def testRaising(self):
        self.raise_catch(AttributeError, "AttributeError")
        self.assertRaises(AttributeError, getattr, sys, "undefined_attribute")

        self.raise_catch(EOFError, "EOFError")
        fp = open(TESTFN, 'w')
        fp.close()
        fp = open(TESTFN, 'r')
        savestdin = sys.stdin
        try:
            try:
                import marshal
                marshal.loads(b'')
            except EOFError:
                pass
        finally:
            sys.stdin = savestdin
            fp.close()
            unlink(TESTFN)

        self.raise_catch(OSError, "OSError")
        self.assertRaises(OSError, open, 'this file does not exist', 'r')

        self.raise_catch(ImportError, "ImportError")
        self.assertRaises(ImportError, __import__, "undefined_module")

        self.raise_catch(IndexError, "IndexError")
        x = []
        self.assertRaises(IndexError, x.__getitem__, 10)

        self.raise_catch(KeyError, "KeyError")
        x = {}
        self.assertRaises(KeyError, x.__getitem__, 'key')

        self.raise_catch(KeyboardInterrupt, "KeyboardInterrupt")

        self.raise_catch(MemoryError, "MemoryError")

        self.raise_catch(NameError, "NameError")
        #try: x = undefined_variable
        #except NameError: pass

        self.raise_catch(OverflowError, "OverflowError")
        x = 1
        for dummy in range(128):
            x += x  # this simply shouldn't blow up

        self.raise_catch(RuntimeError, "RuntimeError")
        self.raise_catch(RecursionError, "RecursionError")

        self.raise_catch(SyntaxError, "SyntaxError")
        try: exec('/\n')
        except SyntaxError: pass

        self.raise_catch(IndentationError, "IndentationError")

        self.raise_catch(TabError, "TabError")
        try: compile("try:\n\t1/0\n    \t1/0\nfinally:\n pass\n",
                     '', 'exec')
        except TabError: pass
        else: self.fail("TabError not raised")

        self.raise_catch(SystemError, "SystemError")

        self.raise_catch(SystemExit, "SystemExit")
        self.assertRaises(SystemExit, sys.exit, 0)

        self.raise_catch(TypeError, "TypeError")
        try: [] + ()
        except TypeError: pass

        self.raise_catch(ValueError, "ValueError")
        self.assertRaises(ValueError, chr, 17<<16)

        ZERO = 0
        self.raise_catch(ZeroDivisionError, "ZeroDivisionError")
        try: x = 1/ZERO
        except ZeroDivisionError: pass

        self.raise_catch(Exception, "Exception")
        try: x = 1/ZERO
        except Exception as e: pass

        self.raise_catch(StopAsyncIteration, "StopAsyncIteration")

    @cpython_only
    def testSyntaxErrorMessage(self):
        # make sure the right exception message is raised for each of
        # these code fragments

        def ckmsg(src, msg):
            try:
                compile(src, '', 'exec')
            except SyntaxError as e:
                if e.msg != msg:
                    self.fail("expected %s, got %s" % (msg, e.msg))
            else:
                self.fail("failed to get expected SyntaxError")

        s = '''if 1:
        try:
            continue
        except:
            pass'''

        ckmsg(s, "'continue' not properly in loop")
        ckmsg("continue\n", "'continue' not properly in loop")

    @cpython_only
    def testSyntaxErrorMissingParens(self):
        def ckmsg(src, msg, exception=SyntaxError):
            try:
                compile(src, '', 'exec')
            except exception as e:
                if e.msg != msg and sys.version_info >= (3, 6):
                    self.fail("expected %s, got %s" % (msg, e.msg))
            else:
                self.fail("failed to get expected SyntaxError")

        s = '''print "old style"'''
        ckmsg(s, "Missing parentheses in call to 'print'. "
                 "Did you mean print(\"old style\")?")

        s = '''print "old style",'''
        ckmsg(s, "Missing parentheses in call to 'print'. "
                 "Did you mean print(\"old style\", end=\" \")?")

        s = '''exec "old style"'''
        ckmsg(s, "Missing parentheses in call to 'exec'")

        # should not apply to subclasses, see issue #31161
        s = '''if True:\nprint "No indent"'''
        ckmsg(s, "expected an indented block", IndentationError)

        s = '''if True:\n        print()\n\texec "mixed tabs and spaces"'''
        ckmsg(s, "inconsistent use of tabs and spaces in indentation", TabError)

    @cpython_only
    def testSyntaxErrorOffset(self):
        def check(src, lineno, offset):
            with self.assertRaises(SyntaxError) as cm:
                compile(src, '', 'exec')
            self.assertEqual(cm.exception.lineno, lineno)
            self.assertEqual(cm.exception.offset, offset)

        check('def fact(x):\n\treturn x!\n', 2, 10)
        check('1 +\n', 1, 4)
        check('def spam():\n  print(1)\n print(2)', 3, 10)
        check('Python = "Python" +', 1, 20)
        check('Python = "\u1e54\xfd\u0163\u0125\xf2\xf1" +', 1, 20)

    @cpython_only
    def testSettingException(self):
        # test that setting an exception at the C level works even if the
        # exception object can't be constructed.

        class BadException(Exception):
            def __init__(self_):
                raise RuntimeError("can't instantiate BadException")

        class InvalidException:
            pass

        def test_capi1():
            import _testcapi
            try:
                _testcapi.raise_exception(BadException, 1)
            except TypeError as err:
                exc, err, tb = sys.exc_info()
                co = tb.tb_frame.f_code
                self.assertEqual(co.co_name, "test_capi1")
                self.assertTrue(co.co_filename.endswith('test_exceptions.py'))
            else:
                self.fail("Expected exception")

        def test_capi2():
            import _testcapi
            try:
                _testcapi.raise_exception(BadException, 0)
            except RuntimeError as err:
                exc, err, tb = sys.exc_info()
                co = tb.tb_frame.f_code
                self.assertEqual(co.co_name, "__init__")
                self.assertTrue(co.co_filename.endswith('test_exceptions.py'))
                co2 = tb.tb_frame.f_back.f_code
                self.assertEqual(co2.co_name, "test_capi2")
            else:
                self.fail("Expected exception")

        def test_capi3():
            import _testcapi
            self.assertRaises(SystemError, _testcapi.raise_exception,
                              InvalidException, 1)

        if not sys.platform.startswith('java'):
            test_capi1()
            test_capi2()
            test_capi3()

    def test_WindowsError(self):
        try:
            WindowsError
        except NameError:
            pass
        else:
            self.assertIs(WindowsError, OSError)
            self.assertEqual(str(OSError(1001)), "1001")
            self.assertEqual(str(OSError(1001, "message")),
                             "[Errno 1001] message")
            # POSIX errno (9 aka EBADF) is untranslated
            w = OSError(9, 'foo', 'bar')
            self.assertEqual(w.errno, 9)
            self.assertEqual(w.winerror, None)
            self.assertEqual(str(w), "[Errno 9] foo: 'bar'")
            # ERROR_PATH_NOT_FOUND (win error 3) becomes ENOENT (2)
            w = OSError(0, 'foo', 'bar', 3)
            self.assertEqual(w.errno, 2)
            self.assertEqual(w.winerror, 3)
            self.assertEqual(w.strerror, 'foo')
            self.assertEqual(w.filename, 'bar')
            self.assertEqual(w.filename2, None)
            self.assertEqual(str(w), "[WinError 3] foo: 'bar'")
            # Unknown win error becomes EINVAL (22)
            w = OSError(0, 'foo', None, 1001)
            self.assertEqual(w.errno, 22)
            self.assertEqual(w.winerror, 1001)
            self.assertEqual(w.strerror, 'foo')
            self.assertEqual(w.filename, None)
            self.assertEqual(w.filename2, None)
            self.assertEqual(str(w), "[WinError 1001] foo")
            # Non-numeric "errno"
            w = OSError('bar', 'foo')
            self.assertEqual(w.errno, 'bar')
            self.assertEqual(w.winerror, None)
            self.assertEqual(w.strerror, 'foo')
            self.assertEqual(w.filename, None)
            self.assertEqual(w.filename2, None)

    @unittest.skipUnless(sys.platform == 'win32',
                         'test specific to Windows')
    def test_windows_message(self):
        """Should fill in unknown error code in Windows error message"""
        ctypes = import_module('ctypes')
        # this error code has no message, Python formats it as hexadecimal
        code = 3765269347
        with self.assertRaisesRegex(OSError, 'Windows Error 0x%x' % code):
            ctypes.pythonapi.PyErr_SetFromWindowsErr(code)

    def testAttributes(self):
        # test that exception attributes are happy

        exceptionList = [
            (BaseException, (), {'args' : ()}),
            (BaseException, (1, ), {'args' : (1,)}),
            (BaseException, ('foo',),
                {'args' : ('foo',)}),
            (BaseException, ('foo', 1),
                {'args' : ('foo', 1)}),
            (SystemExit, ('foo',),
                {'args' : ('foo',), 'code' : 'foo'}),
            (OSError, ('foo',),
                {'args' : ('foo',), 'filename' : None, 'filename2' : None,
                 'errno' : None, 'strerror' : None}),
            (OSError, ('foo', 'bar'),
                {'args' : ('foo', 'bar'),
                 'filename' : None, 'filename2' : None,
                 'errno' : 'foo', 'strerror' : 'bar'}),
            (OSError, ('foo', 'bar', 'baz'),
                {'args' : ('foo', 'bar'),
                 'filename' : 'baz', 'filename2' : None,
                 'errno' : 'foo', 'strerror' : 'bar'}),
            (OSError, ('foo', 'bar', 'baz', None, 'quux'),
                {'args' : ('foo', 'bar'), 'filename' : 'baz', 'filename2': 'quux'}),
            (OSError, ('errnoStr', 'strErrorStr', 'filenameStr'),
                {'args' : ('errnoStr', 'strErrorStr'),
                 'strerror' : 'strErrorStr', 'errno' : 'errnoStr',
                 'filename' : 'filenameStr'}),
            (OSError, (1, 'strErrorStr', 'filenameStr'),
                {'args' : (1, 'strErrorStr'), 'errno' : 1,
                 'strerror' : 'strErrorStr',
                 'filename' : 'filenameStr', 'filename2' : None}),
            (SyntaxError, (), {'msg' : None, 'text' : None,
                'filename' : None, 'lineno' : None, 'offset' : None,
                'print_file_and_line' : None}),
            (SyntaxError, ('msgStr',),
                {'args' : ('msgStr',), 'text' : None,
                 'print_file_and_line' : None, 'msg' : 'msgStr',
                 'filename' : None, 'lineno' : None, 'offset' : None}),
            (SyntaxError, ('msgStr', ('filenameStr', 'linenoStr', 'offsetStr',
                           'textStr')),
                {'offset' : 'offsetStr', 'text' : 'textStr',
                 'args' : ('msgStr', ('filenameStr', 'linenoStr',
                                      'offsetStr', 'textStr')),
                 'print_file_and_line' : None, 'msg' : 'msgStr',
                 'filename' : 'filenameStr', 'lineno' : 'linenoStr'}),
            (SyntaxError, ('msgStr', 'filenameStr', 'linenoStr', 'offsetStr',
                           'textStr', 'print_file_and_lineStr'),
                {'text' : None,
                 'args' : ('msgStr', 'filenameStr', 'linenoStr', 'offsetStr',
                           'textStr', 'print_file_and_lineStr'),
                 'print_file_and_line' : None, 'msg' : 'msgStr',
                 'filename' : None, 'lineno' : None, 'offset' : None}),
            (UnicodeError, (), {'args' : (),}),
            (UnicodeEncodeError, ('ascii', 'a', 0, 1,
                                  'ordinal not in range'),
                {'args' : ('ascii', 'a', 0, 1,
                                           'ordinal not in range'),
                 'encoding' : 'ascii', 'object' : 'a',
                 'start' : 0, 'reason' : 'ordinal not in range'}),
            (UnicodeDecodeError, ('ascii', bytearray(b'\xff'), 0, 1,
                                  'ordinal not in range'),
                {'args' : ('ascii', bytearray(b'\xff'), 0, 1,
                                           'ordinal not in range'),
                 'encoding' : 'ascii', 'object' : b'\xff',
                 'start' : 0, 'reason' : 'ordinal not in range'}),
            (UnicodeDecodeError, ('ascii', b'\xff', 0, 1,
                                  'ordinal not in range'),
                {'args' : ('ascii', b'\xff', 0, 1,
                                           'ordinal not in range'),
                 'encoding' : 'ascii', 'object' : b'\xff',
                 'start' : 0, 'reason' : 'ordinal not in range'}),
            (UnicodeTranslateError, ("\u3042", 0, 1, "ouch"),
                {'args' : ('\u3042', 0, 1, 'ouch'),
                 'object' : '\u3042', 'reason' : 'ouch',
                 'start' : 0, 'end' : 1}),
            (NaiveException, ('foo',),
                {'args': ('foo',), 'x': 'foo'}),
            (SlottedNaiveException, ('foo',),
                {'args': ('foo',), 'x': 'foo'}),
        ]
        try:
            # More tests are in test_WindowsError
            exceptionList.append(
                (WindowsError, (1, 'strErrorStr', 'filenameStr'),
                    {'args' : (1, 'strErrorStr'),
                     'strerror' : 'strErrorStr', 'winerror' : None,
                     'errno' : 1,
                     'filename' : 'filenameStr', 'filename2' : None})
            )
        except NameError:
            pass

        for exc, args, expected in exceptionList:
            try:
                e = exc(*args)
            except:
                print("\nexc=%r, args=%r" % (exc, args), file=sys.stderr)
                raise
            else:
                # Verify module name
                if not type(e).__name__.endswith('NaiveException'):
                    self.assertEqual(type(e).__module__, 'builtins')
                # Verify no ref leaks in Exc_str()
                s = str(e)
                for checkArgName in expected:
                    value = getattr(e, checkArgName)
                    self.assertEqual(repr(value),
                                     repr(expected[checkArgName]),
                                     '%r.%s == %r, expected %r' % (
                                     e, checkArgName,
                                     value, expected[checkArgName]))

                # test for pickling support
                for p in [pickle]:
                    for protocol in range(p.HIGHEST_PROTOCOL + 1):
                        s = p.dumps(e, protocol)
                        new = p.loads(s)
                        for checkArgName in expected:
                            got = repr(getattr(new, checkArgName))
                            want = repr(expected[checkArgName])
                            self.assertEqual(got, want,
                                             'pickled "%r", attribute "%s' %
                                             (e, checkArgName))

    def testWithTraceback(self):
        try:
            raise IndexError(4)
        except:
            tb = sys.exc_info()[2]

        e = BaseException().with_traceback(tb)
        self.assertIsInstance(e, BaseException)
        self.assertEqual(e.__traceback__, tb)

        e = IndexError(5).with_traceback(tb)
        self.assertIsInstance(e, IndexError)
        self.assertEqual(e.__traceback__, tb)

        class MyException(Exception):
            pass

        e = MyException().with_traceback(tb)
        self.assertIsInstance(e, MyException)
        self.assertEqual(e.__traceback__, tb)

    def testInvalidTraceback(self):
        try:
            Exception().__traceback__ = 5
        except TypeError as e:
            self.assertIn("__traceback__ must be a traceback", str(e))
        else:
            self.fail("No exception raised")

    def testInvalidAttrs(self):
        self.assertRaises(TypeError, setattr, Exception(), '__cause__', 1)
        self.assertRaises(TypeError, delattr, Exception(), '__cause__')
        self.assertRaises(TypeError, setattr, Exception(), '__context__', 1)
        self.assertRaises(TypeError, delattr, Exception(), '__context__')

    def testNoneClearsTracebackAttr(self):
        try:
            raise IndexError(4)
        except:
            tb = sys.exc_info()[2]

        e = Exception()
        e.__traceback__ = tb
        e.__traceback__ = None
        self.assertEqual(e.__traceback__, None)

    def testChainingAttrs(self):
        e = Exception()
        self.assertIsNone(e.__context__)
        self.assertIsNone(e.__cause__)

        e = TypeError()
        self.assertIsNone(e.__context__)
        self.assertIsNone(e.__cause__)

        class MyException(OSError):
            pass

        e = MyException()
        self.assertIsNone(e.__context__)
        self.assertIsNone(e.__cause__)

    def testChainingDescriptors(self):
        try:
            raise Exception()
        except Exception as exc:
            e = exc

        self.assertIsNone(e.__context__)
        self.assertIsNone(e.__cause__)
        self.assertFalse(e.__suppress_context__)

        e.__context__ = NameError()
        e.__cause__ = None
        self.assertIsInstance(e.__context__, NameError)
        self.assertIsNone(e.__cause__)
        self.assertTrue(e.__suppress_context__)
        e.__suppress_context__ = False
        self.assertFalse(e.__suppress_context__)

    def testKeywordArgs(self):
        # test that builtin exception don't take keyword args,
        # but user-defined subclasses can if they want
        self.assertRaises(TypeError, BaseException, a=1)

        class DerivedException(BaseException):
            def __init__(self, fancy_arg):
                BaseException.__init__(self)
                self.fancy_arg = fancy_arg

        x = DerivedException(fancy_arg=42)
        self.assertEqual(x.fancy_arg, 42)

    @no_tracing
    def testInfiniteRecursion(self):
        def f():
            return f()
        self.assertRaises(RecursionError, f)

        def g():
            try:
                return g()
            except ValueError:
                return -1
        self.assertRaises(RecursionError, g)

    def test_str(self):
        # Make sure both instances and classes have a str representation.
        self.assertTrue(str(Exception))
        self.assertTrue(str(Exception('a')))
        self.assertTrue(str(Exception('a', 'b')))

    def testExceptionCleanupNames(self):
        # Make sure the local variable bound to the exception instance by
        # an "except" statement is only visible inside the except block.
        try:
            raise Exception()
        except Exception as e:
            self.assertTrue(e)
            del e
        self.assertNotIn('e', locals())

    def testExceptionCleanupState(self):
        # Make sure exception state is cleaned up as soon as the except
        # block is left. See #2507

        class MyException(Exception):
            def __init__(self, obj):
                self.obj = obj
        class MyObj:
            pass

        def inner_raising_func():
            # Create some references in exception value and traceback
            local_ref = obj
            raise MyException(obj)

        # Qualified "except" with "as"
        obj = MyObj()
        wr = weakref.ref(obj)
        try:
            inner_raising_func()
        except MyException as e:
            pass
        obj = None
        obj = wr()
        self.assertIsNone(obj)

        # Qualified "except" without "as"
        obj = MyObj()
        wr = weakref.ref(obj)
        try:
            inner_raising_func()
        except MyException:
            pass
        obj = None
        obj = wr()
        self.assertIsNone(obj)

        # Bare "except"
        obj = MyObj()
        wr = weakref.ref(obj)
        try:
            inner_raising_func()
        except:
            pass
        obj = None
        obj = wr()
        self.assertIsNone(obj)

        # "except" with premature block leave
        obj = MyObj()
        wr = weakref.ref(obj)
        for i in [0]:
            try:
                inner_raising_func()
            except:
                break
        obj = None
        obj = wr()
        self.assertIsNone(obj)

        # "except" block raising another exception
        obj = MyObj()
        wr = weakref.ref(obj)
        try:
            try:
                inner_raising_func()
            except:
                raise KeyError
        except KeyError as e:
            # We want to test that the except block above got rid of
            # the exception raised in inner_raising_func(), but it
            # also ends up in the __context__ of the KeyError, so we
            # must clear the latter manually for our test to succeed.
            e.__context__ = None
            obj = None
            obj = wr()
            # guarantee no ref cycles on CPython (don't gc_collect)
            if check_impl_detail(cpython=False):
                gc_collect()
            self.assertIsNone(obj)

        # Some complicated construct
        obj = MyObj()
        wr = weakref.ref(obj)
        try:
            inner_raising_func()
        except MyException:
            try:
                try:
                    raise
                finally:
                    raise
            except MyException:
                pass
        obj = None
        if check_impl_detail(cpython=False):
            gc_collect()
        obj = wr()
        self.assertIsNone(obj)

        # Inside an exception-silencing "with" block
        class Context:
            def __enter__(self):
                return self
            def __exit__ (self, exc_type, exc_value, exc_tb):
                return True
        obj = MyObj()
        wr = weakref.ref(obj)
        with Context():
            inner_raising_func()
        obj = None
        if check_impl_detail(cpython=False):
            gc_collect()
        obj = wr()
        self.assertIsNone(obj)

    '''
    # This is currently a compile error in Cython-3, although it works in Cython-2 => could also work in Cy-3.
    def test_exception_target_in_nested_scope(self):
        # issue 4617: This used to raise a SyntaxError
        # "can not delete variable 'e' referenced in nested scope"
        def print_error():
            e
        ZERO = 0
        try:
            1/ZERO
        except Exception as e:
            print_error()
            # implicit "del e" here
    '''

    def test_generator_leaking(self):
        # Test that generator exception state doesn't leak into the calling
        # frame
        def yield_raise():
            try:
                raise KeyError("caught")
            except KeyError:
                yield sys.exc_info()[0]
                yield sys.exc_info()[0]
            yield sys.exc_info()[0]
        g = yield_raise()
        self.assertEqual(next(g), KeyError)
        self.assertEqual(sys.exc_info()[0], None)
        self.assertEqual(next(g), KeyError)
        self.assertEqual(sys.exc_info()[0], None)
        self.assertEqual(next(g), None)

        # Same test, but inside an exception handler
        try:
            raise TypeError("foo")
        except TypeError:
            g = yield_raise()
            self.assertEqual(next(g), KeyError)
            self.assertEqual(sys.exc_info()[0], TypeError)
            self.assertEqual(next(g), KeyError)
            self.assertEqual(sys.exc_info()[0], TypeError)
            self.assertEqual(next(g), TypeError)
            del g
            self.assertEqual(sys.exc_info()[0], TypeError)

    def test_generator_leaking2(self):
        # See issue 12475.
        def g():
            yield
        try:
            raise RuntimeError
        except RuntimeError:
            it = g()
            next(it)
        try:
            next(it)
        except StopIteration:
            pass
        self.assertEqual(sys.exc_info(), (None, None, None))

    def test_generator_leaking3(self):
        # See issue #23353.  When gen.throw() is called, the caller's
        # exception state should be save and restored.
        def g():
            try:
                yield
            except ZeroDivisionError:
                yield sys.exc_info()[1]
        it = g()
        next(it)
        ZERO = 0
        try:
            1/ZERO
        except ZeroDivisionError as e:
            self.assertIs(sys.exc_info()[1], e)
            gen_exc = it.throw(e)
            self.assertIs(sys.exc_info()[1], e)
            self.assertIs(gen_exc, e)
        self.assertEqual(sys.exc_info(), (None, None, None))

    def test_generator_leaking4(self):
        # See issue #23353.  When an exception is raised by a generator,
        # the caller's exception state should still be restored.
        def g():
            ZERO = 0
            try:
                1/ZERO
            except ZeroDivisionError:
                yield sys.exc_info()[0]
                raise
        it = g()
        try:
            raise TypeError
        except TypeError:
            # The caller's exception state (TypeError) is temporarily
            # saved in the generator.
            tp = next(it)
        self.assertIs(tp, ZeroDivisionError)
        try:
            next(it)
            # We can't check it immediately, but while next() returns
            # with an exception, it shouldn't have restored the old
            # exception state (TypeError).
        except ZeroDivisionError as e:
            self.assertIs(sys.exc_info()[1], e)
        # We used to find TypeError here.
        self.assertEqual(sys.exc_info(), (None, None, None))

    def test_generator_doesnt_retain_old_exc(self):
        def g():
            self.assertIsInstance(sys.exc_info()[1], RuntimeError)
            yield
            self.assertEqual(sys.exc_info(), (None, None, None))
        it = g()
        try:
            raise RuntimeError
        except RuntimeError:
            next(it)
        self.assertRaises(StopIteration, next, it)

    def test_generator_finalizing_and_exc_info(self):
        # See #7173
        def simple_gen():
            yield 1
        def run_gen():
            gen = simple_gen()
            try:
                raise RuntimeError
            except RuntimeError:
                return next(gen)
        run_gen()
        gc_collect()
        self.assertEqual(sys.exc_info(), (None, None, None))

    def _check_generator_cleanup_exc_state(self, testfunc):
        # Issue #12791: exception state is cleaned up as soon as a generator
        # is closed (reference cycles are broken).
        class MyException(Exception):
            def __init__(self, obj):
                self.obj = obj
        class MyObj:
            pass

        def raising_gen():
            try:
                raise MyException(obj)
            except MyException:
                yield

        obj = MyObj()
        wr = weakref.ref(obj)
        g = raising_gen()
        next(g)
        testfunc(g)
        g = obj = None
        obj = wr()
        self.assertIsNone(obj)

    def test_generator_throw_cleanup_exc_state(self):
        def do_throw(g):
            try:
                g.throw(RuntimeError())
            except RuntimeError:
                pass
        self._check_generator_cleanup_exc_state(do_throw)

    def test_generator_close_cleanup_exc_state(self):
        def do_close(g):
            g.close()
        self._check_generator_cleanup_exc_state(do_close)

    def test_generator_del_cleanup_exc_state(self):
        def do_del(g):
            g = None
        self._check_generator_cleanup_exc_state(do_del)

    def test_generator_next_cleanup_exc_state(self):
        def do_next(g):
            try:
                next(g)
            except StopIteration:
                pass
            else:
                self.fail("should have raised StopIteration")
        self._check_generator_cleanup_exc_state(do_next)

    def test_generator_send_cleanup_exc_state(self):
        def do_send(g):
            try:
                g.send(None)
            except StopIteration:
                pass
            else:
                self.fail("should have raised StopIteration")
        self._check_generator_cleanup_exc_state(do_send)

    def test_3114(self):
        # Bug #3114: in its destructor, MyObject retrieves a pointer to
        # obsolete and/or deallocated objects.
        class MyObject:
            def __del__(self):
                nonlocal e
                e = sys.exc_info()
        e = ()
        try:
            raise Exception(MyObject())
        except:
            pass
        self.assertEqual(e, (None, None, None))

    def test_unicode_change_attributes(self):
        # See issue 7309. This was a crasher.

        u = UnicodeEncodeError('baz', 'xxxxx', 1, 5, 'foo')
        self.assertEqual(str(u), "'baz' codec can't encode characters in position 1-4: foo")
        u.end = 2
        self.assertEqual(str(u), "'baz' codec can't encode character '\\x78' in position 1: foo")
        u.end = 5
        u.reason = 0x345345345345345345
        self.assertEqual(str(u), "'baz' codec can't encode characters in position 1-4: 965230951443685724997")
        u.encoding = 4000
        self.assertEqual(str(u), "'4000' codec can't encode characters in position 1-4: 965230951443685724997")
        u.start = 1000
        self.assertEqual(str(u), "'4000' codec can't encode characters in position 1000-4: 965230951443685724997")

        u = UnicodeDecodeError('baz', b'xxxxx', 1, 5, 'foo')
        self.assertEqual(str(u), "'baz' codec can't decode bytes in position 1-4: foo")
        u.end = 2
        self.assertEqual(str(u), "'baz' codec can't decode byte 0x78 in position 1: foo")
        u.end = 5
        u.reason = 0x345345345345345345
        self.assertEqual(str(u), "'baz' codec can't decode bytes in position 1-4: 965230951443685724997")
        u.encoding = 4000
        self.assertEqual(str(u), "'4000' codec can't decode bytes in position 1-4: 965230951443685724997")
        u.start = 1000
        self.assertEqual(str(u), "'4000' codec can't decode bytes in position 1000-4: 965230951443685724997")

        u = UnicodeTranslateError('xxxx', 1, 5, 'foo')
        self.assertEqual(str(u), "can't translate characters in position 1-4: foo")
        u.end = 2
        self.assertEqual(str(u), "can't translate character '\\x78' in position 1: foo")
        u.end = 5
        u.reason = 0x345345345345345345
        self.assertEqual(str(u), "can't translate characters in position 1-4: 965230951443685724997")
        u.start = 1000
        self.assertEqual(str(u), "can't translate characters in position 1000-4: 965230951443685724997")

    def test_unicode_errors_no_object(self):
        # See issue #21134.
        klasses = UnicodeEncodeError, UnicodeDecodeError, UnicodeTranslateError
        for klass in klasses:
            self.assertEqual(str(klass.__new__(klass)), "")

    @no_tracing
    def test_badisinstance(self):
        # Bug #2542: if issubclass(e, MyException) raises an exception,
        # it should be ignored
        class Meta(type):
            def __subclasscheck__(cls, subclass):
                raise ValueError()
        class MyException(Exception, metaclass=Meta):
            pass

        with captured_stderr() as stderr:
            try:
                raise KeyError()
            except MyException as e:
                self.fail("exception should not be a MyException")
            except KeyError:
                pass
            except:
                self.fail("Should have raised KeyError")
            else:
                self.fail("Should have raised KeyError")

        def g():
            try:
                return g()
            except RecursionError:
                return sys.exc_info()
        e, v, tb = g()
        self.assertIsInstance(v, RecursionError, type(v))
        self.assertIn("maximum recursion depth exceeded", str(v))

    @cpython_only
    def test_recursion_normalizing_exception(self):
        # Issue #22898.
        # Test that a RecursionError is raised when tstate->recursion_depth is
        # equal to recursion_limit in PyErr_NormalizeException() and check
        # that a ResourceWarning is printed.
        # Prior to #22898, the recursivity of PyErr_NormalizeException() was
        # controlled by tstate->recursion_depth and a PyExc_RecursionErrorInst
        # singleton was being used in that case, that held traceback data and
        # locals indefinitely and would cause a segfault in _PyExc_Fini() upon
        # finalization of these locals.
        code = """if 1:
            import sys
            from _testcapi import get_recursion_depth

            class MyException(Exception): pass

            def setrecursionlimit(depth):
                while 1:
                    try:
                        sys.setrecursionlimit(depth)
                        return depth
                    except RecursionError:
                        # sys.setrecursionlimit() raises a RecursionError if
                        # the new recursion limit is too low (issue #25274).
                        depth += 1

            def recurse(cnt):
                cnt -= 1
                if cnt:
                    recurse(cnt)
                else:
                    generator.throw(MyException)

            def gen():
                f = open(%a, mode='rb', buffering=0)
                yield

            generator = gen()
            next(generator)
            recursionlimit = sys.getrecursionlimit()
            depth = get_recursion_depth()
            try:
                # Upon the last recursive invocation of recurse(),
                # tstate->recursion_depth is equal to (recursion_limit - 1)
                # and is equal to recursion_limit when _gen_throw() calls
                # PyErr_NormalizeException().
                recurse(setrecursionlimit(depth + 2) - depth - 1)
            finally:
                sys.setrecursionlimit(recursionlimit)
                print('Done.')
        """ % __file__
        rc, out, err = script_helper.assert_python_failure("-Wd", "-c", code)
        # Check that the program does not fail with SIGABRT.
        self.assertEqual(rc, 1)
        self.assertIn(b'RecursionError', err)
        self.assertIn(b'ResourceWarning', err)
        self.assertIn(b'Done.', out)

    @cpython_only
    def test_recursion_normalizing_infinite_exception(self):
        # Issue #30697. Test that a RecursionError is raised when
        # PyErr_NormalizeException() maximum recursion depth has been
        # exceeded.
        code = """if 1:
            import _testcapi
            try:
                raise _testcapi.RecursingInfinitelyError
            finally:
                print('Done.')
        """
        rc, out, err = script_helper.assert_python_failure("-c", code)
        self.assertEqual(rc, 1)
        self.assertIn(b'RecursionError: maximum recursion depth exceeded '
                      b'while normalizing an exception', err)
        self.assertIn(b'Done.', out)

    @cpython_only
    def test_recursion_normalizing_with_no_memory(self):
        # Issue #30697. Test that in the abort that occurs when there is no
        # memory left and the size of the Python frames stack is greater than
        # the size of the list of preallocated MemoryError instances, the
        # Fatal Python error message mentions MemoryError.
        code = """if 1:
            import _testcapi
            class C(): pass
            def recurse(cnt):
                cnt -= 1
                if cnt:
                    recurse(cnt)
                else:
                    _testcapi.set_nomemory(0)
                    C()
            recurse(16)
        """
        with SuppressCrashReport():
            rc, out, err = script_helper.assert_python_failure("-c", code)
            self.assertIn(b'Fatal Python error: Cannot recover from '
                          b'MemoryErrors while normalizing exceptions.', err)

    @cpython_only
    def test_MemoryError(self):
        # PyErr_NoMemory always raises the same exception instance.
        # Check that the traceback is not doubled.
        import traceback
        from _testcapi import raise_memoryerror
        def raiseMemError():
            try:
                raise_memoryerror()
            except MemoryError as e:
                tb = e.__traceback__
            else:
                self.fail("Should have raises a MemoryError")
            return traceback.format_tb(tb)

        tb1 = raiseMemError()
        tb2 = raiseMemError()
        self.assertEqual(tb1, tb2)

    @cpython_only
    def test_exception_with_doc(self):
        import _testcapi
        doc2 = "This is a test docstring."
        doc4 = "This is another test docstring."

        self.assertRaises(SystemError, _testcapi.make_exception_with_doc,
                          "error1")

        # test basic usage of PyErr_NewException
        error1 = _testcapi.make_exception_with_doc("_testcapi.error1")
        self.assertIs(type(error1), type)
        self.assertTrue(issubclass(error1, Exception))
        self.assertIsNone(error1.__doc__)

        # test with given docstring
        error2 = _testcapi.make_exception_with_doc("_testcapi.error2", doc2)
        self.assertEqual(error2.__doc__, doc2)

        # test with explicit base (without docstring)
        error3 = _testcapi.make_exception_with_doc("_testcapi.error3",
                                                   base=error2)
        self.assertTrue(issubclass(error3, error2))

        # test with explicit base tuple
        class C(object):
            pass
        error4 = _testcapi.make_exception_with_doc("_testcapi.error4", doc4,
                                                   (error3, C))
        self.assertTrue(issubclass(error4, error3))
        self.assertTrue(issubclass(error4, C))
        self.assertEqual(error4.__doc__, doc4)

        # test with explicit dictionary
        error5 = _testcapi.make_exception_with_doc("_testcapi.error5", "",
                                                   error4, {'a': 1})
        self.assertTrue(issubclass(error5, error4))
        self.assertEqual(error5.a, 1)
        self.assertEqual(error5.__doc__, "")

    @cpython_only
    def test_memory_error_cleanup(self):
        # Issue #5437: preallocated MemoryError instances should not keep
        # traceback objects alive.
        from _testcapi import raise_memoryerror
        class C:
            pass
        wr = None
        def inner():
            nonlocal wr
            c = C()
            wr = weakref.ref(c)
            raise_memoryerror()
        # We cannot use assertRaises since it manually deletes the traceback
        try:
            inner()
        except MemoryError as e:
            self.assertNotEqual(wr(), None)
        else:
            self.fail("MemoryError not raised")
        self.assertEqual(wr(), None)

    @no_tracing
    def test_recursion_error_cleanup(self):
        # Same test as above, but with "recursion exceeded" errors
        class C:
            pass
        wr = None
        def inner():
            nonlocal wr
            c = C()
            wr = weakref.ref(c)
            inner()
        # We cannot use assertRaises since it manually deletes the traceback
        try:
            inner()
        except RecursionError as e:
            self.assertNotEqual(wr(), None)
        else:
            self.fail("RecursionError not raised")
        self.assertEqual(wr(), None)

    def test_errno_ENOTDIR(self):
        # Issue #12802: "not a directory" errors are ENOTDIR even on Windows
        with self.assertRaises(OSError) as cm:
            os.listdir(__file__)
        self.assertEqual(cm.exception.errno, errno.ENOTDIR, cm.exception)

    def test_unraisable(self):
        # Issue #22836: PyErr_WriteUnraisable() should give sensible reports
        class BrokenDel:
            def __del__(self):
                exc = ValueError("del is broken")
                # The following line is included in the traceback report:
                raise exc

        class BrokenExceptionDel:
            def __del__(self):
                exc = BrokenStrException()
                # The following line is included in the traceback report:
                raise exc

        for test_class in (BrokenDel, BrokenExceptionDel):
            with self.subTest(test_class):
                obj = test_class()
                with captured_stderr() as stderr:
                    del obj
                report = stderr.getvalue()
                self.assertIn("Exception ignored", report)
                self.assertIn(test_class.__del__.__qualname__, report)
                self.assertIn("test_exceptions.py", report)
                self.assertIn("raise exc", report)
                if test_class is BrokenExceptionDel:
                    self.assertIn("BrokenStrException", report)
                    if sys.version_info >= (3, 6):
                        self.assertIn("", report)
                else:
                    self.assertIn("ValueError", report)
                    self.assertIn("del is broken", report)
                if sys.version_info >= (3, 6):
                    self.assertTrue(report.endswith("\n"))

    def test_unhandled(self):
        # Check for sensible reporting of unhandled exceptions
        for exc_type in (ValueError, BrokenStrException):
            with self.subTest(exc_type):
                try:
                    exc = exc_type("test message")
                    # The following line is included in the traceback report:
                    raise exc
                except exc_type:
                    with captured_stderr() as stderr:
                        sys.__excepthook__(*sys.exc_info())
                report = stderr.getvalue()
                self.assertIn("test_exceptions.py", report)
                self.assertIn("raise exc", report)
                self.assertIn(exc_type.__name__, report)
                if exc_type is BrokenStrException:
                    if sys.version_info >= (3, 6):
                        self.assertIn("", report)
                else:
                    self.assertIn("test message", report)
                if sys.version_info >= (3, 6):
                    self.assertTrue(report.endswith("\n"))

    @cpython_only
    def test_memory_error_in_PyErr_PrintEx(self):
        code = """if 1:
            import _testcapi
            class C(): pass
            _testcapi.set_nomemory(0, %d)
            C()
        """

        # Issue #30817: Abort in PyErr_PrintEx() when no memory.
        # Span a large range of tests as the CPython code always evolves with
        # changes that add or remove memory allocations.
        for i in range(1, 20):
            rc, out, err = script_helper.assert_python_failure("-c", code % i)
            self.assertIn(rc, (1, 120))
            self.assertIn(b'MemoryError', err)

    def test_yield_in_nested_try_excepts(self):
        #Issue #25612
        class MainError(Exception):
            pass

        class SubError(Exception):
            pass

        def main():
            try:
                raise MainError()
            except MainError:
                try:
                    yield
                except SubError:
                    pass
                raise

        coro = main()
        coro.send(None)
        with self.assertRaises(MainError):
            coro.throw(SubError())

    @unittest.skip('currently fails')  #  FIXME: fails in the "inside" assertion but not "outside"
    def test_generator_doesnt_retain_old_exc2(self):
        #Issue 28884#msg282532
        def g():
            try:
                raise ValueError
            except ValueError:
                yield 1
            self.assertEqual(sys.exc_info(), (None, None, None))  # inside
            yield 2

        gen = g()

        try:
            raise IndexError
        except IndexError:
            self.assertEqual(next(gen), 1)
        self.assertEqual(sys.exc_info(), (None, None, None))  # outside
        self.assertEqual(next(gen), 2)

    def test_raise_in_generator(self):
        #Issue 25612#msg304117
        def g():
            yield 1
            raise
            yield 2

        with self.assertRaises(ZeroDivisionError):
            i = g()
            ZERO = 0
            try:
                1/ZERO
            except:
                next(i)
                next(i)


class ImportErrorTests(unittest.TestCase):

    @unittest.skipIf(sys.version_info < (3, 6), "Requires Py3.6+")
    def test_attributes(self):
        # Setting 'name' and 'path' should not be a problem.
        exc = ImportError('test')
        self.assertIsNone(exc.name)
        self.assertIsNone(exc.path)

        exc = ImportError('test', name='somemodule')
        self.assertEqual(exc.name, 'somemodule')
        self.assertIsNone(exc.path)

        exc = ImportError('test', path='somepath')
        self.assertEqual(exc.path, 'somepath')
        self.assertIsNone(exc.name)

        exc = ImportError('test', path='somepath', name='somename')
        self.assertEqual(exc.name, 'somename')
        self.assertEqual(exc.path, 'somepath')

        msg = ("'invalid' is an invalid keyword argument for ImportError"
               if sys.version_info >= (3, 7) else ".*keyword argument.*")
        with self.assertRaisesRegex(TypeError, msg):
            ImportError('test', invalid='keyword')

        with self.assertRaisesRegex(TypeError, msg):
            ImportError('test', name='name', invalid='keyword')

        with self.assertRaisesRegex(TypeError, msg):
            ImportError('test', path='path', invalid='keyword')

        with self.assertRaisesRegex(TypeError, msg):
            ImportError(invalid='keyword')

        with self.assertRaisesRegex(TypeError, msg):
            ImportError('test', invalid='keyword', another=True)

    @unittest.skipIf(sys.version_info < (3, 7), "requires Py3.7+")
    def test_reset_attributes(self):
        exc = ImportError('test', name='name', path='path')
        self.assertEqual(exc.args, ('test',))
        self.assertEqual(exc.msg, 'test')
        self.assertEqual(exc.name, 'name')
        self.assertEqual(exc.path, 'path')

        # Reset not specified attributes
        exc.__init__()
        self.assertEqual(exc.args, ())
        self.assertEqual(exc.msg, None)
        self.assertEqual(exc.name, None)
        self.assertEqual(exc.path, None)

    def test_non_str_argument(self):
        # Issue #15778
        with check_warnings(('', BytesWarning), quiet=True):
            arg = b'abc'
            exc = ImportError(arg)
            self.assertEqual(str(arg), str(exc))

    @unittest.skipIf(sys.version_info < (3, 6), "Requires Py3.6+")
    def test_copy_pickle(self):
        for kwargs in (dict(),
                       dict(name='somename'),
                       dict(path='somepath'),
                       dict(name='somename', path='somepath')):
            orig = ImportError('test', **kwargs)
            for proto in range(pickle.HIGHEST_PROTOCOL + 1):
                exc = pickle.loads(pickle.dumps(orig, proto))
                self.assertEqual(exc.args, ('test',))
                self.assertEqual(exc.msg, 'test')
                self.assertEqual(exc.name, orig.name)
                self.assertEqual(exc.path, orig.path)
            for c in copy.copy, copy.deepcopy:
                exc = c(orig)
                self.assertEqual(exc.args, ('test',))
                self.assertEqual(exc.msg, 'test')
                self.assertEqual(exc.name, orig.name)
                self.assertEqual(exc.path, orig.path)


if __name__ == '__main__':
    unittest.main()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/test_fstring.pyx0000644000175100001770000014251200000000000021024 0ustar00runnerdocker00000000000000# cython: language_level=3
# mode: run
# tag: allow_unknown_names, f_strings, pep498

import ast
import os
import types
import decimal
import unittest

import sys
IS_PY2 = sys.version_info[0] < 3
if IS_PY2:
    # Define `ascii` as `repr` for Python2 as it functions
    # the same way in that version.
    ascii = repr

from Cython.Build.Inline import cython_inline
from Cython.TestUtils import CythonTest
from Cython.Compiler.Errors import CompileError, hold_errors, init_thread, held_errors

def cy_eval(s, **kwargs):
    return cython_inline('return ' + s, force=True, **kwargs)

a_global = 'global variable'

# You could argue that I'm too strict in looking for specific error
#  values with assertRaisesRegex, but without it it's way too easy to
#  make a syntax error in the test strings. Especially with all of the
#  triple quotes, raw strings, backslashes, etc. I think it's a
#  worthwhile tradeoff. When I switched to this method, I found many
#  examples where I wasn't testing what I thought I was.

class TestCase(CythonTest):
    def assertAllRaise(self, exception_type, regex, error_strings):
        for str in error_strings:
            hold_errors()
            if exception_type is SyntaxError:
                try:
                    self.fragment(str)
                except CompileError:
                    assert True
                else:
                    assert held_errors(), "Invalid Cython code failed to raise SyntaxError: %r" % str
                finally:
                    init_thread()  # reset error status
            else:
                try:
                    cython_inline(str, quiet=True)
                except exception_type:
                    assert True
                else:
                    assert False, "Invalid Cython code failed to raise %s: %r" % (exception_type, str)
                finally:
                    init_thread()  # reset error status

    if IS_PY2:
        def assertEqual(self, first, second, msg=None):
            # strip u'' string prefixes in Py2
            if first != second and isinstance(first, unicode):
                stripped_first = first.replace(u"u'", u"'").replace(u'u"', u'"')
                if stripped_first == second:
                    first = second
                elif u'\\' in stripped_first and stripped_first.encode('utf8').decode('unicode_escape') == second:
                    first = second
            super(TestCase, self).assertEqual(first, second, msg)

    def test__format__lookup(self):
        # Make sure __format__ is looked up on the type, not the instance.
        class X:
            def __format__(self, spec):
                return 'class'

        x = X()

        # Add a bound __format__ method to the 'y' instance, but not
        #  the 'x' instance.
        y = X()
        y.__format__ = types.MethodType(lambda self, spec: 'instance', y)

        self.assertEqual(f'{y}', format(y))
        self.assertEqual(f'{y}', 'class')
        self.assertEqual(format(x), format(y))

        # __format__ is not called this way, but still make sure it
        #  returns what we expect (so we can make sure we're bypassing
        #  it).
        self.assertEqual(x.__format__(''), 'class')
        self.assertEqual(y.__format__(''), 'instance')

        # This is how __format__ is actually called.
        self.assertEqual(type(x).__format__(x, ''), 'class')
        self.assertEqual(type(y).__format__(y, ''), 'class')

    def __test_ast(self):
        # Inspired by https://bugs.python.org/issue24975
        class X:
            def __init__(self):
                self.called = False
            def __call__(self):
                self.called = True
                return 4
        x = X()
        expr = """
a = 10
f'{a * x()}'"""
        t = ast.parse(expr)
        c = compile(t, '', 'exec')

        # Make sure x was not called.
        self.assertFalse(x.called)

        # Actually run the code.
        exec(c)

        # Make sure x was called.
        self.assertTrue(x.called)

    def __test_ast_line_numbers(self):
        expr = """
a = 10
f'{a * x()}'"""
        t = ast.parse(expr)
        self.assertEqual(type(t), ast.Module)
        self.assertEqual(len(t.body), 2)
        # check `a = 10`
        self.assertEqual(type(t.body[0]), ast.Assign)
        self.assertEqual(t.body[0].lineno, 2)
        # check `f'...'`
        self.assertEqual(type(t.body[1]), ast.Expr)
        self.assertEqual(type(t.body[1].value), ast.JoinedStr)
        self.assertEqual(len(t.body[1].value.values), 1)
        self.assertEqual(type(t.body[1].value.values[0]), ast.FormattedValue)
        self.assertEqual(t.body[1].lineno, 3)
        self.assertEqual(t.body[1].value.lineno, 3)
        self.assertEqual(t.body[1].value.values[0].lineno, 3)
        # check the binop location
        binop = t.body[1].value.values[0].value
        self.assertEqual(type(binop), ast.BinOp)
        self.assertEqual(type(binop.left), ast.Name)
        self.assertEqual(type(binop.op), ast.Mult)
        self.assertEqual(type(binop.right), ast.Call)
        self.assertEqual(binop.lineno, 3)
        self.assertEqual(binop.left.lineno, 3)
        self.assertEqual(binop.right.lineno, 3)
        self.assertEqual(binop.col_offset, 3)
        self.assertEqual(binop.left.col_offset, 3)
        self.assertEqual(binop.right.col_offset, 7)

    def __test_ast_line_numbers_multiple_formattedvalues(self):
        expr = """
f'no formatted values'
f'eggs {a * x()} spam {b + y()}'"""
        t = ast.parse(expr)
        self.assertEqual(type(t), ast.Module)
        self.assertEqual(len(t.body), 2)
        # check `f'no formatted value'`
        self.assertEqual(type(t.body[0]), ast.Expr)
        self.assertEqual(type(t.body[0].value), ast.JoinedStr)
        self.assertEqual(t.body[0].lineno, 2)
        # check `f'...'`
        self.assertEqual(type(t.body[1]), ast.Expr)
        self.assertEqual(type(t.body[1].value), ast.JoinedStr)
        self.assertEqual(len(t.body[1].value.values), 4)
        self.assertEqual(type(t.body[1].value.values[0]), ast.Constant)
        self.assertEqual(type(t.body[1].value.values[0].value), str)
        self.assertEqual(type(t.body[1].value.values[1]), ast.FormattedValue)
        self.assertEqual(type(t.body[1].value.values[2]), ast.Constant)
        self.assertEqual(type(t.body[1].value.values[2].value), str)
        self.assertEqual(type(t.body[1].value.values[3]), ast.FormattedValue)
        self.assertEqual(t.body[1].lineno, 3)
        self.assertEqual(t.body[1].value.lineno, 3)
        self.assertEqual(t.body[1].value.values[0].lineno, 3)
        self.assertEqual(t.body[1].value.values[1].lineno, 3)
        self.assertEqual(t.body[1].value.values[2].lineno, 3)
        self.assertEqual(t.body[1].value.values[3].lineno, 3)
        # check the first binop location
        binop1 = t.body[1].value.values[1].value
        self.assertEqual(type(binop1), ast.BinOp)
        self.assertEqual(type(binop1.left), ast.Name)
        self.assertEqual(type(binop1.op), ast.Mult)
        self.assertEqual(type(binop1.right), ast.Call)
        self.assertEqual(binop1.lineno, 3)
        self.assertEqual(binop1.left.lineno, 3)
        self.assertEqual(binop1.right.lineno, 3)
        self.assertEqual(binop1.col_offset, 8)
        self.assertEqual(binop1.left.col_offset, 8)
        self.assertEqual(binop1.right.col_offset, 12)
        # check the second binop location
        binop2 = t.body[1].value.values[3].value
        self.assertEqual(type(binop2), ast.BinOp)
        self.assertEqual(type(binop2.left), ast.Name)
        self.assertEqual(type(binop2.op), ast.Add)
        self.assertEqual(type(binop2.right), ast.Call)
        self.assertEqual(binop2.lineno, 3)
        self.assertEqual(binop2.left.lineno, 3)
        self.assertEqual(binop2.right.lineno, 3)
        self.assertEqual(binop2.col_offset, 23)
        self.assertEqual(binop2.left.col_offset, 23)
        self.assertEqual(binop2.right.col_offset, 27)

    def __test_ast_line_numbers_nested(self):
        expr = """
a = 10
f'{a * f"-{x()}-"}'"""
        t = ast.parse(expr)
        self.assertEqual(type(t), ast.Module)
        self.assertEqual(len(t.body), 2)
        # check `a = 10`
        self.assertEqual(type(t.body[0]), ast.Assign)
        self.assertEqual(t.body[0].lineno, 2)
        # check `f'...'`
        self.assertEqual(type(t.body[1]), ast.Expr)
        self.assertEqual(type(t.body[1].value), ast.JoinedStr)
        self.assertEqual(len(t.body[1].value.values), 1)
        self.assertEqual(type(t.body[1].value.values[0]), ast.FormattedValue)
        self.assertEqual(t.body[1].lineno, 3)
        self.assertEqual(t.body[1].value.lineno, 3)
        self.assertEqual(t.body[1].value.values[0].lineno, 3)
        # check the binop location
        binop = t.body[1].value.values[0].value
        self.assertEqual(type(binop), ast.BinOp)
        self.assertEqual(type(binop.left), ast.Name)
        self.assertEqual(type(binop.op), ast.Mult)
        self.assertEqual(type(binop.right), ast.JoinedStr)
        self.assertEqual(binop.lineno, 3)
        self.assertEqual(binop.left.lineno, 3)
        self.assertEqual(binop.right.lineno, 3)
        self.assertEqual(binop.col_offset, 3)
        self.assertEqual(binop.left.col_offset, 3)
        self.assertEqual(binop.right.col_offset, 7)
        # check the nested call location
        self.assertEqual(len(binop.right.values), 3)
        self.assertEqual(type(binop.right.values[0]), ast.Constant)
        self.assertEqual(type(binop.right.values[0].value), str)
        self.assertEqual(type(binop.right.values[1]), ast.FormattedValue)
        self.assertEqual(type(binop.right.values[2]), ast.Constant)
        self.assertEqual(type(binop.right.values[2].value), str)
        self.assertEqual(binop.right.values[0].lineno, 3)
        self.assertEqual(binop.right.values[1].lineno, 3)
        self.assertEqual(binop.right.values[2].lineno, 3)
        call = binop.right.values[1].value
        self.assertEqual(type(call), ast.Call)
        self.assertEqual(call.lineno, 3)
        self.assertEqual(call.col_offset, 11)

    def __test_ast_line_numbers_duplicate_expression(self):
        """Duplicate expression

        NOTE: this is currently broken, always sets location of the first
        expression.
        """
        expr = """
a = 10
f'{a * x()} {a * x()} {a * x()}'
"""
        t = ast.parse(expr)
        self.assertEqual(type(t), ast.Module)
        self.assertEqual(len(t.body), 2)
        # check `a = 10`
        self.assertEqual(type(t.body[0]), ast.Assign)
        self.assertEqual(t.body[0].lineno, 2)
        # check `f'...'`
        self.assertEqual(type(t.body[1]), ast.Expr)
        self.assertEqual(type(t.body[1].value), ast.JoinedStr)
        self.assertEqual(len(t.body[1].value.values), 5)
        self.assertEqual(type(t.body[1].value.values[0]), ast.FormattedValue)
        self.assertEqual(type(t.body[1].value.values[1]), ast.Constant)
        self.assertEqual(type(t.body[1].value.values[1].value), str)
        self.assertEqual(type(t.body[1].value.values[2]), ast.FormattedValue)
        self.assertEqual(type(t.body[1].value.values[3]), ast.Constant)
        self.assertEqual(type(t.body[1].value.values[3].value), str)
        self.assertEqual(type(t.body[1].value.values[4]), ast.FormattedValue)
        self.assertEqual(t.body[1].lineno, 3)
        self.assertEqual(t.body[1].value.lineno, 3)
        self.assertEqual(t.body[1].value.values[0].lineno, 3)
        self.assertEqual(t.body[1].value.values[1].lineno, 3)
        self.assertEqual(t.body[1].value.values[2].lineno, 3)
        self.assertEqual(t.body[1].value.values[3].lineno, 3)
        self.assertEqual(t.body[1].value.values[4].lineno, 3)
        # check the first binop location
        binop = t.body[1].value.values[0].value
        self.assertEqual(type(binop), ast.BinOp)
        self.assertEqual(type(binop.left), ast.Name)
        self.assertEqual(type(binop.op), ast.Mult)
        self.assertEqual(type(binop.right), ast.Call)
        self.assertEqual(binop.lineno, 3)
        self.assertEqual(binop.left.lineno, 3)
        self.assertEqual(binop.right.lineno, 3)
        self.assertEqual(binop.col_offset, 3)
        self.assertEqual(binop.left.col_offset, 3)
        self.assertEqual(binop.right.col_offset, 7)
        # check the second binop location
        binop = t.body[1].value.values[2].value
        self.assertEqual(type(binop), ast.BinOp)
        self.assertEqual(type(binop.left), ast.Name)
        self.assertEqual(type(binop.op), ast.Mult)
        self.assertEqual(type(binop.right), ast.Call)
        self.assertEqual(binop.lineno, 3)
        self.assertEqual(binop.left.lineno, 3)
        self.assertEqual(binop.right.lineno, 3)
        self.assertEqual(binop.col_offset, 3)  # FIXME: this is wrong
        self.assertEqual(binop.left.col_offset, 3)  # FIXME: this is wrong
        self.assertEqual(binop.right.col_offset, 7)  # FIXME: this is wrong
        # check the third binop location
        binop = t.body[1].value.values[4].value
        self.assertEqual(type(binop), ast.BinOp)
        self.assertEqual(type(binop.left), ast.Name)
        self.assertEqual(type(binop.op), ast.Mult)
        self.assertEqual(type(binop.right), ast.Call)
        self.assertEqual(binop.lineno, 3)
        self.assertEqual(binop.left.lineno, 3)
        self.assertEqual(binop.right.lineno, 3)
        self.assertEqual(binop.col_offset, 3)  # FIXME: this is wrong
        self.assertEqual(binop.left.col_offset, 3)  # FIXME: this is wrong
        self.assertEqual(binop.right.col_offset, 7)  # FIXME: this is wrong

    def __test_ast_line_numbers_multiline_fstring(self):
        # See bpo-30465 for details.
        expr = """
a = 10
f'''
  {a
     *
       x()}
non-important content
'''
"""
        t = ast.parse(expr)
        self.assertEqual(type(t), ast.Module)
        self.assertEqual(len(t.body), 2)
        # check `a = 10`
        self.assertEqual(type(t.body[0]), ast.Assign)
        self.assertEqual(t.body[0].lineno, 2)
        # check `f'...'`
        self.assertEqual(type(t.body[1]), ast.Expr)
        self.assertEqual(type(t.body[1].value), ast.JoinedStr)
        self.assertEqual(len(t.body[1].value.values), 3)
        self.assertEqual(type(t.body[1].value.values[0]), ast.Constant)
        self.assertEqual(type(t.body[1].value.values[0].value), str)
        self.assertEqual(type(t.body[1].value.values[1]), ast.FormattedValue)
        self.assertEqual(type(t.body[1].value.values[2]), ast.Constant)
        self.assertEqual(type(t.body[1].value.values[2].value), str)
        self.assertEqual(t.body[1].lineno, 3)
        self.assertEqual(t.body[1].value.lineno, 3)
        self.assertEqual(t.body[1].value.values[0].lineno, 3)
        self.assertEqual(t.body[1].value.values[1].lineno, 3)
        self.assertEqual(t.body[1].value.values[2].lineno, 3)
        self.assertEqual(t.body[1].col_offset, 0)
        self.assertEqual(t.body[1].value.col_offset, 0)
        self.assertEqual(t.body[1].value.values[0].col_offset, 0)
        self.assertEqual(t.body[1].value.values[1].col_offset, 0)
        self.assertEqual(t.body[1].value.values[2].col_offset, 0)
        # NOTE: the following lineno information and col_offset is correct for
        # expressions within FormattedValues.
        binop = t.body[1].value.values[1].value
        self.assertEqual(type(binop), ast.BinOp)
        self.assertEqual(type(binop.left), ast.Name)
        self.assertEqual(type(binop.op), ast.Mult)
        self.assertEqual(type(binop.right), ast.Call)
        self.assertEqual(binop.lineno, 4)
        self.assertEqual(binop.left.lineno, 4)
        self.assertEqual(binop.right.lineno, 6)
        self.assertEqual(binop.col_offset, 4)
        self.assertEqual(binop.left.col_offset, 4)
        self.assertEqual(binop.right.col_offset, 7)

    def test_docstring(self):
        def f():
            f'''Not a docstring'''
        self.assertIsNone(f.__doc__)
        def g():
            '''Not a docstring''' \
            f''
        self.assertIsNone(g.__doc__)

    def __test_literal_eval(self):
        with self.assertRaisesRegex(ValueError, 'malformed node or string'):
            ast.literal_eval("f'x'")

    def __test_ast_compile_time_concat(self):
        x = ['']

        expr = """x[0] = 'foo' f'{3}'"""
        t = ast.parse(expr)
        c = compile(t, '', 'exec')
        exec(c)
        self.assertEqual(x[0], 'foo3')

    def test_compile_time_concat_errors(self):
        self.assertAllRaise(SyntaxError,
                            'cannot mix bytes and nonbytes literals',
                            [r"""f'' b''""",
                             r"""b'' f''""",
                             ])

    def test_literal(self):
        self.assertEqual(f'', '')
        self.assertEqual(f'a', 'a')
        self.assertEqual(f' ', ' ')

    def test_unterminated_string(self):
        self.assertAllRaise(SyntaxError, 'f-string: unterminated string',
                            [r"""f'{"x'""",
                             r"""f'{"x}'""",
                             r"""f'{("x'""",
                             r"""f'{("x}'""",
                             ])

    def test_mismatched_parens(self):
        self.assertAllRaise(SyntaxError, r"f-string: closing parenthesis '\}' "
                            r"does not match opening parenthesis '\('",
                            ["f'{((}'",
                             ])
        self.assertAllRaise(SyntaxError, r"f-string: closing parenthesis '\)' "
                            r"does not match opening parenthesis '\['",
                            ["f'{a[4)}'",
                            ])
        self.assertAllRaise(SyntaxError, r"f-string: closing parenthesis '\]' "
                            r"does not match opening parenthesis '\('",
                            ["f'{a(4]}'",
                            ])
        self.assertAllRaise(SyntaxError, r"f-string: closing parenthesis '\}' "
                            r"does not match opening parenthesis '\['",
                            ["f'{a[4}'",
                            ])
        self.assertAllRaise(SyntaxError, r"f-string: closing parenthesis '\}' "
                            r"does not match opening parenthesis '\('",
                            ["f'{a(4}'",
                            ])
        self.assertRaises(SyntaxError, eval, "f'{" + "("*500 + "}'")

    def test_double_braces(self):
        self.assertEqual(f'{{', '{')
        self.assertEqual(f'a{{', 'a{')
        self.assertEqual(f'{{b', '{b')
        self.assertEqual(f'a{{b', 'a{b')
        self.assertEqual(f'}}', '}')
        self.assertEqual(f'a}}', 'a}')
        self.assertEqual(f'}}b', '}b')
        self.assertEqual(f'a}}b', 'a}b')
        self.assertEqual(f'{{}}', '{}')
        self.assertEqual(f'a{{}}', 'a{}')
        self.assertEqual(f'{{b}}', '{b}')
        self.assertEqual(f'{{}}c', '{}c')
        self.assertEqual(f'a{{b}}', 'a{b}')
        self.assertEqual(f'a{{}}c', 'a{}c')
        self.assertEqual(f'{{b}}c', '{b}c')
        self.assertEqual(f'a{{b}}c', 'a{b}c')

        self.assertEqual(f'{{{10}', '{10')
        self.assertEqual(f'}}{10}', '}10')
        self.assertEqual(f'}}{{{10}', '}{10')
        self.assertEqual(f'}}a{{{10}', '}a{10')

        self.assertEqual(f'{10}{{', '10{')
        self.assertEqual(f'{10}}}', '10}')
        self.assertEqual(f'{10}}}{{', '10}{')
        self.assertEqual(f'{10}}}a{{' '}', '10}a{}')

        # Inside of strings, don't interpret doubled brackets.
        self.assertEqual(f'{"{{}}"}', '{{}}')

        self.assertAllRaise(TypeError, 'unhashable type',
                            ["f'{ {{}} }'", # dict in a set
                             ])

    def test_compile_time_concat(self):
        x = 'def'
        self.assertEqual('abc' f'## {x}ghi', 'abc## defghi')
        self.assertEqual('abc' f'{x}' 'ghi', 'abcdefghi')
        self.assertEqual('abc' f'{x}' 'gh' f'i{x:4}', 'abcdefghidef ')
        self.assertEqual('{x}' f'{x}', '{x}def')
        self.assertEqual('{x' f'{x}', '{xdef')
        self.assertEqual('{x}' f'{x}', '{x}def')
        self.assertEqual('{{x}}' f'{x}', '{{x}}def')
        self.assertEqual('{{x' f'{x}', '{{xdef')
        self.assertEqual('x}}' f'{x}', 'x}}def')
        self.assertEqual(f'{x}' 'x}}', 'defx}}')
        self.assertEqual(f'{x}' '', 'def')
        self.assertEqual('' f'{x}' '', 'def')
        self.assertEqual('' f'{x}', 'def')
        self.assertEqual(f'{x}' '2', 'def2')
        self.assertEqual('1' f'{x}' '2', '1def2')
        self.assertEqual('1' f'{x}', '1def')
        self.assertEqual(f'{x}' f'-{x}', 'def-def')
        self.assertEqual('' f'', '')
        self.assertEqual('' f'' '', '')
        self.assertEqual('' f'' '' f'', '')
        self.assertEqual(f'', '')
        self.assertEqual(f'' '', '')
        self.assertEqual(f'' '' f'', '')
        self.assertEqual(f'' '' f'' '', '')

        self.assertAllRaise(SyntaxError, "f-string: expecting '}'",
                            ["f'{3' f'}'",  # can't concat to get a valid f-string
                             ])

    def test_comments(self):
        # These aren't comments, since they're in strings.
        d = {'#': 'hash'}
        self.assertEqual(f'{"#"}', '#')
        self.assertEqual(f'{d["#"]}', 'hash')

        self.assertAllRaise(SyntaxError, "f-string expression part cannot include '#'",
                            ["f'{1#}'",   # error because the expression becomes "(1#)"
                             "f'{3(#)}'",
                             "f'{#}'",
                             ])
        self.assertAllRaise(SyntaxError, r"f-string: unmatched '\)'",
                            ["f'{)#}'",   # When wrapped in parens, this becomes
                                          #  '()#)'.  Make sure that doesn't compile.
                             ])

    def test_many_expressions(self):
        # Create a string with many expressions in it. Note that
        #  because we have a space in here as a literal, we're actually
        #  going to use twice as many ast nodes: one for each literal
        #  plus one for each expression.
        def build_fstr(n, extra=''):
            return "f'" + ('{x} ' * n) + extra + "'"

        x = 'X'
        width = 1

        # Test around 256.
        # for i in range(250, 260):
        #     self.assertEqual(eval(build_fstr(i)), (x+' ')*i)
        self.assertEqual(
            cy_eval('[' + ', '.join(build_fstr(i) for i in range(250, 260)) + ']', x=x, width=width),
            [(x+' ')*i for i in range(250, 260)],
        )

        # Test concatenating 2 largs fstrings.
        # self.assertEqual(eval(build_fstr(255)*256), (x+' ')*(255*256))
        self.assertEqual(cy_eval(build_fstr(255)*3, x=x, width=width), (x+' ')*(255*3))  # CPython uses 255*256

        s = build_fstr(253, '{x:{width}} ')
        # self.assertEqual(eval(s), (x+' ')*254)
        self.assertEqual(cy_eval(s, x=x, width=width), (x+' ')*254)

        # Test lots of expressions and constants, concatenated.
        s = "f'{1}' 'x' 'y'" * 1024
        # self.assertEqual(eval(s), '1xy' * 1024)
        self.assertEqual(cy_eval(s, x=x, width=width), '1xy' * 1024)

    def test_format_specifier_expressions(self):
        width = 10
        precision = 4
        value = decimal.Decimal('12.34567')
        self.assertEqual(f'result: {value:{width}.{precision}}', 'result:      12.35')
        self.assertEqual(f'result: {value:{width!r}.{precision}}', 'result:      12.35')
        self.assertEqual(f'result: {value:{width:0}.{precision:1}}', 'result:      12.35')
        self.assertEqual(f'result: {value:{1}{0:0}.{precision:1}}', 'result:      12.35')
        self.assertEqual(f'result: {value:{ 1}{ 0:0}.{ precision:1}}', 'result:      12.35')
        self.assertEqual(f'{10:#{1}0x}', '       0xa')
        self.assertEqual(f'{10:{"#"}1{0}{"x"}}', '       0xa')
        self.assertEqual(f'{-10:-{"#"}1{0}x}', '      -0xa')
        self.assertEqual(f'{-10:{"-"}#{1}0{"x"}}', '      -0xa')
        self.assertEqual(f'{10:#{3 != {4:5} and width}x}', '       0xa')

        self.assertAllRaise(SyntaxError, "f-string: expecting '}'",
                            ["""f'{"s"!r{":10"}}'""",

                             # This looks like a nested format spec.
                             ])

        self.assertAllRaise(SyntaxError, "f-string: invalid syntax",
                            [# Invalid syntax inside a nested spec.
                             "f'{4:{/5}}'",
                             ])

        # CYTHON: The nesting restriction seems rather arbitrary. Ignoring it for now and instead test that it works.
        self.assertEqual(f'result: {value:{width:{0}}.{precision:1}}', 'result:      12.35')
        #self.assertAllRaise(SyntaxError, "f-string: expressions nested too deeply",
        #                    [# Can't nest format specifiers.
        #                     "f'result: {value:{width:{0}}.{precision:1}}'",
        #                     ])

        self.assertAllRaise(SyntaxError, 'f-string: invalid conversion character',
                            [# No expansion inside conversion or for
                             #  the : or ! itself.
                             """f'{"s"!{"r"}}'""",
                             ])

    def test_side_effect_order(self):
        class X:
            def __init__(self):
                self.i = 0
            def __format__(self, spec):
                self.i += 1
                return str(self.i)

        x = X()
        self.assertEqual(f'{x} {x}', '1 2')

    def test_missing_expression(self):
        self.assertAllRaise(SyntaxError, 'f-string: empty expression not allowed',
                            ["f'{}'",
                             "f'{ }'"
                             "f' {} '",
                             "f'{!r}'",
                             "f'{ !r}'",
                             "f'{10:{ }}'",
                             "f' { } '",

                             # The Python parser ignores also the following
                             # whitespace characters in additional to a space.
                             "f'''{\t\f\r\n}'''",

                             # Catch the empty expression before the
                             #  invalid conversion.
                             "f'{!x}'",
                             "f'{ !xr}'",
                             "f'{!x:}'",
                             "f'{!x:a}'",
                             "f'{ !xr:}'",
                             "f'{ !xr:a}'",

                             "f'{!}'",
                             "f'{:}'",

                             # We find the empty expression before the
                             #  missing closing brace.
                             "f'{!'",
                             "f'{!s:'",
                             "f'{:'",
                             "f'{:x'",
                             ])

        # Different error message is raised for other whitespace characters.
        self.assertAllRaise(SyntaxError, r"invalid non-printable character U\+00A0",
                            ["f'''{\xa0}'''",
                             #"\xa0",
                             ])

    def test_parens_in_expressions(self):
        self.assertEqual(f'{3,}', '(3,)')

        # Add these because when an expression is evaluated, parens
        #  are added around it. But we shouldn't go from an invalid
        #  expression to a valid one. The added parens are just
        #  supposed to allow whitespace (including newlines).
        self.assertAllRaise(SyntaxError, 'f-string: invalid syntax',
                            ["f'{,}'",
                             "f'{,}'",  # this is (,), which is an error
                             ])

        self.assertAllRaise(SyntaxError, r"f-string: unmatched '\)'",
                            ["f'{3)+(4}'",
                             ])

        self.assertAllRaise(SyntaxError, 'EOL while scanning string literal',
                            ["f'{\n}'",
                             ])

    def test_backslashes_in_string_part(self):
        self.assertEqual(f'\t', '\t')
        self.assertEqual(r'\t', '\\t')
        self.assertEqual(rf'\t', '\\t')
        self.assertEqual(f'{2}\t', '2\t')
        self.assertEqual(f'{2}\t{3}', '2\t3')
        self.assertEqual(f'\t{3}', '\t3')

        self.assertEqual(f'\u0394', '\u0394')
        self.assertEqual(r'\u0394', '\\u0394')
        self.assertEqual(rf'\u0394', '\\u0394')
        self.assertEqual(f'{2}\u0394', '2\u0394')
        self.assertEqual(f'{2}\u0394{3}', '2\u03943')
        self.assertEqual(f'\u0394{3}', '\u03943')

        self.assertEqual(f'\U00000394', '\u0394')
        self.assertEqual(r'\U00000394', '\\U00000394')
        self.assertEqual(rf'\U00000394', '\\U00000394')
        self.assertEqual(f'{2}\U00000394', '2\u0394')
        self.assertEqual(f'{2}\U00000394{3}', '2\u03943')
        self.assertEqual(f'\U00000394{3}', '\u03943')

        self.assertEqual(f'\N{GREEK CAPITAL LETTER DELTA}', '\u0394')
        self.assertEqual(f'{2}\N{GREEK CAPITAL LETTER DELTA}', '2\u0394')
        self.assertEqual(f'{2}\N{GREEK CAPITAL LETTER DELTA}{3}', '2\u03943')
        self.assertEqual(f'\N{GREEK CAPITAL LETTER DELTA}{3}', '\u03943')
        self.assertEqual(f'2\N{GREEK CAPITAL LETTER DELTA}', '2\u0394')
        self.assertEqual(f'2\N{GREEK CAPITAL LETTER DELTA}3', '2\u03943')
        self.assertEqual(f'\N{GREEK CAPITAL LETTER DELTA}3', '\u03943')

        self.assertEqual(f'\x20', ' ')
        self.assertEqual(r'\x20', '\\x20')
        self.assertEqual(rf'\x20', '\\x20')
        self.assertEqual(f'{2}\x20', '2 ')
        self.assertEqual(f'{2}\x20{3}', '2 3')
        self.assertEqual(f'\x20{3}', ' 3')

        self.assertEqual(f'2\x20', '2 ')
        self.assertEqual(f'2\x203', '2 3')
        self.assertEqual(f'\x203', ' 3')

        #with self.assertWarns(DeprecationWarning):  # invalid escape sequence
        #    value = cy_eval(r"f'\{6*7}'")
        #self.assertEqual(value, '\\42')
        self.assertEqual(f'\\{6*7}', '\\42')
        self.assertEqual(fr'\{6*7}', '\\42')

        AMPERSAND = 'spam'
        # Get the right unicode character (&), or pick up local variable
        # depending on the number of backslashes.
        self.assertEqual(f'\N{AMPERSAND}', '&')
        self.assertEqual(f'\\N{AMPERSAND}', '\\Nspam')
        self.assertEqual(fr'\N{AMPERSAND}', '\\Nspam')
        self.assertEqual(f'\\\N{AMPERSAND}', '\\&')

    def test_misformed_unicode_character_name(self):
        # These test are needed because unicode names are parsed
        # differently inside f-strings.
        self.assertAllRaise(SyntaxError, r"\(unicode error\) 'unicodeescape' codec can't decode bytes in position .*: malformed \\N character escape",
                            [r"f'\N'",
                             r"f'\N{'",
                             r"f'\N{GREEK CAPITAL LETTER DELTA'",

                             # Here are the non-f-string versions,
                             #  which should give the same errors.
                             r"'\N'",
                             r"'\N{'",
                             r"'\N{GREEK CAPITAL LETTER DELTA'",
                             ])

    def test_no_backslashes_in_expression_part(self):
        self.assertAllRaise(SyntaxError, 'f-string expression part cannot include a backslash',
                            [r"f'{\'a\'}'",
                             r"f'{\t3}'",
                             r"f'{\}'",
                             r"rf'{\'a\'}'",
                             r"rf'{\t3}'",
                             r"rf'{\}'",
                             r"""rf'{"\N{LEFT CURLY BRACKET}"}'""",
                             r"f'{\n}'",
                             ])

    def test_no_escapes_for_braces(self):
        """
        Only literal curly braces begin an expression.
        """
        # \x7b is '{'.
        self.assertEqual(f'\x7b1+1}}', '{1+1}')
        self.assertEqual(f'\x7b1+1', '{1+1')
        self.assertEqual(f'\u007b1+1', '{1+1')
        self.assertEqual(f'\N{LEFT CURLY BRACKET}1+1\N{RIGHT CURLY BRACKET}', '{1+1}')

    def test_newlines_in_expressions(self):
        self.assertEqual(f'{0}', '0')
        self.assertEqual(rf'''{3+
4}''', '7')

    def test_lambda(self):
        x = 5
        self.assertEqual(f'{(lambda y:x*y)("8")!r}', "'88888'")
        if not IS_PY2:
            self.assertEqual(f'{(lambda y:x*y)("8")!r:10}', "'88888'   ")
        self.assertEqual(f'{(lambda y:x*y)("8"):10}', "88888     ")

        # lambda doesn't work without parens, because the colon
        #  makes the parser think it's a format_spec
        self.assertAllRaise(SyntaxError, 'f-string: invalid syntax',
                            ["f'{lambda x:x}'",
                             ])

    def test_yield(self):
        # Not terribly useful, but make sure the yield turns
        #  a function into a generator
        def fn(y):
            f'y:{yield y*2}'
            f'{yield}'

        g = fn(4)
        self.assertEqual(next(g), 8)
        self.assertEqual(next(g), None)

    def test_yield_send(self):
        def fn(x):
            yield f'x:{yield (lambda i: x * i)}'

        g = fn(10)
        the_lambda = next(g)
        self.assertEqual(the_lambda(4), 40)
        self.assertEqual(g.send('string'), 'x:string')

    def test_expressions_with_triple_quoted_strings(self):
        self.assertEqual(f"{'''x'''}", 'x')
        self.assertEqual(f"{'''eric's'''}", "eric's")

        # Test concatenation within an expression
        self.assertEqual(f'{"x" """eric"s""" "y"}', 'xeric"sy')
        self.assertEqual(f'{"x" """eric"s"""}', 'xeric"s')
        self.assertEqual(f'{"""eric"s""" "y"}', 'eric"sy')
        self.assertEqual(f'{"""x""" """eric"s""" "y"}', 'xeric"sy')
        self.assertEqual(f'{"""x""" """eric"s""" """y"""}', 'xeric"sy')
        self.assertEqual(f'{r"""x""" """eric"s""" """y"""}', 'xeric"sy')

    def test_multiple_vars(self):
        x = 98
        y = 'abc'
        self.assertEqual(f'{x}{y}', '98abc')

        self.assertEqual(f'X{x}{y}', 'X98abc')
        self.assertEqual(f'{x}X{y}', '98Xabc')
        self.assertEqual(f'{x}{y}X', '98abcX')

        self.assertEqual(f'X{x}Y{y}', 'X98Yabc')
        self.assertEqual(f'X{x}{y}Y', 'X98abcY')
        self.assertEqual(f'{x}X{y}Y', '98XabcY')

        self.assertEqual(f'X{x}Y{y}Z', 'X98YabcZ')

    def test_closure(self):
        def outer(x):
            def inner():
                return f'x:{x}'
            return inner

        self.assertEqual(outer('987')(), 'x:987')
        self.assertEqual(outer(7)(), 'x:7')

    def test_arguments(self):
        y = 2
        def f(x, width):
            return f'x={x*y:{width}}'

        self.assertEqual(f('foo', 10), 'x=foofoo    ')
        x = 'bar'
        self.assertEqual(f(10, 10), 'x=        20')

    def test_locals(self):
        value = 123
        self.assertEqual(f'v:{value}', 'v:123')

    def test_missing_variable(self):
        with self.assertRaises(NameError):
            f'v:{value}'

    def test_missing_format_spec(self):
        class O:
            def __format__(self, spec):
                if not spec:
                    return '*'
                return spec

        self.assertEqual(f'{O():x}', 'x')
        self.assertEqual(f'{O()}', '*')
        self.assertEqual(f'{O():}', '*')

        self.assertEqual(f'{3:}', '3')
        self.assertEqual(f'{3!s:}', '3')

    def test_global(self):
        self.assertEqual(f'g:{a_global}', 'g:global variable')
        self.assertEqual(f'g:{a_global!r}', "g:'global variable'")

        a_local = 'local variable'
        self.assertEqual(f'g:{a_global} l:{a_local}',
                         'g:global variable l:local variable')
        self.assertEqual(f'g:{a_global!r}',
                         "g:'global variable'")
        self.assertEqual(f'g:{a_global} l:{a_local!r}',
                         "g:global variable l:'local variable'")

        self.assertIn("module 'unittest' from", f'{unittest}')

    def test_shadowed_global(self):
        a_global = 'really a local'
        self.assertEqual(f'g:{a_global}', 'g:really a local')
        self.assertEqual(f'g:{a_global!r}', "g:'really a local'")

        a_local = 'local variable'
        self.assertEqual(f'g:{a_global} l:{a_local}',
                         'g:really a local l:local variable')
        self.assertEqual(f'g:{a_global!r}',
                         "g:'really a local'")
        self.assertEqual(f'g:{a_global} l:{a_local!r}',
                         "g:really a local l:'local variable'")

    def test_call(self):
        def foo(x):
            return 'x=' + str(x)

        self.assertEqual(f'{foo(10)}', 'x=10')

    def test_nested_fstrings(self):
        y = 5
        self.assertEqual(f'{f"{0}"*3}', '000')
        self.assertEqual(f'{f"{y}"*3}', '555')

    def test_invalid_string_prefixes(self):
        single_quote_cases = ["fu''",
                             "uf''",
                             "Fu''",
                             "fU''",
                             "Uf''",
                             "uF''",
                             "ufr''",
                             "urf''",
                             "fur''",
                             "fru''",
                             "rfu''",
                             "ruf''",
                             "FUR''",
                             "Fur''",
                             "fb''",
                             "fB''",
                             "Fb''",
                             "FB''",
                             "bf''",
                             "bF''",
                             "Bf''",
                             "BF''",]
        double_quote_cases = [case.replace("'", '"') for case in single_quote_cases]
        self.assertAllRaise(SyntaxError, 'unexpected EOF while parsing',
                            single_quote_cases + double_quote_cases)

    def test_leading_trailing_spaces(self):
        self.assertEqual(f'{ 3}', '3')
        self.assertEqual(f'{  3}', '3')
        self.assertEqual(f'{3 }', '3')
        self.assertEqual(f'{3  }', '3')

        self.assertEqual(f'expr={ {x: y for x, y in [(1, 2), ]}}',
                         'expr={1: 2}')
        self.assertEqual(f'expr={ {x: y for x, y in [(1, 2), ]} }',
                         'expr={1: 2}')

    def test_not_equal(self):
        # There's a special test for this because there's a special
        #  case in the f-string parser to look for != as not ending an
        #  expression. Normally it would, while looking for !s or !r.

        self.assertEqual(f'{3!=4}', 'True')
        self.assertEqual(f'{3!=4:}', 'True')
        self.assertEqual(f'{3!=4!s}', 'True')
        self.assertEqual(f'{3!=4!s:.3}', 'Tru')

    def test_equal_equal(self):
        # Because an expression ending in = has special meaning,
        # there's a special test for ==. Make sure it works.

        self.assertEqual(f'{0==1}', 'False')

    def test_conversions(self):
        self.assertEqual(f'{3.14:10.10}', '      3.14')
        self.assertEqual(f'{3.14!s:10.10}', '3.14      ')
        self.assertEqual(f'{3.14!r:10.10}', '3.14      ')
        self.assertEqual(f'{3.14!a:10.10}', '3.14      ')

        self.assertEqual(f'{"a"}', 'a')
        self.assertEqual(f'{"a"!r}', "'a'")
        self.assertEqual(f'{"a"!a}', "'a'")

        # Not a conversion.
        self.assertEqual(f'{"a!r"}', "a!r")

        # Not a conversion, but show that ! is allowed in a format spec.
        self.assertEqual(f'{3.14:!<10.10}', '3.14!!!!!!')

        self.assertAllRaise(SyntaxError, 'f-string: invalid conversion character',
                            ["f'{3!g}'",
                             "f'{3!A}'",
                             "f'{3!3}'",
                             "f'{3!G}'",
                             "f'{3!!}'",
                             "f'{3!:}'",
                             "f'{3! s}'",  # no space before conversion char
                             ])

        self.assertAllRaise(SyntaxError, "f-string: expecting '}'",
                            ["f'{x!s{y}}'",
                             "f'{3!ss}'",
                             "f'{3!ss:}'",
                             "f'{3!ss:s}'",
                             ])

    def test_assignment(self):
        self.assertAllRaise(SyntaxError, 'invalid syntax',
                            ["f'' = 3",
                             "f'{0}' = x",
                             "f'{x}' = x",
                             ])

    def test_del(self):
        self.assertAllRaise(CompileError, 'invalid syntax',   # CPython raises SyntaxError
                            ["del f''",
                             "del '' f''",
                             ])

    def test_mismatched_braces(self):
        self.assertAllRaise(SyntaxError, "f-string: single '}' is not allowed",
                            ["f'{{}'",
                             "f'{{}}}'",
                             "f'}'",
                             "f'x}'",
                             "f'x}x'",
                             r"f'\u007b}'",

                             # Can't have { or } in a format spec.
                             "f'{3:}>10}'",
                             "f'{3:}}>10}'",
                             ])

        self.assertAllRaise(SyntaxError, "f-string: expecting '}'",
                            ["f'{3:{{>10}'",
                             "f'{3'",
                             "f'{3!'",
                             "f'{3:'",
                             "f'{3!s'",
                             "f'{3!s:'",
                             "f'{3!s:3'",
                             "f'x{'",
                             "f'x{x'",
                             "f'{x'",
                             "f'{3:s'",
                             "f'{{{'",
                             "f'{{}}{'",
                             "f'{'",
                             ])

        # But these are just normal strings.
        self.assertEqual(f'{"{"}', '{')
        self.assertEqual(f'{"}"}', '}')
        self.assertEqual(f'{3:{"}"}>10}', '}}}}}}}}}3')
        self.assertEqual(f'{2:{"{"}>10}', '{{{{{{{{{2')

    def test_if_conditional(self):
        # There's special logic in compile.c to test if the
        #  conditional for an if (and while) are constants. Exercise
        #  that code.

        def test_fstring(x, expected):
            flag = 0
            if f'{x}':
                flag = 1
            else:
                flag = 2
            self.assertEqual(flag, expected)

        def test_concat_empty(x, expected):
            flag = 0
            if '' f'{x}':
                flag = 1
            else:
                flag = 2
            self.assertEqual(flag, expected)

        def test_concat_non_empty(x, expected):
            flag = 0
            if ' ' f'{x}':
                flag = 1
            else:
                flag = 2
            self.assertEqual(flag, expected)

        test_fstring('', 2)
        test_fstring(' ', 1)

        test_concat_empty('', 2)
        test_concat_empty(' ', 1)

        test_concat_non_empty('', 1)
        test_concat_non_empty(' ', 1)

    def test_empty_format_specifier(self):
        x = 'test'
        self.assertEqual(f'{x}', 'test')
        self.assertEqual(f'{x:}', 'test')
        self.assertEqual(f'{x!s:}', 'test')
        self.assertEqual(f'{x!r:}', "'test'")

    def test_str_format_differences(self):
        d = {'a': 'string',
             0: 'integer',
             }
        a = 0
        self.assertEqual(f'{d[0]}', 'integer')
        self.assertEqual(f'{d["a"]}', 'string')
        self.assertEqual(f'{d[a]}', 'integer')
        self.assertEqual('{d[a]}'.format(d=d), 'string')
        self.assertEqual('{d[0]}'.format(d=d), 'integer')

    def test_errors(self):
        # see issue 26287
        exc = ValueError if sys.version_info < (3, 4) else TypeError
        self.assertAllRaise(exc, 'unsupported',
                            [r"f'{(lambda: 0):x}'",
                             r"f'{(0,):x}'",
                             ])
        self.assertAllRaise(ValueError, 'Unknown format code',
                            [r"f'{1000:j}'",
                             r"f'{1000:j}'",
                            ])

    def __test_filename_in_syntaxerror(self):
        # see issue 38964
        with temp_cwd() as cwd:
            file_path = os.path.join(cwd, 't.py')
            with open(file_path, 'w') as f:
                f.write('f"{a b}"') # This generates a SyntaxError
            _, _, stderr = assert_python_failure(file_path,
                                                 PYTHONIOENCODING='ascii')
        self.assertIn(file_path.encode('ascii', 'backslashreplace'), stderr)

    def test_loop(self):
        for i in range(1000):
            self.assertEqual(f'i:{i}', 'i:' + str(i))

    def test_dict(self):
        d = {'"': 'dquote',
             "'": 'squote',
             'foo': 'bar',
             }
        self.assertEqual(f'''{d["'"]}''', 'squote')
        self.assertEqual(f"""{d['"']}""", 'dquote')

        self.assertEqual(f'{d["foo"]}', 'bar')
        self.assertEqual(f"{d['foo']}", 'bar')

    def __test_backslash_char(self):
        # Check eval of a backslash followed by a control char.
        # See bpo-30682: this used to raise an assert in pydebug mode.
        self.assertEqual(cy_eval('f"\\\n"'), '')
        self.assertEqual(cy_eval('f"\\\r"'), '')

    def test_debug_conversion(self):
        x = 'A string'
        self.assertEqual(f'{x=}', 'x=' + repr(x))
        self.assertEqual(f'{x =}', 'x =' + repr(x))
        self.assertEqual(f'{x=!s}', 'x=' + str(x))
        self.assertEqual(f'{x=!r}', 'x=' + repr(x))
        self.assertEqual(f'{x=!a}', 'x=' + ascii(x))

        x = 2.71828
        self.assertEqual(f'{x=:.2f}', 'x=' + format(x, '.2f'))
        self.assertEqual(f'{x=:}', 'x=' + format(x, ''))
        self.assertEqual(f'{x=!r:^20}', 'x=' + format(repr(x), '^20'))
        self.assertEqual(f'{x=!s:^20}', 'x=' + format(str(x), '^20'))
        self.assertEqual(f'{x=!a:^20}', 'x=' + format(ascii(x), '^20'))

        x = 9
        self.assertEqual(f'{3*x+15=}', '3*x+15=42')

        # There is code in ast.c that deals with non-ascii expression values.  So,
        # use a unicode identifier to trigger that.
        tenπ = 31.4
        self.assertEqual(f'{tenπ=:.2f}', 'tenπ=31.40')

        # Also test with Unicode in non-identifiers.
        if not IS_PY2:  # unicode representation looks different right now - not sure if that's a good thing
            self.assertEqual(f'{"Σ"=}', '"Σ"=\'Σ\'')

        # Make sure nested fstrings still work.
        self.assertEqual(f'{f"{3.1415=:.1f}":*^20}', '*****3.1415=3.1*****')

        # Make sure text before and after an expression with = works
        # correctly.
        pi = 'π'
        if not IS_PY2:  # unicode representation looks different right now - not sure if that's a good thing
            self.assertEqual(f'alpha α {pi=} ω omega', u"alpha α pi='π' ω omega")

        # Check multi-line expressions.
        self.assertEqual(f'''{
3
=}''', '\n3\n=3')

        # Since = is handled specially, make sure all existing uses of
        # it still work.

        self.assertEqual(f'{0==1}', 'False')
        self.assertEqual(f'{0!=1}', 'True')
        self.assertEqual(f'{0<=1}', 'True')
        self.assertEqual(f'{0>=1}', 'False')
        self.assertEqual(f'{(x:="5")}', '5')
        self.assertEqual(x, '5')
        self.assertEqual(f'{(x:=5)}', '5')
        self.assertEqual(x, 5)
        self.assertEqual(f'{"="}', '=')

        x = 20
        # This isn't an assignment expression, it's 'x', with a format
        # spec of '=10'.  See test_walrus: you need to use parens.
        self.assertEqual(f'{x:=10}', '        20')

        # Test named function parameters, to make sure '=' parsing works
        # there.
        def f(a):
            nonlocal x
            oldx = x
            x = a
            return oldx
        x = 0
        self.assertEqual(f'{f(a="3=")}', '0')
        self.assertEqual(x, '3=')
        self.assertEqual(f'{f(a=4)}', '3=')
        self.assertEqual(x, 4)

        # Make sure __format__ is being called.
        class C:
            def __format__(self, s):
                return f'FORMAT-{s}'
            def __repr__(self):
                return 'REPR'

        self.assertEqual(f'{C()=}', 'C()=REPR')
        self.assertEqual(f'{C()=!r}', 'C()=REPR')
        self.assertEqual(f'{C()=:}', 'C()=FORMAT-')
        self.assertEqual(f'{C()=: }', 'C()=FORMAT- ')
        self.assertEqual(f'{C()=:x}', 'C()=FORMAT-x')
        self.assertEqual(f'{C()=!r:*^20}', 'C()=********REPR********')

        self.assertRaises(SyntaxError, eval, "f'{C=]'")

        # Make sure leading and following text works.
        x = 'foo'
        self.assertEqual(f'X{x=}Y', 'Xx='+repr(x)+'Y')

        # Make sure whitespace around the = works.
        self.assertEqual(f'X{x  =}Y', 'Xx  ='+repr(x)+'Y')
        self.assertEqual(f'X{x=  }Y', 'Xx=  '+repr(x)+'Y')
        self.assertEqual(f'X{x  =  }Y', 'Xx  =  '+repr(x)+'Y')

        # These next lines contains tabs.  Backslash escapes don't
        # work in f-strings.
        # patchcheck doesn't like these tabs.  So the only way to test
        # this will be to dynamically created and exec the f-strings.  But
        # that's such a hassle I'll save it for another day.  For now, convert
        # the tabs to spaces just to shut up patchcheck.
        #self.assertEqual(f'X{x =}Y', 'Xx\t='+repr(x)+'Y')
        #self.assertEqual(f'X{x =       }Y', 'Xx\t=\t'+repr(x)+'Y')


    def test_walrus(self):
        x = 20
        # This isn't an assignment expression, it's 'x', with a format
        # spec of '=10'.
        self.assertEqual(f'{x:=10}', '        20')

        # This is an assignment expression, which requires parens.
        self.assertEqual(f'{(x:=10)}', '10')
        self.assertEqual(x, 10)

    def test_invalid_syntax_error_message(self):
        # with self.assertRaisesRegex(SyntaxError, "f-string: invalid syntax"):
        #     compile("f'{a $ b}'", "?", "exec")
        self.assertAllRaise(CompileError, "f-string: invalid syntax", ["f'{a $ b}'"])


if __name__ == '__main__':
    unittest.main()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/test_genericclass.py0000644000175100001770000002312200000000000021615 0ustar00runnerdocker00000000000000# mode: run
# tag: pure3.7
# cython: language_level=3

# COPIED FROM CPython 3.7

import contextlib
import unittest
import sys

class TestMROEntry(unittest.TestCase):
    def test_mro_entry_signature(self):
        tested = []
        class B: ...
        class C:
            def __mro_entries__(self, *args, **kwargs):
                tested.extend([args, kwargs])
                return (C,)
        c = C()
        self.assertEqual(tested, [])
        class D(B, c): ...
        self.assertEqual(tested[0], ((B, c),))
        self.assertEqual(tested[1], {})

    def test_mro_entry(self):
        tested = []
        class A: ...
        class B: ...
        class C:
            def __mro_entries__(self, bases):
                tested.append(bases)
                return (self.__class__,)
        c = C()
        self.assertEqual(tested, [])
        class D(A, c, B): ...
        self.assertEqual(tested[-1], (A, c, B))
        self.assertEqual(D.__bases__, (A, C, B))
        self.assertEqual(D.__orig_bases__, (A, c, B))
        self.assertEqual(D.__mro__, (D, A, C, B, object))
        d = D()
        class E(d): ...
        self.assertEqual(tested[-1], (d,))
        self.assertEqual(E.__bases__, (D,))

    def test_mro_entry_none(self):
        tested = []
        class A: ...
        class B: ...
        class C:
            def __mro_entries__(self, bases):
                tested.append(bases)
                return ()
        c = C()
        self.assertEqual(tested, [])
        class D(A, c, B): ...
        self.assertEqual(tested[-1], (A, c, B))
        self.assertEqual(D.__bases__, (A, B))
        self.assertEqual(D.__orig_bases__, (A, c, B))
        self.assertEqual(D.__mro__, (D, A, B, object))
        class E(c): ...
        self.assertEqual(tested[-1], (c,))
        if sys.version_info[0] > 2:
            # not all of it works on Python 2
            self.assertEqual(E.__bases__, (object,))
        self.assertEqual(E.__orig_bases__, (c,))
        if sys.version_info[0] > 2:
            # not all of it works on Python 2
            self.assertEqual(E.__mro__, (E, object))

    def test_mro_entry_with_builtins(self):
        tested = []
        class A: ...
        class C:
            def __mro_entries__(self, bases):
                tested.append(bases)
                return (dict,)
        c = C()
        self.assertEqual(tested, [])
        class D(A, c): ...
        self.assertEqual(tested[-1], (A, c))
        self.assertEqual(D.__bases__, (A, dict))
        self.assertEqual(D.__orig_bases__, (A, c))
        self.assertEqual(D.__mro__, (D, A, dict, object))

    def test_mro_entry_with_builtins_2(self):
        tested = []
        class C:
            def __mro_entries__(self, bases):
                tested.append(bases)
                return (C,)
        c = C()
        self.assertEqual(tested, [])
        class D(c, dict): ...
        self.assertEqual(tested[-1], (c, dict))
        self.assertEqual(D.__bases__, (C, dict))
        self.assertEqual(D.__orig_bases__, (c, dict))
        self.assertEqual(D.__mro__, (D, C, dict, object))

    def test_mro_entry_errors(self):
        class C_too_many:
            def __mro_entries__(self, bases, something, other):
                return ()
        c = C_too_many()
        with self.assertRaises(TypeError):
            class D(c): ...
        class C_too_few:
            def __mro_entries__(self):
                return ()
        d = C_too_few()
        with self.assertRaises(TypeError):
            class D(d): ...

    def test_mro_entry_errors_2(self):
        class C_not_callable:
            __mro_entries__ = "Surprise!"
        c = C_not_callable()
        with self.assertRaises(TypeError):
            class D(c): ...
        class C_not_tuple:
            def __mro_entries__(self):
                return object
        c = C_not_tuple()
        with self.assertRaises(TypeError):
            class D(c): ...

    def test_mro_entry_metaclass(self):
        meta_args = []
        class Meta(type):
            def __new__(mcls, name, bases, ns):
                meta_args.extend([mcls, name, bases, ns])
                return super().__new__(mcls, name, bases, ns)
        class A: ...
        class C:
            def __mro_entries__(self, bases):
                return (A,)
        c = C()
        class D(c, metaclass=Meta):
            x = 1
        self.assertEqual(meta_args[0], Meta)
        self.assertEqual(meta_args[1], 'D')
        self.assertEqual(meta_args[2], (A,))
        self.assertEqual(meta_args[3]['x'], 1)
        self.assertEqual(D.__bases__, (A,))
        self.assertEqual(D.__orig_bases__, (c,))
        self.assertEqual(D.__mro__, (D, A, object))
        self.assertEqual(D.__class__, Meta)

    @unittest.skipIf(sys.version_info < (3, 7), "'type' checks for __mro_entries__ not implemented")
    def test_mro_entry_type_call(self):
        # Substitution should _not_ happen in direct type call
        class C:
            def __mro_entries__(self, bases):
                return ()
        c = C()
        with self.assertRaisesRegex(TypeError,
                                    "MRO entry resolution; "
                                    "use types.new_class()"):
            type('Bad', (c,), {})


class TestClassGetitem(unittest.TestCase):
    # BEGIN - Additional tests from cython
    def test_no_class_getitem(self):
        class C: ...
        # PyPy<7.3.8 raises AttributeError on __class_getitem__
        if hasattr(sys, "pypy_version_info")  and sys.pypy_version_info < (7, 3, 8):
            err = AttributeError
        else:
            err = TypeError
        with self.assertRaises(err):
            C[int]

    # END - Additional tests from cython

    def test_class_getitem(self):
        getitem_args = []
        class C:
            def __class_getitem__(*args, **kwargs):
                getitem_args.extend([args, kwargs])
                return None
        C[int, str]
        self.assertEqual(getitem_args[0], (C, (int, str)))
        self.assertEqual(getitem_args[1], {})

    def test_class_getitem_format(self):
        class C:
            def __class_getitem__(cls, item):
                return f'C[{item.__name__}]'
        self.assertEqual(C[int], 'C[int]')
        self.assertEqual(C[C], 'C[C]')

    def test_class_getitem_inheritance(self):
        class C:
            def __class_getitem__(cls, item):
                return f'{cls.__name__}[{item.__name__}]'
        class D(C): ...
        self.assertEqual(D[int], 'D[int]')
        self.assertEqual(D[D], 'D[D]')

    def test_class_getitem_inheritance_2(self):
        class C:
            def __class_getitem__(cls, item):
                return 'Should not see this'
        class D(C):
            def __class_getitem__(cls, item):
                return f'{cls.__name__}[{item.__name__}]'
        self.assertEqual(D[int], 'D[int]')
        self.assertEqual(D[D], 'D[D]')

    def test_class_getitem_classmethod(self):
        class C:
            @classmethod
            def __class_getitem__(cls, item):
                return f'{cls.__name__}[{item.__name__}]'
        class D(C): ...
        self.assertEqual(D[int], 'D[int]')
        self.assertEqual(D[D], 'D[D]')

    @unittest.skipIf(sys.version_info < (3, 6), "__init_subclass__() requires Py3.6+ (PEP 487)")
    def test_class_getitem_patched(self):
        class C:
            def __init_subclass__(cls):
                def __class_getitem__(cls, item):
                    return f'{cls.__name__}[{item.__name__}]'
                cls.__class_getitem__ = classmethod(__class_getitem__)
        class D(C): ...
        self.assertEqual(D[int], 'D[int]')
        self.assertEqual(D[D], 'D[D]')

    def test_class_getitem_with_builtins(self):
        class A(dict):
            called_with = None

            def __class_getitem__(cls, item):
                cls.called_with = item
        class B(A):
            pass
        self.assertIs(B.called_with, None)
        B[int]
        self.assertIs(B.called_with, int)

    def test_class_getitem_errors(self):
        class C_too_few:
            def __class_getitem__(cls):
                return None
        with self.assertRaises(TypeError):
            C_too_few[int]
        class C_too_many:
            def __class_getitem__(cls, one, two):
                return None
        with self.assertRaises(TypeError):
            C_too_many[int]

    def test_class_getitem_errors_2(self):
        class C:
            def __class_getitem__(cls, item):
                return None
        with self.assertRaises(TypeError):
            C()[int]
        class E: ...
        e = E()
        e.__class_getitem__ = lambda cls, item: 'This will not work'
        with self.assertRaises(TypeError):
            e[int]
        class C_not_callable:
            __class_getitem__ = "Surprise!"
        with self.assertRaises(TypeError):
            C_not_callable[int]

    def test_class_getitem_metaclass(self):
        class Meta(type):
            def __class_getitem__(cls, item):
                return f'{cls.__name__}[{item.__name__}]'
        self.assertEqual(Meta[int], 'Meta[int]')

    def test_class_getitem_with_metaclass(self):
        class Meta(type): pass
        class C(metaclass=Meta):
            def __class_getitem__(cls, item):
                return f'{cls.__name__}[{item.__name__}]'
        self.assertEqual(C[int], 'C[int]')

    def test_class_getitem_metaclass_first(self):
        class Meta(type):
            def __getitem__(cls, item):
                return 'from metaclass'
        class C(metaclass=Meta):
            def __class_getitem__(cls, item):
                return 'from __class_getitem__'
        self.assertEqual(C[int], 'from metaclass')


if __name__ == '__main__':
    unittest.main()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/test_genericclass_exttype.pyx0000644000175100001770000000550300000000000023572 0ustar00runnerdocker00000000000000# mode: run
# cython: language_level=3

import unittest
import sys


cdef class UnSupport: pass

cdef class Unpack:
    para_list = []
    def __class_getitem__(*args, **kwargs):
        Unpack.para_list.extend([args, kwargs])

cdef class Format:
    def __class_getitem__(cls, item):
        return f'{cls.__name__}[{item.__name__}]'

cdef class ExFormat(Format): pass

cdef class Override:
    def __class_getitem__(cls, item):
        return 'Should not see this'

cdef class Covered(Override):
    def __class_getitem__(cls, item):
        return f'{cls.__name__}[{item.__name__}]'

cdef class Decorated:
    @classmethod
    def __class_getitem__(cls, item):
        return f'{cls.__name__}[{item.__name__}]'

cdef class ExDecorated(Decorated): pass

cdef class Invalid1:
    def __class_getitem__(cls): pass

cdef class Invalid2:
    def __class_getitem__(cls, item1, item2): pass

cdef class Invalid3:
    cdef dict __dict__
    def __init__(self):
        self.__class_getitem__ = lambda cls, items: 'This will not work'

cdef class Invalid4:
    __class_getitem__ = "Surprise!"


class TestClassGetitem(unittest.TestCase):
    # BEGIN - Additional tests from cython
    def test_no_class_getitem(self):
        # PyPy<7.3.8 raises AttributeError on __class_getitem__
        if hasattr(sys, "pypy_version_info")  and sys.pypy_version_info < (7, 3, 8):
            err = AttributeError
        else:
            err = TypeError
        with self.assertRaises(err):
            UnSupport[int]

    # END - Additional tests from cython

    def test_class_getitem(self):
        Unpack[int, str]
        self.assertEqual(Unpack.para_list[0], (Unpack, (int, str)))
        self.assertEqual(Unpack.para_list[1], {})

    def test_class_getitem_format(self):
        self.assertEqual(Format[int], 'Format[int]')
        self.assertEqual(Format[Format], 'Format[Format]')

    def test_class_getitem_inheritance(self):
        self.assertEqual(ExFormat[int], 'ExFormat[int]')
        self.assertEqual(ExFormat[ExFormat], 'ExFormat[ExFormat]')

    def test_class_getitem_inheritance_2(self):
        self.assertEqual(Covered[int], 'Covered[int]')
        self.assertEqual(Covered[Covered], 'Covered[Covered]')

    def test_class_getitem_classmethod(self):
        self.assertEqual(ExDecorated[int], 'ExDecorated[int]')
        self.assertEqual(ExDecorated[ExDecorated], 'ExDecorated[ExDecorated]')

    def test_class_getitem_errors(self):
        with self.assertRaises(TypeError):
            Invalid1[int]
        with self.assertRaises(TypeError):
            Invalid2[int]

    def test_class_getitem_errors_2(self):
        with self.assertRaises(TypeError):
            Format()[int]
        with self.assertRaises(TypeError):
            Invalid3()[int]
        with self.assertRaises(TypeError):
            Invalid4[int]


if __name__ == '__main__':
    unittest.main()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/test_grammar.py0000644000175100001770000017751000000000000020614 0ustar00runnerdocker00000000000000### COPIED FROM CPython 3.9 - ADDED PART FOLLOWS ###
# cython: language_level=3

import cython
import contextlib
from tempfile import NamedTemporaryFile
from Cython.Compiler.Main import compile as cython_compile, CompileError
from Cython.Build.Inline import cython_inline


@contextlib.contextmanager
def hidden_stderr():
    try:
        from StringIO import StringIO
    except ImportError:
        from io import StringIO

    old_stderr = sys.stderr
    try:
        sys.stderr = StringIO()
        yield
    finally:
        sys.stderr = old_stderr


def _compile(code):
    with NamedTemporaryFile(suffix='.py') as f:
        f.write(code.encode('utf8'))
        f.flush()

        with hidden_stderr():
            result = cython_compile(f.name, language_level=3)
    return result


def check_syntax_error(test, code, msg=None):
    result = _compile(code)
    assert not result.c_file


def check_syntax_warning(test, code, *args):
    # ignore for now
    return _compile(code)


if cython.compiled:
    def compile(code, name, what):
        assert what == 'exec'
        result = _compile(code)
        if not result.c_file:
            raise SyntaxError('unexpected EOF')  # see usage of compile() below

    def exec(code):
        result = _compile(code)
        if not result.c_file:
            raise SyntaxError('unexpected EOF')  # see usage of compile() below

    def eval(code):
        try:
            with hidden_stderr():
                return cython_inline(code)
        except CompileError as exc:
            raise SyntaxError(str(exc))


def use_old_parser():
    return False


import unittest

if not hasattr(unittest, 'skipUnless'):
    def skipUnless(condition, message):
        def decorator(func):
            if condition:
                return func

            def test_method(self):
                print(message)
            return test_method
        return decorator

    unittest.skipUnless = skipUnless

if not hasattr(unittest, 'skip'):
    def skip(message):
        return unittest.skipUnless(False, message)

    unittest.skip = skip

skip = unittest.skip


### END OF CYTHON ADDED PART - COPIED PART FOLLOWS ###

# Python test set -- part 1, grammar.
# This just tests whether the parser accepts them all.

#from test.support import check_syntax_error, check_syntax_warning, use_old_parser
import inspect
import unittest
import sys
import warnings
# testing import *
from sys import *

# different import patterns to check that __annotations__ does not interfere
# with import machinery
#import test.ann_module as ann_module
#import typing
#from collections import ChainMap
#from test import ann_module2
#import test

# These are shared with test_tokenize and other test modules.
#
# Note: since several test cases filter out floats by looking for "e" and ".",
# don't add hexadecimal literals that contain "e" or "E".
VALID_UNDERSCORE_LITERALS = [
    '0_0_0',
    '4_2',
    '1_0000_0000',
    '0b1001_0100',
    '0xffff_ffff',
    '0o5_7_7',
    '1_00_00.5',
    '1_00_00.5e5',
    '1_00_00e5_1',
    '1e1_0',
    '.1_4',
    '.1_4e1',
    '0b_0',
    '0x_f',
    '0o_5',
    '1_00_00j',
    '1_00_00.5j',
    '1_00_00e5_1j',
    '.1_4j',
    '(1_2.5+3_3j)',
    '(.5_6j)',
]
INVALID_UNDERSCORE_LITERALS = [
    # Trailing underscores:
    '0_',
    '42_',
    '1.4j_',
    '0x_',
    '0b1_',
    '0xf_',
    '0o5_',
    '0 if 1_Else 1',
    # Underscores in the base selector:
    '0_b0',
    '0_xf',
    '0_o5',
    # Old-style octal, still disallowed:
    '0_7',
    '09_99',
    # Multiple consecutive underscores:
    '4_______2',
    '0.1__4',
    '0.1__4j',
    '0b1001__0100',
    '0xffff__ffff',
    '0x___',
    '0o5__77',
    '1e1__0',
    '1e1__0j',
    # Underscore right before a dot:
    '1_.4',
    '1_.4j',
    # Underscore right after a dot:
    '1._4',
    '1._4j',
    '._5',
    '._5j',
    # Underscore right after a sign:
    '1.0e+_1',
    '1.0e+_1j',
    # Underscore right before j:
    '1.4_j',
    '1.4e5_j',
    # Underscore right before e:
    '1_e1',
    '1.4_e1',
    '1.4_e1j',
    # Underscore right after e:
    '1e_1',
    '1.4e_1',
    '1.4e_1j',
    # Complex cases with parens:
    '(1+1.5_j_)',
    '(1+1.5_j)',
]


class TokenTests(unittest.TestCase):

    #from test.support import check_syntax_error
    check_syntax_error = check_syntax_error

    def test_backslash(self):
        # Backslash means line continuation:
        x = 1 \
        + 1
        self.assertEqual(x, 2, 'backslash for line continuation')

        # Backslash does not means continuation in comments :\
        x = 0
        self.assertEqual(x, 0, 'backslash ending comment')

    def test_plain_integers(self):
        self.assertEqual(type(000), type(0))
        self.assertEqual(0xff, 255)
        self.assertEqual(0o377, 255)
        self.assertEqual(2147483647, 0o17777777777)
        self.assertEqual(0b1001, 9)
        # "0x" is not a valid literal
        self.assertRaises(SyntaxError, eval, "0x")
        from sys import maxsize
        if maxsize == 2147483647:
            self.assertEqual(-2147483647-1, -0o20000000000)
            # XXX -2147483648
            self.assertTrue(0o37777777777 > 0)
            self.assertTrue(0xffffffff > 0)
            self.assertTrue(0b1111111111111111111111111111111 > 0)
            for s in ('2147483648', '0o40000000000', '0x100000000',
                      '0b10000000000000000000000000000000'):
                try:
                    x = eval(s)
                except OverflowError:
                    self.fail("OverflowError on huge integer literal %r" % s)
        elif maxsize == 9223372036854775807:
            self.assertEqual(-9223372036854775807-1, -0o1000000000000000000000)
            self.assertTrue(0o1777777777777777777777 > 0)
            self.assertTrue(0xffffffffffffffff > 0)
            self.assertTrue(0b11111111111111111111111111111111111111111111111111111111111111 > 0)
            for s in '9223372036854775808', '0o2000000000000000000000', \
                     '0x10000000000000000', \
                     '0b100000000000000000000000000000000000000000000000000000000000000':
                try:
                    x = eval(s)
                except OverflowError:
                    self.fail("OverflowError on huge integer literal %r" % s)
        else:
            self.fail('Weird maxsize value %r' % maxsize)

    def test_long_integers(self):
        x = 0
        x = 0xffffffffffffffff
        x = 0Xffffffffffffffff
        x = 0o77777777777777777
        x = 0O77777777777777777
        x = 123456789012345678901234567890
        x = 0b100000000000000000000000000000000000000000000000000000000000000000000
        x = 0B111111111111111111111111111111111111111111111111111111111111111111111

    def test_floats(self):
        x = 3.14
        x = 314.
        x = 0.314
        # XXX x = 000.314
        x = .314
        x = 3e14
        x = 3E14
        x = 3e-14
        x = 3e+14
        x = 3.e14
        x = .3e14
        x = 3.1e4

    def test_float_exponent_tokenization(self):
        # See issue 21642.
        self.assertEqual(1 if 1else 0, 1)
        self.assertEqual(1 if 0else 0, 0)
        self.assertRaises(SyntaxError, eval, "0 if 1Else 0")

    @skip("Done more efficiently in TestGrammar")
    def test_underscore_literals(self):
        for lit in VALID_UNDERSCORE_LITERALS:
            self.assertEqual(eval(lit), eval(lit.replace('_', '')))
        for lit in INVALID_UNDERSCORE_LITERALS:
            self.assertRaises(SyntaxError, eval, lit)
        # Sanity check: no literal begins with an underscore
        self.assertRaises(NameError, eval, "_0")

    def test_bad_numerical_literals(self):
        check = self.check_syntax_error
        check("0b12", "invalid digit '2' in binary literal")
        check("0b1_2", "invalid digit '2' in binary literal")
        check("0b2", "invalid digit '2' in binary literal")
        check("0b1_", "invalid binary literal")
        check("0b", "invalid binary literal")
        check("0o18", "invalid digit '8' in octal literal")
        check("0o1_8", "invalid digit '8' in octal literal")
        check("0o8", "invalid digit '8' in octal literal")
        check("0o1_", "invalid octal literal")
        check("0o", "invalid octal literal")
        check("0x1_", "invalid hexadecimal literal")
        check("0x", "invalid hexadecimal literal")
        check("1_", "invalid decimal literal")
        # FIXME: not currently a syntax error
        """
        check("012",
              "leading zeros in decimal integer literals are not permitted; "
              "use an 0o prefix for octal integers")
        """
        check("1.2_", "invalid decimal literal")
        check("1e2_", "invalid decimal literal")
        check("1e+", "invalid decimal literal")

    def test_string_literals(self):
        x = ''; y = ""; self.assertTrue(len(x) == 0 and x == y)
        x = '\''; y = "'"; self.assertTrue(len(x) == 1 and x == y and ord(x) == 39)
        x = '"'; y = "\""; self.assertTrue(len(x) == 1 and x == y and ord(x) == 34)
        x = "doesn't \"shrink\" does it"
        y = 'doesn\'t "shrink" does it'
        self.assertTrue(len(x) == 24 and x == y)
        x = "does \"shrink\" doesn't it"
        y = 'does "shrink" doesn\'t it'
        self.assertTrue(len(x) == 24 and x == y)
        x = """
The "quick"
brown fox
jumps over
the 'lazy' dog.
"""
        y = '\nThe "quick"\nbrown fox\njumps over\nthe \'lazy\' dog.\n'
        self.assertEqual(x, y)
        y = '''
The "quick"
brown fox
jumps over
the 'lazy' dog.
'''
        self.assertEqual(x, y)
        y = "\n\
The \"quick\"\n\
brown fox\n\
jumps over\n\
the 'lazy' dog.\n\
"
        self.assertEqual(x, y)
        y = '\n\
The \"quick\"\n\
brown fox\n\
jumps over\n\
the \'lazy\' dog.\n\
'
        self.assertEqual(x, y)

    def test_ellipsis(self):
        x = ...
        self.assertTrue(x is Ellipsis)
        # FIXME: why is this not rejected ???
        #self.assertRaises(SyntaxError, eval, ".. .")

    def test_eof_error(self):
        samples = ("def foo(", "\ndef foo(", "def foo(\n")
        for s in samples:
            with self.assertRaises(SyntaxError) as cm:
                compile(s, "", "exec")
            self.assertIn("unexpected EOF", str(cm.exception))

var_annot_global: int  # a global annotated is necessary for test_var_annot

# custom namespace for testing __annotations__

class CNS:
    def __init__(self):
        self._dct = {}
    def __setitem__(self, item, value):
        self._dct[item.lower()] = value
    def __getitem__(self, item):
        return self._dct[item]


class GrammarTests(unittest.TestCase):

    #from test.support import check_syntax_error, check_syntax_warning
    check_syntax_error, check_syntax_warning = check_syntax_error, check_syntax_warning

    if not hasattr(unittest.TestCase, 'subTest'):
        @contextlib.contextmanager
        def subTest(self, source=None, case=None, **kwargs):
            try:
                yield
            except Exception:
                print(source or case)
                raise

    # single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
    # XXX can't test in a script -- this rule is only used when interactive

    # file_input: (NEWLINE | stmt)* ENDMARKER
    # Being tested as this very moment this very module

    # expr_input: testlist NEWLINE
    # XXX Hard to test -- used only in calls to input()

    def test_eval_input(self):
        # testlist ENDMARKER
        x = eval('1, 0 or 1')

    def test_var_annot_basics(self):
        # all these should be allowed
        var1: int = 5
        var2: [int, str]
        my_lst = [42]
        def one():
            return 1
        int.new_attr: int
        [list][0]: type
        my_lst[one()-1]: int = 5
        self.assertEqual(my_lst, [5])

    @skip("Cython Bug: global vs. local declarations do not currently raise an error")
    def test_var_annot_syntax_errors(self):
        # parser pass
        check_syntax_error(self, "def f: int")
        check_syntax_error(self, "x: int: str")
        check_syntax_error(self, "def f():\n"
                                 "    nonlocal x: int\n")
        # AST pass
        check_syntax_error(self, "[x, 0]: int\n")
        check_syntax_error(self, "f(): int\n")
        check_syntax_error(self, "(x,): int")
        check_syntax_error(self, "def f():\n"
                                 "    (x, y): int = (1, 2)\n")
        # symtable pass
        check_syntax_error(self, "def f():\n"
                                 "    x: int\n"
                                 "    global x\n")
        check_syntax_error(self, "def f():\n"
                                 "    global x\n"
                                 "    x: int\n")

    def test_var_annot_basic_semantics(self):
        # execution order
        with self.assertRaises(ZeroDivisionError):
            no_name[does_not_exist]: no_name_again = 1/0
        with self.assertRaises(NameError):
            no_name[does_not_exist]: 1/0 = 0
        global var_annot_global

        # function semantics
        def f():
            st: str = "Hello"
            a.b: int = (1, 2)
            return st
        self.assertEqual(f.__annotations__, {})
        def f_OK():
            x: 1/0
        f_OK()
        # Compile-time errors in Cython:
        """
        def fbad():
            x: int
            print(x)
        with self.assertRaises(UnboundLocalError):
            fbad()
        def f2bad():
            (no_such_global): int
            print(no_such_global)
        try:
            f2bad()
        except Exception as e:
            self.assertIs(type(e), NameError)
        """

        # class semantics
        class C:
            __foo: int
            s: str = "attr"
            z = 2
            def __init__(self, x):
                self.x: int = x

        self.assertEqual(C.__annotations__, {'_C__foo': 'int', 's': 'str'})
        with self.assertRaises(NameError):
            class CBad:
                no_such_name_defined.attr: int = 0
        with self.assertRaises(NameError):
            class Cbad2(C):
                x: int
                x.y: list = []

    @skip("Not currently supported: https://github.com/cython/cython/issues/3839")
    def test_var_annot_metaclass_semantics(self):
        class CMeta(type):
            @classmethod
            def __prepare__(metacls, name, bases, **kwds):
                return {'__annotations__': CNS()}
        class CC(metaclass=CMeta):
            XX: 'ANNOT'
        self.assertEqual(CC.__annotations__['xx'], 'ANNOT')

    @skip("Depends on external test module")
    def test_var_annot_module_semantics(self):
        with self.assertRaises(AttributeError):
            print(test.__annotations__)
        self.assertEqual(ann_module.__annotations__,
                     {1: 2, 'x': int, 'y': str, 'f': typing.Tuple[int, int]})
        self.assertEqual(ann_module.M.__annotations__,
                              {'123': 123, 'o': type})
        self.assertEqual(ann_module2.__annotations__, {})

    @skip("Depends on external test module")
    def test_var_annot_in_module(self):
        # check that functions fail the same way when executed
        # outside of module where they were defined
        from test.ann_module3 import f_bad_ann, g_bad_ann, D_bad_ann
        with self.assertRaises(NameError):
            f_bad_ann()
        with self.assertRaises(NameError):
            g_bad_ann()
        with self.assertRaises(NameError):
            D_bad_ann(5)

    @skip("Depends on 3-args compiled exec()")
    def test_var_annot_simple_exec(self):
        gns = {}; lns= {}
        exec("'docstring'\n"
             "__annotations__[1] = 2\n"
             "x: int = 5\n", gns, lns)
        self.assertEqual(lns["__annotations__"], {1: 2, 'x': int})
        with self.assertRaises(KeyError):
            gns['__annotations__']

    @skip("Depends on 3-args compiled exec()")
    def test_var_annot_custom_maps(self):
        # tests with custom locals() and __annotations__
        ns = {'__annotations__': CNS()}
        exec('X: int; Z: str = "Z"; (w): complex = 1j', ns)
        self.assertEqual(ns['__annotations__']['x'], int)
        self.assertEqual(ns['__annotations__']['z'], str)
        with self.assertRaises(KeyError):
            ns['__annotations__']['w']
        nonloc_ns = {}
        class CNS2:
            def __init__(self):
                self._dct = {}
            def __setitem__(self, item, value):
                nonlocal nonloc_ns
                self._dct[item] = value
                nonloc_ns[item] = value
            def __getitem__(self, item):
                return self._dct[item]
        exec('x: int = 1', {}, CNS2())
        self.assertEqual(nonloc_ns['__annotations__']['x'], int)

    @skip("Depends on 3-args compiled exec()")
    def test_var_annot_refleak(self):
        # complex case: custom locals plus custom __annotations__
        # this was causing refleak
        cns = CNS()
        nonloc_ns = {'__annotations__': cns}
        class CNS2:
            def __init__(self):
                self._dct = {'__annotations__': cns}
            def __setitem__(self, item, value):
                nonlocal nonloc_ns
                self._dct[item] = value
                nonloc_ns[item] = value
            def __getitem__(self, item):
                return self._dct[item]
        exec('X: str', {}, CNS2())
        self.assertEqual(nonloc_ns['__annotations__']['x'], str)

    @skip("Depends on 3-args compiled exec()")
    def test_var_annot_rhs(self):
        ns = {}
        exec('x: tuple = 1, 2', ns)
        self.assertEqual(ns['x'], (1, 2))
        stmt = ('def f():\n'
                '    x: int = yield')
        exec(stmt, ns)
        self.assertEqual(list(ns['f']()), [None])

        ns = {"a": 1, 'b': (2, 3, 4), "c":5, "Tuple": typing.Tuple}
        exec('x: Tuple[int, ...] = a,*b,c', ns)
        self.assertEqual(ns['x'], (1, 2, 3, 4, 5))

    def test_funcdef(self):
        ### [decorators] 'def' NAME parameters ['->' test] ':' suite
        ### decorator: '@' namedexpr_test NEWLINE
        ### decorators: decorator+
        ### parameters: '(' [typedargslist] ')'
        ### typedargslist: ((tfpdef ['=' test] ',')*
        ###                ('*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef)
        ###                | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
        ### tfpdef: NAME [':' test]
        ### varargslist: ((vfpdef ['=' test] ',')*
        ###              ('*' [vfpdef] (',' vfpdef ['=' test])*  [',' '**' vfpdef] | '**' vfpdef)
        ###              | vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
        ### vfpdef: NAME
        def f1(): pass
        f1()
        f1(*())
        f1(*(), **{})
        def f2(one_argument): pass
        def f3(two, arguments): pass
        self.assertEqual(f2.__code__.co_varnames, ('one_argument',))
        self.assertEqual(f3.__code__.co_varnames, ('two', 'arguments'))
        def a1(one_arg,): pass
        def a2(two, args,): pass
        def v0(*rest): pass
        def v1(a, *rest): pass
        def v2(a, b, *rest): pass

        f1()
        f2(1)
        f2(1,)
        f3(1, 2)
        f3(1, 2,)
        v0()
        v0(1)
        v0(1,)
        v0(1,2)
        v0(1,2,3,4,5,6,7,8,9,0)
        v1(1)
        v1(1,)
        v1(1,2)
        v1(1,2,3)
        v1(1,2,3,4,5,6,7,8,9,0)
        v2(1,2)
        v2(1,2,3)
        v2(1,2,3,4)
        v2(1,2,3,4,5,6,7,8,9,0)

        def d01(a=1): pass
        d01()
        d01(1)
        d01(*(1,))
        d01(*[] or [2])
        d01(*() or (), *{} and (), **() or {})
        d01(**{'a':2})
        d01(**{'a':2} or {})
        def d11(a, b=1): pass
        d11(1)
        d11(1, 2)
        d11(1, **{'b':2})
        def d21(a, b, c=1): pass
        d21(1, 2)
        d21(1, 2, 3)
        d21(*(1, 2, 3))
        d21(1, *(2, 3))
        d21(1, 2, *(3,))
        d21(1, 2, **{'c':3})
        def d02(a=1, b=2): pass
        d02()
        d02(1)
        d02(1, 2)
        d02(*(1, 2))
        d02(1, *(2,))
        d02(1, **{'b':2})
        d02(**{'a': 1, 'b': 2})
        def d12(a, b=1, c=2): pass
        d12(1)
        d12(1, 2)
        d12(1, 2, 3)
        def d22(a, b, c=1, d=2): pass
        d22(1, 2)
        d22(1, 2, 3)
        d22(1, 2, 3, 4)
        def d01v(a=1, *rest): pass
        d01v()
        d01v(1)
        d01v(1, 2)
        d01v(*(1, 2, 3, 4))
        d01v(*(1,))
        d01v(**{'a':2})
        def d11v(a, b=1, *rest): pass
        d11v(1)
        d11v(1, 2)
        d11v(1, 2, 3)
        def d21v(a, b, c=1, *rest): pass
        d21v(1, 2)
        d21v(1, 2, 3)
        d21v(1, 2, 3, 4)
        d21v(*(1, 2, 3, 4))
        d21v(1, 2, **{'c': 3})
        def d02v(a=1, b=2, *rest): pass
        d02v()
        d02v(1)
        d02v(1, 2)
        d02v(1, 2, 3)
        d02v(1, *(2, 3, 4))
        d02v(**{'a': 1, 'b': 2})
        def d12v(a, b=1, c=2, *rest): pass
        d12v(1)
        d12v(1, 2)
        d12v(1, 2, 3)
        d12v(1, 2, 3, 4)
        d12v(*(1, 2, 3, 4))
        d12v(1, 2, *(3, 4, 5))
        d12v(1, *(2,), **{'c': 3})
        def d22v(a, b, c=1, d=2, *rest): pass
        d22v(1, 2)
        d22v(1, 2, 3)
        d22v(1, 2, 3, 4)
        d22v(1, 2, 3, 4, 5)
        d22v(*(1, 2, 3, 4))
        d22v(1, 2, *(3, 4, 5))
        d22v(1, *(2, 3), **{'d': 4})

        # keyword argument type tests
        try:
            str('x', **{b'foo':1 })
        except TypeError:
            pass
        else:
            self.fail('Bytes should not work as keyword argument names')
        # keyword only argument tests
        def pos0key1(*, key): return key
        pos0key1(key=100)
        def pos2key2(p1, p2, *, k1, k2=100): return p1,p2,k1,k2
        pos2key2(1, 2, k1=100)
        pos2key2(1, 2, k1=100, k2=200)
        pos2key2(1, 2, k2=100, k1=200)
        def pos2key2dict(p1, p2, *, k1=100, k2, **kwarg): return p1,p2,k1,k2,kwarg
        pos2key2dict(1,2,k2=100,tokwarg1=100,tokwarg2=200)
        pos2key2dict(1,2,tokwarg1=100,tokwarg2=200, k2=100)

        # FIXME: currently does not raise an error
        #self.assertRaises(SyntaxError, eval, "def f(*): pass")
        #self.assertRaises(SyntaxError, eval, "def f(*,): pass")
        #self.assertRaises(SyntaxError, eval, "def f(*, **kwds): pass")

        # keyword arguments after *arglist
        def f(*args, **kwargs):
            return args, kwargs
        self.assertEqual(f(1, x=2, *[3, 4], y=5), ((1, 3, 4),
                                                    {'x':2, 'y':5}))
        self.assertEqual(f(1, *(2,3), 4), ((1, 2, 3, 4), {}))
        self.assertRaises(SyntaxError, eval, "f(1, x=2, *(3,4), x=5)")
        self.assertEqual(f(**{'eggs':'scrambled', 'spam':'fried'}),
                         ((), {'eggs':'scrambled', 'spam':'fried'}))
        self.assertEqual(f(spam='fried', **{'eggs':'scrambled'}),
                         ((), {'eggs':'scrambled', 'spam':'fried'}))

        # Check ast errors in *args and *kwargs
        check_syntax_error(self, "f(*g(1=2))")
        check_syntax_error(self, "f(**g(1=2))")

        # argument annotation tests
        def f(x) -> list: pass
        self.assertEqual(f.__annotations__, {'return': 'list'})
        def f(x: int): pass
        self.assertEqual(f.__annotations__, {'x': 'int'})
        def f(x: int, /): pass
        self.assertEqual(f.__annotations__, {'x': 'int'})
        def f(x: int = 34, /): pass
        self.assertEqual(f.__annotations__, {'x': 'int'})
        def f(*x: str): pass
        self.assertEqual(f.__annotations__, {'x': 'str'})
        def f(**x: float): pass
        self.assertEqual(f.__annotations__, {'x': 'float'})
        def f(x, y: 1+2): pass
        self.assertEqual(f.__annotations__, {'y': '1 + 2'})
        def f(x, y: 1+2, /): pass
        self.assertEqual(f.__annotations__, {'y': '1 + 2'})
        def f(a, b: 1, c: 2, d): pass
        self.assertEqual(f.__annotations__, {'b': '1', 'c': '2'})
        def f(a, b: 1, /, c: 2, d): pass
        self.assertEqual(f.__annotations__, {'b': '1', 'c': '2'})
        def f(a, b: 1, c: 2, d, e: 3 = 4, f=5, *g: 6): pass
        self.assertEqual(f.__annotations__,
                         {'b': '1', 'c': '2', 'e': '3', 'g': '6'})
        def f(a, b: 1, c: 2, d, e: 3 = 4, f=5, *g: 6, h: 7, i=8, j: 9 = 10,
              **k: 11) -> 12: pass
        self.assertEqual(f.__annotations__,
                         {'b': '1', 'c': '2', 'e': '3', 'g': '6', 'h': '7', 'j': '9',
                          'k': '11', 'return': '12'})
        # FIXME: compile failure on positional-only argument declaration
        """
        def f(a, b: 1, c: 2, d, e: 3 = 4, f: int = 5, /, *g: 6, h: 7, i=8, j: 9 = 10,
              **k: 11) -> 12: pass
        self.assertEqual(f.__annotations__,
                          {'b': 1, 'c': 2, 'e': 3, 'f': int, 'g': 6, 'h': 7, 'j': 9,
                           'k': 11, 'return': 12})
        """
        # Check for issue #20625 -- annotations mangling
        class Spam:
            def f(self, *, __kw: 1):
                pass
        class Ham(Spam): pass
        # FIXME: not currently mangled
        """
        self.assertEqual(Spam.f.__annotations__, {'_Spam__kw': '1'})
        self.assertEqual(Ham.f.__annotations__, {'_Spam__kw': '1'})
        """
        # Check for SF Bug #1697248 - mixing decorators and a return annotation
        def null(x): return x
        @null
        def f(x) -> list: pass
        self.assertEqual(f.__annotations__, {'return': 'list'})

        # Test expressions as decorators (PEP 614):
        @False or null
        def f(x): pass
        @d := null
        def f(x): pass
        @lambda f: null(f)
        def f(x): pass
        @[..., null, ...][1]
        def f(x): pass
        @null(null)(null)
        def f(x): pass
        @[null][0].__call__.__call__
        def f(x): pass

        # test closures with a variety of opargs
        closure = 1
        def f(): return closure
        def f(x=1): return closure
        def f(*, k=1): return closure
        def f() -> int: return closure

        # Check trailing commas are permitted in funcdef argument list
        def f(a,): pass
        def f(*args,): pass
        def f(**kwds,): pass
        def f(a, *args,): pass
        def f(a, **kwds,): pass
        def f(*args, b,): pass
        def f(*, b,): pass
        def f(*args, **kwds,): pass
        def f(a, *args, b,): pass
        def f(a, *, b,): pass
        def f(a, *args, **kwds,): pass
        def f(*args, b, **kwds,): pass
        def f(*, b, **kwds,): pass
        def f(a, *args, b, **kwds,): pass
        def f(a, *, b, **kwds,): pass

    def test_lambdef(self):
        ### lambdef: 'lambda' [varargslist] ':' test
        l1 = lambda : 0
        self.assertEqual(l1(), 0)
        l2 = lambda : a[d]  # XXX just testing the expression
        l3 = lambda : [2 < x for x in [-1, 3, 0]]
        self.assertEqual(l3(), [0, 1, 0])
        l4 = lambda x = lambda y = lambda z=1 : z : y() : x()
        self.assertEqual(l4(), 1)
        l5 = lambda x, y, z=2: x + y + z
        self.assertEqual(l5(1, 2), 5)
        self.assertEqual(l5(1, 2, 3), 6)
        check_syntax_error(self, "lambda x: x = 2")
        check_syntax_error(self, "lambda (None,): None")
        l6 = lambda x, y, *, k=20: x+y+k
        self.assertEqual(l6(1,2), 1+2+20)
        self.assertEqual(l6(1,2,k=10), 1+2+10)

        # check that trailing commas are permitted
        l10 = lambda a,: 0
        l11 = lambda *args,: 0
        l12 = lambda **kwds,: 0
        l13 = lambda a, *args,: 0
        l14 = lambda a, **kwds,: 0
        l15 = lambda *args, b,: 0
        l16 = lambda *, b,: 0
        l17 = lambda *args, **kwds,: 0
        l18 = lambda a, *args, b,: 0
        l19 = lambda a, *, b,: 0
        l20 = lambda a, *args, **kwds,: 0
        l21 = lambda *args, b, **kwds,: 0
        l22 = lambda *, b, **kwds,: 0
        l23 = lambda a, *args, b, **kwds,: 0
        l24 = lambda a, *, b, **kwds,: 0


    ### stmt: simple_stmt | compound_stmt
    # Tested below

    def test_simple_stmt(self):
        ### simple_stmt: small_stmt (';' small_stmt)* [';']
        x = 1; pass; del x
        def foo():
            # verify statements that end with semi-colons
            x = 1; pass; del x;
        foo()

    ### small_stmt: expr_stmt | pass_stmt | del_stmt | flow_stmt | import_stmt | global_stmt | access_stmt
    # Tested below

    def test_expr_stmt(self):
        # (exprlist '=')* exprlist
        1
        1, 2, 3
        x = 1
        x = 1, 2, 3
        x = y = z = 1, 2, 3
        x, y, z = 1, 2, 3
        abc = a, b, c = x, y, z = xyz = 1, 2, (3, 4)

        check_syntax_error(self, "x + 1 = 1")
        check_syntax_error(self, "a + 1 = b + 2")

    # Check the heuristic for print & exec covers significant cases
    # As well as placing some limits on false positives
    def test_former_statements_refer_to_builtins(self):
        keywords = "print", "exec"
        # Cases where we want the custom error
        cases = [
            "{} foo",
            "{} {{1:foo}}",
            "if 1: {} foo",
            "if 1: {} {{1:foo}}",
            "if 1:\n    {} foo",
            "if 1:\n    {} {{1:foo}}",
        ]
        for keyword in keywords:
            custom_msg = "call to '{}'".format(keyword)
            for case in cases:
                source = case.format(keyword)
                with self.subTest(source=source):
                    #with self.assertRaisesRegex(SyntaxError, custom_msg):
                    with self.assertRaises(SyntaxError):
                        exec(source)
                source = source.replace("foo", "(foo.)")
                with self.subTest(source=source):
                    #with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
                    with self.assertRaises(SyntaxError):
                        exec(source)

    def test_del_stmt(self):
        # 'del' exprlist
        abc = [1,2,3]
        x, y, z = abc
        xyz = x, y, z

        del abc
        del x, y, (z, xyz)

        x, y, z = "xyz"
        del x
        del y,
        del (z)
        del ()

        a, b, c, d, e, f, g = "abcdefg"
        del a, (b, c), (d, (e, f))

        a, b, c, d, e, f, g = "abcdefg"
        del a, [b, c], (d, [e, f])

        abcd = list("abcd")
        del abcd[1:2]

        # FIXME: currently fails to compile
        #compile("del a, (b[0].c, (d.e, f.g[1:2])), [h.i.j], ()", "", "exec")

    def test_pass_stmt(self):
        # 'pass'
        pass

    # flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt
    # Tested below

    def test_break_stmt(self):
        # 'break'
        while 1: break

    def test_continue_stmt(self):
        # 'continue'
        i = 1
        while i: i = 0; continue

        msg = ""
        while not msg:
            msg = "ok"
            try:
                continue
                msg = "continue failed to continue inside try"
            except:
                msg = "continue inside try called except block"
        if msg != "ok":
            self.fail(msg)

        msg = ""
        while not msg:
            msg = "finally block not called"
            try:
                continue
            finally:
                msg = "ok"
        if msg != "ok":
            self.fail(msg)

    def test_break_continue_loop(self):
        # This test warrants an explanation. It is a test specifically for SF bugs
        # #463359 and #462937. The bug is that a 'break' statement executed or
        # exception raised inside a try/except inside a loop, *after* a continue
        # statement has been executed in that loop, will cause the wrong number of
        # arguments to be popped off the stack and the instruction pointer reset to
        # a very small number (usually 0.) Because of this, the following test
        # *must* written as a function, and the tracking vars *must* be function
        # arguments with default values. Otherwise, the test will loop and loop.

        def test_inner(extra_burning_oil = 1, count=0):
            big_hippo = 2
            while big_hippo:
                count += 1
                try:
                    if extra_burning_oil and big_hippo == 1:
                        extra_burning_oil -= 1
                        break
                    big_hippo -= 1
                    continue
                except:
                    raise
            if count > 2 or big_hippo != 1:
                self.fail("continue then break in try/except in loop broken!")
        test_inner()

    def test_return(self):
        # 'return' [testlist_star_expr]
        def g1(): return
        def g2(): return 1
        def g3():
            z = [2, 3]
            return 1, *z

        g1()
        x = g2()
        y = g3()
        self.assertEqual(y, (1, 2, 3), "unparenthesized star expr return")
        check_syntax_error(self, "class foo:return 1")

    def test_break_in_finally(self):
        count = 0
        while count < 2:
            count += 1
            try:
                pass
            finally:
                break
        self.assertEqual(count, 1)

        count = 0
        while count < 2:
            count += 1
            try:
                continue
            finally:
                break
        self.assertEqual(count, 1)

        count = 0
        while count < 2:
            count += 1
            try:
                1/0
            finally:
                break
        self.assertEqual(count, 1)

        for count in [0, 1]:
            self.assertEqual(count, 0)
            try:
                pass
            finally:
                break
        self.assertEqual(count, 0)

        for count in [0, 1]:
            self.assertEqual(count, 0)
            try:
                continue
            finally:
                break
        self.assertEqual(count, 0)

        for count in [0, 1]:
            self.assertEqual(count, 0)
            try:
                1/0
            finally:
                break
        self.assertEqual(count, 0)

    def test_continue_in_finally(self):
        count = 0
        while count < 2:
            count += 1
            try:
                pass
            finally:
                continue
            break
        self.assertEqual(count, 2)

        count = 0
        while count < 2:
            count += 1
            try:
                break
            finally:
                continue
        self.assertEqual(count, 2)

        count = 0
        while count < 2:
            count += 1
            try:
                1/0
            finally:
                continue
            break
        self.assertEqual(count, 2)

        for count in [0, 1]:
            try:
                pass
            finally:
                continue
            break
        self.assertEqual(count, 1)

        for count in [0, 1]:
            try:
                break
            finally:
                continue
        self.assertEqual(count, 1)

        for count in [0, 1]:
            try:
                1/0
            finally:
                continue
            break
        self.assertEqual(count, 1)

    def test_return_in_finally(self):
        def g1():
            try:
                pass
            finally:
                return 1
        self.assertEqual(g1(), 1)

        def g2():
            try:
                return 2
            finally:
                return 3
        self.assertEqual(g2(), 3)

        def g3():
            try:
                1/0
            finally:
                return 4
        self.assertEqual(g3(), 4)

    @skip("FIXME: currently crashes because the iterable is cleaned up on 'return', not on loop exit")
    def test_break_in_finally_after_return(self):
        # See issue #37830
        def g1(x):
            for count in [0, 1]:
                count2 = 0
                while count2 < 20:
                    count2 += 10
                    try:
                        return count + count2
                    finally:
                        if x:
                            break
            return 'end', count, count2
        self.assertEqual(g1(False), 10)
        self.assertEqual(g1(True), ('end', 1, 10))

        def g2(x):
            for count in [0, 1]:
                for count2 in [10, 20]:
                    try:
                        return count + count2
                    finally:
                        if x:
                            break
            return 'end', count, count2
        self.assertEqual(g2(False), 10)
        self.assertEqual(g2(True), ('end', 1, 10))

    @skip("FIXME: currently crashes because the iterable is cleaned up on 'return', not on loop exit")
    def test_continue_in_finally_after_return(self):
        # See issue #37830
        def g1(x):
            count = 0
            while count < 100:
                count += 1
                try:
                    return count
                finally:
                    if x:
                        continue
            return 'end', count
        self.assertEqual(g1(False), 1)
        self.assertEqual(g1(True), ('end', 100))

        def g2(x):
            for count in [0, 1]:
                try:
                    return count
                finally:
                    if x:
                        continue
            return 'end', count
        self.assertEqual(g2(False), 0)
        self.assertEqual(g2(True), ('end', 1))

    def test_yield(self):
        # Allowed as standalone statement
        def g(): yield 1
        def g(): yield from ()
        # Allowed as RHS of assignment
        def g(): x = yield 1
        def g(): x = yield from ()
        # Ordinary yield accepts implicit tuples
        def g(): yield 1, 1
        def g(): x = yield 1, 1
        # 'yield from' does not
        check_syntax_error(self, "def g(): yield from (), 1")
        check_syntax_error(self, "def g(): x = yield from (), 1")
        # Requires parentheses as subexpression
        def g(): 1, (yield 1)
        def g(): 1, (yield from ())
        check_syntax_error(self, "def g(): 1, yield 1")
        check_syntax_error(self, "def g(): 1, yield from ()")
        # Requires parentheses as call argument
        def g(): f((yield 1))
        def g(): f((yield 1), 1)
        def g(): f((yield from ()))
        def g(): f((yield from ()), 1)
        # Do not require parenthesis for tuple unpacking
        def g(): rest = 4, 5, 6; yield 1, 2, 3, *rest
        self.assertEqual(list(g()), [(1, 2, 3, 4, 5, 6)])
        check_syntax_error(self, "def g(): f(yield 1)")
        check_syntax_error(self, "def g(): f(yield 1, 1)")
        check_syntax_error(self, "def g(): f(yield from ())")
        check_syntax_error(self, "def g(): f(yield from (), 1)")
        # Not allowed at top level
        check_syntax_error(self, "yield")
        check_syntax_error(self, "yield from")
        # Not allowed at class scope
        check_syntax_error(self, "class foo:yield 1")
        check_syntax_error(self, "class foo:yield from ()")
        # Check annotation refleak on SyntaxError
        #check_syntax_error(self, "def g(a:(yield)): pass")  # no longer a syntax error with PEP-563

    @skip("Not currently a syntax error")
    def test_yield_in_comprehensions(self):
        # Check yield in comprehensions
        def g(): [x for x in [(yield 1)]]
        def g(): [x for x in [(yield from ())]]

        check = self.check_syntax_error
        check("def g(): [(yield x) for x in ()]",
              "'yield' inside list comprehension")
        check("def g(): [x for x in () if not (yield x)]",
              "'yield' inside list comprehension")
        check("def g(): [y for x in () for y in [(yield x)]]",
              "'yield' inside list comprehension")
        check("def g(): {(yield x) for x in ()}",
              "'yield' inside set comprehension")
        check("def g(): {(yield x): x for x in ()}",
              "'yield' inside dict comprehension")
        check("def g(): {x: (yield x) for x in ()}",
              "'yield' inside dict comprehension")
        check("def g(): ((yield x) for x in ())",
              "'yield' inside generator expression")
        check("def g(): [(yield from x) for x in ()]",
              "'yield' inside list comprehension")
        check("class C: [(yield x) for x in ()]",
              "'yield' inside list comprehension")
        check("[(yield x) for x in ()]",
              "'yield' inside list comprehension")

    def test_raise(self):
        # 'raise' test [',' test]
        try: raise RuntimeError('just testing')
        except RuntimeError: pass
        try: raise KeyboardInterrupt
        except KeyboardInterrupt: pass

    def test_import(self):
        # 'import' dotted_as_names
        import sys
        import time, sys
        # 'from' dotted_name 'import' ('*' | '(' import_as_names ')' | import_as_names)
        from time import time
        from time import (time)
        # not testable inside a function, but already done at top of the module
        # from sys import *
        from sys import path, argv
        from sys import (path, argv)
        from sys import (path, argv,)

    def test_global(self):
        # 'global' NAME (',' NAME)*
        global a
        global a, b
        global one, two, three, four, five, six, seven, eight, nine, ten

    def test_nonlocal(self):
        # 'nonlocal' NAME (',' NAME)*
        x = 0
        y = 0
        def f():
            nonlocal x
            nonlocal x, y

    def test_assert(self):
        # assertTruestmt: 'assert' test [',' test]
        assert 1
        assert 1, 1
        assert lambda x:x
        assert 1, lambda x:x+1

        try:
            assert True
        except AssertionError as e:
            self.fail("'assert True' should not have raised an AssertionError")

        try:
            assert True, 'this should always pass'
        except AssertionError as e:
            self.fail("'assert True, msg' should not have "
                      "raised an AssertionError")

    # these tests fail if python is run with -O, so check __debug__
    @unittest.skipUnless(__debug__, "Won't work if __debug__ is False")
    def testAssert2(self):
        try:
            assert 0, "msg"
        except AssertionError as e:
            self.assertEqual(e.args[0], "msg")
        else:
            self.fail("AssertionError not raised by assert 0")

        try:
            assert False
        except AssertionError as e:
            self.assertEqual(len(e.args), 0)
        else:
            self.fail("AssertionError not raised by 'assert False'")

        self.check_syntax_warning('assert(x, "msg")',
                                  'assertion is always true')
        # FIXME: currently fails to compile
        """
        with warnings.catch_warnings():
            warnings.simplefilter('error', SyntaxWarning)
            compile('assert x, "msg"', '', 'exec')
        """


    ### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
    # Tested below

    def test_if(self):
        # 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
        if 1: pass
        if 1: pass
        else: pass
        if 0: pass
        elif 0: pass
        if 0: pass
        elif 0: pass
        elif 0: pass
        elif 0: pass
        else: pass

    def test_while(self):
        # 'while' test ':' suite ['else' ':' suite]
        while 0: pass
        while 0: pass
        else: pass

        # Issue1920: "while 0" is optimized away,
        # ensure that the "else" clause is still present.
        x = 0
        while 0:
            x = 1
        else:
            x = 2
        self.assertEqual(x, 2)

    def test_for(self):
        # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
        for i in 1, 2, 3: pass
        for i, j, k in (): pass
        else: pass
        class Squares:
            def __init__(self, max):
                self.max = max
                self.sofar = []
            def __len__(self): return len(self.sofar)
            def __getitem__(self, i):
                if not 0 <= i < self.max: raise IndexError
                n = len(self.sofar)
                while n <= i:
                    self.sofar.append(n*n)
                    n = n+1
                return self.sofar[i]
        n = 0
        for x in Squares(10): n = n+x
        if n != 285:
            self.fail('for over growing sequence')

        result = []
        for x, in [(1,), (2,), (3,)]:
            result.append(x)
        self.assertEqual(result, [1, 2, 3])

    def test_try(self):
        ### try_stmt: 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite]
        ###         | 'try' ':' suite 'finally' ':' suite
        ### except_clause: 'except' [expr ['as' NAME]]
        try:
            1/0
        except ZeroDivisionError:
            pass
        else:
            pass
        try: 1/0
        except EOFError: pass
        except TypeError as msg: pass
        except: pass
        else: pass
        try: 1/0
        except (EOFError, TypeError, ZeroDivisionError): pass
        try: 1/0
        except (EOFError, TypeError, ZeroDivisionError) as msg: pass
        try: pass
        finally: pass
        with self.assertRaises(SyntaxError):
            compile("try:\n    pass\nexcept Exception as a.b:\n    pass", "?", "exec")
            compile("try:\n    pass\nexcept Exception as a[b]:\n    pass", "?", "exec")

    def test_suite(self):
        # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
        if 1: pass
        if 1:
            pass
        if 1:
            #
            #
            #
            pass
            pass
            #
            pass
            #

    def test_test(self):
        ### and_test ('or' and_test)*
        ### and_test: not_test ('and' not_test)*
        ### not_test: 'not' not_test | comparison
        if not 1: pass
        if 1 and 1: pass
        if 1 or 1: pass
        if not not not 1: pass
        if not 1 and 1 and 1: pass
        if 1 and 1 or 1 and 1 and 1 or not 1 and 1: pass

    def test_comparison(self):
        ### comparison: expr (comp_op expr)*
        ### comp_op: '<'|'>'|'=='|'>='|'<='|'!='|'in'|'not' 'in'|'is'|'is' 'not'
        if 1: pass
        x = (1 == 1)
        if 1 == 1: pass
        if 1 != 1: pass
        if 1 < 1: pass
        if 1 > 1: pass
        if 1 <= 1: pass
        if 1 >= 1: pass
        if x is x: pass
        if x is not x: pass
        if 1 in (): pass
        if 1 not in (): pass
        if 1 < 1 > 1 == 1 >= 1 <= 1 != 1 in 1 not in x is x is not x: pass

    def test_comparison_is_literal(self):
        def check(test, msg='"is" with a literal'):
            self.check_syntax_warning(test, msg)

        check('x is 1')
        check('x is "thing"')
        check('1 is x')
        check('x is y is 1')
        check('x is not 1', '"is not" with a literal')

        # FIXME: this fails to compile
        """
        with warnings.catch_warnings():
            warnings.simplefilter('error', SyntaxWarning)
            compile('x is None', '', 'exec')
            compile('x is False', '', 'exec')
            compile('x is True', '', 'exec')
            compile('x is ...', '', 'exec')
        """

    def test_warn_missed_comma(self):
        # FIXME: would be nice if this could actually raise a compile time warning as well
        def check(test):
            self.check_syntax_warning(test, msg)

        msg=r'is not callable; perhaps you missed a comma\?'
        check('[(1, 2) (3, 4)]')
        check('[(x, y) (3, 4)]')
        check('[[1, 2] (3, 4)]')
        check('[{1, 2} (3, 4)]')
        check('[{1: 2} (3, 4)]')
        check('[[i for i in range(5)] (3, 4)]')
        check('[{i for i in range(5)} (3, 4)]')
        check('[(i for i in range(5)) (3, 4)]')
        check('[{i: i for i in range(5)} (3, 4)]')
        check('[f"{x}" (3, 4)]')
        check('[f"x={x}" (3, 4)]')
        check('["abc" (3, 4)]')
        check('[b"abc" (3, 4)]')
        check('[123 (3, 4)]')
        check('[12.3 (3, 4)]')
        check('[12.3j (3, 4)]')
        check('[None (3, 4)]')
        check('[True (3, 4)]')
        check('[... (3, 4)]')

        msg=r'is not subscriptable; perhaps you missed a comma\?'
        check('[{1, 2} [i, j]]')
        check('[{i for i in range(5)} [i, j]]')
        check('[(i for i in range(5)) [i, j]]')
        check('[(lambda x, y: x) [i, j]]')
        check('[123 [i, j]]')
        check('[12.3 [i, j]]')
        check('[12.3j [i, j]]')
        check('[None [i, j]]')
        check('[True [i, j]]')
        check('[... [i, j]]')

        msg=r'indices must be integers or slices, not tuple; perhaps you missed a comma\?'
        check('[(1, 2) [i, j]]')
        check('[(x, y) [i, j]]')
        check('[[1, 2] [i, j]]')
        check('[[i for i in range(5)] [i, j]]')
        check('[f"{x}" [i, j]]')
        check('[f"x={x}" [i, j]]')
        check('["abc" [i, j]]')
        check('[b"abc" [i, j]]')

        msg=r'indices must be integers or slices, not tuple;'
        check('[[1, 2] [3, 4]]')
        msg=r'indices must be integers or slices, not list;'
        check('[[1, 2] [[3, 4]]]')
        check('[[1, 2] [[i for i in range(5)]]]')
        msg=r'indices must be integers or slices, not set;'
        check('[[1, 2] [{3, 4}]]')
        check('[[1, 2] [{i for i in range(5)}]]')
        msg=r'indices must be integers or slices, not dict;'
        check('[[1, 2] [{3: 4}]]')
        check('[[1, 2] [{i: i for i in range(5)}]]')
        msg=r'indices must be integers or slices, not generator;'
        check('[[1, 2] [(i for i in range(5))]]')
        msg=r'indices must be integers or slices, not function;'
        check('[[1, 2] [(lambda x, y: x)]]')
        msg=r'indices must be integers or slices, not str;'
        check('[[1, 2] [f"{x}"]]')
        check('[[1, 2] [f"x={x}"]]')
        check('[[1, 2] ["abc"]]')
        msg=r'indices must be integers or slices, not'
        check('[[1, 2] [b"abc"]]')
        check('[[1, 2] [12.3]]')
        check('[[1, 2] [12.3j]]')
        check('[[1, 2] [None]]')
        check('[[1, 2] [...]]')

        """
        with warnings.catch_warnings():
            warnings.simplefilter('error', SyntaxWarning)
            compile('[(lambda x, y: x) (3, 4)]', '', 'exec')
            compile('[[1, 2] [i]]', '', 'exec')
            compile('[[1, 2] [0]]', '', 'exec')
            compile('[[1, 2] [True]]', '', 'exec')
            compile('[[1, 2] [1:2]]', '', 'exec')
            compile('[{(1, 2): 3} [i, j]]', '', 'exec')
        """

    def test_binary_mask_ops(self):
        x = 1 & 1
        x = 1 ^ 1
        x = 1 | 1

    def test_shift_ops(self):
        x = 1 << 1
        x = 1 >> 1
        x = 1 << 1 >> 1

    def test_additive_ops(self):
        x = 1
        x = 1 + 1
        x = 1 - 1 - 1
        x = 1 - 1 + 1 - 1 + 1

    def test_multiplicative_ops(self):
        x = 1 * 1
        x = 1 / 1
        x = 1 % 1
        x = 1 / 1 * 1 % 1

    def test_unary_ops(self):
        x = +1
        x = -1
        x = ~1
        x = ~1 ^ 1 & 1 | 1 & 1 ^ -1
        x = -1*1/1 + 1*1 - ---1*1

    def test_selectors(self):
        ### trailer: '(' [testlist] ')' | '[' subscript ']' | '.' NAME
        ### subscript: expr | [expr] ':' [expr]

        import sys, time
        c = sys.path[0]
        x = time.time()
        x = sys.modules['time'].time()
        a = '01234'
        c = a[0]
        c = a[-1]
        s = a[0:5]
        s = a[:5]
        s = a[0:]
        s = a[:]
        s = a[-5:]
        s = a[:-1]
        s = a[-4:-3]
        # A rough test of SF bug 1333982.  http://python.org/sf/1333982
        # The testing here is fairly incomplete.
        # Test cases should include: commas with 1 and 2 colons
        d = {}
        d[1] = 1
        d[1,] = 2
        d[1,2] = 3
        d[1,2,3] = 4
        L = list(d)
        L.sort(key=lambda x: (type(x).__name__, x))
        self.assertEqual(str(L), '[1, (1,), (1, 2), (1, 2, 3)]')

    def test_atoms(self):
        ### atom: '(' [testlist] ')' | '[' [testlist] ']' | '{' [dictsetmaker] '}' | NAME | NUMBER | STRING
        ### dictsetmaker: (test ':' test (',' test ':' test)* [',']) | (test (',' test)* [','])

        x = (1)
        x = (1 or 2 or 3)
        x = (1 or 2 or 3, 2, 3)

        x = []
        x = [1]
        x = [1 or 2 or 3]
        x = [1 or 2 or 3, 2, 3]
        x = []

        x = {}
        x = {'one': 1}
        x = {'one': 1,}
        x = {'one' or 'two': 1 or 2}
        x = {'one': 1, 'two': 2}
        x = {'one': 1, 'two': 2,}
        x = {'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6}

        x = {'one'}
        x = {'one', 1,}
        x = {'one', 'two', 'three'}
        x = {2, 3, 4,}

        x = x
        x = 'x'
        x = 123

    ### exprlist: expr (',' expr)* [',']
    ### testlist: test (',' test)* [',']
    # These have been exercised enough above

    def test_classdef(self):
        # 'class' NAME ['(' [testlist] ')'] ':' suite
        class B: pass
        class B2(): pass
        class C1(B): pass
        class C2(B): pass
        class D(C1, C2, B): pass
        class C:
            def meth1(self): pass
            def meth2(self, arg): pass
            def meth3(self, a1, a2): pass

        # decorator: '@' namedexpr_test NEWLINE
        # decorators: decorator+
        # decorated: decorators (classdef | funcdef)
        def class_decorator(x): return x
        @class_decorator
        class G: pass

        # Test expressions as decorators (PEP 614):
        @False or class_decorator
        class H: pass
        @d := class_decorator
        class I: pass
        @lambda c: class_decorator(c)
        class J: pass
        @[..., class_decorator, ...][1]
        class K: pass
        @class_decorator(class_decorator)(class_decorator)
        class L: pass
        @[class_decorator][0].__call__.__call__
        class M: pass

    def test_dictcomps(self):
        # dictorsetmaker: ( (test ':' test (comp_for |
        #                                   (',' test ':' test)* [','])) |
        #                   (test (comp_for | (',' test)* [','])) )
        nums = [1, 2, 3]
        self.assertEqual({i:i+1 for i in nums}, {1: 2, 2: 3, 3: 4})

    def test_listcomps(self):
        # list comprehension tests
        nums = [1, 2, 3, 4, 5]
        strs = ["Apple", "Banana", "Coconut"]
        spcs = ["  Apple", " Banana ", "Coco  nut  "]

        self.assertEqual([s.strip() for s in spcs], ['Apple', 'Banana', 'Coco  nut'])
        self.assertEqual([3 * x for x in nums], [3, 6, 9, 12, 15])
        self.assertEqual([x for x in nums if x > 2], [3, 4, 5])
        self.assertEqual([(i, s) for i in nums for s in strs],
                         [(1, 'Apple'), (1, 'Banana'), (1, 'Coconut'),
                          (2, 'Apple'), (2, 'Banana'), (2, 'Coconut'),
                          (3, 'Apple'), (3, 'Banana'), (3, 'Coconut'),
                          (4, 'Apple'), (4, 'Banana'), (4, 'Coconut'),
                          (5, 'Apple'), (5, 'Banana'), (5, 'Coconut')])
        self.assertEqual([(i, s) for i in nums for s in [f for f in strs if "n" in f]],
                         [(1, 'Banana'), (1, 'Coconut'), (2, 'Banana'), (2, 'Coconut'),
                          (3, 'Banana'), (3, 'Coconut'), (4, 'Banana'), (4, 'Coconut'),
                          (5, 'Banana'), (5, 'Coconut')])
        self.assertEqual([(lambda a:[a**i for i in range(a+1)])(j) for j in range(5)],
                         [[1], [1, 1], [1, 2, 4], [1, 3, 9, 27], [1, 4, 16, 64, 256]])

        def test_in_func(l):
            return [0 < x < 3 for x in l if x > 2]

        self.assertEqual(test_in_func(nums), [False, False, False])

        def test_nested_front():
            self.assertEqual([[y for y in [x, x + 1]] for x in [1,3,5]],
                             [[1, 2], [3, 4], [5, 6]])

        test_nested_front()

        check_syntax_error(self, "[i, s for i in nums for s in strs]")
        check_syntax_error(self, "[x if y]")

        suppliers = [
          (1, "Boeing"),
          (2, "Ford"),
          (3, "Macdonalds")
        ]

        parts = [
          (10, "Airliner"),
          (20, "Engine"),
          (30, "Cheeseburger")
        ]

        suppart = [
          (1, 10), (1, 20), (2, 20), (3, 30)
        ]

        x = [
          (sname, pname)
            for (sno, sname) in suppliers
              for (pno, pname) in parts
                for (sp_sno, sp_pno) in suppart
                  if sno == sp_sno and pno == sp_pno
        ]

        self.assertEqual(x, [('Boeing', 'Airliner'), ('Boeing', 'Engine'), ('Ford', 'Engine'),
                             ('Macdonalds', 'Cheeseburger')])

    def test_genexps(self):
        # generator expression tests
        g = ([x for x in range(10)] for x in range(1))
        self.assertEqual(next(g), [x for x in range(10)])
        try:
            next(g)
            self.fail('should produce StopIteration exception')
        except StopIteration:
            pass

        a = 1
        try:
            g = (a for d in a)
            next(g)
            self.fail('should produce TypeError')
        except TypeError:
            pass

        self.assertEqual(list((x, y) for x in 'abcd' for y in 'abcd'), [(x, y) for x in 'abcd' for y in 'abcd'])
        self.assertEqual(list((x, y) for x in 'ab' for y in 'xy'), [(x, y) for x in 'ab' for y in 'xy'])

        a = [x for x in range(10)]
        b = (x for x in (y for y in a))
        self.assertEqual(sum(b), sum([x for x in range(10)]))

        self.assertEqual(sum(x**2 for x in range(10)), sum([x**2 for x in range(10)]))
        self.assertEqual(sum(x*x for x in range(10) if x % 2), sum([x*x for x in range(10) if x % 2]))
        self.assertEqual(sum(x for x in (y for y in range(10))), sum([x for x in range(10)]))
        self.assertEqual(sum(x for x in (y for y in (z for z in range(10)))), sum([x for x in range(10)]))
        self.assertEqual(sum(x for x in [y for y in (z for z in range(10))]), sum([x for x in range(10)]))
        self.assertEqual(sum(x for x in (y for y in (z for z in range(10) if True)) if True), sum([x for x in range(10)]))
        self.assertEqual(sum(x for x in (y for y in (z for z in range(10) if True) if False) if True), 0)
        check_syntax_error(self, "foo(x for x in range(10), 100)")
        check_syntax_error(self, "foo(100, x for x in range(10))")

    def test_comprehension_specials(self):
        # test for outmost iterable precomputation
        # FIXME: https://github.com/cython/cython/issues/1159
        """
        x = 10; g = (i for i in range(x)); x = 5
        self.assertEqual(len(list(g)), 10)

        # This should hold, since we're only precomputing outmost iterable.
        x = 10; t = False; g = ((i,j) for i in range(x) if t for j in range(x))
        x = 5; t = True;
        self.assertEqual([(i,j) for i in range(10) for j in range(5)], list(g))
        """

        # Grammar allows multiple adjacent 'if's in listcomps and genexps,
        # even though it's silly. Make sure it works (ifelse broke this.)
        self.assertEqual([ x for x in range(10) if x % 2 if x % 3 ], [1, 5, 7])
        self.assertEqual(list(x for x in range(10) if x % 2 if x % 3), [1, 5, 7])

        # verify unpacking single element tuples in listcomp/genexp.
        self.assertEqual([x for x, in [(4,), (5,), (6,)]], [4, 5, 6])
        self.assertEqual(list(x for x, in [(7,), (8,), (9,)]), [7, 8, 9])

    def test_with_statement(self):
        class manager(object):
            def __enter__(self):
                return (1, 2)
            def __exit__(self, *args):
                pass

        with manager():
            pass
        with manager() as x:
            pass
        with manager() as (x, y):
            pass
        with manager(), manager():
            pass
        with manager() as x, manager() as y:
            pass
        with manager() as x, manager():
            pass

        with (
            manager()
        ):
            pass

        with (
            manager() as x
        ):
            pass

        with (
            manager() as (x, y),
            manager() as z,
        ):
            pass

        with (
            manager(),
            manager()
        ):
            pass

        with (
            manager() as x,
            manager() as y
        ):
            pass

        with (
            manager() as x,
            manager()
        ):
            pass

        with (
            manager() as x,
            manager() as y,
            manager() as z,
        ):
            pass

        with (
            manager() as x,
            manager() as y,
            manager(),
        ):
            pass


    def test_if_else_expr(self):
        # Test ifelse expressions in various cases
        def _checkeval(msg, ret):
            "helper to check that evaluation of expressions is done correctly"
            print(msg)
            return ret

        # the next line is not allowed anymore
        #self.assertEqual([ x() for x in lambda: True, lambda: False if x() ], [True])
        self.assertEqual([ x() for x in (lambda: True, lambda: False) if x() ], [True])
        self.assertEqual([ x(False) for x in (lambda x: False if x else True, lambda x: True if x else False) if x(False) ], [True])
        self.assertEqual((5 if 1 else _checkeval("check 1", 0)), 5)
        self.assertEqual((_checkeval("check 2", 0) if 0 else 5), 5)
        self.assertEqual((5 and 6 if 0 else 1), 1)
        self.assertEqual(((5 and 6) if 0 else 1), 1)
        self.assertEqual((5 and (6 if 1 else 1)), 6)
        self.assertEqual((0 or _checkeval("check 3", 2) if 0 else 3), 3)
        self.assertEqual((1 or _checkeval("check 4", 2) if 1 else _checkeval("check 5", 3)), 1)
        self.assertEqual((0 or 5 if 1 else _checkeval("check 6", 3)), 5)
        self.assertEqual((not 5 if 1 else 1), False)
        self.assertEqual((not 5 if 0 else 1), 1)
        self.assertEqual((6 + 1 if 1 else 2), 7)
        self.assertEqual((6 - 1 if 1 else 2), 5)
        self.assertEqual((6 * 2 if 1 else 4), 12)
        self.assertEqual((6 / 2 if 1 else 3), 3)
        self.assertEqual((6 < 4 if 0 else 2), 2)

    def test_paren_evaluation(self):
        self.assertEqual(16 // (4 // 2), 8)
        self.assertEqual((16 // 4) // 2, 2)
        self.assertEqual(16 // 4 // 2, 2)
        x = 2
        y = 3
        self.assertTrue(False is (x is y))
        self.assertFalse((False is x) is y)
        self.assertFalse(False is x is y)

    def test_matrix_mul(self):
        # This is not intended to be a comprehensive test, rather just to be few
        # samples of the @ operator in test_grammar.py.
        class M:
            def __matmul__(self, o):
                return 4
            def __imatmul__(self, o):
                self.other = o
                return self
        m = M()
        self.assertEqual(m @ m, 4)
        m @= 42
        self.assertEqual(m.other, 42)

    def test_async_await(self):
        async def test():
            def sum():
                pass
            if 1:
                await someobj()

        self.assertEqual(test.__name__, 'test')
        #self.assertTrue(bool(test.__code__.co_flags & inspect.CO_COROUTINE))

        def decorator(func):
            setattr(func, '_marked', True)
            return func

        @decorator
        async def test2():
            return 22
        self.assertTrue(test2._marked)
        self.assertEqual(test2.__name__, 'test2')
        #self.assertTrue(bool(test2.__code__.co_flags & inspect.CO_COROUTINE))

    def test_async_for(self):
        class Done(Exception): pass

        class AIter:
            def __aiter__(self):
                return self
            async def __anext__(self):
                raise StopAsyncIteration

        async def foo():
            async for i in AIter():
                pass
            async for i, j in AIter():
                pass
            async for i in AIter():
                pass
            else:
                pass
            raise Done

        with self.assertRaises(Done):
            foo().send(None)

    def test_async_with(self):
        class Done(Exception): pass

        class manager:
            async def __aenter__(self):
                return (1, 2)
            async def __aexit__(self, *exc):
                return False

        async def foo():
            async with manager():
                pass
            async with manager() as x:
                pass
            async with manager() as (x, y):
                pass
            async with manager(), manager():
                pass
            async with manager() as x, manager() as y:
                pass
            async with manager() as x, manager():
                pass
            raise Done

        with self.assertRaises(Done):
            foo().send(None)


if __name__ == '__main__':
    unittest.main()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/test_named_expressions.py0000644000175100001770000004546300000000000022715 0ustar00runnerdocker00000000000000# mode: run
# tag: pure3.8, no-cpp

# copied from cpython with minimal modifications (mainly exec->cython_inline, and a few exception strings)
# This is not currently run in C++ because all the cython_inline compilations fail for reasons that are unclear
# cython: language_level=3

import unittest
import cython
from Cython.Compiler.Main import CompileError
from Cython.Build.Inline import cython_inline
import re
import sys

if cython.compiled:
    try:
        from StringIO import StringIO
    except ImportError:
        from io import StringIO

    class StdErrHider:
        def __enter__(self):
            self.old_stderr = sys.stderr
            self.new_stderr = StringIO()
            sys.stderr = self.new_stderr

            return self

        def __exit__(self, exc_type, exc_value, traceback):
            sys.stderr = self.old_stderr

        @property
        def stderr_contents(self):
            return self.new_stderr.getvalue()

    def exec(code, globals_=None, locals_=None):
        if locals_ and globals_ and (locals_ is not globals_):
            # a hacky attempt to treat as a class definition
            code = "class Cls:\n" + "\n".join(
                "    " + line for line in code.split("\n"))
        code += "\nreturn globals(), locals()"  # so we can inspect it for changes, overriding the default cython_inline behaviour
        try:
            with StdErrHider() as stderr_handler:
                try:
                    g, l = cython_inline(code, globals=globals_, locals=locals_)
                finally:
                    err_messages = stderr_handler.stderr_contents
            if globals_ is not None:
                # because Cython inline bundles everything into a function some values that
                # we'd expect to be in globals end up in locals. This isn't quite right but is
                # as close as it's possible to get to retrieving the values
                globals_.update(l)
                globals_.update(g)
        except CompileError as exc:
            raised_message = str(exc)
            if raised_message.endswith(".pyx"):
                # unhelpfully Cython sometimes raises a compile error and sometimes just raises the filename
                raised_message = []
                for line in err_messages.split("\n"):
                    # search for the two line number groups (we can't just split by ':' because Windows
                    # filenames contain ':')
                    match = re.match(r"(.+?):\d+:\d+:(.*)", line)
                    # a usable error message with be filename:line:char: message
                    if match and match.group(1).endswith(".pyx"):
                        raised_message.append(match.group(2))
                # output all the errors - we aren't worried about reproducing the exact order CPython
                # emits errors in
                raised_message = "; ".join(raised_message)
            raise SyntaxError(raised_message) from None

if sys.version_info[0] < 3:
    # some monkey patching
    unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp

    class FakeSubTest(object):
        def __init__(self, *args, **kwds):
            pass
        def __enter__(self):
            pass
        def __exit__(self, *args):
            pass
    unittest.TestCase.subTest = FakeSubTest

class NamedExpressionInvalidTest(unittest.TestCase):

    def test_named_expression_invalid_01(self):
        code = """x := 0"""

        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
            exec(code, {}, {})

    def test_named_expression_invalid_02(self):
        code = """x = y := 0"""

        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
            exec(code, {}, {})

    def test_named_expression_invalid_03(self):
        code = """y := f(x)"""

        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
            exec(code, {}, {})

    def test_named_expression_invalid_04(self):
        code = """y0 = y1 := f(x)"""

        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
            exec(code, {}, {})

    def test_named_expression_invalid_06(self):
        code = """((a, b) := (1, 2))"""

        # TODO Cython correctly generates an error but the message could be better
        with self.assertRaisesRegex(SyntaxError, ""):
            exec(code, {}, {})

    def test_named_expression_invalid_07(self):
        code = """def spam(a = b := 42): pass"""

        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
            exec(code, {}, {})

    def test_named_expression_invalid_08(self):
        code = """def spam(a: b := 42 = 5): pass"""

        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
            exec(code, {}, {})

    def test_named_expression_invalid_09(self):
        code = """spam(a=b := 'c')"""

        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
            exec(code, {}, {})

    def test_named_expression_invalid_10(self):
        code = """spam(x = y := f(x))"""

        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
            exec(code, {}, {})

    def test_named_expression_invalid_11(self):
        code = """spam(a=1, b := 2)"""

        with self.assertRaisesRegex(SyntaxError,
            "follow.* keyword arg"):
            exec(code, {}, {})

    def test_named_expression_invalid_12(self):
        code = """spam(a=1, (b := 2))"""

        with self.assertRaisesRegex(SyntaxError,
            "follow.* keyword arg"):
            exec(code, {}, {})

    def test_named_expression_invalid_13(self):
        code = """spam(a=1, (b := 2))"""

        with self.assertRaisesRegex(SyntaxError,
            "follow.* keyword arg"):
            exec(code, {}, {})

    def test_named_expression_invalid_14(self):
        code = """(x := lambda: y := 1)"""

        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
            exec(code, {}, {})

    def test_named_expression_invalid_15(self):
        code = """(lambda: x := 1)"""

        # TODO at the moment the error message is valid, but not the same as Python
        with self.assertRaisesRegex(SyntaxError,
            ""):
            exec(code, {}, {})

    def test_named_expression_invalid_16(self):
        code = "[i + 1 for i in i := [1,2]]"

        # TODO at the moment the error message is valid, but not the same as Python
        with self.assertRaisesRegex(SyntaxError, ""):
            exec(code, {}, {})

    def test_named_expression_invalid_17(self):
        code = "[i := 0, j := 1 for i, j in [(1, 2), (3, 4)]]"

        # TODO at the moment the error message is valid, but not the same as Python
        with self.assertRaisesRegex(SyntaxError, ""):
            exec(code, {}, {})

    def test_named_expression_invalid_in_class_body(self):
        code = """class Foo():
            [(42, 1 + ((( j := i )))) for i in range(5)]
        """

        with self.assertRaisesRegex(SyntaxError,
            "assignment expression within a comprehension cannot be used in a class body"):
            exec(code, {}, {})

    def test_named_expression_invalid_rebinding_comprehension_iteration_variable(self):
        cases = [
            ("Local reuse", 'i', "[i := 0 for i in range(5)]"),
            ("Nested reuse", 'j', "[[(j := 0) for i in range(5)] for j in range(5)]"),
            ("Reuse inner loop target", 'j', "[(j := 0) for i in range(5) for j in range(5)]"),
            ("Unpacking reuse", 'i', "[i := 0 for i, j in [(0, 1)]]"),
            ("Reuse in loop condition", 'i', "[i+1 for i in range(5) if (i := 0)]"),
            ("Unreachable reuse", 'i', "[False or (i:=0) for i in range(5)]"),
            ("Unreachable nested reuse", 'i',
                "[(i, j) for i in range(5) for j in range(5) if True or (i:=10)]"),
        ]
        for case, target, code in cases:
            msg = f"assignment expression cannot rebind comprehension iteration variable '{target}'"
            with self.subTest(case=case):
                with self.assertRaisesRegex(SyntaxError, msg):
                    exec(code, {}, {})

    def test_named_expression_invalid_rebinding_comprehension_inner_loop(self):
        cases = [
            ("Inner reuse", 'j', "[i for i in range(5) if (j := 0) for j in range(5)]"),
            ("Inner unpacking reuse", 'j', "[i for i in range(5) if (j := 0) for j, k in [(0, 1)]]"),
        ]
        for case, target, code in cases:
            msg = f"comprehension inner loop cannot rebind assignment expression target '{target}'"
            with self.subTest(case=case):
                with self.assertRaisesRegex(SyntaxError, msg):
                    exec(code, {}) # Module scope
                with self.assertRaisesRegex(SyntaxError, msg):
                    exec(code, {}, {}) # Class scope
                with self.assertRaisesRegex(SyntaxError, msg):
                    exec(f"lambda: {code}", {}) # Function scope

    def test_named_expression_invalid_comprehension_iterable_expression(self):
        cases = [
            ("Top level", "[i for i in (i := range(5))]"),
            ("Inside tuple", "[i for i in (2, 3, i := range(5))]"),
            ("Inside list", "[i for i in [2, 3, i := range(5)]]"),
            ("Different name", "[i for i in (j := range(5))]"),
            ("Lambda expression", "[i for i in (lambda:(j := range(5)))()]"),
            ("Inner loop", "[i for i in range(5) for j in (i := range(5))]"),
            ("Nested comprehension", "[i for i in [j for j in (k := range(5))]]"),
            ("Nested comprehension condition", "[i for i in [j for j in range(5) if (j := True)]]"),
            ("Nested comprehension body", "[i for i in [(j := True) for j in range(5)]]"),
        ]
        msg = "assignment expression cannot be used in a comprehension iterable expression"
        for case, code in cases:
            with self.subTest(case=case):
                with self.assertRaisesRegex(SyntaxError, msg):
                    exec(code, {}) # Module scope - FIXME this test puts it in __invoke in cython_inline
                with self.assertRaisesRegex(SyntaxError, msg):
                    exec(code, {}, {}) # Class scope
                with self.assertRaisesRegex(SyntaxError, msg):
                    exec(f"lambda: {code}", {}) # Function scope


class NamedExpressionAssignmentTest(unittest.TestCase):

    def test_named_expression_assignment_01(self):
        (a := 10)

        self.assertEqual(a, 10)

    def test_named_expression_assignment_02(self):
        a = 20
        (a := a)

        self.assertEqual(a, 20)

    def test_named_expression_assignment_03(self):
        (total := 1 + 2)

        self.assertEqual(total, 3)

    def test_named_expression_assignment_04(self):
        (info := (1, 2, 3))

        self.assertEqual(info, (1, 2, 3))

    def test_named_expression_assignment_05(self):
        (x := 1, 2)

        self.assertEqual(x, 1)

    def test_named_expression_assignment_06(self):
        (z := (y := (x := 0)))

        self.assertEqual(x, 0)
        self.assertEqual(y, 0)
        self.assertEqual(z, 0)

    def test_named_expression_assignment_07(self):
        (loc := (1, 2))

        self.assertEqual(loc, (1, 2))

    def test_named_expression_assignment_08(self):
        if spam := "eggs":
            self.assertEqual(spam, "eggs")
        else: self.fail("variable was not assigned using named expression")

    def test_named_expression_assignment_09(self):
        if True and (spam := True):
            self.assertTrue(spam)
        else: self.fail("variable was not assigned using named expression")

    def test_named_expression_assignment_10(self):
        if (match := 10) == 10:
            pass
        else: self.fail("variable was not assigned using named expression")

    def test_named_expression_assignment_11(self):
        def spam(a):
            return a
        input_data = [1, 2, 3]
        res = [(x, y, x/y) for x in input_data if (y := spam(x)) > 0]

        self.assertEqual(res, [(1, 1, 1.0), (2, 2, 1.0), (3, 3, 1.0)])

    def test_named_expression_assignment_12(self):
        def spam(a):
            return a
        res = [[y := spam(x), x/y] for x in range(1, 5)]

        self.assertEqual(res, [[1, 1.0], [2, 1.0], [3, 1.0], [4, 1.0]])

    def test_named_expression_assignment_13(self):
        length = len(lines := [1, 2])

        self.assertEqual(length, 2)
        self.assertEqual(lines, [1,2])

    def test_named_expression_assignment_14(self):
        """
        Where all variables are positive integers, and a is at least as large
        as the n'th root of x, this algorithm returns the floor of the n'th
        root of x (and roughly doubling the number of accurate bits per
        iteration):
        """
        a = 9
        n = 2
        x = 3

        while a > (d := x // a**(n-1)):
            a = ((n-1)*a + d) // n

        self.assertEqual(a, 1)

    def test_named_expression_assignment_15(self):
        while a := False:
            pass  # This will not run

        self.assertEqual(a, False)

    def test_named_expression_assignment_16(self):
        a, b = 1, 2
        fib = {(c := a): (a := b) + (b := a + c) - b for __ in range(6)}
        self.assertEqual(fib, {1: 2, 2: 3, 3: 5, 5: 8, 8: 13, 13: 21})


class NamedExpressionScopeTest(unittest.TestCase):

    def test_named_expression_scope_01(self):
        code = """def spam():
    (a := 5)
print(a)"""

        # FIXME for some reason the error message raised is a nonsense filename instead of "undeclared name not builtin"
        # "name .* not"):
        with self.assertRaisesRegex(SyntaxError if cython.compiled else NameError, ""):
            exec(code, {}, {})

    def test_named_expression_scope_02(self):
        total = 0
        partial_sums = [total := total + v for v in range(5)]

        self.assertEqual(partial_sums, [0, 1, 3, 6, 10])
        self.assertEqual(total, 10)

    def test_named_expression_scope_03(self):
        containsOne = any((lastNum := num) == 1 for num in [1, 2, 3])

        self.assertTrue(containsOne)
        self.assertEqual(lastNum, 1)

    def test_named_expression_scope_04(self):
        def spam(a):
            return a
        res = [[y := spam(x), x/y] for x in range(1, 5)]

        self.assertEqual(y, 4)

    def test_named_expression_scope_05(self):
        def spam(a):
            return a
        input_data = [1, 2, 3]
        res = [(x, y, x/y) for x in input_data if (y := spam(x)) > 0]

        self.assertEqual(res, [(1, 1, 1.0), (2, 2, 1.0), (3, 3, 1.0)])
        self.assertEqual(y, 3)

    def test_named_expression_scope_06(self):
        res = [[spam := i for i in range(3)] for j in range(2)]

        self.assertEqual(res, [[0, 1, 2], [0, 1, 2]])
        self.assertEqual(spam, 2)

    def test_named_expression_scope_07(self):
        len(lines := [1, 2])

        self.assertEqual(lines, [1, 2])

    def test_named_expression_scope_08(self):
        def spam(a):
            return a

        def eggs(b):
            return b * 2

        res = [spam(a := eggs(b := h)) for h in range(2)]

        self.assertEqual(res, [0, 2])
        self.assertEqual(a, 2)
        self.assertEqual(b, 1)

    def test_named_expression_scope_09(self):
        def spam(a):
            return a

        def eggs(b):
            return b * 2

        res = [spam(a := eggs(a := h)) for h in range(2)]

        self.assertEqual(res, [0, 2])
        self.assertEqual(a, 2)

    def test_named_expression_scope_10(self):
        res = [b := [a := 1 for i in range(2)] for j in range(2)]

        self.assertEqual(res, [[1, 1], [1, 1]])
        self.assertEqual(a, 1)
        self.assertEqual(b, [1, 1])

    def test_named_expression_scope_11(self):
        res = [j := i for i in range(5)]

        self.assertEqual(res, [0, 1, 2, 3, 4])
        self.assertEqual(j, 4)

    def test_named_expression_scope_17(self):
        b = 0
        res = [b := i + b for i in range(5)]

        self.assertEqual(res, [0, 1, 3, 6, 10])
        self.assertEqual(b, 10)

    def test_named_expression_scope_18(self):
        def spam(a):
            return a

        res = spam(b := 2)

        self.assertEqual(res, 2)
        self.assertEqual(b, 2)

    def test_named_expression_scope_19(self):
        def spam(a):
            return a

        res = spam((b := 2))

        self.assertEqual(res, 2)
        self.assertEqual(b, 2)

    def test_named_expression_scope_20(self):
        def spam(a):
            return a

        res = spam(a=(b := 2))

        self.assertEqual(res, 2)
        self.assertEqual(b, 2)

    def test_named_expression_scope_21(self):
        def spam(a, b):
            return a + b

        res = spam(c := 2, b=1)

        self.assertEqual(res, 3)
        self.assertEqual(c, 2)

    def test_named_expression_scope_22(self):
        def spam(a, b):
            return a + b

        res = spam((c := 2), b=1)

        self.assertEqual(res, 3)
        self.assertEqual(c, 2)

    def test_named_expression_scope_23(self):
        def spam(a, b):
            return a + b

        res = spam(b=(c := 2), a=1)

        self.assertEqual(res, 3)
        self.assertEqual(c, 2)

    def test_named_expression_scope_24(self):
        a = 10
        def spam():
            nonlocal a
            (a := 20)
        spam()

        self.assertEqual(a, 20)

    def test_named_expression_scope_25(self):
        ns = {}
        code = """a = 10
def spam():
    global a
    (a := 20)
spam()"""

        exec(code, ns, {})

        self.assertEqual(ns["a"], 20)

    def test_named_expression_variable_reuse_in_comprehensions(self):
        # The compiler is expected to raise syntax error for comprehension
        # iteration variables, but should be fine with rebinding of other
        # names (e.g. globals, nonlocals, other assignment expressions)

        # The cases are all defined to produce the same expected result
        # Each comprehension is checked at both function scope and module scope
        rebinding = "[x := i for i in range(3) if (x := i) or not x]"
        filter_ref = "[x := i for i in range(3) if x or not x]"
        body_ref = "[x for i in range(3) if (x := i) or not x]"
        nested_ref = "[j for i in range(3) if x or not x for j in range(3) if (x := i)][:-3]"
        cases = [
            ("Rebind global", f"x = 1; result = {rebinding}"),
            ("Rebind nonlocal", f"result, x = (lambda x=1: ({rebinding}, x))()"),
            ("Filter global", f"x = 1; result = {filter_ref}"),
            ("Filter nonlocal", f"result, x = (lambda x=1: ({filter_ref}, x))()"),
            ("Body global", f"x = 1; result = {body_ref}"),
            ("Body nonlocal", f"result, x = (lambda x=1: ({body_ref}, x))()"),
            ("Nested global", f"x = 1; result = {nested_ref}"),
            ("Nested nonlocal", f"result, x = (lambda x=1: ({nested_ref}, x))()"),
        ]
        for case, code in cases:
            with self.subTest(case=case):
                ns = {}
                exec(code, ns)
                self.assertEqual(ns["x"], 2)
                self.assertEqual(ns["result"], [0, 1, 2])

if __name__ == "__main__":
    unittest.main()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/test_raisefrom.pyx0000644000175100001770000000365200000000000021340 0ustar00runnerdocker00000000000000
import sys
import unittest

# adapted from pyregr
class TestCause(unittest.TestCase):
    def test_invalid_cause(self):
        try:
            raise IndexError from 5
        except TypeError as e:
            self.assertTrue("exception cause" in str(e))
        else:
            self.fail("No exception raised")

    def test_raise_from_none_sets_no_cause(self):
        try:
            raise IndexError from None
        except IndexError as e:
            self.assertFalse(e.__cause__)
            if sys.version_info[:2] >= (3,3):
                self.assertTrue(e.__suppress_context__)
        else:
            self.fail("No exception raised")

    def test_raise_from_none_covers_context(self):
        try:
            try:
                raise IndexError("INDEX")
            except IndexError as e:
                raise ValueError("VALUE") from None
            else:
                self.fail("No exception raised")
        except ValueError as e:
            self.assertFalse(e.__cause__)
            self.assertTrue(e.__context__)
            if sys.version_info[:2] >= (3,3):
                self.assertTrue(e.__suppress_context__)

    def test_class_cause(self):
        try:
            raise IndexError from KeyError
        except IndexError as e:
            self.assertTrue(isinstance(e.__cause__, KeyError))
        else:
            self.fail("No exception raised")

    def test_instance_cause(self):
        cause = KeyError()
        try:
            raise IndexError from cause
        except IndexError as e:
            self.assertTrue(e.__cause__ is cause)
        else:
            self.fail("No exception raised")

    def test_erroneous_cause(self):
        class MyException(Exception):
            def __init__(self):
                raise RuntimeError()

        try:
            raise IndexError from MyException
        except RuntimeError:
            pass
        else:
            self.fail("No exception raised")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/test_shadow_error.py0000644000175100001770000000043700000000000021655 0ustar00runnerdocker00000000000000# mode: run
# tag: numpy, gh5411

import pickle
import numpy as np

# This adds e.g
# sys.modules['cython.cimports'] = CythonCImports('cython.cimports')
from Cython import Shadow

# This calls hasattr(CythonCImports, "add")
add = pickle.loads(pickle.dumps(np.add))

assert add is np.add
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/test_subclassinit.py0000644000175100001770000002345000000000000021662 0ustar00runnerdocker00000000000000# mode: run
# tag: pure3.6
# cython: language_level=3str

import sys
HAS_NATIVE_SUPPORT = sys.version_info >= (3, 6)
IS_PY2 = sys.version_info[0] == 2

import re
import types
import unittest

ZERO = 0

skip_if_not_native = unittest.skipIf(not HAS_NATIVE_SUPPORT, "currently requires Python 3.6+")


class Test(unittest.TestCase):
    if not hasattr(unittest.TestCase, 'assertRegex'):
        def assertRegex(self, value, regex):
            self.assertTrue(re.search(regex, str(value)),
                            "'%s' did not match '%s'" % (value, regex))

    if not hasattr(unittest.TestCase, 'assertCountEqual'):
        def assertCountEqual(self, first, second):
            self.assertEqual(set(first), set(second))
            self.assertEqual(len(first), len(second))

    def test_init_subclass(self):
        class A:
            initialized = False

            def __init_subclass__(cls):
                if HAS_NATIVE_SUPPORT:
                    super().__init_subclass__()
                cls.initialized = True

        class B(A):
            pass

        self.assertFalse(A.initialized)
        self.assertTrue(B.initialized)

    def test_init_subclass_dict(self):
        class A(dict):
            initialized = False

            def __init_subclass__(cls):
                if HAS_NATIVE_SUPPORT:
                    super().__init_subclass__()
                cls.initialized = True

        class B(A):
            pass

        self.assertFalse(A.initialized)
        self.assertTrue(B.initialized)

    def test_init_subclass_kwargs(self):
        class A:
            def __init_subclass__(cls, **kwargs):
                cls.kwargs = kwargs

        class B(A, x=3):
            pass

        self.assertEqual(B.kwargs, dict(x=3))

    def test_init_subclass_error(self):
        class A:
            def __init_subclass__(cls):
                raise RuntimeError

        with self.assertRaises(RuntimeError):
            class B(A):
                pass

    def test_init_subclass_wrong(self):
        class A:
            def __init_subclass__(cls, whatever):
                pass

        with self.assertRaises(TypeError):
            class B(A):
                pass

    def test_init_subclass_skipped(self):
        class BaseWithInit:
            def __init_subclass__(cls, **kwargs):
                if HAS_NATIVE_SUPPORT:
                    super().__init_subclass__(**kwargs)
                cls.initialized = cls

        class BaseWithoutInit(BaseWithInit):
            pass

        class A(BaseWithoutInit):
            pass

        self.assertIs(A.initialized, A)
        self.assertIs(BaseWithoutInit.initialized, BaseWithoutInit)

    def test_init_subclass_diamond(self):
        class Base:
            def __init_subclass__(cls, **kwargs):
                if HAS_NATIVE_SUPPORT:
                    super().__init_subclass__(**kwargs)
                cls.calls = []

        class Left(Base):
            pass

        class Middle:
            def __init_subclass__(cls, middle, **kwargs):
                super().__init_subclass__(**kwargs)
                cls.calls += [middle]

        class Right(Base):
            def __init_subclass__(cls, right="right", **kwargs):
                super().__init_subclass__(**kwargs)
                cls.calls += [right]

        class A(Left, Middle, Right, middle="middle"):
            pass

        self.assertEqual(A.calls, ["right", "middle"])
        self.assertEqual(Left.calls, [])
        self.assertEqual(Right.calls, [])

    def test_set_name(self):
        class Descriptor:
            def __set_name__(self, owner, name):
                self.owner = owner
                self.name = name

        class A:
            d = Descriptor()

        self.assertEqual(A.d.name, "d")
        self.assertIs(A.d.owner, A)

    @skip_if_not_native
    def test_set_name_metaclass(self):
        class Meta(type):
            def __new__(cls, name, bases, ns):
                ret = super().__new__(cls, name, bases, ns)
                self.assertEqual(ret.d.name, "d")
                self.assertIs(ret.d.owner, ret)
                return 0

        class Descriptor:
            def __set_name__(self, owner, name):
                self.owner = owner
                self.name = name

        class A(metaclass=Meta):
            d = Descriptor()
        self.assertEqual(A, 0)

    def test_set_name_error(self):
        class Descriptor:
            def __set_name__(self, owner, name):
                1 / ZERO

        with self.assertRaises((RuntimeError, ZeroDivisionError)) as cm:
            class NotGoingToWork:
                attr = Descriptor()

        if sys.version_info >= (3, 12):
            notes = cm.exception.__notes__
            self.assertRegex(str(notes), r'\bNotGoingToWork\b')
            self.assertRegex(str(notes), r'\battr\b')
            self.assertRegex(str(notes), r'\bDescriptor\b')
        else:
            exc = cm.exception
            self.assertRegex(str(exc), r'\bNotGoingToWork\b')
            self.assertRegex(str(exc), r'\battr\b')
            self.assertRegex(str(exc), r'\bDescriptor\b')
            if HAS_NATIVE_SUPPORT:
                self.assertIsInstance(exc.__cause__, ZeroDivisionError)

    def test_set_name_wrong(self):
        class Descriptor:
            def __set_name__(self):
                pass

        with self.assertRaises((RuntimeError, TypeError)) as cm:
            class NotGoingToWork:
                attr = Descriptor()

        if sys.version_info >= (3, 12):
            notes = cm.exception.__notes__
            self.assertRegex(str(notes), r'\bNotGoingToWork\b')
            self.assertRegex(str(notes), r'\battr\b')
            self.assertRegex(str(notes), r'\bDescriptor\b')
        else:
            exc = cm.exception
            self.assertRegex(str(exc), r'\bNotGoingToWork\b')
            self.assertRegex(str(exc), r'\battr\b')
            self.assertRegex(str(exc), r'\bDescriptor\b')
            if HAS_NATIVE_SUPPORT:
                self.assertIsInstance(exc.__cause__, TypeError)

    def test_set_name_lookup(self):
        resolved = []
        class NonDescriptor:
            def __getattr__(self, name):
                resolved.append(name)

        class A:
            d = NonDescriptor()

        self.assertNotIn('__set_name__', resolved,
                         '__set_name__ is looked up in instance dict')

    @skip_if_not_native
    def test_set_name_init_subclass(self):
        class Descriptor:
            def __set_name__(self, owner, name):
                self.owner = owner
                self.name = name

        class Meta(type):
            def __new__(cls, name, bases, ns):
                self = super().__new__(cls, name, bases, ns)
                self.meta_owner = self.owner
                self.meta_name = self.name
                return self

        class A:
            def __init_subclass__(cls):
                cls.owner = cls.d.owner
                cls.name = cls.d.name

        class B(A, metaclass=Meta):
            d = Descriptor()

        self.assertIs(B.owner, B)
        self.assertEqual(B.name, 'd')
        self.assertIs(B.meta_owner, B)
        self.assertEqual(B.name, 'd')

    def test_set_name_modifying_dict(self):
        notified = []
        class Descriptor:
            def __set_name__(self, owner, name):
                setattr(owner, name + 'x', None)
                notified.append(name)

        class A:
            a = Descriptor()
            b = Descriptor()
            c = Descriptor()
            d = Descriptor()
            e = Descriptor()

        self.assertCountEqual(notified, ['a', 'b', 'c', 'd', 'e'])

    def test_errors(self):
        class MyMeta(type):
            pass

        with self.assertRaises(TypeError):
            class MyClass(metaclass=MyMeta, otherarg=1):
                pass

        if not IS_PY2:
            with self.assertRaises(TypeError):
                types.new_class("MyClass", (object,),
                                dict(metaclass=MyMeta, otherarg=1))
            types.prepare_class("MyClass", (object,),
                                dict(metaclass=MyMeta, otherarg=1))

        class MyMeta(type):
            def __init__(self, name, bases, namespace, otherarg):
                super().__init__(name, bases, namespace)

        with self.assertRaises(TypeError):
            class MyClass(metaclass=MyMeta, otherarg=1):
                pass

        class MyMeta(type):
            def __new__(cls, name, bases, namespace, otherarg):
                return super().__new__(cls, name, bases, namespace)

            def __init__(self, name, bases, namespace, otherarg):
                super().__init__(name, bases, namespace)
                self.otherarg = otherarg

        class MyClass(metaclass=MyMeta, otherarg=1):
            pass

        self.assertEqual(MyClass.otherarg, 1)

    @skip_if_not_native
    def test_errors_changed_pep487(self):
        # These tests failed before Python 3.6, PEP 487
        class MyMeta(type):
            def __new__(cls, name, bases, namespace):
                return super().__new__(cls, name=name, bases=bases,
                                       dict=namespace)

        with self.assertRaises(TypeError):
            class MyClass(metaclass=MyMeta):
                pass

        class MyMeta(type):
            def __new__(cls, name, bases, namespace, otherarg):
                self = super().__new__(cls, name, bases, namespace)
                self.otherarg = otherarg
                return self

        class MyClass(metaclass=MyMeta, otherarg=1):
            pass

        self.assertEqual(MyClass.otherarg, 1)

    def test_type(self):
        t = type('NewClass', (object,), {})
        self.assertIsInstance(t, type)
        self.assertEqual(t.__name__, 'NewClass')

        with self.assertRaises(TypeError):
            type(name='NewClass', bases=(object,), dict={})


if __name__ == "__main__":
    unittest.main()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/test_unicode.pyx0000644000175100001770000040515200000000000021000 0ustar00runnerdocker00000000000000# cython: language_level=3

""" Test script for the Unicode implementation.

Written by Marc-Andre Lemburg (mal@lemburg.com).

(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.

"""
#import _string
import codecs
import itertools
import operator
#import struct
#import sys
#import unittest
import warnings
# from test import support, string_tests
from contextlib import contextmanager


class support(object):
    @staticmethod
    def _ignore(func):
        return unittest.skip("Ignoring CPython-only test")(func)

    def run_with_locale(*args):
        return support._ignore

    cpython_only = _ignore

    def check_free_after_iterating(*args):
        pass

    @contextmanager
    def check_warnings(*args):
        yield  # ignore any warnings

support = support()

include "test_unicode_string_tests.pxi"


############### ORIGINAL TESTS START HERE #################


# Error handling (bad decoder return)
def search_function(encoding):
    def decode1(input, errors="strict"):
        return 42 # not a tuple
    def encode1(input, errors="strict"):
        return 42 # not a tuple
    def encode2(input, errors="strict"):
        return (42, 42) # no unicode
    def decode2(input, errors="strict"):
        return (42, 42) # no unicode
    if encoding=="test.unicode1":
        return (encode1, decode1, None, None)
    elif encoding=="test.unicode2":
        return (encode2, decode2, None, None)
    else:
        return None
codecs.register(search_function)

def duplicate_string(text):
    """
    Try to get a fresh clone of the specified text:
    new object with a reference count of 1.

    This is a best-effort: latin1 single letters and the empty
    string ('') are singletons and cannot be cloned.
    """
    return text.encode().decode()

class StrSubclass(str):
    pass

class UnicodeTest(CommonTest,
        MixinStrUnicodeUserStringTest,
        MixinStrUnicodeTest,
        unittest.TestCase):

    type2test = str

    def checkequalnofix(self, result, object, methodname, *args):
        method = getattr(object, methodname)
        realresult = method(*args)
        self.assertEqual(realresult, result)
        self.assertTrue(type(realresult) is type(result))

        # if the original is returned make sure that
        # this doesn't happen with subclasses
        if realresult is object:
            class usub(str):
                def __repr__(self):
                    return 'usub(%r)' % str.__repr__(self)
            object = usub(object)
            method = getattr(object, methodname)
            realresult = method(*args)
            self.assertEqual(realresult, result)
            self.assertTrue(object is not realresult)

    def test_literals(self):
        self.assertEqual('\xff', '\u00ff')
        self.assertEqual('\uffff', '\U0000ffff')
        self.assertRaises(SyntaxError, eval, '\'\\Ufffffffe\'')
        self.assertRaises(SyntaxError, eval, '\'\\Uffffffff\'')
        self.assertRaises(SyntaxError, eval, '\'\\U%08x\'' % 0x110000)
        # raw strings should not have unicode escapes
        self.assertNotEqual(r"\u0020", " ")

    def test_ascii(self):
        if not sys.platform.startswith('java'):
            # Test basic sanity of repr()
            self.assertEqual(ascii('abc'), "'abc'")
            self.assertEqual(ascii('ab\\c'), "'ab\\\\c'")
            self.assertEqual(ascii('ab\\'), "'ab\\\\'")
            self.assertEqual(ascii('\\c'), "'\\\\c'")
            self.assertEqual(ascii('\\'), "'\\\\'")
            self.assertEqual(ascii('\n'), "'\\n'")
            self.assertEqual(ascii('\r'), "'\\r'")
            self.assertEqual(ascii('\t'), "'\\t'")
            self.assertEqual(ascii('\b'), "'\\x08'")
            self.assertEqual(ascii("'\""), """'\\'"'""")
            self.assertEqual(ascii("'\""), """'\\'"'""")
            self.assertEqual(ascii("'"), '''"'"''')
            self.assertEqual(ascii('"'), """'"'""")
            latin1repr = (
                "'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r"
                "\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a"
                "\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123456789:;<=>?@ABCDEFGHI"
                "JKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\\x7f"
                "\\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87\\x88\\x89\\x8a\\x8b\\x8c\\x8d"
                "\\x8e\\x8f\\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97\\x98\\x99\\x9a\\x9b"
                "\\x9c\\x9d\\x9e\\x9f\\xa0\\xa1\\xa2\\xa3\\xa4\\xa5\\xa6\\xa7\\xa8\\xa9"
                "\\xaa\\xab\\xac\\xad\\xae\\xaf\\xb0\\xb1\\xb2\\xb3\\xb4\\xb5\\xb6\\xb7"
                "\\xb8\\xb9\\xba\\xbb\\xbc\\xbd\\xbe\\xbf\\xc0\\xc1\\xc2\\xc3\\xc4\\xc5"
                "\\xc6\\xc7\\xc8\\xc9\\xca\\xcb\\xcc\\xcd\\xce\\xcf\\xd0\\xd1\\xd2\\xd3"
                "\\xd4\\xd5\\xd6\\xd7\\xd8\\xd9\\xda\\xdb\\xdc\\xdd\\xde\\xdf\\xe0\\xe1"
                "\\xe2\\xe3\\xe4\\xe5\\xe6\\xe7\\xe8\\xe9\\xea\\xeb\\xec\\xed\\xee\\xef"
                "\\xf0\\xf1\\xf2\\xf3\\xf4\\xf5\\xf6\\xf7\\xf8\\xf9\\xfa\\xfb\\xfc\\xfd"
                "\\xfe\\xff'")
            testrepr = ascii(''.join(map(chr, range(256))))
            self.assertEqual(testrepr, latin1repr)
            # Test ascii works on wide unicode escapes without overflow.
            self.assertEqual(ascii("\U00010000" * 39 + "\uffff" * 4096),
                             ascii("\U00010000" * 39 + "\uffff" * 4096))

            class WrongRepr:
                def __repr__(self):
                    return b'byte-repr'
            self.assertRaises(TypeError, ascii, WrongRepr())

    def test_repr(self):
        if not sys.platform.startswith('java'):
            # Test basic sanity of repr()
            self.assertEqual(repr('abc'), "'abc'")
            self.assertEqual(repr('ab\\c'), "'ab\\\\c'")
            self.assertEqual(repr('ab\\'), "'ab\\\\'")
            self.assertEqual(repr('\\c'), "'\\\\c'")
            self.assertEqual(repr('\\'), "'\\\\'")
            self.assertEqual(repr('\n'), "'\\n'")
            self.assertEqual(repr('\r'), "'\\r'")
            self.assertEqual(repr('\t'), "'\\t'")
            self.assertEqual(repr('\b'), "'\\x08'")
            self.assertEqual(repr("'\""), """'\\'"'""")
            self.assertEqual(repr("'\""), """'\\'"'""")
            self.assertEqual(repr("'"), '''"'"''')
            self.assertEqual(repr('"'), """'"'""")
            latin1repr = (
                "'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r"
                "\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a"
                "\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123456789:;<=>?@ABCDEFGHI"
                "JKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\\x7f"
                "\\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87\\x88\\x89\\x8a\\x8b\\x8c\\x8d"
                "\\x8e\\x8f\\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97\\x98\\x99\\x9a\\x9b"
                "\\x9c\\x9d\\x9e\\x9f\\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9"
                "\xaa\xab\xac\\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
                "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5"
                "\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3"
                "\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1"
                "\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"
                "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd"
                "\xfe\xff'")
            testrepr = repr(''.join(map(chr, range(256))))
            self.assertEqual(testrepr, latin1repr)
            # Test repr works on wide unicode escapes without overflow.
            self.assertEqual(repr("\U00010000" * 39 + "\uffff" * 4096),
                             repr("\U00010000" * 39 + "\uffff" * 4096))

            class WrongRepr:
                def __repr__(self):
                    return b'byte-repr'
            self.assertRaises(TypeError, repr, WrongRepr())

    def test_iterators(self):
        # Make sure unicode objects have an __iter__ method
        it = "\u1111\u2222\u3333".__iter__()
        self.assertEqual(next(it), "\u1111")
        self.assertEqual(next(it), "\u2222")
        self.assertEqual(next(it), "\u3333")
        self.assertRaises(StopIteration, next, it)

    def test_count(self):
        CommonTest.test_count(self)
        # check mixed argument types
        self.checkequalnofix(3,  'aaa', 'count', 'a')
        self.checkequalnofix(0,  'aaa', 'count', 'b')
        self.checkequalnofix(3, 'aaa', 'count',  'a')
        self.checkequalnofix(0, 'aaa', 'count',  'b')
        self.checkequalnofix(0, 'aaa', 'count',  'b')
        self.checkequalnofix(1, 'aaa', 'count',  'a', -1)
        self.checkequalnofix(3, 'aaa', 'count',  'a', -10)
        self.checkequalnofix(2, 'aaa', 'count',  'a', 0, -1)
        self.checkequalnofix(0, 'aaa', 'count',  'a', 0, -10)
        # test mixed kinds
        self.checkequal(10, '\u0102' + 'a' * 10, 'count', 'a')
        self.checkequal(10, '\U00100304' + 'a' * 10, 'count', 'a')
        self.checkequal(10, '\U00100304' + '\u0102' * 10, 'count', '\u0102')
        self.checkequal(0, 'a' * 10, 'count', '\u0102')
        self.checkequal(0, 'a' * 10, 'count', '\U00100304')
        self.checkequal(0, '\u0102' * 10, 'count', '\U00100304')
        self.checkequal(10, '\u0102' + 'a_' * 10, 'count', 'a_')
        self.checkequal(10, '\U00100304' + 'a_' * 10, 'count', 'a_')
        self.checkequal(10, '\U00100304' + '\u0102_' * 10, 'count', '\u0102_')
        self.checkequal(0, 'a' * 10, 'count', 'a\u0102')
        self.checkequal(0, 'a' * 10, 'count', 'a\U00100304')
        self.checkequal(0, '\u0102' * 10, 'count', '\u0102\U00100304')

    def test_find(self):
        CommonTest.test_find(self)
        # test implementation details of the memchr fast path
        self.checkequal(100, 'a' * 100 + '\u0102', 'find', '\u0102')
        self.checkequal(-1, 'a' * 100 + '\u0102', 'find', '\u0201')
        self.checkequal(-1, 'a' * 100 + '\u0102', 'find', '\u0120')
        self.checkequal(-1, 'a' * 100 + '\u0102', 'find', '\u0220')
        self.checkequal(100, 'a' * 100 + '\U00100304', 'find', '\U00100304')
        self.checkequal(-1, 'a' * 100 + '\U00100304', 'find', '\U00100204')
        self.checkequal(-1, 'a' * 100 + '\U00100304', 'find', '\U00102004')
        # check mixed argument types
        self.checkequalnofix(0,  'abcdefghiabc', 'find', 'abc')
        self.checkequalnofix(9,  'abcdefghiabc', 'find', 'abc', 1)
        self.checkequalnofix(-1, 'abcdefghiabc', 'find', 'def', 4)

        self.assertRaises(TypeError, 'hello'.find)
        self.assertRaises(TypeError, 'hello'.find, 42)
        # test mixed kinds
        self.checkequal(100, '\u0102' * 100 + 'a', 'find', 'a')
        self.checkequal(100, '\U00100304' * 100 + 'a', 'find', 'a')
        self.checkequal(100, '\U00100304' * 100 + '\u0102', 'find', '\u0102')
        self.checkequal(-1, 'a' * 100, 'find', '\u0102')
        self.checkequal(-1, 'a' * 100, 'find', '\U00100304')
        self.checkequal(-1, '\u0102' * 100, 'find', '\U00100304')
        self.checkequal(100, '\u0102' * 100 + 'a_', 'find', 'a_')
        self.checkequal(100, '\U00100304' * 100 + 'a_', 'find', 'a_')
        self.checkequal(100, '\U00100304' * 100 + '\u0102_', 'find', '\u0102_')
        self.checkequal(-1, 'a' * 100, 'find', 'a\u0102')
        self.checkequal(-1, 'a' * 100, 'find', 'a\U00100304')
        self.checkequal(-1, '\u0102' * 100, 'find', '\u0102\U00100304')

    def test_rfind(self):
        CommonTest.test_rfind(self)
        # test implementation details of the memrchr fast path
        self.checkequal(0, '\u0102' + 'a' * 100 , 'rfind', '\u0102')
        self.checkequal(-1, '\u0102' + 'a' * 100 , 'rfind', '\u0201')
        self.checkequal(-1, '\u0102' + 'a' * 100 , 'rfind', '\u0120')
        self.checkequal(-1, '\u0102' + 'a' * 100 , 'rfind', '\u0220')
        self.checkequal(0, '\U00100304' + 'a' * 100, 'rfind', '\U00100304')
        self.checkequal(-1, '\U00100304' + 'a' * 100, 'rfind', '\U00100204')
        self.checkequal(-1, '\U00100304' + 'a' * 100, 'rfind', '\U00102004')
        # check mixed argument types
        self.checkequalnofix(9,   'abcdefghiabc', 'rfind', 'abc')
        self.checkequalnofix(12,  'abcdefghiabc', 'rfind', '')
        self.checkequalnofix(12, 'abcdefghiabc', 'rfind',  '')
        # test mixed kinds
        self.checkequal(0, 'a' + '\u0102' * 100, 'rfind', 'a')
        self.checkequal(0, 'a' + '\U00100304' * 100, 'rfind', 'a')
        self.checkequal(0, '\u0102' + '\U00100304' * 100, 'rfind', '\u0102')
        self.checkequal(-1, 'a' * 100, 'rfind', '\u0102')
        self.checkequal(-1, 'a' * 100, 'rfind', '\U00100304')
        self.checkequal(-1, '\u0102' * 100, 'rfind', '\U00100304')
        self.checkequal(0, '_a' + '\u0102' * 100, 'rfind', '_a')
        self.checkequal(0, '_a' + '\U00100304' * 100, 'rfind', '_a')
        self.checkequal(0, '_\u0102' + '\U00100304' * 100, 'rfind', '_\u0102')
        self.checkequal(-1, 'a' * 100, 'rfind', '\u0102a')
        self.checkequal(-1, 'a' * 100, 'rfind', '\U00100304a')
        self.checkequal(-1, '\u0102' * 100, 'rfind', '\U00100304\u0102')

    def test_index(self):
        CommonTest.test_index(self)
        self.checkequalnofix(0, 'abcdefghiabc', 'index',  '')
        self.checkequalnofix(3, 'abcdefghiabc', 'index',  'def')
        self.checkequalnofix(0, 'abcdefghiabc', 'index',  'abc')
        self.checkequalnofix(9, 'abcdefghiabc', 'index',  'abc', 1)
        self.assertRaises(ValueError, 'abcdefghiabc'.index, 'hib')
        self.assertRaises(ValueError, 'abcdefghiab'.index,  'abc', 1)
        self.assertRaises(ValueError, 'abcdefghi'.index,  'ghi', 8)
        self.assertRaises(ValueError, 'abcdefghi'.index,  'ghi', -1)
        # test mixed kinds
        self.checkequal(100, '\u0102' * 100 + 'a', 'index', 'a')
        self.checkequal(100, '\U00100304' * 100 + 'a', 'index', 'a')
        self.checkequal(100, '\U00100304' * 100 + '\u0102', 'index', '\u0102')
        self.assertRaises(ValueError, ('a' * 100).index, '\u0102')
        self.assertRaises(ValueError, ('a' * 100).index, '\U00100304')
        self.assertRaises(ValueError, ('\u0102' * 100).index, '\U00100304')
        self.checkequal(100, '\u0102' * 100 + 'a_', 'index', 'a_')
        self.checkequal(100, '\U00100304' * 100 + 'a_', 'index', 'a_')
        self.checkequal(100, '\U00100304' * 100 + '\u0102_', 'index', '\u0102_')
        self.assertRaises(ValueError, ('a' * 100).index, 'a\u0102')
        self.assertRaises(ValueError, ('a' * 100).index, 'a\U00100304')
        self.assertRaises(ValueError, ('\u0102' * 100).index, '\u0102\U00100304')

    def test_rindex(self):
        CommonTest.test_rindex(self)
        self.checkequalnofix(12, 'abcdefghiabc', 'rindex',  '')
        self.checkequalnofix(3,  'abcdefghiabc', 'rindex',  'def')
        self.checkequalnofix(9,  'abcdefghiabc', 'rindex',  'abc')
        self.checkequalnofix(0,  'abcdefghiabc', 'rindex',  'abc', 0, -1)

        self.assertRaises(ValueError, 'abcdefghiabc'.rindex,  'hib')
        self.assertRaises(ValueError, 'defghiabc'.rindex,  'def', 1)
        self.assertRaises(ValueError, 'defghiabc'.rindex,  'abc', 0, -1)
        self.assertRaises(ValueError, 'abcdefghi'.rindex,  'ghi', 0, 8)
        self.assertRaises(ValueError, 'abcdefghi'.rindex,  'ghi', 0, -1)
        # test mixed kinds
        self.checkequal(0, 'a' + '\u0102' * 100, 'rindex', 'a')
        self.checkequal(0, 'a' + '\U00100304' * 100, 'rindex', 'a')
        self.checkequal(0, '\u0102' + '\U00100304' * 100, 'rindex', '\u0102')
        self.assertRaises(ValueError, ('a' * 100).rindex, '\u0102')
        self.assertRaises(ValueError, ('a' * 100).rindex, '\U00100304')
        self.assertRaises(ValueError, ('\u0102' * 100).rindex, '\U00100304')
        self.checkequal(0, '_a' + '\u0102' * 100, 'rindex', '_a')
        self.checkequal(0, '_a' + '\U00100304' * 100, 'rindex', '_a')
        self.checkequal(0, '_\u0102' + '\U00100304' * 100, 'rindex', '_\u0102')
        self.assertRaises(ValueError, ('a' * 100).rindex, '\u0102a')
        self.assertRaises(ValueError, ('a' * 100).rindex, '\U00100304a')
        self.assertRaises(ValueError, ('\u0102' * 100).rindex, '\U00100304\u0102')

    @unittest.skipIf(sys.version_info < (3, 6), 'Python str.translate() test requires Py3.6+')
    def test_maketrans_translate(self):
        # these work with plain translate()
        self.checkequalnofix('bbbc', 'abababc', 'translate',
                             {ord('a'): None})
        self.checkequalnofix('iiic', 'abababc', 'translate',
                             {ord('a'): None, ord('b'): ord('i')})
        self.checkequalnofix('iiix', 'abababc', 'translate',
                             {ord('a'): None, ord('b'): ord('i'), ord('c'): 'x'})
        self.checkequalnofix('c', 'abababc', 'translate',
                             {ord('a'): None, ord('b'): ''})
        self.checkequalnofix('xyyx', 'xzx', 'translate',
                             {ord('z'): 'yy'})

        # this needs maketrans()
        self.checkequalnofix('abababc', 'abababc', 'translate',
                             {'b': ''})
        tbl = self.type2test.maketrans({'a': None, 'b': ''})
        self.checkequalnofix('c', 'abababc', 'translate', tbl)
        # test alternative way of calling maketrans()
        tbl = self.type2test.maketrans('abc', 'xyz', 'd')
        self.checkequalnofix('xyzzy', 'abdcdcbdddd', 'translate', tbl)

        # various tests switching from ASCII to latin1 or the opposite;
        # same length, remove a letter, or replace with a longer string.
        self.assertEqual("[a]".translate(str.maketrans('a', 'X')),
                         "[X]")
        self.assertEqual("[a]".translate(str.maketrans({'a': 'X'})),
                         "[X]")
        self.assertEqual("[a]".translate(str.maketrans({'a': None})),
                         "[]")
        self.assertEqual("[a]".translate(str.maketrans({'a': 'XXX'})),
                         "[XXX]")
        self.assertEqual("[a]".translate(str.maketrans({'a': '\xe9'})),
                         "[\xe9]")
        self.assertEqual('axb'.translate(str.maketrans({'a': None, 'b': '123'})),
                         "x123")
        self.assertEqual('axb'.translate(str.maketrans({'a': None, 'b': '\xe9'})),
                         "x\xe9")

        # test non-ASCII (don't take the fast-path)
        self.assertEqual("[a]".translate(str.maketrans({'a': '<\xe9>'})),
                         "[<\xe9>]")
        self.assertEqual("[\xe9]".translate(str.maketrans({'\xe9': 'a'})),
                         "[a]")
        self.assertEqual("[\xe9]".translate(str.maketrans({'\xe9': None})),
                         "[]")
        self.assertEqual("[\xe9]".translate(str.maketrans({'\xe9': '123'})),
                         "[123]")
        self.assertEqual("[a\xe9]".translate(str.maketrans({'a': '<\u20ac>'})),
                         "[<\u20ac>\xe9]")

        # invalid Unicode characters
        invalid_char = 0x10ffff+1
        for before in "a\xe9\u20ac\U0010ffff":
            mapping = str.maketrans({before: invalid_char})
            text = "[%s]" % before
            self.assertRaises(ValueError, text.translate, mapping)

        # errors
        self.assertRaises(TypeError, self.type2test.maketrans)
        self.assertRaises(ValueError, self.type2test.maketrans, 'abc', 'defg')
        self.assertRaises(TypeError, self.type2test.maketrans, 2, 'def')
        self.assertRaises(TypeError, self.type2test.maketrans, 'abc', 2)
        self.assertRaises(TypeError, self.type2test.maketrans, 'abc', 'def', 2)
        self.assertRaises(ValueError, self.type2test.maketrans, {'xy': 2})
        self.assertRaises(TypeError, self.type2test.maketrans, {(1,): 2})

        self.assertRaises(TypeError, 'hello'.translate)
        self.assertRaises(TypeError, 'abababc'.translate, 'abc', 'xyz')

    def test_split(self):
        CommonTest.test_split(self)

        # test mixed kinds
        for left, right in ('ba', '\u0101\u0100', '\U00010301\U00010300'):
            left *= 9
            right *= 9
            for delim in ('c', '\u0102', '\U00010302'):
                self.checkequal([left + right],
                                left + right, 'split', delim)
                self.checkequal([left, right],
                                left + delim + right, 'split', delim)
                self.checkequal([left + right],
                                left + right, 'split', delim * 2)
                self.checkequal([left, right],
                                left + delim * 2 + right, 'split', delim *2)

    def test_rsplit(self):
        CommonTest.test_rsplit(self)
        # test mixed kinds
        for left, right in ('ba', '\u0101\u0100', '\U00010301\U00010300'):
            left *= 9
            right *= 9
            for delim in ('c', '\u0102', '\U00010302'):
                self.checkequal([left + right],
                                left + right, 'rsplit', delim)
                self.checkequal([left, right],
                                left + delim + right, 'rsplit', delim)
                self.checkequal([left + right],
                                left + right, 'rsplit', delim * 2)
                self.checkequal([left, right],
                                left + delim * 2 + right, 'rsplit', delim *2)

    def test_partition(self):
        MixinStrUnicodeUserStringTest.test_partition(self)
        # test mixed kinds
        self.checkequal(('ABCDEFGH', '', ''), 'ABCDEFGH', 'partition', '\u4200')
        for left, right in ('ba', '\u0101\u0100', '\U00010301\U00010300'):
            left *= 9
            right *= 9
            for delim in ('c', '\u0102', '\U00010302'):
                self.checkequal((left + right, '', ''),
                                left + right, 'partition', delim)
                self.checkequal((left, delim, right),
                                left + delim + right, 'partition', delim)
                self.checkequal((left + right, '', ''),
                                left + right, 'partition', delim * 2)
                self.checkequal((left, delim * 2, right),
                                left + delim * 2 + right, 'partition', delim * 2)

    def test_rpartition(self):
        MixinStrUnicodeUserStringTest.test_rpartition(self)
        # test mixed kinds
        self.checkequal(('', '', 'ABCDEFGH'), 'ABCDEFGH', 'rpartition', '\u4200')
        for left, right in ('ba', '\u0101\u0100', '\U00010301\U00010300'):
            left *= 9
            right *= 9
            for delim in ('c', '\u0102', '\U00010302'):
                self.checkequal(('', '', left + right),
                                left + right, 'rpartition', delim)
                self.checkequal((left, delim, right),
                                left + delim + right, 'rpartition', delim)
                self.checkequal(('', '', left + right),
                                left + right, 'rpartition', delim * 2)
                self.checkequal((left, delim * 2, right),
                                left + delim * 2 + right, 'rpartition', delim * 2)

    def test_join(self):
        MixinStrUnicodeUserStringTest.test_join(self)

        class MyWrapper:
            def __init__(self, sval): self.sval = sval
            def __str__(self): return self.sval

        # mixed arguments
        self.checkequalnofix('a b c d', ' ', 'join', ['a', 'b', 'c', 'd'])
        self.checkequalnofix('abcd', '', 'join', ('a', 'b', 'c', 'd'))
        self.checkequalnofix('w x y z', ' ', 'join', Sequence('wxyz'))
        self.checkequalnofix('a b c d', ' ', 'join', ['a', 'b', 'c', 'd'])
        self.checkequalnofix('a b c d', ' ', 'join', ['a', 'b', 'c', 'd'])
        self.checkequalnofix('abcd', '', 'join', ('a', 'b', 'c', 'd'))
        self.checkequalnofix('w x y z', ' ', 'join', Sequence('wxyz'))
        self.checkraises(TypeError, ' ', 'join', ['1', '2', MyWrapper('foo')])
        self.checkraises(TypeError, ' ', 'join', ['1', '2', '3', bytes()])
        self.checkraises(TypeError, ' ', 'join', [1, 2, 3])
        self.checkraises(TypeError, ' ', 'join', ['1', '2', 3])

    @unittest.skipIf(sys.maxsize > 2**32,
        'needs too much memory on a 64-bit platform')
    def test_join_overflow(self):
        size = int(sys.maxsize**0.5) + 1
        seq = ('A' * size,) * size
        self.assertRaises(OverflowError, ''.join, seq)

    def test_replace(self):
        CommonTest.test_replace(self)

        # method call forwarded from str implementation because of unicode argument
        self.checkequalnofix('one@two!three!', 'one!two!three!', 'replace', '!', '@', 1)
        self.assertRaises(TypeError, 'replace'.replace, "r", 42)
        # test mixed kinds
        for left, right in ('ba', '\u0101\u0100', '\U00010301\U00010300'):
            left *= 9
            right *= 9
            for delim in ('c', '\u0102', '\U00010302'):
                for repl in ('d', '\u0103', '\U00010303'):
                    self.checkequal(left + right,
                                    left + right, 'replace', delim, repl)
                    self.checkequal(left + repl + right,
                                    left + delim + right,
                                    'replace', delim, repl)
                    self.checkequal(left + right,
                                    left + right, 'replace', delim * 2, repl)
                    self.checkequal(left + repl + right,
                                    left + delim * 2 + right,
                                    'replace', delim * 2, repl)

    @support.cpython_only
    def test_replace_id(self):
        pattern = 'abc'
        text = 'abc def'
        self.assertIs(text.replace(pattern, pattern), text)

    def test_bytes_comparison(self):
        with support.check_warnings():
            warnings.simplefilter('ignore', BytesWarning)
            self.assertEqual('abc' == b'abc', False)
            self.assertEqual('abc' != b'abc', True)
            self.assertEqual('abc' == bytearray(b'abc'), False)
            self.assertEqual('abc' != bytearray(b'abc'), True)

    def test_comparison(self):
        # Comparisons:
        self.assertEqual('abc', 'abc')
        self.assertTrue('abcd' > 'abc')
        self.assertTrue('abc' < 'abcd')

        if 0:
            # Move these tests to a Unicode collation module test...
            # Testing UTF-16 code point order comparisons...

            # No surrogates, no fixup required.
            self.assertTrue('\u0061' < '\u20ac')
            # Non surrogate below surrogate value, no fixup required
            self.assertTrue('\u0061' < '\ud800\udc02')

            # Non surrogate above surrogate value, fixup required
            def test_lecmp(s, s2):
                self.assertTrue(s < s2)

            def test_fixup(s):
                s2 = '\ud800\udc01'
                test_lecmp(s, s2)
                s2 = '\ud900\udc01'
                test_lecmp(s, s2)
                s2 = '\uda00\udc01'
                test_lecmp(s, s2)
                s2 = '\udb00\udc01'
                test_lecmp(s, s2)
                s2 = '\ud800\udd01'
                test_lecmp(s, s2)
                s2 = '\ud900\udd01'
                test_lecmp(s, s2)
                s2 = '\uda00\udd01'
                test_lecmp(s, s2)
                s2 = '\udb00\udd01'
                test_lecmp(s, s2)
                s2 = '\ud800\ude01'
                test_lecmp(s, s2)
                s2 = '\ud900\ude01'
                test_lecmp(s, s2)
                s2 = '\uda00\ude01'
                test_lecmp(s, s2)
                s2 = '\udb00\ude01'
                test_lecmp(s, s2)
                s2 = '\ud800\udfff'
                test_lecmp(s, s2)
                s2 = '\ud900\udfff'
                test_lecmp(s, s2)
                s2 = '\uda00\udfff'
                test_lecmp(s, s2)
                s2 = '\udb00\udfff'
                test_lecmp(s, s2)

                test_fixup('\ue000')
                test_fixup('\uff61')

        # Surrogates on both sides, no fixup required
        self.assertTrue('\ud800\udc02' < '\ud84d\udc56')

    def test_islower(self):
        super().test_islower()
        self.checkequalnofix(False, '\u1FFc', 'islower')
        self.assertFalse('\u2167'.islower())
        self.assertTrue('\u2177'.islower())
        # non-BMP, uppercase
        self.assertFalse('\U00010401'.islower())
        self.assertFalse('\U00010427'.islower())
        # non-BMP, lowercase
        self.assertTrue('\U00010429'.islower())
        self.assertTrue('\U0001044E'.islower())
        # non-BMP, non-cased
        self.assertFalse('\U0001F40D'.islower())
        self.assertFalse('\U0001F46F'.islower())

    def test_isupper(self):
        super().test_isupper()
        if not sys.platform.startswith('java'):
            self.checkequalnofix(False, '\u1FFc', 'isupper')
        self.assertTrue('\u2167'.isupper())
        self.assertFalse('\u2177'.isupper())
        # non-BMP, uppercase
        self.assertTrue('\U00010401'.isupper())
        self.assertTrue('\U00010427'.isupper())
        # non-BMP, lowercase
        self.assertFalse('\U00010429'.isupper())
        self.assertFalse('\U0001044E'.isupper())
        # non-BMP, non-cased
        self.assertFalse('\U0001F40D'.isupper())
        self.assertFalse('\U0001F46F'.isupper())

    def test_istitle(self):
        super().test_istitle()
        self.checkequalnofix(True, '\u1FFc', 'istitle')
        self.checkequalnofix(True, 'Greek \u1FFcitlecases ...', 'istitle')

        # non-BMP, uppercase + lowercase
        self.assertTrue('\U00010401\U00010429'.istitle())
        self.assertTrue('\U00010427\U0001044E'.istitle())
        # apparently there are no titlecased (Lt) non-BMP chars in Unicode 6
        for ch in ['\U00010429', '\U0001044E', '\U0001F40D', '\U0001F46F']:
            self.assertFalse(ch.istitle(), '{!a} is not title'.format(ch))

    def test_isspace(self):
        super().test_isspace()
        self.checkequalnofix(True, '\u2000', 'isspace')
        self.checkequalnofix(True, '\u200a', 'isspace')
        self.checkequalnofix(False, '\u2014', 'isspace')
        # apparently there are no non-BMP spaces chars in Unicode 6
        for ch in ['\U00010401', '\U00010427', '\U00010429', '\U0001044E',
                   '\U0001F40D', '\U0001F46F']:
            self.assertFalse(ch.isspace(), '{!a} is not space.'.format(ch))

    def test_isalnum(self):
        super().test_isalnum()
        for ch in ['\U00010401', '\U00010427', '\U00010429', '\U0001044E',
                   '\U0001D7F6', '\U00011066', '\U000104A0', '\U0001F107']:
            self.assertTrue(ch.isalnum(), '{!a} is alnum.'.format(ch))

    def test_isalpha(self):
        super().test_isalpha()
        self.checkequalnofix(True, '\u1FFc', 'isalpha')
        # non-BMP, cased
        self.assertTrue('\U00010401'.isalpha())
        self.assertTrue('\U00010427'.isalpha())
        self.assertTrue('\U00010429'.isalpha())
        self.assertTrue('\U0001044E'.isalpha())
        # non-BMP, non-cased
        self.assertFalse('\U0001F40D'.isalpha())
        self.assertFalse('\U0001F46F'.isalpha())

    @unittest.skipIf(sys.version_info < (3, 7), 'Python lacks str.isascii()')
    def test_isascii(self):
        super().test_isascii()
        self.assertFalse("\u20ac".isascii())
        self.assertFalse("\U0010ffff".isascii())

    def test_isdecimal(self):
        self.checkequalnofix(False, '', 'isdecimal')
        self.checkequalnofix(False, 'a', 'isdecimal')
        self.checkequalnofix(True, '0', 'isdecimal')
        self.checkequalnofix(False, '\u2460', 'isdecimal') # CIRCLED DIGIT ONE
        self.checkequalnofix(False, '\xbc', 'isdecimal') # VULGAR FRACTION ONE QUARTER
        self.checkequalnofix(True, '\u0660', 'isdecimal') # ARABIC-INDIC DIGIT ZERO
        self.checkequalnofix(True, '0123456789', 'isdecimal')
        self.checkequalnofix(False, '0123456789a', 'isdecimal')

        self.checkraises(TypeError, 'abc', 'isdecimal', 42)

        for ch in ['\U00010401', '\U00010427', '\U00010429', '\U0001044E',
                   '\U0001F40D', '\U0001F46F', '\U00011065', '\U0001F107']:
            self.assertFalse(ch.isdecimal(), '{!a} is not decimal.'.format(ch))
        for ch in ['\U0001D7F6', '\U00011066', '\U000104A0']:
            self.assertTrue(ch.isdecimal(), '{!a} is decimal.'.format(ch))

    def test_isdigit(self):
        super().test_isdigit()
        self.checkequalnofix(True, '\u2460', 'isdigit')
        self.checkequalnofix(False, '\xbc', 'isdigit')
        self.checkequalnofix(True, '\u0660', 'isdigit')

        for ch in ['\U00010401', '\U00010427', '\U00010429', '\U0001044E',
                   '\U0001F40D', '\U0001F46F', '\U00011065']:
            self.assertFalse(ch.isdigit(), '{!a} is not a digit.'.format(ch))
        for ch in ['\U0001D7F6', '\U00011066', '\U000104A0', '\U0001F107']:
            self.assertTrue(ch.isdigit(), '{!a} is a digit.'.format(ch))

    def test_isnumeric(self):
        self.checkequalnofix(False, '', 'isnumeric')
        self.checkequalnofix(False, 'a', 'isnumeric')
        self.checkequalnofix(True, '0', 'isnumeric')
        self.checkequalnofix(True, '\u2460', 'isnumeric')
        self.checkequalnofix(True, '\xbc', 'isnumeric')
        self.checkequalnofix(True, '\u0660', 'isnumeric')
        self.checkequalnofix(True, '0123456789', 'isnumeric')
        self.checkequalnofix(False, '0123456789a', 'isnumeric')

        self.assertRaises(TypeError, "abc".isnumeric, 42)

        for ch in ['\U00010401', '\U00010427', '\U00010429', '\U0001044E',
                   '\U0001F40D', '\U0001F46F']:
            self.assertFalse(ch.isnumeric(), '{!a} is not numeric.'.format(ch))
        for ch in ['\U00011065', '\U0001D7F6', '\U00011066',
                   '\U000104A0', '\U0001F107']:
            self.assertTrue(ch.isnumeric(), '{!a} is numeric.'.format(ch))

    def test_isidentifier(self):
        self.assertTrue("a".isidentifier())
        self.assertTrue("Z".isidentifier())
        self.assertTrue("_".isidentifier())
        self.assertTrue("b0".isidentifier())
        self.assertTrue("bc".isidentifier())
        self.assertTrue("b_".isidentifier())
        self.assertTrue("µ".isidentifier())
        self.assertTrue("𝔘𝔫𝔦𝔠𝔬𝔡𝔢".isidentifier())

        self.assertFalse(" ".isidentifier())
        self.assertFalse("[".isidentifier())
        self.assertFalse("©".isidentifier())
        self.assertFalse("0".isidentifier())

    def test_isprintable(self):
        self.assertTrue("".isprintable())
        self.assertTrue(" ".isprintable())
        self.assertTrue("abcdefg".isprintable())
        self.assertFalse("abcdefg\n".isprintable())
        # some defined Unicode character
        self.assertTrue("\u0374".isprintable())
        # undefined character
        self.assertFalse("\u0378".isprintable())
        # single surrogate character
        self.assertFalse("\ud800".isprintable())

        self.assertTrue('\U0001F46F'.isprintable())
        self.assertFalse('\U000E0020'.isprintable())

    def test_surrogates(self):
        for s in ('a\uD800b\uDFFF', 'a\uDFFFb\uD800',
                  'a\uD800b\uDFFFa', 'a\uDFFFb\uD800a'):
            self.assertTrue(s.islower())
            self.assertFalse(s.isupper())
            self.assertFalse(s.istitle())
        for s in ('A\uD800B\uDFFF', 'A\uDFFFB\uD800',
                  'A\uD800B\uDFFFA', 'A\uDFFFB\uD800A'):
            self.assertFalse(s.islower())
            self.assertTrue(s.isupper())
            self.assertTrue(s.istitle())

        for meth_name in ('islower', 'isupper', 'istitle'):
            meth = getattr(str, meth_name)
            for s in ('\uD800', '\uDFFF', '\uD800\uD800', '\uDFFF\uDFFF'):
                self.assertFalse(meth(s), '%a.%s() is False' % (s, meth_name))

        for meth_name in ('isalpha', 'isalnum', 'isdigit', 'isspace',
                          'isdecimal', 'isnumeric',
                          'isidentifier', 'isprintable'):
            meth = getattr(str, meth_name)
            for s in ('\uD800', '\uDFFF', '\uD800\uD800', '\uDFFF\uDFFF',
                      'a\uD800b\uDFFF', 'a\uDFFFb\uD800',
                      'a\uD800b\uDFFFa', 'a\uDFFFb\uD800a'):
                self.assertFalse(meth(s), '%a.%s() is False' % (s, meth_name))


    def test_lower(self):
        CommonTest.test_lower(self)
        self.assertEqual('\U00010427'.lower(), '\U0001044F')
        self.assertEqual('\U00010427\U00010427'.lower(),
                         '\U0001044F\U0001044F')
        self.assertEqual('\U00010427\U0001044F'.lower(),
                         '\U0001044F\U0001044F')
        self.assertEqual('X\U00010427x\U0001044F'.lower(),
                         'x\U0001044Fx\U0001044F')
        self.assertEqual('fi'.lower(), 'fi')
        self.assertEqual('\u0130'.lower(), '\u0069\u0307')
        # Special case for GREEK CAPITAL LETTER SIGMA U+03A3
        self.assertEqual('\u03a3'.lower(), '\u03c3')
        self.assertEqual('\u0345\u03a3'.lower(), '\u0345\u03c3')
        self.assertEqual('A\u0345\u03a3'.lower(), 'a\u0345\u03c2')
        self.assertEqual('A\u0345\u03a3a'.lower(), 'a\u0345\u03c3a')
        self.assertEqual('A\u0345\u03a3'.lower(), 'a\u0345\u03c2')
        self.assertEqual('A\u03a3\u0345'.lower(), 'a\u03c2\u0345')
        self.assertEqual('\u03a3\u0345 '.lower(), '\u03c3\u0345 ')
        self.assertEqual('\U0008fffe'.lower(), '\U0008fffe')
        self.assertEqual('\u2177'.lower(), '\u2177')

    def test_casefold(self):
        self.assertEqual('hello'.casefold(), 'hello')
        self.assertEqual('hELlo'.casefold(), 'hello')
        self.assertEqual('ß'.casefold(), 'ss')
        self.assertEqual('fi'.casefold(), 'fi')
        self.assertEqual('\u03a3'.casefold(), '\u03c3')
        self.assertEqual('A\u0345\u03a3'.casefold(), 'a\u03b9\u03c3')
        self.assertEqual('\u00b5'.casefold(), '\u03bc')

    def test_upper(self):
        CommonTest.test_upper(self)
        self.assertEqual('\U0001044F'.upper(), '\U00010427')
        self.assertEqual('\U0001044F\U0001044F'.upper(),
                         '\U00010427\U00010427')
        self.assertEqual('\U00010427\U0001044F'.upper(),
                         '\U00010427\U00010427')
        self.assertEqual('X\U00010427x\U0001044F'.upper(),
                         'X\U00010427X\U00010427')
        self.assertEqual('fi'.upper(), 'FI')
        self.assertEqual('\u0130'.upper(), '\u0130')
        self.assertEqual('\u03a3'.upper(), '\u03a3')
        self.assertEqual('ß'.upper(), 'SS')
        self.assertEqual('\u1fd2'.upper(), '\u0399\u0308\u0300')
        self.assertEqual('\U0008fffe'.upper(), '\U0008fffe')
        self.assertEqual('\u2177'.upper(), '\u2167')

    def test_capitalize(self):
        CommonTest.test_capitalize(self)
        self.assertEqual('\U0001044F'.capitalize(), '\U00010427')
        self.assertEqual('\U0001044F\U0001044F'.capitalize(),
                         '\U00010427\U0001044F')
        self.assertEqual('\U00010427\U0001044F'.capitalize(),
                         '\U00010427\U0001044F')
        self.assertEqual('\U0001044F\U00010427'.capitalize(),
                         '\U00010427\U0001044F')
        self.assertEqual('X\U00010427x\U0001044F'.capitalize(),
                         'X\U0001044Fx\U0001044F')
        self.assertEqual('h\u0130'.capitalize(), 'H\u0069\u0307')
        exp = '\u0399\u0308\u0300\u0069\u0307'
        self.assertEqual('\u1fd2\u0130'.capitalize(), exp)
        if sys.version_info < (3, 8):
            self.assertEqual('finnish'.capitalize(), 'FInnish')
        else:
            self.assertEqual('finnish'.capitalize(), 'Finnish')
        self.assertEqual('A\u0345\u03a3'.capitalize(), 'A\u0345\u03c2')

    def test_title(self):
        super().test_title()
        self.assertEqual('\U0001044F'.title(), '\U00010427')
        self.assertEqual('\U0001044F\U0001044F'.title(),
                         '\U00010427\U0001044F')
        self.assertEqual('\U0001044F\U0001044F \U0001044F\U0001044F'.title(),
                         '\U00010427\U0001044F \U00010427\U0001044F')
        self.assertEqual('\U00010427\U0001044F \U00010427\U0001044F'.title(),
                         '\U00010427\U0001044F \U00010427\U0001044F')
        self.assertEqual('\U0001044F\U00010427 \U0001044F\U00010427'.title(),
                         '\U00010427\U0001044F \U00010427\U0001044F')
        self.assertEqual('X\U00010427x\U0001044F X\U00010427x\U0001044F'.title(),
                         'X\U0001044Fx\U0001044F X\U0001044Fx\U0001044F')
        self.assertEqual('fiNNISH'.title(), 'Finnish')
        self.assertEqual('A\u03a3 \u1fa1xy'.title(), 'A\u03c2 \u1fa9xy')
        self.assertEqual('A\u03a3A'.title(), 'A\u03c3a')

    def test_swapcase(self):
        CommonTest.test_swapcase(self)
        self.assertEqual('\U0001044F'.swapcase(), '\U00010427')
        self.assertEqual('\U00010427'.swapcase(), '\U0001044F')
        self.assertEqual('\U0001044F\U0001044F'.swapcase(),
                         '\U00010427\U00010427')
        self.assertEqual('\U00010427\U0001044F'.swapcase(),
                         '\U0001044F\U00010427')
        self.assertEqual('\U0001044F\U00010427'.swapcase(),
                         '\U00010427\U0001044F')
        self.assertEqual('X\U00010427x\U0001044F'.swapcase(),
                         'x\U0001044FX\U00010427')
        self.assertEqual('fi'.swapcase(), 'FI')
        self.assertEqual('\u0130'.swapcase(), '\u0069\u0307')
        # Special case for GREEK CAPITAL LETTER SIGMA U+03A3
        self.assertEqual('\u03a3'.swapcase(), '\u03c3')
        self.assertEqual('\u0345\u03a3'.swapcase(), '\u0399\u03c3')
        self.assertEqual('A\u0345\u03a3'.swapcase(), 'a\u0399\u03c2')
        self.assertEqual('A\u0345\u03a3a'.swapcase(), 'a\u0399\u03c3A')
        self.assertEqual('A\u0345\u03a3'.swapcase(), 'a\u0399\u03c2')
        self.assertEqual('A\u03a3\u0345'.swapcase(), 'a\u03c2\u0399')
        self.assertEqual('\u03a3\u0345 '.swapcase(), '\u03c3\u0399 ')
        self.assertEqual('\u03a3'.swapcase(), '\u03c3')
        self.assertEqual('ß'.swapcase(), 'SS')
        self.assertEqual('\u1fd2'.swapcase(), '\u0399\u0308\u0300')

    def test_center(self):
        CommonTest.test_center(self)
        self.assertEqual('x'.center(2, '\U0010FFFF'),
                         'x\U0010FFFF')
        self.assertEqual('x'.center(3, '\U0010FFFF'),
                         '\U0010FFFFx\U0010FFFF')
        self.assertEqual('x'.center(4, '\U0010FFFF'),
                         '\U0010FFFFx\U0010FFFF\U0010FFFF')

    @unittest.skipUnless(sys.maxsize == 2**31 - 1, "requires 32-bit system")
    @support.cpython_only
    def test_case_operation_overflow(self):
        # Issue #22643
        size = 2**32//12 + 1
        try:
            s = "ü" * size
        except MemoryError:
            self.skipTest('no enough memory (%.0f MiB required)' % (size / 2**20))
        try:
            self.assertRaises(OverflowError, s.upper)
        finally:
            del s

    def test_contains(self):
        # Testing Unicode contains method
        self.assertIn('a', 'abdb')
        self.assertIn('a', 'bdab')
        self.assertIn('a', 'bdaba')
        self.assertIn('a', 'bdba')
        self.assertNotIn('a', 'bdb')
        self.assertIn('a', 'bdba')
        self.assertIn('a', ('a',1,None))
        self.assertIn('a', (1,None,'a'))
        self.assertIn('a', ('a',1,None))
        self.assertIn('a', (1,None,'a'))
        self.assertNotIn('a', ('x',1,'y'))
        self.assertNotIn('a', ('x',1,None))
        self.assertNotIn('abcd', 'abcxxxx')
        self.assertIn('ab', 'abcd')
        self.assertIn('ab', 'abc')
        self.assertIn('ab', (1,None,'ab'))
        self.assertIn('', 'abc')
        self.assertIn('', '')
        self.assertIn('', 'abc')
        self.assertNotIn('\0', 'abc')
        self.assertIn('\0', '\0abc')
        self.assertIn('\0', 'abc\0')
        self.assertIn('a', '\0abc')
        self.assertIn('asdf', 'asdf')
        self.assertNotIn('asdf', 'asd')
        self.assertNotIn('asdf', '')

        self.assertRaises(TypeError, "abc".__contains__)
        # test mixed kinds
        for fill in ('a', '\u0100', '\U00010300'):
            fill *= 9
            for delim in ('c', '\u0102', '\U00010302'):
                self.assertNotIn(delim, fill)
                self.assertIn(delim, fill + delim)
                self.assertNotIn(delim * 2, fill)
                self.assertIn(delim * 2, fill + delim * 2)

    def test_issue18183(self):
        '\U00010000\U00100000'.lower()
        '\U00010000\U00100000'.casefold()
        '\U00010000\U00100000'.upper()
        '\U00010000\U00100000'.capitalize()
        '\U00010000\U00100000'.title()
        '\U00010000\U00100000'.swapcase()
        '\U00100000'.center(3, '\U00010000')
        '\U00100000'.ljust(3, '\U00010000')
        '\U00100000'.rjust(3, '\U00010000')

    def test_format(self):
        self.assertEqual(''.format(), '')
        self.assertEqual('a'.format(), 'a')
        self.assertEqual('ab'.format(), 'ab')
        self.assertEqual('a{{'.format(), 'a{')
        self.assertEqual('a}}'.format(), 'a}')
        self.assertEqual('{{b'.format(), '{b')
        self.assertEqual('}}b'.format(), '}b')
        self.assertEqual('a{{b'.format(), 'a{b')

        # examples from the PEP:
        import datetime
        self.assertEqual("My name is {0}".format('Fred'), "My name is Fred")
        self.assertEqual("My name is {0[name]}".format(dict(name='Fred')),
                         "My name is Fred")
        self.assertEqual("My name is {0} :-{{}}".format('Fred'),
                         "My name is Fred :-{}")

        d = datetime.date(2007, 8, 18)
        self.assertEqual("The year is {0.year}".format(d),
                         "The year is 2007")

        # classes we'll use for testing
        class C:
            def __init__(self, x=100):
                self._x = x
            def __format__(self, spec):
                return spec

        class D:
            def __init__(self, x):
                self.x = x
            def __format__(self, spec):
                return str(self.x)

        # class with __str__, but no __format__
        class E:
            def __init__(self, x):
                self.x = x
            def __str__(self):
                return 'E(' + self.x + ')'

        # class with __repr__, but no __format__ or __str__
        class F:
            def __init__(self, x):
                self.x = x
            def __repr__(self):
                return 'F(' + self.x + ')'

        # class with __format__ that forwards to string, for some format_spec's
        class G:
            def __init__(self, x):
                self.x = x
            def __str__(self):
                return "string is " + self.x
            def __format__(self, format_spec):
                if format_spec == 'd':
                    return 'G(' + self.x + ')'
                return object.__format__(self, format_spec)

        class I(datetime.date):
            def __format__(self, format_spec):
                return self.strftime(format_spec)

        class J(int):
            def __format__(self, format_spec):
                return int.__format__(self * 2, format_spec)

        class M:
            def __init__(self, x):
                self.x = x
            def __repr__(self):
                return 'M(' + self.x + ')'
            __str__ = None

        class N:
            def __init__(self, x):
                self.x = x
            def __repr__(self):
                return 'N(' + self.x + ')'
            __format__ = None

        self.assertEqual(''.format(), '')
        self.assertEqual('abc'.format(), 'abc')
        self.assertEqual('{0}'.format('abc'), 'abc')
        self.assertEqual('{0:}'.format('abc'), 'abc')
#        self.assertEqual('{ 0 }'.format('abc'), 'abc')
        self.assertEqual('X{0}'.format('abc'), 'Xabc')
        self.assertEqual('{0}X'.format('abc'), 'abcX')
        self.assertEqual('X{0}Y'.format('abc'), 'XabcY')
        self.assertEqual('{1}'.format(1, 'abc'), 'abc')
        self.assertEqual('X{1}'.format(1, 'abc'), 'Xabc')
        self.assertEqual('{1}X'.format(1, 'abc'), 'abcX')
        self.assertEqual('X{1}Y'.format(1, 'abc'), 'XabcY')
        self.assertEqual('{0}'.format(-15), '-15')
        self.assertEqual('{0}{1}'.format(-15, 'abc'), '-15abc')
        self.assertEqual('{0}X{1}'.format(-15, 'abc'), '-15Xabc')
        self.assertEqual('{{'.format(), '{')
        self.assertEqual('}}'.format(), '}')
        self.assertEqual('{{}}'.format(), '{}')
        self.assertEqual('{{x}}'.format(), '{x}')
        self.assertEqual('{{{0}}}'.format(123), '{123}')
        self.assertEqual('{{{{0}}}}'.format(), '{{0}}')
        self.assertEqual('}}{{'.format(), '}{')
        self.assertEqual('}}x{{'.format(), '}x{')

        # weird field names
        self.assertEqual("{0[foo-bar]}".format({'foo-bar':'baz'}), 'baz')
        self.assertEqual("{0[foo bar]}".format({'foo bar':'baz'}), 'baz')
        self.assertEqual("{0[ ]}".format({' ':3}), '3')

        self.assertEqual('{foo._x}'.format(foo=C(20)), '20')
        self.assertEqual('{1}{0}'.format(D(10), D(20)), '2010')
        self.assertEqual('{0._x.x}'.format(C(D('abc'))), 'abc')
        self.assertEqual('{0[0]}'.format(['abc', 'def']), 'abc')
        self.assertEqual('{0[1]}'.format(['abc', 'def']), 'def')
        self.assertEqual('{0[1][0]}'.format(['abc', ['def']]), 'def')
        self.assertEqual('{0[1][0].x}'.format(['abc', [D('def')]]), 'def')

        # strings
        self.assertEqual('{0:.3s}'.format('abc'), 'abc')
        self.assertEqual('{0:.3s}'.format('ab'), 'ab')
        self.assertEqual('{0:.3s}'.format('abcdef'), 'abc')
        self.assertEqual('{0:.0s}'.format('abcdef'), '')
        self.assertEqual('{0:3.3s}'.format('abc'), 'abc')
        self.assertEqual('{0:2.3s}'.format('abc'), 'abc')
        self.assertEqual('{0:2.2s}'.format('abc'), 'ab')
        self.assertEqual('{0:3.2s}'.format('abc'), 'ab ')
        self.assertEqual('{0:x<0s}'.format('result'), 'result')
        self.assertEqual('{0:x<5s}'.format('result'), 'result')
        self.assertEqual('{0:x<6s}'.format('result'), 'result')
        self.assertEqual('{0:x<7s}'.format('result'), 'resultx')
        self.assertEqual('{0:x<8s}'.format('result'), 'resultxx')
        self.assertEqual('{0: <7s}'.format('result'), 'result ')
        self.assertEqual('{0:<7s}'.format('result'), 'result ')
        self.assertEqual('{0:>7s}'.format('result'), ' result')
        self.assertEqual('{0:>8s}'.format('result'), '  result')
        self.assertEqual('{0:^8s}'.format('result'), ' result ')
        self.assertEqual('{0:^9s}'.format('result'), ' result  ')
        self.assertEqual('{0:^10s}'.format('result'), '  result  ')
        self.assertEqual('{0:10000}'.format('a'), 'a' + ' ' * 9999)
        self.assertEqual('{0:10000}'.format(''), ' ' * 10000)
        self.assertEqual('{0:10000000}'.format(''), ' ' * 10000000)

        # issue 12546: use \x00 as a fill character
        self.assertEqual('{0:\x00<6s}'.format('foo'), 'foo\x00\x00\x00')
        self.assertEqual('{0:\x01<6s}'.format('foo'), 'foo\x01\x01\x01')
        self.assertEqual('{0:\x00^6s}'.format('foo'), '\x00foo\x00\x00')
        self.assertEqual('{0:^6s}'.format('foo'), ' foo  ')

        self.assertEqual('{0:\x00<6}'.format(3), '3\x00\x00\x00\x00\x00')
        self.assertEqual('{0:\x01<6}'.format(3), '3\x01\x01\x01\x01\x01')
        self.assertEqual('{0:\x00^6}'.format(3), '\x00\x003\x00\x00\x00')
        self.assertEqual('{0:<6}'.format(3), '3     ')

        self.assertEqual('{0:\x00<6}'.format(3.14), '3.14\x00\x00')
        self.assertEqual('{0:\x01<6}'.format(3.14), '3.14\x01\x01')
        self.assertEqual('{0:\x00^6}'.format(3.14), '\x003.14\x00')
        self.assertEqual('{0:^6}'.format(3.14), ' 3.14 ')

        self.assertEqual('{0:\x00<12}'.format(3+2.0j), '(3+2j)\x00\x00\x00\x00\x00\x00')
        self.assertEqual('{0:\x01<12}'.format(3+2.0j), '(3+2j)\x01\x01\x01\x01\x01\x01')
        self.assertEqual('{0:\x00^12}'.format(3+2.0j), '\x00\x00\x00(3+2j)\x00\x00\x00')
        self.assertEqual('{0:^12}'.format(3+2.0j), '   (3+2j)   ')

        # format specifiers for user defined type
        self.assertEqual('{0:abc}'.format(C()), 'abc')

        # !r, !s and !a coercions
        self.assertEqual('{0!s}'.format('Hello'), 'Hello')
        self.assertEqual('{0!s:}'.format('Hello'), 'Hello')
        self.assertEqual('{0!s:15}'.format('Hello'), 'Hello          ')
        self.assertEqual('{0!s:15s}'.format('Hello'), 'Hello          ')
        self.assertEqual('{0!r}'.format('Hello'), "'Hello'")
        self.assertEqual('{0!r:}'.format('Hello'), "'Hello'")
        self.assertEqual('{0!r}'.format(F('Hello')), 'F(Hello)')
        self.assertEqual('{0!r}'.format('\u0378'), "'\\u0378'") # nonprintable
        self.assertEqual('{0!r}'.format('\u0374'), "'\u0374'")  # printable
        self.assertEqual('{0!r}'.format(F('\u0374')), 'F(\u0374)')
        self.assertEqual('{0!a}'.format('Hello'), "'Hello'")
        self.assertEqual('{0!a}'.format('\u0378'), "'\\u0378'") # nonprintable
        self.assertEqual('{0!a}'.format('\u0374'), "'\\u0374'") # printable
        self.assertEqual('{0!a:}'.format('Hello'), "'Hello'")
        self.assertEqual('{0!a}'.format(F('Hello')), 'F(Hello)')
        self.assertEqual('{0!a}'.format(F('\u0374')), 'F(\\u0374)')

        # test fallback to object.__format__
        self.assertEqual('{0}'.format({}), '{}')
        self.assertEqual('{0}'.format([]), '[]')
        self.assertEqual('{0}'.format([1]), '[1]')

        self.assertEqual('{0:d}'.format(G('data')), 'G(data)')
        self.assertEqual('{0!s}'.format(G('data')), 'string is data')

        self.assertRaises(TypeError, '{0:^10}'.format, E('data'))
        self.assertRaises(TypeError, '{0:^10s}'.format, E('data'))
        self.assertRaises(TypeError, '{0:>15s}'.format, G('data'))

        self.assertEqual("{0:date: %Y-%m-%d}".format(I(year=2007,
                                                       month=8,
                                                       day=27)),
                         "date: 2007-08-27")

        # test deriving from a builtin type and overriding __format__
        self.assertEqual("{0}".format(J(10)), "20")


        # string format specifiers
        self.assertEqual('{0:}'.format('a'), 'a')

        # computed format specifiers
        self.assertEqual("{0:.{1}}".format('hello world', 5), 'hello')
        self.assertEqual("{0:.{1}s}".format('hello world', 5), 'hello')
        self.assertEqual("{0:.{precision}s}".format('hello world', precision=5), 'hello')
        self.assertEqual("{0:{width}.{precision}s}".format('hello world', width=10, precision=5), 'hello     ')
        self.assertEqual("{0:{width}.{precision}s}".format('hello world', width='10', precision='5'), 'hello     ')

        # test various errors
        self.assertRaises(ValueError, '{'.format)
        self.assertRaises(ValueError, '}'.format)
        self.assertRaises(ValueError, 'a{'.format)
        self.assertRaises(ValueError, 'a}'.format)
        self.assertRaises(ValueError, '{a'.format)
        self.assertRaises(ValueError, '}a'.format)
        self.assertRaises(IndexError, '{0}'.format)
        self.assertRaises(IndexError, '{1}'.format, 'abc')
        self.assertRaises(KeyError,   '{x}'.format)
        self.assertRaises(ValueError, "}{".format)
        self.assertRaises(ValueError, "abc{0:{}".format)
        self.assertRaises(ValueError, "{0".format)
        self.assertRaises(IndexError, "{0.}".format)
        self.assertRaises(ValueError, "{0.}".format, 0)
        self.assertRaises(ValueError, "{0[}".format)
        self.assertRaises(ValueError, "{0[}".format, [])
        self.assertRaises(KeyError,   "{0]}".format)
        self.assertRaises(ValueError, "{0.[]}".format, 0)
        self.assertRaises(ValueError, "{0..foo}".format, 0)
        self.assertRaises(ValueError, "{0[0}".format, 0)
        self.assertRaises(ValueError, "{0[0:foo}".format, 0)
        self.assertRaises(KeyError,   "{c]}".format)
        self.assertRaises(ValueError, "{{ {{{0}}".format, 0)
        self.assertRaises(ValueError, "{0}}".format, 0)
        self.assertRaises(KeyError,   "{foo}".format, bar=3)
        self.assertRaises(ValueError, "{0!x}".format, 3)
        self.assertRaises(ValueError, "{0!}".format, 0)
        self.assertRaises(ValueError, "{0!rs}".format, 0)
        self.assertRaises(ValueError, "{!}".format)
        self.assertRaises(IndexError, "{:}".format)
        self.assertRaises(IndexError, "{:s}".format)
        self.assertRaises(IndexError, "{}".format)
        big = "23098475029384702983476098230754973209482573"
        self.assertRaises(ValueError, ("{" + big + "}").format)
        self.assertRaises(ValueError, ("{[" + big + "]}").format, [0])

        # issue 6089
        self.assertRaises(ValueError, "{0[0]x}".format, [None])
        self.assertRaises(ValueError, "{0[0](10)}".format, [None])

        # can't have a replacement on the field name portion
        self.assertRaises(TypeError, '{0[{1}]}'.format, 'abcdefg', 4)

        # exceed maximum recursion depth
        self.assertRaises(ValueError, "{0:{1:{2}}}".format, 'abc', 's', '')
        self.assertRaises(ValueError, "{0:{1:{2:{3:{4:{5:{6}}}}}}}".format,
                          0, 1, 2, 3, 4, 5, 6, 7)

        # string format spec errors
        self.assertRaises(ValueError, "{0:-s}".format, '')
        self.assertRaises(ValueError, format, "", "-")
        self.assertRaises(ValueError, "{0:=s}".format, '')

        # Alternate formatting is not supported
        self.assertRaises(ValueError, format, '', '#')
        self.assertRaises(ValueError, format, '', '#20')

        # Non-ASCII
        self.assertEqual("{0:s}{1:s}".format("ABC", "\u0410\u0411\u0412"),
                         'ABC\u0410\u0411\u0412')
        self.assertEqual("{0:.3s}".format("ABC\u0410\u0411\u0412"),
                         'ABC')
        self.assertEqual("{0:.0s}".format("ABC\u0410\u0411\u0412"),
                         '')

        self.assertEqual("{[{}]}".format({"{}": 5}), "5")
        self.assertEqual("{[{}]}".format({"{}" : "a"}), "a")
        self.assertEqual("{[{]}".format({"{" : "a"}), "a")
        self.assertEqual("{[}]}".format({"}" : "a"}), "a")
        self.assertEqual("{[[]}".format({"[" : "a"}), "a")
        self.assertEqual("{[!]}".format({"!" : "a"}), "a")
        self.assertRaises(ValueError, "{a{}b}".format, 42)
        self.assertRaises(ValueError, "{a{b}".format, 42)
        self.assertRaises(ValueError, "{[}".format, 42)

        self.assertEqual("0x{:0{:d}X}".format(0x0,16), "0x0000000000000000")

        # Blocking fallback
        m = M('data')
        self.assertEqual("{!r}".format(m), 'M(data)')
        self.assertRaises(TypeError, "{!s}".format, m)
        self.assertRaises(TypeError, "{}".format, m)
        n = N('data')
        self.assertEqual("{!r}".format(n), 'N(data)')
        self.assertEqual("{!s}".format(n), 'N(data)')
        self.assertRaises(TypeError, "{}".format, n)

    @unittest.skipIf(sys.version_info < (3, 6), 'Python str.format_map() test requires Py3.6+')
    def test_format_map(self):
        self.assertEqual(''.format_map({}), '')
        self.assertEqual('a'.format_map({}), 'a')
        self.assertEqual('ab'.format_map({}), 'ab')
        self.assertEqual('a{{'.format_map({}), 'a{')
        self.assertEqual('a}}'.format_map({}), 'a}')
        self.assertEqual('{{b'.format_map({}), '{b')
        self.assertEqual('}}b'.format_map({}), '}b')
        self.assertEqual('a{{b'.format_map({}), 'a{b')

        # using mappings
        class Mapping(dict):
            def __missing__(self, key):
                return key
        self.assertEqual('{hello}'.format_map(Mapping()), 'hello')
        self.assertEqual('{a} {world}'.format_map(Mapping(a='hello')), 'hello world')

        class InternalMapping:
            def __init__(self):
                self.mapping = {'a': 'hello'}
            def __getitem__(self, key):
                return self.mapping[key]
        self.assertEqual('{a}'.format_map(InternalMapping()), 'hello')


        class C:
            def __init__(self, x=100):
                self._x = x
            def __format__(self, spec):
                return spec
        self.assertEqual('{foo._x}'.format_map({'foo': C(20)}), '20')

        # test various errors
        self.assertRaises(TypeError, ''.format_map)
        self.assertRaises(TypeError, 'a'.format_map)

        self.assertRaises(ValueError, '{'.format_map, {})
        self.assertRaises(ValueError, '}'.format_map, {})
        self.assertRaises(ValueError, 'a{'.format_map, {})
        self.assertRaises(ValueError, 'a}'.format_map, {})
        self.assertRaises(ValueError, '{a'.format_map, {})
        self.assertRaises(ValueError, '}a'.format_map, {})

        # issue #12579: can't supply positional params to format_map
        self.assertRaises(ValueError, '{}'.format_map, {'a' : 2})
        self.assertRaises(ValueError, '{}'.format_map, 'a')
        self.assertRaises(ValueError, '{a} {}'.format_map, {"a" : 2, "b" : 1})

        ZERO = 0
        class BadMapping:
            def __getitem__(self, key):
                return 1 / ZERO
        self.assertRaises(KeyError, '{a}'.format_map, {})
        self.assertRaises(TypeError, '{a}'.format_map, [])
        self.assertRaises(ZeroDivisionError, '{a}'.format_map, BadMapping())

    def test_format_huge_precision(self):
        format_string = ".{}f".format(sys.maxsize + 1)
        with self.assertRaises(ValueError):
            result = format(2.34, format_string)

    def test_format_huge_width(self):
        format_string = "{}f".format(sys.maxsize + 1)
        with self.assertRaises(ValueError):
            result = format(2.34, format_string)

    def test_format_huge_item_number(self):
        format_string = "{{{}:.6f}}".format(sys.maxsize + 1)
        with self.assertRaises(ValueError):
            result = format_string.format(2.34)

    def test_format_auto_numbering(self):
        class C:
            def __init__(self, x=100):
                self._x = x
            def __format__(self, spec):
                return spec

        self.assertEqual('{}'.format(10), '10')
        self.assertEqual('{:5}'.format('s'), 's    ')
        self.assertEqual('{!r}'.format('s'), "'s'")
        self.assertEqual('{._x}'.format(C(10)), '10')
        self.assertEqual('{[1]}'.format([1, 2]), '2')
        self.assertEqual('{[a]}'.format({'a':4, 'b':2}), '4')
        self.assertEqual('a{}b{}c'.format(0, 1), 'a0b1c')

        self.assertEqual('a{:{}}b'.format('x', '^10'), 'a    x     b')
        self.assertEqual('a{:{}x}b'.format(20, '#'), 'a0x14b')

        # can't mix and match numbering and auto-numbering
        self.assertRaises(ValueError, '{}{1}'.format, 1, 2)
        self.assertRaises(ValueError, '{1}{}'.format, 1, 2)
        self.assertRaises(ValueError, '{:{1}}'.format, 1, 2)
        self.assertRaises(ValueError, '{0:{}}'.format, 1, 2)

        # can mix and match auto-numbering and named
        self.assertEqual('{f}{}'.format(4, f='test'), 'test4')
        self.assertEqual('{}{f}'.format(4, f='test'), '4test')
        self.assertEqual('{:{f}}{g}{}'.format(1, 3, g='g', f=2), ' 1g3')
        self.assertEqual('{f:{}}{}{g}'.format(2, 4, f=1, g='g'), ' 14g')

    def test_formatting(self):
        MixinStrUnicodeUserStringTest.test_formatting(self)
        # Testing Unicode formatting strings...
        self.assertEqual("%s, %s" % ("abc", "abc"), 'abc, abc')
        self.assertEqual("%s, %s, %i, %f, %5.2f" % ("abc", "abc", 1, 2, 3), 'abc, abc, 1, 2.000000,  3.00')
        self.assertEqual("%s, %s, %i, %f, %5.2f" % ("abc", "abc", 1, -2, 3), 'abc, abc, 1, -2.000000,  3.00')
        self.assertEqual("%s, %s, %i, %f, %5.2f" % ("abc", "abc", -1, -2, 3.5), 'abc, abc, -1, -2.000000,  3.50')
        self.assertEqual("%s, %s, %i, %f, %5.2f" % ("abc", "abc", -1, -2, 3.57), 'abc, abc, -1, -2.000000,  3.57')
        self.assertEqual("%s, %s, %i, %f, %5.2f" % ("abc", "abc", -1, -2, 1003.57), 'abc, abc, -1, -2.000000, 1003.57')
        if not sys.platform.startswith('java'):
            self.assertEqual("%r, %r" % (b"abc", "abc"), "b'abc', 'abc'")
            self.assertEqual("%r" % ("\u1234",), "'\u1234'")
            self.assertEqual("%a" % ("\u1234",), "'\\u1234'")
        self.assertEqual("%(x)s, %(y)s" % {'x':"abc", 'y':"def"}, 'abc, def')
        self.assertEqual("%(x)s, %(\xfc)s" % {'x':"abc", '\xfc':"def"}, 'abc, def')

        self.assertEqual('%c' % 0x1234, '\u1234')
        self.assertEqual('%c' % 0x21483, '\U00021483')
        self.assertRaises(OverflowError, "%c".__mod__, (0x110000,))
        self.assertEqual('%c' % '\U00021483', '\U00021483')
        self.assertRaises(TypeError, "%c".__mod__, "aa")
        self.assertRaises(ValueError, "%.1\u1032f".__mod__, (1.0/3))
        self.assertRaises(TypeError, "%i".__mod__, "aa")

        # formatting jobs delegated from the string implementation:
        self.assertEqual('...%(foo)s...' % {'foo':"abc"}, '...abc...')
        self.assertEqual('...%(foo)s...' % {'foo':"abc"}, '...abc...')
        self.assertEqual('...%(foo)s...' % {'foo':"abc"}, '...abc...')
        self.assertEqual('...%(foo)s...' % {'foo':"abc"}, '...abc...')
        self.assertEqual('...%(foo)s...' % {'foo':"abc",'def':123},  '...abc...')
        self.assertEqual('...%(foo)s...' % {'foo':"abc",'def':123}, '...abc...')
        self.assertEqual('...%s...%s...%s...%s...' % (1,2,3,"abc"), '...1...2...3...abc...')
        self.assertEqual('...%%...%%s...%s...%s...%s...%s...' % (1,2,3,"abc"), '...%...%s...1...2...3...abc...')
        self.assertEqual('...%s...' % "abc", '...abc...')
        self.assertEqual('%*s' % (5,'abc',), '  abc')
        self.assertEqual('%*s' % (-5,'abc',), 'abc  ')
        self.assertEqual('%*.*s' % (5,2,'abc',), '   ab')
        self.assertEqual('%*.*s' % (5,3,'abc',), '  abc')
        self.assertEqual('%i %*.*s' % (10, 5,3,'abc',), '10   abc')
        self.assertEqual('%i%s %*.*s' % (10, 3, 5, 3, 'abc',), '103   abc')
        self.assertEqual('%c' % 'a', 'a')
        class Wrapper:
            def __str__(self):
                return '\u1234'
        self.assertEqual('%s' % Wrapper(), '\u1234')

        # issue 3382
        NAN = float('nan')
        INF = float('inf')
        self.assertEqual('%f' % NAN, 'nan')
        self.assertEqual('%F' % NAN, 'NAN')
        self.assertEqual('%f' % INF, 'inf')
        self.assertEqual('%F' % INF, 'INF')

        # PEP 393
        self.assertEqual('%.1s' % "a\xe9\u20ac", 'a')
        self.assertEqual('%.2s' % "a\xe9\u20ac", 'a\xe9')

        #issue 19995
        class PseudoInt:
            def __init__(self, value):
                self.value = int(value)
            def __int__(self):
                return self.value
            def __index__(self):
                return self.value
        class PseudoFloat:
            def __init__(self, value):
                self.value = float(value)
            def __int__(self):
                return int(self.value)
        pi = PseudoFloat(3.1415)
        letter_m = PseudoInt(109)
        self.assertEqual('%x' % 42, '2a')
        self.assertEqual('%X' % 15, 'F')
        self.assertEqual('%o' % 9, '11')
        self.assertEqual('%c' % 109, 'm')
        self.assertEqual('%x' % letter_m, '6d')
        self.assertEqual('%X' % letter_m, '6D')
        self.assertEqual('%o' % letter_m, '155')
        self.assertEqual('%c' % letter_m, 'm')
        if sys.version_info >= (3, 5):
            self.assertRaisesRegex(TypeError, '%x format: an integer is required, not float', operator.mod, '%x', 3.14),
            self.assertRaisesRegex(TypeError, '%X format: an integer is required, not float', operator.mod, '%X', 2.11),
            self.assertRaisesRegex(TypeError, '%o format: an integer is required, not float', operator.mod, '%o', 1.79),
            self.assertRaisesRegex(TypeError, '%x format: an integer is required, not PseudoFloat', operator.mod, '%x', pi),
            self.assertRaises(TypeError, operator.mod, '%c', pi),

    def test_formatting_with_enum(self):
        # issue18780
        import enum
        class Float(float, enum.Enum):
            PI = 3.1415926
        class Int(enum.IntEnum):
            IDES = 15
        class Str(str, enum.Enum):
            ABC = 'abc'
        # Testing Unicode formatting strings...
        self.assertEqual(("%s, %s" % (Str.ABC, Str.ABC)).replace("Str.", ""),
                         'ABC, ABC')
        self.assertEqual(("%s, %s, %d, %i, %u, %f, %5.2f" %
                        (Str.ABC, Str.ABC,
                         Int.IDES, Int.IDES, Int.IDES,
                         Float.PI, Float.PI)).replace("Str.", ""),
                         'ABC, ABC, 15, 15, 15, 3.141593,  3.14')

        # formatting jobs delegated from the string implementation:
        self.assertEqual(('...%(foo)s...' % {'foo':Str.ABC}).replace("Str.", ""),
                         '...ABC...')
        self.assertEqual(('...%(foo)s...' % {'foo':Int.IDES}).replace("Int.", ""),
                         '...IDES...' if sys.version_info < (3,11) else '...15...')
        self.assertEqual('...%(foo)i...' % {'foo':Int.IDES},
                         '...15...')
        self.assertEqual('...%(foo)d...' % {'foo':Int.IDES},
                         '...15...')
        self.assertEqual('...%(foo)u...' % {'foo':Int.IDES, 'def':Float.PI},
                         '...15...')
        self.assertEqual('...%(foo)f...' % {'foo':Float.PI,'def':123},
                         '...3.141593...')

    def test_formatting_huge_precision(self):
        format_string = "%.{}f".format(sys.maxsize + 1)
        with self.assertRaises(ValueError):
            result = format_string % 2.34

    @unittest.skip('BROKEN!')
    def test_issue28598_strsubclass_rhs(self):
        # A subclass of str with an __rmod__ method should be able to hook
        # into the % operator
        class SubclassedStr(str):
            def __rmod__(self, other):
                return 'Success, self.__rmod__({!r}) was called'.format(other)
        self.assertEqual('lhs %% %r' % SubclassedStr('rhs'),
                         "Success, self.__rmod__('lhs %% %r') was called")

    @support.cpython_only
    def test_formatting_huge_precision_c_limits(self):
        from _testcapi import INT_MAX
        format_string = "%.{}f".format(INT_MAX + 1)
        with self.assertRaises(ValueError):
            result = format_string % 2.34

    def test_formatting_huge_width(self):
        format_string = "%{}f".format(sys.maxsize + 1)
        with self.assertRaises(ValueError):
            result = format_string % 2.34

    def test_startswith_endswith_errors(self):
        for meth in ('foo'.startswith, 'foo'.endswith):
            with self.assertRaises(TypeError) as cm:
                meth(['f'])
            exc = str(cm.exception)
            self.assertIn('str', exc)
            self.assertIn('tuple', exc)

    @support.run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
    def test_format_float(self):
        # should not format with a comma, but always with C locale
        self.assertEqual('1.0', '%.1f' % 1.0)

    def test_constructor(self):
        # unicode(obj) tests (this maps to PyObject_Unicode() at C level)

        self.assertEqual(
            str('unicode remains unicode'),
            'unicode remains unicode'
        )

        for text in ('ascii', '\xe9', '\u20ac', '\U0010FFFF'):
            subclass = StrSubclass(text)
            self.assertEqual(str(subclass), text)
            self.assertEqual(len(subclass), len(text))
            if text == 'ascii':
                self.assertEqual(subclass.encode('ascii'), b'ascii')
                self.assertEqual(subclass.encode('utf-8'), b'ascii')

        self.assertEqual(
            str('strings are converted to unicode'),
            'strings are converted to unicode'
        )

        class StringCompat:
            def __init__(self, x):
                self.x = x
            def __str__(self):
                return self.x

        self.assertEqual(
            str(StringCompat('__str__ compatible objects are recognized')),
            '__str__ compatible objects are recognized'
        )

        # unicode(obj) is compatible to str():

        o = StringCompat('unicode(obj) is compatible to str()')
        self.assertEqual(str(o), 'unicode(obj) is compatible to str()')
        self.assertEqual(str(o), 'unicode(obj) is compatible to str()')

        for obj in (123, 123.45, 123):
            self.assertEqual(str(obj), str(str(obj)))

        # unicode(obj, encoding, error) tests (this maps to
        # PyUnicode_FromEncodedObject() at C level)

        if not sys.platform.startswith('java'):
            self.assertRaises(
                TypeError,
                str,
                'decoding unicode is not supported',
                'utf-8',
                'strict'
            )

        self.assertEqual(
            str(b'strings are decoded to unicode', 'utf-8', 'strict'),
            'strings are decoded to unicode'
        )

        if not sys.platform.startswith('java'):
            self.assertEqual(
                str(
                    memoryview(b'character buffers are decoded to unicode'),
                    'utf-8',
                    'strict'
                ),
                'character buffers are decoded to unicode'
            )

        self.assertRaises(TypeError, str, 42, 42, 42)

    def test_constructor_keyword_args(self):
        """Pass various keyword argument combinations to the constructor."""
        # The object argument can be passed as a keyword.
        self.assertEqual(str(object='foo'), 'foo')
        self.assertEqual(str(object=b'foo', encoding='utf-8'), 'foo')
        # The errors argument without encoding triggers "decode" mode.
        self.assertEqual(str(b'foo', errors='strict'), 'foo')  # not "b'foo'"
        self.assertEqual(str(object=b'foo', errors='strict'), 'foo')

    def test_constructor_defaults(self):
        """Check the constructor argument defaults."""
        # The object argument defaults to '' or b''.
        self.assertEqual(str(), '')
        self.assertEqual(str(errors='strict'), '')
        utf8_cent = '¢'.encode('utf-8')
        # The encoding argument defaults to utf-8.
        self.assertEqual(str(utf8_cent, errors='strict'), '¢')
        # The errors argument defaults to strict.
        self.assertRaises(UnicodeDecodeError, str, utf8_cent, encoding='ascii')

    @unittest.skipIf(sys.version_info < (3, 6), 'Python utf-7 codec test requires Py3.6+')
    def test_codecs_utf7(self):
        utfTests = [
            ('A\u2262\u0391.', b'A+ImIDkQ.'),             # RFC2152 example
            ('Hi Mom -\u263a-!', b'Hi Mom -+Jjo--!'),     # RFC2152 example
            ('\u65E5\u672C\u8A9E', b'+ZeVnLIqe-'),        # RFC2152 example
            ('Item 3 is \u00a31.', b'Item 3 is +AKM-1.'), # RFC2152 example
            ('+', b'+-'),
            ('+-', b'+--'),
            ('+?', b'+-?'),
            (r'\?', b'+AFw?'),
            ('+?', b'+-?'),
            (r'\\?', b'+AFwAXA?'),
            (r'\\\?', b'+AFwAXABc?'),
            (r'++--', b'+-+---'),
            ('\U000abcde', b'+2m/c3g-'),                  # surrogate pairs
            ('/', b'/'),
        ]

        for (x, y) in utfTests:
            self.assertEqual(x.encode('utf-7'), y)

        # Unpaired surrogates are passed through
        self.assertEqual('\uD801'.encode('utf-7'), b'+2AE-')
        self.assertEqual('\uD801x'.encode('utf-7'), b'+2AE-x')
        self.assertEqual('\uDC01'.encode('utf-7'), b'+3AE-')
        self.assertEqual('\uDC01x'.encode('utf-7'), b'+3AE-x')
        self.assertEqual(b'+2AE-'.decode('utf-7'), '\uD801')
        self.assertEqual(b'+2AE-x'.decode('utf-7'), '\uD801x')
        self.assertEqual(b'+3AE-'.decode('utf-7'), '\uDC01')
        self.assertEqual(b'+3AE-x'.decode('utf-7'), '\uDC01x')

        self.assertEqual('\uD801\U000abcde'.encode('utf-7'), b'+2AHab9ze-')
        self.assertEqual(b'+2AHab9ze-'.decode('utf-7'), '\uD801\U000abcde')

        # Issue #2242: crash on some Windows/MSVC versions
        self.assertEqual(b'+\xc1'.decode('utf-7', 'ignore'), '')

        # Direct encoded characters
        set_d = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'(),-./:?"
        # Optional direct characters
        set_o = '!"#$%&*;<=>@[]^_`{|}'
        for c in set_d:
            self.assertEqual(c.encode('utf7'), c.encode('ascii'))
            self.assertEqual(c.encode('ascii').decode('utf7'), c)
        for c in set_o:
            self.assertEqual(c.encode('ascii').decode('utf7'), c)

        if sys.version_info >= (3, 8):
            with self.assertRaisesRegex(UnicodeDecodeError,
                                        'ill-formed sequence'):
                b'+@'.decode('utf-7')

    def test_codecs_utf8(self):
        self.assertEqual(''.encode('utf-8'), b'')
        self.assertEqual('\u20ac'.encode('utf-8'), b'\xe2\x82\xac')
        self.assertEqual('\U00010002'.encode('utf-8'), b'\xf0\x90\x80\x82')
        self.assertEqual('\U00023456'.encode('utf-8'), b'\xf0\xa3\x91\x96')
        self.assertEqual('\ud800'.encode('utf-8', 'surrogatepass'), b'\xed\xa0\x80')
        self.assertEqual('\udc00'.encode('utf-8', 'surrogatepass'), b'\xed\xb0\x80')
        self.assertEqual(('\U00010002'*10).encode('utf-8'),
                         b'\xf0\x90\x80\x82'*10)
        self.assertEqual(
            '\u6b63\u78ba\u306b\u8a00\u3046\u3068\u7ffb\u8a33\u306f'
            '\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u4e00'
            '\u90e8\u306f\u30c9\u30a4\u30c4\u8a9e\u3067\u3059\u304c'
            '\u3001\u3042\u3068\u306f\u3067\u305f\u3089\u3081\u3067'
            '\u3059\u3002\u5b9f\u969b\u306b\u306f\u300cWenn ist das'
            ' Nunstuck git und'.encode('utf-8'),
            b'\xe6\xad\xa3\xe7\xa2\xba\xe3\x81\xab\xe8\xa8\x80\xe3\x81'
            b'\x86\xe3\x81\xa8\xe7\xbf\xbb\xe8\xa8\xb3\xe3\x81\xaf\xe3'
            b'\x81\x95\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x84\xe3\x81\xbe'
            b'\xe3\x81\x9b\xe3\x82\x93\xe3\x80\x82\xe4\xb8\x80\xe9\x83'
            b'\xa8\xe3\x81\xaf\xe3\x83\x89\xe3\x82\xa4\xe3\x83\x84\xe8'
            b'\xaa\x9e\xe3\x81\xa7\xe3\x81\x99\xe3\x81\x8c\xe3\x80\x81'
            b'\xe3\x81\x82\xe3\x81\xa8\xe3\x81\xaf\xe3\x81\xa7\xe3\x81'
            b'\x9f\xe3\x82\x89\xe3\x82\x81\xe3\x81\xa7\xe3\x81\x99\xe3'
            b'\x80\x82\xe5\xae\x9f\xe9\x9a\x9b\xe3\x81\xab\xe3\x81\xaf'
            b'\xe3\x80\x8cWenn ist das Nunstuck git und'
        )

        # UTF-8 specific decoding tests
        self.assertEqual(str(b'\xf0\xa3\x91\x96', 'utf-8'), '\U00023456' )
        self.assertEqual(str(b'\xf0\x90\x80\x82', 'utf-8'), '\U00010002' )
        self.assertEqual(str(b'\xe2\x82\xac', 'utf-8'), '\u20ac' )

        # Other possible utf-8 test cases:
        # * strict decoding testing for all of the
        #   UTF8_ERROR cases in PyUnicode_DecodeUTF8

    def test_utf8_decode_valid_sequences(self):
        sequences = [
            # single byte
            (b'\x00', '\x00'), (b'a', 'a'), (b'\x7f', '\x7f'),
            # 2 bytes
            (b'\xc2\x80', '\x80'), (b'\xdf\xbf', '\u07ff'),
            # 3 bytes
            (b'\xe0\xa0\x80', '\u0800'), (b'\xed\x9f\xbf', '\ud7ff'),
            (b'\xee\x80\x80', '\uE000'), (b'\xef\xbf\xbf', '\uffff'),
            # 4 bytes
            (b'\xF0\x90\x80\x80', '\U00010000'),
            (b'\xf4\x8f\xbf\xbf', '\U0010FFFF')
        ]
        for seq, res in sequences:
            self.assertEqual(seq.decode('utf-8'), res)


    def test_utf8_decode_invalid_sequences(self):
        # continuation bytes in a sequence of 2, 3, or 4 bytes
        continuation_bytes = [bytes([x]) for x in range(0x80, 0xC0)]
        # start bytes of a 2-byte sequence equivalent to code points < 0x7F
        invalid_2B_seq_start_bytes = [bytes([x]) for x in range(0xC0, 0xC2)]
        # start bytes of a 4-byte sequence equivalent to code points > 0x10FFFF
        invalid_4B_seq_start_bytes = [bytes([x]) for x in range(0xF5, 0xF8)]
        invalid_start_bytes = (
            continuation_bytes + invalid_2B_seq_start_bytes +
            invalid_4B_seq_start_bytes + [bytes([x]) for x in range(0xF7, 0x100)]
        )

        for byte in invalid_start_bytes:
            self.assertRaises(UnicodeDecodeError, byte.decode, 'utf-8')

        for sb in invalid_2B_seq_start_bytes:
            for cb in continuation_bytes:
                self.assertRaises(UnicodeDecodeError, (sb+cb).decode, 'utf-8')

        for sb in invalid_4B_seq_start_bytes:
            for cb1 in continuation_bytes[:3]:
                for cb3 in continuation_bytes[:3]:
                    self.assertRaises(UnicodeDecodeError,
                                      (sb+cb1+b'\x80'+cb3).decode, 'utf-8')

        for cb in [bytes([x]) for x in range(0x80, 0xA0)]:
            self.assertRaises(UnicodeDecodeError,
                              (b'\xE0'+cb+b'\x80').decode, 'utf-8')
            self.assertRaises(UnicodeDecodeError,
                              (b'\xE0'+cb+b'\xBF').decode, 'utf-8')
        # surrogates
        for cb in [bytes([x]) for x in range(0xA0, 0xC0)]:
            self.assertRaises(UnicodeDecodeError,
                              (b'\xED'+cb+b'\x80').decode, 'utf-8')
            self.assertRaises(UnicodeDecodeError,
                              (b'\xED'+cb+b'\xBF').decode, 'utf-8')
        for cb in [bytes([x]) for x in range(0x80, 0x90)]:
            self.assertRaises(UnicodeDecodeError,
                              (b'\xF0'+cb+b'\x80\x80').decode, 'utf-8')
            self.assertRaises(UnicodeDecodeError,
                              (b'\xF0'+cb+b'\xBF\xBF').decode, 'utf-8')
        for cb in [bytes([x]) for x in range(0x90, 0xC0)]:
            self.assertRaises(UnicodeDecodeError,
                              (b'\xF4'+cb+b'\x80\x80').decode, 'utf-8')
            self.assertRaises(UnicodeDecodeError,
                              (b'\xF4'+cb+b'\xBF\xBF').decode, 'utf-8')

    def test_issue8271(self):
        # Issue #8271: during the decoding of an invalid UTF-8 byte sequence,
        # only the start byte and the continuation byte(s) are now considered
        # invalid, instead of the number of bytes specified by the start byte.
        # See http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf (page 95,
        # table 3-8, Row 2) for more information about the algorithm used.
        FFFD = '\ufffd'
        sequences = [
            # invalid start bytes
            (b'\x80', FFFD), # continuation byte
            (b'\x80\x80', FFFD*2), # 2 continuation bytes
            (b'\xc0', FFFD),
            (b'\xc0\xc0', FFFD*2),
            (b'\xc1', FFFD),
            (b'\xc1\xc0', FFFD*2),
            (b'\xc0\xc1', FFFD*2),
            # with start byte of a 2-byte sequence
            (b'\xc2', FFFD), # only the start byte
            (b'\xc2\xc2', FFFD*2), # 2 start bytes
            (b'\xc2\xc2\xc2', FFFD*3), # 3 start bytes
            (b'\xc2\x41', FFFD+'A'), # invalid continuation byte
            # with start byte of a 3-byte sequence
            (b'\xe1', FFFD), # only the start byte
            (b'\xe1\xe1', FFFD*2), # 2 start bytes
            (b'\xe1\xe1\xe1', FFFD*3), # 3 start bytes
            (b'\xe1\xe1\xe1\xe1', FFFD*4), # 4 start bytes
            (b'\xe1\x80', FFFD), # only 1 continuation byte
            (b'\xe1\x41', FFFD+'A'), # invalid continuation byte
            (b'\xe1\x41\x80', FFFD+'A'+FFFD), # invalid cb followed by valid cb
            (b'\xe1\x41\x41', FFFD+'AA'), # 2 invalid continuation bytes
            (b'\xe1\x80\x41', FFFD+'A'), # only 1 valid continuation byte
            (b'\xe1\x80\xe1\x41', FFFD*2+'A'), # 1 valid and the other invalid
            (b'\xe1\x41\xe1\x80', FFFD+'A'+FFFD), # 1 invalid and the other valid
            # with start byte of a 4-byte sequence
            (b'\xf1', FFFD), # only the start byte
            (b'\xf1\xf1', FFFD*2), # 2 start bytes
            (b'\xf1\xf1\xf1', FFFD*3), # 3 start bytes
            (b'\xf1\xf1\xf1\xf1', FFFD*4), # 4 start bytes
            (b'\xf1\xf1\xf1\xf1\xf1', FFFD*5), # 5 start bytes
            (b'\xf1\x80', FFFD), # only 1 continuation bytes
            (b'\xf1\x80\x80', FFFD), # only 2 continuation bytes
            (b'\xf1\x80\x41', FFFD+'A'), # 1 valid cb and 1 invalid
            (b'\xf1\x80\x41\x41', FFFD+'AA'), # 1 valid cb and 1 invalid
            (b'\xf1\x80\x80\x41', FFFD+'A'), # 2 valid cb and 1 invalid
            (b'\xf1\x41\x80', FFFD+'A'+FFFD), # 1 invalid cv and 1 valid
            (b'\xf1\x41\x80\x80', FFFD+'A'+FFFD*2), # 1 invalid cb and 2 invalid
            (b'\xf1\x41\x80\x41', FFFD+'A'+FFFD+'A'), # 2 invalid cb and 1 invalid
            (b'\xf1\x41\x41\x80', FFFD+'AA'+FFFD), # 1 valid cb and 1 invalid
            (b'\xf1\x41\xf1\x80', FFFD+'A'+FFFD),
            (b'\xf1\x41\x80\xf1', FFFD+'A'+FFFD*2),
            (b'\xf1\xf1\x80\x41', FFFD*2+'A'),
            (b'\xf1\x41\xf1\xf1', FFFD+'A'+FFFD*2),
            # with invalid start byte of a 4-byte sequence (rfc2279)
            (b'\xf5', FFFD), # only the start byte
            (b'\xf5\xf5', FFFD*2), # 2 start bytes
            (b'\xf5\x80', FFFD*2), # only 1 continuation byte
            (b'\xf5\x80\x80', FFFD*3), # only 2 continuation byte
            (b'\xf5\x80\x80\x80', FFFD*4), # 3 continuation bytes
            (b'\xf5\x80\x41', FFFD*2+'A'), #  1 valid cb and 1 invalid
            (b'\xf5\x80\x41\xf5', FFFD*2+'A'+FFFD),
            (b'\xf5\x41\x80\x80\x41', FFFD+'A'+FFFD*2+'A'),
            # with invalid start byte of a 5-byte sequence (rfc2279)
            (b'\xf8', FFFD), # only the start byte
            (b'\xf8\xf8', FFFD*2), # 2 start bytes
            (b'\xf8\x80', FFFD*2), # only one continuation byte
            (b'\xf8\x80\x41', FFFD*2 + 'A'), # 1 valid cb and 1 invalid
            (b'\xf8\x80\x80\x80\x80', FFFD*5), # invalid 5 bytes seq with 5 bytes
            # with invalid start byte of a 6-byte sequence (rfc2279)
            (b'\xfc', FFFD), # only the start byte
            (b'\xfc\xfc', FFFD*2), # 2 start bytes
            (b'\xfc\x80\x80', FFFD*3), # only 2 continuation bytes
            (b'\xfc\x80\x80\x80\x80\x80', FFFD*6), # 6 continuation bytes
            # invalid start byte
            (b'\xfe', FFFD),
            (b'\xfe\x80\x80', FFFD*3),
            # other sequences
            (b'\xf1\x80\x41\x42\x43', '\ufffd\x41\x42\x43'),
            (b'\xf1\x80\xff\x42\x43', '\ufffd\ufffd\x42\x43'),
            (b'\xf1\x80\xc2\x81\x43', '\ufffd\x81\x43'),
            (b'\x61\xF1\x80\x80\xE1\x80\xC2\x62\x80\x63\x80\xBF\x64',
             '\x61\uFFFD\uFFFD\uFFFD\x62\uFFFD\x63\uFFFD\uFFFD\x64'),
        ]
        for n, (seq, res) in enumerate(sequences):
            self.assertRaises(UnicodeDecodeError, seq.decode, 'utf-8', 'strict')
            self.assertEqual(seq.decode('utf-8', 'replace'), res)
            self.assertEqual((seq+b'b').decode('utf-8', 'replace'), res+'b')
            self.assertEqual(seq.decode('utf-8', 'ignore'),
                             res.replace('\uFFFD', ''))

    def assertCorrectUTF8Decoding(self, seq, res, err):
        """
        Check that an invalid UTF-8 sequence raises a UnicodeDecodeError when
        'strict' is used, returns res when 'replace' is used, and that doesn't
        return anything when 'ignore' is used.
        """
        with self.assertRaises(UnicodeDecodeError) as cm:
            seq.decode('utf-8')
        exc = cm.exception

        self.assertIn(err, str(exc))
        self.assertEqual(seq.decode('utf-8', 'replace'), res)
        self.assertEqual((b'aaaa' + seq + b'bbbb').decode('utf-8', 'replace'),
                         'aaaa' + res + 'bbbb')
        res = res.replace('\ufffd', '')
        self.assertEqual(seq.decode('utf-8', 'ignore'), res)
        self.assertEqual((b'aaaa' + seq + b'bbbb').decode('utf-8', 'ignore'),
                          'aaaa' + res + 'bbbb')

    def test_invalid_start_byte(self):
        """
        Test that an 'invalid start byte' error is raised when the first byte
        is not in the ASCII range or is not a valid start byte of a 2-, 3-, or
        4-bytes sequence. The invalid start byte is replaced with a single
        U+FFFD when errors='replace'.
        E.g. <80> is a continuation byte and can appear only after a start byte.
        """
        FFFD = '\ufffd'
        for byte in b'\x80\xA0\x9F\xBF\xC0\xC1\xF5\xFF':
            self.assertCorrectUTF8Decoding(bytes([byte]), '\ufffd',
                                           'invalid start byte')

    def test_unexpected_end_of_data(self):
        """
        Test that an 'unexpected end of data' error is raised when the string
        ends after a start byte of a 2-, 3-, or 4-bytes sequence without having
        enough continuation bytes.  The incomplete sequence is replaced with a
        single U+FFFD when errors='replace'.
        E.g. in the sequence , F3 is the start byte of a 4-bytes
        sequence, but it's followed by only 2 valid continuation bytes and the
        last continuation bytes is missing.
        Note: the continuation bytes must be all valid, if one of them is
        invalid another error will be raised.
        """
        sequences = [
            'C2', 'DF',
            'E0 A0', 'E0 BF', 'E1 80', 'E1 BF', 'EC 80', 'EC BF',
            'ED 80', 'ED 9F', 'EE 80', 'EE BF', 'EF 80', 'EF BF',
            'F0 90', 'F0 BF', 'F0 90 80', 'F0 90 BF', 'F0 BF 80', 'F0 BF BF',
            'F1 80', 'F1 BF', 'F1 80 80', 'F1 80 BF', 'F1 BF 80', 'F1 BF BF',
            'F3 80', 'F3 BF', 'F3 80 80', 'F3 80 BF', 'F3 BF 80', 'F3 BF BF',
            'F4 80', 'F4 8F', 'F4 80 80', 'F4 80 BF', 'F4 8F 80', 'F4 8F BF'
        ]
        FFFD = '\ufffd'
        for seq in sequences:
            self.assertCorrectUTF8Decoding(bytes.fromhex(seq), '\ufffd',
                                           'unexpected end of data')

    def test_invalid_cb_for_2bytes_seq(self):
        """
        Test that an 'invalid continuation byte' error is raised when the
        continuation byte of a 2-bytes sequence is invalid.  The start byte
        is replaced by a single U+FFFD and the second byte is handled
        separately when errors='replace'.
        E.g. in the sequence , C2 is the start byte of a 2-bytes
        sequence, but 41 is not a valid continuation byte because it's the
        ASCII letter 'A'.
        """
        FFFD = '\ufffd'
        FFFDx2 = FFFD * 2
        sequences = [
            ('C2 00', FFFD+'\x00'), ('C2 7F', FFFD+'\x7f'),
            ('C2 C0', FFFDx2), ('C2 FF', FFFDx2),
            ('DF 00', FFFD+'\x00'), ('DF 7F', FFFD+'\x7f'),
            ('DF C0', FFFDx2), ('DF FF', FFFDx2),
        ]
        for seq, res in sequences:
            self.assertCorrectUTF8Decoding(bytes.fromhex(seq), res,
                                           'invalid continuation byte')

    def test_invalid_cb_for_3bytes_seq(self):
        """
        Test that an 'invalid continuation byte' error is raised when the
        continuation byte(s) of a 3-bytes sequence are invalid.  When
        errors='replace', if the first continuation byte is valid, the first
        two bytes (start byte + 1st cb) are replaced by a single U+FFFD and the
        third byte is handled separately, otherwise only the start byte is
        replaced with a U+FFFD and the other continuation bytes are handled
        separately.
        E.g. in the sequence , E1 is the start byte of a 3-bytes
        sequence, 80 is a valid continuation byte, but 41 is not a valid cb
        because it's the ASCII letter 'A'.
        Note: when the start byte is E0 or ED, the valid ranges for the first
        continuation byte are limited to A0..BF and 80..9F respectively.
        Python 2 used to consider all the bytes in range 80..BF valid when the
        start byte was ED.  This is fixed in Python 3.
        """
        FFFD = '\ufffd'
        FFFDx2 = FFFD * 2
        sequences = [
            ('E0 00', FFFD+'\x00'), ('E0 7F', FFFD+'\x7f'), ('E0 80', FFFDx2),
            ('E0 9F', FFFDx2), ('E0 C0', FFFDx2), ('E0 FF', FFFDx2),
            ('E0 A0 00', FFFD+'\x00'), ('E0 A0 7F', FFFD+'\x7f'),
            ('E0 A0 C0', FFFDx2), ('E0 A0 FF', FFFDx2),
            ('E0 BF 00', FFFD+'\x00'), ('E0 BF 7F', FFFD+'\x7f'),
            ('E0 BF C0', FFFDx2), ('E0 BF FF', FFFDx2), ('E1 00', FFFD+'\x00'),
            ('E1 7F', FFFD+'\x7f'), ('E1 C0', FFFDx2), ('E1 FF', FFFDx2),
            ('E1 80 00', FFFD+'\x00'), ('E1 80 7F', FFFD+'\x7f'),
            ('E1 80 C0', FFFDx2), ('E1 80 FF', FFFDx2),
            ('E1 BF 00', FFFD+'\x00'), ('E1 BF 7F', FFFD+'\x7f'),
            ('E1 BF C0', FFFDx2), ('E1 BF FF', FFFDx2), ('EC 00', FFFD+'\x00'),
            ('EC 7F', FFFD+'\x7f'), ('EC C0', FFFDx2), ('EC FF', FFFDx2),
            ('EC 80 00', FFFD+'\x00'), ('EC 80 7F', FFFD+'\x7f'),
            ('EC 80 C0', FFFDx2), ('EC 80 FF', FFFDx2),
            ('EC BF 00', FFFD+'\x00'), ('EC BF 7F', FFFD+'\x7f'),
            ('EC BF C0', FFFDx2), ('EC BF FF', FFFDx2), ('ED 00', FFFD+'\x00'),
            ('ED 7F', FFFD+'\x7f'),
            ('ED A0', FFFDx2), ('ED BF', FFFDx2), # see note ^
            ('ED C0', FFFDx2), ('ED FF', FFFDx2), ('ED 80 00', FFFD+'\x00'),
            ('ED 80 7F', FFFD+'\x7f'), ('ED 80 C0', FFFDx2),
            ('ED 80 FF', FFFDx2), ('ED 9F 00', FFFD+'\x00'),
            ('ED 9F 7F', FFFD+'\x7f'), ('ED 9F C0', FFFDx2),
            ('ED 9F FF', FFFDx2), ('EE 00', FFFD+'\x00'),
            ('EE 7F', FFFD+'\x7f'), ('EE C0', FFFDx2), ('EE FF', FFFDx2),
            ('EE 80 00', FFFD+'\x00'), ('EE 80 7F', FFFD+'\x7f'),
            ('EE 80 C0', FFFDx2), ('EE 80 FF', FFFDx2),
            ('EE BF 00', FFFD+'\x00'), ('EE BF 7F', FFFD+'\x7f'),
            ('EE BF C0', FFFDx2), ('EE BF FF', FFFDx2), ('EF 00', FFFD+'\x00'),
            ('EF 7F', FFFD+'\x7f'), ('EF C0', FFFDx2), ('EF FF', FFFDx2),
            ('EF 80 00', FFFD+'\x00'), ('EF 80 7F', FFFD+'\x7f'),
            ('EF 80 C0', FFFDx2), ('EF 80 FF', FFFDx2),
            ('EF BF 00', FFFD+'\x00'), ('EF BF 7F', FFFD+'\x7f'),
            ('EF BF C0', FFFDx2), ('EF BF FF', FFFDx2),
        ]
        for seq, res in sequences:
            self.assertCorrectUTF8Decoding(bytes.fromhex(seq), res,
                                           'invalid continuation byte')

    def test_invalid_cb_for_4bytes_seq(self):
        """
        Test that an 'invalid continuation byte' error is raised when the
        continuation byte(s) of a 4-bytes sequence are invalid.  When
        errors='replace',the start byte and all the following valid
        continuation bytes are replaced with a single U+FFFD, and all the bytes
        starting from the first invalid continuation bytes (included) are
        handled separately.
        E.g. in the sequence , E1 is the start byte of a 3-bytes
        sequence, 80 is a valid continuation byte, but 41 is not a valid cb
        because it's the ASCII letter 'A'.
        Note: when the start byte is E0 or ED, the valid ranges for the first
        continuation byte are limited to A0..BF and 80..9F respectively.
        However, when the start byte is ED, Python 2 considers all the bytes
        in range 80..BF valid.  This is fixed in Python 3.
        """
        FFFD = '\ufffd'
        FFFDx2 = FFFD * 2
        sequences = [
            ('F0 00', FFFD+'\x00'), ('F0 7F', FFFD+'\x7f'), ('F0 80', FFFDx2),
            ('F0 8F', FFFDx2), ('F0 C0', FFFDx2), ('F0 FF', FFFDx2),
            ('F0 90 00', FFFD+'\x00'), ('F0 90 7F', FFFD+'\x7f'),
            ('F0 90 C0', FFFDx2), ('F0 90 FF', FFFDx2),
            ('F0 BF 00', FFFD+'\x00'), ('F0 BF 7F', FFFD+'\x7f'),
            ('F0 BF C0', FFFDx2), ('F0 BF FF', FFFDx2),
            ('F0 90 80 00', FFFD+'\x00'), ('F0 90 80 7F', FFFD+'\x7f'),
            ('F0 90 80 C0', FFFDx2), ('F0 90 80 FF', FFFDx2),
            ('F0 90 BF 00', FFFD+'\x00'), ('F0 90 BF 7F', FFFD+'\x7f'),
            ('F0 90 BF C0', FFFDx2), ('F0 90 BF FF', FFFDx2),
            ('F0 BF 80 00', FFFD+'\x00'), ('F0 BF 80 7F', FFFD+'\x7f'),
            ('F0 BF 80 C0', FFFDx2), ('F0 BF 80 FF', FFFDx2),
            ('F0 BF BF 00', FFFD+'\x00'), ('F0 BF BF 7F', FFFD+'\x7f'),
            ('F0 BF BF C0', FFFDx2), ('F0 BF BF FF', FFFDx2),
            ('F1 00', FFFD+'\x00'), ('F1 7F', FFFD+'\x7f'), ('F1 C0', FFFDx2),
            ('F1 FF', FFFDx2), ('F1 80 00', FFFD+'\x00'),
            ('F1 80 7F', FFFD+'\x7f'), ('F1 80 C0', FFFDx2),
            ('F1 80 FF', FFFDx2), ('F1 BF 00', FFFD+'\x00'),
            ('F1 BF 7F', FFFD+'\x7f'), ('F1 BF C0', FFFDx2),
            ('F1 BF FF', FFFDx2), ('F1 80 80 00', FFFD+'\x00'),
            ('F1 80 80 7F', FFFD+'\x7f'), ('F1 80 80 C0', FFFDx2),
            ('F1 80 80 FF', FFFDx2), ('F1 80 BF 00', FFFD+'\x00'),
            ('F1 80 BF 7F', FFFD+'\x7f'), ('F1 80 BF C0', FFFDx2),
            ('F1 80 BF FF', FFFDx2), ('F1 BF 80 00', FFFD+'\x00'),
            ('F1 BF 80 7F', FFFD+'\x7f'), ('F1 BF 80 C0', FFFDx2),
            ('F1 BF 80 FF', FFFDx2), ('F1 BF BF 00', FFFD+'\x00'),
            ('F1 BF BF 7F', FFFD+'\x7f'), ('F1 BF BF C0', FFFDx2),
            ('F1 BF BF FF', FFFDx2), ('F3 00', FFFD+'\x00'),
            ('F3 7F', FFFD+'\x7f'), ('F3 C0', FFFDx2), ('F3 FF', FFFDx2),
            ('F3 80 00', FFFD+'\x00'), ('F3 80 7F', FFFD+'\x7f'),
            ('F3 80 C0', FFFDx2), ('F3 80 FF', FFFDx2),
            ('F3 BF 00', FFFD+'\x00'), ('F3 BF 7F', FFFD+'\x7f'),
            ('F3 BF C0', FFFDx2), ('F3 BF FF', FFFDx2),
            ('F3 80 80 00', FFFD+'\x00'), ('F3 80 80 7F', FFFD+'\x7f'),
            ('F3 80 80 C0', FFFDx2), ('F3 80 80 FF', FFFDx2),
            ('F3 80 BF 00', FFFD+'\x00'), ('F3 80 BF 7F', FFFD+'\x7f'),
            ('F3 80 BF C0', FFFDx2), ('F3 80 BF FF', FFFDx2),
            ('F3 BF 80 00', FFFD+'\x00'), ('F3 BF 80 7F', FFFD+'\x7f'),
            ('F3 BF 80 C0', FFFDx2), ('F3 BF 80 FF', FFFDx2),
            ('F3 BF BF 00', FFFD+'\x00'), ('F3 BF BF 7F', FFFD+'\x7f'),
            ('F3 BF BF C0', FFFDx2), ('F3 BF BF FF', FFFDx2),
            ('F4 00', FFFD+'\x00'), ('F4 7F', FFFD+'\x7f'), ('F4 90', FFFDx2),
            ('F4 BF', FFFDx2), ('F4 C0', FFFDx2), ('F4 FF', FFFDx2),
            ('F4 80 00', FFFD+'\x00'), ('F4 80 7F', FFFD+'\x7f'),
            ('F4 80 C0', FFFDx2), ('F4 80 FF', FFFDx2),
            ('F4 8F 00', FFFD+'\x00'), ('F4 8F 7F', FFFD+'\x7f'),
            ('F4 8F C0', FFFDx2), ('F4 8F FF', FFFDx2),
            ('F4 80 80 00', FFFD+'\x00'), ('F4 80 80 7F', FFFD+'\x7f'),
            ('F4 80 80 C0', FFFDx2), ('F4 80 80 FF', FFFDx2),
            ('F4 80 BF 00', FFFD+'\x00'), ('F4 80 BF 7F', FFFD+'\x7f'),
            ('F4 80 BF C0', FFFDx2), ('F4 80 BF FF', FFFDx2),
            ('F4 8F 80 00', FFFD+'\x00'), ('F4 8F 80 7F', FFFD+'\x7f'),
            ('F4 8F 80 C0', FFFDx2), ('F4 8F 80 FF', FFFDx2),
            ('F4 8F BF 00', FFFD+'\x00'), ('F4 8F BF 7F', FFFD+'\x7f'),
            ('F4 8F BF C0', FFFDx2), ('F4 8F BF FF', FFFDx2)
        ]
        for seq, res in sequences:
            self.assertCorrectUTF8Decoding(bytes.fromhex(seq), res,
                                           'invalid continuation byte')

    def test_codecs_idna(self):
        # Test whether trailing dot is preserved
        self.assertEqual("www.python.org.".encode("idna"), b"www.python.org.")

    def test_codecs_errors(self):
        # Error handling (encoding)
        self.assertRaises(UnicodeError, 'Andr\202 x'.encode, 'ascii')
        self.assertRaises(UnicodeError, 'Andr\202 x'.encode, 'ascii','strict')
        self.assertEqual('Andr\202 x'.encode('ascii','ignore'), b"Andr x")
        self.assertEqual('Andr\202 x'.encode('ascii','replace'), b"Andr? x")
        self.assertEqual('Andr\202 x'.encode('ascii', 'replace'),
                         'Andr\202 x'.encode('ascii', errors='replace'))
        self.assertEqual('Andr\202 x'.encode('ascii', 'ignore'),
                         'Andr\202 x'.encode(encoding='ascii', errors='ignore'))

        # Error handling (decoding)
        self.assertRaises(UnicodeError, str, b'Andr\202 x', 'ascii')
        self.assertRaises(UnicodeError, str, b'Andr\202 x', 'ascii', 'strict')
        self.assertEqual(str(b'Andr\202 x', 'ascii', 'ignore'), "Andr x")
        self.assertEqual(str(b'Andr\202 x', 'ascii', 'replace'), 'Andr\uFFFD x')
        self.assertEqual(str(b'\202 x', 'ascii', 'replace'), '\uFFFD x')

        # Error handling (unknown character names)
        self.assertEqual(b"\\N{foo}xx".decode("unicode-escape", "ignore"), "xx")

        # Error handling (truncated escape sequence)
        self.assertRaises(UnicodeError, b"\\".decode, "unicode-escape")

        self.assertRaises(TypeError, b"hello".decode, "test.unicode1")
        self.assertRaises(TypeError, str, b"hello", "test.unicode2")
        self.assertRaises(TypeError, "hello".encode, "test.unicode1")
        self.assertRaises(TypeError, "hello".encode, "test.unicode2")

        # Error handling (wrong arguments)
        self.assertRaises(TypeError, "hello".encode, 42, 42, 42)

        # Error handling (lone surrogate in
        # _PyUnicode_TransformDecimalAndSpaceToASCII())
        self.assertRaises(ValueError, int, "\ud800")
        self.assertRaises(ValueError, int, "\udf00")
        self.assertRaises(ValueError, float, "\ud800")
        self.assertRaises(ValueError, float, "\udf00")
        self.assertRaises(ValueError, complex, "\ud800")
        self.assertRaises(ValueError, complex, "\udf00")

    def test_codecs(self):
        # Encoding
        self.assertEqual('hello'.encode('ascii'), b'hello')
        self.assertEqual('hello'.encode('utf-7'), b'hello')
        self.assertEqual('hello'.encode('utf-8'), b'hello')
        self.assertEqual('hello'.encode('utf-8'), b'hello')
        self.assertEqual('hello'.encode('utf-16-le'), b'h\000e\000l\000l\000o\000')
        self.assertEqual('hello'.encode('utf-16-be'), b'\000h\000e\000l\000l\000o')
        self.assertEqual('hello'.encode('latin-1'), b'hello')

        # Default encoding is utf-8
        self.assertEqual('\u2603'.encode(), b'\xe2\x98\x83')

        # Roundtrip safety for BMP (just the first 1024 chars)
        for c in range(1024):
            u = chr(c)
            for encoding in ('utf-7', 'utf-8', 'utf-16', 'utf-16-le',
                             'utf-16-be', 'raw_unicode_escape',
                             'unicode_escape'):
                self.assertEqual(str(u.encode(encoding),encoding), u)

        # Roundtrip safety for BMP (just the first 256 chars)
        for c in range(256):
            u = chr(c)
            for encoding in ('latin-1',):
                self.assertEqual(str(u.encode(encoding),encoding), u)

        # Roundtrip safety for BMP (just the first 128 chars)
        for c in range(128):
            u = chr(c)
            for encoding in ('ascii',):
                self.assertEqual(str(u.encode(encoding),encoding), u)

        # Roundtrip safety for non-BMP (just a few chars)
        with warnings.catch_warnings():
            u = '\U00010001\U00020002\U00030003\U00040004\U00050005'
            for encoding in ('utf-8', 'utf-16', 'utf-16-le', 'utf-16-be',
                             'raw_unicode_escape', 'unicode_escape'):
                self.assertEqual(str(u.encode(encoding),encoding), u)

        # UTF-8 must be roundtrip safe for all code points
        # (except surrogates, which are forbidden).
        u = ''.join(map(chr, list(range(0, 0xd800)) +
                             list(range(0xe000, 0x110000))))
        for encoding in ('utf-8',):
            self.assertEqual(str(u.encode(encoding),encoding), u)

    @unittest.skipIf(sys.version_info < (3, 5), 'codecs test requires Py3.5+')
    def test_codecs_charmap(self):
        # 0-127
        s = bytes(range(128))
        for encoding in (
            'cp037', 'cp1026', 'cp273',
            'cp437', 'cp500', 'cp720', 'cp737', 'cp775', 'cp850',
            'cp852', 'cp855', 'cp858', 'cp860', 'cp861', 'cp862',
            'cp863', 'cp865', 'cp866', 'cp1125',
            'iso8859_10', 'iso8859_13', 'iso8859_14', 'iso8859_15',
            'iso8859_2', 'iso8859_3', 'iso8859_4', 'iso8859_5', 'iso8859_6',
            'iso8859_7', 'iso8859_9',
            'koi8_r', 'koi8_t', 'koi8_u', 'kz1048', 'latin_1',
            'mac_cyrillic', 'mac_latin2',

            'cp1250', 'cp1251', 'cp1252', 'cp1253', 'cp1254', 'cp1255',
            'cp1256', 'cp1257', 'cp1258',
            'cp856', 'cp857', 'cp864', 'cp869', 'cp874',

            'mac_greek', 'mac_iceland','mac_roman', 'mac_turkish',
            'cp1006', 'iso8859_8',

            ### These have undefined mappings:
            #'cp424',

            ### These fail the round-trip:
            #'cp875'

            ):
            self.assertEqual(str(s, encoding).encode(encoding), s)

        # 128-255
        s = bytes(range(128, 256))
        for encoding in (
            'cp037', 'cp1026', 'cp273',
            'cp437', 'cp500', 'cp720', 'cp737', 'cp775', 'cp850',
            'cp852', 'cp855', 'cp858', 'cp860', 'cp861', 'cp862',
            'cp863', 'cp865', 'cp866', 'cp1125',
            'iso8859_10', 'iso8859_13', 'iso8859_14', 'iso8859_15',
            'iso8859_2', 'iso8859_4', 'iso8859_5',
            'iso8859_9', 'koi8_r', 'koi8_u', 'latin_1',
            'mac_cyrillic', 'mac_latin2',

            ### These have undefined mappings:
            #'cp1250', 'cp1251', 'cp1252', 'cp1253', 'cp1254', 'cp1255',
            #'cp1256', 'cp1257', 'cp1258',
            #'cp424', 'cp856', 'cp857', 'cp864', 'cp869', 'cp874',
            #'iso8859_3', 'iso8859_6', 'iso8859_7', 'koi8_t', 'kz1048',
            #'mac_greek', 'mac_iceland','mac_roman', 'mac_turkish',

            ### These fail the round-trip:
            #'cp1006', 'cp875', 'iso8859_8',

            ):
            self.assertEqual(str(s, encoding).encode(encoding), s)

    def test_concatenation(self):
        self.assertEqual(("abc" "def"), "abcdef")
        self.assertEqual(("abc" "def"), "abcdef")
        self.assertEqual(("abc" "def"), "abcdef")
        self.assertEqual(("abc" "def" "ghi"), "abcdefghi")
        self.assertEqual(("abc" "def" "ghi"), "abcdefghi")

    def test_printing(self):
        class BitBucket:
            def write(self, text):
                pass

        out = BitBucket()
        print('abc', file=out)
        print('abc', 'def', file=out)
        print('abc', 'def', file=out)
        print('abc', 'def', file=out)
        print('abc\n', file=out)
        print('abc\n', end=' ', file=out)
        print('abc\n', end=' ', file=out)
        print('def\n', file=out)
        print('def\n', file=out)

    def test_ucs4(self):
        x = '\U00100000'
        y = x.encode("raw-unicode-escape").decode("raw-unicode-escape")
        self.assertEqual(x, y)

        y = br'\U00100000'
        x = y.decode("raw-unicode-escape").encode("raw-unicode-escape")
        self.assertEqual(x, y)
        y = br'\U00010000'
        x = y.decode("raw-unicode-escape").encode("raw-unicode-escape")
        self.assertEqual(x, y)

        try:
            br'\U11111111'.decode("raw-unicode-escape")
        except UnicodeDecodeError as e:
            self.assertEqual(e.start, 0)
            self.assertEqual(e.end, 10)
        else:
            self.fail("Should have raised UnicodeDecodeError")

    def test_conversion(self):
        # Make sure __str__() works properly
        class ObjectToStr:
            def __str__(self):
                return "foo"

        class StrSubclassToStr(str):
            def __str__(self):
                return "foo"

        class StrSubclassToStrSubclass(str):
            def __new__(cls, content=""):
                return str.__new__(cls, 2*content)
            def __str__(self):
                return self

        self.assertEqual(str(ObjectToStr()), "foo")
        self.assertEqual(str(StrSubclassToStr("bar")), "foo")
        s = str(StrSubclassToStrSubclass("foo"))
        self.assertEqual(s, "foofoo")
        self.assertIs(type(s), StrSubclassToStrSubclass)
        s = StrSubclass(StrSubclassToStrSubclass("foo"))
        self.assertEqual(s, "foofoo")
        self.assertIs(type(s), StrSubclass)

    def test_unicode_repr(self):
        class s1:
            def __repr__(self):
                return '\\n'

        class s2:
            def __repr__(self):
                return '\\n'

        self.assertEqual(repr(s1()), '\\n')
        self.assertEqual(repr(s2()), '\\n')

    def test_printable_repr(self):
        self.assertEqual(repr('\U00010000'), "'%c'" % (0x10000,)) # printable
        self.assertEqual(repr('\U00014000'), "'\\U00014000'")     # nonprintable

    # This test only affects 32-bit platforms because expandtabs can only take
    # an int as the max value, not a 64-bit C long.  If expandtabs is changed
    # to take a 64-bit long, this test should apply to all platforms.
    @unittest.skipIf(sys.maxsize > (1 << 32) or struct.calcsize('P') != 4,
                     'only applies to 32-bit platforms')
    def test_expandtabs_overflows_gracefully(self):
        self.assertRaises(OverflowError, 't\tt\t'.expandtabs, sys.maxsize)

    @support.cpython_only
    def test_expandtabs_optimization(self):
        s = 'abc'
        self.assertIs(s.expandtabs(), s)

    def test_raiseMemError(self):
        if struct.calcsize('P') == 8:
            # 64 bits pointers
            ascii_struct_size = 48
            compact_struct_size = 72
        else:
            # 32 bits pointers
            ascii_struct_size = 24
            compact_struct_size = 36

        for char in ('a', '\xe9', '\u20ac', '\U0010ffff'):
            code = ord(char)
            if code < 0x100:
                char_size = 1  # sizeof(Py_UCS1)
                struct_size = ascii_struct_size
            elif code < 0x10000:
                char_size = 2  # sizeof(Py_UCS2)
                struct_size = compact_struct_size
            else:
                char_size = 4  # sizeof(Py_UCS4)
                struct_size = compact_struct_size
            # Note: sys.maxsize is half of the actual max allocation because of
            # the signedness of Py_ssize_t. Strings of maxlen-1 should in principle
            # be allocatable, given enough memory.
            maxlen = ((sys.maxsize - struct_size) // char_size)
            alloc = lambda: char * maxlen
            self.assertRaises(MemoryError, alloc)
            self.assertRaises(MemoryError, alloc)

    def test_format_subclass(self):
        class S(str):
            def __str__(self):
                return '__str__ overridden'
        s = S('xxx')
        self.assertEqual("%s" % s, '__str__ overridden')
        self.assertEqual("{}".format(s), '__str__ overridden')

    def test_subclass_add(self):
        class S(str):
            def __add__(self, o):
                return "3"
        self.assertEqual(S("4") + S("5"), "3")
        class S(str):
            def __iadd__(self, o):
                return "3"
        s = S("1")
        s += "4"
        self.assertEqual(s, "3")

    def _test_getnewargs(self):
        text = 'abc'
        args = text.__getnewargs__()
        self.assertIsNot(args[0], text)
        self.assertEqual(args[0], text)
        self.assertEqual(len(args), 1)

    @unittest.skipIf(sys.version_info < (3, 8), 'resize test requires Py3.8+')
    @support.cpython_only
    def test_resize(self):
        from _testcapi import getargs_u
        for length in range(1, 100, 7):
            # generate a fresh string (refcount=1)
            text = 'a' * length + 'b'

            # fill wstr internal field
            abc = getargs_u(text)
            self.assertEqual(abc, text)

            # resize text: wstr field must be cleared and then recomputed
            text += 'c'
            abcdef = getargs_u(text)
            self.assertNotEqual(abc, abcdef)
            self.assertEqual(abcdef, text)

    def test_compare(self):
        # Issue #17615
        N = 10
        ascii = 'a' * N
        ascii2 = 'z' * N
        latin = '\x80' * N
        latin2 = '\xff' * N
        bmp = '\u0100' * N
        bmp2 = '\uffff' * N
        astral = '\U00100000' * N
        astral2 = '\U0010ffff' * N
        strings = (
            ascii, ascii2,
            latin, latin2,
            bmp, bmp2,
            astral, astral2)
        for text1, text2 in itertools.combinations(strings, 2):
            equal = (text1 is text2)
            self.assertEqual(text1 == text2, equal)
            self.assertEqual(text1 != text2, not equal)

            if equal:
                self.assertTrue(text1 <= text2)
                self.assertTrue(text1 >= text2)

                # text1 is text2: duplicate strings to skip the "str1 == str2"
                # optimization in unicode_compare_eq() and really compare
                # character per character
                copy1 = duplicate_string(text1)
                copy2 = duplicate_string(text2)
                self.assertIsNot(copy1, copy2)

                self.assertTrue(copy1 == copy2)
                self.assertFalse(copy1 != copy2)

                self.assertTrue(copy1 <= copy2)
                self.assertTrue(copy2 >= copy2)

        self.assertTrue(ascii < ascii2)
        self.assertTrue(ascii < latin)
        self.assertTrue(ascii < bmp)
        self.assertTrue(ascii < astral)
        self.assertFalse(ascii >= ascii2)
        self.assertFalse(ascii >= latin)
        self.assertFalse(ascii >= bmp)
        self.assertFalse(ascii >= astral)

        self.assertFalse(latin < ascii)
        self.assertTrue(latin < latin2)
        self.assertTrue(latin < bmp)
        self.assertTrue(latin < astral)
        self.assertTrue(latin >= ascii)
        self.assertFalse(latin >= latin2)
        self.assertFalse(latin >= bmp)
        self.assertFalse(latin >= astral)

        self.assertFalse(bmp < ascii)
        self.assertFalse(bmp < latin)
        self.assertTrue(bmp < bmp2)
        self.assertTrue(bmp < astral)
        self.assertTrue(bmp >= ascii)
        self.assertTrue(bmp >= latin)
        self.assertFalse(bmp >= bmp2)
        self.assertFalse(bmp >= astral)

        self.assertFalse(astral < ascii)
        self.assertFalse(astral < latin)
        self.assertFalse(astral < bmp2)
        self.assertTrue(astral < astral2)
        self.assertTrue(astral >= ascii)
        self.assertTrue(astral >= latin)
        self.assertTrue(astral >= bmp2)
        self.assertFalse(astral >= astral2)

    def test_free_after_iterating(self):
        support.check_free_after_iterating(self, iter, str)
        support.check_free_after_iterating(self, reversed, str)


u"""
class CAPITest(unittest.TestCase):

    # Test PyUnicode_FromFormat()
    def test_from_format(self):
        support.import_module('ctypes')
        from ctypes import (
            pythonapi, py_object, sizeof,
            c_int, c_long, c_longlong, c_ssize_t,
            c_uint, c_ulong, c_ulonglong, c_size_t, c_void_p)
        name = "PyUnicode_FromFormat"
        _PyUnicode_FromFormat = getattr(pythonapi, name)
        _PyUnicode_FromFormat.restype = py_object

        def PyUnicode_FromFormat(format, *args):
            cargs = tuple(
                py_object(arg) if isinstance(arg, str) else arg
                for arg in args)
            return _PyUnicode_FromFormat(format, *cargs)

        def check_format(expected, format, *args):
            text = PyUnicode_FromFormat(format, *args)
            self.assertEqual(expected, text)

        # ascii format, non-ascii argument
        check_format('ascii\x7f=unicode\xe9',
                     b'ascii\x7f=%U', 'unicode\xe9')

        # non-ascii format, ascii argument: ensure that PyUnicode_FromFormatV()
        # raises an error
        self.assertRaisesRegex(ValueError,
            r'^PyUnicode_FromFormatV\(\) expects an ASCII-encoded format '
            'string, got a non-ASCII byte: 0xe9$',
            PyUnicode_FromFormat, b'unicode\xe9=%s', 'ascii')

        # test "%c"
        check_format('\uabcd',
                     b'%c', c_int(0xabcd))
        check_format('\U0010ffff',
                     b'%c', c_int(0x10ffff))
        with self.assertRaises(OverflowError):
            PyUnicode_FromFormat(b'%c', c_int(0x110000))
        # Issue #18183
        check_format('\U00010000\U00100000',
                     b'%c%c', c_int(0x10000), c_int(0x100000))

        # test "%"
        check_format('%',
                     b'%')
        check_format('%',
                     b'%%')
        check_format('%s',
                     b'%%s')
        check_format('[%]',
                     b'[%%]')
        check_format('%abc',
                     b'%%%s', b'abc')

        # truncated string
        check_format('abc',
                     b'%.3s', b'abcdef')
        check_format('abc[\ufffd',
                     b'%.5s', 'abc[\u20ac]'.encode('utf8'))
        check_format("'\\u20acABC'",
                     b'%A', '\u20acABC')
        check_format("'\\u20",
                     b'%.5A', '\u20acABCDEF')
        check_format("'\u20acABC'",
                     b'%R', '\u20acABC')
        check_format("'\u20acA",
                     b'%.3R', '\u20acABCDEF')
        check_format('\u20acAB',
                     b'%.3S', '\u20acABCDEF')
        check_format('\u20acAB',
                     b'%.3U', '\u20acABCDEF')
        check_format('\u20acAB',
                     b'%.3V', '\u20acABCDEF', None)
        check_format('abc[\ufffd',
                     b'%.5V', None, 'abc[\u20ac]'.encode('utf8'))

        # following tests comes from #7330
        # test width modifier and precision modifier with %S
        check_format("repr=  abc",
                     b'repr=%5S', 'abc')
        check_format("repr=ab",
                     b'repr=%.2S', 'abc')
        check_format("repr=   ab",
                     b'repr=%5.2S', 'abc')

        # test width modifier and precision modifier with %R
        check_format("repr=   'abc'",
                     b'repr=%8R', 'abc')
        check_format("repr='ab",
                     b'repr=%.3R', 'abc')
        check_format("repr=  'ab",
                     b'repr=%5.3R', 'abc')

        # test width modifier and precision modifier with %A
        check_format("repr=   'abc'",
                     b'repr=%8A', 'abc')
        check_format("repr='ab",
                     b'repr=%.3A', 'abc')
        check_format("repr=  'ab",
                     b'repr=%5.3A', 'abc')

        # test width modifier and precision modifier with %s
        check_format("repr=  abc",
                     b'repr=%5s', b'abc')
        check_format("repr=ab",
                     b'repr=%.2s', b'abc')
        check_format("repr=   ab",
                     b'repr=%5.2s', b'abc')

        # test width modifier and precision modifier with %U
        check_format("repr=  abc",
                     b'repr=%5U', 'abc')
        check_format("repr=ab",
                     b'repr=%.2U', 'abc')
        check_format("repr=   ab",
                     b'repr=%5.2U', 'abc')

        # test width modifier and precision modifier with %V
        check_format("repr=  abc",
                     b'repr=%5V', 'abc', b'123')
        check_format("repr=ab",
                     b'repr=%.2V', 'abc', b'123')
        check_format("repr=   ab",
                     b'repr=%5.2V', 'abc', b'123')
        check_format("repr=  123",
                     b'repr=%5V', None, b'123')
        check_format("repr=12",
                     b'repr=%.2V', None, b'123')
        check_format("repr=   12",
                     b'repr=%5.2V', None, b'123')

        # test integer formats (%i, %d, %u)
        check_format('010',
                     b'%03i', c_int(10))
        check_format('0010',
                     b'%0.4i', c_int(10))
        check_format('-123',
                     b'%i', c_int(-123))
        check_format('-123',
                     b'%li', c_long(-123))
        check_format('-123',
                     b'%lli', c_longlong(-123))
        check_format('-123',
                     b'%zi', c_ssize_t(-123))

        check_format('-123',
                     b'%d', c_int(-123))
        check_format('-123',
                     b'%ld', c_long(-123))
        check_format('-123',
                     b'%lld', c_longlong(-123))
        check_format('-123',
                     b'%zd', c_ssize_t(-123))

        check_format('123',
                     b'%u', c_uint(123))
        check_format('123',
                     b'%lu', c_ulong(123))
        check_format('123',
                     b'%llu', c_ulonglong(123))
        check_format('123',
                     b'%zu', c_size_t(123))

        # test long output
        min_longlong = -(2 ** (8 * sizeof(c_longlong) - 1))
        max_longlong = -min_longlong - 1
        check_format(str(min_longlong),
                     b'%lld', c_longlong(min_longlong))
        check_format(str(max_longlong),
                     b'%lld', c_longlong(max_longlong))
        max_ulonglong = 2 ** (8 * sizeof(c_ulonglong)) - 1
        check_format(str(max_ulonglong),
                     b'%llu', c_ulonglong(max_ulonglong))
        PyUnicode_FromFormat(b'%p', c_void_p(-1))

        # test padding (width and/or precision)
        check_format('123'.rjust(10, '0'),
                     b'%010i', c_int(123))
        check_format('123'.rjust(100),
                     b'%100i', c_int(123))
        check_format('123'.rjust(100, '0'),
                     b'%.100i', c_int(123))
        check_format('123'.rjust(80, '0').rjust(100),
                     b'%100.80i', c_int(123))

        check_format('123'.rjust(10, '0'),
                     b'%010u', c_uint(123))
        check_format('123'.rjust(100),
                     b'%100u', c_uint(123))
        check_format('123'.rjust(100, '0'),
                     b'%.100u', c_uint(123))
        check_format('123'.rjust(80, '0').rjust(100),
                     b'%100.80u', c_uint(123))

        check_format('123'.rjust(10, '0'),
                     b'%010x', c_int(0x123))
        check_format('123'.rjust(100),
                     b'%100x', c_int(0x123))
        check_format('123'.rjust(100, '0'),
                     b'%.100x', c_int(0x123))
        check_format('123'.rjust(80, '0').rjust(100),
                     b'%100.80x', c_int(0x123))

        # test %A
        check_format(r"%A:'abc\xe9\uabcd\U0010ffff'",
                     b'%%A:%A', 'abc\xe9\uabcd\U0010ffff')

        # test %V
        check_format('repr=abc',
                     b'repr=%V', 'abc', b'xyz')

        # Test string decode from parameter of %s using utf-8.
        # b'\xe4\xba\xba\xe6\xb0\x91' is utf-8 encoded byte sequence of
        # '\u4eba\u6c11'
        check_format('repr=\u4eba\u6c11',
                     b'repr=%V', None, b'\xe4\xba\xba\xe6\xb0\x91')

        #Test replace error handler.
        check_format('repr=abc\ufffd',
                     b'repr=%V', None, b'abc\xff')

        # not supported: copy the raw format string. these tests are just here
        # to check for crashes and should not be considered as specifications
        check_format('%s',
                     b'%1%s', b'abc')
        check_format('%1abc',
                     b'%1abc')
        check_format('%+i',
                     b'%+i', c_int(10))
        check_format('%.%s',
                     b'%.%s', b'abc')

        # Issue #33817: empty strings
        check_format('',
                     b'')
        check_format('',
                     b'%s', b'')

    # Test PyUnicode_AsWideChar()
    @support.cpython_only
    def test_aswidechar(self):
        from _testcapi import unicode_aswidechar
        support.import_module('ctypes')
        from ctypes import c_wchar, sizeof

        wchar, size = unicode_aswidechar('abcdef', 2)
        self.assertEqual(size, 2)
        self.assertEqual(wchar, 'ab')

        wchar, size = unicode_aswidechar('abc', 3)
        self.assertEqual(size, 3)
        self.assertEqual(wchar, 'abc')

        wchar, size = unicode_aswidechar('abc', 4)
        self.assertEqual(size, 3)
        self.assertEqual(wchar, 'abc\0')

        wchar, size = unicode_aswidechar('abc', 10)
        self.assertEqual(size, 3)
        self.assertEqual(wchar, 'abc\0')

        wchar, size = unicode_aswidechar('abc\0def', 20)
        self.assertEqual(size, 7)
        self.assertEqual(wchar, 'abc\0def\0')

        nonbmp = chr(0x10ffff)
        if sizeof(c_wchar) == 2:
            buflen = 3
            nchar = 2
        else: # sizeof(c_wchar) == 4
            buflen = 2
            nchar = 1
        wchar, size = unicode_aswidechar(nonbmp, buflen)
        self.assertEqual(size, nchar)
        self.assertEqual(wchar, nonbmp + '\0')

    # Test PyUnicode_AsWideCharString()
    @support.cpython_only
    def test_aswidecharstring(self):
        from _testcapi import unicode_aswidecharstring
        support.import_module('ctypes')
        from ctypes import c_wchar, sizeof

        wchar, size = unicode_aswidecharstring('abc')
        self.assertEqual(size, 3)
        self.assertEqual(wchar, 'abc\0')

        wchar, size = unicode_aswidecharstring('abc\0def')
        self.assertEqual(size, 7)
        self.assertEqual(wchar, 'abc\0def\0')

        nonbmp = chr(0x10ffff)
        if sizeof(c_wchar) == 2:
            nchar = 2
        else: # sizeof(c_wchar) == 4
            nchar = 1
        wchar, size = unicode_aswidecharstring(nonbmp)
        self.assertEqual(size, nchar)
        self.assertEqual(wchar, nonbmp + '\0')

    # Test PyUnicode_AsUCS4()
    @support.cpython_only
    def test_asucs4(self):
        from _testcapi import unicode_asucs4
        for s in ['abc', '\xa1\xa2', '\u4f60\u597d', 'a\U0001f600',
                  'a\ud800b\udfffc', '\ud834\udd1e']:
            l = len(s)
            self.assertEqual(unicode_asucs4(s, l, 1), s+'\0')
            self.assertEqual(unicode_asucs4(s, l, 0), s+'\uffff')
            self.assertEqual(unicode_asucs4(s, l+1, 1), s+'\0\uffff')
            self.assertEqual(unicode_asucs4(s, l+1, 0), s+'\0\uffff')
            self.assertRaises(SystemError, unicode_asucs4, s, l-1, 1)
            self.assertRaises(SystemError, unicode_asucs4, s, l-2, 0)
            s = '\0'.join([s, s])
            self.assertEqual(unicode_asucs4(s, len(s), 1), s+'\0')
            self.assertEqual(unicode_asucs4(s, len(s), 0), s+'\uffff')

    # Test PyUnicode_FindChar()
    @support.cpython_only
    def test_findchar(self):
        from _testcapi import unicode_findchar

        for str in "\xa1", "\u8000\u8080", "\ud800\udc02", "\U0001f100\U0001f1f1":
            for i, ch in enumerate(str):
                self.assertEqual(unicode_findchar(str, ord(ch), 0, len(str), 1), i)
                self.assertEqual(unicode_findchar(str, ord(ch), 0, len(str), -1), i)

        str = "!>_= end
        self.assertEqual(unicode_findchar(str, ord('!'), 0, 0, 1), -1)
        self.assertEqual(unicode_findchar(str, ord('!'), len(str), 0, 1), -1)
        # negative
        self.assertEqual(unicode_findchar(str, ord('!'), -len(str), -1, 1), 0)
        self.assertEqual(unicode_findchar(str, ord('!'), -len(str), -1, -1), 0)

    # Test PyUnicode_CopyCharacters()
    @support.cpython_only
    def test_copycharacters(self):
        from _testcapi import unicode_copycharacters

        strings = [
            'abcde', '\xa1\xa2\xa3\xa4\xa5',
            '\u4f60\u597d\u4e16\u754c\uff01',
            '\U0001f600\U0001f601\U0001f602\U0001f603\U0001f604'
        ]

        for idx, from_ in enumerate(strings):
            # wide -> narrow: exceed maxchar limitation
            for to in strings[:idx]:
                self.assertRaises(
                    SystemError,
                    unicode_copycharacters, to, 0, from_, 0, 5
                )
            # same kind
            for from_start in range(5):
                self.assertEqual(
                    unicode_copycharacters(from_, 0, from_, from_start, 5),
                    (from_[from_start:from_start+5].ljust(5, '\0'),
                     5-from_start)
                )
            for to_start in range(5):
                self.assertEqual(
                    unicode_copycharacters(from_, to_start, from_, to_start, 5),
                    (from_[to_start:to_start+5].rjust(5, '\0'),
                     5-to_start)
                )
            # narrow -> wide
            # Tests omitted since this creates invalid strings.

        s = strings[0]
        self.assertRaises(IndexError, unicode_copycharacters, s, 6, s, 0, 5)
        self.assertRaises(IndexError, unicode_copycharacters, s, -1, s, 0, 5)
        self.assertRaises(IndexError, unicode_copycharacters, s, 0, s, 6, 5)
        self.assertRaises(IndexError, unicode_copycharacters, s, 0, s, -1, 5)
        self.assertRaises(SystemError, unicode_copycharacters, s, 1, s, 0, 5)
        self.assertRaises(SystemError, unicode_copycharacters, s, 0, s, 0, -1)
        self.assertRaises(SystemError, unicode_copycharacters, s, 0, b'', 0, 0)

    @support.cpython_only
    def test_encode_decimal(self):
        from _testcapi import unicode_encodedecimal
        self.assertEqual(unicode_encodedecimal('123'),
                         b'123')
        self.assertEqual(unicode_encodedecimal('\u0663.\u0661\u0664'),
                         b'3.14')
        self.assertEqual(unicode_encodedecimal("\N{EM SPACE}3.14\N{EN SPACE}"),
                         b' 3.14 ')
        self.assertRaises(UnicodeEncodeError,
                          unicode_encodedecimal, "123\u20ac", "strict")
        self.assertRaisesRegex(
            ValueError,
            "^'decimal' codec can't encode character",
            unicode_encodedecimal, "123\u20ac", "replace")

    @support.cpython_only
    def test_transform_decimal(self):
        from _testcapi import unicode_transformdecimaltoascii as transform_decimal
        self.assertEqual(transform_decimal('123'),
                         '123')
        self.assertEqual(transform_decimal('\u0663.\u0661\u0664'),
                         '3.14')
        self.assertEqual(transform_decimal("\N{EM SPACE}3.14\N{EN SPACE}"),
                         "\N{EM SPACE}3.14\N{EN SPACE}")
        self.assertEqual(transform_decimal('123\u20ac'),
                         '123\u20ac')

    @support.cpython_only
    def test_pep393_utf8_caching_bug(self):
        # Issue #25709: Problem with string concatenation and utf-8 cache
        from _testcapi import getargs_s_hash
        for k in 0x24, 0xa4, 0x20ac, 0x1f40d:
            s = ''
            for i in range(5):
                # Due to CPython specific optimization the 's' string can be
                # resized in-place.
                s += chr(k)
                # Parsing with the "s#" format code calls indirectly
                # PyUnicode_AsUTF8AndSize() which creates the UTF-8
                # encoded string cached in the Unicode object.
                self.assertEqual(getargs_s_hash(s), chr(k).encode() * (i + 1))
                # Check that the second call returns the same result
                self.assertEqual(getargs_s_hash(s), chr(k).encode() * (i + 1))
"""


u"""
class StringModuleTest(unittest.TestCase):
    def test_formatter_parser(self):
        def parse(format):
            return list(_string.formatter_parser(format))

        formatter = parse("prefix {2!s}xxx{0:^+10.3f}{obj.attr!s} {z[0]!s:10}")
        self.assertEqual(formatter, [
            ('prefix ', '2', '', 's'),
            ('xxx', '0', '^+10.3f', None),
            ('', 'obj.attr', '', 's'),
            (' ', 'z[0]', '10', 's'),
        ])

        formatter = parse("prefix {} suffix")
        self.assertEqual(formatter, [
            ('prefix ', '', '', None),
            (' suffix', None, None, None),
        ])

        formatter = parse("str")
        self.assertEqual(formatter, [
            ('str', None, None, None),
        ])

        formatter = parse("")
        self.assertEqual(formatter, [])

        formatter = parse("{0}")
        self.assertEqual(formatter, [
            ('', '0', '', None),
        ])

        self.assertRaises(TypeError, _string.formatter_parser, 1)

    def test_formatter_field_name_split(self):
        def split(name):
            items = list(_string.formatter_field_name_split(name))
            items[1] = list(items[1])
            return items
        self.assertEqual(split("obj"), ["obj", []])
        self.assertEqual(split("obj.arg"), ["obj", [(True, 'arg')]])
        self.assertEqual(split("obj[key]"), ["obj", [(False, 'key')]])
        self.assertEqual(split("obj.arg[key1][key2]"), [
            "obj",
            [(True, 'arg'),
             (False, 'key1'),
             (False, 'key2'),
            ]])
        self.assertRaises(TypeError, _string.formatter_field_name_split, 1)
"""


if __name__ == "__main__":
    unittest.main()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/test_unicode_string_tests.pxi0000644000175100001770000020245700000000000023573 0ustar00runnerdocker00000000000000"""
Common tests shared by test_unicode, test_userstring and test_bytes.
"""

import unittest, string, sys, struct
#from test import support
#from collections import UserList

class Sequence:
    def __init__(self, seq='wxyz'): self.seq = seq
    def __len__(self): return len(self.seq)
    def __getitem__(self, i): return self.seq[i]

class BadSeq1(Sequence):
    def __init__(self): self.seq = [7, 'hello', 123]
    def __str__(self): return '{0} {1} {2}'.format(*self.seq)

class BadSeq2(Sequence):
    def __init__(self): self.seq = ['a', 'b', 'c']
    def __len__(self): return 8

class BaseTest:
    # These tests are for buffers of values (bytes) and not
    # specific to character interpretation, used for bytes objects
    # and various string implementations

    # The type to be tested
    # Change in subclasses to change the behaviour of fixtesttype()
    type2test = None

    # Whether the "contained items" of the container are integers in
    # range(0, 256) (i.e. bytes, bytearray) or strings of length 1
    # (str)
    contains_bytes = False

    # All tests pass their arguments to the testing methods
    # as str objects. fixtesttype() can be used to propagate
    # these arguments to the appropriate type
    def fixtype(self, obj):
        if isinstance(obj, str):
            return self.__class__.type2test(obj)
        elif isinstance(obj, list):
            return [self.fixtype(x) for x in obj]
        elif isinstance(obj, tuple):
            return tuple([self.fixtype(x) for x in obj])
        elif isinstance(obj, dict):
            return dict([
               (self.fixtype(key), self.fixtype(value))
               for (key, value) in obj.items()
            ])
        else:
            return obj

    def test_fixtype(self):
        self.assertIs(type(self.fixtype("123")), self.type2test)

    # check that obj.method(*args) returns result
    def checkequal(self, result, obj, methodname, *args, **kwargs):
        result = self.fixtype(result)
        obj = self.fixtype(obj)
        args = self.fixtype(args)
        kwargs = {k: self.fixtype(v) for k,v in kwargs.items()}
        realresult = getattr(obj, methodname)(*args, **kwargs)
        self.assertEqual(
            result,
            realresult
        )
        # if the original is returned make sure that
        # this doesn't happen with subclasses
        if obj is realresult:
            try:
                class subtype(self.__class__.type2test):
                    pass
            except TypeError:
                pass  # Skip this if we can't subclass
            else:
                obj = subtype(obj)
                realresult = getattr(obj, methodname)(*args)
                self.assertIsNot(obj, realresult)

    # check that obj.method(*args) raises exc
    def checkraises(self, exc, obj, methodname, *args):
        obj = self.fixtype(obj)
        args = self.fixtype(args)
        with self.assertRaises(exc) as cm:
            getattr(obj, methodname)(*args)
        self.assertNotEqual(str(cm.exception), '')

    # call obj.method(*args) without any checks
    def checkcall(self, obj, methodname, *args):
        obj = self.fixtype(obj)
        args = self.fixtype(args)
        getattr(obj, methodname)(*args)

    def test_count(self):
        self.checkequal(3, 'aaa', 'count', 'a')
        self.checkequal(0, 'aaa', 'count', 'b')
        self.checkequal(3, 'aaa', 'count', 'a')
        self.checkequal(0, 'aaa', 'count', 'b')
        self.checkequal(3, 'aaa', 'count', 'a')
        self.checkequal(0, 'aaa', 'count', 'b')
        self.checkequal(0, 'aaa', 'count', 'b')
        self.checkequal(2, 'aaa', 'count', 'a', 1)
        self.checkequal(0, 'aaa', 'count', 'a', 10)
        self.checkequal(1, 'aaa', 'count', 'a', -1)
        self.checkequal(3, 'aaa', 'count', 'a', -10)
        self.checkequal(1, 'aaa', 'count', 'a', 0, 1)
        self.checkequal(3, 'aaa', 'count', 'a', 0, 10)
        self.checkequal(2, 'aaa', 'count', 'a', 0, -1)
        self.checkequal(0, 'aaa', 'count', 'a', 0, -10)
        self.checkequal(3, 'aaa', 'count', '', 1)
        self.checkequal(1, 'aaa', 'count', '', 3)
        self.checkequal(0, 'aaa', 'count', '', 10)
        self.checkequal(2, 'aaa', 'count', '', -1)
        self.checkequal(4, 'aaa', 'count', '', -10)

        self.checkequal(1, '', 'count', '')
        self.checkequal(0, '', 'count', '', 1, 1)
        self.checkequal(0, '', 'count', '', sys.maxsize, 0)

        self.checkequal(0, '', 'count', 'xx')
        self.checkequal(0, '', 'count', 'xx', 1, 1)
        self.checkequal(0, '', 'count', 'xx', sys.maxsize, 0)

        self.checkraises(TypeError, 'hello', 'count')

        if self.contains_bytes:
            self.checkequal(0, 'hello', 'count', 42)
        else:
            self.checkraises(TypeError, 'hello', 'count', 42)

        # For a variety of combinations,
        #    verify that str.count() matches an equivalent function
        #    replacing all occurrences and then differencing the string lengths
        charset = ['', 'a', 'b']
        digits = 7
        base = len(charset)
        teststrings = set()
        for i in range(base ** digits):
            entry = []
            for j in range(digits):
                i, m = divmod(i, base)
                entry.append(charset[m])
            teststrings.add(''.join(entry))
        teststrings = [self.fixtype(ts) for ts in teststrings]
        for i in teststrings:
            n = len(i)
            for j in teststrings:
                r1 = i.count(j)
                if j:
                    r2, rem = divmod(n - len(i.replace(j, self.fixtype(''))),
                                     len(j))
                else:
                    r2, rem = len(i)+1, 0
                if rem or r1 != r2:
                    self.assertEqual(rem, 0, '%s != 0 for %s' % (rem, i))
                    self.assertEqual(r1, r2, '%s != %s for %s' % (r1, r2, i))

    def test_find(self):
        self.checkequal(0, 'abcdefghiabc', 'find', 'abc')
        self.checkequal(9, 'abcdefghiabc', 'find', 'abc', 1)
        self.checkequal(-1, 'abcdefghiabc', 'find', 'def', 4)

        self.checkequal(0, 'abc', 'find', '', 0)
        self.checkequal(3, 'abc', 'find', '', 3)
        self.checkequal(-1, 'abc', 'find', '', 4)

        # to check the ability to pass None as defaults
        self.checkequal( 2, 'rrarrrrrrrrra', 'find', 'a')
        self.checkequal(12, 'rrarrrrrrrrra', 'find', 'a', 4)
        self.checkequal(-1, 'rrarrrrrrrrra', 'find', 'a', 4, 6)
        self.checkequal(12, 'rrarrrrrrrrra', 'find', 'a', 4, None)
        self.checkequal( 2, 'rrarrrrrrrrra', 'find', 'a', None, 6)

        self.checkraises(TypeError, 'hello', 'find')

        if self.contains_bytes:
            self.checkequal(-1, 'hello', 'find', 42)
        else:
            self.checkraises(TypeError, 'hello', 'find', 42)

        self.checkequal(0, '', 'find', '')
        self.checkequal(-1, '', 'find', '', 1, 1)
        self.checkequal(-1, '', 'find', '', sys.maxsize, 0)

        self.checkequal(-1, '', 'find', 'xx')
        self.checkequal(-1, '', 'find', 'xx', 1, 1)
        self.checkequal(-1, '', 'find', 'xx', sys.maxsize, 0)

        # issue 7458
        self.checkequal(-1, 'ab', 'find', 'xxx', sys.maxsize + 1, 0)

        # For a variety of combinations,
        #    verify that str.find() matches __contains__
        #    and that the found substring is really at that location
        charset = ['', 'a', 'b', 'c']
        digits = 5
        base = len(charset)
        teststrings = set()
        for i in range(base ** digits):
            entry = []
            for j in range(digits):
                i, m = divmod(i, base)
                entry.append(charset[m])
            teststrings.add(''.join(entry))
        teststrings = [self.fixtype(ts) for ts in teststrings]
        for i in teststrings:
            for j in teststrings:
                loc = i.find(j)
                r1 = (loc != -1)
                r2 = j in i
                self.assertEqual(r1, r2)
                if loc != -1:
                    self.assertEqual(i[loc:loc+len(j)], j)

    def test_rfind(self):
        self.checkequal(9,  'abcdefghiabc', 'rfind', 'abc')
        self.checkequal(12, 'abcdefghiabc', 'rfind', '')
        self.checkequal(0, 'abcdefghiabc', 'rfind', 'abcd')
        self.checkequal(-1, 'abcdefghiabc', 'rfind', 'abcz')

        self.checkequal(3, 'abc', 'rfind', '', 0)
        self.checkequal(3, 'abc', 'rfind', '', 3)
        self.checkequal(-1, 'abc', 'rfind', '', 4)

        # to check the ability to pass None as defaults
        self.checkequal(12, 'rrarrrrrrrrra', 'rfind', 'a')
        self.checkequal(12, 'rrarrrrrrrrra', 'rfind', 'a', 4)
        self.checkequal(-1, 'rrarrrrrrrrra', 'rfind', 'a', 4, 6)
        self.checkequal(12, 'rrarrrrrrrrra', 'rfind', 'a', 4, None)
        self.checkequal( 2, 'rrarrrrrrrrra', 'rfind', 'a', None, 6)

        self.checkraises(TypeError, 'hello', 'rfind')

        if self.contains_bytes:
            self.checkequal(-1, 'hello', 'rfind', 42)
        else:
            self.checkraises(TypeError, 'hello', 'rfind', 42)

        # For a variety of combinations,
        #    verify that str.rfind() matches __contains__
        #    and that the found substring is really at that location
        charset = ['', 'a', 'b', 'c']
        digits = 5
        base = len(charset)
        teststrings = set()
        for i in range(base ** digits):
            entry = []
            for j in range(digits):
                i, m = divmod(i, base)
                entry.append(charset[m])
            teststrings.add(''.join(entry))
        teststrings = [self.fixtype(ts) for ts in teststrings]
        for i in teststrings:
            for j in teststrings:
                loc = i.rfind(j)
                r1 = (loc != -1)
                r2 = j in i
                self.assertEqual(r1, r2)
                if loc != -1:
                    self.assertEqual(i[loc:loc+len(j)], j)

        # issue 7458
        self.checkequal(-1, 'ab', 'rfind', 'xxx', sys.maxsize + 1, 0)

        # issue #15534
        self.checkequal(0, '<......\u043c...', "rfind", "<")

    def test_index(self):
        self.checkequal(0, 'abcdefghiabc', 'index', '')
        self.checkequal(3, 'abcdefghiabc', 'index', 'def')
        self.checkequal(0, 'abcdefghiabc', 'index', 'abc')
        self.checkequal(9, 'abcdefghiabc', 'index', 'abc', 1)

        self.checkraises(ValueError, 'abcdefghiabc', 'index', 'hib')
        self.checkraises(ValueError, 'abcdefghiab', 'index', 'abc', 1)
        self.checkraises(ValueError, 'abcdefghi', 'index', 'ghi', 8)
        self.checkraises(ValueError, 'abcdefghi', 'index', 'ghi', -1)

        # to check the ability to pass None as defaults
        self.checkequal( 2, 'rrarrrrrrrrra', 'index', 'a')
        self.checkequal(12, 'rrarrrrrrrrra', 'index', 'a', 4)
        self.checkraises(ValueError, 'rrarrrrrrrrra', 'index', 'a', 4, 6)
        self.checkequal(12, 'rrarrrrrrrrra', 'index', 'a', 4, None)
        self.checkequal( 2, 'rrarrrrrrrrra', 'index', 'a', None, 6)

        self.checkraises(TypeError, 'hello', 'index')

        if self.contains_bytes:
            self.checkraises(ValueError, 'hello', 'index', 42)
        else:
            self.checkraises(TypeError, 'hello', 'index', 42)

    def test_rindex(self):
        self.checkequal(12, 'abcdefghiabc', 'rindex', '')
        self.checkequal(3,  'abcdefghiabc', 'rindex', 'def')
        self.checkequal(9,  'abcdefghiabc', 'rindex', 'abc')
        self.checkequal(0,  'abcdefghiabc', 'rindex', 'abc', 0, -1)

        self.checkraises(ValueError, 'abcdefghiabc', 'rindex', 'hib')
        self.checkraises(ValueError, 'defghiabc', 'rindex', 'def', 1)
        self.checkraises(ValueError, 'defghiabc', 'rindex', 'abc', 0, -1)
        self.checkraises(ValueError, 'abcdefghi', 'rindex', 'ghi', 0, 8)
        self.checkraises(ValueError, 'abcdefghi', 'rindex', 'ghi', 0, -1)

        # to check the ability to pass None as defaults
        self.checkequal(12, 'rrarrrrrrrrra', 'rindex', 'a')
        self.checkequal(12, 'rrarrrrrrrrra', 'rindex', 'a', 4)
        self.checkraises(ValueError, 'rrarrrrrrrrra', 'rindex', 'a', 4, 6)
        self.checkequal(12, 'rrarrrrrrrrra', 'rindex', 'a', 4, None)
        self.checkequal( 2, 'rrarrrrrrrrra', 'rindex', 'a', None, 6)

        self.checkraises(TypeError, 'hello', 'rindex')

        if self.contains_bytes:
            self.checkraises(ValueError, 'hello', 'rindex', 42)
        else:
            self.checkraises(TypeError, 'hello', 'rindex', 42)

    def test_lower(self):
        self.checkequal('hello', 'HeLLo', 'lower')
        self.checkequal('hello', 'hello', 'lower')
        self.checkraises(TypeError, 'hello', 'lower', 42)

    def test_upper(self):
        self.checkequal('HELLO', 'HeLLo', 'upper')
        self.checkequal('HELLO', 'HELLO', 'upper')
        self.checkraises(TypeError, 'hello', 'upper', 42)

    def test_expandtabs(self):
        self.checkequal('abc\rab      def\ng       hi', 'abc\rab\tdef\ng\thi',
                        'expandtabs')
        self.checkequal('abc\rab      def\ng       hi', 'abc\rab\tdef\ng\thi',
                        'expandtabs', 8)
        self.checkequal('abc\rab  def\ng   hi', 'abc\rab\tdef\ng\thi',
                        'expandtabs', 4)
        self.checkequal('abc\r\nab      def\ng       hi', 'abc\r\nab\tdef\ng\thi',
                        'expandtabs')
        self.checkequal('abc\r\nab      def\ng       hi', 'abc\r\nab\tdef\ng\thi',
                        'expandtabs', 8)
        self.checkequal('abc\r\nab  def\ng   hi', 'abc\r\nab\tdef\ng\thi',
                        'expandtabs', 4)
        self.checkequal('abc\r\nab\r\ndef\ng\r\nhi', 'abc\r\nab\r\ndef\ng\r\nhi',
                        'expandtabs', 4)
        # check keyword args
        self.checkequal('abc\rab      def\ng       hi', 'abc\rab\tdef\ng\thi',
                        'expandtabs', tabsize=8)
        self.checkequal('abc\rab  def\ng   hi', 'abc\rab\tdef\ng\thi',
                        'expandtabs', tabsize=4)

        self.checkequal('  a\n b', ' \ta\n\tb', 'expandtabs', 1)

        self.checkraises(TypeError, 'hello', 'expandtabs', 42, 42)
        # This test is only valid when sizeof(int) == sizeof(void*) == 4.
        if sys.maxsize < (1 << 32) and struct.calcsize('P') == 4:
            self.checkraises(OverflowError,
                             '\ta\n\tb', 'expandtabs', sys.maxsize)

    def test_split(self):
        # by a char
        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'split', '|')
        self.checkequal(['a|b|c|d'], 'a|b|c|d', 'split', '|', 0)
        self.checkequal(['a', 'b|c|d'], 'a|b|c|d', 'split', '|', 1)
        self.checkequal(['a', 'b', 'c|d'], 'a|b|c|d', 'split', '|', 2)
        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'split', '|', 3)
        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'split', '|', 4)
        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'split', '|',
                        sys.maxsize-2)
        self.checkequal(['a|b|c|d'], 'a|b|c|d', 'split', '|', 0)
        self.checkequal(['a', '', 'b||c||d'], 'a||b||c||d', 'split', '|', 2)
        self.checkequal(['abcd'], 'abcd', 'split', '|')
        self.checkequal([''], '', 'split', '|')
        self.checkequal(['endcase ', ''], 'endcase |', 'split', '|')
        self.checkequal(['', ' startcase'], '| startcase', 'split', '|')
        self.checkequal(['', 'bothcase', ''], '|bothcase|', 'split', '|')
        self.checkequal(['a', '', 'b\x00c\x00d'], 'a\x00\x00b\x00c\x00d', 'split', '\x00', 2)

        self.checkequal(['a']*20, ('a|'*20)[:-1], 'split', '|')
        self.checkequal(['a']*15 +['a|a|a|a|a'],
                                   ('a|'*20)[:-1], 'split', '|', 15)

        # by string
        self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'split', '//')
        self.checkequal(['a', 'b//c//d'], 'a//b//c//d', 'split', '//', 1)
        self.checkequal(['a', 'b', 'c//d'], 'a//b//c//d', 'split', '//', 2)
        self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'split', '//', 3)
        self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'split', '//', 4)
        self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'split', '//',
                        sys.maxsize-10)
        self.checkequal(['a//b//c//d'], 'a//b//c//d', 'split', '//', 0)
        self.checkequal(['a', '', 'b////c////d'], 'a////b////c////d', 'split', '//', 2)
        self.checkequal(['endcase ', ''], 'endcase test', 'split', 'test')
        self.checkequal(['', ' begincase'], 'test begincase', 'split', 'test')
        self.checkequal(['', ' bothcase ', ''], 'test bothcase test',
                        'split', 'test')
        self.checkequal(['a', 'bc'], 'abbbc', 'split', 'bb')
        self.checkequal(['', ''], 'aaa', 'split', 'aaa')
        self.checkequal(['aaa'], 'aaa', 'split', 'aaa', 0)
        self.checkequal(['ab', 'ab'], 'abbaab', 'split', 'ba')
        self.checkequal(['aaaa'], 'aaaa', 'split', 'aab')
        self.checkequal([''], '', 'split', 'aaa')
        self.checkequal(['aa'], 'aa', 'split', 'aaa')
        self.checkequal(['A', 'bobb'], 'Abbobbbobb', 'split', 'bbobb')
        self.checkequal(['A', 'B', ''], 'AbbobbBbbobb', 'split', 'bbobb')

        self.checkequal(['a']*20, ('aBLAH'*20)[:-4], 'split', 'BLAH')
        self.checkequal(['a']*20, ('aBLAH'*20)[:-4], 'split', 'BLAH', 19)
        self.checkequal(['a']*18 + ['aBLAHa'], ('aBLAH'*20)[:-4],
                        'split', 'BLAH', 18)

        # with keyword args
        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'split', sep='|')
        self.checkequal(['a', 'b|c|d'],
                        'a|b|c|d', 'split', '|', maxsplit=1)
        self.checkequal(['a', 'b|c|d'],
                        'a|b|c|d', 'split', sep='|', maxsplit=1)
        self.checkequal(['a', 'b|c|d'],
                        'a|b|c|d', 'split', maxsplit=1, sep='|')
        self.checkequal(['a', 'b c d'],
                        'a b c d', 'split', maxsplit=1)

        # argument type
        self.checkraises(TypeError, 'hello', 'split', 42, 42, 42)

        # null case
        self.checkraises(ValueError, 'hello', 'split', '')
        self.checkraises(ValueError, 'hello', 'split', '', 0)

    def test_rsplit(self):
        # by a char
        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'rsplit', '|')
        self.checkequal(['a|b|c', 'd'], 'a|b|c|d', 'rsplit', '|', 1)
        self.checkequal(['a|b', 'c', 'd'], 'a|b|c|d', 'rsplit', '|', 2)
        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'rsplit', '|', 3)
        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'rsplit', '|', 4)
        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'rsplit', '|',
                        sys.maxsize-100)
        self.checkequal(['a|b|c|d'], 'a|b|c|d', 'rsplit', '|', 0)
        self.checkequal(['a||b||c', '', 'd'], 'a||b||c||d', 'rsplit', '|', 2)
        self.checkequal(['abcd'], 'abcd', 'rsplit', '|')
        self.checkequal([''], '', 'rsplit', '|')
        self.checkequal(['', ' begincase'], '| begincase', 'rsplit', '|')
        self.checkequal(['endcase ', ''], 'endcase |', 'rsplit', '|')
        self.checkequal(['', 'bothcase', ''], '|bothcase|', 'rsplit', '|')

        self.checkequal(['a\x00\x00b', 'c', 'd'], 'a\x00\x00b\x00c\x00d', 'rsplit', '\x00', 2)

        self.checkequal(['a']*20, ('a|'*20)[:-1], 'rsplit', '|')
        self.checkequal(['a|a|a|a|a']+['a']*15,
                        ('a|'*20)[:-1], 'rsplit', '|', 15)

        # by string
        self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'rsplit', '//')
        self.checkequal(['a//b//c', 'd'], 'a//b//c//d', 'rsplit', '//', 1)
        self.checkequal(['a//b', 'c', 'd'], 'a//b//c//d', 'rsplit', '//', 2)
        self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'rsplit', '//', 3)
        self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'rsplit', '//', 4)
        self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'rsplit', '//',
                        sys.maxsize-5)
        self.checkequal(['a//b//c//d'], 'a//b//c//d', 'rsplit', '//', 0)
        self.checkequal(['a////b////c', '', 'd'], 'a////b////c////d', 'rsplit', '//', 2)
        self.checkequal(['', ' begincase'], 'test begincase', 'rsplit', 'test')
        self.checkequal(['endcase ', ''], 'endcase test', 'rsplit', 'test')
        self.checkequal(['', ' bothcase ', ''], 'test bothcase test',
                        'rsplit', 'test')
        self.checkequal(['ab', 'c'], 'abbbc', 'rsplit', 'bb')
        self.checkequal(['', ''], 'aaa', 'rsplit', 'aaa')
        self.checkequal(['aaa'], 'aaa', 'rsplit', 'aaa', 0)
        self.checkequal(['ab', 'ab'], 'abbaab', 'rsplit', 'ba')
        self.checkequal(['aaaa'], 'aaaa', 'rsplit', 'aab')
        self.checkequal([''], '', 'rsplit', 'aaa')
        self.checkequal(['aa'], 'aa', 'rsplit', 'aaa')
        self.checkequal(['bbob', 'A'], 'bbobbbobbA', 'rsplit', 'bbobb')
        self.checkequal(['', 'B', 'A'], 'bbobbBbbobbA', 'rsplit', 'bbobb')

        self.checkequal(['a']*20, ('aBLAH'*20)[:-4], 'rsplit', 'BLAH')
        self.checkequal(['a']*20, ('aBLAH'*20)[:-4], 'rsplit', 'BLAH', 19)
        self.checkequal(['aBLAHa'] + ['a']*18, ('aBLAH'*20)[:-4],
                        'rsplit', 'BLAH', 18)

        # with keyword args
        self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'rsplit', sep='|')
        self.checkequal(['a|b|c', 'd'],
                        'a|b|c|d', 'rsplit', '|', maxsplit=1)
        self.checkequal(['a|b|c', 'd'],
                        'a|b|c|d', 'rsplit', sep='|', maxsplit=1)
        self.checkequal(['a|b|c', 'd'],
                        'a|b|c|d', 'rsplit', maxsplit=1, sep='|')
        self.checkequal(['a b c', 'd'],
                        'a b c d', 'rsplit', maxsplit=1)

        # argument type
        self.checkraises(TypeError, 'hello', 'rsplit', 42, 42, 42)

        # null case
        self.checkraises(ValueError, 'hello', 'rsplit', '')
        self.checkraises(ValueError, 'hello', 'rsplit', '', 0)

    def test_replace(self):
        EQ = self.checkequal

        # Operations on the empty string
        EQ("", "", "replace", "", "")
        EQ("A", "", "replace", "", "A")
        EQ("", "", "replace", "A", "")
        EQ("", "", "replace", "A", "A")
        EQ("", "", "replace", "", "", 100)
        EQ("", "", "replace", "", "", sys.maxsize)

        # interleave (from=="", 'to' gets inserted everywhere)
        EQ("A", "A", "replace", "", "")
        EQ("*A*", "A", "replace", "", "*")
        EQ("*1A*1", "A", "replace", "", "*1")
        EQ("*-#A*-#", "A", "replace", "", "*-#")
        EQ("*-A*-A*-", "AA", "replace", "", "*-")
        EQ("*-A*-A*-", "AA", "replace", "", "*-", -1)
        EQ("*-A*-A*-", "AA", "replace", "", "*-", sys.maxsize)
        EQ("*-A*-A*-", "AA", "replace", "", "*-", 4)
        EQ("*-A*-A*-", "AA", "replace", "", "*-", 3)
        EQ("*-A*-A", "AA", "replace", "", "*-", 2)
        EQ("*-AA", "AA", "replace", "", "*-", 1)
        EQ("AA", "AA", "replace", "", "*-", 0)

        # single character deletion (from=="A", to=="")
        EQ("", "A", "replace", "A", "")
        EQ("", "AAA", "replace", "A", "")
        EQ("", "AAA", "replace", "A", "", -1)
        EQ("", "AAA", "replace", "A", "", sys.maxsize)
        EQ("", "AAA", "replace", "A", "", 4)
        EQ("", "AAA", "replace", "A", "", 3)
        EQ("A", "AAA", "replace", "A", "", 2)
        EQ("AA", "AAA", "replace", "A", "", 1)
        EQ("AAA", "AAA", "replace", "A", "", 0)
        EQ("", "AAAAAAAAAA", "replace", "A", "")
        EQ("BCD", "ABACADA", "replace", "A", "")
        EQ("BCD", "ABACADA", "replace", "A", "", -1)
        EQ("BCD", "ABACADA", "replace", "A", "", sys.maxsize)
        EQ("BCD", "ABACADA", "replace", "A", "", 5)
        EQ("BCD", "ABACADA", "replace", "A", "", 4)
        EQ("BCDA", "ABACADA", "replace", "A", "", 3)
        EQ("BCADA", "ABACADA", "replace", "A", "", 2)
        EQ("BACADA", "ABACADA", "replace", "A", "", 1)
        EQ("ABACADA", "ABACADA", "replace", "A", "", 0)
        EQ("BCD", "ABCAD", "replace", "A", "")
        EQ("BCD", "ABCADAA", "replace", "A", "")
        EQ("BCD", "BCD", "replace", "A", "")
        EQ("*************", "*************", "replace", "A", "")
        EQ("^A^", "^"+"A"*1000+"^", "replace", "A", "", 999)

        # substring deletion (from=="the", to=="")
        EQ("", "the", "replace", "the", "")
        EQ("ater", "theater", "replace", "the", "")
        EQ("", "thethe", "replace", "the", "")
        EQ("", "thethethethe", "replace", "the", "")
        EQ("aaaa", "theatheatheathea", "replace", "the", "")
        EQ("that", "that", "replace", "the", "")
        EQ("thaet", "thaet", "replace", "the", "")
        EQ("here and re", "here and there", "replace", "the", "")
        EQ("here and re and re", "here and there and there",
           "replace", "the", "", sys.maxsize)
        EQ("here and re and re", "here and there and there",
           "replace", "the", "", -1)
        EQ("here and re and re", "here and there and there",
           "replace", "the", "", 3)
        EQ("here and re and re", "here and there and there",
           "replace", "the", "", 2)
        EQ("here and re and there", "here and there and there",
           "replace", "the", "", 1)
        EQ("here and there and there", "here and there and there",
           "replace", "the", "", 0)
        EQ("here and re and re", "here and there and there", "replace", "the", "")

        EQ("abc", "abc", "replace", "the", "")
        EQ("abcdefg", "abcdefg", "replace", "the", "")

        # substring deletion (from=="bob", to=="")
        EQ("bob", "bbobob", "replace", "bob", "")
        EQ("bobXbob", "bbobobXbbobob", "replace", "bob", "")
        EQ("aaaaaaa", "aaaaaaabob", "replace", "bob", "")
        EQ("aaaaaaa", "aaaaaaa", "replace", "bob", "")

        # single character replace in place (len(from)==len(to)==1)
        EQ("Who goes there?", "Who goes there?", "replace", "o", "o")
        EQ("WhO gOes there?", "Who goes there?", "replace", "o", "O")
        EQ("WhO gOes there?", "Who goes there?", "replace", "o", "O", sys.maxsize)
        EQ("WhO gOes there?", "Who goes there?", "replace", "o", "O", -1)
        EQ("WhO gOes there?", "Who goes there?", "replace", "o", "O", 3)
        EQ("WhO gOes there?", "Who goes there?", "replace", "o", "O", 2)
        EQ("WhO goes there?", "Who goes there?", "replace", "o", "O", 1)
        EQ("Who goes there?", "Who goes there?", "replace", "o", "O", 0)

        EQ("Who goes there?", "Who goes there?", "replace", "a", "q")
        EQ("who goes there?", "Who goes there?", "replace", "W", "w")
        EQ("wwho goes there?ww", "WWho goes there?WW", "replace", "W", "w")
        EQ("Who goes there!", "Who goes there?", "replace", "?", "!")
        EQ("Who goes there!!", "Who goes there??", "replace", "?", "!")

        EQ("Who goes there?", "Who goes there?", "replace", ".", "!")

        # substring replace in place (len(from)==len(to) > 1)
        EQ("Th** ** a t**sue", "This is a tissue", "replace", "is", "**")
        EQ("Th** ** a t**sue", "This is a tissue", "replace", "is", "**", sys.maxsize)
        EQ("Th** ** a t**sue", "This is a tissue", "replace", "is", "**", -1)
        EQ("Th** ** a t**sue", "This is a tissue", "replace", "is", "**", 4)
        EQ("Th** ** a t**sue", "This is a tissue", "replace", "is", "**", 3)
        EQ("Th** ** a tissue", "This is a tissue", "replace", "is", "**", 2)
        EQ("Th** is a tissue", "This is a tissue", "replace", "is", "**", 1)
        EQ("This is a tissue", "This is a tissue", "replace", "is", "**", 0)
        EQ("cobob", "bobob", "replace", "bob", "cob")
        EQ("cobobXcobocob", "bobobXbobobob", "replace", "bob", "cob")
        EQ("bobob", "bobob", "replace", "bot", "bot")

        # replace single character (len(from)==1, len(to)>1)
        EQ("ReyKKjaviKK", "Reykjavik", "replace", "k", "KK")
        EQ("ReyKKjaviKK", "Reykjavik", "replace", "k", "KK", -1)
        EQ("ReyKKjaviKK", "Reykjavik", "replace", "k", "KK", sys.maxsize)
        EQ("ReyKKjaviKK", "Reykjavik", "replace", "k", "KK", 2)
        EQ("ReyKKjavik", "Reykjavik", "replace", "k", "KK", 1)
        EQ("Reykjavik", "Reykjavik", "replace", "k", "KK", 0)
        EQ("A----B----C----", "A.B.C.", "replace", ".", "----")
        # issue #15534
        EQ('...\u043c......<', '...\u043c......<', "replace", "<", "<")

        EQ("Reykjavik", "Reykjavik", "replace", "q", "KK")

        # replace substring (len(from)>1, len(to)!=len(from))
        EQ("ham, ham, eggs and ham", "spam, spam, eggs and spam",
           "replace", "spam", "ham")
        EQ("ham, ham, eggs and ham", "spam, spam, eggs and spam",
           "replace", "spam", "ham", sys.maxsize)
        EQ("ham, ham, eggs and ham", "spam, spam, eggs and spam",
           "replace", "spam", "ham", -1)
        EQ("ham, ham, eggs and ham", "spam, spam, eggs and spam",
           "replace", "spam", "ham", 4)
        EQ("ham, ham, eggs and ham", "spam, spam, eggs and spam",
           "replace", "spam", "ham", 3)
        EQ("ham, ham, eggs and spam", "spam, spam, eggs and spam",
           "replace", "spam", "ham", 2)
        EQ("ham, spam, eggs and spam", "spam, spam, eggs and spam",
           "replace", "spam", "ham", 1)
        EQ("spam, spam, eggs and spam", "spam, spam, eggs and spam",
           "replace", "spam", "ham", 0)

        EQ("bobob", "bobobob", "replace", "bobob", "bob")
        EQ("bobobXbobob", "bobobobXbobobob", "replace", "bobob", "bob")
        EQ("BOBOBOB", "BOBOBOB", "replace", "bob", "bobby")

        self.checkequal('one@two!three!', 'one!two!three!', 'replace', '!', '@', 1)
        self.checkequal('onetwothree', 'one!two!three!', 'replace', '!', '')
        self.checkequal('one@two@three!', 'one!two!three!', 'replace', '!', '@', 2)
        self.checkequal('one@two@three@', 'one!two!three!', 'replace', '!', '@', 3)
        self.checkequal('one@two@three@', 'one!two!three!', 'replace', '!', '@', 4)
        self.checkequal('one!two!three!', 'one!two!three!', 'replace', '!', '@', 0)
        self.checkequal('one@two@three@', 'one!two!three!', 'replace', '!', '@')
        self.checkequal('one!two!three!', 'one!two!three!', 'replace', 'x', '@')
        self.checkequal('one!two!three!', 'one!two!three!', 'replace', 'x', '@', 2)
        self.checkequal('-a-b-c-', 'abc', 'replace', '', '-')
        self.checkequal('-a-b-c', 'abc', 'replace', '', '-', 3)
        self.checkequal('abc', 'abc', 'replace', '', '-', 0)
        self.checkequal('', '', 'replace', '', '')
        self.checkequal('abc', 'abc', 'replace', 'ab', '--', 0)
        self.checkequal('abc', 'abc', 'replace', 'xy', '--')
        # Next three for SF bug 422088: [OSF1 alpha] string.replace(); died with
        # MemoryError due to empty result (platform malloc issue when requesting
        # 0 bytes).
        self.checkequal('', '123', 'replace', '123', '')
        self.checkequal('', '123123', 'replace', '123', '')
        self.checkequal('x', '123x123', 'replace', '123', '')

        self.checkraises(TypeError, 'hello', 'replace')
        self.checkraises(TypeError, 'hello', 'replace', 42)
        self.checkraises(TypeError, 'hello', 'replace', 42, 'h')
        self.checkraises(TypeError, 'hello', 'replace', 'h', 42)

    @unittest.skipIf(sys.maxsize > (1 << 32) or struct.calcsize('P') != 4,
                     'only applies to 32-bit platforms')
    def test_replace_overflow(self):
        # Check for overflow checking on 32 bit machines
        A2_16 = "A" * (2**16)
        self.checkraises(OverflowError, A2_16, "replace", "", A2_16)
        self.checkraises(OverflowError, A2_16, "replace", "A", A2_16)
        self.checkraises(OverflowError, A2_16, "replace", "AA", A2_16+A2_16)

    def test_capitalize(self):
        self.checkequal(' hello ', ' hello ', 'capitalize')
        self.checkequal('Hello ', 'Hello ','capitalize')
        self.checkequal('Hello ', 'hello ','capitalize')
        self.checkequal('Aaaa', 'aaaa', 'capitalize')
        self.checkequal('Aaaa', 'AaAa', 'capitalize')

        self.checkraises(TypeError, 'hello', 'capitalize', 42)

    def test_additional_split(self):
        self.checkequal(['this', 'is', 'the', 'split', 'function'],
            'this is the split function', 'split')

        # by whitespace
        self.checkequal(['a', 'b', 'c', 'd'], 'a b c d ', 'split')
        self.checkequal(['a', 'b c d'], 'a b c d', 'split', None, 1)
        self.checkequal(['a', 'b', 'c d'], 'a b c d', 'split', None, 2)
        self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'split', None, 3)
        self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'split', None, 4)
        self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'split', None,
                        sys.maxsize-1)
        self.checkequal(['a b c d'], 'a b c d', 'split', None, 0)
        self.checkequal(['a b c d'], '  a b c d', 'split', None, 0)
        self.checkequal(['a', 'b', 'c  d'], 'a  b  c  d', 'split', None, 2)

        self.checkequal([], '         ', 'split')
        self.checkequal(['a'], '  a    ', 'split')
        self.checkequal(['a', 'b'], '  a    b   ', 'split')
        self.checkequal(['a', 'b   '], '  a    b   ', 'split', None, 1)
        self.checkequal(['a    b   c   '], '  a    b   c   ', 'split', None, 0)
        self.checkequal(['a', 'b   c   '], '  a    b   c   ', 'split', None, 1)
        self.checkequal(['a', 'b', 'c   '], '  a    b   c   ', 'split', None, 2)
        self.checkequal(['a', 'b', 'c'], '  a    b   c   ', 'split', None, 3)
        self.checkequal(['a', 'b'], '\n\ta \t\r b \v ', 'split')
        aaa = ' a '*20
        self.checkequal(['a']*20, aaa, 'split')
        self.checkequal(['a'] + [aaa[4:]], aaa, 'split', None, 1)
        self.checkequal(['a']*19 + ['a '], aaa, 'split', None, 19)

        for b in ('arf\tbarf', 'arf\nbarf', 'arf\rbarf',
                  'arf\fbarf', 'arf\vbarf'):
            self.checkequal(['arf', 'barf'], b, 'split')
            self.checkequal(['arf', 'barf'], b, 'split', None)
            self.checkequal(['arf', 'barf'], b, 'split', None, 2)

    def test_additional_rsplit(self):
        self.checkequal(['this', 'is', 'the', 'rsplit', 'function'],
                         'this is the rsplit function', 'rsplit')

        # by whitespace
        self.checkequal(['a', 'b', 'c', 'd'], 'a b c d ', 'rsplit')
        self.checkequal(['a b c', 'd'], 'a b c d', 'rsplit', None, 1)
        self.checkequal(['a b', 'c', 'd'], 'a b c d', 'rsplit', None, 2)
        self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'rsplit', None, 3)
        self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'rsplit', None, 4)
        self.checkequal(['a', 'b', 'c', 'd'], 'a b c d', 'rsplit', None,
                        sys.maxsize-20)
        self.checkequal(['a b c d'], 'a b c d', 'rsplit', None, 0)
        self.checkequal(['a b c d'], 'a b c d  ', 'rsplit', None, 0)
        self.checkequal(['a  b', 'c', 'd'], 'a  b  c  d', 'rsplit', None, 2)

        self.checkequal([], '         ', 'rsplit')
        self.checkequal(['a'], '  a    ', 'rsplit')
        self.checkequal(['a', 'b'], '  a    b   ', 'rsplit')
        self.checkequal(['  a', 'b'], '  a    b   ', 'rsplit', None, 1)
        self.checkequal(['  a    b   c'], '  a    b   c   ', 'rsplit',
                        None, 0)
        self.checkequal(['  a    b','c'], '  a    b   c   ', 'rsplit',
                        None, 1)
        self.checkequal(['  a', 'b', 'c'], '  a    b   c   ', 'rsplit',
                        None, 2)
        self.checkequal(['a', 'b', 'c'], '  a    b   c   ', 'rsplit',
                        None, 3)
        self.checkequal(['a', 'b'], '\n\ta \t\r b \v ', 'rsplit', None, 88)
        aaa = ' a '*20
        self.checkequal(['a']*20, aaa, 'rsplit')
        self.checkequal([aaa[:-4]] + ['a'], aaa, 'rsplit', None, 1)
        self.checkequal([' a  a'] + ['a']*18, aaa, 'rsplit', None, 18)

        for b in ('arf\tbarf', 'arf\nbarf', 'arf\rbarf',
                  'arf\fbarf', 'arf\vbarf'):
            self.checkequal(['arf', 'barf'], b, 'rsplit')
            self.checkequal(['arf', 'barf'], b, 'rsplit', None)
            self.checkequal(['arf', 'barf'], b, 'rsplit', None, 2)

    def test_strip_whitespace(self):
        self.checkequal('hello', '   hello   ', 'strip')
        self.checkequal('hello   ', '   hello   ', 'lstrip')
        self.checkequal('   hello', '   hello   ', 'rstrip')
        self.checkequal('hello', 'hello', 'strip')

        b = ' \t\n\r\f\vabc \t\n\r\f\v'
        self.checkequal('abc', b, 'strip')
        self.checkequal('abc \t\n\r\f\v', b, 'lstrip')
        self.checkequal(' \t\n\r\f\vabc', b, 'rstrip')

        # strip/lstrip/rstrip with None arg
        self.checkequal('hello', '   hello   ', 'strip', None)
        self.checkequal('hello   ', '   hello   ', 'lstrip', None)
        self.checkequal('   hello', '   hello   ', 'rstrip', None)
        self.checkequal('hello', 'hello', 'strip', None)

    def test_strip(self):
        # strip/lstrip/rstrip with str arg
        self.checkequal('hello', 'xyzzyhelloxyzzy', 'strip', 'xyz')
        self.checkequal('helloxyzzy', 'xyzzyhelloxyzzy', 'lstrip', 'xyz')
        self.checkequal('xyzzyhello', 'xyzzyhelloxyzzy', 'rstrip', 'xyz')
        self.checkequal('hello', 'hello', 'strip', 'xyz')
        self.checkequal('', 'mississippi', 'strip', 'mississippi')

        # only trim the start and end; does not strip internal characters
        self.checkequal('mississipp', 'mississippi', 'strip', 'i')

        self.checkraises(TypeError, 'hello', 'strip', 42, 42)
        self.checkraises(TypeError, 'hello', 'lstrip', 42, 42)
        self.checkraises(TypeError, 'hello', 'rstrip', 42, 42)

    def test_ljust(self):
        self.checkequal('abc       ', 'abc', 'ljust', 10)
        self.checkequal('abc   ', 'abc', 'ljust', 6)
        self.checkequal('abc', 'abc', 'ljust', 3)
        self.checkequal('abc', 'abc', 'ljust', 2)
        self.checkequal('abc*******', 'abc', 'ljust', 10, '*')
        self.checkraises(TypeError, 'abc', 'ljust')

    def test_rjust(self):
        self.checkequal('       abc', 'abc', 'rjust', 10)
        self.checkequal('   abc', 'abc', 'rjust', 6)
        self.checkequal('abc', 'abc', 'rjust', 3)
        self.checkequal('abc', 'abc', 'rjust', 2)
        self.checkequal('*******abc', 'abc', 'rjust', 10, '*')
        self.checkraises(TypeError, 'abc', 'rjust')

    def test_center(self):
        self.checkequal('   abc    ', 'abc', 'center', 10)
        self.checkequal(' abc  ', 'abc', 'center', 6)
        self.checkequal('abc', 'abc', 'center', 3)
        self.checkequal('abc', 'abc', 'center', 2)
        self.checkequal('***abc****', 'abc', 'center', 10, '*')
        self.checkraises(TypeError, 'abc', 'center')

    def test_swapcase(self):
        self.checkequal('hEllO CoMPuTErS', 'HeLLo cOmpUteRs', 'swapcase')

        self.checkraises(TypeError, 'hello', 'swapcase', 42)

    def test_zfill(self):
        self.checkequal('123', '123', 'zfill', 2)
        self.checkequal('123', '123', 'zfill', 3)
        self.checkequal('0123', '123', 'zfill', 4)
        self.checkequal('+123', '+123', 'zfill', 3)
        self.checkequal('+123', '+123', 'zfill', 4)
        self.checkequal('+0123', '+123', 'zfill', 5)
        self.checkequal('-123', '-123', 'zfill', 3)
        self.checkequal('-123', '-123', 'zfill', 4)
        self.checkequal('-0123', '-123', 'zfill', 5)
        self.checkequal('000', '', 'zfill', 3)
        self.checkequal('34', '34', 'zfill', 1)
        self.checkequal('0034', '34', 'zfill', 4)

        self.checkraises(TypeError, '123', 'zfill')

    def test_islower(self):
        self.checkequal(False, '', 'islower')
        self.checkequal(True, 'a', 'islower')
        self.checkequal(False, 'A', 'islower')
        self.checkequal(False, '\n', 'islower')
        self.checkequal(True, 'abc', 'islower')
        self.checkequal(False, 'aBc', 'islower')
        self.checkequal(True, 'abc\n', 'islower')
        self.checkraises(TypeError, 'abc', 'islower', 42)

    def test_isupper(self):
        self.checkequal(False, '', 'isupper')
        self.checkequal(False, 'a', 'isupper')
        self.checkequal(True, 'A', 'isupper')
        self.checkequal(False, '\n', 'isupper')
        self.checkequal(True, 'ABC', 'isupper')
        self.checkequal(False, 'AbC', 'isupper')
        self.checkequal(True, 'ABC\n', 'isupper')
        self.checkraises(TypeError, 'abc', 'isupper', 42)

    def test_istitle(self):
        self.checkequal(False, '', 'istitle')
        self.checkequal(False, 'a', 'istitle')
        self.checkequal(True, 'A', 'istitle')
        self.checkequal(False, '\n', 'istitle')
        self.checkequal(True, 'A Titlecased Line', 'istitle')
        self.checkequal(True, 'A\nTitlecased Line', 'istitle')
        self.checkequal(True, 'A Titlecased, Line', 'istitle')
        self.checkequal(False, 'Not a capitalized String', 'istitle')
        self.checkequal(False, 'Not\ta Titlecase String', 'istitle')
        self.checkequal(False, 'Not--a Titlecase String', 'istitle')
        self.checkequal(False, 'NOT', 'istitle')
        self.checkraises(TypeError, 'abc', 'istitle', 42)

    def test_isspace(self):
        self.checkequal(False, '', 'isspace')
        self.checkequal(False, 'a', 'isspace')
        self.checkequal(True, ' ', 'isspace')
        self.checkequal(True, '\t', 'isspace')
        self.checkequal(True, '\r', 'isspace')
        self.checkequal(True, '\n', 'isspace')
        self.checkequal(True, ' \t\r\n', 'isspace')
        self.checkequal(False, ' \t\r\na', 'isspace')
        self.checkraises(TypeError, 'abc', 'isspace', 42)

    def test_isalpha(self):
        self.checkequal(False, '', 'isalpha')
        self.checkequal(True, 'a', 'isalpha')
        self.checkequal(True, 'A', 'isalpha')
        self.checkequal(False, '\n', 'isalpha')
        self.checkequal(True, 'abc', 'isalpha')
        self.checkequal(False, 'aBc123', 'isalpha')
        self.checkequal(False, 'abc\n', 'isalpha')
        self.checkraises(TypeError, 'abc', 'isalpha', 42)

    def test_isalnum(self):
        self.checkequal(False, '', 'isalnum')
        self.checkequal(True, 'a', 'isalnum')
        self.checkequal(True, 'A', 'isalnum')
        self.checkequal(False, '\n', 'isalnum')
        self.checkequal(True, '123abc456', 'isalnum')
        self.checkequal(True, 'a1b3c', 'isalnum')
        self.checkequal(False, 'aBc000 ', 'isalnum')
        self.checkequal(False, 'abc\n', 'isalnum')
        self.checkraises(TypeError, 'abc', 'isalnum', 42)

    def test_isascii(self):
        self.checkequal(True, '', 'isascii')
        self.checkequal(True, '\x00', 'isascii')
        self.checkequal(True, '\x7f', 'isascii')
        self.checkequal(True, '\x00\x7f', 'isascii')
        self.checkequal(False, '\x80', 'isascii')
        self.checkequal(False, '\xe9', 'isascii')
        # bytes.isascii() and bytearray.isascii() has optimization which
        # check 4 or 8 bytes at once.  So check some alignments.
        for p in range(8):
            self.checkequal(True, ' '*p + '\x7f', 'isascii')
            self.checkequal(False, ' '*p + '\x80', 'isascii')
            self.checkequal(True, ' '*p + '\x7f' + ' '*8, 'isascii')
            self.checkequal(False, ' '*p + '\x80' + ' '*8, 'isascii')

    def test_isdigit(self):
        self.checkequal(False, '', 'isdigit')
        self.checkequal(False, 'a', 'isdigit')
        self.checkequal(True, '0', 'isdigit')
        self.checkequal(True, '0123456789', 'isdigit')
        self.checkequal(False, '0123456789a', 'isdigit')

        self.checkraises(TypeError, 'abc', 'isdigit', 42)

    def test_title(self):
        self.checkequal(' Hello ', ' hello ', 'title')
        self.checkequal('Hello ', 'hello ', 'title')
        self.checkequal('Hello ', 'Hello ', 'title')
        self.checkequal('Format This As Title String', "fOrMaT thIs aS titLe String", 'title')
        self.checkequal('Format,This-As*Title;String', "fOrMaT,thIs-aS*titLe;String", 'title', )
        self.checkequal('Getint', "getInt", 'title')
        self.checkraises(TypeError, 'hello', 'title', 42)

    def test_splitlines(self):
        self.checkequal(['abc', 'def', '', 'ghi'], "abc\ndef\n\rghi", 'splitlines')
        self.checkequal(['abc', 'def', '', 'ghi'], "abc\ndef\n\r\nghi", 'splitlines')
        self.checkequal(['abc', 'def', 'ghi'], "abc\ndef\r\nghi", 'splitlines')
        self.checkequal(['abc', 'def', 'ghi'], "abc\ndef\r\nghi\n", 'splitlines')
        self.checkequal(['abc', 'def', 'ghi', ''], "abc\ndef\r\nghi\n\r", 'splitlines')
        self.checkequal(['', 'abc', 'def', 'ghi', ''], "\nabc\ndef\r\nghi\n\r", 'splitlines')
        self.checkequal(['', 'abc', 'def', 'ghi', ''],
                        "\nabc\ndef\r\nghi\n\r", 'splitlines', False)
        self.checkequal(['\n', 'abc\n', 'def\r\n', 'ghi\n', '\r'],
                        "\nabc\ndef\r\nghi\n\r", 'splitlines', True)
        self.checkequal(['', 'abc', 'def', 'ghi', ''], "\nabc\ndef\r\nghi\n\r",
                        'splitlines', keepends=False)
        self.checkequal(['\n', 'abc\n', 'def\r\n', 'ghi\n', '\r'],
                        "\nabc\ndef\r\nghi\n\r", 'splitlines', keepends=True)

        self.checkraises(TypeError, 'abc', 'splitlines', 42, 42)


class CommonTest(BaseTest):
    # This testcase contains tests that can be used in all
    # stringlike classes. Currently this is str and UserString.

    def test_hash(self):
        # SF bug 1054139:  += optimization was not invalidating cached hash value
        a = self.type2test('DNSSEC')
        b = self.type2test('')
        for c in a:
            b += c
            hash(b)
        self.assertEqual(hash(a), hash(b))

    def test_capitalize_nonascii(self):
        # check that titlecased chars are lowered correctly
        # \u1ffc is the titlecased char
        # Note: differs between Py<3.8 and later.
        #self.checkequal('\u03a9\u0399\u1ff3\u1ff3\u1ff3',
        #                '\u1ff3\u1ff3\u1ffc\u1ffc', 'capitalize')
        # check with cased non-letter chars
        self.checkequal('\u24c5\u24e8\u24e3\u24d7\u24de\u24dd',
                        '\u24c5\u24ce\u24c9\u24bd\u24c4\u24c3', 'capitalize')
        self.checkequal('\u24c5\u24e8\u24e3\u24d7\u24de\u24dd',
                        '\u24df\u24e8\u24e3\u24d7\u24de\u24dd', 'capitalize')
        self.checkequal('\u2160\u2171\u2172',
                        '\u2160\u2161\u2162', 'capitalize')
        self.checkequal('\u2160\u2171\u2172',
                        '\u2170\u2171\u2172', 'capitalize')
        # check with Ll chars with no upper - nothing changes here
        self.checkequal('\u019b\u1d00\u1d86\u0221\u1fb7',
                        '\u019b\u1d00\u1d86\u0221\u1fb7', 'capitalize')

    def test_list_concat(self):
        # https://github.com/cython/cython/issues/3426
        y = []
        y += 'ab'
        self.assertEqual('a', y[0])
        self.assertEqual('b', y[1])
        self.assertEqual(['a', 'b'], y)


class MixinStrUnicodeUserStringTest:
    # additional tests that only work for
    # stringlike objects, i.e. str, UserString

    @unittest.skipIf(sys.version_info < (3, 5), 'Python str.startswith() test requires Py3.5+')
    def test_startswith(self):
        self.checkequal(True, 'hello', 'startswith', 'he')
        self.checkequal(True, 'hello', 'startswith', 'hello')
        self.checkequal(False, 'hello', 'startswith', 'hello world')
        self.checkequal(True, 'hello', 'startswith', '')
        self.checkequal(False, 'hello', 'startswith', 'ello')
        self.checkequal(True, 'hello', 'startswith', 'ello', 1)
        self.checkequal(True, 'hello', 'startswith', 'o', 4)
        self.checkequal(False, 'hello', 'startswith', 'o', 5)
        self.checkequal(True, 'hello', 'startswith', '', 5)
        self.checkequal(False, 'hello', 'startswith', 'lo', 6)
        self.checkequal(True, 'helloworld', 'startswith', 'lowo', 3)
        self.checkequal(True, 'helloworld', 'startswith', 'lowo', 3, 7)
        self.checkequal(False, 'helloworld', 'startswith', 'lowo', 3, 6)
        self.checkequal(True, '', 'startswith', '', 0, 1)
        self.checkequal(True, '', 'startswith', '', 0, 0)
        self.checkequal(False, '', 'startswith', '', 1, 0)

        # test negative indices
        self.checkequal(True, 'hello', 'startswith', 'he', 0, -1)
        self.checkequal(True, 'hello', 'startswith', 'he', -53, -1)
        self.checkequal(False, 'hello', 'startswith', 'hello', 0, -1)
        self.checkequal(False, 'hello', 'startswith', 'hello world', -1, -10)
        self.checkequal(False, 'hello', 'startswith', 'ello', -5)
        self.checkequal(True, 'hello', 'startswith', 'ello', -4)
        self.checkequal(False, 'hello', 'startswith', 'o', -2)
        self.checkequal(True, 'hello', 'startswith', 'o', -1)
        self.checkequal(True, 'hello', 'startswith', '', -3, -3)
        self.checkequal(False, 'hello', 'startswith', 'lo', -9)

        self.checkraises(TypeError, 'hello', 'startswith')
        self.checkraises(TypeError, 'hello', 'startswith', 42)

        # test tuple arguments
        self.checkequal(True, 'hello', 'startswith', ('he', 'ha'))
        self.checkequal(False, 'hello', 'startswith', ('lo', 'llo'))
        self.checkequal(True, 'hello', 'startswith', ('hellox', 'hello'))
        self.checkequal(False, 'hello', 'startswith', ())
        self.checkequal(True, 'helloworld', 'startswith', ('hellowo',
                                                           'rld', 'lowo'), 3)
        self.checkequal(False, 'helloworld', 'startswith', ('hellowo', 'ello',
                                                            'rld'), 3)
        self.checkequal(True, 'hello', 'startswith', ('lo', 'he'), 0, -1)
        self.checkequal(False, 'hello', 'startswith', ('he', 'hel'), 0, 1)
        self.checkequal(True, 'hello', 'startswith', ('he', 'hel'), 0, 2)

        self.checkraises(TypeError, 'hello', 'startswith', (42,))

    @unittest.skipIf(sys.version_info < (3, 5), 'Python str.endswith() test requires Py3.5+')
    def test_endswith(self):
        self.checkequal(True, 'hello', 'endswith', 'lo')
        self.checkequal(False, 'hello', 'endswith', 'he')
        self.checkequal(True, 'hello', 'endswith', '')
        self.checkequal(False, 'hello', 'endswith', 'hello world')
        self.checkequal(False, 'helloworld', 'endswith', 'worl')
        self.checkequal(True, 'helloworld', 'endswith', 'worl', 3, 9)
        self.checkequal(True, 'helloworld', 'endswith', 'world', 3, 12)
        self.checkequal(True, 'helloworld', 'endswith', 'lowo', 1, 7)
        self.checkequal(True, 'helloworld', 'endswith', 'lowo', 2, 7)
        self.checkequal(True, 'helloworld', 'endswith', 'lowo', 3, 7)
        self.checkequal(False, 'helloworld', 'endswith', 'lowo', 4, 7)
        self.checkequal(False, 'helloworld', 'endswith', 'lowo', 3, 8)
        self.checkequal(False, 'ab', 'endswith', 'ab', 0, 1)
        self.checkequal(False, 'ab', 'endswith', 'ab', 0, 0)
        self.checkequal(True, '', 'endswith', '', 0, 1)
        self.checkequal(True, '', 'endswith', '', 0, 0)
        self.checkequal(False, '', 'endswith', '', 1, 0)

        # test negative indices
        self.checkequal(True, 'hello', 'endswith', 'lo', -2)
        self.checkequal(False, 'hello', 'endswith', 'he', -2)
        self.checkequal(True, 'hello', 'endswith', '', -3, -3)
        self.checkequal(False, 'hello', 'endswith', 'hello world', -10, -2)
        self.checkequal(False, 'helloworld', 'endswith', 'worl', -6)
        self.checkequal(True, 'helloworld', 'endswith', 'worl', -5, -1)
        self.checkequal(True, 'helloworld', 'endswith', 'worl', -5, 9)
        self.checkequal(True, 'helloworld', 'endswith', 'world', -7, 12)
        self.checkequal(True, 'helloworld', 'endswith', 'lowo', -99, -3)
        self.checkequal(True, 'helloworld', 'endswith', 'lowo', -8, -3)
        self.checkequal(True, 'helloworld', 'endswith', 'lowo', -7, -3)
        self.checkequal(False, 'helloworld', 'endswith', 'lowo', 3, -4)
        self.checkequal(False, 'helloworld', 'endswith', 'lowo', -8, -2)

        self.checkraises(TypeError, 'hello', 'endswith')
        self.checkraises(TypeError, 'hello', 'endswith', 42)

        # test tuple arguments
        self.checkequal(False, 'hello', 'endswith', ('he', 'ha'))
        self.checkequal(True, 'hello', 'endswith', ('lo', 'llo'))
        self.checkequal(True, 'hello', 'endswith', ('hellox', 'hello'))
        self.checkequal(False, 'hello', 'endswith', ())
        self.checkequal(True, 'helloworld', 'endswith', ('hellowo',
                                                           'rld', 'lowo'), 3)
        self.checkequal(False, 'helloworld', 'endswith', ('hellowo', 'ello',
                                                            'rld'), 3, -1)
        self.checkequal(True, 'hello', 'endswith', ('hell', 'ell'), 0, -1)
        self.checkequal(False, 'hello', 'endswith', ('he', 'hel'), 0, 1)
        self.checkequal(True, 'hello', 'endswith', ('he', 'hell'), 0, 4)

        self.checkraises(TypeError, 'hello', 'endswith', (42,))

    def test___contains__(self):
        self.checkequal(True, '', '__contains__', '')
        self.checkequal(True, 'abc', '__contains__', '')
        self.checkequal(False, 'abc', '__contains__', '\0')
        self.checkequal(True, '\0abc', '__contains__', '\0')
        self.checkequal(True, 'abc\0', '__contains__', '\0')
        self.checkequal(True, '\0abc', '__contains__', 'a')
        self.checkequal(True, 'asdf', '__contains__', 'asdf')
        self.checkequal(False, 'asd', '__contains__', 'asdf')
        self.checkequal(False, '', '__contains__', 'asdf')

    def test_subscript(self):
        self.checkequal('a', 'abc', '__getitem__', 0)
        self.checkequal('c', 'abc', '__getitem__', -1)
        self.checkequal('a', 'abc', '__getitem__', 0)
        self.checkequal('abc', 'abc', '__getitem__', slice(0, 3))
        self.checkequal('abc', 'abc', '__getitem__', slice(0, 1000))
        self.checkequal('a', 'abc', '__getitem__', slice(0, 1))
        self.checkequal('', 'abc', '__getitem__', slice(0, 0))

        self.checkraises(TypeError, 'abc', '__getitem__', 'def')

    def test_slice(self):
        self.checkequal('abc', 'abc', '__getitem__', slice(0, 1000))
        self.checkequal('abc', 'abc', '__getitem__', slice(0, 3))
        self.checkequal('ab', 'abc', '__getitem__', slice(0, 2))
        self.checkequal('bc', 'abc', '__getitem__', slice(1, 3))
        self.checkequal('b', 'abc', '__getitem__', slice(1, 2))
        self.checkequal('', 'abc', '__getitem__', slice(2, 2))
        self.checkequal('', 'abc', '__getitem__', slice(1000, 1000))
        self.checkequal('', 'abc', '__getitem__', slice(2000, 1000))
        self.checkequal('', 'abc', '__getitem__', slice(2, 1))

        self.checkraises(TypeError, 'abc', '__getitem__', 'def')

    def test_extended_getslice(self):
        # Test extended slicing by comparing with list slicing.
        s = string.ascii_letters + string.digits
        indices = (0, None, 1, 3, 41, -1, -2, -37)
        for start in indices:
            for stop in indices:
                # Skip step 0 (invalid)
                for step in indices[1:]:
                    L = list(s)[start:stop:step]
                    self.checkequal("".join(L), s, '__getitem__',
                                    slice(start, stop, step))

    def test_mul(self):
        self.checkequal('', 'abc', '__mul__', -1)
        self.checkequal('', 'abc', '__mul__', 0)
        self.checkequal('abc', 'abc', '__mul__', 1)
        self.checkequal('abcabcabc', 'abc', '__mul__', 3)
        self.checkraises(TypeError, 'abc', '__mul__')
        self.checkraises(TypeError, 'abc', '__mul__', '')
        # XXX: on a 64-bit system, this doesn't raise an overflow error,
        # but either raises a MemoryError, or succeeds (if you have 54TiB)
        #self.checkraises(OverflowError, 10000*'abc', '__mul__', 2000000000)

    def test_join(self):
        # join now works with any sequence type
        # moved here, because the argument order is
        # different in string.join
        self.checkequal('a b c d', ' ', 'join', ['a', 'b', 'c', 'd'])
        self.checkequal('abcd', '', 'join', ('a', 'b', 'c', 'd'))
        self.checkequal('bd', '', 'join', ('', 'b', '', 'd'))
        self.checkequal('ac', '', 'join', ('a', '', 'c', ''))
        self.checkequal('w x y z', ' ', 'join', Sequence())
        self.checkequal('abc', 'a', 'join', ('abc',))
        #self.checkequal('z', 'a', 'join', UserList(['z']))
        self.checkequal('a.b.c', '.', 'join', ['a', 'b', 'c'])
        self.assertRaises(TypeError, '.'.join, ['a', 'b', 3])
        for i in [5, 25, 125]:
            self.checkequal(((('a' * i) + '-') * i)[:-1], '-', 'join',
                 ['a' * i] * i)
            self.checkequal(((('a' * i) + '-') * i)[:-1], '-', 'join',
                 ('a' * i,) * i)

        #self.checkequal(str(BadSeq1()), ' ', 'join', BadSeq1())
        self.checkequal('a b c', ' ', 'join', BadSeq2())

        self.checkraises(TypeError, ' ', 'join')
        self.checkraises(TypeError, ' ', 'join', None)
        self.checkraises(TypeError, ' ', 'join', 7)
        self.checkraises(TypeError, ' ', 'join', [1, 2, bytes()])
        try:
            def f():
                yield 4 + ""
            self.fixtype(' ').join(f())
        except TypeError as e:
            if '+' not in str(e):
                self.fail('join() ate exception message')
        else:
            self.fail('exception not raised')

    def test_formatting(self):
        self.checkequal('+hello+', '+%s+', '__mod__', 'hello')
        self.checkequal('+10+', '+%d+', '__mod__', 10)
        self.checkequal('a', "%c", '__mod__', "a")
        self.checkequal('a', "%c", '__mod__', "a")
        self.checkequal('"', "%c", '__mod__', 34)
        self.checkequal('$', "%c", '__mod__', 36)
        self.checkequal('10', "%d", '__mod__', 10)
        self.checkequal('\x7f', "%c", '__mod__', 0x7f)

        for ordinal in (-100, 0x200000):
            # unicode raises ValueError, str raises OverflowError
            self.checkraises((ValueError, OverflowError), '%c', '__mod__', ordinal)

        longvalue = sys.maxsize + 10
        slongvalue = str(longvalue)
        self.checkequal(' 42', '%3ld', '__mod__', 42)
        self.checkequal('42', '%d', '__mod__', 42.0)
        self.checkequal(slongvalue, '%d', '__mod__', longvalue)
        self.checkcall('%d', '__mod__', float(longvalue))
        self.checkequal('0042.00', '%07.2f', '__mod__', 42)
        self.checkequal('0042.00', '%07.2F', '__mod__', 42)

        self.checkraises(TypeError, 'abc', '__mod__')
        self.checkraises(TypeError, '%(foo)s', '__mod__', 42)
        self.checkraises(TypeError, '%s%s', '__mod__', (42,))
        self.checkraises(TypeError, '%c', '__mod__', (None,))
        self.checkraises(ValueError, '%(foo', '__mod__', {})
        self.checkraises(TypeError, '%(foo)s %(bar)s', '__mod__', ('foo', 42))
        self.checkraises(TypeError, '%d', '__mod__', "42") # not numeric
        self.checkraises(TypeError, '%d', '__mod__', (42+0j)) # no int conversion provided

        # argument names with properly nested brackets are supported
        self.checkequal('bar', '%((foo))s', '__mod__', {'(foo)': 'bar'})

        # 100 is a magic number in PyUnicode_Format, this forces a resize
        self.checkequal(103*'a'+'x', '%sx', '__mod__', 103*'a')

        self.checkraises(TypeError, '%*s', '__mod__', ('foo', 'bar'))
        self.checkraises(TypeError, '%10.*f', '__mod__', ('foo', 42.))
        self.checkraises(ValueError, '%10', '__mod__', (42,))

        # Outrageously large width or precision should raise ValueError.
        self.checkraises(ValueError, '%%%df' % (2**64), '__mod__', (3.2))
        self.checkraises(ValueError, '%%.%df' % (2**64), '__mod__', (3.2))
        self.checkraises(OverflowError, '%*s', '__mod__',
                         (sys.maxsize + 1, ''))
        self.checkraises(OverflowError, '%.*f', '__mod__',
                         (sys.maxsize + 1, 1. / 7))

        class X(object): pass
        self.checkraises(TypeError, 'abc', '__mod__', X())

    @support.cpython_only
    def test_formatting_c_limits(self):
        from _testcapi import PY_SSIZE_T_MAX, INT_MAX, UINT_MAX
        SIZE_MAX = (1 << (PY_SSIZE_T_MAX.bit_length() + 1)) - 1
        self.checkraises(OverflowError, '%*s', '__mod__',
                         (PY_SSIZE_T_MAX + 1, ''))
        self.checkraises(OverflowError, '%.*f', '__mod__',
                         (INT_MAX + 1, 1. / 7))
        # Issue 15989
        self.checkraises(OverflowError, '%*s', '__mod__',
                         (SIZE_MAX + 1, ''))
        self.checkraises(OverflowError, '%.*f', '__mod__',
                         (UINT_MAX + 1, 1. / 7))

    def test_floatformatting(self):
        # float formatting
        for prec in range(100):
            format = '%%.%if' % prec
            value = 0.01
            for x in range(60):
                value = value * 3.14159265359 / 3.0 * 10.0
                self.checkcall(format, "__mod__", value)

    def test_inplace_rewrites(self):
        # Check that strings don't copy and modify cached single-character strings
        self.checkequal('a', 'A', 'lower')
        self.checkequal(True, 'A', 'isupper')
        self.checkequal('A', 'a', 'upper')
        self.checkequal(True, 'a', 'islower')

        self.checkequal('a', 'A', 'replace', 'A', 'a')
        self.checkequal(True, 'A', 'isupper')

        self.checkequal('A', 'a', 'capitalize')
        self.checkequal(True, 'a', 'islower')

        self.checkequal('A', 'a', 'swapcase')
        self.checkequal(True, 'a', 'islower')

        self.checkequal('A', 'a', 'title')
        self.checkequal(True, 'a', 'islower')

    @unittest.skipIf(sys.version_info < (3, 5), 'Python str.partition() test requires Py3.5+')
    def test_partition(self):

        self.checkequal(('this is the par', 'ti', 'tion method'),
            'this is the partition method', 'partition', 'ti')

        # from raymond's original specification
        S = 'http://www.python.org'
        self.checkequal(('http', '://', 'www.python.org'), S, 'partition', '://')
        self.checkequal(('http://www.python.org', '', ''), S, 'partition', '?')
        self.checkequal(('', 'http://', 'www.python.org'), S, 'partition', 'http://')
        self.checkequal(('http://www.python.', 'org', ''), S, 'partition', 'org')

        self.checkraises(ValueError, S, 'partition', '')
        self.checkraises(TypeError, S, 'partition', None)

    @unittest.skipIf(sys.version_info < (3, 5), 'Python str.rpartition() test requires Py3.5+')
    def test_rpartition(self):

        self.checkequal(('this is the rparti', 'ti', 'on method'),
            'this is the rpartition method', 'rpartition', 'ti')

        # from raymond's original specification
        S = 'http://www.python.org'
        self.checkequal(('http', '://', 'www.python.org'), S, 'rpartition', '://')
        self.checkequal(('', '', 'http://www.python.org'), S, 'rpartition', '?')
        self.checkequal(('', 'http://', 'www.python.org'), S, 'rpartition', 'http://')
        self.checkequal(('http://www.python.', 'org', ''), S, 'rpartition', 'org')

        self.checkraises(ValueError, S, 'rpartition', '')
        self.checkraises(TypeError, S, 'rpartition', None)

    def test_none_arguments(self):
        # issue 11828
        s = 'hello'
        self.checkequal(2, s, 'find', 'l', None)
        self.checkequal(3, s, 'find', 'l', -2, None)
        self.checkequal(2, s, 'find', 'l', None, -2)
        self.checkequal(0, s, 'find', 'h', None, None)

        self.checkequal(3, s, 'rfind', 'l', None)
        self.checkequal(3, s, 'rfind', 'l', -2, None)
        self.checkequal(2, s, 'rfind', 'l', None, -2)
        self.checkequal(0, s, 'rfind', 'h', None, None)

        self.checkequal(2, s, 'index', 'l', None)
        self.checkequal(3, s, 'index', 'l', -2, None)
        self.checkequal(2, s, 'index', 'l', None, -2)
        self.checkequal(0, s, 'index', 'h', None, None)

        self.checkequal(3, s, 'rindex', 'l', None)
        self.checkequal(3, s, 'rindex', 'l', -2, None)
        self.checkequal(2, s, 'rindex', 'l', None, -2)
        self.checkequal(0, s, 'rindex', 'h', None, None)

        self.checkequal(2, s, 'count', 'l', None)
        self.checkequal(1, s, 'count', 'l', -2, None)
        self.checkequal(1, s, 'count', 'l', None, -2)
        self.checkequal(0, s, 'count', 'x', None, None)

        self.checkequal(True, s, 'endswith', 'o', None)
        self.checkequal(True, s, 'endswith', 'lo', -2, None)
        self.checkequal(True, s, 'endswith', 'l', None, -2)
        self.checkequal(False, s, 'endswith', 'x', None, None)

        self.checkequal(True, s, 'startswith', 'h', None)
        self.checkequal(True, s, 'startswith', 'l', -2, None)
        self.checkequal(True, s, 'startswith', 'h', None, -2)
        self.checkequal(False, s, 'startswith', 'x', None, None)

    def test_find_etc_raise_correct_error_messages(self):
        # issue 11828
        s = 'hello'
        x = 'x'
        self.assertRaisesRegex(TypeError, r'^find\(', s.find,
                                x, None, None, None)
        self.assertRaisesRegex(TypeError, r'^rfind\(', s.rfind,
                                x, None, None, None)
        self.assertRaisesRegex(TypeError, r'^index\(', s.index,
                                x, None, None, None)
        self.assertRaisesRegex(TypeError, r'^rindex\(', s.rindex,
                                x, None, None, None)
        self.assertRaisesRegex(TypeError, r'^count\(', s.count,
                                x, None, None, None)
        self.assertRaisesRegex(TypeError, r'^startswith\(', s.startswith,
                                x, None, None, None)
        self.assertRaisesRegex(TypeError, r'^endswith\(', s.endswith,
                                x, None, None, None)

        # issue #15534
        self.checkequal(10, "...\u043c......<", "find", "<")


class MixinStrUnicodeTest:
    # Additional tests that only work with str.

    def test_bug1001011(self):
        # Make sure join returns a NEW object for single item sequences
        # involving a subclass.
        # Make sure that it is of the appropriate type.
        # Check the optimisation still occurs for standard objects.
        t = self.type2test
        class subclass(t):
            pass
        s1 = subclass("abcd")
        s2 = t().join([s1])
        self.assertIsNot(s1, s2)
        self.assertIs(type(s2), t)

        s1 = t("abcd")
        s2 = t().join([s1])
        self.assertIs(s1, s2)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/testinclude.pxi0000644000175100001770000000003700000000000020607 0ustar00runnerdocker00000000000000# this will be included

D = 2
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/ticket_123.pyx0000644000175100001770000000052000000000000020151 0ustar00runnerdocker00000000000000__doc__ = u"""
>>> ret = repeat_iter()
>>> for s in ret:
...     print(s)
a
a
b
b
c
c
"""

def repeat_iter():
    cdef dict e
    cdef unicode s
    ret = []
    e = {u"A": u"a", u"B": u"b", u"C": u"c"}
    for s in e.itervalues():
        ret.append(s)
    for s in e.itervalues():
        ret.append(s)

    ret.sort()
    return ret
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/ticket_124.pyx0000644000175100001770000000017600000000000020161 0ustar00runnerdocker00000000000000def spam(dict d):
    """
    >>> spam(dict(test=2))
    False
    """
    for elm in d:
        return False
    return True
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/time_pxd.pyx0000644000175100001770000000330000000000000020111 0ustar00runnerdocker00000000000000# mode: run
# tag: py3only,pytime

import time

from cpython cimport time as ctime


def test_time():
    """
    >>> tic1, tic2, tic3 = test_time()
    >>> tic1 <= tic3  # sanity check
    True
    >>> tic1 <= tic2
    True
    >>> tic2 <= tic3
    True
    """
    # check that ctime.time() matches time.time() to within call-time tolerance
    tic1 = time.time()
    tic2 = ctime.time()
    tic3 = time.time()

    return tic1, tic2, tic3


def test_localtime():
    """
    >>> ltp, ltc = test_localtime()
    >>> ltp.tm_year == ltc['tm_year']  or  (ltp.tm_year, ltc['tm_year'])
    True
    >>> ltp.tm_mon == ltc['tm_mon']  or  (ltp.tm_mon, ltc['tm_mon'])
    True
    >>> ltp.tm_mday == ltc['tm_mday']  or  (ltp.tm_mday, ltc['tm_mday'])
    True
    >>> ltp.tm_hour == ltc['tm_hour']  or  (ltp.tm_hour, ltc['tm_hour'])
    True
    >>> ltp.tm_min == ltc['tm_min']  or  (ltp.tm_min, ltc['tm_min'])
    True
    >>> ltp.tm_sec == ltc['tm_sec']  or  (ltp.tm_sec, ltc['tm_sec'])
    True
    >>> ltp.tm_wday == ltc['tm_wday']  or (ltp.tm_wday, ltc['tm_wday'])
    True
    >>> ltp.tm_yday == ltc['tm_yday']  or  (ltp.tm_yday, ltc['tm_yday'])
    True
    >>> ltp.tm_isdst == ltc['tm_isdst']  or  (ltp.tm_isdst, ltc['tm_isdst'])
    True
    """
    ltp = time.localtime()
    ltc = ctime.localtime()

    i = 0
    while ltp.tm_sec != ltc.tm_sec:
        # If the time.localtime call is just before the end of a second and the
        #  ctime.localtime call is just after the beginning of the next second,
        #  re-call.  This should not occur twice in a row.
        time.sleep(0.1)
        ltp = time.localtime()
        ltc = ctime.localtime()
        i += 1
        if i > 10:
            break

    return ltp, ltc
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/tp_new.pyx0000644000175100001770000001315500000000000017605 0ustar00runnerdocker00000000000000# mode: run
# tag: exttype, tpnew
# ticket: t808

cimport cython

cdef class MyType:
    cdef public args, kwargs
    def __cinit__(self, *args, **kwargs):
        self.args, self.kwargs = args, kwargs
        print "CINIT"
    def __init__(self, *args, **kwargs):
        print "INIT"

cdef class MySubType(MyType):
    def __cinit__(self, *args, **kwargs):
        self.args, self.kwargs = args, kwargs
        print "CINIT(SUB)"
    def __init__(self, *args, **kwargs):
        print "INIT"

class MyClass(object):
    def __cinit__(self, *args, **kwargs):
        self.args, self.kwargs = args, kwargs
        print "CINIT"
    def __init__(self, *args, **kwargs):
        print "INIT"

class MyTypeSubClass(MyType):
    def __cinit__(self, *args, **kwargs):
        # not called: Python class!
        print "CINIT(PYSUB)"
    def __init__(self, *args, **kwargs):
        print "INIT"

# See ticket T808, vtab must be set even if there is no __cinit__.

cdef class Base(object):
    pass

cdef class Derived(Base):
    cpdef int f(self):
        return 42

def test_derived_vtab():
    """
    >>> test_derived_vtab()
    42
    """
    cdef Derived d = Derived.__new__(Derived)
    return d.f()


# only these can be safely optimised:

@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists(
    '//SimpleCallNode/AttributeNode',
    '//PyMethodCallNode',
)
def make_new():
    """
    >>> isinstance(make_new(), MyType)
    CINIT
    True
    """
    m = MyType.__new__(MyType)
    return m

@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists(
    '//SimpleCallNode/AttributeNode',
    '//PyMethodCallNode',
)
def make_new_typed_target():
    """
    >>> isinstance(make_new_typed_target(), MyType)
    CINIT
    True
    """
    cdef MyType m
    m = MyType.__new__(MyType)
    return m

@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists(
    '//SimpleCallNode/AttributeNode',
    '//PyMethodCallNode',
)
def make_new_with_args():
    """
    >>> isinstance(make_new_with_args(), MyType)
    CINIT
    (1, 2, 3)
    {}
    True
    """
    m = MyType.__new__(MyType, 1, 2 ,3)
    print m.args
    print m.kwargs
    return m

@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists(
    '//SimpleCallNode/AttributeNode',
    '//PyMethodCallNode',
)
def make_new_with_args_kwargs():
    """
    >>> isinstance(make_new_with_args_kwargs(), MyType)
    CINIT
    (1, 2, 3)
    {'a': 4}
    True
    """
    m = MyType.__new__(MyType, 1, 2 ,3, a=4)
    print m.args
    print m.kwargs
    return m

@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists(
    '//SimpleCallNode/AttributeNode',
    '//PyMethodCallNode',
)
def make_new_builtin():
    """
    >>> isinstance(make_new_builtin(), tuple)
    True
    """
    m = dict.__new__(dict)
    m = list.__new__(list)
    m = tuple.__new__(tuple)
    return m

@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists(
    '//SimpleCallNode/AttributeNode',
    '//PyMethodCallNode',
)
def make_new_none(type t=None):
    """
    >>> make_new_none()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ... is not a type object (NoneType)
    """
    m = t.__new__(t)
    return m

@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists(
    '//SimpleCallNode/AttributeNode',
    '//PyMethodCallNode',
)
def make_new_kwargs(type t=None):
    """
    >>> m = make_new_kwargs(MyType)
    CINIT
    >>> isinstance(m, MyType)
    True
    >>> m.args
    (1, 2, 3)
    >>> m.kwargs
    {'a': 5}
    """
    m = t.__new__(t, 1, 2, 3, a=5)
    return m

# these cannot:

@cython.test_assert_path_exists('//PyMethodCallNode/AttributeNode')
@cython.test_fail_if_path_exists('//PythonCapiCallNode')
def make_new_pyclass():
    """
    >>> isinstance(make_new_pyclass(), MyTypeSubClass)
    CINIT
    True
    """
    m = MyClass.__new__(MyClass)
    m = MyTypeSubClass.__new__(MyTypeSubClass)
    return m

@cython.test_assert_path_exists('//PyMethodCallNode/AttributeNode')
@cython.test_fail_if_path_exists('//PythonCapiCallNode')
def make_new_args(type t1=None, type t2=None):
    """
    >>> isinstance(make_new_args(), MyType)
    CINIT
    True
    >>> isinstance(make_new_args(MyType), MyType)
    CINIT
    True
    >>> isinstance(make_new_args(MyType, MyType), MyType)
    CINIT
    True

    >>> isinstance(make_new_args(MyType, MySubType), MySubType)
    Traceback (most recent call last):
    TypeError: tp_new.MyType.__new__(tp_new.MySubType) is not safe, use tp_new.MySubType.__new__()
    >>> isinstance(make_new_args(MySubType, MyType), MyType)
    Traceback (most recent call last):
    TypeError: tp_new.MySubType.__new__(tp_new.MyType): tp_new.MyType is not a subtype of tp_new.MySubType
    """
    if t1 is None:
        t1 = MyType
    if t2 is None:
        t2 = MyType
    m = t1.__new__(t2)
    return m

@cython.test_assert_path_exists('//PyMethodCallNode/AttributeNode')
@cython.test_fail_if_path_exists('//PythonCapiCallNode')
def make_new_none_typed(tuple t=None):
    """
    >>> make_new_none_typed()  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ... is not a type object (NoneType)
    """
    m = t.__new__(t)
    return m

@cython.test_assert_path_exists('//PyMethodCallNode/AttributeNode')
@cython.test_fail_if_path_exists('//PythonCapiCallNode')
def make_new_untyped(t):
    """
    >>> make_new_untyped(None)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ... is not a type object (NoneType)
    """
    m = t.__new__(t)
    return m
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/tp_new_T454.pyx0000644000175100001770000000061500000000000020322 0ustar00runnerdocker00000000000000# ticket: t454

cimport cython

cdef class TypeWithFactory:
    @cython.test_assert_path_exists('//PythonCapiCallNode')
    @cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
    @classmethod
    def new(cls):
        return cls.__new__(cls)

def make_new_factory():
    """
    >>> isinstance(make_new_factory(), TypeWithFactory)
    True
    """
    return TypeWithFactory.new()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/tp_new_cimport.srctree0000644000175100001770000000343700000000000022173 0ustar00runnerdocker00000000000000PYTHON setup.py build_ext --inplace
PYTHON -c "import tp_new_tests; tp_new_tests.test_all()"
PYTHON -c "import tp_new_tests; tp_new_tests.test_sub()"

######## setup.py ########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup

setup(
    ext_modules = cythonize("**/*.pyx"),
    )

######## tp_new_tests.py ########

def test_all():
    test_a()
    test_b()
    test_a_in_b()
    test_sub()

def test_a():
    import a
    assert isinstance(a.tpnew_ExtTypeA(), a.ExtTypeA)
    assert a.tpnew_ExtTypeA().attrA == 123

def test_b():
    import b
    assert isinstance(b.tpnew_ExtTypeB(), b.ExtTypeB)
    assert b.tpnew_ExtTypeB().attrB == 234

def test_a_in_b():
    import a,b
    assert isinstance(b.tpnew_ExtTypeA(), a.ExtTypeA)
    assert b.tpnew_ExtTypeA().attrA == 123

def test_sub():
    import b
    assert isinstance(b.tpnew_SubExtTypeA(), b.SubExtTypeA)
    assert b.tpnew_SubExtTypeA().attrAB == 345
    assert b.tpnew_SubExtTypeA().attrA == 123

######## a.pxd ########

cdef api class ExtTypeA[type ExtTypeA_Type, object ExtTypeAObject]:
    cdef readonly attrA

######## a.pyx ########

cdef class ExtTypeA:
    def __cinit__(self):
        self.attrA = 123

def tpnew_ExtTypeA():
    return ExtTypeA.__new__(ExtTypeA)

######## b.pxd ########

from a cimport ExtTypeA

cdef class ExtTypeB:
    cdef readonly attrB

cdef class SubExtTypeA(ExtTypeA):
    cdef readonly attrAB

######## b.pyx ########

from a cimport ExtTypeA

cdef class ExtTypeB:
    def __cinit__(self):
        self.attrB = 234

cdef class SubExtTypeA(ExtTypeA):
    def __cinit__(self):
        self.attrAB = 345

def tpnew_ExtTypeA():
    return ExtTypeA.__new__(ExtTypeA)

def tpnew_ExtTypeB():
    return ExtTypeB.__new__(ExtTypeB)

def tpnew_SubExtTypeA():
    return SubExtTypeA.__new__(SubExtTypeA)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/trace_nogil.pyx0000644000175100001770000000063000000000000020571 0ustar00runnerdocker00000000000000# cython: linetrace=True

cdef void foo(int err) except * nogil:
    with gil:
        raise ValueError(err)


# Test from gh-4637
def handler(int err):
    """
    >>> handler(0)
    All good
    >>> handler(1)    # doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    ValueError: 1
    """
    if (err % 2):
        with nogil:
            foo(err)
    else:
        print("All good")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/tracebacks.pyx0000644000175100001770000000141000000000000020402 0ustar00runnerdocker00000000000000# tag: traceback

def foo1():
  foo2()

cdef foo2():
  foo3()

cdef int foo3() except -1:
  raise RuntimeError('my_message')

def test_traceback(cline_in_traceback=None):
  """
  >>> test_traceback()
  >>> test_traceback(True)
  >>> test_traceback(False)
  """
  if cline_in_traceback is not None:
    import cython_runtime
    cython_runtime.cline_in_traceback = cline_in_traceback
  try:
    foo1()
  except:
    import traceback
    tb_string = traceback.format_exc()
    expected = (
      'tracebacks.pyx',
      'foo1', 'foo2', 'foo3',
      'line 4', 'line 7', 'line 10',
      'my_message')
    for s in expected:
      assert s in tb_string, s
    if cline_in_traceback:
      assert 'tracebacks.c' in tb_string
    else:
      assert 'tracebacks.c' not in tb_string
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/trashcan.pyx0000644000175100001770000000766200000000000020122 0ustar00runnerdocker00000000000000# mode: run

cimport cython

import sys

# The tests here are to do with a deterministic order of destructors which
# isn't reliable for PyPy. Therefore, on PyPy we treat the test as
# "compiles and doesn't crash"
IS_PYPY = hasattr(sys, 'pypy_version_info')

# Count number of times an object was deallocated twice. This should remain 0.
cdef int double_deallocations = 0
def assert_no_double_deallocations():
    if IS_PYPY:
        return
    global double_deallocations
    err = double_deallocations
    double_deallocations = 0
    assert not err


# Compute x = f(f(f(...(None)...))) nested n times and throw away the result.
# The real test happens when exiting this function: then a big recursive
# deallocation of x happens. We are testing two things in the tests below:
# that Python does not crash and that no double deallocation happens.
# See also https://github.com/python/cpython/pull/11841
def recursion_test(f, int n=2**20):
    x = None
    cdef int i
    for i in range(n):
        x = f(x)


@cython.trashcan(True)
cdef class Recurse:
    """
    >>> recursion_test(Recurse)
    >>> assert_no_double_deallocations()
    """
    cdef public attr
    cdef int deallocated

    def __cinit__(self, x):
        self.attr = x

    def __dealloc__(self):
        # Check that we're not being deallocated twice
        global double_deallocations
        double_deallocations += self.deallocated
        self.deallocated = 1


cdef class RecurseSub(Recurse):
    """
    >>> recursion_test(RecurseSub)
    >>> assert_no_double_deallocations()
    """
    cdef int subdeallocated

    def __dealloc__(self):
        # Check that we're not being deallocated twice
        global double_deallocations
        double_deallocations += self.subdeallocated
        self.subdeallocated = 1


@cython.freelist(4)
@cython.trashcan(True)
cdef class RecurseFreelist:
    """
    >>> recursion_test(RecurseFreelist)
    >>> recursion_test(RecurseFreelist, 1000)
    >>> assert_no_double_deallocations()
    """
    cdef public attr
    cdef int deallocated

    def __cinit__(self, x):
        self.attr = x

    def __dealloc__(self):
        # Check that we're not being deallocated twice
        global double_deallocations
        double_deallocations += self.deallocated
        self.deallocated = 1


# Subclass of list => uses trashcan by default
# As long as https://github.com/python/cpython/pull/11841 is not fixed,
# this does lead to double deallocations, so we skip that check.
cdef class RecurseList(list):
    """
    >>> RecurseList(42)
    [42]
    >>> recursion_test(RecurseList)
    """
    def __init__(self, x):
        super().__init__((x,))


# Some tests where the trashcan is NOT used. When the trashcan is not used
# in a big recursive deallocation, the __dealloc__s of the base classes are
# only run after the __dealloc__s of the subclasses.
# We use this to detect trashcan usage.
cdef int base_deallocated = 0
cdef int trashcan_used = 0
def assert_no_trashcan_used():
    if IS_PYPY:
        return
    global base_deallocated, trashcan_used
    err = trashcan_used
    trashcan_used = base_deallocated = 0
    assert not err


cdef class Base:
    def __dealloc__(self):
        global base_deallocated
        base_deallocated = 1


# Trashcan disabled by default
cdef class Sub1(Base):
    """
    >>> recursion_test(Sub1, 100)
    >>> assert_no_trashcan_used()
    """
    cdef public attr

    def __cinit__(self, x):
        self.attr = x

    def __dealloc__(self):
        global base_deallocated, trashcan_used
        trashcan_used += base_deallocated


@cython.trashcan(True)
cdef class Middle(Base):
    cdef public foo


# Trashcan disabled explicitly
@cython.trashcan(False)
cdef class Sub2(Middle):
    """
    >>> recursion_test(Sub2, 1000)
    >>> assert_no_trashcan_used()
    """
    cdef public attr

    def __cinit__(self, x):
        self.attr = x

    def __dealloc__(self):
        global base_deallocated, trashcan_used
        trashcan_used += base_deallocated
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/trybreak.pyx0000644000175100001770000000122200000000000020124 0ustar00runnerdocker00000000000000# Indirectly makes sure the cleanup happens correctly on breaking.

def try_except_break():
    """
    >>> print(try_except_break())
    a
    """
    for x in list("abc"):
        try:
            x()
        except:
            break
    return x

def try_break_except():
    """
    >>> print(try_break_except())
    a
    """
    for x in list("abc"):
        try:
            break
        except:
            pass
    return x

def try_no_break_except_return():
    """
    >>> print(try_no_break_except_return())
    a
    """
    for x in list("abc"):
        try:
            x()
            break
        except:
            return x
    return x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/tryexcept.pyx0000644000175100001770000002542600000000000020344 0ustar00runnerdocker00000000000000def single_except(a, x):
    """
    >>> single_except(ValueError, None)
    2
    >>> single_except(ValueError, ValueError('test'))
    3
    >>> single_except(ValueError, TypeError('test'))
    Traceback (most recent call last):
    TypeError: test
    """
    cdef int i
    try:
        i = 1
        if x:
            raise x
        i = 2
    except a:
        i = 3
    return i

def single_except_builtin(a, x):
    """
    >>> single_except_builtin(ValueError, None)
    2
    >>> single_except_builtin(ValueError, ValueError('test'))
    3
    >>> single_except_builtin(ValueError, TypeError('test'))
    Traceback (most recent call last):
    TypeError: test
    """
    cdef int i
    try:
        i = 1
        if x:
            raise x
        i = 2
    except ValueError:
        i = 3
    return i

def single_except_expression(a, x):
    """
    >>> single_except_expression([[ValueError]], None)
    2
    >>> single_except_expression([[ValueError]], ValueError('test'))
    3
    >>> single_except_expression([[ValueError]], TypeError('test'))
    Traceback (most recent call last):
    TypeError: test
    """
    cdef int i
    try:
        i = 1
        if x:
            raise x
        i = 2
    except a[0][0]:
        i = 3
    return i


exceptions = (ValueError, TypeError)


def single_except_global_tuple(x):
    """
    >>> single_except_global_tuple(None)
    2
    >>> single_except_global_tuple(ValueError('test'))
    3
    >>> single_except_global_tuple(TypeError('test'))
    3
    >>> class TypeErrorSubtype(TypeError): pass
    >>> single_except_global_tuple(TypeErrorSubtype('test'))
    3
    >>> single_except_global_tuple(AttributeError('test'))
    Traceback (most recent call last):
    AttributeError: test
    """
    cdef int i
    try:
        i = 1
        if x:
            raise x
        i = 2
    except exceptions:
        i = 3
    return i


def double_except_no_raise(a,b):
    """
    >>> double_except_no_raise(TypeError, ValueError)
    1
    """
    d = a or b  # mark used

    cdef int i
    try:
        i = 1
    except a:
        i = 2
    except b:
        i = 3
    return i

def double_except_raise(x, a, b):
    """
    >>> double_except_raise(None, TypeError, ValueError)
    1
    >>> double_except_raise(TypeError('test'), TypeError, ValueError)
    2
    >>> double_except_raise(ValueError('test'), TypeError, ValueError)
    3
    >>> double_except_raise(None, TypeError, ValueError)
    1
    """
    cdef int i
    try:
        i = 1
        if x:
            raise x
    except a:
        i = 2
    except b:
        i = 3
    return i

def target_except_no_raise(a):
    """
    >>> target_except_no_raise(TypeError)
    1
    """
    d = a  # mark used

    cdef int i
    try:
        i = 1
    except a, b:
        i = 2
    return i

def target_except_raise(x, a):
    """
    >>> target_except_raise(None, TypeError)
    1
    >>> target_except_raise(TypeError('test'), TypeError)
    2
    >>> target_except_raise(ValueError('test'), TypeError)
    Traceback (most recent call last):
    ValueError: test
    >>> target_except_raise(None, TypeError)
    1
    """
    cdef int i
    try:
        i = 1
        if x:
            raise x
    except a, b:
        i = 2
        assert isinstance(b, a)
    return i

def tuple_except_builtin(x):
    """
    >>> tuple_except_builtin(None)
    1
    >>> tuple_except_builtin(TypeError('test'))
    2
    >>> tuple_except_builtin(ValueError('test'))
    2
    >>> tuple_except_builtin(IndexError('5'))
    Traceback (most recent call last):
    IndexError: 5
    >>> tuple_except_builtin(None)
    1
    """
    cdef int i
    try:
        i = 1
        if x:
            raise x
    except (TypeError, ValueError):
        i = 2
    return i

def normal_and_bare_except_no_raise(a):
    """
    >>> normal_and_bare_except_no_raise(TypeError)
    1
    """
    d = a  # mark used

    cdef int i
    try:
        i = 1
    except a:
        i = 2
    except:
        i = 3
    return i

def normal_and_bare_except_raise(x, a):
    """
    >>> normal_and_bare_except_raise(None, TypeError)
    1
    >>> normal_and_bare_except_raise(TypeError('test'), TypeError)
    2
    >>> normal_and_bare_except_raise(ValueError('test'), TypeError)
    3
    >>> normal_and_bare_except_raise(TypeError('test'), (TypeError, ValueError))
    2
    >>> normal_and_bare_except_raise(ValueError('test'), (TypeError, ValueError))
    2
    >>> normal_and_bare_except_raise(None, TypeError)
    1
    """
    cdef int i
    try:
        i = 1
        if x:
            raise x
    except a:
        i = 2
    except:
        i = 3
    return i

def tuple_except_index_target_no_raise(a, b, c):
    """
    >>> l = [None, None]
    >>> tuple_except_index_target_no_raise(TypeError, ValueError, l)
    1
    >>> l
    [None, None]
    """
    d = a or b or c  # mark used

    cdef int i
    try:
        i = 1
    except (a, b), c[1]:
        i = 2
    return i

def tuple_except_index_target_raise(x, a, b, c):
    """
    >>> l = [None, None]
    >>> tuple_except_index_target_raise(None, TypeError, ValueError, l)
    1
    >>> l
    [None, None]
    >>> tuple_except_index_target_raise(TypeError('test'), TypeError, ValueError, l)
    2
    >>> l[0] is None, isinstance(l[1], TypeError)
    (True, True)
    >>> tuple_except_index_target_raise(ValueError('test'), TypeError, ValueError, l)
    2
    >>> l[0] is None, isinstance(l[1], ValueError)
    (True, True)
    >>> tuple_except_index_target_raise(IndexError('5'), TypeError, ValueError, l)
    Traceback (most recent call last):
    IndexError: 5
    >>> tuple_except_index_target_raise(None, TypeError, ValueError, l)
    1
    >>> l[0] is None, isinstance(l[1], ValueError)
    (True, True)
    """
    cdef int i
    try:
        i = 1
        if x:
            raise x
    except (a, b), c[1]:
        i = 2
        assert isinstance(c[1], (a,b))
    return i

def loop_bare_except_no_raise(a, b, int c):
    """
    >>> loop_bare_except_no_raise(TypeError, range(2), 2)
    (1, 3528)
    """
    cdef int i = 1
    for a in b:
        try:
            c = c * 42
        except:
            i = 17
    return i,c

def loop_bare_except_raise(a, b, int c):
    """
    >>> loop_bare_except_raise(TypeError, range(2), 2)
    (1, 3528)
    >>> loop_bare_except_raise(TypeError, range(3), 2)
    (17, 148176)
    >>> loop_bare_except_raise(TypeError, range(4), 2)
    (17, 6223392)
    """
    cdef int i = 1
    for a in b:
        try:
            c = c * 42
            if a == 2:
                raise TypeError('test')
        except:
            i = 17
    return i,c

def bare_except_reraise_no_raise(l):
    """
    >>> l = [None]
    >>> bare_except_reraise_no_raise(l)
    1
    >>> l
    [None]
    """
    d = l  # mark used

    cdef int i
    try:
        i = 1
    except:
        l[0] = 2
        raise
    return i

def bare_except_reraise_raise(x, l):
    """
    >>> l = [None]
    >>> bare_except_reraise_raise(None, l)
    1
    >>> l
    [None]
    >>> bare_except_reraise_raise(TypeError('test'), l)
    Traceback (most recent call last):
    TypeError: test
    >>> l
    [2]
    >>> l = [None]
    >>> bare_except_reraise_raise(None, l)
    1
    >>> l
    [None]
    """
    cdef int i
    try:
        i = 1
        if x:
            raise x
    except:
        l[0] = 2
        raise
    return i

def except_as_no_raise(a):
    """
    >>> except_as_no_raise(TypeError)
    1
    """
    d = a  # mark used

    try:
        i = 1
    except a as b:
        i = 2
    return i

def except_as_raise(x, a):
    """
    >>> except_as_raise(None, TypeError)
    1
    >>> except_as_raise(TypeError('test'), TypeError)
    2
    >>> except_as_raise(ValueError('test'), TypeError)
    Traceback (most recent call last):
    ValueError: test
    >>> except_as_raise(None, TypeError)
    1
    """
    try:
        i = 1
        if x:
            raise x
    except a as b:
        i = 2
        assert isinstance(b, a)
    return i

def except_as_no_raise_does_not_touch_target(a):
    """
    >>> i,b = except_as_no_raise_does_not_touch_target(TypeError)
    >>> i
    1
    >>> b
    1
    """
    d = a  # mark used

    b = 1
    try:
        i = 1
    except a as b:
        i = 2
    return i, b

def except_as_raise_does_not_delete_target(x, a):
    """
    >>> except_as_raise_does_not_delete_target(None, TypeError)
    1
    >>> except_as_raise_does_not_delete_target(TypeError('test'), TypeError)
    2
    >>> except_as_raise_does_not_delete_target(ValueError('test'), TypeError)
    Traceback (most recent call last):
    ValueError: test
    >>> except_as_raise_does_not_delete_target(None, TypeError)
    1
    """
    b = 1
    try:
        i = 1
        if x:
            raise x
    except a as b:
        i = 2
        assert isinstance(b, a)

    # exception variable leaks with Py2 except-as semantics
    if x:
        assert isinstance(b, a)
    else:
        assert b == 1
    return i

def except_as_raise_with_empty_except(x, a):
    """
    >>> except_as_raise_with_empty_except(None, TypeError)
    >>> except_as_raise_with_empty_except(TypeError('test'), TypeError)
    >>> except_as_raise_with_empty_except(ValueError('test'), TypeError)
    Traceback (most recent call last):
    ValueError: test
    >>> except_as_raise_with_empty_except(None, TypeError)
    """
    try:
        if x:
            raise x
        b = 1
    except a as b:
        pass
    if x:
        assert isinstance(b, a)
    else:
        assert b == 1

def complete_except_as_no_raise(a, b):
    """
    >>> complete_except_as_no_raise(TypeError, ValueError)
    5
    """
    d = a or b  # mark used

    try:
        i = 1
    except (a, b) as c:
        i = 2
    except (b, a) as c:
        i = 3
    except:
        i = 4
    else:
        i = 5
    return i

def complete_except_as_raise(x, a, b):
    """
    >>> complete_except_as_raise(None, TypeError, ValueError)
    5
    >>> complete_except_as_raise(TypeError('test'), TypeError, ValueError)
    2
    >>> complete_except_as_raise(ValueError('test'), TypeError, ValueError)
    2
    >>> complete_except_as_raise(IndexError('5'), TypeError, ValueError)
    4
    >>> complete_except_as_raise(None, TypeError, ValueError)
    5
    """
    try:
        i = 1
        if x:
            raise x
    except (a, b) as c:
        i = 2
        assert isinstance(c, (a, b))
    except (b, a) as c:
        i = 3
        assert isinstance(c, (a, b))
    except:
        i = 4
    else:
        i = 5
    return i


def try_except_raise_new(initial, catch, throw):
    """
    >>> try_except_raise_new(None, TypeError, ValueError)
    >>> try_except_raise_new(TypeError, IndexError, ValueError)
    Traceback (most recent call last):
    TypeError
    >>> try_except_raise_new(TypeError, TypeError, ValueError)
    Traceback (most recent call last):
    ValueError
    """
    try:
        if initial is not None:
            raise initial
    except catch:
        raise throw
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/tryfinally.pyx0000644000175100001770000003165500000000000020513 0ustar00runnerdocker00000000000000# mode: run
# tag: tryfinally

import string
import sys
IS_PY3 = sys.version_info[0] >= 3

cimport cython

try:
    next
except NameError:
    def next(it): return it.next()


def finally_except():
    """
    >>> try:
    ...     raise ValueError
    ... finally:
    ...     raise TypeError
    Traceback (most recent call last):
    TypeError
    >>> finally_except()
    Traceback (most recent call last):
    TypeError
    """
    try:
        raise ValueError
    finally:
        raise TypeError


def finally_pass():
    """
    >>> finally_pass()
    Traceback (most recent call last):
    ValueError
    """
    try:
        raise ValueError()
    finally:
        pass


def except_finally_reraise():
    """
    >>> def py_check():
    ...     try: raise ValueError
    ...     except ValueError:
    ...         for i in range(2):
    ...             try: raise TypeError
    ...             finally:
    ...                 break
    ...         assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
    ...         raise
    ...
    >>> py_check()
    Traceback (most recent call last):
    ValueError
    >>> except_finally_reraise()
    Traceback (most recent call last):
    ValueError
    """
    try:
        raise ValueError
    except ValueError:
        for i in range(2):
            try:
                raise TypeError
            finally:
                break
        assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
        raise


def except_finally_reraise_new():
    """
    >>> def py_check():
    ...     try: raise ValueError
    ...     except ValueError:
    ...         try: raise TypeError
    ...         finally:
    ...             raise
    >>> try: py_check()
    ... except ValueError: assert not IS_PY3
    ... except TypeError: assert IS_PY3
    ... else: assert False
    >>> try: except_finally_reraise_new()
    ... except TypeError: pass  # currently only Py3 semantics implemented
    ... else: assert False
    """
    try:
        raise ValueError
    except ValueError:
        try:
            raise TypeError
        finally:
            raise


def finally_exception_check_return():
    """
    >>> if not IS_PY3:
    ...     sys.exc_clear()
    >>> def py_check():
    ...     try: raise ValueError()
    ...     finally:
    ...         if IS_PY3:
    ...             assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
    ...         else:
    ...             assert sys.exc_info() == (None, None, None), str(sys.exc_info())
    ...         return 1
    >>> py_check()
    1
    >>> finally_exception_check_return()
    1
    """
    try:
        raise ValueError()
    finally:
        if IS_PY3:
            assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
        else:
            assert sys.exc_info() == (None, None, None), str(sys.exc_info())
        return 1


cdef void swallow():
    try:
        raise TypeError()
    except:
        return


def finally_exception_check_swallow():
    """
    >>> if not IS_PY3:
    ...     sys.exc_clear()
    >>> def swallow():
    ...     try: raise TypeError()
    ...     except: return
    >>> def py_check():
    ...     try: raise ValueError()
    ...     finally:
    ...         if IS_PY3:
    ...             assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
    ...         else:
    ...             assert sys.exc_info() == (None, None, None), str(sys.exc_info())
    ...         swallow()
    ...         if IS_PY3:
    ...             assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
    ...         else:
    ...             assert sys.exc_info() == (None, None, None), str(sys.exc_info())
    >>> py_check()
    Traceback (most recent call last):
    ValueError
    >>> if not IS_PY3:
    ...     sys.exc_clear()
    >>> finally_exception_check_swallow()
    Traceback (most recent call last):
    ValueError
    """
    try:
        raise ValueError()
    finally:
        if IS_PY3:
            assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
        else:
            assert sys.exc_info() == (None, None, None), str(sys.exc_info())
        swallow()
        if IS_PY3:
            assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
        else:
            assert sys.exc_info() == (None, None, None), str(sys.exc_info())


def finally_exception_break_check():
    """
    >>> if not IS_PY3:
    ...     sys.exc_clear()
    >>> def py_check():
    ...     i = None
    ...     for i in range(2):
    ...         try: raise ValueError()
    ...         finally:
    ...             if IS_PY3:
    ...                 assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
    ...             else:
    ...                 assert sys.exc_info() == (None, None, None), str(sys.exc_info())
    ...             break
    ...     assert sys.exc_info() == (None, None, None), str(sys.exc_info())
    ...     return i
    >>> py_check()
    0
    >>> finally_exception_break_check()
    0
    """
    i = None
    for i in range(2):
        try:
            raise ValueError()
        finally:
            if IS_PY3:
                assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
            else:
                assert sys.exc_info() == (None, None, None), str(sys.exc_info())
            break
    assert sys.exc_info() == (None, None, None), str(sys.exc_info())
    return i


def finally_exception_break_check_with_swallowed_raise():
    """
    >>> if not IS_PY3:
    ...     sys.exc_clear()
    >>> def swallow():
    ...     try: raise TypeError()
    ...     except: return
    >>> def py_check():
    ...     i = None
    ...     for i in range(2):
    ...         try: raise ValueError()
    ...         finally:
    ...             if IS_PY3:
    ...                 assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
    ...             else:
    ...                 assert sys.exc_info() == (None, None, None), str(sys.exc_info())
    ...             swallow()
    ...             if IS_PY3:
    ...                 assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
    ...             else:
    ...                 assert sys.exc_info() == (None, None, None), str(sys.exc_info())
    ...             break
    ...     assert sys.exc_info() == (None, None, None), str(sys.exc_info())
    ...     return i
    >>> py_check()
    0
    >>> finally_exception_break_check_with_swallowed_raise()
    0
    """
    i = None
    for i in range(2):
        try:
            raise ValueError()
        finally:
            if IS_PY3:
                assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
            else:
                assert sys.exc_info() == (None, None, None), str(sys.exc_info())
            swallow()
            if IS_PY3:
                assert sys.exc_info()[0] == ValueError, str(sys.exc_info())
            else:
                assert sys.exc_info() == (None, None, None), str(sys.exc_info())
            break
    assert sys.exc_info() == (None, None, None), str(sys.exc_info())
    return i


def try_return_cy():
    """
    >>> def try_return_py():
    ...    try:
    ...        return 1
    ...    finally:
    ...        return 2
    >>> try_return_py()
    2
    >>> try_return_cy()
    2
    """
    try:
        return 1
    finally:
        return 2

cdef int try_return_c():
    try:
        return 1
    finally:
        return 2

def call_try_return_c():
    """
    >>> call_try_return_c()
    2
    """
    return try_return_c()

cdef int try_return_with_exception():
    try:
        raise TypeError
    finally:
        return 1

def call_try_return_with_exception():
    """
    >>> call_try_return_with_exception()
    1
    """
    return try_return_with_exception()

def try_return_temp(a):
    b = a+2
    try:
        c = a+b
        return c
    finally:
        print b-a

def try_continue(a):
    """
    >>> i=1
    >>> for i in range(3):
    ...     try:
    ...         continue
    ...     finally:
    ...         i+=1
    >>> i
    3
    >>> try_continue(3)
    3
    """
    i=1
    for i in range(a):
        try:
            continue
        finally:
            i+=1
    return i


def try_return_none_1():
    """
    >>> try_return_none_1()
    """
    try:
        return
    finally:
        return

cdef extern from *:
    ctypedef struct PyObject
    void Py_INCREF(object)

cdef PyObject* _none():
    ret = None
    Py_INCREF(ret)
    return  ret

def try_return_none_2():
    """
    >>> try_return_none_2()
    """
    try:
        return  _none()
    finally:
        return  _none()

def try_break():
    """
    >>> try_break()
    """
    for a in "abcd":
        try:
            if a == 'c':
                break
        except:
            break


def empty_try():
    """
    >>> empty_try()
    1
    """
    try:
        pass
    finally:
        return 1


def empty_try_in_except_raise(raise_in_finally):
    """
    >>> empty_try_in_except_raise(False)
    Traceback (most recent call last):
    ValueError: HUHU
    >>> empty_try_in_except_raise(True)
    Traceback (most recent call last):
    TypeError: OLA
    """
    try:
        raise ValueError("HUHU")
    except ValueError:
        try:
            pass
        finally:
            if raise_in_finally:
                raise TypeError('OLA')
        raise


def try_all_cases(x):
    """
    >>> try_all_cases(None)
    2
    >>> try_all_cases('break')
    4
    >>> try_all_cases('raise')
    Traceback (most recent call last):
    ValueError
    >>> try_all_cases('return')
    3
    >>> try_all_cases('tryraise')
    Traceback (most recent call last):
    TypeError
    >>> try_all_cases('trybreak')
    4
    """
    for i in range(3):
        try:
            if i == 0:
                pass
            elif i == 1:
                continue
            elif x == 'trybreak':
                break
            elif x == 'tryraise':
                raise TypeError()
            else:
                return 2
        finally:
            if x == 'raise':
                raise ValueError()
            elif x == 'break':
                break
            elif x == 'return':
                return 3
    return 4


def finally_yield(x):
    """
    >>> g = finally_yield(None)
    >>> next(g)  # 1
    1
    >>> next(g)  # 2
    1
    >>> next(g)  # 3
    Traceback (most recent call last):
    StopIteration

    >>> g = finally_yield('raise')
    >>> next(g)  # raise 1
    1
    >>> next(g)  # raise 2
    1
    >>> next(g)  # raise 3
    Traceback (most recent call last):
    TypeError

    >>> g = finally_yield('break')
    >>> next(g)   # break 1
    1
    >>> next(g)   # break 2
    1
    >>> next(g)   # break 3
    Traceback (most recent call last):
    StopIteration
    """
    for i in range(3):
        try:
            if i == 0:
                continue
            elif x == 'raise':
                raise TypeError()
            elif x == 'break':
                break
            else:
                return
        finally:
            yield 1


def complex_finally_clause(x, obj):
    """
    >>> class T(object):
    ...     def method(self, value):
    ...         print(value)

    >>> complex_finally_clause('finish', T())
    module.py
    module.py
    module.py
    99
    >>> complex_finally_clause('tryreturn', T())
    module.py
    module.py
    module.py
    2
    >>> complex_finally_clause('trybreak', T())
    module.py
    module.py
    module.py
    99
    >>> complex_finally_clause('tryraise', T())
    Traceback (most recent call last):
    TypeError
    """
    name = 'module'
    l = []
    cdef object lobj = l

    for i in range(3):
        l[:] = [1, 2, 3]
        try:
            if i == 0:
                pass
            elif i == 1:
                continue
            elif x == 'trybreak':
                break
            elif x == 'tryraise':
                raise TypeError()
            elif x == 'tryreturn':
                return 2
            else:
                pass
        finally:
            obj.method(name + '.py')
            from contextlib import contextmanager
            with contextmanager(lambda: (yield 1))() as y:
                assert y == 1
                a = 1
            with nogil:
                if i > 0:
                    with gil:
                        assert obj.method
                        a = 2
            # FIXME: prevent deep-copying inner functions
            #def closure(l):
            #    assert l == lobj
            #closure()
            assert name[0] in string.ascii_letters
            string.Template("-- huhu $name --").substitute(**{'name': '(%s)' % name})
            if a:
                a = 3
            del l[0], lobj[0]
            assert all(i == 3 for i in l), l
    return 99

def function_in_finally():
    """
    https://github.com/cython/cython/issues/4651 - function definitions in the
    except copy of the finally clause weren't generated

    >>> function_in_finally()
    in try
    in func()
    finished
    """
    try:
        print('in try')
    finally:
        def func():
            print('in func()')
        func()
    print('finished')
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/tryfinallychaining.pyx0000644000175100001770000000205600000000000022205 0ustar00runnerdocker00000000000000# mode: run
# tag: exceptions, tryfinally

import sys
IS_PY3 = sys.version_info[0] >= 3


def test_finally_c():
    """
    >>> def test_finally_py():
    ...     try:
    ...         raise AttributeError()
    ...     finally:
    ...         raise KeyError()

    >>> try:
    ...     test_finally_py()
    ... except KeyError:
    ...     print(sys.exc_info()[0] is KeyError or sys.exc_info()[0])
    ...     if IS_PY3:
    ...         print(isinstance(sys.exc_info()[1].__context__, AttributeError)
    ...               or sys.exc_info()[1].__context__)
    ...     else:
    ...         print(True)
    True
    True

    >>> try:
    ...     test_finally_c()
    ... except KeyError:
    ...     print(sys.exc_info()[0] is KeyError or sys.exc_info()[0])
    ...     if IS_PY3:
    ...         print(isinstance(sys.exc_info()[1].__context__, AttributeError)
    ...               or sys.exc_info()[1].__context__)
    ...     else:
    ...         print(True)
    True
    True
    """
    try:
        raise AttributeError()
    finally:
        raise KeyError()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/tss.pyx0000644000175100001770000000371400000000000017122 0ustar00runnerdocker00000000000000# mode: run

from cpython.pythread cimport *


cdef Py_tss_t *pass_py_tss_t_ptr(Py_tss_t *value):
    return value


def tss_create_delete():
    """
    >>> tss_create_delete()
    (True, False)
    """
    cdef Py_tss_t tss_key
    cdef bint after_create, after_delete
    if PyThread_tss_create(&tss_key) != 0:
        raise MemoryError()
    after_create = PyThread_tss_is_created(&tss_key) != 0
    assert after_create == PyThread_tss_is_created(pass_py_tss_t_ptr(&tss_key))
    PyThread_tss_delete(&tss_key)
    after_delete = PyThread_tss_is_created(&tss_key) != 0
    return (after_create, after_delete)


def tss_alloc_free():
    """
    >>> tss_alloc_free()
    False
    """
    cdef Py_tss_t *ptr_key
    cdef bint after_alloc, after_free
    ptr_key = PyThread_tss_alloc()
    if ptr_key == NULL:
        raise MemoryError()
    after_alloc = PyThread_tss_is_created(ptr_key) != 0
    PyThread_tss_free(ptr_key)
    return after_alloc


def tss_alloc_create_delete_free():
    """
    >>> tss_alloc_create_delete_free()
    (False, True, False)
    """
    cdef Py_tss_t *ptr_key
    cdef bint after_alloc, after_free
    ptr_key = PyThread_tss_alloc()
    if ptr_key == NULL:
        raise MemoryError()
    after_alloc = PyThread_tss_is_created(ptr_key) != 0
    if PyThread_tss_create(ptr_key) != 0:
        raise MemoryError()
    after_create = PyThread_tss_is_created(ptr_key) != 0
    PyThread_tss_delete(ptr_key)
    after_delete = PyThread_tss_is_created(ptr_key) != 0
    PyThread_tss_free(ptr_key)
    return (after_alloc, after_create, after_delete)


def tss_set_get():
    """
    >>> tss_set_get()
    1
    """
    cdef Py_tss_t tss_key
    cdef int the_value = 1
    cdef int ret_value
    if PyThread_tss_create(&tss_key) != 0:
        raise MemoryError()
    if PyThread_tss_get(&tss_key) == NULL:
        PyThread_tss_set(&tss_key, &the_value)
    ret_value = (PyThread_tss_get(&tss_key))[0]
    PyThread_tss_delete(&tss_key)
    return ret_value
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/tuple.pyx0000644000175100001770000000567500000000000017452 0ustar00runnerdocker00000000000000
cimport cython


def f(obj1, obj2, obj3, obj4, obj5):
    """
    >>> f(1,2,3,4,5)
    ()
    """
    obj1 = ()
    return obj1


def g(obj1, obj2, obj3, obj4, obj5):
    """
    >>> g(1,2,3,4,5)
    (2,)
    """
    obj1 = ()
    obj1 = (obj2,)
    return obj1


def h(obj1, obj2, obj3, obj4, obj5):
    """
    >>> h(1,2,3,4,5)
    (2, 3)
    """
    obj1 = ()
    obj1 = (obj2,)
    obj1 = obj2, obj3
    return obj1


def j(obj1, obj2, obj3, obj4, obj5):
    """
    >>> j(1,2,3,4,5)
    (2, 3, 4)
    """
    obj1 = ()
    obj1 = (obj2,)
    obj1 = obj2, obj3
    obj1 = (obj2, obj3, obj4)
    return obj1


def k(obj1, obj2, obj3, obj4, obj5):
    """
    >>> k(1,2,3,4,5)
    (2, 3, 4)
    """
    obj1 = ()
    obj1 = (obj2,)
    obj1 = obj2, obj3
    obj1 = (obj2, obj3, obj4)
    obj1 = (obj2, obj3, obj4,)
    return obj1


def l(obj1, obj2, obj3, obj4, obj5):
    """
    >>> l(1,2,3,4,5)
    (17, 42, 88)
    """
    obj1 = ()
    obj1 = (obj2,)
    obj1 = obj2, obj3
    obj1 = (obj2, obj3, obj4)
    obj1 = (obj2, obj3, obj4,)
    obj1 = 17, 42, 88
    return obj1


def tuple_none():
    """
    >>> tuple_none()   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...itera...
    """
    return tuple(None)


def tuple_none_list():
    """
    >>> tuple_none_list()   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...iterable...
    """
    cdef list none = None
    return tuple(none)


@cython.test_fail_if_path_exists(
    '//SimpleCallNode',
    '//PythonCapiCallNode'
)
def tuple_of_tuple_literal():
    """
    >>> tuple_of_tuple_literal()
    (1, 2, 3)
    """
    return tuple(tuple(tuple((1,2,3))))


@cython.test_fail_if_path_exists(
    '//SimpleCallNode',
    '//PythonCapiCallNode'
)
def tuple_of_args_tuple(*args):
    """
    >>> tuple_of_args_tuple(1,2,3)
    (1, 2, 3)
    """
    return tuple(tuple(tuple(args)))


@cython.test_fail_if_path_exists('//SimpleCallNode//SimpleCallNode')
def tuple_of_object(ob):
    """
    >>> tuple(type(1))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...type...
    >>> sorted(tuple(set([1, 2, 3])))
    [1, 2, 3]
    """
    return tuple(ob)


@cython.test_fail_if_path_exists(
    '//SimpleCallNode',
    '//PythonCapiCallNode//PythonCapiCallNode'
)
def tuple_of_tuple_or_none(tuple x):
    """
    >>> tuple_of_tuple_or_none((1,2,3))
    (1, 2, 3)
    >>> tuple_of_tuple_or_none(None)   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...itera...
    """
    return tuple(tuple(tuple(x)))


@cython.test_fail_if_path_exists(
    "//ExprStatNode//TupleNode",
    "//ExprStatNode",
)
def unused_literals():
    """
    >>> unused_literals()
    """
    (1, 2, 3)
    (1, 2, 3 + 4)
    ("abc", 'def')
    #(int(), 2, 3)


@cython.test_assert_path_exists(
    "//ExprStatNode",
    "//ExprStatNode//TupleNode",
)
def unused_non_literal():
    """
    >>> unused_non_literal()
    """
    (set(), None)
    (range(10), None)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/tuple_constants.pyx0000644000175100001770000001376700000000000021547 0ustar00runnerdocker00000000000000
cimport cython

module_level_tuple = (1,2,3)
second_module_level_tuple = (1,2,3)  # should be deduplicated to be the same as the first
string_module_level_tuple = ("1", "2")
string_module_level_tuple2 = ("1", "2")

def return_module_level_tuple():
    """
    >>> return_module_level_tuple()
    (1, 2, 3)
    """
    return module_level_tuple

def test_deduplicated_tuples():
    """
    >>> test_deduplicated_tuples()
    """
    assert (module_level_tuple is second_module_level_tuple)
    assert (module_level_tuple is (1,2,3))  # also deduplicated with a function tuple
    assert (string_module_level_tuple is string_module_level_tuple2)
    assert (string_module_level_tuple is ("1", "2"))

def func1(arg1, arg2):
    pass

def func2(arg1, arg2):
    pass

def test_deduplicated_args():
    """
    >>> test_deduplicated_args()
    """
    # This is a concern because in large modules *a lot* of similar code objects
    # are generated often with the same argument names. Therefore it's worth ensuring that
    # they are correctly deduplicated
    import sys
    check_identity_of_co_varnames = (
        not hasattr(sys, "pypy_version_info") and  # test doesn't work on PyPy (which is probably fair enough)
        sys.version_info < (3, 11)  # on Python 3.11 co_varnames returns a new, dynamically-calculated tuple
                                    # each time it is run
    )
    if check_identity_of_co_varnames:
        assert func1.__code__.co_varnames is func2.__code__.co_varnames

@cython.test_assert_path_exists("//TupleNode",
                                "//TupleNode[@is_literal = true]")
@cython.test_fail_if_path_exists("//TupleNode[@is_literal = false]")
def return_empty_tuple():
    """
    >>> return_empty_tuple()
    ()
    """
    return ()

@cython.test_assert_path_exists("//TupleNode",
                                "//TupleNode[@is_literal = true]")
@cython.test_fail_if_path_exists("//TupleNode[@is_literal = false]")
def return_constant_tuple1():
    """
    >>> return_constant_tuple1()
    (1,)
    """
    return (1,)

@cython.test_assert_path_exists("//TupleNode",
                                "//TupleNode[@is_literal = true]")
@cython.test_fail_if_path_exists("//TupleNode[@is_literal = false]")
def return_folded_tuple():
    """
    >>> return_folded_tuple()
    (1, 2, 3)
    """
    return (1, 1+1, 1+1+1)

@cython.test_assert_path_exists("//TupleNode",
                                "//TupleNode[@is_literal = true]")
@cython.test_fail_if_path_exists("//TupleNode[@is_literal = false]")
def return_nested_tuple():
    """
    >>> return_nested_tuple()
    (1, (2, 3), (3, (4, 5), (2, 3, 2, 3)))
    """
    return (1, (2, 3), (3, (4, 5), (2, 3) * 2))

@cython.test_assert_path_exists("//TupleNode",
                                "//TupleNode[@is_literal = true]")
@cython.test_fail_if_path_exists("//TupleNode[@is_literal = false]")
def constant_tuple1():
    """
    >>> constant_tuple1()
    (1,)
    """
    tuple1 = (1,)
    return tuple1

@cython.test_assert_path_exists("//TupleNode",
                                "//TupleNode[@is_literal = true]")
@cython.test_fail_if_path_exists("//TupleNode[@is_literal = false]")
def return_constant_tuple2():
    """
    >>> return_constant_tuple2()
    (1, 2)
    """
    return (1,2)


def return_multiplied_constant_tuple(n):
    """
    >>> tuples = return_multiplied_constant_tuple(2)
    >>> type(tuples) is tuple
    True
    >>> for t in tuples: print(t)
    ()
    (1, 2, 3)
    (1, 2, 3, 1, 2, 3)
    (1, 2, 3, 1, 2, 3, 1, 2, 3)
    (1, 2, 3, 1, 2, 3)
    (1, 2, 3, 1, 2, 3)
    ((1, 2, 3, 1, 2, 3), (1, 2, 3), (1, 2, 3, 1, 2, 3))
    """
    return (
        (1, 2, 3) * 0,
        (1, 2, 3) * 1,
        (1, 2, 3) * 2,
        (1, 2, 3) * 3,
        (1, 2, 3) * 2,
        (1, 2, 3) * n,
        ((1, 2, 3) * n, (1, 2, 3), (1, 2, 3) * n),
    )


@cython.test_assert_path_exists("//TupleNode",
                                "//TupleNode[@is_literal = true]")
@cython.test_fail_if_path_exists("//TupleNode[@is_literal = false]")
def return_constant_tuple_strings():
    """
    >>> return_constant_tuple_strings()
    ('tuple_1', 'bc', 'tuple_2')
    """
    return ('tuple_1', 'bc', 'tuple_2')

@cython.test_assert_path_exists("//TupleNode",
                                "//TupleNode[@is_literal = true]")
@cython.test_fail_if_path_exists("//TupleNode[@is_literal = false]")
def return_constant_tuples_string_types():
    """
    >>> a,b,c = return_constant_tuples_string_types()
    >>> a is b
    False
    >>> a is c
    False
    >>> b is c
    False
    """
    return ('a', 'bc'), (u'a', u'bc'), (b'a', b'bc')

@cython.test_assert_path_exists("//ReturnStatNode//TupleNode",
                                "//ReturnStatNode//TupleNode[@is_literal = false]")
@cython.test_fail_if_path_exists("//ReturnStatNode//TupleNode[@is_literal = true]")
def return_nonconstant_tuple():
    """
    >>> return_nonconstant_tuple()
    ('a', 1, 'd')
    """
    a = eval("1")
    return ('a', a, 'd')


def constant_types_comparing_equal():
    """
    >>> constant_types_comparing_equal()
    ((False, False), (0, 0), (0.0, 0.0), (0, False), (False, 0.0), (0, 0.0))
    """
    bool_tuple= (False, False)
    int_tuple = (0, 0)
    float_tuple = (0.0, 0.0)
    int_bool = (0, False)
    bool_float = (False, 0.0)
    int_float = (0, 0.0)

    assert bool_tuple is (False, False)
    assert int_tuple is (0, 0)
    assert bool_tuple == int_tuple
    assert bool_tuple is not int_tuple
    assert float_tuple is (0., 0.)
    assert float_tuple == int_tuple
    assert float_tuple is not int_tuple
    assert int_bool is (0, False)
    assert int_bool == bool_tuple
    assert int_bool is not bool_tuple
    assert int_bool is not int_tuple
    assert bool_float is (False, 0.)
    assert bool_float == bool_tuple
    assert bool_float is not bool_tuple
    assert bool_float is not float_tuple
    assert int_float is (0, 0.)
    assert int_float == int_tuple
    assert int_float is not int_tuple
    assert int_float is not float_tuple

    return bool_tuple, int_tuple, float_tuple, int_bool, bool_float, int_float
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/tuple_unpack_string.pyx0000644000175100001770000000340200000000000022363 0ustar00runnerdocker00000000000000# mode: run
# tag: string, unicode, sequence unpacking, starexpr

def unpack_single_str():
    """
    >>> print(unpack_single_str())
    a
    """
    a, = 'a'
    return a

def unpack_str():
    """
    >>> a,b = unpack_str()
    >>> print(a)
    a
    >>> print(b)
    b
    """
    a,b = 'ab'
    return a,b

def star_unpack_str():
    """
    >>> a,b,c = star_unpack_str()
    >>> print(a)
    a
    >>> type(b) is list
    True
    >>> print(''.join(b))
    bbb
    >>> print(c)
    c
    """
    a,*b,c = 'abbbc'
    return a,b,c

def unpack_single_unicode():
    """
    >>> print(unpack_single_unicode())
    a
    """
    a, = u'a'
    return a

def unpack_unicode():
    """
    >>> a,b = unpack_unicode()
    >>> print(a)
    a
    >>> print(b)
    b
    """
    a,b = u'ab'
    return a,b

def star_unpack_unicode():
    """
    >>> a,b,c = star_unpack_unicode()
    >>> print(a)
    a
    >>> type(b) is list
    True
    >>> print(''.join(b))
    bbb
    >>> print(c)
    c
    """
    a,*b,c = u'abbbc'
    return a,b,c

# the following is not supported due to Py2/Py3 bytes differences

## def unpack_single_bytes():
##     """
##     >>> print(unpack_single_bytes().decode('ASCII'))
##     a
##     """
##     a, = b'a'
##     return a

## def unpack_bytes():
##     """
##     >>> a,b = unpack_bytes()
##     >>> print(a.decode('ASCII'))
##     a
##     >>> print(b.decode('ASCII'))
##     b
##     """
##     a,b = b'ab'
##     return a,b

## def star_unpack_bytes():
##     """
##     >>> a,b,c = star_unpack_bytes()
##     >>> print(a.decode('ASCII'))
##     a
##     >>> type(b) is list
##     True
##     >>> print(''.join([ch.decode('ASCII') for ch in b]))
##     bbb
##     >>> print(c.decode('ASCII'))
##     c
##     """
##     a,*b,c = b'abbbc'
##     return a,b,c
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/tupleassign.pyx0000644000175100001770000000603600000000000020647 0ustar00runnerdocker00000000000000t = (1,2,3)
l = [1,2,3]

def assign3(t):
    """
    >>> assign3(l)
    (1, 2, 3)
    >>> assign3(t)
    (1, 2, 3)
    >>> assign3((1,))
    Traceback (most recent call last):
    ValueError: need more than 1 value to unpack
    >>> assign3((1,2))
    Traceback (most recent call last):
    ValueError: need more than 2 values to unpack
    >>> assign3((1,2,3,4))
    Traceback (most recent call last):
    ValueError: too many values to unpack (expected 3)
    """
    a,b,c = t
    return (a,b,c)

def assign3_typed(tuple t):
    """
    >>> assign3_typed(t)
    (1, 2, 3)
    >>> assign3_typed(l)
    Traceback (most recent call last):
    TypeError: Argument 't' has incorrect type (expected tuple, got list)
    >>> a,b,c = (1,) # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...
    >>> assign3_typed((1,))
    Traceback (most recent call last):
    ValueError: need more than 1 value to unpack
    >>> a,b,c = (1,2) # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...
    >>> assign3_typed((1,2))
    Traceback (most recent call last):
    ValueError: need more than 2 values to unpack
    >>> a,b,c = (1,2,3,4)    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...
    >>> assign3_typed((1,2,3,4))
    Traceback (most recent call last):
    ValueError: too many values to unpack (expected 3)
    >>> a,b = 99,98
    >>> a,b = t     # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...
    >>> a,b
    (99, 98)
    """
    a,b,c = t
    return (a,b,c)

def assign3_int(t):
    """
    >>> assign3_int(l)
    (1, 2, 3)
    """
    cdef int a,b,c
    a,b,c = t
    return (a,b,c)

def assign3_mixed1(t):
    """
    >>> assign3_mixed1(l)
    (1, 2, 3)
    """
    cdef int a
    a,b,c = t
    return (a,b,c)

def assign3_mixed2(t):
    """
    >>> assign3_mixed2(l)
    (1, 2, 3)
    """
    cdef int b
    a,b,c = t
    return (a,b,c)

def assign3_mixed3(t):
    """
    >>> assign3_mixed3(l)
    (1, 2, 3)
    """
    cdef int c
    a,b,c = t
    return (a,b,c)

def assign3_mixed4(t):
    cdef int b,c
    a,b,c = t
    return (a,b,c)

def test_overwrite(t):
    """
    >>> test_overwrite(l)
    (99, 98)
    >>> test_overwrite(t)
    (99, 98)
    """
    a,b = 99,98
    try:
        a,b = t
    except ValueError:
        pass
    return (a,b)

def test_overwrite_int(t):
    """
    >>> test_overwrite_int(l)
    (99, 98)
    >>> test_overwrite_int(t)
    (99, 98)
    """
    cdef int a,b
    a,b = 99,98
    try:
        a,b = t
    except ValueError:
        pass
    return (a,b)

def test_overwrite_mixed(t):
    """
    >>> test_overwrite_mixed(l)
    (99, 98)
    >>> test_overwrite_mixed(t)
    (99, 98)
    """
    cdef int b
    a,b = 99,98
    try:
        a,b = t
    except ValueError:
        pass
    return (a,b)

def test_overwrite_mixed2(t):
    """
    >>> test_overwrite_mixed2(l)
    (99, 98)
    >>> test_overwrite_mixed2(t)
    (99, 98)
    """
    cdef int a
    a,b = 99,98
    try:
        a,b = t
    except ValueError:
        pass
    return (a,b)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/tuplereassign.pyx0000644000175100001770000000066400000000000021177 0ustar00runnerdocker00000000000000def test1(t):
    """
    >>> test1( (1,2,3) )
    1
    """
    t,a,b = t
    return t

def test3(t):
    """
    >>> test3( (1,2,3) )
    3
    """
    a,b,t = t
    return t

def test(t):
    """
    >>> test( (1,2,3) )
    3
    """
    t,t,t = t
    return t

def testnonsense():
    """
    >>> testnonsense()     # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    t,t,t = 1*2
    return t
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/tupleunpack_T298.pyx0000644000175100001770000000043100000000000021363 0ustar00runnerdocker00000000000000# ticket: t298

"""
>>> func()
0 0
0
0
1 1
1
1
2 2
2
2
>>> func2()
"""

def g():
    return ((3, 2), 1, 0)

def func2():
    (a, b), c, d = g()

def func():
    for (a, b),c ,d in zip(zip(range(3), range(3)), range(3), range(3)):
        print a, b
        print c
        print d
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/tupleunpack_T712.pyx0000644000175100001770000000037600000000000021362 0ustar00runnerdocker00000000000000# mode: run
# ticket: t712

def single_from_string():
    """
    >>> print(single_from_string())
    a
    """
    (a,) = 'a'
    return a

def single_from_set():
    """
    >>> print(single_from_set())
    a
    """
    (a,) = set(["a"])
    return a
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/type_inference.pyx0000644000175100001770000004566200000000000021320 0ustar00runnerdocker00000000000000# cython: infer_types = True


cimport cython
from cython cimport typeof, infer_types

from cpython cimport bool

##################################################
# type inference tests in 'full' mode

cdef class MyType:
    pass

def simple():
    """
    >>> simple()
    """
    i = 3
    assert typeof(i) == "long", typeof(i)
    x = 1.41
    assert typeof(x) == "double", typeof(x)
    xptr = &x
    assert typeof(xptr) == "double *", typeof(xptr)
    xptrptr = &xptr
    assert typeof(xptrptr) == "double **", typeof(xptrptr)
    b = b"abc"
    assert typeof(b) == "bytes object", typeof(b)
    s = "abc"
    assert typeof(s) == "str object", typeof(s)
    u = u"xyz"
    assert typeof(u) == "unicode object", typeof(u)
    L = [1,2,3]
    assert typeof(L) == "list object", typeof(L)
    t = (4,5,6,())
    assert typeof(t) == "tuple object", typeof(t)
    t2 = (4, 5.0, 6)
    assert typeof(t2) == "(long, double, long)", typeof(t)

def builtin_types():
    """
    >>> builtin_types()
    """
    b = bytes()
    assert typeof(b) == "bytes object", typeof(b)
    u = unicode()
    assert typeof(u) == "unicode object", typeof(u)
    L = list()
    assert typeof(L) == "list object", typeof(L)
    t = tuple()
    assert typeof(t) == "tuple object", typeof(t)
    d = dict()
    assert typeof(d) == "dict object", typeof(d)
    B = bool()
    assert typeof(B) == "bool", typeof(B)

def slicing():
    """
    >>> slicing()
    """
    b = b"abc"
    assert typeof(b) == "bytes object", typeof(b)
    b1 = b[1:2]
    assert typeof(b1) == "bytes object", typeof(b1)
    b2 = b[1:2:2]
    assert typeof(b2) == "bytes object", typeof(b2)
    u = u"xyz"
    assert typeof(u) == "unicode object", typeof(u)
    u1 = u[1:2]
    assert typeof(u1) == "unicode object", typeof(u1)
    u2 = u[1:2:2]
    assert typeof(u2) == "unicode object", typeof(u2)
    s = "xyz"
    assert typeof(s) == "str object", typeof(s)
    s1 = s[1:2]
    assert typeof(s1) == "str object", typeof(s1)
    s2 = s[1:2:2]
    assert typeof(s2) == "str object", typeof(s2)
    L = [1,2,3]
    assert typeof(L) == "list object", typeof(L)
    L1 = L[1:2]
    assert typeof(L1) == "list object", typeof(L1)
    L2 = L[1:2:2]
    assert typeof(L2) == "list object", typeof(L2)
    t = (4,5,6,())
    assert typeof(t) == "tuple object", typeof(t)
    t1 = t[1:2]
    assert typeof(t1) == "tuple object", typeof(t1)
    t2 = t[1:2:2]
    assert typeof(t2) == "tuple object", typeof(t2)

def indexing():
    """
    >>> indexing()
    """
    b = b"abc"
    assert typeof(b) == "bytes object", typeof(b)
    b1 = b[1]
    assert typeof(b1) == "Python object", typeof(b1) # Py2: bytes, Py3: int
    u = u"xyz"
    assert typeof(u) == "unicode object", typeof(u)
    u1 = u[1]
    assert typeof(u1) == "Py_UCS4", typeof(u1)
    s = "xyz"
    assert typeof(s) == "str object", typeof(s)
    s1 = s[1]
    assert typeof(s1) == "str object", typeof(s1)
    L = [1,2,3]
    assert typeof(L) == "list object", typeof(L)
    L1 = L[1]
    assert typeof(L1) == "Python object", typeof(L1)
    t = (4,5,())
    assert typeof(t) == "tuple object", typeof(t)
    t1 = t[1]
    assert typeof(t1) == "long", typeof(t1)
    t2 = ('abc', 'def', 'ghi')
    assert typeof(t2) == "tuple object", typeof(t2)
    t2_1 = t2[1]
    assert typeof(t2_1) == "str object", typeof(t2_1)
    t2_2 = t2[t[0]-3]
    assert typeof(t2_2) == "str object", typeof(t2_2)
    t5 = (b'abc', 'def', u'ghi')
    t5_0 = t5[0]
    assert typeof(t5_0) == "bytes object", typeof(t5_0)
    t5_1 = t5[1]
    assert typeof(t5_1) == "str object", typeof(t5_1)
    t5_2 = t5[2]
    assert typeof(t5_2) == "unicode object", typeof(t5_2)
    t5_3 = t5[t[0]-3]
    assert typeof(t5_3) == "Python object", typeof(t5_3)


def multiple_assignments():
    """
    >>> multiple_assignments()
    """
    a = 3
    a = 4
    a = 5
    assert typeof(a) == "long", typeof(a)
    b = a
    b = 3.1
    b = 3.14159
    assert typeof(b) == "double", typeof(b)
    c = a
    c = b
    c = [1,2,3]
    assert typeof(c) == "Python object", typeof(c)
    d = b'abc'
    d = bytes()
    d = bytes(b'xyz')
    d = None
    assert typeof(d) == "bytes object", typeof(d)


def arithmetic():
    """
    >>> arithmetic()
    """
    a = 1 + 2
    assert typeof(a) == "long", typeof(a)
    b = 1 + 1.5
    assert typeof(b) == "double", typeof(b)
    c = 1 + 2
    assert typeof(c) == "Python object", typeof(c)
    d = 1 * 1.5 ** 2
    assert typeof(d) == "double", typeof(d)

cdef class some_class:
    pass

def unary_operators():
    """
    >>> unary_operators()
    """
    cdef int x = 1
    assert typeof(~x) == "int", typeof(~x)
    cdef some_class obj
    assert typeof(~obj) == "Python object", typeof(~obj)
    a = int(1)
    assert typeof(a) == "Python object", typeof(a)
    b = not int(3)
    assert typeof(b) == "bint", typeof(b)
    c = +int(3)
    assert typeof(c) == "Python object", typeof(c)
    d = -int(5)
    assert typeof(d) == "Python object", typeof(d)


def builtin_type_operations():
    """
    >>> builtin_type_operations()
    """
    b1 = b'a' * 10
    b1 = 10 * b'a'
    b1 = 10 * b'a' * 10
    assert typeof(b1) == "bytes object", typeof(b1)
    b2 = b'a' + b'b'
    assert typeof(b2) == "bytes object", typeof(b2)
    u1 = u'a' * 10
    u1 = 10 * u'a'
    assert typeof(u1) == "unicode object", typeof(u1)
    u2 = u'a' + u'b'
    assert typeof(u2) == "unicode object", typeof(u2)
    u3 = u'a%s' % u'b'
    u3 = u'a%s' % 10
    assert typeof(u3) == "unicode object", typeof(u3)
    s1 = "abc %s" % "x"
    s1 = "abc %s" % 10
    assert typeof(s1) == "str object", typeof(s1)
    s2 = "abc %s" + "x"
    assert typeof(s2) == "str object", typeof(s2)
    s3 = "abc %s" * 10
    s3 = "abc %s" * 10 * 10
    s3 = 10 * "abc %s" * 10
    assert typeof(s3) == "str object", typeof(s3)
    L1 = [] + []
    assert typeof(L1) == "list object", typeof(L1)
    L2 = [] * 2
    assert typeof(L2) == "list object", typeof(L2)
    T1 = () + ()
    assert typeof(T1) == "tuple object", typeof(T1)
    T2 = () * 2
    assert typeof(T2) == "tuple object", typeof(T2)

def builtin_type_methods():
    """
    >>> builtin_type_methods()
    """
    l = []
    assert typeof(l) == 'list object', typeof(l)
    append = l.append
    assert typeof(append) == 'Python object', typeof(append)
    append(1)
    assert l == [1], str(l)

cdef int cfunc(int x):
    return x+1

def c_functions():
    """
    >>> c_functions()
    """
    f = cfunc
    assert typeof(f) == 'int (*)(int) except? -1', typeof(f)
    assert 2 == f(1)

def builtin_functions():
    """
    >>> _abs, _getattr = builtin_functions()
    Python object
    Python object
    >>> _abs(-1)
    1
    >>> class o(object): pass
    >>> o.x = 1
    >>> _getattr(o, 'x')
    1
    """
    _abs = abs
    print(typeof(_abs))
    _getattr = getattr
    print(typeof(_getattr))
    return _abs, _getattr

def cascade():
    """
    >>> cascade()
    """
    a = 1.0
    b = a + 2
    c = b + 3
    d = c + 4
    assert typeof(d) == "double"
    e = a + b + c + d
    assert typeof(e) == "double"

def cascaded_assignment():
    """
    >>> cascaded_assignment()
    """
    a = b = c = d = 1.0
    assert typeof(a) == "double"
    assert typeof(b) == "double"
    assert typeof(c) == "double"
    assert typeof(d) == "double"
    e = a + b + c + d
    assert typeof(e) == "double"


def unpacking(x):
    """
    >>> unpacking(0)
    """
    a, b, c, (d, e) = x, 1, 2.0, [3, [5, 6]]
    assert typeof(a) == "Python object", typeof(a)
    assert typeof(b) == "long", typeof(b)
    assert typeof(c) == "double", typeof(c)
    assert typeof(d) == "long", typeof(d)
    assert typeof(e) == "list object", typeof(e)


def star_unpacking(*x):
    """
    >>> star_unpacking(1, 2)
    """
    a, b = x
    c, *d = x
    *e, f = x
    *g, g = x  # re-assignment
    assert typeof(a) == "Python object", typeof(a)
    assert typeof(b) == "Python object", typeof(b)
    assert typeof(c) == "Python object", typeof(c)
    assert typeof(d) == "list object", typeof(d)
    assert typeof(e) == "list object", typeof(e)
    assert typeof(f) == "Python object", typeof(f)
    assert typeof(g) == "Python object", typeof(f)


def increment():
    """
    >>> increment()
    """
    a = 5
    a += 1
    assert typeof(a) == "long"

def loop():
    """
    >>> loop()
    """
    for a in range(10):
        pass
    assert typeof(a) == "long"

    b = 1.0
    for b in range(5):
        pass
    assert typeof(b) == "double"

    for c from 0 <= c < 10 by .5:
        pass
    assert typeof(c) == "double"

    for d in range(0, 10L, 2):
        pass
    assert typeof(a) == "long"

def loop_over_charptr():
    """
    >>> print( loop_over_charptr() )
    char
    """
    cdef char* char_ptr_string = 'abcdefg'
    for c in char_ptr_string:
        pass
    return typeof(c)

def loop_over_bytes_literal():
    """
    >>> print( loop_over_bytes_literal() )
    Python object
    """
    for c in b'abcdefg':
        pass
    return typeof(c)

def loop_over_bytes():
    """
    >>> print( loop_over_bytes() )
    Python object
    """
    cdef bytes bytes_string = b'abcdefg'
    # bytes in Py2, int in Py3
    for c in bytes_string:
        pass
    return typeof(c)

def loop_over_str():
    """
    >>> print( loop_over_str() )
    str object
    """
    cdef str string = 'abcdefg'
    # str (bytes) in Py2, str (unicode) in Py3
    for c in string:
        pass
    return typeof(c)

def loop_over_unicode():
    """
    >>> print( loop_over_unicode() )
    Py_UCS4
    """
    cdef unicode ustring = u'abcdefg'
    # Py_UCS4 can represent any Unicode character
    for uchar in ustring:
        pass
    return typeof(uchar)

def loop_over_unicode_literal():
    """
    >>> print( loop_over_unicode_literal() )
    Py_UCS4
    """
    # Py_UCS4 can represent any Unicode character
    for uchar in u'abcdefg':
        pass
    return typeof(uchar)

def loop_over_int_array():
    """
    >>> print( loop_over_int_array() )
    int
    """
    cdef int[10] int_array
    for i in int_array:
        pass
    return typeof(i)

cdef struct MyStruct:
    int a

def loop_over_struct_ptr():
    """
    >>> print( loop_over_struct_ptr() )
    MyStruct
    """
    cdef MyStruct[10] a_list
    cdef MyStruct *a_ptr = a_list
    for i in a_list[:10]:
        pass
    return typeof(i)

cdef unicode retu():
    return u"12345"

cdef bytes retb():
    return b"12345"

def conditional(x):
    """
    >>> conditional(True)
    (True, 'Python object')
    >>> conditional(False)
    (False, 'Python object')
    """
    if x:
        a = retu()
    else:
        a = retb()
    return type(a) is unicode, typeof(a)

##################################################
# type inference tests that work in 'safe' mode

@infer_types(None)
def double_inference():
    """
    >>> values, types = double_inference()
    >>> values == (1.0, 1.0*2, 1.0*2.0+2.0*2.0, 1.0*2.0)
    True
    >>> types
    ('double', 'double', 'double', 'Python object')
    """
    d_a = 1.0
    d_b = d_a * float(2)
    d_c = d_a * float(some_float_value()) + d_b * float(some_float_value())
    o_d = d_a * some_float_value()
    return (d_a,d_b,d_c,o_d), (typeof(d_a), typeof(d_b), typeof(d_c), typeof(o_d))

cdef object some_float_value():
    return 2.0


@infer_types(None)
@cython.test_fail_if_path_exists('//DefNode//NameNode[@type.is_pyobject = True]')
@cython.test_assert_path_exists('//DefNode//NameNode[@type.is_pyobject]',
                                '//DefNode//NameNode[@type.is_pyobject = False]')
def double_loop():
    """
    >>> double_loop() == 1.0 * 10
    True
    """
    cdef int i
    d = 1.0
    for i in range(9):
        d += 1.0
    return d

@infer_types(None)
def safe_only():
    """
    >>> safe_only()
    """
    a = 1.0
    assert typeof(a) == "double", typeof(c)
    b = 1;
    assert typeof(b) == "long", typeof(b)
    c = MyType()
    assert typeof(c) == "MyType", typeof(c)
    for i in range(10): pass
    assert typeof(i) == "long", typeof(i)
    d = 1
    res = ~d
    assert typeof(d) == "long", typeof(d)

    # we special-case inference to type str, see
    # trac #553
    s = "abc"
    assert typeof(s) == "Python object", typeof(s)
    cdef str t = "def"
    assert typeof(t) == "str object", typeof(t)

    # potentially overflowing arithmetic
    e = 1
    e += 1
    assert typeof(e) == "Python object", typeof(e)
    f = 1
    res = f * 10
    assert typeof(f) == "Python object", typeof(f)
    g = 1
    res = 10*(~g)
    assert typeof(g) == "Python object", typeof(g)
    for j in range(10):
        res = -j
    assert typeof(j) == "Python object", typeof(j)
    h = 1
    res = abs(h)
    assert typeof(h) == "Python object", typeof(h)
    cdef int c_int = 1
    assert typeof(abs(c_int)) == "int", typeof(abs(c_int))

    # float can be inferred
    cdef float fl = 5.0
    from_fl = fl
    assert typeof(from_fl) == "float", typeof(from_fl)


@infer_types(None)
def safe_c_functions():
    """
    >>> safe_c_functions()
    """
    f = cfunc
    assert typeof(f) == 'int (*)(int) except? -1', typeof(f)
    assert 2 == f(1)

@infer_types(None)
def ptr_types():
    """
    >>> ptr_types()
    """
    cdef int a
    a_ptr = &a
    assert typeof(a_ptr) == "int *", typeof(a_ptr)
    a_ptr_ptr = &a_ptr
    assert typeof(a_ptr_ptr) == "int **", typeof(a_ptr_ptr)
    cdef int[1] b
    b_ref = b
    assert typeof(b_ref) == "int *", typeof(b_ref)
    ptr = &a
    ptr = b
    assert typeof(ptr) == "int *", typeof(ptr)

def const_types(const double x, double y, double& z):
    """
    >>> const_types(1, 1, 1)
    """
    a = x
    a = y
    a = z
    assert typeof(a) == "double", typeof(a)

@infer_types(None)
def args_tuple_keywords(*args, **kwargs):
    """
    >>> args_tuple_keywords(1,2,3, a=1, b=2)
    """
    assert typeof(args) == "tuple object", typeof(args)
    assert typeof(kwargs) == "dict object", typeof(kwargs)

@infer_types(None)
def args_tuple_keywords_reassign_same(*args, **kwargs):
    """
    >>> args_tuple_keywords_reassign_same(1,2,3, a=1, b=2)
    """
    assert typeof(args) == "tuple object", typeof(args)
    assert typeof(kwargs) == "dict object", typeof(kwargs)

    args = ()
    kwargs = {}

@infer_types(None)
def args_tuple_keywords_reassign_pyobjects(*args, **kwargs):
    """
    >>> args_tuple_keywords_reassign_pyobjects(1,2,3, a=1, b=2)
    """
    assert typeof(args) == "Python object", typeof(args)
    assert typeof(kwargs) == "Python object", typeof(kwargs)

    args = []
    kwargs = "test"

#                 / A -> AA -> AAA
# Base0 -> Base -
#                 \ B -> BB
# C -> CC

cdef class Base0: pass
cdef class Base(Base0): pass
cdef class A(Base): pass
cdef class AA(A): pass
cdef class AAA(AA): pass
cdef class B(Base): pass
cdef class BB(B): pass
cdef class C: pass
cdef class CC(C): pass

@infer_types(None)
def common_extension_type_base():
    """
    >>> common_extension_type_base()
    """
    x = A()
    x = AA()
    assert typeof(x) == "A", typeof(x)
    y = A()
    y = B()
    assert typeof(y) == "Base", typeof(y)
    z = AAA()
    z = BB()
    assert typeof(z) == "Base", typeof(z)
    w = A()
    w = CC()
    assert typeof(w) == "Python object", typeof(w)

cdef class AcceptsKeywords:
    def __init__(self, *args, **kwds):
        pass

@infer_types(None)
def constructor_call():
    """
    >>> constructor_call()
    """
    x = AcceptsKeywords(a=1, b=2)
    assert typeof(x) == "AcceptsKeywords", typeof(x)


@infer_types(None)
def large_literals():
    """
    >>> large_literals()
    """
    # It's only safe to infer small integer literals.
    a = 10
    b = 100000000000000000000000000000000
    assert typeof(a) == "long", typeof(a)
    assert typeof(b) == "Python object", typeof(b)
    c, d = 10, 100000000000000000000000000000000
    assert typeof(c) == "long", typeof(c)
    assert typeof(d) == "Python object", typeof(d)


class EmptyContextManager(object):
    def __enter__(self):
        return None
    def __exit__(self, *args):
        return 0

def with_statement():
    """
    >>> with_statement()
    Python object
    Python object
    """
    x = 1.0
    with EmptyContextManager() as x:
        print(typeof(x))
    print(typeof(x))
    return x

@cython.final
cdef class TypedContextManager(object):
    cpdef double __enter__(self):
        return 2.0
    def __exit__(self, *args):
        return 0

def with_statement_typed():
    """
    >>> with_statement_typed()
    double
    double
    2.0
    """
    x = 1.0
    with TypedContextManager() as x:
        print(typeof(x))
    print(typeof(x))
    return x

def with_statement_untyped():
    """
    >>> with_statement_untyped()
    Python object
    Python object
    2.0
    """
    x = 1.0
    cdef object t = TypedContextManager()
    with t as x:
        print(typeof(x))
    print(typeof(x))
    return x

def self_lookup(a):
    b = a
    b = b.foo(keyword=None)
    print typeof(b)

# Regression test for trac #638.

def bar(foo):
    qux = foo
    quux = foo[qux.baz]


cdef enum MyEnum:
    enum_x = 1
    enum_y = 2

ctypedef long my_long
def test_int_typedef_inference():
    """
    >>> test_int_typedef_inference()
    """
    cdef long x = 1
    cdef my_long y = 2
    cdef long long z = 3
    assert typeof(x + y) == typeof(y + x) == 'my_long', typeof(x + y)
    assert typeof(y + z) == typeof(z + y) == 'long long', typeof(y + z)

from libc.stdint cimport int32_t, int64_t
def int64_long_sum():
    cdef long x = 1
    cdef int32_t x32 = 2
    cdef int64_t x64 = 3
    cdef unsigned long ux = 4
    assert typeof(x + x32) == typeof(x32 + x) == 'long', typeof(x + x32)
    assert typeof(x + x64) == typeof(x64 + x) == 'int64_t', typeof(x + x64)
    # The correct answer here is either unsigned long or int64_t, depending on
    # whether sizeof(long) == 64 or not.  Incorrect signedness is probably
    # preferable to incorrect width.
    assert typeof(ux + x64) == typeof(x64 + ux) == 'int64_t', typeof(ux + x64)

cdef class InferInProperties:
    """
    >>> InferInProperties().x
    ('double', 'unicode object', 'MyEnum', 'MyEnum')
    """
    cdef MyEnum attr
    def __cinit__(self):
        self.attr = enum_x

    property x:
        def __get__(self):
            a = 1.0
            b = u'abc'
            c = self.attr
            d = enum_y
            c = d
            return typeof(a), typeof(b), typeof(c), typeof(d)

cdef class WithMethods:
    cdef int offset
    def __init__(self, offset):
        self.offset = offset
    cpdef int one_arg(self, int x):
        return x + self.offset
    cpdef int default_arg(self, int x, int y=0):
        return x + y + self.offset

def test_bound_methods():
  """
  >>> test_bound_methods()
  """
  o = WithMethods(10)
  assert typeof(o) == 'WithMethods', typeof(o)

  one_arg = o.one_arg
  assert one_arg(2) == 12, one_arg(2)

  default_arg = o.default_arg
  assert default_arg(2) == 12, default_arg(2)
  assert default_arg(2, 3) == 15, default_arg(2, 2)

def test_builtin_max():
    """
    # builtin max is slightly complicated because it gets transformed to EvalWithTempExprNode
    # See https://github.com/cython/cython/issues/4155
    >>> test_builtin_max()
    """
    class C:
        a = 2
        def get_max(self):
            a = max(self.a, self.a)
            assert typeof(a) == "Python object", typeof(a)
    C().get_max()
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/type_inference_T768.pyx0000644000175100001770000000052100000000000022031 0ustar00runnerdocker00000000000000# mode: run
# ticket: t768
from cython cimport typeof

def type_inference_del_int():
    """
    >>> type_inference_del_int()
    'Python object'
    """
    x = 1
    del x
    return typeof(x)

def type_inference_del_dict():
    """
    >>> type_inference_del_dict()
    'dict object'
    """
    x = {}
    del x
    return typeof(x)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/type_inference_T768_cpp.pyx0000644000175100001770000000057600000000000022705 0ustar00runnerdocker00000000000000# mode: run
# tag: cpp
# ticket: t768
from cython cimport typeof

cdef extern from "shapes.h" namespace "shapes":
    cdef cppclass Shape:
        float area()

    cdef cppclass Circle(Shape):
        int radius
        Circle(int)

def type_inference_del_cpp():
    """
    >>> type_inference_del_cpp()
    'Circle *'
    """
    x = new Circle(10)
    del x
    return typeof(x)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/type_inference_new.pyx0000644000175100001770000000554300000000000022163 0ustar00runnerdocker00000000000000cimport cython

from cython cimport typeof, infer_types


def test_swap():
    """
    >>> test_swap()
    """
    a = 0
    b = 1
    tmp = a
    a = b
    b = tmp
    assert typeof(a) == "long", typeof(a)
    assert typeof(b) == "long", typeof(b)
    assert typeof(tmp) == "long", typeof(tmp)

def test_object_assmt():
    """
    >>> test_object_assmt()
    """
    a = 1
    b = a
    a = "str"
    assert typeof(a) == "Python object", typeof(a)
    assert typeof(b) == "long", typeof(b)


class RAdd(object):
    other = None
    def __radd__(self, other):
        self._other = other
        return self
    def __repr__(self):
        return '%s(%s)' % (type(self).__name__, self._other)


def test_inplace_assignment():
    """
    >>> test_inplace_assignment()
    RAdd([1, 2, 3])
    """
    l = [1, 2, 3]
    # inferred type of l is list, but assignment result is object
    l += RAdd()
    return l


def test_reassignment():
    """
    >>> test_reassignment()
    (1, 2, 3)
    """
    l = [1, 2, 3]
    l = (1, 2, 3)
    return l


def test_long_vs_double(cond):
    """
    >>> test_long_vs_double(0)
    """
    assert typeof(a) == "double", typeof(a)
    assert typeof(b) == "double", typeof(b)
    assert typeof(c) == "double", typeof(c)
    assert typeof(d) == "double", typeof(d)

    if cond:
        a = 1
        b = 2
        c = (a + b) / 2
    else:
        a = 1.0
        b = 2.0
        d = (a + b) / 2

def test_double_vs_pyobject():
    """
    >>> test_double_vs_pyobject()
    """
    assert typeof(a) == "Python object", typeof(a)
    assert typeof(b) == "Python object", typeof(b)
    assert typeof(d) == "double", typeof(d)

    a = []
    b = []

    a = 1.0
    b = 2.0
    d = (a + b) / 2

def test_python_objects(cond):
    """
    >>> test_python_objects(0)
    """
    if cond == 1:
        a = [1, 2, 3]
        o_list = a
    elif cond == 2:
        a = set([1, 2, 3])
        o_set = a
    else:
        a = {1:1, 2:2, 3:3}
        o_dict = a
    assert typeof(a) == "Python object", typeof(a)
    assert typeof(o_list) == "list object", typeof(o_list)
    assert typeof(o_dict) == "dict object", typeof(o_dict)
    assert typeof(o_set) == "set object", typeof(o_set)

# CF loops
def test_cf_loop():
    """
    >>> test_cf_loop()
    """
    cdef int i
    a = 0.0
    for i in range(3):
        a += 1
    assert typeof(a) == "double", typeof(a)

def test_cf_loop_intermediate():
    """
    >>> test_cf_loop()
    """
    cdef int i
    a = 0
    for i in range(3):
        b = a
        a = b + 1
    assert typeof(a) == "long", typeof(a)
    assert typeof(b) == "long", typeof(b)

# Integer overflow
def test_integer_overflow():
    """
    >>> test_integer_overflow()
    """
    a = 1
    b = 2
    c = a + b
    assert typeof(a) == "Python object", typeof(a)
    assert typeof(b) == "Python object", typeof(b)
    assert typeof(c) == "Python object", typeof(c)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/type_slots_int_long_T287.pyx0000644000175100001770000000147600000000000023136 0ustar00runnerdocker00000000000000# ticket: t287

__doc__ = u"""
>>> print( "%d" % Int() )
2
>>> print( "%d" % Long() )
3
>>> print( "%d" % IntLongA() )
2
>>> print( "%d" % IntLongB() )
2

"""


def getint(int i):
    """
    >>> getint( Int() )
    2
    >>> getint( Long() )
    3
    >>> getint( IntLongA() )
    2
    >>> getint( IntLongB() )
    2
    """
    return i

def getlong(long long i):
    """
    >>> getlong( Int() )
    2
    >>> getlong( Long() )
    3
    >>> getlong( IntLongA() )
    2
    >>> getlong( IntLongB() )
    2
    """
    return i


cdef class Int:
   def __int__(self):
       return 2

cdef class Long:
   def __long__(self):
       return 3

cdef class IntLongA:
   def __int__(self):
       return 2
   def __long__(self):
       return 3

cdef class IntLongB:
   def __int__(self):
       return 2
   __long__ = __int__
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/type_slots_nonzero_bool.pyx0000644000175100001770000000114600000000000023300 0ustar00runnerdocker00000000000000__doc__ = """

>>> not not BoolA(0)
False
>>> not not BoolA(1)
True

>>> not not BoolB(0)
False
>>> not not BoolB(1)
True

>>> not not BoolX(0)
False
>>> not not BoolX(1)
True

>>> not not BoolY(0)
False
>>> not not BoolY(1)
True

"""

cdef class BoolA:
    cdef bint value
    def __cinit__(self, bint value):
        self.value = value
    def __nonzero__(self):
        return self.value

cdef class BoolB:
    cdef bint value
    def __cinit__(self, bint value):
        self.value = value
    def __bool__(self):
        return self.value

cdef class BoolX(BoolA):
    pass

cdef class BoolY(BoolB):
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/typed_slice.pyx0000644000175100001770000004116500000000000020617 0ustar00runnerdocker00000000000000# mode: run
# tag: list, tuple, slice, slicing

cimport cython


@cython.test_fail_if_path_exists("//CondExprNode")
def slice_list(list l, int start, int stop):
    """
    >>> slice_list([1,2,3,4], 1, 3)
    [2, 3]
    >>> slice_list([1,2,3,4], 1, 7)
    [2, 3, 4]
    >>> slice_list([], 1, 3)
    []
    >>> slice_list([1], 1, 3)
    []
    >>> slice_list([1,2,3,4], -3, -1)
    [2, 3]
    >>> slice_list([1,2,3,4], -10, -1)
    [1, 2, 3]
    >>> slice_list([], -3, -1)
    []
    >>> slice_list([1], -3, -1)
    []
    """
    return l[start:stop]

@cython.test_fail_if_path_exists("//CondExprNode")
def slice_list_start(list l, int start):
    """
    >>> slice_list_start([1,2,3,4], 1)
    [2, 3, 4]
    >>> slice_list_start([], 1)
    []
    >>> slice_list_start([1], 1)
    []
    >>> slice_list_start([1], 2)
    []
    >>> slice_list_start([1,2,3,4], -3)
    [2, 3, 4]
    >>> slice_list_start([1,2,3,4], -10)
    [1, 2, 3, 4]
    >>> slice_list_start([], -3)
    []
    >>> slice_list_start([1], -3)
    [1]
    """
    return l[start:]


@cython.test_fail_if_path_exists("//CondExprNode")
def slice_list_stop(list l, int stop):
    """
    >>> slice_list_stop([1,2,3,4], 3)
    [1, 2, 3]
    >>> slice_list_stop([1,2,3,4], 7)
    [1, 2, 3, 4]
    >>> slice_list_stop([], 3)
    []
    >>> slice_list_stop([1], 3)
    [1]
    >>> slice_list_stop([1,2,3,4], -3)
    [1]
    >>> slice_list_stop([1,2,3,4], -10)
    []
    >>> slice_list_stop([], -1)
    []
    >>> slice_list_stop([1], -1)
    []
    >>> slice_list_stop([1, 2], -3)
    []
    """
    return l[:stop]


@cython.test_fail_if_path_exists("//CondExprNode")
def slice_list_copy(list l):
    """
    >>> slice_list_copy([])
    []
    >>> slice_list_copy([1,2,3])
    [1, 2, 3]
    """
    return l[:]


@cython.test_fail_if_path_exists("//CondExprNode")
def slice_tuple_copy(tuple l):
    """
    >>> slice_tuple_copy(())
    ()
    >>> slice_tuple_copy((1,2,3))
    (1, 2, 3)
    """
    return l[:]


@cython.test_fail_if_path_exists("//CondExprNode")
def slice_tuple(tuple t, int start, int stop):
    """
    >>> slice_tuple((1,2,3,4), 1, 3)
    (2, 3)
    >>> slice_tuple((1,2,3,4), 1, 7)
    (2, 3, 4)
    >>> slice_tuple((), 1, 3)
    ()
    >>> slice_tuple((1,), 1, 3)
    ()
    >>> slice_tuple((1,2,3,4), -3, -1)
    (2, 3)
    >>> slice_tuple((1,2,3,4), -10, -1)
    (1, 2, 3)
    >>> slice_tuple((), -3, -1)
    ()
    >>> slice_tuple((1,), -3, -1)
    ()
    """
    return t[start:stop]


@cython.test_fail_if_path_exists("//CondExprNode")
def slice_tuple_start(tuple t, int start):
    """
    >>> slice_tuple_start((1,2,3,4), 1)
    (2, 3, 4)
    >>> slice_tuple_start((), 1)
    ()
    >>> slice_tuple_start((1,), 1)
    ()
    >>> slice_tuple_start((1,2,3,4), -3)
    (2, 3, 4)
    >>> slice_tuple_start((1,2,3,4), -10)
    (1, 2, 3, 4)
    >>> slice_tuple_start((), -3)
    ()
    >>> slice_tuple_start((1,), -3)
    (1,)
    """
    return t[start:]


@cython.test_fail_if_path_exists("//CondExprNode")
def slice_tuple_stop(tuple t, int stop):
    """
    >>> slice_tuple_stop((1,2,3,4), 3)
    (1, 2, 3)
    >>> slice_tuple_stop((1,2,3,4), 7)
    (1, 2, 3, 4)
    >>> slice_tuple_stop((), 3)
    ()
    >>> slice_tuple_stop((1,), 3)
    (1,)
    >>> slice_tuple_stop((1,2,3,4), -1)
    (1, 2, 3)
    >>> slice_tuple_stop((), -1)
    ()
    """
    return t[:stop]


@cython.test_fail_if_path_exists("//CondExprNode")
def slice_list_assign_list(list l):
    """
    >>> l = [1,2,3,4]
    >>> l2 = l[:]
    >>> slice_list_assign_list(l2)
    [1, 1, 2, 3, 4, 4]
    """
    l[1:3] = [1,2,3,4]
    return l


@cython.test_fail_if_path_exists("//CondExprNode")
def slice_list_assign_tuple(list l):
    """
    >>> l = [1,2,3,4]
    >>> l2 = l[:]
    >>> slice_list_assign_tuple(l2)
    [1, 1, 2, 3, 4, 4]
    """
    l[1:3] = (1,2,3,4)
    return l


@cython.test_fail_if_path_exists("//CondExprNode")
def slice_list_assign(list l, value):
    """
    >>> l = [1,2,3,4]
    >>> l2 = l[:]
    >>> slice_list_assign(l2, (1,2,3,4))
    [1, 1, 2, 3, 4, 4]
    >>> l2 = l[:]
    >>> slice_list_assign(l2, dict(zip(l,l)))
    [1, 1, 2, 3, 4, 4]
    """
    l[1:3] = value
    return l


def slice_charp(py_string_arg):
    """
    >>> print("%s" % slice_charp('abcdefg'))
    bc
    """
    cdef bytes py_string = py_string_arg.encode(u'ASCII')
    cdef char* s = py_string
    return s[1:3].decode(u'ASCII')


def slice_charp_repeat(py_string_arg):
    """
    >>> print("%s" % slice_charp_repeat('abcdefg'))
    cd
    """
    cdef bytes py_string = py_string_arg.encode(u'ASCII')
    cdef char* s = py_string
    cdef bytes slice_val = s[1:6]
    s = slice_val
    return s[1:3].decode(u'ASCII')


# Readers will find the common boilerplate in the tests below:
#     >>> l = [1,2,3,4,5]
#     >>> t = tuple(l)
#     >>> b = ''.join(map(str, l)).encode('ASCII')
#     >>> u = b.decode('ASCII')
#     >>> o = (l, t, b, u)
#     >>> n = ('list', 'tuple', 'bytes', 'unicode')
#     >>> p = lambda o: o.decode() if isinstance(o, type(b)) else str(o)
#     >>> r = lambda i, *a: '%s[%s] -> %s' % (n[i], ':'.join(map(repr, a)), FUNCTION_NAME(o[i], *a))
# Originally, this was planned to be a basic iteration over
#   the various object types contained within the sliceable fused
#   type, but Python2 -> Python3 semantics changed the class names
#   and string representations used for raw bytes and unicode.
# As a result, we dynamically adjust the printed string output
#   for each test in order to ensure consistent results when running
#   both Python2 and Python3.

ctypedef fused sliceable:
    list
    tuple
    bytes
    unicode


@cython.test_assert_path_exists("//SliceIndexNode//CondExprNode")
def slice_fused_type_start(sliceable seq, start):
    """
    >>> l = [1,2,3,4,5]
    >>> t = tuple(l)
    >>> b = ''.join(map(str, l)).encode('ASCII')
    >>> u = b.decode('ASCII')
    >>> o = (l, t, b, u)
    >>> n = ('list', 'tuple', 'bytes', 'unicode')
    >>> p = lambda o: o.decode() if isinstance(o, type(b)) else str(o)
    >>> r = lambda i, s: '%s[%r:] -> %s' % (n[i], s, p(slice_fused_type_start(o[i], s)))
    >>> for i in range(len(o)):
    ...     for s in (0, len(l) - 1, len(l), -1, -len(l), None):
    ...         print(r(i, s))
    ... 
    list[0:] -> [1, 2, 3, 4, 5]
    list[4:] -> [5]
    list[5:] -> []
    list[-1:] -> [5]
    list[-5:] -> [1, 2, 3, 4, 5]
    list[None:] -> [1, 2, 3, 4, 5]
    tuple[0:] -> (1, 2, 3, 4, 5)
    tuple[4:] -> (5,)
    tuple[5:] -> ()
    tuple[-1:] -> (5,)
    tuple[-5:] -> (1, 2, 3, 4, 5)
    tuple[None:] -> (1, 2, 3, 4, 5)
    bytes[0:] -> 12345
    bytes[4:] -> 5
    bytes[5:] -> 
    bytes[-1:] -> 5
    bytes[-5:] -> 12345
    bytes[None:] -> 12345
    unicode[0:] -> 12345
    unicode[4:] -> 5
    unicode[5:] -> 
    unicode[-1:] -> 5
    unicode[-5:] -> 12345
    unicode[None:] -> 12345
    """
    obj = seq[start:]
    return obj


@cython.test_assert_path_exists("//SliceIndexNode//CondExprNode")
def slice_fused_type_stop(sliceable seq, stop):
    """
    >>> l = [1,2,3,4,5]
    >>> t = tuple(l)
    >>> b = ''.join(map(str, l)).encode('ASCII')
    >>> u = b.decode('ASCII')
    >>> o = (l, t, b, u)
    >>> n = ('list', 'tuple', 'bytes', 'unicode')
    >>> p = lambda o: o.decode() if isinstance(o, type(b)) else str(o)
    >>> r = lambda i, s: '%s[:%r] -> %s' % (n[i], s, p(slice_fused_type_stop(o[i], s)))
    >>> for i in range(len(o)):
    ...     for s in (0, len(l) - 1, len(l), -1, -len(l), None):
    ...         print(r(i, s))
    ... 
    list[:0] -> []
    list[:4] -> [1, 2, 3, 4]
    list[:5] -> [1, 2, 3, 4, 5]
    list[:-1] -> [1, 2, 3, 4]
    list[:-5] -> []
    list[:None] -> [1, 2, 3, 4, 5]
    tuple[:0] -> ()
    tuple[:4] -> (1, 2, 3, 4)
    tuple[:5] -> (1, 2, 3, 4, 5)
    tuple[:-1] -> (1, 2, 3, 4)
    tuple[:-5] -> ()
    tuple[:None] -> (1, 2, 3, 4, 5)
    bytes[:0] -> 
    bytes[:4] -> 1234
    bytes[:5] -> 12345
    bytes[:-1] -> 1234
    bytes[:-5] -> 
    bytes[:None] -> 12345
    unicode[:0] -> 
    unicode[:4] -> 1234
    unicode[:5] -> 12345
    unicode[:-1] -> 1234
    unicode[:-5] -> 
    unicode[:None] -> 12345
    """
    obj = seq[:stop]
    return obj


@cython.test_assert_path_exists("//SliceIndexNode//CondExprNode")
def slice_fused_type_start_and_stop(sliceable seq, start, stop):
    """
    >>> l = [1,2,3,4,5]
    >>> t = tuple(l)
    >>> b = ''.join(map(str, l)).encode('ASCII')
    >>> u = b.decode('ASCII')
    >>> o = (l, t, b, u)
    >>> n = ('list', 'tuple', 'bytes', 'unicode')
    >>> p = lambda o: o.decode() if isinstance(o, type(b)) else str(o)
    >>> r = lambda i, t, s: '%s[%r:%r] -> %s' % (n[i], t, s, p(slice_fused_type_start_and_stop(o[i], t, s)))
    >>> for i in range(len(o)): 
    ...     for start, stop in ((0, len(l)), (0, None), (None, len(l)),
    ...                         (-len(l), 0), (1, 0), (0, 1)):
    ...         print(r(i, start, stop))
    ... 
    list[0:5] -> [1, 2, 3, 4, 5]
    list[0:None] -> [1, 2, 3, 4, 5]
    list[None:5] -> [1, 2, 3, 4, 5]
    list[-5:0] -> []
    list[1:0] -> []
    list[0:1] -> [1]
    tuple[0:5] -> (1, 2, 3, 4, 5)
    tuple[0:None] -> (1, 2, 3, 4, 5)
    tuple[None:5] -> (1, 2, 3, 4, 5)
    tuple[-5:0] -> ()
    tuple[1:0] -> ()
    tuple[0:1] -> (1,)
    bytes[0:5] -> 12345
    bytes[0:None] -> 12345
    bytes[None:5] -> 12345
    bytes[-5:0] -> 
    bytes[1:0] -> 
    bytes[0:1] -> 1
    unicode[0:5] -> 12345
    unicode[0:None] -> 12345
    unicode[None:5] -> 12345
    unicode[-5:0] -> 
    unicode[1:0] -> 
    unicode[0:1] -> 1
    """
    obj = seq[start:stop]
    return obj


def slice_fused_type_step(sliceable seq, step):
    """
    >>> l = [1,2,3,4,5]
    >>> t = tuple(l)
    >>> b = ''.join(map(str, l)).encode('ASCII')
    >>> u = b.decode('ASCII')
    >>> o = (l, t, b, u)
    >>> n = ('list', 'tuple', 'bytes', 'unicode')
    >>> p = lambda o: o.decode() if isinstance(o, type(b)) else str(o)
    >>> r = lambda i, s: '%s[::%r] -> %s' % (n[i], s, p(slice_fused_type_step(o[i], s)))
    >>> for i in range(len(o)):
    ...     for s in (1, -1, 2, -3, 5, -5, None):
    ...         print(r(i, s))
    ... 
    list[::1] -> [1, 2, 3, 4, 5]
    list[::-1] -> [5, 4, 3, 2, 1]
    list[::2] -> [1, 3, 5]
    list[::-3] -> [5, 2]
    list[::5] -> [1]
    list[::-5] -> [5]
    list[::None] -> [1, 2, 3, 4, 5]
    tuple[::1] -> (1, 2, 3, 4, 5)
    tuple[::-1] -> (5, 4, 3, 2, 1)
    tuple[::2] -> (1, 3, 5)
    tuple[::-3] -> (5, 2)
    tuple[::5] -> (1,)
    tuple[::-5] -> (5,)
    tuple[::None] -> (1, 2, 3, 4, 5)
    bytes[::1] -> 12345
    bytes[::-1] -> 54321
    bytes[::2] -> 135
    bytes[::-3] -> 52
    bytes[::5] -> 1
    bytes[::-5] -> 5
    bytes[::None] -> 12345
    unicode[::1] -> 12345
    unicode[::-1] -> 54321
    unicode[::2] -> 135
    unicode[::-3] -> 52
    unicode[::5] -> 1
    unicode[::-5] -> 5
    unicode[::None] -> 12345
    >>> for v in o:
    ...     try: slice_fused_type_step(v, 0)
    ...     except ValueError: pass
    ...     try: slice_fused_type_step(v, v)
    ...     except TypeError: pass
    """
    obj = seq[::step]
    return obj


def slice_fused_type_start_and_step(sliceable seq, start, step):
    """
    >>> l = [1,2,3,4,5]
    >>> t = tuple(l)
    >>> b = ''.join(map(str, l)).encode('ASCII')
    >>> u = b.decode('ASCII')
    >>> o = (l, t, b, u)
    >>> n = ('list', 'tuple', 'bytes', 'unicode')
    >>> p = lambda o: o.decode() if isinstance(o, type(b)) else str(o)
    >>> r = lambda i, s, t: '%s[%r::%r] -> %s' % (n[i], s, t, p(slice_fused_type_start_and_step(o[i], s, t)))
    >>> for i in range(len(o)):
    ...     for start, step in ((0, 1), (0, -1), (1, 1), (1, -1),
    ...                         (None, 1), (None, -1), (None, None),
    ...                         (1, 2), (len(l), -2), (len(l), len(l))):
    ...         print(r(i, start, step))
    ... 
    list[0::1] -> [1, 2, 3, 4, 5]
    list[0::-1] -> [1]
    list[1::1] -> [2, 3, 4, 5]
    list[1::-1] -> [2, 1]
    list[None::1] -> [1, 2, 3, 4, 5]
    list[None::-1] -> [5, 4, 3, 2, 1]
    list[None::None] -> [1, 2, 3, 4, 5]
    list[1::2] -> [2, 4]
    list[5::-2] -> [5, 3, 1]
    list[5::5] -> []
    tuple[0::1] -> (1, 2, 3, 4, 5)
    tuple[0::-1] -> (1,)
    tuple[1::1] -> (2, 3, 4, 5)
    tuple[1::-1] -> (2, 1)
    tuple[None::1] -> (1, 2, 3, 4, 5)
    tuple[None::-1] -> (5, 4, 3, 2, 1)
    tuple[None::None] -> (1, 2, 3, 4, 5)
    tuple[1::2] -> (2, 4)
    tuple[5::-2] -> (5, 3, 1)
    tuple[5::5] -> ()
    bytes[0::1] -> 12345
    bytes[0::-1] -> 1
    bytes[1::1] -> 2345
    bytes[1::-1] -> 21
    bytes[None::1] -> 12345
    bytes[None::-1] -> 54321
    bytes[None::None] -> 12345
    bytes[1::2] -> 24
    bytes[5::-2] -> 531
    bytes[5::5] -> 
    unicode[0::1] -> 12345
    unicode[0::-1] -> 1
    unicode[1::1] -> 2345
    unicode[1::-1] -> 21
    unicode[None::1] -> 12345
    unicode[None::-1] -> 54321
    unicode[None::None] -> 12345
    unicode[1::2] -> 24
    unicode[5::-2] -> 531
    unicode[5::5] -> 
    >>> for o in (l, t, b):
    ...     try: slice_fused_type_start_and_step(o, 0, 0)
    ...     except ValueError: pass
    """
    obj = seq[start::step]
    return obj


def slice_fused_type_stop_and_step(sliceable seq, stop, step):
    """
    >>> l = [1,2,3,4,5]
    >>> t = tuple(l)
    >>> b = ''.join(map(str, l)).encode('ASCII')
    >>> u = b.decode('ASCII')
    >>> o = (l, t, b, u)
    >>> n = ('list', 'tuple', 'bytes', 'unicode')
    >>> p = lambda o: o.decode() if isinstance(o, type(b)) else str(o)
    >>> r = lambda i, s, t: '%s[:%r:%r] -> %s' % (n[i], s, t, p(slice_fused_type_stop_and_step(o[i], s, t)))
    >>> for i in range(len(o)):
    ...     for stop, step in ((len(l), 1), (len(l), None), (None, 1),
    ...                        (len(l), -1), (len(l) - 1, 2), (len(l), -2),
    ...                        (len(l), len(l))):
    ...         print(r(i, stop, step))
    ... 
    list[:5:1] -> [1, 2, 3, 4, 5]
    list[:5:None] -> [1, 2, 3, 4, 5]
    list[:None:1] -> [1, 2, 3, 4, 5]
    list[:5:-1] -> []
    list[:4:2] -> [1, 3]
    list[:5:-2] -> []
    list[:5:5] -> [1]
    tuple[:5:1] -> (1, 2, 3, 4, 5)
    tuple[:5:None] -> (1, 2, 3, 4, 5)
    tuple[:None:1] -> (1, 2, 3, 4, 5)
    tuple[:5:-1] -> ()
    tuple[:4:2] -> (1, 3)
    tuple[:5:-2] -> ()
    tuple[:5:5] -> (1,)
    bytes[:5:1] -> 12345
    bytes[:5:None] -> 12345
    bytes[:None:1] -> 12345
    bytes[:5:-1] -> 
    bytes[:4:2] -> 13
    bytes[:5:-2] -> 
    bytes[:5:5] -> 1
    unicode[:5:1] -> 12345
    unicode[:5:None] -> 12345
    unicode[:None:1] -> 12345
    unicode[:5:-1] -> 
    unicode[:4:2] -> 13
    unicode[:5:-2] -> 
    unicode[:5:5] -> 1
    >>> for v in o:
    ...     try: slice_fused_type_stop_and_step(v, len(l), 0)
    ...     except ValueError: pass
    ...     try: slice_fused_type_stop_and_step(v, len(l), v)
    ...     except TypeError: pass
    """
    obj = seq[:stop:step]
    return obj


def slice_fused_type_all(sliceable seq, start, stop, step):
    """
    >>> l = [1,2,3,4,5]
    >>> t = tuple(l)
    >>> b = ''.join(map(str, l)).encode('ASCII')
    >>> u = b.decode('ASCII')
    >>> o = (l, t, b, u)
    >>> n = ('list', 'tuple', 'bytes', 'unicode')
    >>> p = lambda o: o.decode() if isinstance(o, type(b)) else str(o)
    >>> r = lambda i, s, t, e: '%s[%r:%r:%r] -> %s' % (n[i], s, t, e, p(slice_fused_type_all(o[i], s, t, e)))
    >>> for i in range(len(o)):
    ...     for args in ((0, len(l), 1), (len(l), 0, -1), (None, len(l), 1),
    ...                  (len(l), None, -1), (-len(l), len(l), None), (None, None, None),
    ...                  (1, 3, 2), (len(l), 1, -3), (len(l), 0, 1)):
    ...         print(r(i, *args))
    ... 
    list[0:5:1] -> [1, 2, 3, 4, 5]
    list[5:0:-1] -> [5, 4, 3, 2]
    list[None:5:1] -> [1, 2, 3, 4, 5]
    list[5:None:-1] -> [5, 4, 3, 2, 1]
    list[-5:5:None] -> [1, 2, 3, 4, 5]
    list[None:None:None] -> [1, 2, 3, 4, 5]
    list[1:3:2] -> [2]
    list[5:1:-3] -> [5]
    list[5:0:1] -> []
    tuple[0:5:1] -> (1, 2, 3, 4, 5)
    tuple[5:0:-1] -> (5, 4, 3, 2)
    tuple[None:5:1] -> (1, 2, 3, 4, 5)
    tuple[5:None:-1] -> (5, 4, 3, 2, 1)
    tuple[-5:5:None] -> (1, 2, 3, 4, 5)
    tuple[None:None:None] -> (1, 2, 3, 4, 5)
    tuple[1:3:2] -> (2,)
    tuple[5:1:-3] -> (5,)
    tuple[5:0:1] -> ()
    bytes[0:5:1] -> 12345
    bytes[5:0:-1] -> 5432
    bytes[None:5:1] -> 12345
    bytes[5:None:-1] -> 54321
    bytes[-5:5:None] -> 12345
    bytes[None:None:None] -> 12345
    bytes[1:3:2] -> 2
    bytes[5:1:-3] -> 5
    bytes[5:0:1] -> 
    unicode[0:5:1] -> 12345
    unicode[5:0:-1] -> 5432
    unicode[None:5:1] -> 12345
    unicode[5:None:-1] -> 54321
    unicode[-5:5:None] -> 12345
    unicode[None:None:None] -> 12345
    unicode[1:3:2] -> 2
    unicode[5:1:-3] -> 5
    unicode[5:0:1] -> 
    >>> for v in o:
    ...     try: slice_fused_type_stop_and_step(v, len(l), 0)
    ...     except ValueError: pass
    ...     try: slice_fused_type_stop_and_step(v, len(l), v)
    ...     except TypeError: pass
    """
    obj = seq[start:stop:step]
    return obj
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/typeddefaultargT373.pyx0000644000175100001770000000044400000000000022053 0ustar00runnerdocker00000000000000# ticket: t373

import math

cdef class MyClass:
    """
    >>> x=MyClass()
    4
    """
    def __cinit__(self, int arg=2*2):
        print arg

cdef class MyOtherClass:
    """
    >>> x=MyOtherClass()
    8
    """
    def __cinit__(self, int arg=4*int(math.sqrt(4))):
        print arg
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/typedfieldbug_T303.pyx0000644000175100001770000000221200000000000021641 0ustar00runnerdocker00000000000000# mode: run
# ticket: t303

__doc__ = """
>>> try: readonly()
... except (TypeError, AttributeError): pass
"""


cdef extern from "external_defs.h":
    ctypedef float DoubleTypedef
    ctypedef float LongDoubleTypedef

cdef public DoubleTypedef global_tdef
cdef public double global_double

cdef class MyClass:
    cdef readonly:
        double actual_double
        DoubleTypedef float_isreally_double
        LongDoubleTypedef float_isreally_longdouble

    def __init__(self):
        self.actual_double = 42.0
        self.float_isreally_double = 42.0
        self.float_isreally_longdouble = 42.0

def global_vars(x):
    """
    >>> global_vars(12.0)
    12.0 12.0
    """
    global global_tdef, global_double
    global_tdef = x
    global_double = x
    print global_tdef, global_double

def f():
    """
    >>> f()
    42.0
    42.0
    """
    cdef object c = MyClass()
    print c.actual_double
    print c.float_isreally_double

def longdouble_access():
    """
    >>> longdouble_access()
    42.0
    """
    cdef object c = MyClass()
    print c.float_isreally_longdouble


def readonly():
    cdef object c = MyClass()
    c.actual_double = 3
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/typeof.pyx0000644000175100001770000000204400000000000017612 0ustar00runnerdocker00000000000000from cython cimport typeof

cdef class A:
    pass

cdef class B(A):
    pass

cdef struct X:
    double a
    double complex b

def simple():
    """
    >>> simple()
    int
    long
    long long
    int *
    int **
    A
    B
    X
    Python object
    """
    cdef int i = 0
    cdef long l = 0
    cdef long long ll = 0
    cdef int* iptr = &i
    cdef int** iptrptr = &iptr
    cdef A a = None
    cdef B b = None
    cdef X x = X(a=1, b=2)
    print typeof(i)
    print typeof(l)
    print typeof(ll)
    print typeof(iptr)
    print typeof(iptrptr)
    print typeof(a)
    print typeof(b)
    print typeof(x)
    print typeof(None)
    used = i, l, ll, iptr, iptrptr, a, b, x

def expression():
    """
    >>> expression()
    double
    double complex
    int
    unsigned int
    """
    cdef X x = X(a=1, b=2)
    cdef X *xptr = &x
    cdef short s = 0
    cdef int i = 0
    cdef unsigned int ui = 0
    print typeof(x.a)
    print typeof(xptr.b)
    print typeof(s + i)
    print typeof(i + ui)
    used = x, xptr, s, i, ui
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/typeofexttype.pyx0000644000175100001770000000020100000000000021226 0ustar00runnerdocker00000000000000# mode: run
# tag: exttype


cdef class Spam:
    pass


def test():
    """
    >>> test()
    """
    cdef type t
    t = Spam
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/types.h0000644000175100001770000000021600000000000017056 0ustar00runnerdocker00000000000000/*
This header is present to test effects of misdeclaring
types Cython-side.
*/
typedef long actually_long_t;
typedef short actually_short_t;
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/typetest_T417.pyx0000644000175100001770000000462400000000000020712 0ustar00runnerdocker00000000000000# ticket: t417
#cython: autotestdict=True

cdef class Foo:
    cdef int i
    def __cinit__(self):
        self.i = 1

cdef class SubFoo(Foo):
    pass

cdef class Bar:
    pass

def foo1(arg):
    """
    >>> foo1(Foo())
    >>> foo1(SubFoo())
    >>> foo1(None)
    >>> foo1(123)
    >>> foo1(Bar())
    """
    cdef Foo val = arg

def foo2(arg):
    """
    >>> foo2(Foo())
    >>> foo2(SubFoo())
    >>> foo2(None)
    >>> foo2(123)
    Traceback (most recent call last):
       ...
    TypeError: Cannot convert int to typetest_T417.Foo
    >>> foo2(Bar())
    Traceback (most recent call last):
       ...
    TypeError: Cannot convert typetest_T417.Bar to typetest_T417.Foo
    """
    cdef Foo val = arg

def foo3(arg):
    """
    >>> foo3(Foo())
    >>> foo3(SubFoo())
    >>> foo3(None)
    Traceback (most recent call last):
       ...
    TypeError: Cannot convert NoneType to typetest_T417.Foo
    >>> foo3(123)
    Traceback (most recent call last):
       ...
    TypeError: Cannot convert int to typetest_T417.Foo
    >>> foo2(Bar())
    Traceback (most recent call last):
       ...
    TypeError: Cannot convert typetest_T417.Bar to typetest_T417.Foo
    """
    cdef val = arg

def attribute_access(arg):
    """
    >>> attribute_access(Foo())
    >>> attribute_access(SubFoo())
    >>> attribute_access(None)
    Traceback (most recent call last):
       ...
    TypeError: Cannot convert NoneType to typetest_T417.Foo
    >>> attribute_access(123)
    Traceback (most recent call last):
       ...
    TypeError: Cannot convert int to typetest_T417.Foo
    >>> attribute_access(Bar())
    Traceback (most recent call last):
       ...
    TypeError: Cannot convert typetest_T417.Bar to typetest_T417.Foo
    """
    cdef val = (arg).i


cdef int count = 0

cdef object getFoo():
     global count
     count += 1
     return Foo()

def test_getFoo():
    """
    >>> test_getFoo()
    1
    """
    cdef int old_count = count
    cdef Foo x = getFoo()
    return count - old_count

def test_getFooCast():
    """
    >>> test_getFooCast()
    1
    """
    cdef int old_count = count
    cdef Foo x = getFoo()
    return count - old_count

def test_builtin_typecheck_cast(maybe_list):
    """
    >>> test_builtin_typecheck_cast([])
    []
    >>> test_builtin_typecheck_cast({})
    Traceback (most recent call last):
       ...
    TypeError: Expected list, got dict
    """
    return maybe_list
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/typing_module.py0000644000175100001770000000205200000000000020772 0ustar00runnerdocker00000000000000# mode: run
# tag: pure3.6

from __future__ import print_function

import cython

try:
    import typing
    from typing import List
    from typing import Set as _SET_
except ImportError:
    pass  # this should allow Cython to interpret the directives even when the module doesn't exist


def test_subscripted_types():
    """
    >>> test_subscripted_types()
    dict object
    list object
    set object
    """
    a: typing.Dict[int, float] = {}
    b: List[int] = []
    c: _SET_[object] = set()

    print(cython.typeof(a) + (" object" if not cython.compiled else ""))
    print(cython.typeof(b) + (" object" if not cython.compiled else ""))
    print(cython.typeof(c) + (" object" if not cython.compiled else ""))

@cython.cclass
class TestClassVar:
    """
    >>> TestClassVar.cls
    5
    >>> TestClassVar.regular  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
        ...
    AttributeError:
    """
    regular: int
    cls: typing.ClassVar[int] = 5  # this is a little redundant really because the assignment ensures it
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/typing_module_cy.pyx0000644000175100001770000000146700000000000021666 0ustar00runnerdocker00000000000000# mode: run

import cython

try:
    import typing
    from typing import List
    from typing import Set as _SET_
except ImportError:
    pass  # this should allow Cython to interpret the directives even when the module doesn't exist

def test_subscripted_types():
    """
    >>> test_subscripted_types()
    dict object
    list object
    set object
    """
    cdef typing.Dict[int, float] a = {}
    cdef List[int] b = []
    cdef _SET_[object] c = set()

    print(cython.typeof(a))
    print(cython.typeof(b))
    print(cython.typeof(c))

cdef class TestClassVar:
    """
    >>> TestClassVar.cls
    5
    >>> TestClassVar.regular  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
        ...
    AttributeError:
    """
    cdef int regular
    cdef typing.ClassVar[int] cls
    cls = 5
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/ufunc.pyx0000644000175100001770000001172400000000000017431 0ustar00runnerdocker00000000000000# mode: run
# tag: numpy

cimport cython

import numpy as np

# I'm making these arrays have slightly irregular strides deliberately
int_arr_1d = np.arange(20, dtype=int)[::4]
int_arr_2d = np.arange(500, dtype=int).reshape((50, -1))[5:8, 6:8]
double_arr_1d = int_arr_1d.astype(np.double)
double_arr_2d = int_arr_2d.astype(np.double)
# Numpy has a cutoff at about 500 where it releases the GIL, so test some large arrays
large_int_arr_1d = np.arange(1500, dtype=int)
large_int_arr_2d = np.arange(1500*600, dtype=int).reshape((1500, -1))
large_double_arr_1d = large_int_arr_1d.astype(np.double)
large_double_arr_2d = large_int_arr_2d.astype(np.double)

# it's fairly hard to test that nogil results in the GIL actually
# being released unfortunately
@cython.ufunc
cdef double triple_it(long x) nogil:
    """triple_it doc"""
    return x*3.

def test_triple_it():
    """
    Ufunc also generates a signature so just look at the end
    >>> triple_it.__doc__.endswith('triple_it doc')
    True
    >>> triple_it(int_arr_1d)
    array([ 0., 12., 24., 36., 48.])
    >>> triple_it(int_arr_2d)
    array([[168., 171.],
           [198., 201.],
           [228., 231.]])

    Treat the large arrays just as a "don't crash" test
    >>> _ = triple_it(large_int_arr_1d)
    >>> _ = triple_it(large_int_arr_2d)
    """

@cython.ufunc
cdef double to_the_power(double x, double y):
    return x**y

def test_to_the_power():
    """
    >>> np.allclose(to_the_power(double_arr_1d, 1.), double_arr_1d)
    True
    >>> np.allclose(to_the_power(1., double_arr_2d), np.ones_like(double_arr_2d))
    True
    >>> _ = to_the_power(large_double_arr_1d, -large_double_arr_1d)
    >>> _ = to_the_power(large_double_arr_2d, -large_double_arr_2d)
    """

@cython.ufunc
cdef object py_return_value(double x):
    if x >= 0:
        return x
    # default returns None

def test_py_return_value():
    """
    >>> py_return_value(5.)
    5.0
    >>> py_return_value(double_arr_1d).dtype
    dtype('O')
    >>> py_return_value(-1.)  # returns None
    >>> _ = py_return_value(large_double_arr_1d)
    """

@cython.ufunc
cdef double py_arg(object x):
    return float(x)

def test_py_arg():
    """
    >>> py_arg(np.array([1, "2.0", 3.0], dtype=object))
    array([1., 2., 3.])
    >>> _ = py_arg(np.array([1]*1200, dtype=object))
    """

@cython.ufunc
cdef (double, long) multiple_return_values(long x):
    return x*1.5, x*2

@cython.ufunc
cdef (double, long) multiple_return_values2(long x):
    inefficient_tuple_intermediate = (x*1.5, x*2)
    return inefficient_tuple_intermediate

def test_multiple_return_values():
    """
    >>> multiple_return_values(int_arr_1d)
    (array([ 0.,  6., 12., 18., 24.]), array([ 0,  8, 16, 24, 32]))
    >>> multiple_return_values2(int_arr_1d)
    (array([ 0.,  6., 12., 18., 24.]), array([ 0,  8, 16, 24, 32]))
    """

@cython.ufunc
cdef cython.numeric plus_one(cython.numeric x):
    return x+1

def test_plus_one():
    """
    This generates all the fused combinations
    >>> plus_one(int_arr_1d)  # doctest: +ELLIPSIS
    array([ 1,  5,  9, 13, 17]...)
    >>> plus_one(double_arr_2d)
    array([[57., 58.],
           [67., 68.],
           [77., 78.]])
    >>> plus_one(1.j)
    (1+1j)
    """

###### Test flow-control ######
# An initial implementation of ufunc did some odd restructuring of the code to
# bring the functions completely inline at the Cython level. These tests were to
# test that "return" statements work. They're less needed now, but don't do any
# harm

@cython.ufunc
cdef double return_stops_execution(double x):
    return x
    print "This should not happen"

@cython.ufunc
cdef double return_in_if(double x):
    if x<0:
        return -x
    return x

@cython.ufunc
cdef double nested_loops(double x):
    cdef double counter=0
    while x>counter:
        counter+=10.
        for i in range(100):
            if i>x:
                return i
    return x-counter

def test_flow_control():
    """
    >>> np.allclose(return_stops_execution(double_arr_1d), double_arr_1d)
    True
    >>> return_in_if(-1.)
    1.0
    >>> return_in_if(2.0)
    2.0
    >>> nested_loops(5.5)
    6.0
    >>> nested_loops(105.)
    -5.0
    """

@cython.ufunc
cdef double nested_function(double x):
    def f(x):
        return x*2
    return f(x)

def test_nested_function():
    """
    >>> np.allclose(nested_function(double_arr_1d), 2*double_arr_1d)
    True
    >>> nested_function(-1.)
    -2.0
    """

@cython.ufunc
cdef double can_throw(double x):
    if x<0:
        raise RuntimeError
    return x

def test_can_throw():
    """
    >>> arr = double_arr_1d.copy()
    >>> arr[1] = -1.
    >>> can_throw(arr)
    Traceback (most recent call last):
    ...
    RuntimeError
    >>> large_arr = large_double_arr_1d.copy()
    >>> large_arr[-4] = -2.
    >>> can_throw(large_arr)
    Traceback (most recent call last):
    ...
    RuntimeError
    >>> large_arr2d = large_double_arr_2d.copy()
    >>> large_arr2d[100, 200] = -1.
    >>> can_throw(large_arr2d)
    Traceback (most recent call last):
    ...
    RuntimeError
    """
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/unbound_builtin_methods.pyx0000644000175100001770000000134200000000000023227 0ustar00runnerdocker00000000000000
def list_insert(list l):
    """
    >>> list_insert([1,2,3])
    [1, 4, 2, 3]
    """
    list.insert(l, 1, 4)
    return l


def list_insert_literal():
    """
    >>> list_insert_literal()
    (None, [1, 4, 2, 3])
    """
    l = [1,2,3]
    r = list.insert(l, 1, 4)
    return r, l


def list_insert_assigned():
    """
    >>> list_insert_assigned()
    (None, [1, 4, 2, 3])
    """
    insert = list.insert
    l = [1,2,3]
    r = insert(l, 1, 4)
    return r, l


def list_pop():
    """
    >>> list_pop()
    (2, [1, 3])
    """
    l = [1,2,3]
    r = list.pop(l, 1)
    return r, l


def list_pop_assigned():
    """
    >>> list_pop_assigned()
    [1, 3]
    """
    pop = list.pop
    l = [1,2,3]
    pop(l, 1)
    return l
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/unbound_special_methods.pyx0000644000175100001770000000334200000000000023203 0ustar00runnerdocker00000000000000# mode: run
# tag: special_method

cimport cython

text = u'ab jd  sdflk as sa  sadas asdas fsdf '


@cython.test_fail_if_path_exists(
    "//CoerceFromPyTypeNode")
@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//AttributeNode",
    "//AttributeNode[@entry.cname = 'PyUnicode_Contains']")
def unicode_contains(unicode s, substring):
    """
    >>> unicode_contains(text, u'fl')
    True
    >>> unicode_contains(text, u'XYZ')
    False
    >>> unicode_contains(None, u'XYZ')
    Traceback (most recent call last):
    AttributeError: 'NoneType' object has no attribute '__contains__'
    """
    return s.__contains__(substring)


@cython.test_fail_if_path_exists(
    "//CoerceFromPyTypeNode")
@cython.test_assert_path_exists(
#    "//CoerceToPyTypeNode",
    "//NameNode[@entry.cname = 'PyUnicode_Contains']")
def unicode_contains_unbound(unicode s, substring):
    """
    >>> unicode_contains_unbound(text, u'fl')
    True
    >>> unicode_contains_unbound(text, u'XYZ')
    False
    >>> unicode_contains_unbound(None, u'XYZ')   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: descriptor '__contains__' requires a '...' object but received a 'NoneType'
    """
    return unicode.__contains__(s, substring)


cdef class UnicodeSubclass(unicode):
    """
    >>> u = UnicodeSubclass(text)
    >>> u'fl' in u
    False
    >>> u'XYZ' in u
    True
    >>> u.method(u'fl')
    False
    >>> u.method(u'XYZ')
    True
    >>> u.operator(u'fl')
    False
    >>> u.operator(u'XYZ')
    True
    """
    def __contains__(self, substring):
        return substring not in (self + u'x')

    def method(self, other):
        return self.__contains__(other)

    def operator(self, other):
        return other in self
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/unicode_ascii_auto_encoding.pyx0000644000175100001770000000317400000000000024005 0ustar00runnerdocker00000000000000#cython: c_string_type = unicode
#cython: c_string_encoding = ascii

auto_string_type = unicode

from libc.string cimport strcmp


def _as_string(x):
    try:
        return x.decode('latin1')
    except AttributeError:
        return x


def as_objects(char* ascii_data):
    """
    >>> x = as_objects('abc')
    >>> isinstance(x, auto_string_type) or type(x)
    True
    >>> _as_string(x) == 'abc' or repr(x)
    True
    """
    assert isinstance(ascii_data, auto_string_type)
    assert isinstance(ascii_data, bytes)
    assert isinstance(ascii_data, str)
    assert isinstance(ascii_data, unicode)
    return ascii_data

def from_object():
    """
    >>> from_object()
    """
    cdef bytes b = b"abc"
    cdef str s = "abc"
    cdef unicode u = u"abc"
    assert strcmp(b, "abc") == 0
    assert strcmp(s, "abc") == 0
    assert strcmp(u, "abc") == 0

def slice_as_objects(char* ascii_data, int start, int end):
    """
    >>> x = slice_as_objects('grok', 1, 3)
    >>> isinstance(x, auto_string_type) or type(x)
    True
    >>> _as_string(x) == 'ro' or repr(x)
    True
    """
    assert isinstance(ascii_data[start:end], auto_string_type)
    assert isinstance(ascii_data[start:end], bytes)
    assert isinstance(ascii_data[start:end], str)
    assert isinstance(ascii_data[start:end], unicode)

    assert isinstance(ascii_data[start:], auto_string_type)
    assert isinstance(ascii_data[start:], bytes)
    assert isinstance(ascii_data[start:], str)
    assert isinstance(ascii_data[start:], unicode)

    return ascii_data[start:end]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/unicode_default_auto_encoding.pyx0000644000175100001770000000047300000000000024340 0ustar00runnerdocker00000000000000# cython: c_string_type = unicode
# cython: c_string_encoding = default

import sys
if sys.version_info[0] >= 3:
    __doc__ = r"""
        >>> as_objects("ab\xff") == "ab\xff"
        True
        >>> slice_as_objects("ab\xffd", 1, 4) == "b\xff"
        True
        """

include "unicode_ascii_auto_encoding.pyx"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/unicode_formatting.pyx0000644000175100001770000000266700000000000022177 0ustar00runnerdocker00000000000000# mode: run
# tag: stringformat

from __future__ import unicode_literals


def ascii_format(a, int b, list c):
    """
    >>> print(ascii_format('x', 2, [1]))
    -'x'-2-[1]-
    """
    return '-%a-%a-%a-' % (a, b, c)


def repr_format(a, int b, list c):
    """
    >>> print(repr_format('x', 2, [1]))
    -'x'-2-[1]-
    """
    return '-%r-%r-%r-' % (a, b, c)


def str_format(a, int b, list c):
    """
    >>> print(str_format('x', 2, [1]))
    -x-2-[1]-
    """
    return '-%s-%s-%s-' % (a, b, c)


def mix_format(a, int b, list c):
    """
    >>> print(mix_format('x', 2, [1]))
    -x-2-[1]-
    """
    return '-%s-%r-%a-' % (a, b, c)


class PySubtype(unicode):
    def __rmod__(self, other):
        return f'PyRMOD({self}, {other})'


cdef class ExtSubtype(unicode):
    def __rmod__(self, other):
        return f'ExtRMOD({self}, {other})'


def subtypes():
    """
    >>> py, ext = subtypes()
    >>> print(py)
    PyRMOD(PySub, -%s-)
    >>> print(ext)
    ExtRMOD(ExtSub, -%s-)
    """
    return [
        '-%s-' % PySubtype("PySub"),
        '-%s-' % ExtSubtype("ExtSub"),
    ]


def format_int(value):
    """
    >>> print(format_int(5))
    5
    >>> print(format_int(5.0))
    5
    >>> format_int(u"xyz")  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...int...
    >>> format_int([])  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...int...
    """
    return "%d" % (value,)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/unicode_identifiers.pxd0000644000175100001770000000034500000000000022274 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*-
# cython: language_level=3

cdef Fα1()
cdef class Γναμε2:
    cdef public int α
    cdef boring_cdef(self)
    cdef εxciting_cdef(self)
    cpdef boring_cpdef(self)
    cpdef εxciting_cpdef(self)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/unicode_identifiers.pyx0000644000175100001770000001333200000000000022321 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*-
# mode: run
# tag: pep3131, traceback

# cython: language_level=3

# Code with unicode identifiers can be compiled with Cython running either Python 2 or 3.
# However Python access to unicode identifiers is only possible in Python 3. In Python 2
# it's only really safe to use the unicode identifiers for purely Cython interfaces
# (although this isn't enforced...). Therefore the majority of the doctests are
# Python3 only and only a limited set are run in Python2.
# This is controlled by putting the Python3 only tests in the module __doc__ attribute
# Most of the individual function and class docstrings are only present as a compile test

cimport cython

import sys


if sys.version_info[0] > 2:
    __doc__ = u"""
    >>> f()()
    2
    >>> f().__name__
    'nεsted'

    The test is mainly to see if the traceback is generated correctly
    >>> print_traceback_name()
    unicode_identifiers.Fα1

    Just check that a cpdef function is callable
    >>> Fα3()
    1

    >>> Γναμε2.ναμε3
    1
    >>> x = Γναμε2()
    >>> print(x.α)
    100
    >>> x.α = 200
    >>> print(x.α)
    200

    >>> B().Ƒ()
    >>> C().Ƒ()

    Test generation of locals()
    >>> sorted(Γναμε2().boring_function(1,2).keys())
    ['self', 'somevalue', 'x', 'ναμε5', 'ναμε6']

    >>> Γναμε2().boring_cpdef() - Γναμε2().εxciting_cpdef()
    0
    >>> function_taking_fancy_argument(Γναμε2()).ναμε3
    1
    >>> metho_function_taking_fancy_argument(Γναμε2()).ναμε3
    1
    >>> NormalClassΓΓ().ναμε
    10
    >>> NormalClassΓΓ().εxciting_function(None).__qualname__
    'NormalClassΓΓ.εxciting_function..nestεd'

    Do kwargs work?
    >>> unicode_kwarg(αrγ=5)
    5
    >>> unicode_kwarg_from_cy()
    1

    Normalization of attributes
    (The cdef class version is testable in Python 2 too)
    >>> NormalizeAttrPy().get()
    5
    """
else:
    __doc__ = ""

global_ναμε1 = None
cdef double global_ναμε2 = 1.2

def f():
    """docstring"""
    ναμε2 = 2
    def nεsted():
        return ναμε2
    return nεsted

# Ƒ is notably awkward because its punycode starts with "2" causing
# C compile errors. Therefore try a few different variations...
cdef class A:
    cdef int ναμε
    def __init__(self):
        self.ναμε = 1
    cdef Ƒ(self):
        return self.ναμε == 1
    def regular_function(self):
        """
        Can use unicode cdef functions and (private) attributes internally
        >>> A().regular_function()
        True
        """
        return self.Ƒ()
cdef class B:
    cpdef Ƒ(self):
        pass
cdef class C:
    def Ƒ(self):
        pass
cdef class D:
    cdef int Ƒ

def regular_function():
    """
    Unicode names can be used internally on python2
    >>> regular_function()
    10
    """
    cdef int variableƑ = 5
    ναμε2 = 2
    return variableƑ*ναμε2

cdef Fα1():
    """docstring"""
    ναμε2 = 2
    raise RuntimeError() # forces generation of a traceback

def print_traceback_name():
    try:
        Fα1()
    except RuntimeError as e:
        import traceback
        # get the name of one level up in the traceback
        print(traceback.extract_tb(e.__traceback__,2)[1][2])


def Fα2():
    """docstring"""
    def nested_normal():
        """docstring"""
        pass
    def nεstεd_uni():
        """docstring"""
        pass
    return nested_normal, nεstεd_uni

cpdef Fα3():
    """docstring"""
    return 1

cdef class Γναμε2:
    """
    docstring
    """
    ναμε3 = 1

    def __init__(self):
        self.α = 100
    def boring_function(self,x,ναμε5):
        """docstring"""
        ναμε6 = ναμε5
        somevalue = global_ναμε1 == self.ναμε3
        return locals()
    def εxciting_function(self,y):
        """docstring"""
        def nestεd():
            pass
        return nestεd

    cdef boring_cdef(self):
        """docstring"""
        pass
    cdef εxciting_cdef(self):
        """docstring"""
        pass

    cpdef boring_cpdef(self):
        """docstring"""
        return 2
    cpdef εxciting_cpdef(self):
        """docstring"""
        return 2

cdef class Derived(Γναμε2):
    pass

cdef Γναμε2 global_ναμε3 = Γναμε2()


@cython.always_allow_keywords(False)  # METH_O signature
def metho_function_taking_fancy_argument(Γναμε2 αrγ):
    return αrγ

@cython.always_allow_keywords(True)
def function_taking_fancy_argument(Γναμε2 αrγ):
    return αrγ


class NormalClassΓΓ(Γναμε2):
    """
    docstring
    """
    def __init__(self):
        self.ναμε = 10

    def boring_function(self,x,ναμε5):
        """docstring"""
        ναμε6 = ναμε5
        somevalue = global_ναμε1 == self.ναμε3
        return locals()
    def εxciting_function(self,y):
        """docstring"""
        def nestεd():
            pass
        return nestεd

def unicode_kwarg(*, αrγ):
    return αrγ

def unicode_kwarg_from_cy():
    return unicode_kwarg(αrγ=1)

class NormalizeAttrPy:
    """Python normalizes identifier names before they are used;
    therefore fi and fi should access the same attribute"""
    def __init__(self):
        self.fi = 5 # note unicode ligature symbol
    def get(self):
        return self.fi

cdef class NormalizeAttrCdef:
    """Python normalizes identifier names before they are used;
    therefore fi and fi should access the same attribute
    >>> NormalizeAttrCdef().get()
    5
    """
    cdef int fi # note unicode ligature symbol
    def __init__(self):
        self.fi = 5
    def get(self):
        return self.fi

if sys.version_info[0]<=2:
    # These symbols are causing problems for doctest
    del NormalClassΓΓ
    del globals()[u'Γναμε2'.encode('utf-8')]
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/unicode_identifiers_import.pyx0000644000175100001770000000123300000000000023710 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*-
# cython: language_level = 3
# mode: compile
# tag: pep3131

# compile only test since there's no way to get
# it to import another test module at runtime

# this test looks at [c]importing unicode stuff
from unicode_identifiers cimport Fα1, Γναμε2
cimport unicode_identifiers
from unicode_identifiers cimport Γναμε2 as Γναμε3

from unicode_identifiers import NormalClassΓΓ
from unicode_identifiers import NormalClassΓΓ as NörmalCläss


cdef class C(unicode_identifiers.Γναμε2):
    pass

cdef class D(Γναμε2):
    pass

cdef class E(Γναμε3):
    pass

def f():
    Fα1()
    unicode_identifiers.Fα1()


././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/unicode_identifiers_normalization.srctree0000644000175100001770000000432500000000000026120 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*-
# mode: run
# tag: pure3.0, pep3131

PYTHON build_tests.py
# show behaviour in Python mode
PYTHON -m doctest test0.py
PYTHON -m doctest test1.py
PYTHON -m doctest test2.py

PYTHON setup.py build_ext --inplace
# test in Cython mode
PYTHON -c "import doctest; import test0 as m; exit(doctest.testmod(m)[0])"
PYTHON -c "import doctest; import test1 as m; exit(doctest.testmod(m)[0])"
PYTHON -c "import doctest; import test2 as m; exit(doctest.testmod(m)[0])"

########## setup.py #########

from Cython.Build.Dependencies import cythonize
from distutils.core import setup

setup(
  ext_modules = cythonize("test*.py"),
)

######### build_tests.py ########
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import sys
import unicodedata

# a few pairs of unicode strings that should be equivalent after normalization
string_pairs = [("fi", "fi"), # ligature and two letters
                ("a\u0301", '\u00e1'), # a with acute accent with combining character or as 1 character
                ("α\u0334\u0362", "α\u0362\u0334") # alpha with a pair of combining characters
                    # in a different order. No single character to normalize to
                ]

# Show that the pairs genuinely aren't equal before normalization
for sp in string_pairs:
    assert sp[0] != sp[1]
    assert unicodedata.normalize('NFKC', sp[0]) == unicodedata.normalize('NFKC', sp[1])
    
# some code that accesses the identifiers through the two different names
#  contains doctests
example_code = [
"""
class C:
    '''
    >>> C().get()
    True
    '''
    def __init__(self):
        self.{0} = True
    def get(self):
        return self.{1}
""", """
def pass_through({0}):
    '''
    >>> pass_through(True)
    True
    '''
    return {1}
""", """
import cython
{0} = True
def test():
    '''
    >>> test()
    True
    '''
    return {1}
"""]

from io import open

for idx, (code, strings) in enumerate(zip(example_code, string_pairs)):
    with open("test{0}.py".format(idx), "w", encoding="utf8") as f:
        code = code.format(*strings)
        f.write("# -*- coding: utf-8 -*-\n")
        # The code isn't Py2 compatible. Only write actual code in Py3+.
        if sys.version_info[0] > 2:
            f.write(code)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4287221
Cython-3.0.8/tests/run/unicode_imports.srctree0000644000175100001770000000314400000000000022340 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*-
# tag: py3, pep489

PYTHON setup.py build_ext --inplace
PYTHON -m mydoctest

########### mydoctest.py #######

import sys
if sys.version_info < (3, 5):
    # The module is only Cythonized and not build for these versions
    # so don't run the tests
    exit()
    
import doctest
import from_py
val = doctest.testmod(from_py)[0]
import from_cy
val += doctest.testmod(from_cy)[0]

exit(val)

########### setup.py ########

# -*- coding: utf-8 -*-

from __future__ import unicode_literals

import sys
from Cython.Build import cythonize

files = ["mymoð.pyx", "from_cy.pyx"]


# For Python 2 and Python <= 3.4 just run pyx->c; 
# don't compile the C file
modules = cythonize(files)

if sys.version_info >= (3, 5):
    from distutils.core import setup

    setup(
        ext_modules = modules
    )

############ mymoð.pyx #########

def f():
    return True

cdef public api void cdef_func():
    pass

############ pxd_moð.pxd ##########

cdef struct S:
    int x
    
cdef public api void cdef_func() # just to test generation of headers
    
############ from_py.py #########

# -*- coding: utf-8 -*-

import mymoð
from mymoð import f

__doc__ = """
>>> mymoð.f()
True
>>> f()
True
"""

######### from_cy.pyx ##########

# -*- coding: utf-8 -*-

import mymoð

from mymoð import f

cimport pxd_moð
from pxd_moð cimport S


def test_imported():
    """
    >>> test_imported()
    True
    """
    return mymoð.f() and f() # True and True


def test_cimported():
    """
    >>> test_cimported()
    3
    """
    cdef pxd_moð.S v1
    v1.x = 1
    cdef S v2
    v2.x = 2
    return v1.x + v2.x
    
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unicode_indexing.pyx0000644000175100001770000001753500000000000021632 0ustar00runnerdocker00000000000000
cimport cython

cdef unicode _ustring = u'azerty123456'
ustring = _ustring


@cython.test_assert_path_exists("//CoerceToPyTypeNode",
                                "//IndexNode")
@cython.test_fail_if_path_exists("//IndexNode//CoerceToPyTypeNode")
def index(unicode ustring, Py_ssize_t i):
    """
    >>> index(ustring, 0) == 'a'
    True
    >>> index(ustring, 2) == 'e'
    True
    >>> index(ustring, -1) == '6'
    True
    >>> index(ustring, -len(ustring)) == 'a'
    True

    >>> index(ustring, len(ustring))
    Traceback (most recent call last):
    IndexError: string index out of range
    """
    return ustring[i]


@cython.test_assert_path_exists("//IndexNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def index_pyindex(unicode ustring, i):
    """
    >>> index(ustring, 0) == 'a'
    True
    >>> index(ustring, 2) == 'e'
    True
    >>> index(ustring, -1) == '6'
    True
    >>> index(ustring, -len(ustring)) == 'a'
    True

    >>> index(ustring, len(ustring))
    Traceback (most recent call last):
    IndexError: string index out of range
    """
    return ustring[i]



@cython.test_assert_path_exists("//CoerceToPyTypeNode",
                                "//IndexNode")
@cython.test_fail_if_path_exists("//IndexNode//CoerceToPyTypeNode")
def index_literal(Py_ssize_t i):
    """
    >>> index_literal(0) == 'a'
    True
    >>> index_literal(2) == 'e'
    True
    >>> index_literal(-1) == '6'
    True
    >>> index_literal(-len('azerty123456')) == 'a'
    True

    >>> index_literal(len(ustring))
    Traceback (most recent call last):
    IndexError: string index out of range
    """
    return u'azerty123456'[i]


@cython.test_assert_path_exists("//IndexNode")
@cython.test_fail_if_path_exists("//IndexNode//CoerceToPyTypeNode")
def index_literal_pyunicode_cast(int i):
    """
    >>> index_literal_pyunicode_cast(0) == '1'
    True
    >>> index_literal_pyunicode_cast(-5) == '1'
    True
    >>> index_literal_pyunicode_cast(2) == '3'
    True
    >>> index_literal_pyunicode_cast(4) == '5'
    True
    >>> index_literal_pyunicode_coerce(6)
    Traceback (most recent call last):
    IndexError: string index out of range
    """
    return (u"12345"[i])


@cython.test_assert_path_exists("//IndexNode",
                                "//SingleAssignmentNode")
@cython.test_fail_if_path_exists("//SingleAssignmentNode//CoerceToPyTypeNode")
def index_literal_pyunicode_coerce(int i):
    """
    >>> index_literal_pyunicode_coerce(0) == '1'
    True
    >>> index_literal_pyunicode_coerce(-5) == '1'
    True
    >>> index_literal_pyunicode_coerce(2) == '3'
    True
    >>> index_literal_pyunicode_coerce(4) == '5'
    True
    >>> index_literal_pyunicode_coerce(6)
    Traceback (most recent call last):
    IndexError: string index out of range
    """
    cdef Py_UNICODE result = u"12345"[i]
    return result


@cython.test_assert_path_exists("//SingleAssignmentNode")
@cython.test_fail_if_path_exists("//SingleAssignmentNode//CoerceFromPyTypeNode")
@cython.boundscheck(False)
def index_literal_pyunicode_coerce_no_check(int i):
    """
    >>> index_literal_pyunicode_coerce_no_check(0) == '1'
    True
    >>> index_literal_pyunicode_coerce_no_check(-5) == '1'
    True
    >>> index_literal_pyunicode_coerce_no_check(2) == '3'
    True
    >>> index_literal_pyunicode_coerce_no_check(4) == '5'
    True
    """
    cdef Py_UNICODE result = u"12345"[i]
    return result


@cython.test_assert_path_exists("//CoerceToPyTypeNode",
                                "//IndexNode")
@cython.test_fail_if_path_exists("//IndexNode//CoerceToPyTypeNode")
@cython.boundscheck(False)
def index_no_boundscheck(unicode ustring, Py_ssize_t i):
    """
    >>> index_no_boundscheck(ustring, 0) == 'a'
    True
    >>> index_no_boundscheck(ustring, 2) == 'e'
    True
    >>> index_no_boundscheck(ustring, -1) == '6'
    True
    >>> index_no_boundscheck(ustring, len(ustring)-1) == '6'
    True
    >>> index_no_boundscheck(ustring, -len(ustring)) == 'a'
    True
    """
    return ustring[i]


@cython.test_assert_path_exists("//CoerceToPyTypeNode",
                                "//IndexNode")
@cython.test_fail_if_path_exists("//IndexNode//CoerceToPyTypeNode")
@cython.boundscheck(False)
def unsigned_index_no_boundscheck(unicode ustring, unsigned int i):
    """
    >>> unsigned_index_no_boundscheck(ustring, 0) == 'a'
    True
    >>> unsigned_index_no_boundscheck(ustring, 2) == 'e'
    True
    >>> unsigned_index_no_boundscheck(ustring, len(ustring)-1) == '6'
    True
    """
    return ustring[i]

@cython.test_assert_path_exists("//CoerceToPyTypeNode",
                                "//IndexNode",
                                "//PrimaryCmpNode")
@cython.test_fail_if_path_exists("//IndexNode//CoerceToPyTypeNode")
def index_compare(unicode ustring, Py_ssize_t i):
    """
    >>> index_compare(ustring, 0)
    True
    >>> index_compare(ustring, 1)
    False
    >>> index_compare(ustring, -1)
    False
    >>> index_compare(ustring, -len(ustring))
    True

    >>> index_compare(ustring, len(ustring))
    Traceback (most recent call last):
    IndexError: string index out of range
    """
    return ustring[i] == u'a'


@cython.test_assert_path_exists("//CoerceToPyTypeNode",
                                "//IndexNode",
                                "//PrimaryCmpNode")
@cython.test_fail_if_path_exists("//IndexNode//CoerceToPyTypeNode")
def index_compare_string(unicode ustring, Py_ssize_t i, unicode other):
    """
    >>> index_compare_string(ustring, 0, ustring[0])
    True
    >>> index_compare_string(ustring, 0, ustring[:4])
    False
    >>> index_compare_string(ustring, 1, ustring[0])
    False
    >>> index_compare_string(ustring, 1, ustring[1])
    True
    >>> index_compare_string(ustring, -1, ustring[0])
    False
    >>> index_compare_string(ustring, -1, ustring[-1])
    True
    >>> index_compare_string(ustring, -len(ustring), ustring[-len(ustring)])
    True

    >>> index_compare_string(ustring, len(ustring), ustring)
    Traceback (most recent call last):
    IndexError: string index out of range
    """
    return ustring[i] == other


@cython.test_assert_path_exists("//CoerceToPyTypeNode",
                                "//IndexNode",
                                "//MulNode",
                                "//MulNode/CoerceToPyTypeNode")
@cython.test_fail_if_path_exists("//IndexNode//CoerceToPyTypeNode")
def index_multiply(unicode ustring, Py_ssize_t i, int mul):
    """
    >>> ustring[0] * 5 == 'aaaaa'
    True
    >>> index_multiply(ustring, 0, 5) == 'aaaaa'
    True
    """
    return ustring[i] * mul


@cython.test_assert_path_exists("//CoerceToPyTypeNode",
                                "//IndexNode",
                                "//AddNode",
                                "//AddNode/CoerceToPyTypeNode")
@cython.test_fail_if_path_exists("//IndexNode//CoerceToPyTypeNode")
def index_add(unicode ustring, Py_ssize_t i, Py_ssize_t j):
    """
    >>> ustring[0] + ustring[-1] == 'a6'
    True
    >>> index_add(ustring, 0, -1) == 'a6'
    True
    """
    return ustring[i] + ustring[j]


@cython.test_assert_path_exists("//CoerceToPyTypeNode",
                                "//IndexNode",
                                "//CoerceToPyTypeNode//IndexNode")
@cython.test_fail_if_path_exists("//IndexNode//CoerceToPyTypeNode")
def index_concat_loop(unicode ustring):
    """
    >>> index_concat_loop(ustring) == ustring
    True
    """
    cdef int i
    cdef unicode s = u''
    for i in range(len(ustring)):
        s += ustring[i]
    return s


@cython.test_assert_path_exists("//CoerceToPyTypeNode",
                                "//IndexNode",
                                "//CoerceToPyTypeNode//IndexNode")
@cython.test_fail_if_path_exists("//IndexNode//CoerceToPyTypeNode")
def index_join_loop(unicode ustring):
    """
    >>> index_join_loop(ustring) == ustring
    True
    """
    cdef int i
    return u''.join([ ustring[i] for i in range(len(ustring)) ])
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unicode_kwargs.pyx0000644000175100001770000000332500000000000021313 0ustar00runnerdocker00000000000000# -*- coding: utf8 -*-

try:
    import platform
    IS_PYPY = platform.python_implementation() == 'PyPy'
except (ImportError, AttributeError):
    IS_PYPY = False

ustring_a = u'a'
ustring_ascii = u'abc'
ustring_nonascii = u'àöé\u0888'


def accept_kwargs(a, b, c=1, **kwargs):
    """
    >>> accept_kwargs(1, 2, 3)
    (1, 2, 3, {})
    >>> accept_kwargs(1, 2, 3, d=5)
    (1, 2, 3, {'d': 5})

    >>> accept_kwargs(1, 2, 3, **{ustring_a: 5})
    Traceback (most recent call last):
    TypeError: accept_kwargs() got multiple values for keyword argument 'a'

    >>> if not IS_PYPY: a, b, c, kwargs = accept_kwargs(1, 2, 3, **{ustring_ascii: 5})
    >>> IS_PYPY and (1,2,3,1) or (a,b,c,len(kwargs))
    (1, 2, 3, 1)
    >>> IS_PYPY and 5 or kwargs[ustring_ascii]
    5

    >>> if not IS_PYPY: a, b, c, kwargs = accept_kwargs(1, 2, 3, **{ustring_nonascii: 5})
    >>> IS_PYPY and (1,2,3,1) or (a,b,c,len(kwargs))
    (1, 2, 3, 1)
    >>> IS_PYPY and 5 or kwargs[ustring_nonascii]
    5

    >>> if not IS_PYPY: a, b, c, kwargs = accept_kwargs(1, 2, 3, **{ustring_nonascii: 5, ustring_ascii: 6})
    >>> IS_PYPY and (1,2,3,2) or (a,b,c,len(kwargs))
    (1, 2, 3, 2)
    >>> IS_PYPY and 5 or kwargs[ustring_nonascii]
    5
    >>> IS_PYPY and 6 or kwargs[ustring_ascii]
    6
    """
    return a, b, c, kwargs

def unexpected_kwarg(a, b, c=1):
    """
    >>> unexpected_kwarg(1, b=2)
    (1, 2, 1)
    >>> unexpected_kwarg(1, 2, **{ustring_ascii: 5})
    Traceback (most recent call last):
    TypeError: unexpected_kwarg() got an unexpected keyword argument 'abc'
    >>> unexpected_kwarg(1, 2, 3, d=5)
    Traceback (most recent call last):
    TypeError: unexpected_kwarg() got an unexpected keyword argument 'd'
    """
    return a, b, c
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unicode_slicing.pyx0000644000175100001770000001266500000000000021454 0ustar00runnerdocker00000000000000# coding: utf-8

__doc__ = u"""
    >>> slice_start_end(u'abcdef', 2, 3)
    c
    >>> slice_start(u'abcdef', 2, 3)
    cdef
    >>> slice_end(u'abcdef', 2, 3)
    ab
    >>> slice_all(u'abcdef', 2, 3)
    abcdef
    >>> slice_start_none(u'abcdef', 2, 3)
    cdef
    >>> slice_none_end(u'abcdef', 2, 3)
    ab
    >>> slice_none_none(u'abcdef', 2, 3)
    abcdef

    >>> slice_start_end(u'abcdef', 2, 10)
    cdef
    >>> slice_start(u'abcdef', 2, 10)
    cdef
    >>> slice_end(u'abcdef', 2, 10)
    ab
    >>> slice_all(u'abcdef', 2, 10)
    abcdef

    >>> slice_start_end(u'abcdef', 0, 5)
    abcde
    >>> slice_start(u'abcdef', 0, 5)
    abcdef
    >>> slice_end(u'abcdef', 0, 5)
    
    >>> slice_all(u'abcdef', 0, 5)
    abcdef
    >>> slice_start_none(u'abcdef', 0, 5)
    abcdef
    >>> slice_none_end(u'abcdef', 0, 5)
    
    >>> slice_none_none(u'abcdef', 0, 5)
    abcdef

    >>> slice_start_end(u'abcdef', -6, -1)
    abcde
    >>> slice_start(u'abcdef', -6, -1)
    abcdef
    >>> slice_end(u'abcdef', -6, -1)
    
    >>> slice_all(u'abcdef', -6, -1)
    abcdef
    >>> slice_start_none(u'abcdef', -6, -1)
    abcdef
    >>> slice_none_end(u'abcdef', -6, -1)
    
    >>> slice_none_none(u'abcdef', -6, -1)
    abcdef

    >>> slice_start_end(u'abcdef', -6, -7)
    
    >>> slice_start(u'abcdef', -6, -7)
    abcdef
    >>> slice_end(u'abcdef', -6, -7)
    
    >>> slice_all(u'abcdef', -6, -7)
    abcdef
    >>> slice_start_none(u'abcdef', -6, -7)
    abcdef
    >>> slice_none_end(u'abcdef', -6, -7)
    
    >>> slice_none_none(u'abcdef', -6, -7)
    abcdef

    >>> slice_start_end(u'abcdef', -7, -7)
    
    >>> slice_start(u'abcdef', -7, -7)
    abcdef
    >>> slice_end(u'abcdef', -7, -7)
    
    >>> slice_all(u'abcdef', -7, -7)
    abcdef
    >>> slice_start_none(u'abcdef', -7, -7)
    abcdef
    >>> slice_none_end(u'abcdef', -7, -7)
    
    >>> slice_none_none(u'abcdef', -7, -7)
    abcdef

    >>> slice_start_end(u'aАbБcСdДeЕfФ', 2, 8)
    bБcСdД
    >>> slice_start(u'aАbБcСdДeЕfФ', 2, 8)
    bБcСdДeЕfФ
    >>> slice_end(u'aАbБcСdДeЕfФ', 2, 8)
    aА
    >>> slice_all(u'aАbБcСdДeЕfФ', 2, 8)
    aАbБcСdДeЕfФ
    >>> slice_start_none(u'aАbБcСdДeЕfФ', 2, 8)
    bБcСdДeЕfФ
    >>> slice_none_end(u'aАbБcСdДeЕfФ', 2, 8)
    aА
    >>> slice_none_none(u'aАbБcСdДeЕfФ', 2, 8)
    aАbБcСdДeЕfФ

    >>> slice_start_end(u'АБСДЕФ', 2, 4)
    СД
    >>> slice_start(u'АБСДЕФ', 2, 4)
    СДЕФ
    >>> slice_end(u'АБСДЕФ', 2, 4)
    АБ
    >>> slice_all(u'АБСДЕФ', 2, 4)
    АБСДЕФ
    >>> slice_start_none(u'АБСДЕФ', 2, 4)
    СДЕФ
    >>> slice_none_end(u'АБСДЕФ', 2, 4)
    АБ
    >>> slice_none_none(u'АБСДЕФ', 2, 4)
    АБСДЕФ

    >>> slice_start_end(u'АБСДЕФ', -4, -2)
    СД
    >>> slice_start(u'АБСДЕФ', -4, -2)
    СДЕФ
    >>> slice_end(u'АБСДЕФ', -4, -2)
    АБ
    >>> slice_all(u'АБСДЕФ', -4, -2)
    АБСДЕФ
    >>> slice_start_none(u'АБСДЕФ', -4, -2)
    СДЕФ
    >>> slice_none_end(u'АБСДЕФ', -4, -2)
    АБ
    >>> slice_none_none(u'АБСДЕФ', -4, -2)
    АБСДЕФ

    >>> slice_start_end(None, 2, 4)
    Traceback (most recent call last):    
    TypeError: 'NoneType' object is not subscriptable
    >>> slice_start(None, 2, 4)
    Traceback (most recent call last):    
    TypeError: 'NoneType' object is not subscriptable
    >>> slice_end(None, 2, 4)
    Traceback (most recent call last):    
    TypeError: 'NoneType' object is not subscriptable
    >>> slice_all(None, 2, 4)
    Traceback (most recent call last):    
    TypeError: 'NoneType' object is not subscriptable
    >>> slice_start_none(None, 2, 4)
    Traceback (most recent call last):    
    TypeError: 'NoneType' object is not subscriptable
    >>> slice_none_end(None, 2, 4)
    Traceback (most recent call last):    
    TypeError: 'NoneType' object is not subscriptable
    >>> slice_none_none(None, 2, 4)
    Traceback (most recent call last):    
    TypeError: 'NoneType' object is not subscriptable

    >>> slice_start_end(u'abcdef', SSIZE_T_MAX, SSIZE_T_MIN)
    
    >>> slice_start(u'abcdef', SSIZE_T_MAX, SSIZE_T_MIN)
    
    >>> slice_end(u'abcdef', SSIZE_T_MAX, SSIZE_T_MIN)
    abcdef
    >>> slice_all(u'abcdef', SSIZE_T_MAX, SSIZE_T_MIN)
    abcdef
    >>> slice_start_none(u'abcdef', SSIZE_T_MAX, SSIZE_T_MIN)
    
    >>> slice_none_end(u'abcdef', SSIZE_T_MAX, SSIZE_T_MIN)
    abcdef
    >>> slice_none_none(u'abcdef', SSIZE_T_MAX, SSIZE_T_MIN)
    abcdef
"""

cdef extern from *:
    const Py_ssize_t PY_SSIZE_T_MIN
    const Py_ssize_t PY_SSIZE_T_MAX

SSIZE_T_MAX = PY_SSIZE_T_MAX
SSIZE_T_MIN = PY_SSIZE_T_MIN

import sys

if sys.version_info[0] >= 3:
    __doc__ = __doc__.replace(u"(u'", u"('").replace(u" u'", u" '")

def slice_start_end(unicode s, Py_ssize_t i, Py_ssize_t j):
    print(s[i:j])

def slice_start(unicode s, Py_ssize_t i, Py_ssize_t j):
    print(s[i:])

def slice_end(unicode s, Py_ssize_t i, Py_ssize_t j):
    print(s[:i])

def slice_all(unicode s, Py_ssize_t i, Py_ssize_t j):
    print(s[:])

def slice_start_none(unicode s, Py_ssize_t i, Py_ssize_t j):
    print(s[i:None])

def slice_none_end(unicode s, Py_ssize_t i, Py_ssize_t j):
    print(s[None:i])

def slice_none_none(unicode s, Py_ssize_t i, Py_ssize_t j):
    print(s[None:None])
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unicodeencode.pyx0000644000175100001770000000512700000000000021115 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*-

__doc__ = u"""
>>> len(u)
15
"""

cimport cython

_bytes = bytes

cdef unicode text = u'abcäöüöéèâÁÀABC'

u = text

def default():
    """
    >>> default() == 'abcdefg'.encode()
    True
    """
    return u'abcdefg'.encode()

def encode_non_constant(encoding):
    """
    >>> isinstance(encode_non_constant('utf8'), _bytes)
    True
    >>> encode_non_constant('utf8') == u.encode('UTF-8')
    True
    """
    return text.encode(encoding)

@cython.test_assert_path_exists('//PythonCapiFunctionNode[@cname = "PyUnicode_AsUTF8String"]')
def utf8():
    """
    >>> isinstance(utf8(), _bytes)
    True
    >>> utf8() == u.encode('UTF-8')
    True
    """
    return text.encode(u'UTF-8')

@cython.test_assert_path_exists('//PythonCapiFunctionNode[@cname = "PyUnicode_AsUTF8String"]')
def utf8_strict():
    """
    >>> isinstance(utf8_strict(), _bytes)
    True
    >>> utf8_strict() == u.encode('UTF-8', 'strict')
    True
    """
    return text.encode(u'UTF-8', u'strict')

@cython.test_assert_path_exists('//PythonCapiFunctionNode[@cname = "PyUnicode_AsUTF8String"]')
def utf8_str_strict():
    """
    >>> isinstance(utf8_str_strict(), _bytes)
    True
    >>> utf8_str_strict() == u.encode('UTF-8', 'strict')
    True
    """
    return text.encode('UTF-8', 'strict')

@cython.test_assert_path_exists('//PythonCapiFunctionNode[@cname = "PyUnicode_AsUTF8String"]')
def utf8_bytes_strict():
    """
    >>> isinstance(utf8_bytes_strict(), _bytes)
    True
    >>> utf8_bytes_strict() == u.encode('UTF-8', 'strict')
    True
    """
    return text.encode(b'UTF-8', b'strict')

@cython.test_assert_path_exists('//PythonCapiFunctionNode[@cname = "PyUnicode_AsEncodedString"]')
def ascii_replace():
    """
    >>> isinstance(ascii_replace(), _bytes)
    True
    >>> ascii_replace() == u.encode('ASCII', 'replace')
    True
    """
    return text.encode(u'ASCII', u'replace')

def cp850_strict():
    """
    >>> isinstance(cp850_strict(), _bytes)
    True
    >>> cp850_strict() == u.encode('cp850', 'strict')
    True
    """
    return text.encode(u'cp850', u'strict')

@cython.test_assert_path_exists('//PythonCapiFunctionNode[@cname = "PyUnicode_AsLatin1String"]')
def latin1():
    """
    >>> isinstance(latin1(), _bytes)
    True
    >>> latin1() == u.encode('latin-1')
    True
    """
    return text.encode(u'latin-1')

@cython.test_fail_if_path_exists('//PythonCapiFunctionNode', '//SimpleCallNode')
def latin1_constant():
    """
    >>> isinstance(latin1_constant(), _bytes)
    True
    >>> latin1_constant() == latin1()
    True
    """
    return u'abcäöüöéèâÁÀABC'.encode('latin1')
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unicodefunction.pyx0000644000175100001770000000260300000000000021501 0ustar00runnerdocker00000000000000# mode: run
# tag: unicode

__doc__ = u"""
   >>> u('test')
   u'test'
   >>> e
   u''
   >>> z
   u'test'
   >>> c('testing')
   u'testing'
   >>> subu('testing a Python subtype')
   u'testing a Python subtype'
   >>> sub('testing a Python subtype')
   u'testing a Python subtype'

#   >>> csubu('testing a C subtype')
#   u'testing a C subtype'
#   >>> csub('testing a C subtype')
#   u'testing a C subtype'
"""


cimport cython

import sys
if sys.version_info[0] >= 3:
    __doc__ = __doc__.replace(u" u'", u" '")

u = unicode
e = unicode()
z = unicode(u'test')


def c(string):
    return unicode(string)


class subu(unicode):
    pass


def sub(string):
    return subu(string)


#cdef class csubu(unicode):
#    pass


#def csub(string):
#    return csubu(string)


@cython.test_fail_if_path_exists("//SimpleCallNode")
@cython.test_assert_path_exists("//PythonCapiCallNode")
def typed(unicode s):
    """
    >>> print(typed(None))
    None
    >>> type(typed(None)) is u or type(typed(None))
    True
    >>> print(typed(u'abc'))
    abc
    >>> type(typed(u'abc')) is u or type(typed(u'abc'))
    True
    """
    return unicode(s)


@cython.test_fail_if_path_exists(
    "//SimpleCallNode",
    "//PythonCapiCallNode",
)
def typed_not_none(unicode s not None):
    """
    >>> print(typed(u'abc'))
    abc
    >>> type(typed(u'abc')) is u or type(typed(u'abc'))
    True
    """
    return unicode(s)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unicodeliterals.pyx0000644000175100001770000000620100000000000021471 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*-

import sys

__doc__ = br"""
    >>> sa
    'abc'
    >>> ua
    u'abc'
    >>> b
    u'123'
    >>> c
    u'S\xf8k ik'
    >>> d
    u'\xfc\xd6\xe4'
    >>> e
    u'\x03g\xf8\uf8d2S\xf8k ik'
    >>> f
    u'\xf8'
    >>> g
    u'\udc00'
    >>> h
    u'\ud800'
    >>> q
    u'\udc00\ud800'

    # The output of surrogate pairs differs between 16/32bit Unicode runtimes.
    #>>> p
    #u'\ud800\udc00'

    >>> add
    u'S\xf8k ik\xfc\xd6\xe4abc'
    >>> null
    u'\x00'
""".decode("ASCII") + b"""
    >>> len(sa)
    3
    >>> len(ua)
    3
    >>> len(b)
    3
    >>> len(c)
    6
    >>> len(d)
    3
    >>> len(e)
    10
    >>> len(f)
    1
    >>> len(g)
    1
    >>> len(h)
    1
    >>> len(q)
    2
    >>> len(q)
    2
    >>> len(add)
    12
    >>> len(null)
    1
    >>> sys.maxunicode >= 65535
    True
    >>> sys.maxunicode == 65535 and 1 or len(wide_literal) # test for wide build
    1
    >>> sys.maxunicode > 65535 and 2 or len(wide_literal)  # test for narrow build
    2
""".decode("ASCII") + u"""
    >>> ua == u'abc'
    True
    >>> b == u'123'
    True
    >>> c == u'Søk ik'
    True
    >>> d == u'üÖä'
    True
    >>> e == u'\x03\x67\xf8\uf8d2Søk ik'     # unescaped by Cython
    True
    >>> e == u'\\x03\\x67\\xf8\\uf8d2Søk ik' # unescaped by Python
    True
    >>> f == u'\xf8'  # unescaped by Cython
    True
    >>> f == u'\\xf8' # unescaped by Python
    True
    >>> g == u'\\udc00' # unescaped by Python (required by doctest)
    True
    >>> h == u'\\ud800' # unescaped by Python (required by doctest)
    True
    >>> p == (u'\\ud800\\udc00' if sys.maxunicode == 1114111 else u'\\U00010000')  or  p  # unescaped by Python (required by doctest)
    True
    >>> q == u'\\udc00\\ud800'  or  q  # unescaped by Python (required by doctest)
    True
    >>> k == u'\\N{SNOWMAN}' == u'\\u2603'  or  k
    True
    >>> m == u'abc\\\\xf8\\\\t\\u00f8\\U000000f8'  or  m  # unescaped by Python (required by doctest)
    True
    >>> add == u'Søk ik' + u'üÖä' + 'abc'  or  add
    True
    >>> null == u'\\x00' # unescaped by Python (required by doctest)
    True
    >>> wide_literal == u'\\U00101234'   # unescaped by Python
    True
    >>> ustring_in_constant_tuple == ('a', u'abc', u'\\N{SNOWMAN}', u'x' * 3, u'\\N{SNOWMAN}' * 4 + u'O')  or  ustring_in_constant_tuple  # unescaped by Python
    True

    >>> expected = u'\U00101234'    # unescaped by Cython
    >>> if wide_literal == expected: print(True)
    ... else: print(repr(wide_literal), repr(expected), sys.maxunicode)
    True
"""

if sys.version_info[0] >= 3:
    __doc__ = __doc__.replace(u" u'", u" '")
else:
    __doc__ = __doc__.replace(u" b'", u" '")

sa = 'abc'
ua = u'abc'

b = u'123'
c = u'Søk ik'
d = u'üÖä'
e = u'\x03\x67\xf8\uf8d2Søk ik'
f = u'\xf8'
g = u'\udc00'   # lone trail surrogate
h = u'\ud800'   # lone lead surrogate
k = u'\N{SNOWMAN}'
m = ur'abc\xf8\t\u00f8\U000000f8'
p = u'\ud800\udc00'  # surrogate pair
q = u'\udc00\ud800'  # reversed surrogate pair

add = u'Søk ik' + u'üÖä' + u'abc'
null = u'\x00'

wide_literal = u'\U00101234'

ustring_in_constant_tuple = ('a', u'abc', u'\N{SNOWMAN}', u'x' * 3, u'\N{SNOWMAN}' * 4 + u'O')
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unicodeliteralsdefault.pyx0000644000175100001770000000276400000000000023050 0ustar00runnerdocker00000000000000## keep two lines free to make sure PEP 263 does not apply
##

##

# This file is written in UTF-8, but it has no encoding declaration,
# so it just defaults to UTF-8 (PEP 3120).

__doc__ = br"""
    >>> sa
    'abc'
    >>> ua
    u'abc'
    >>> b
    u'123'
    >>> c
    u'S\xf8k ik'
    >>> d
    u'\xfc\xd6\xe4'
    >>> e
    u'\x03g\xf8\uf8d2S\xf8k ik'
    >>> f
    u'\xf8'
    >>> add
    u'S\xf8k ik\xfc\xd6\xe4abc'
    >>> null
    u'\x00'
""".decode("ASCII") + b"""
    >>> len(sa)
    3
    >>> len(ua)
    3
    >>> len(b)
    3
    >>> len(c)
    6
    >>> len(d)
    3
    >>> len(e)
    10
    >>> len(f)
    1
    >>> len(add)
    12
    >>> len(null)
    1
""".decode("ASCII") + u"""
    >>> ua == u'abc'
    True
    >>> b == u'123'
    True
    >>> c == u'Søk ik'
    True
    >>> d == u'üÖä'
    True
    >>> e == u'\x03\x67\xf8\uf8d2Søk ik'     # unescaped by Cython
    True
    >>> e == u'\\x03\\x67\\xf8\\uf8d2Søk ik' # unescaped by Python
    True
    >>> f == u'\xf8'  # unescaped by Cython
    True
    >>> f == u'\\xf8' # unescaped by Python
    True
    >>> add == u'Søk ik' + u'üÖä' + 'abc'
    True
    >>> null == u'\\x00' # unescaped by Python (required by doctest)
    True
"""

import sys
if sys.version_info[0] >= 3:
    __doc__ = __doc__.replace(u" u'", u" '")
else:
    __doc__ = __doc__.replace(u" b'", u" '")

sa = 'abc'
ua = u'abc'

b = u'123'
c = u'Søk ik'
d = u'üÖä'
e = u'\x03\x67\xf8\uf8d2Søk ik'
f = u'\xf8'

add = u'Søk ik' + u'üÖä' + u'abc'
null = u'\x00'
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unicodeliteralslatin1.pyx0000644000175100001770000000270100000000000022603 0ustar00runnerdocker00000000000000# -*- coding: latin-1 -*-

__doc__ = br"""
    >>> sa
    'abc'
    >>> ua
    u'abc'
    >>> b
    u'123'
    >>> c
    u'S\xf8k ik'
    >>> d
    u'\xfc\xd6\xe4'
    >>> e
    u'\x03g\xf8\uf8d2S\xf8k ik'
    >>> f
    u'\xf8'
    >>> add
    u'S\xf8k ik\xfc\xd6\xe4abc'
    >>> null
    u'\x00'
""".decode("ASCII") + b"""
    >>> len(sa)
    3
    >>> len(ua)
    3
    >>> len(b)
    3
    >>> len(c)
    6
    >>> len(d)
    3
    >>> len(e)
    10
    >>> len(f)
    1
    >>> len(add)
    12
    >>> len(null)
    1
""".decode("ASCII") + u"""
    >>> ua == u'abc'
    True
    >>> b == u'123'
    True
    >>> c == u'Sk ik'
    True
    >>> d == u''
    True
    >>> e == u'\x03\x67\xf8\uf8d2Sk ik'     # unescaped by Cython
    True
    >>> e == u'\\x03\\x67\\xf8\\uf8d2Sk ik' # unescaped by Python
    True
    >>> f == u'\xf8'  # unescaped by Cython
    True
    >>> f == u'\\xf8' # unescaped by Python
    True
    >>> k == u'' == u'\\N{LATIN SMALL LETTER A WITH DIAERESIS}'
    True
    >>> add == u'Sk ik' + u'' + 'abc'
    True
    >>> null == u'\\x00' # unescaped by Python (required by doctest)
    True
"""

import sys
if sys.version_info[0] >= 3:
    __doc__ = __doc__.replace(u" u'", u" '")
else:
    __doc__ = __doc__.replace(u" b'", u" '")

sa = 'abc'
ua = u'abc'

b = u'123'
c = u'Sk ik'
d = u''
e = u'\x03\x67\xf8\uf8d2Sk ik'
f = u'\xf8'
k = u'\N{LATIN SMALL LETTER A WITH DIAERESIS}'

add = u'Sk ik' + u'' + u'abc'
null = u'\x00'
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unicodemethods.pyx0000644000175100001770000006174400000000000021332 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*-

cimport cython

import sys

text = u'ab jd  sdflk as sa  sadas asdas fsdf '
sep = u'  '
format1 = u'abc%sdef'
format2 = u'abc%sdef%sghi'
unicode_sa = u'sa'

multiline_text = u'''\
ab jd
sdflk as sa
sadas asdas fsdf '''

def print_all(l):
    for s in l:
        print(s)


# unicode.split(s, [sep, [maxsplit]])

@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
def split(unicode s):
    """
    >>> def test_split():
    ...     py = text.split()
    ...     cy = split(text)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> print_all( test_split() )
    ab
    jd
    sdflk
    as
    sa
    sadas
    asdas
    fsdf
    """
    return s.split()

@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
def split_sep(unicode s, sep):
    """
    >>> def test_split_sep(sep):
    ...     py = text.split(sep)
    ...     cy = split_sep(text, sep)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> print_all( test_split_sep(sep) )
    ab jd
    sdflk as sa
    sadas asdas fsdf\x20
    >>> print_all( test_split_sep(None) )
    ab
    jd
    sdflk
    as
    sa
    sadas
    asdas
    fsdf
    """
    return s.split(sep)

@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode",
    "//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
    "//CoerceFromPyTypeNode",
    "//PythonCapiCallNode")
def split_sep_max(unicode s, sep, max):
    """
    >>> def test_split_sep_max(sep, max):
    ...     py = text.split(sep, max)
    ...     cy = split_sep_max(text, sep, max)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> print_all( test_split_sep_max(sep, 1) )
    ab jd
    sdflk as sa  sadas asdas fsdf\x20
    >>> print_all( test_split_sep_max(None, 2) )
    ab
    jd
    sdflk as sa  sadas asdas fsdf\x20
    >>> print_all( text.split(None, 2) )
    ab
    jd
    sdflk as sa  sadas asdas fsdf\x20
    >>> print_all( split_sep_max(text, None, 2) )
    ab
    jd
    sdflk as sa  sadas asdas fsdf\x20
    """
    return s.split(sep, max)

@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode", "//CoerceFromPyTypeNode",
    "//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
def split_sep_max_int(unicode s, sep):
    """
    >>> def test_split_sep_max_int(sep):
    ...     py = text.split(sep, 1)
    ...     cy = split_sep_max_int(text, sep)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> print_all( test_split_sep_max_int(sep) )
    ab jd
    sdflk as sa  sadas asdas fsdf\x20
    >>> print_all( test_split_sep_max_int(None) )
    ab
    jd  sdflk as sa  sadas asdas fsdf\x20
    """
    return s.split(sep, 1)


# unicode.splitlines(s, [keepends])

@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
def splitlines(unicode s):
    """
    >>> def test_splitlines(s):
    ...     py = s.splitlines()
    ...     cy = splitlines(s)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> len(test_splitlines(multiline_text))
    3
    >>> print_all( test_splitlines(multiline_text) )
    ab jd
    sdflk as sa
    sadas asdas fsdf\x20
    """
    return s.splitlines()

@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
def splitlines_keep(unicode s, keep):
    """
    >>> def test_splitlines_keep(s, keep):
    ...     py = s.splitlines(keep)
    ...     cy = splitlines_keep(s, keep)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> len(test_splitlines_keep(multiline_text, True))
    3
    >>> print_all( test_splitlines_keep(multiline_text, True) )
    ab jd
    
    sdflk as sa
    
    sadas asdas fsdf\x20
    """
    return s.splitlines(keep)

@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode", "//CoerceFromPyTypeNode",
    "//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
def splitlines_keep_bint(unicode s):
    """
    >>> def test_splitlines_keep_bint(s):
    ...     py = s.splitlines(True) + ['--'] + s.splitlines(False)
    ...     cy = splitlines_keep_bint(s)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> len(test_splitlines_keep_bint(multiline_text))
    7
    >>> print_all( test_splitlines_keep_bint(multiline_text) )
    ab jd
    
    sdflk as sa
    
    sadas asdas fsdf\x20
    --
    ab jd
    sdflk as sa
    sadas asdas fsdf\x20
    """
    return s.splitlines(True) + ['--'] + s.splitlines(False)


# unicode.join(s, iterable)

pipe_sep = u'|'

@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode", "//CoerceFromPyTypeNode",
    "//CastNode", "//TypecastNode",
    "//SimpleCallNode//AttributeNode[@is_py_attr = true]")
@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
)
def join(unicode sep, l):
    """
    >>> def test_join(sep, l):
    ...     py = sep.join(l)
    ...     cy = join(sep, l)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> l = text.split()
    >>> len(l)
    8
    >>> print( test_join(pipe_sep, l) )
    ab|jd|sdflk|as|sa|sadas|asdas|fsdf
    """
    return sep.join(l)


@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode", "//CoerceFromPyTypeNode",
    "//CastNode", "//TypecastNode", "//NoneCheckNode",
    "//SimpleCallNode//AttributeNode[@is_py_attr = true]")
@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
)
def join_sep(l):
    """
    >>> def test_join_sep(l):
    ...     py = '|'.join(l)
    ...     cy = join_sep(l)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> l = text.split()
    >>> len(l)
    8
    >>> print( test_join_sep(l) )
    ab|jd|sdflk|as|sa|sadas|asdas|fsdf
    """
    result = u'|'.join(l)
    assert cython.typeof(result) == 'unicode object', cython.typeof(result)
    return result


@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode", "//CoerceFromPyTypeNode",
    "//CastNode", "//TypecastNode", "//NoneCheckNode",
    "//SimpleCallNode//AttributeNode[@is_py_attr = true]"
)
@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
    "//InlinedGeneratorExpressionNode"
)
def join_sep_genexpr(l):
    """
    >>> def test_join_sep_genexpr(l):
    ...     py = '|'.join(s + ' ' for s in l)
    ...     cy = join_sep_genexpr(l)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> l = text.split()
    >>> len(l)
    8
    >>> print( '<<%s>>' % test_join_sep_genexpr(l) )
    <>
    """
    result = u'|'.join(s + u' ' for s in l)
    assert cython.typeof(result) == 'unicode object', cython.typeof(result)
    return result


@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode", "//CoerceFromPyTypeNode",
    "//CastNode", "//TypecastNode",
)
@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
    "//InlinedGeneratorExpressionNode"
)
def join_sep_genexpr_dictiter(dict d):
    """
    >>> def test_join_sep_genexpr_dictiter(d):
    ...     py = '|'.join( sorted(' '.join('%s:%s' % (k, v) for k, v in d.items()).split()) )
    ...     cy = '|'.join( sorted(join_sep_genexpr_dictiter(d).split()) )
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> l = text.split()
    >>> d = dict(zip(range(len(l)), l))
    >>> print( test_join_sep_genexpr_dictiter(d) )
    0:ab|1:jd|2:sdflk|3:as|4:sa|5:sadas|6:asdas|7:fsdf
    """
    result = u' '.join('%s:%s' % (k, v) for k, v in d.iteritems())
    assert cython.typeof(result) == 'unicode object', cython.typeof(result)
    return result


@cython.test_assert_path_exists(
    "//PythonCapiCallNode",
)
def join_unbound(unicode sep, l):
    """
    >>> def test_join_unbound(sep, l):
    ...     py = sep.join(l)
    ...     cy = join_unbound(sep, l)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> l = text.split()
    >>> len(l)
    8
    >>> print( test_join_unbound(pipe_sep, l) )
    ab|jd|sdflk|as|sa|sadas|asdas|fsdf
    """
    join = unicode.join
    return join(sep, l)


# unicode.startswith(s, prefix, [start, [end]])

@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode",
    "//CoerceFromPyTypeNode",
    "//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
def startswith(unicode s, sub):
    """
    >>> def test_startswith(s, sub):
    ...     py = s.startswith(sub)
    ...     cy = startswith(s, sub)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> test_startswith(text, 'ab ')
    True
    >>> test_startswith(text, 'ab X')
    False

    >>> test_startswith(text, ('ab', 'ab '))
    True
    >>> not test_startswith(text, (' ab', 'ab X'))
    True
    """
    if s.startswith(sub):
        return True
    else:
        return False

@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode",
    "//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
    "//CoerceFromPyTypeNode",
    "//PythonCapiCallNode")
def startswith_start_end(unicode s, sub, start, end):
    """
    >>> def test_startswith_start_end(s, sub, start, end):
    ...     py = s.startswith(sub, start, end)
    ...     cy = startswith_start_end(s, sub, start, end)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> test_startswith_start_end(text, 'b ', 1, 5)
    True
    >>> test_startswith_start_end(text, 'ab ', -1000, 5000)
    True
    >>> test_startswith_start_end(text, 'b X', 1, 5)
    False

    >>> test_startswith_start_end(text, 'ab ', None, None)
    True
    >>> test_startswith_start_end(text, 'ab ', 1, None)
    False
    >>> test_startswith_start_end(text, 'b ',  1, None)
    True
    >>> test_startswith_start_end(text, 'ab ', None, 3)
    True
    >>> test_startswith_start_end(text, 'ab ', None, 2)
    False
    """
    if s.startswith(sub, start, end):
        return True
    else:
        return False


# unicode.endswith(s, prefix, [start, [end]])

@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode",
    "//CoerceFromPyTypeNode",
    "//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
def endswith(unicode s, sub):
    """
    >>> def test_endswith(s, sub):
    ...     py = s.endswith(sub)
    ...     cy = endswith(s, sub)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> test_endswith(text, 'fsdf ')
    True
    >>> test_endswith(text, 'fsdf X')
    False

    >>> test_endswith(text, ('fsdf', 'fsdf '))
    True
    >>> test_endswith(text, ('fsdf', 'fsdf X'))
    False
    """
    if s.endswith(sub):
        return True
    else:
        return False

@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode",
    "//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
    "//CoerceFromPyTypeNode",
    "//PythonCapiCallNode")
def endswith_start_end(unicode s, sub, start, end):
    """
    >>> def test_endswith_start_end(s, sub, start, end):
    ...     py = s.endswith(sub, start, end)
    ...     cy = endswith_start_end(s, sub, start, end)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> test_endswith_start_end(text, 'fsdf', 10, len(text)-1)
    True
    >>> test_endswith_start_end(text, 'fsdf ', 10, len(text)-1)
    False

    >>> test_endswith_start_end(text, 'fsdf ', -1000, 5000)
    True

    >>> test_endswith_start_end(text, ('fsd', 'fsdf'), 10, len(text)-1)
    True
    >>> test_endswith_start_end(text, ('fsdf ', 'fsdf X'), 10, len(text)-1)
    False

    >>> test_endswith_start_end(text, 'fsdf ', None, None)
    True
    >>> test_endswith_start_end(text, 'fsdf ', 32, None)
    True
    >>> test_endswith_start_end(text, 'fsdf ', 33, None)
    False
    >>> test_endswith_start_end(text, 'fsdf ', None, 37)
    True
    >>> test_endswith_start_end(text, 'fsdf ', None, 36)
    False
    """
    if s.endswith(sub, start, end):
        return True
    else:
        return False


# unicode.__contains__(s, sub)

@cython.test_fail_if_path_exists(
    "//CoerceFromPyTypeNode", "//AttributeNode")
@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode", "//PrimaryCmpNode")
def in_test(unicode s, substring):
    """
    >>> in_test(text, 'sa')
    True
    >>> in_test(text, 'XYZ')
    False
    >>> in_test(None, 'sa')
    Traceback (most recent call last):
    TypeError: 'NoneType' object is not iterable
    """
    return substring in s


# unicode.__concat__(s, suffix)

def concat_any(unicode s, suffix):
    """
    >>> concat(text, 'sa') == text + 'sa'  or  concat(text, 'sa')
    True
    >>> concat(None, 'sa')   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> concat(text, None)   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> class RAdd(object):
    ...     def __radd__(self, other):
    ...         return 123
    >>> concat(None, 'sa')   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    assert cython.typeof(s + suffix) == 'Python object', cython.typeof(s + suffix)
    return s + suffix


def concat(unicode s, str suffix):
    """
    >>> concat(text, 'sa') == text + 'sa'  or  concat(text, 'sa')
    True
    >>> concat(None, 'sa')   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> concat(text, None)   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> class RAdd(object):
    ...     def __radd__(self, other):
    ...         return 123
    >>> concat(None, 'sa')   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    assert cython.typeof(s + object()) == 'Python object', cython.typeof(s + object())
    assert cython.typeof(s + suffix) == 'unicode object', cython.typeof(s + suffix)
    return s + suffix


def concat_literal_str(str suffix):
    """
    >>> concat_literal_str('sa') == 'abcsa'  or  concat_literal_str('sa')
    True
    >>> concat_literal_str(None)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...NoneType...
    """
    assert cython.typeof(u'abc' + object()) == 'Python object', cython.typeof(u'abc' + object())
    assert cython.typeof(u'abc' + suffix) == 'unicode object', cython.typeof(u'abc' + suffix)
    return u'abc' + suffix


def concat_literal_unicode(unicode suffix):
    """
    >>> concat_literal_unicode(unicode_sa) == 'abcsa'  or  concat_literal_unicode(unicode_sa)
    True
    >>> concat_literal_unicode(None)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...NoneType...
    """
    assert cython.typeof(u'abc' + suffix) == 'unicode object', cython.typeof(u'abc' + suffix)
    return u'abc' + suffix


# unicode.__mod__(format, values)

def mod_format(unicode s, values):
    """
    >>> mod_format(format1, 'sa') == 'abcsadef'  or  mod_format(format1, 'sa')
    True
    >>> mod_format(format2, ('XYZ', 'ABC')) == 'abcXYZdefABCghi'  or  mod_format(format2, ('XYZ', 'ABC'))
    True

    Exact TypeError message is different in PyPy
    >>> mod_format(None, 'sa')   # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    TypeError: unsupported operand type(s) for %: 'NoneType' and 'str'
    >>> class RMod(object):
    ...     def __rmod__(self, other):
    ...         return 123
    >>> mod_format(None, RMod())
    123
    """
    assert cython.typeof(s % values) == 'Python object', cython.typeof(s % values)
    return s % values


def mod_format_literal(values):
    """
    >>> mod_format_literal('sa') == 'abcsadef'  or  mod_format(format1, 'sa')
    True
    >>> mod_format_literal(('sa',)) == 'abcsadef'  or  mod_format(format1, ('sa',))
    True
    >>> mod_format_literal(['sa']) == "abc['sa']def"  or  mod_format(format1, ['sa'])
    True
    """
    assert cython.typeof(u'abc%sdef' % values) == 'unicode object', cython.typeof(u'abc%sdef' % values)
    return u'abc%sdef' % values


def mod_format_tuple(*values):
    """
    >>> mod_format_tuple('sa') == 'abcsadef'  or  mod_format(format1, 'sa')
    True
    >>> mod_format_tuple()
    Traceback (most recent call last):
    TypeError: not enough arguments for format string
    """
    assert cython.typeof(u'abc%sdef' % values) == 'unicode object', cython.typeof(u'abc%sdef' % values)
    return u'abc%sdef' % values


# unicode.find(s, sub, [start, [end]])

@cython.test_fail_if_path_exists(
    "//CoerceFromPyTypeNode",
    "//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//PythonCapiCallNode")
def find(unicode s, substring):
    """
    >>> def test_find(s, substring):
    ...     py = s.find(substring)
    ...     cy = find(s, substring)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> test_find(text, 'sa')
    16
    """
    cdef Py_ssize_t pos = s.find(substring)
    return pos

@cython.test_fail_if_path_exists(
    "//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//PythonCapiCallNode")
def find_start_end(unicode s, substring, start, end):
    """
    >>> def test_find_start_end(s, substring, start, end):
    ...     py = s.find(substring, start, end)
    ...     cy = find_start_end(s, substring, start, end)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> test_find_start_end(text, 'sa', 17, 25)
    20
    >>> test_find_start_end(text, 'sa', None, None)
    16
    >>> test_find_start_end(text, 'sa', 16, None)
    16
    >>> test_find_start_end(text, 'sa', 17, None)
    20
    >>> test_find_start_end(text, 'sa', None, 16)
    -1
    >>> test_find_start_end(text, 'sa', None, 19)
    16
    """
    cdef Py_ssize_t pos = s.find(substring, start, end)
    return pos


# unicode.rfind(s, sub, [start, [end]])

@cython.test_fail_if_path_exists(
    "//CoerceFromPyTypeNode",
    "//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//PythonCapiCallNode")
def rfind(unicode s, substring):
    """
    >>> def test_rfind(s, substring):
    ...     py = s.rfind(substring)
    ...     cy = rfind(s, substring)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> test_rfind(text, 'sa')
    20
    """
    cdef Py_ssize_t pos = s.rfind(substring)
    return pos

@cython.test_fail_if_path_exists(
    "//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//PythonCapiCallNode")
def rfind_start_end(unicode s, substring, start, end):
    """
    >>> def test_rfind_start_end(s, substring, start, end):
    ...     py = s.rfind(substring, start, end)
    ...     cy = rfind_start_end(s, substring, start, end)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> test_rfind_start_end(text, 'sa', 14, 19)
    16
    >>> test_rfind_start_end(text, 'sa', None, None)
    20
    >>> test_rfind_start_end(text, 'sa', 16, None)
    20
    >>> test_rfind_start_end(text, 'sa', 21, None)
    -1
    >>> test_rfind_start_end(text, 'sa', None, 22)
    20
    >>> test_rfind_start_end(text, 'sa', None, 21)
    16
    """
    cdef Py_ssize_t pos = s.rfind(substring, start, end)
    return pos


# unicode.count(s, sub, [start, [end]])

@cython.test_fail_if_path_exists(
    "//CoerceFromPyTypeNode",
    "//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//PythonCapiCallNode")
def count(unicode s, substring):
    """
    >>> def test_count(s, substring):
    ...     py = s.count(substring)
    ...     cy = count(s, substring)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> test_count(text, 'sa')
    2
    """
    cdef Py_ssize_t pos = s.count(substring)
    return pos

@cython.test_fail_if_path_exists(
    "//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
    "//CoerceToPyTypeNode",
    "//PythonCapiCallNode")
def count_start_end(unicode s, substring, start, end):
    """
    >>> def test_count_start_end(s, substring, start, end):
    ...     py = s.count(substring, start, end)
    ...     cy = count_start_end(s, substring, start, end)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> test_count_start_end(text, 'sa', 14, 21)
    1
    >>> test_count_start_end(text, 'sa', 14, 22)
    2
    >>> test_count_start_end(text, 'sa', None, None)
    2
    >>> test_count_start_end(text, 'sa', 14, None)
    2
    >>> test_count_start_end(text, 'sa', 17, None)
    1
    >>> test_count_start_end(text, 'sa', None, 23)
    2
    >>> test_count_start_end(text, 'sa', None, 20)
    1
    """
    cdef Py_ssize_t pos = s.count(substring, start, end)
    return pos


# unicode.replace(s, sub, repl, [maxcount])

@cython.test_fail_if_path_exists(
    "//CoerceFromPyTypeNode",
    "//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
    "//PythonCapiCallNode")
def replace(unicode s, substring, repl):
    """
    >>> def test_replace(s, substring, repl):
    ...     py = s.replace(substring, repl)
    ...     cy = replace(s, substring, repl)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> print( test_replace(text, 'sa', 'SA') )
    ab jd  sdflk as SA  SAdas asdas fsdf\x20
    """
    return s.replace(substring, repl)

@cython.test_fail_if_path_exists(
    "//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
    "//CoerceFromPyTypeNode",
    "//PythonCapiCallNode")
def replace_maxcount(unicode s, substring, repl, maxcount):
    """
    >>> def test_replace_maxcount(s, substring, repl, maxcount):
    ...     py = s.replace(substring, repl, maxcount)
    ...     cy = replace_maxcount(s, substring, repl, maxcount)
    ...     assert py == cy, (py, cy)
    ...     return cy
    >>> print( test_replace_maxcount(text, 'sa', 'SA', 1) )
    ab jd  sdflk as SA  sadas asdas fsdf\x20
    """
    return s.replace(substring, repl, maxcount)


# unicode * int

@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode",
)
@cython.test_assert_path_exists(
    "//MulNode[@is_sequence_mul = True]",
)
def multiply(unicode ustring, int mul):
    """
    >>> astr = u"abc"
    >>> ustr = u"abcüöä\\U0001F642"

    >>> print(multiply(astr, -1))
    
    >>> print(multiply(ustr, -1))
    

    >>> print(multiply(astr, 0))
    
    >>> print(multiply(ustr, 0))
    

    >>> print(multiply(astr, 1))
    abc
    >>> print(multiply(ustr, 1))
    abcüöä\U0001F642

    >>> print(multiply(astr, 2))
    abcabc
    >>> print(multiply(ustr, 2))
    abcüöä\U0001F642abcüöä\U0001F642

    >>> print(multiply(astr, 5))
    abcabcabcabcabc
    >>> print(multiply(ustr, 5))
    abcüöä\U0001F642abcüöä\U0001F642abcüöä\U0001F642abcüöä\U0001F642abcüöä\U0001F642
    """
    return ustring * mul


#@cython.test_fail_if_path_exists(
#    "//CoerceToPyTypeNode",
#    "//CastNode", "//TypecastNode")
#@cython.test_assert_path_exists(
#    "//PythonCapiCallNode")
def multiply_inplace(unicode ustring, int mul):
    """
    >>> astr = u"abc"
    >>> ustr = u"abcüöä\\U0001F642"

    >>> print(multiply_inplace(astr, -1))
    
    >>> print(multiply_inplace(ustr, -1))
    

    >>> print(multiply_inplace(astr, 0))
    
    >>> print(multiply_inplace(ustr, 0))
    

    >>> print(multiply_inplace(astr, 1))
    abc
    >>> print(multiply_inplace(ustr, 1))
    abcüöä\U0001F642

    >>> print(multiply_inplace(astr, 2))
    abcabc
    >>> print(multiply_inplace(ustr, 2))
    abcüöä\U0001F642abcüöä\U0001F642

    >>> print(multiply_inplace(astr, 5))
    abcabcabcabcabc
    >>> print(multiply_inplace(ustr, 5))
    abcüöä\U0001F642abcüöä\U0001F642abcüöä\U0001F642abcüöä\U0001F642abcüöä\U0001F642
    """
    ustring *= mul
    return ustring


@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode",
)
@cython.test_assert_path_exists(
    "//MulNode[@is_sequence_mul = True]",
)
def multiply_reversed(unicode ustring, int mul):
    """
    >>> astr = u"abc"
    >>> ustr = u"abcüöä\\U0001F642"

    >>> print(multiply_reversed(astr, -1))
    
    >>> print(multiply_reversed(ustr, -1))
    

    >>> print(multiply_reversed(astr, 0))
    
    >>> print(multiply_reversed(ustr, 0))
    

    >>> print(multiply_reversed(astr, 1))
    abc
    >>> print(multiply_reversed(ustr, 1))
    abcüöä\U0001F642

    >>> print(multiply_reversed(astr, 2))
    abcabc
    >>> print(multiply_reversed(ustr, 2))
    abcüöä\U0001F642abcüöä\U0001F642

    >>> print(multiply_reversed(astr, 5))
    abcabcabcabcabc
    >>> print(multiply_reversed(ustr, 5))
    abcüöä\U0001F642abcüöä\U0001F642abcüöä\U0001F642abcüöä\U0001F642abcüöä\U0001F642
    """
    return mul * ustring


@cython.test_fail_if_path_exists(
    "//CoerceToPyTypeNode",
)
def unicode__mul__(unicode ustring, int mul):
    """
    >>> astr = u"abc"
    >>> ustr = u"abcüöä\\U0001F642"

    >>> print(unicode__mul__(astr, -1))
    
    >>> print(unicode__mul__(ustr, -1))
    

    >>> print(unicode__mul__(astr, 0))
    
    >>> print(unicode__mul__(ustr, 0))
    

    >>> print(unicode__mul__(astr, 1))
    abc
    >>> print(unicode__mul__(ustr, 1))
    abcüöä\U0001F642

    >>> print(unicode__mul__(astr, 2))
    abcabc
    >>> print(unicode__mul__(ustr, 2))
    abcüöä\U0001F642abcüöä\U0001F642

    >>> print(unicode__mul__(astr, 5))
    abcabcabcabcabc
    >>> print(unicode__mul__(ustr, 5))
    abcüöä\U0001F642abcüöä\U0001F642abcüöä\U0001F642abcüöä\U0001F642abcüöä\U0001F642
    """
    return ustring.__mul__(mul)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/uninitialized.py0000644000175100001770000000711500000000000020770 0ustar00runnerdocker00000000000000# mode: run
# tag: control-flow, uninitialized

def conditional(cond):
    """
    >>> conditional(True)
    []
    >>> conditional(False)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    UnboundLocalError: ...local variable 'a'...
    """
    if cond:
        a = []
    return a

def inside_loop(iter):
    """
    >>> inside_loop([1,2,3])
    3
    >>> inside_loop([])  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    UnboundLocalError: ...local variable 'i'...
    """
    for i in iter:
        pass
    return i

def try_except(cond):
    """
    >>> try_except(True)
    []
    >>> try_except(False)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    UnboundLocalError: ...local variable 'a'...
    """
    try:
        if cond:
            a = []
        raise ValueError
    except ValueError:
        return a

def try_finally(cond):
    """
    >>> try_finally(True)
    []
    >>> try_finally(False)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    UnboundLocalError: ...local variable 'a'...
    """
    try:
        if cond:
            a = []
        raise ValueError
    finally:
        return a

def deleted(cond):
    """
    >>> deleted(False)
    {}
    >>> deleted(True)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    UnboundLocalError: ...local variable 'a'...
    """
    a = {}
    if cond:
        del a
    return a

def test_nested(cond):
    """
    >>> test_nested(True)
    >>> test_nested(False)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    UnboundLocalError: ...local variable 'a'...
    """
    if cond:
        def a():
            pass
    return a()

def test_outer(cond):
    """
    >>> test_outer(True)
    {}
    >>> test_outer(False)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    UnboundLocalError: ...local variable 'a'...
    """
    if cond:
        a = {}
    def inner():
        return a
    return a

def test_inner(cond):
    """
    >>> test_inner(True)
    {}
    >>> test_inner(False)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    NameError: ...free variable 'a' ... in enclosing scope
    """
    if cond:
        a = {}
    def inner():
        return a
    return inner()

def test_class(cond):
    """
    >>> test_class(True)
    1
    >>> test_class(False)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    UnboundLocalError: ...local variable 'A'...
    """
    if cond:
        class A:
            x = 1
    return A.x


def test_try_except_regression(c):
    """
    >>> test_try_except_regression(True)
    (123,)
    >>> test_try_except_regression(False)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    UnboundLocalError: ...local variable 'a'...
    """
    if c:
        a = (123,)
    try:
        return a
    except:
        return a


def test_try_finally_regression(c):
    """
    >>> test_try_finally_regression(True)
    (123,)
    >>> test_try_finally_regression(False)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    UnboundLocalError: ...local variable 'a'...
    """
    if c:
        a = (123,)
    try:
        return a
    finally:
        return a


def test_expression_calculation_order_bug(a):
    """
    >>> test_expression_calculation_order_bug(False)
    []
    >>> test_expression_calculation_order_bug(True)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    UnboundLocalError: ...local variable 'b'...
    """
    if not a:
        b = []
    return (a or b) and (b or a)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unop.pyx0000644000175100001770000000060400000000000017265 0ustar00runnerdocker00000000000000def f(obj1, obj2, obj3):
    """
    >>> f(1, 2, 3)
    (-3, -4, 1)
    """
    cdef int bool1, bool2
    cdef int int1, int2
    cdef char *str1

    int2 = obj3
    str1 = NULL
    bool2 = 0

    bool1 = not bool2
    obj1 = not obj2
    bool1 = not str1
    int1 = +int2
    obj1 = +obj2
    int1 = -int2
    obj1 = -obj2
    int1 = ~int2
    obj1 = ~obj2
    return obj1, int1, bool1
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unop_extras.pyx0000644000175100001770000000115100000000000020651 0ustar00runnerdocker00000000000000cimport cython.operator
from cython.operator cimport dereference
from cython.operator cimport dereference as deref

def test_deref(int x):
    """
    >>> test_deref(3)
    (3, 3, 3)
    >>> test_deref(5)
    (5, 5, 5)
    """
    cdef int* x_ptr = &x
    return cython.operator.dereference(x_ptr), dereference(x_ptr), deref(x_ptr)

def increment_decrement(int x):
    """
    >>> increment_decrement(10)
    11 11 12
    11 11 10
    10
    """
    print cython.operator.preincrement(x), cython.operator.postincrement(x), x
    print cython.operator.predecrement(x), cython.operator.postdecrement(x), x
    return x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unpack.pyx0000644000175100001770000002265400000000000017576 0ustar00runnerdocker00000000000000# mode: run
# tag: sequence_unpacking

import cython


def _it(N):
    for i in range(N):
        yield i


cdef class ItCount(object):
    cdef object values
    cdef readonly count
    def __init__(self, values):
        self.values = iter(values)
        self.count = 0
    def __iter__(self):
        return self
    def __next__(self):
        self.count += 1
        return next(self.values)

def kunterbunt(obj1, obj2, obj3, obj4, obj5):
    """
    >>> kunterbunt(1, (2,), (3,4,5), (6,(7,(8,9))), 0)
    (8, 9, (8, 9), (6, (7, (8, 9))), 0)
    """
    obj1, = obj2
    obj1, obj2 = obj2 + obj2
    obj1, obj2, obj3 = obj3
    obj1, (obj2, obj3) = obj4
    [obj1, obj2] = obj3
    return obj1, obj2, obj3, obj4, obj5

def unpack_tuple(tuple it):
    """
    >>> unpack_tuple((1,2,3))
    (1, 2, 3)

    >>> a,b,c = None   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> unpack_tuple(None)   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    a,b,c = it
    return a,b,c

def unpack_list(list it):
    """
    >>> unpack_list([1,2,3])
    (1, 2, 3)

    >>> a,b,c = None   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    >>> unpack_list(None)   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...
    """
    a,b,c = it
    return a,b,c

def unpack_to_itself(it):
    """
    >>> it = _it(2)
    >>> it, it = it
    >>> it
    1
    >>> unpack_to_itself([1,2])
    2
    >>> unpack_to_itself((1,2))
    2
    >>> unpack_to_itself(_it(2))
    1
    >>> unpack_to_itself((1,2,3))
    Traceback (most recent call last):
    ValueError: too many values to unpack (expected 2)
    >>> unpack_to_itself(_it(3))
    Traceback (most recent call last):
    ValueError: too many values to unpack (expected 2)
    """
    it, it = it
    return it

def unpack_partial(it):
    """
    >>> it = _it(2)
    >>> a = b = c = 0
    >>> try: a,b,c = it
    ... except ValueError: pass
    ... else: print("DID NOT FAIL!")
    >>> a, b, c
    (0, 0, 0)
    >>> unpack_partial([1,2])
    (0, 0, 0)
    >>> unpack_partial((1,2))
    (0, 0, 0)
    >>> unpack_partial(_it(2))
    (0, 0, 0)

    >>> it = ItCount([1,2])
    >>> a = b = c = 0
    >>> try: a,b,c = it
    ... except ValueError: pass
    ... else: print("DID NOT FAIL!")
    >>> a, b, c
    (0, 0, 0)
    >>> it.count
    3
    >>> it = ItCount([1,2])
    >>> unpack_partial(it)
    (0, 0, 0)
    >>> it.count
    3
    """
    a = b = c = 0
    try:
        a, b, c = it
    except ValueError:
        pass
    return a, b, c

def unpack_fail_assignment(it):
    """
    >>> it = ItCount([1, 2, 3])
    >>> a = b = c = 0
    >>> try: a, b[0], c = it
    ... except TypeError: pass
    >>> a,b,c
    (1, 0, 0)
    >>> it.count
    4
    >>> it = ItCount([1, 2, 3])
    >>> unpack_fail_assignment(it)
    (1, 0, 0)
    >>> it.count
    4
    """
    cdef object a,b,c
    a = b = c = 0
    try:
        a, b[0], c = it
    except TypeError:
        pass
    return a, b, c

def unpack_partial_typed(it):
    """
    >>> unpack_partial_typed([1, 2, 'abc'])
    (0, 0, 0)
    >>> unpack_partial_typed((1, 'abc', 3))
    (0, 0, 0)
    >>> unpack_partial_typed(set([1, 'abc', 3]))
    (0, 0, 0)

    >>> it = ItCount([1, 'abc', 3])
    >>> unpack_partial_typed(it)
    (0, 0, 0)
    >>> it.count
    4
    """
    cdef int a,b,c
    a = b = c = 0
    try:
        a, b, c = it
    except TypeError:
        pass
    return a, b, c

def unpack_typed(it):
    """
    >>> unpack_typed((1, 2.0, [1]))
    (1, 2.0, [1])
    >>> unpack_typed([1, 2.0, [1]])
    (1, 2.0, [1])
    >>> it = ItCount([1, 2.0, [1]])
    >>> unpack_typed(it)
    (1, 2.0, [1])
    >>> it.count
    4

    >>> try: unpack_typed((1, None, [1]))
    ... except TypeError: pass
    >>> try: unpack_typed([1, None, [1]])
    ... except TypeError: pass
    >>> it = ItCount([1, None, [1]])
    >>> try: unpack_typed(it)
    ... except TypeError: pass
    >>> it.count
    4

    >>> unpack_typed((1, 2.0, (1,)))
    Traceback (most recent call last):
    TypeError: Expected list, got tuple
    >>> it = ItCount([1, 2.0, (1,)])
    >>> unpack_typed(it)
    Traceback (most recent call last):
    TypeError: Expected list, got tuple
    >>> it.count
    4
    """
    cdef int a
    cdef float b
    cdef list c
    a,b,c = it
    return a,b,c

def failure_too_many(it):
    """
    >>> try: a,b,c = [1,2,3,4]
    ... except ValueError: pass
    >>> failure_too_many([1,2,3,4])
    Traceback (most recent call last):
    ValueError: too many values to unpack (expected 3)

    >>> try: a,b,c = [1,2,3,4]
    ... except ValueError: pass
    >>> failure_too_many((1,2,3,4))
    Traceback (most recent call last):
    ValueError: too many values to unpack (expected 3)

    >>> a,b,c = set([1,2,3,4])    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: too many values to unpack...
    >>> failure_too_many(set([1,2,3,4]))
    Traceback (most recent call last):
    ValueError: too many values to unpack (expected 3)

    >>> a,b,c = _it(4)    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: too many values to unpack...
    >>> failure_too_many(_it(4))
    Traceback (most recent call last):
    ValueError: too many values to unpack (expected 3)
    """
    a,b,c = it
    return a,b,c


def failure_too_few(it):
    """
    >>> try: a,b,c = [1,2]
    ... except ValueError: pass
    >>> failure_too_few([1,2])
    Traceback (most recent call last):
    ValueError: need more than 2 values to unpack

    >>> try: a,b,c = (1,2)
    ... except ValueError: pass
    >>> failure_too_few((1,2))
    Traceback (most recent call last):
    ValueError: need more than 2 values to unpack

    >>> try: a,b,c = set([1,2])
    ... except ValueError: pass
    ... else: print("DID NOT FAIL!")
    >>> failure_too_few(set([1,2]))
    Traceback (most recent call last):
    ValueError: need more than 2 values to unpack

    >>> try: a,b,c = _it(2)
    ... except ValueError: pass
    ... else: print("DID NOT FAIL!")
    >>> failure_too_few(_it(2))
    Traceback (most recent call last):
    ValueError: need more than 2 values to unpack
    """
    a,b,c = it
    return a,b,c


def _it_failure(N):
    for i in range(N):
        yield i
    raise ValueError("huhu")

def failure_while_unpacking(it):
    """
    >>> a,b,c = _it_failure(0)
    Traceback (most recent call last):
    ValueError: huhu
    >>> failure_while_unpacking(_it_failure(0))
    Traceback (most recent call last):
    ValueError: huhu

    >>> a,b,c = _it_failure(1)
    Traceback (most recent call last):
    ValueError: huhu
    >>> failure_while_unpacking(_it_failure(1))
    Traceback (most recent call last):
    ValueError: huhu

    >>> a,b,c = _it_failure(2)
    Traceback (most recent call last):
    ValueError: huhu
    >>> failure_while_unpacking(_it_failure(2))
    Traceback (most recent call last):
    ValueError: huhu

    >>> a,b,c = _it_failure(3)
    Traceback (most recent call last):
    ValueError: huhu
    >>> failure_while_unpacking(_it_failure(3))
    Traceback (most recent call last):
    ValueError: huhu

    >>> a,b,c = _it_failure(4)    # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: too many values to unpack...
    >>> failure_while_unpacking(_it_failure(4))
    Traceback (most recent call last):
    ValueError: too many values to unpack (expected 3)
    """
    a,b,c = it
    return a,b,c

def unpack_many(it):
    """
    >>> items = range(1,13)
    >>> unpack_many(items)
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    >>> unpack_many(iter(items))
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    >>> unpack_many(list(items))
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    >>> unpack_many(tuple(items))
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    """
    a,b,c,d,e,f,g,h,i,j,k,l = it
    return a,b,c,d,e,f,g,h,i,j,k,l

def unpack_many_tuple(tuple it):
    """
    >>> items = range(1,13)
    >>> unpack_many_tuple(tuple(items))
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    """
    a,b,c,d,e,f,g,h,i,j,k,l = it
    return a,b,c,d,e,f,g,h,i,j,k,l

def unpack_many_list(list it):
    """
    >>> items = range(1,13)
    >>> unpack_many_list(list(items))
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    """
    a,b,c,d,e,f,g,h,i,j,k,l = it
    return a,b,c,d,e,f,g,h,i,j,k,l

def unpack_many_int(it):
    """
    >>> items = range(1,13)
    >>> unpack_many_int(items)
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    >>> unpack_many_int(iter(items))
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    >>> unpack_many_int(list(items))
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    >>> unpack_many_int(tuple(items))
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    """
    cdef int b
    cdef long f
    cdef Py_ssize_t h
    a,b,c,d,e,f,g,h,i,j,k,l = it
    return a,b,c,d,e,f,g,h,i,j,k,l


@cython.test_fail_if_path_exists('//PyTypeTestNode')
def unpack_literal_none_to_builtin_type():
    """
    >>> unpack_literal_none_to_builtin_type()
    (None, None, None, None)
    """
    cdef list a,b,c,d
    a, b = c, d = None, None
    return a,b,c,d


cdef class ExtType:
    pass


@cython.test_fail_if_path_exists('//PyTypeTestNode')
def unpack_literal_none_to_exttype():
    """
    >>> unpack_literal_none_to_exttype()
    (None, None, None, None)
    """
    cdef ExtType a,b,c,d
    a, b = c, d = None, None
    return a,b,c,d


# Github issue #1523
def test_unpack_resultref():
    """
    >>> test_unpack_resultref() == ((1, set()), 1, set())
    True
    """
    a = b, c = 1, set()
    return a, b, c
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unpack_fused.pyx0000644000175100001770000000545600000000000020765 0ustar00runnerdocker00000000000000
ctypedef fused sequence:
    list
    tuple
    object

def unpack_one(sequence it):
    """
    >>> items = [1]
    >>> unpack_one(items)
    1
    >>> unpack_one(iter(items))
    1
    >>> unpack_one(list(items))
    1
    >>> unpack_one(tuple(items))
    1
    """
    a, = it
    return a

def unpack_two(sequence it):
    """
    >>> items = [1,2]
    >>> unpack_two(items)
    (1, 2)
    >>> unpack_two(iter(items))
    (1, 2)
    >>> unpack_two(list(items))
    (1, 2)
    >>> unpack_two(tuple(items))
    (1, 2)
    """
    a,b = it
    return a,b

def unpack_two_int(sequence it):
    """
    >>> items = [1,2]
    >>> unpack_two_int(items)
    (1, 2)
    >>> unpack_two_int(iter(items))
    (1, 2)
    >>> unpack_two_int(list(items))
    (1, 2)
    >>> unpack_two_int(tuple(items))
    (1, 2)

    >>> items = [1, object()]
    >>> unpack_two_int(items)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...int...
    >>> unpack_two_int(iter(items))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...int...
    >>> unpack_two_int(list(items))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...int...
    >>> unpack_two_int(tuple(items))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
    TypeError: ...int...
    """
    cdef int b
    a,b = it
    return a,b

def unpack_many(sequence it):
    """
    >>> items = range(1,13)
    >>> unpack_many(items)
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    >>> unpack_many(iter(items))
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    >>> unpack_many(list(items))
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    >>> unpack_many(tuple(items))
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    """
    a,b,c,d,e,f,g,h,i,j,k,l = it
    return a,b,c,d,e,f,g,h,i,j,k,l

def unpack_many_int(sequence it):
    """
    >>> items = range(1,13)
    >>> unpack_many_int(items)
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    >>> unpack_many_int(iter(items))
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    >>> unpack_many_int(list(items))
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    >>> unpack_many_int(tuple(items))
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)

    >>> items = range(1,10)
    >>> unpack_many_int(items)
    Traceback (most recent call last):
    ValueError: need more than 9 values to unpack
    >>> unpack_many_int(iter(items))
    Traceback (most recent call last):
    ValueError: need more than 9 values to unpack
    >>> unpack_many_int(list(items))
    Traceback (most recent call last):
    ValueError: need more than 9 values to unpack
    >>> unpack_many_int(tuple(items))
    Traceback (most recent call last):
    ValueError: need more than 9 values to unpack
    """
    cdef int b
    cdef long f
    cdef Py_ssize_t h
    a,b,c,d,e,f,g,h,i,j,k,l = it
    return a,b,c,d,e,f,g,h,i,j,k,l
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unpacklistcomp.pyx0000644000175100001770000000123600000000000021342 0ustar00runnerdocker00000000000000def unpack_normal(l):
    """
    >>> unpack_normal([1,2])
    (1, 2)
    >>> unpack_normal([1,2,3]) # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...
    """
    a,b = l
    return a,b

def unpack_comp(l):
    """
    >>> unpack_comp([1,2])
    (1, 2)
    >>> unpack_comp([1,2,3]) # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...
    """
    a,b = [ n for n in l ]
    return a,b

def unpack_expr(l):
    """
    >>> unpack_expr([1,2])
    (1, 4)
    >>> unpack_expr([1,2,3]) # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ValueError: ...
    """
    a,b = [ n*n for n in l ]
    return a,b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unreachable.pyx0000644000175100001770000000024200000000000020553 0ustar00runnerdocker00000000000000# mode: run
# tag: generators unreachable

def with_yield_removed():
    """
    >>> o = with_yield_removed()
    >>> list(o)
    []
    """
    return
    yield
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unsigned.pyx0000644000175100001770000000173300000000000020124 0ustar00runnerdocker00000000000000cdef int i = 1
cdef long l = 2
cdef unsigned int ui = 4
cdef unsigned long ul = 8

def test_add():
    """
    >>> test_add()
    3
    9
    6
    12
    """
    print i + l
    print i + ul
    print ui + l
    print ui + ul

def test_add_sshort_ulong(signed short a, unsigned long b):
    """
    >>> test_add_sshort_ulong(1, 1) == 2
    True
    >>> test_add_sshort_ulong(-1, 1) == 0
    True
    >>> test_add_sshort_ulong(-2, 1) == -1
    False
    """
    return a + b

def test_add_ushort_slonglong(unsigned short a, signed long long b):
    """
    >>> test_add_ushort_slonglong(1, 1) == 2
    True
    >>> test_add_ushort_slonglong(1, -1) == 0
    True
    >>> test_add_ushort_slonglong(1, -2) == -1
    True
    """
    return a + b

def test_add_slong_ulong(signed long a, unsigned long b):
    """
    >>> test_add_slong_ulong(1, 1) == 2
    True
    >>> test_add_slong_ulong(-1, 1) == 0
    True
    >>> test_add_slong_ulong(-2, 1) == -1
    False
    """
    return a + b

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unsigned_char_ptr_bytes_conversion_T359.pyx0000644000175100001770000000124700000000000026205 0ustar00runnerdocker00000000000000# ticket: t359

cdef unsigned char* some_c_unstring = 'test toast taste'

def test_uchar_conversion():
    """
    >>> py_string1, py_string2, py_string3 = test_uchar_conversion()
    >>> print(py_string1.decode('iso8859-1'))
    test toast taste
    >>> print(py_string2.decode('iso8859-1'))
    test toast taste
    >>> print(py_string3.decode('iso8859-1'))
    test toast taste
    """

    cdef object py_string1 = some_c_unstring

    cdef unsigned char* c_unstring_from_py = py_string1
    cdef object py_string2 = c_unstring_from_py

    cdef char* c_string_from_py = py_string2
    cdef object py_string3 = c_string_from_py

    return py_string1, py_string2, py_string3
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unsignedbehaviour_T184.pyx0000644000175100001770000000102100000000000022537 0ustar00runnerdocker00000000000000# ticket: t184

"""
>>> c_call()
(-10, 10)
>>> py_call()
(-10, 10)
>>> loop()
19
>>> rangelist()
[-3, -2, -1, 0, 1, 2]
"""

cdef c_g(int a, int b):
    return (a, b)

def py_g(a, b):
    return (a, b)

def c_call():
    cdef unsigned int i = 10
    return c_g(-i, i)

def py_call():
    cdef unsigned int i = 10
    return py_g(-i, i)

def loop():
    cdef unsigned int i = 10
    times = 0
    for x in range(-i,i):
        times += 1
    return times

def rangelist():
    cdef unsigned int i = 3
    return list(range(-i, i))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unused.pyx0000644000175100001770000000131700000000000017611 0ustar00runnerdocker00000000000000cdef c_unused_simple(a, b, c):
    """
    >>> c_unused_simple(1, 2, 3)
    3
    """
    return a + b

cdef c_unused_optional(a, b, c=1, d=2):
    """
    >>> c_unused_optional(1, 2)
    4
    >>> c_unused_optional(1, 2, 3, 4)
    6
    """
    return b + d

cpdef cp_unused_simple(a, b, c):
    """
    >>> cp_unused_simple(1, 2, 3)
    3
    """
    return a + b

cpdef cp_unused_optional(a, b, c=1, d=2):
    """
    >>> cp_unused_optional(1, 2)
    4
    >>> cp_unused_optional(1, 2, 3, 4)
    6
    """
    return b + d


cdef class Unused:
    """
    >>> o = Unused()
    """

    cpdef cp_unused_simple(self, a, b, c):
        return c

    cpdef cp_unused_optional(self, a, b, c=1, d=2):
        return b + d
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/unused_args.pyx0000644000175100001770000000153300000000000020625 0ustar00runnerdocker00000000000000cdef c_unused_simple(a, b, c):
    """
    >>> c_unused_simple(1, 2, 3)
    3
    """
    return a + b

cdef c_unused_optional(a, b, c=1, d=2):
    """
    >>> c_unused_optional(1, 2)
    4
    >>> c_unused_optional(1, 2, 3, 4)
    6
    """
    return b + d

cpdef cp_unused_simple(a, b, c):
    """
    >>> cp_unused_simple(1, 2, 3)
    3
    """
    return a + b

cpdef cp_unused_optional(a, b, c=1, d=2):
    """
    >>> cp_unused_optional(1, 2)
    4
    >>> cp_unused_optional(1, 2, 3, 4)
    6
    """
    return b + d


cdef class Unused:
    """
    >>> o = Unused()
    """

    cpdef cp_unused_simple(self, a, b, c):
        return c

    cpdef cp_unused_optional(self, a, b, c=1, d=2):
        return b + d

def def_unused(a, b, c):
    """
    >>> def_unused(1, 2, 3)
    """

def def_unused_metho(o):
    """
    >>> def_unused_metho(0)
    """
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/varargcall.pyx0000644000175100001770000000027300000000000020424 0ustar00runnerdocker00000000000000cdef grail(const char *blarg, ...):
    pass


def swallow():
    """
    >>> swallow()
    """
    grail("spam")
    grail("spam", 42)
    grail("spam", b"abc")
    grail("spam", "abc")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/varargdecl.pyx0000644000175100001770000000020300000000000020411 0ustar00runnerdocker00000000000000cdef grail(char *blarg, ...):
    pass

def test():
    """
    >>> test()
    """
    grail(b"test")
    grail(b"test", b"toast")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/verbatiminclude.h0000644000175100001770000000011500000000000021065 0ustar00runnerdocker00000000000000static long cube(long x)
{
    return x * x * x;
}

#define long broken_long
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/verbatiminclude.pyx0000644000175100001770000000172200000000000021463 0ustar00runnerdocker00000000000000cdef extern from "verbatiminclude.h":
    long cube(long)

cdef extern from *:
    """
    static long square(long x)
    {
        return x * x;
    }
    """
    long square(long)


cdef extern from "verbatiminclude.h":
    "typedef int myint;"
    ctypedef int myint

cdef extern from "verbatiminclude.h":
    "#undef long"


cdef class C:
    cdef myint val


cdef extern from "Python.h":
    """
    #define my_SET_SIZE(obj, size)  __Pyx_SET_SIZE(obj, size)
    """
    void my_SET_SIZE(object, Py_ssize_t)


def test_square(x):
    """
    >>> test_square(4)
    16
    """
    return square(x)


def test_cube(x):
    """
    >>> test_cube(4)
    64
    """
    return cube(x)


def test_class():
    """
    >>> test_class()
    42
    """
    cdef C x = C()
    x.val = 42
    return x.val


def test_set_size(x, size):
    # This function manipulates Python objects in a bad way, so we
    # do not call it. The real test is that it compiles.
    my_SET_SIZE(x, size)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/versioned_pxds.srctree0000644000175100001770000000242700000000000022174 0ustar00runnerdocker00000000000000# mode: run
# tag: pxd

"""
PYTHON setup.py build_ext --inplace
PYTHON -c "import runner"
"""

######## setup.py ########

from Cython.Build.Dependencies import cythonize

from distutils.core import setup, Extension

setup(
  ext_modules=cythonize([
    Extension("pkg.m1.a", ["pkg/m1/a.pyx"]),
    Extension("pkg.m2.b", ["pkg/m2/b.pyx"])
  ]),
)

######## pkg/__init__.py ########

######## pkg/m1/__init__.py ########


######## pkg/m1/a.pyx ########

cdef class A:
    def __init__(self):
        self.x = 5

######## pkg/m1/a.pxd ########

to be ignored if there is a more specific file

######## pkg/m1/a.cython-2.pxd ########

very outdated, not to be picked up

######## pkg/m1/a.cython-20.pxd ########

outdated, not to be picked up

######## pkg/m1/a.cython-29.pxd ########

# closest version should get found!

cdef class A:
    cdef public float x

######## pkg/m1/a.cython-300000.pxd ########

Invalid distant future syntax right here!

######## pkg/m1/a.cython-100000.pxd ########

Invalid future syntax right here!


######## pkg/m2/__init__.py ########

######## pkg/m2/b.pyx ########

from pkg.m1.a cimport A

cdef class B(A):
    pass

######## runner.py ########

from pkg.m1.a import A
from pkg.m2.b import B

a = A()
b = B()

assert a.x == 5
assert isinstance(a.x, float), type(a.x)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/voidstarcast.pyx0000644000175100001770000000066000000000000021014 0ustar00runnerdocker00000000000000cdef class C:
    cdef int i

    def foo(self):
        self.i = 42

    def get_i(self):
        return self.i


def cast_cast_cast(arg):
    """
    >>> x = C()
    >>> x.foo()
    >>> cast_cast_cast(x) == x
    True
    >>> x.get_i()
    42
    """
    cdef object x
    cdef void *p = arg
    cdef int i
    x = p
    p = x
    x = (p).foo
    i = (p).i
    (p).i = i
    return p
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/watts1.pyx0000644000175100001770000000021500000000000017525 0ustar00runnerdocker00000000000000def test():
    """
    >>> test() == 55 + 66
    True
    """
    cdef int a,b
    cdef object foo = (55,66)
    a,b = foo
    return a + b
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/weakfail.pyx0000644000175100001770000000072300000000000020071 0ustar00runnerdocker00000000000000import gc
import weakref

foo_dict = weakref.WeakValueDictionary()

cdef class Foo:
    cdef object __weakref__

def test_weakref(key):
    """
    Test af9cfeb5f94d9cd4f2989fc8e111c33208494ba4 fix.
    Originally running it using debug build of python lead to::

      visit_decref: Assertion `gc->gc.gc_refs != 0' failed

    >>> _ = gc.collect()
    >>> _ = test_weakref(48)
    >>> _ = gc.collect()
    """
    obj = Foo()
    foo_dict[key] = obj
    return obj

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/with_gil.pyx0000644000175100001770000002643600000000000020125 0ustar00runnerdocker00000000000000# mode: run
# tag: nogil, withgil

"""
Test the 'with gil:' statement.
"""

cimport cython
from cpython.ref cimport PyObject

import sys


def redirect_stderr(func, *args, **kwargs):
    """
    Helper function that redirects stderr to stdout for doctest.
    """
    stderr, sys.stderr = sys.stderr, sys.stdout
    func(*args, **kwargs)
    sys.stderr = stderr

cdef void puts(char *string) with gil:
    """
    We need this for doctest, used from nogil sections.
    """
    print string.decode('ascii')

class ExceptionWithMsg(Exception):
    """
    In python2.4 Exception is formatted as  when swallowed.
    """

    def __repr__(self):
        return "ExceptionWithMsg(%r)" % self.args


# Start with some normal Python functions

def test_simple():
    """
    >>> test_simple()
    ['spam', 'ham']
    """
    with nogil:
        with gil:
            print ['spam', 'ham']

def test_nested_gil_blocks():
    """
    >>> test_nested_gil_blocks()
    entered outer nogil section
    entered outer gil section
    entered inner nogil section
    entered inner gil section
    leaving inner gil section
    leaving inner nogil section
    leaving outer gil section
    leaving outer nogil section
    """

    with nogil:
        puts("entered outer nogil section")

        with gil:
            print 'entered outer gil section'

            with nogil:
                puts("entered inner nogil section")
                with gil:
                    print 'entered inner gil section'
                    print 'leaving inner gil section'
                puts("leaving inner nogil section")

            print "leaving outer gil section"
        puts("leaving outer nogil section")

def test_propagate_exception():
    """
    >>> test_propagate_exception()
    Traceback (most recent call last):
        ...
    Exception: This exception propagates!
    """
    # Note, doctest doesn't support both output and exceptions
    with nogil:
        with gil:
            raise Exception("This exception propagates!")

def test_catch_exception():
    """
    >>> test_catch_exception()
    This is executed
    Exception value
    This is also executed
    """
    try:
        with nogil:
            with gil:
                print "This is executed"
                raise Exception("Exception value")
                print "This is not executed"
            puts("This is also not executed")
    except Exception, e:
        print e
    print "This is also executed"

def test_try_finally_and_outer_except():
    """
    >>> test_try_finally_and_outer_except()
    First finally clause
    Second finally clause
    Caught: Some Exception
    End of function
    """
    try:

        with nogil:
            with gil:
                try:
                    with nogil:
                        with gil:
                            try:
                                raise Exception("Some Exception")
                            finally:
                                puts("First finally clause")
                finally:
                    puts("Second finally clause")
            puts("This is not executed")

    except Exception, e:
        print "Caught:", e

    print "End of function"

def test_restore_exception():
    """
    >>> test_restore_exception()
    Traceback (most recent call last):
        ...
    Exception: Override the raised exception
    """
    with nogil:
        with gil:
            try:
                with nogil:
                    with gil:
                        raise Exception("Override this please")
            finally:
                raise Exception("Override the raised exception")

### DISABLED: this cannot work with flow control analysis
##
## def test_declared_variables():
##     """
##     >>> test_declared_variables()
##     None
##     None
##     ['s', 'p', 'a', 'm']
##     ['s', 'p', 'a', 'm']
##     """
##     cdef object somevar
##
##     print somevar
##
##     with nogil:
##         with gil:
##             print somevar
##             somevar = list("spam")
##             print somevar
##
##     print somevar

### DISABLED: this cannot work with flow control analysis
##
## def test_undeclared_variables():
##     """
##     >>> test_undeclared_variables()
##     None
##     None
##     ['s', 'p', 'a', 'm']
##     ['s', 'p', 'a', 'm']
##     """
##     print somevar
##     with nogil:
##         with gil:
##             print somevar
##             somevar = list("spam")
##             print somevar
##
##     print somevar

def test_loops_and_boxing():
    """
    >>> test_loops_and_boxing()
    spamham
    h
    a
    m
    done looping
    """
    cdef char c, *string = "spamham"

    with nogil:
        with gil:
            print string.decode('ascii')
            for c in string[4:]:
                print "%c" % c
            else:
                print "done looping"

cdef class SomeExtClass(object):
    cdef int some_attribute

@cython.infer_types(True)
def test_infer_types():
    """
    >>> test_infer_types()
    10
    """
    with nogil:
        with gil:
            obj = SomeExtClass()
            obj.some_attribute = 10

    print obj.some_attribute

def test_closure():
    """
    >>> test_closure()
    Traceback (most recent call last):
        ...
    Exception: {'twinkle': 'little star'}
    """
    a = dict(twinkle='little star')

    def inner_function():
        with nogil:
            with gil:
                raise Exception(a)

    with nogil:
        with gil:
            inner_function()

    raise Exception("This should not be raised!")

cpdef test_cpdef():
    """
    >>> test_cpdef()
    Seems to work!
    Or does it?
    """
    with nogil:
        with gil:
            print "Seems to work!"
        puts("Or does it?")


# Now test some cdef functions with different return types

cdef void void_nogil_ignore_exception() noexcept nogil:
    with gil:
        raise ExceptionWithMsg("This is swallowed")

    puts("unreachable")
    with gil:
        print "unreachable"

cdef void void_nogil_nested_gil() noexcept nogil:
    with gil:
        with nogil:
            with gil:
                print 'Inner gil section'
            puts("nogil section")
        raise ExceptionWithMsg("Swallow this")
    puts("Don't print this")

def test_nogil_void_funcs_with_gil():
    """
    >>> redirect_stderr(test_nogil_void_funcs_with_gil)  # doctest: +ELLIPSIS
    with_gil.ExceptionWithMsg: This is swallowed
    Exception... ignored...
    Inner gil section
    nogil section
    ...
    Exception... ignored...
    """
    void_nogil_ignore_exception()
    void_nogil_nested_gil()

def test_nogil_void_funcs_with_nogil():
    """
    >>> redirect_stderr(test_nogil_void_funcs_with_nogil)  # doctest: +ELLIPSIS
    with_gil.ExceptionWithMsg: This is swallowed
    Exception... ignored...
    Inner gil section
    nogil section
    with_gil.ExceptionWithMsg: Swallow this
    Exception... ignored...
    """
    with nogil:
        void_nogil_ignore_exception()
        void_nogil_nested_gil()


cdef PyObject *nogil_propagate_exception() except NULL nogil:
    with nogil:
        with gil:
            raise Exception("This exception propagates!")
    return  1

def test_nogil_propagate_exception():
    """
    >>> test_nogil_propagate_exception()
    Traceback (most recent call last):
        ...
    Exception: This exception propagates!
    """
    nogil_propagate_exception()


cdef with_gil_raise() with gil:
    raise Exception("This exception propagates!")

def test_release_gil_call_gil_func():
    """
    >>> test_release_gil_call_gil_func()
    Traceback (most recent call last):
        ...
    Exception: This exception propagates!
    """
    with nogil:
        with gil:
            with_gil_raise()


# Test try/finally in nogil blocks

def test_try_finally_in_nogil():
    """
    >>> test_try_finally_in_nogil()
    Traceback (most recent call last):
        ...
    Exception: Override exception!
    """
    with nogil:
        try:
            with gil:
                raise Exception("This will be overridden")
        finally:
            with gil:
                raise Exception("Override exception!")

            with gil:
                raise Exception("This code should not be executed!")

def test_nogil_try_finally_no_exception():
    """
    >>> test_nogil_try_finally_no_exception()
    first nogil try
    nogil try gil
    second nogil try
    nogil finally
    ------
    First with gil block
    Second with gil block
    finally block
    """
    with nogil:
        try:
            puts("first nogil try")
            with gil:
                print "nogil try gil"
            puts("second nogil try")
        finally:
            puts("nogil finally")

    print '------'

    with nogil:
        try:
            with gil:
                print "First with gil block"

            with gil:
                print "Second with gil block"
        finally:
            puts("finally block")

def test_nogil_try_finally_propagate_exception():
    """
    >>> test_nogil_try_finally_propagate_exception()
    Execute finally clause
    Propagate this!
    """
    try:
        with nogil:
            try:
                with gil:
                    raise Exception("Propagate this!")
                with gil:
                    raise Exception("Don't reach this section!")
            finally:
                puts("Execute finally clause")
    except Exception, e:
        print e

def test_nogil_try_finally_return_in_with_gil(x):
    """
    >>> test_nogil_try_finally_return_in_with_gil(10)
    print me
    10
    """
    with nogil:
        try:
            with gil:
                raise Exception("Swallow me!")
        finally:
            with gil:
                print "print me"
                return x

    print "I am not executed"

cdef void nogil_try_finally_return() nogil:
    try:
        with gil:
            raise Exception("I am swallowed in nogil code... right?")
    finally:
        with gil:
            print "print me first"

        return

    with gil:
        print "I am not executed"

def test_nogil_try_finally_return():
    """
    >>> test_nogil_try_finally_return()
    print me first
    """
    with nogil:
        nogil_try_finally_return()

cdef int error_func() except -1 with gil:
    raise Exception("propagate this")

def test_nogil_try_finally_error_label():
    """
    >>> test_nogil_try_finally_error_label()
    print me first
    propagate this
    """
    try:
        with nogil:
            try:
                error_func()
            finally:
                with gil: print "print me first"
    except Exception, e:
        print e.args[0]


def void_with_python_objects():
    """
    >>> void_with_python_objects()
    """
    with nogil:
        _void_with_python_objects()


cdef void _void_with_python_objects() nogil:
    c = 123
    with gil:
        obj1 = [123]
        obj2 = [456]


def void_with_py_arg_reassigned(x):
    """
    >>> void_with_py_arg_reassigned(123)
    """
    with nogil:
        _void_with_py_arg_reassigned(x)


cdef void _void_with_py_arg_reassigned(x) nogil:
    c = 123
    with gil:
        x = [456]


cdef void test_timing_callback() with gil:
  pass

def test_timing(long N):
  """
  >>> sorted([test_timing(10000) for _ in range(10)])  # doctest: +ELLIPSIS
  [...]
  """
  import time
  t = time.time()
  with nogil:
    for _ in range(N):
      test_timing_callback()
  return time.time() - t
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/with_gil_automatic.pyx0000644000175100001770000000617500000000000022171 0ustar00runnerdocker00000000000000# mode: run
# tag: nogil
# cython: language_level=2

cimport cython


#### print

@cython.test_assert_path_exists(
    "//GILStatNode",
    "//GILStatNode//GILStatNode",
    "//GILStatNode//GILStatNode//PrintStatNode",
)
def test_print_in_nogil_section(x):
    """
    >>> test_print_in_nogil_section(123)
    --123--
    """
    with nogil:
        print f"--{x}--"


@cython.test_assert_path_exists(
    "//GILStatNode",
    "//GILStatNode//PrintStatNode",
)
@cython.test_fail_if_path_exists(
    "//GILStatNode//GILStatNode",
)
cpdef int test_print_in_nogil_func(x) except -1 nogil:
    """
    >>> _ = test_print_in_nogil_func(123)
    --123--
    """
    print f"--{x}--"


#### raise

@cython.test_assert_path_exists(
    "//GILStatNode",
    "//GILStatNode//GILStatNode",
    "//GILStatNode//GILStatNode//RaiseStatNode",
)
def test_raise_in_nogil_section(x):
    """
    >>> try: test_raise_in_nogil_section(123)
    ... except ValueError as exc: print(exc)
    ... else: print("NOT RAISED !")
    --123--
    """
    with nogil:
        raise ValueError(f"--{x}--")


@cython.test_assert_path_exists(
    "//GILStatNode",
    "//GILStatNode//RaiseStatNode",
)
@cython.test_fail_if_path_exists(
    "//GILStatNode//GILStatNode",
)
cpdef int test_raise_in_nogil_func(x) except -1 nogil:
    """
    >>> test_raise_in_nogil_func(123)
    Traceback (most recent call last):
    ValueError: --123--
    """
    raise ValueError(f"--{x}--")


#### assert

@cython.test_assert_path_exists(
    "//GILStatNode",
    "//GILStatNode//AssertStatNode",
    "//GILStatNode//AssertStatNode//GILStatNode",
    "//GILStatNode//AssertStatNode//GILStatNode//RaiseStatNode",
)
def assert_in_nogil_section(int x):
    """
    >>> assert_in_nogil_section(123)
    >>> assert_in_nogil_section(0)
    Traceback (most recent call last):
    AssertionError
    """
    with nogil:
        assert x


@cython.test_assert_path_exists(
    "//GILStatNode",
    "//GILStatNode//AssertStatNode",
    "//GILStatNode//AssertStatNode//GILStatNode",
    "//GILStatNode//AssertStatNode//GILStatNode//RaiseStatNode",
)
def assert_in_nogil_section_ustring(int x):
    """
    >>> assert_in_nogil_section_string(123)
    >>> assert_in_nogil_section_string(0)
    Traceback (most recent call last):
    AssertionError: failed!
    """
    with nogil:
        assert x, u"failed!"


@cython.test_assert_path_exists(
    "//GILStatNode",
    "//GILStatNode//AssertStatNode",
    "//GILStatNode//AssertStatNode//GILStatNode",
    "//GILStatNode//AssertStatNode//GILStatNode//RaiseStatNode",
)
def assert_in_nogil_section_string(int x):
    """
    >>> assert_in_nogil_section_string(123)
    >>> assert_in_nogil_section_string(0)
    Traceback (most recent call last):
    AssertionError: failed!
    """
    with nogil:
        assert x, "failed!"


@cython.test_assert_path_exists(
    "//AssertStatNode",
    "//AssertStatNode//GILStatNode",
    "//AssertStatNode//GILStatNode//RaiseStatNode",
)
cpdef int assert_in_nogil_func(int x) except -1 nogil:
    """
    >>> _ = assert_in_nogil_func(123)
    >>> assert_in_nogil_func(0)
    Traceback (most recent call last):
    AssertionError: failed!
    """
    assert x, "failed!"
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/with_statement_module_level_T536.pyx0000644000175100001770000000134600000000000024624 0ustar00runnerdocker00000000000000# ticket: t536

__doc__ = """
>>> inner_result
['ENTER']
>>> result  # doctest: +ELLIPSIS
['ENTER', ...EXIT (<...ValueError...>,...ValueError..., >> inner_result_no_exc
['ENTER']
>>> result_no_exc
['ENTER', 'EXIT (None, None, None)']
"""

class ContextManager(object):
    def __init__(self, result):
        self.result = result
    def __enter__(self):
        self.result.append("ENTER")
    def __exit__(self, *values):
        self.result.append("EXIT %r" % (values,))
        return True

result_no_exc = []

with ContextManager(result_no_exc) as c:
    inner_result_no_exc = result_no_exc[:]

result = []

with ContextManager(result) as c:
    inner_result = result[:]
    raise ValueError('TEST')
    
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/withnogil.pyx0000644000175100001770000000040200000000000020304 0ustar00runnerdocker00000000000000def f(x):
    """
    >>> f(1)
    (1, 17)
    """
    cdef int y
    z = 42
    with nogil:
        y = 17
    z = x
    return z,y

def g():
    """
    >>> g()
    1
    """
    with nogil:
        h()
    return 1

cdef int h() except -1 nogil:
    pass
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/withstat.pyx0000644000175100001770000001336600000000000020164 0ustar00runnerdocker00000000000000from __future__ import with_statement

import sys

def typename(t):
    name = type(t).__name__
    if sys.version_info < (2,5):
        if name == 'classobj' and issubclass(t, MyException):
            name = 'type'
        elif name == 'instance' and isinstance(t, MyException):
            name = 'MyException'
    return u"" % name

class MyException(Exception):
    pass

class ContextManager(object):
    def __init__(self, value, exit_ret = None):
        self.value = value
        self.exit_ret = exit_ret

    def __exit__(self, a, b, tb):
        print u"exit", typename(a), typename(b), typename(tb)
        return self.exit_ret

    def __enter__(self):
        print u"enter"
        return self.value

def no_as():
    """
    >>> no_as()
    enter
    hello
    exit   
    """
    with ContextManager(u"value"):
        print u"hello"

def basic():
    """
    >>> basic()
    enter
    value
    exit   
    """
    with ContextManager(u"value") as x:
        print x

def with_pass():
    """
    >>> with_pass()
    enter
    exit   
    """
    with ContextManager(u"value") as x:
        pass

def with_exception(exit_ret):
    """
    >>> with_exception(None)
    enter
    value
    exit   
    outer except
    >>> with_exception(True)
    enter
    value
    exit   
    """
    try:
        with ContextManager(u"value", exit_ret=exit_ret) as value:
            print value
            raise MyException()
    except:
        print u"outer except"

def multitarget():
    """
    >>> multitarget()
    enter
    1 2 3 4 5
    exit   
    """
    with ContextManager((1, 2, (3, (4, 5)))) as (a, b, (c, (d, e))):
        print a, b, c, d, e

def tupletarget():
    """
    >>> tupletarget()
    enter
    (1, 2, (3, (4, 5)))
    exit   
    """
    with ContextManager((1, 2, (3, (4, 5)))) as t:
        print t

def typed():
    """
    >>> typed()
    enter
    10
    exit   
    """
    cdef unsigned char i
    c = ContextManager(255)
    with c as i:
        i += 11
        print i

def multimanager():
    """
    >>> multimanager()
    enter
    enter
    enter
    enter
    enter
    enter
    2
    value
    1 2 3 4 5
    nested
    exit   
    exit   
    exit   
    exit   
    exit   
    exit   
    """
    with ContextManager(1), ContextManager(2) as x, ContextManager(u'value') as y,\
            ContextManager(3), ContextManager((1, 2, (3, (4, 5)))) as (a, b, (c, (d, e))):
        with ContextManager(u'nested') as nested:
            print x
            print y
            print a, b, c, d, e
            print nested

# Tests borrowed from pyregr test_with.py,
# modified to follow the constraints of Cython.
import unittest

class Dummy(object):
    def __init__(self, value=None, gobble=False):
        if value is None:
            value = self
        self.value = value
        self.gobble = gobble
        self.enter_called = False
        self.exit_called = False

    def __enter__(self):
        self.enter_called = True
        return self.value

    def __exit__(self, *exc_info):
        self.exit_called = True
        self.exc_info = exc_info
        if self.gobble:
            return True

class InitRaises(object):
    def __init__(self): raise RuntimeError()

class EnterRaises(object):
    def __enter__(self): raise RuntimeError()
    def __exit__(self, *exc_info): pass

class ExitRaises(object):
    def __enter__(self): pass
    def __exit__(self, *exc_info): raise RuntimeError()

class NestedWith(unittest.TestCase):
    """
    >>> NestedWith().runTest()
    """

    def runTest(self):
        self.testNoExceptions()
        self.testExceptionInExprList()
        self.testExceptionInEnter()
        self.testExceptionInExit()
        self.testEnterReturnsTuple()

    def testNoExceptions(self):
        with Dummy() as a, Dummy() as b:
            self.assertTrue(a.enter_called)
            self.assertTrue(b.enter_called)
        self.assertTrue(a.exit_called)
        self.assertTrue(b.exit_called)

    def testExceptionInExprList(self):
        try:
            with Dummy() as a, InitRaises():
                pass
        except:
            pass
        self.assertTrue(a.enter_called)
        self.assertTrue(a.exit_called)

    def testExceptionInEnter(self):
        try:
            with Dummy() as a, EnterRaises():
                self.fail('body of bad with executed')
        except RuntimeError:
            pass
        else:
            self.fail('RuntimeError not reraised')
        self.assertTrue(a.enter_called)
        self.assertTrue(a.exit_called)

    def testExceptionInExit(self):
        body_executed = False
        with Dummy(gobble=True) as a, ExitRaises():
            body_executed = True
        self.assertTrue(a.enter_called)
        self.assertTrue(a.exit_called)
        self.assertTrue(body_executed)
        self.assertNotEqual(a.exc_info[0], None)

    def testEnterReturnsTuple(self):
        with Dummy(value=(1,2)) as (a1, a2), \
             Dummy(value=(10, 20)) as (b1, b2):
            self.assertEqual(1, a1)
            self.assertEqual(2, a2)
            self.assertEqual(10, b1)
            self.assertEqual(20, b2)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/withstat_py.py0000644000175100001770000001146600000000000020503 0ustar00runnerdocker00000000000000import sys


def typename(t):
    name = type(t).__name__
    if sys.version_info < (2,5):
        if name == 'classobj' and issubclass(t, MyException):
            name = 'type'
        elif name == 'instance' and isinstance(t, MyException):
            name = 'MyException'
    return "" % name


class MyException(Exception):
    pass


class ContextManager(object):
    def __init__(self, value, exit_ret = None):
        self.value = value
        self.exit_ret = exit_ret

    def __exit__(self, a, b, tb):
        print("exit %s %s %s" % (typename(a), typename(b), typename(tb)))
        return self.exit_ret

    def __enter__(self):
        print("enter")
        return self.value


def no_as():
    """
    >>> no_as()
    enter
    hello
    exit   
    """
    with ContextManager("value"):
        print("hello")


def basic():
    """
    >>> basic()
    enter
    value
    exit   
    """
    with ContextManager("value") as x:
        print(x)


def with_pass():
    """
    >>> with_pass()
    enter
    exit   
    """
    with ContextManager("value") as x:
        pass


def with_return():
    """
    >>> print(with_return())
    enter
    exit   
    value
    """
    with ContextManager("value") as x:
        return x


def with_break():
    """
    >>> print(with_break())
    enter
    exit   
    a
    """
    for c in list("abc"):
        with ContextManager("value") as x:
            break
        print("FAILED")
    return c


def with_continue():
    """
    >>> print(with_continue())
    enter
    exit   
    enter
    exit   
    enter
    exit   
    c
    """
    for c in list("abc"):
        with ContextManager("value") as x:
            continue
        print("FAILED")
    return c


def with_exception(exit_ret):
    """
    >>> with_exception(None)
    enter
    value
    exit   
    outer except
    >>> with_exception(True)
    enter
    value
    exit   
    """
    try:
        with ContextManager("value", exit_ret=exit_ret) as value:
            print(value)
            raise MyException()
    except:
        print("outer except")


def with_real_lock():
    """
    >>> with_real_lock()
    about to acquire lock
    holding lock
    lock no longer held
    """
    from threading import Lock
    lock = Lock()

    print("about to acquire lock")

    with lock:
        print("holding lock")

    print("lock no longer held")


def functions_in_with():
    """
    >>> f = functions_in_with()
    enter
    exit   
    outer except
    >>> f(1)[0]
    1
    >>> print(f(1)[1])
    value
    """
    try:
        with ContextManager("value") as value:
            def f(x): return x, value
            make = lambda x:x()
            raise make(MyException)
    except:
        print("outer except")
    return f


def multitarget():
    """
    >>> multitarget()
    enter
    1 2 3 4 5
    exit   
    """
    with ContextManager((1, 2, (3, (4, 5)))) as (a, b, (c, (d, e))):
        print('%s %s %s %s %s' % (a, b, c, d, e))


def tupletarget():
    """
    >>> tupletarget()
    enter
    (1, 2, (3, (4, 5)))
    exit   
    """
    with ContextManager((1, 2, (3, (4, 5)))) as t:
        print(t)


class GetManager(object):
    def get(self, *args):
        return ContextManager(*args)


def manager_from_expression():
    """
    >>> manager_from_expression()
    enter
    1
    exit   
    enter
    2
    exit   
    """
    with GetManager().get(1) as x:
        print(x)
    g = GetManager()
    with g.get(2) as x:
        print(x)

def manager_from_ternary(use_first):
    """
    >>> manager_from_ternary(True)
    enter
    exit   
    >>> manager_from_ternary(False)
    enter
    exit   
    In except
    """
    # This is mostly testing a parsing problem, hence the
    # result of the ternary must be callable
    cm1_getter = lambda: ContextManager("1", exit_ret=True)
    cm2_getter = lambda: ContextManager("2")
    try:
        with (cm1_getter if use_first else cm2_getter)():
            raise ValueError
    except ValueError:
        print("In except")
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/withstat_py27.py0000644000175100001770000001101100000000000020636 0ustar00runnerdocker00000000000000import sys


def typename(t):
    name = type(t).__name__
    if sys.version_info < (2,5):
        if name == 'classobj' and issubclass(t, MyException):
            name = 'type'
        elif name == 'instance' and isinstance(t, MyException):
            name = 'MyException'
    return "" % name


class MyException(Exception):
    pass


class ContextManager(object):
    def __init__(self, value, exit_ret = None):
        self.value = value
        self.exit_ret = exit_ret

    def __exit__(self, a, b, tb):
        print("exit %s %s %s" % (typename(a), typename(b), typename(tb)))
        return self.exit_ret

    def __enter__(self):
        print("enter")
        return self.value


def multimanager():
    """
    >>> multimanager()
    enter
    enter
    enter
    enter
    enter
    enter
    2
    value
    1 2 3 4 5
    nested
    exit   
    exit   
    exit   
    exit   
    exit   
    exit   
    """
    with ContextManager(1), ContextManager(2) as x, ContextManager('value') as y,\
            ContextManager(3), ContextManager((1, 2, (3, (4, 5)))) as (a, b, (c, (d, e))):
        with ContextManager('nested') as nested:
            print(x)
            print(y)
            print('%s %s %s %s %s' % (a, b, c, d, e))
            print(nested)


class GetManager(object):
    def get(self, *args):
        return ContextManager(*args)

def manager_from_expression():
    """
    >>> manager_from_expression()
    enter
    1
    exit   
    enter
    2
    exit   
    """
    with GetManager().get(1) as x:
        print(x)
    g = GetManager()
    with g.get(2) as x:
        print(x)


# Tests borrowed from pyregr test_with.py,
# modified to follow the constraints of Cython.
import unittest

class Dummy(object):
    def __init__(self, value=None, gobble=False):
        if value is None:
            value = self
        self.value = value
        self.gobble = gobble
        self.enter_called = False
        self.exit_called = False

    def __enter__(self):
        self.enter_called = True
        return self.value

    def __exit__(self, *exc_info):
        self.exit_called = True
        self.exc_info = exc_info
        if self.gobble:
            return True

class InitRaises(object):
    def __init__(self): raise RuntimeError()

class EnterRaises(object):
    def __enter__(self): raise RuntimeError()
    def __exit__(self, *exc_info): pass

class ExitRaises(object):
    def __enter__(self): pass
    def __exit__(self, *exc_info): raise RuntimeError()

class NestedWith(unittest.TestCase):
    """
    >>> NestedWith().runTest()
    """

    def runTest(self):
        self.testNoExceptions()
        self.testExceptionInExprList()
        self.testExceptionInEnter()
        self.testExceptionInExit()
        self.testEnterReturnsTuple()

    def testNoExceptions(self):
        with Dummy() as a, Dummy() as b:
            self.assertTrue(a.enter_called)
            self.assertTrue(b.enter_called)
        self.assertTrue(a.exit_called)
        self.assertTrue(b.exit_called)

    def testExceptionInExprList(self):
        try:
            with Dummy() as a, InitRaises():
                pass
        except:
            pass
        self.assertTrue(a.enter_called)
        self.assertTrue(a.exit_called)

    def testExceptionInEnter(self):
        try:
            with Dummy() as a, EnterRaises():
                self.fail('body of bad with executed')
        except RuntimeError:
            pass
        else:
            self.fail('RuntimeError not reraised')
        self.assertTrue(a.enter_called)
        self.assertTrue(a.exit_called)

    def testExceptionInExit(self):
        body_executed = False
        with Dummy(gobble=True) as a, ExitRaises():
            body_executed = True
        self.assertTrue(a.enter_called)
        self.assertTrue(a.exit_called)
        self.assertTrue(body_executed)
        self.assertNotEqual(a.exc_info[0], None)

    def testEnterReturnsTuple(self):
        with Dummy(value=(1,2)) as (a1, a2), \
             Dummy(value=(10, 20)) as (b1, b2):
            self.assertEqual(1, a1)
            self.assertEqual(2, a2)
            self.assertEqual(10, b1)
            self.assertEqual(20, b2)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/wundram1.pyx0000644000175100001770000000011000000000000020032 0ustar00runnerdocker00000000000000"""
>>> x == 5 or repr(x)
True
"""


cdef unsigned int ui
ui = 5
x = ui
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/yield_from_pep380.pyx0000644000175100001770000006170600000000000021546 0ustar00runnerdocker00000000000000# -*- coding: utf-8 -*-

"""
Test suite for PEP 380 implementation

adapted from original tests written by Greg Ewing
see 
"""

import sys


def _lines(trace):
    for line in trace:
        print(line)


def test_delegation_of_initial_next_to_subgenerator():
    """
    >>> _lines(test_delegation_of_initial_next_to_subgenerator())
    Starting g1
    Starting g2
    Yielded 42
    Finishing g2
    Finishing g1
    """
    trace = []
    def g1():
        trace.append("Starting g1")
        yield from g2()
        trace.append("Finishing g1")
    def g2():
        trace.append("Starting g2")
        yield 42
        trace.append("Finishing g2")
    for x in g1():
        trace.append("Yielded %s" % (x,))
    return trace

def test_raising_exception_in_initial_next_call():
    """
    >>> _lines(test_raising_exception_in_initial_next_call())
    Starting g1
    Starting g2
    Finishing g2
    Finishing g1
    """
    trace = []
    def g1():
        try:
            trace.append("Starting g1")
            yield from g2()
        finally:
            trace.append("Finishing g1")
    def g2():
        try:
            trace.append("Starting g2")
            raise ValueError("spanish inquisition occurred")
        finally:
            trace.append("Finishing g2")
    try:
        for x in g1():
            trace.append("Yielded %s" % (x,))
    except ValueError as e:
        pass
    else:
        trace.append("subgenerator failed to raise ValueError")
    return trace

def test_delegation_of_next_call_to_subgenerator():
    """
    >>> _lines(test_delegation_of_next_call_to_subgenerator())
    Starting g1
    Yielded g1 ham
    Starting g2
    Yielded g2 spam
    Yielded g2 more spam
    Finishing g2
    Yielded g1 eggs
    Finishing g1
    """
    trace = []
    def g1():
        trace.append("Starting g1")
        yield "g1 ham"
        yield from g2()
        yield "g1 eggs"
        trace.append("Finishing g1")
    def g2():
        trace.append("Starting g2")
        yield "g2 spam"
        yield "g2 more spam"
        trace.append("Finishing g2")
    for x in g1():
        trace.append("Yielded %s" % (x,))
    return trace

def test_raising_exception_in_delegated_next_call():
    """
    >>> _lines(test_raising_exception_in_delegated_next_call())
    Starting g1
    Yielded g1 ham
    Starting g2
    Yielded g2 spam
    Finishing g2
    Finishing g1
    """
    trace = []
    def g1():
        try:
            trace.append("Starting g1")
            yield "g1 ham"
            yield from g2()
            yield "g1 eggs"
        finally:
            trace.append("Finishing g1")
    def g2():
        try:
            trace.append("Starting g2")
            yield "g2 spam"
            raise ValueError("hovercraft is full of eels")
            yield "g2 more spam"
        finally:
            trace.append("Finishing g2")
    try:
        for x in g1():
            trace.append("Yielded %s" % (x,))
    except ValueError:
        pass
    else:
        trace.append("subgenerator failed to raise ValueError")
    return trace

def test_delegation_of_send():
    """
    >>> _lines(test_delegation_of_send())
    Starting g1
    g1 received 1
    Starting g2
    Yielded g2 spam
    g2 received 2
    Yielded g2 more spam
    g2 received 3
    Finishing g2
    Yielded g1 eggs
    g1 received 4
    Finishing g1
    """
    trace = []
    def g1():
        trace.append("Starting g1")
        x = yield "g1 ham"
        trace.append("g1 received %s" % (x,))
        yield from g2()
        x = yield "g1 eggs"
        trace.append("g1 received %s" % (x,))
        trace.append("Finishing g1")
    def g2():
        trace.append("Starting g2")
        x = yield "g2 spam"
        trace.append("g2 received %s" % (x,))
        x = yield "g2 more spam"
        trace.append("g2 received %s" % (x,))
        trace.append("Finishing g2")
    g = g1()
    y = next(g)
    x = 1
    try:
        while 1:
            y = g.send(x)
            trace.append("Yielded %s" % (y,))
            x += 1
    except StopIteration:
        pass
    return trace

def test_handling_exception_while_delegating_send():
    """
    >>> _lines(test_handling_exception_while_delegating_send())
    Starting g1
    g1 received 1
    Starting g2
    Yielded g2 spam
    g2 received 2
    """
    trace = []
    def g1():
        trace.append("Starting g1")
        x = yield "g1 ham"
        trace.append("g1 received %s" % (x,))
        yield from g2()
        x = yield "g1 eggs"
        trace.append("g1 received %s" % (x,))
        trace.append("Finishing g1")
    def g2():
        trace.append("Starting g2")
        x = yield "g2 spam"
        trace.append("g2 received %s" % (x,))
        raise ValueError("hovercraft is full of eels")
        x = yield "g2 more spam"
        trace.append("g2 received %s" % (x,))
        trace.append("Finishing g2")
    def run():
        g = g1()
        y = next(g)
        x = 1
        try:
            while 1:
                y = g.send(x)
                trace.append("Yielded %s" % (y,))
                x += 1
        except StopIteration:
            trace.append("StopIteration")
    try:
        run()
    except ValueError:
        pass # ok
    else:
        trace.append("no ValueError")
    return trace

def test_delegating_close():
    """
    >>> _lines(test_delegating_close())
    Starting g1
    Yielded g1 ham
    Starting g2
    Yielded g2 spam
    Finishing g2
    Finishing g1
    """
    trace = []
    def g1():
        try:
            trace.append("Starting g1")
            yield "g1 ham"
            yield from g2()
            yield "g1 eggs"
        finally:
            trace.append("Finishing g1")
    def g2():
        try:
            trace.append("Starting g2")
            yield "g2 spam"
            yield "g2 more spam"
        finally:
            trace.append("Finishing g2")
    g = g1()
    for i in range(2):
        x = next(g)
        trace.append("Yielded %s" % (x,))
    g.close()
    return trace

def test_handing_exception_while_delegating_close():
    """
    >>> _lines(test_handing_exception_while_delegating_close())
    Starting g1
    Yielded g1 ham
    Starting g2
    Yielded g2 spam
    Finishing g2
    Finishing g1
    nybbles have exploded with delight
    """
    trace = []
    def g1():
        try:
            trace.append("Starting g1")
            yield "g1 ham"
            yield from g2()
            yield "g1 eggs"
        finally:
            trace.append("Finishing g1")
    def g2():
        try:
            trace.append("Starting g2")
            yield "g2 spam"
            yield "g2 more spam"
        finally:
            trace.append("Finishing g2")
            raise ValueError("nybbles have exploded with delight")
    try:
        g = g1()
        for i in range(2):
            x = next(g)
            trace.append("Yielded %s" % (x,))
        g.close()
    except ValueError as e:
        trace.append(e.args[0])
        # FIXME: __context__ is currently not set
        #if sys.version_info[0] >= 3:
        #    assert isinstance(e.__context__, GeneratorExit), 'exception context is %r' % e.__context__
    else:
        trace.append("subgenerator failed to raise ValueError")
    return trace

def test_delegating_throw():
    """
    >>> _lines(test_delegating_throw())
    Starting g1
    Yielded g1 ham
    Starting g2
    Yielded g2 spam
    Finishing g2
    Finishing g1
    """
    trace = []
    def g1():
        try:
            trace.append("Starting g1")
            yield "g1 ham"
            yield from g2()
            yield "g1 eggs"
        finally:
            trace.append("Finishing g1")
    def g2():
        try:
            trace.append("Starting g2")
            yield "g2 spam"
            yield "g2 more spam"
        finally:
            trace.append("Finishing g2")
    try:
        g = g1()
        for i in range(2):
            x = next(g)
            trace.append("Yielded %s" % (x,))
        e = ValueError("tomato ejected")
        g.throw(e)
    except ValueError:
        pass
    else:
        trace.append("subgenerator failed to raise ValueError")
    return trace

def __test_value_attribute_of_StopIteration_exception():
    """
    StopIteration:
    value = None
    StopIteration: spam
    value = spam
    StopIteration: spam
    value = eggs
    """
    trace = []
    def pex(e):
        trace.append("%s: %s" % (e.__class__.__name__, e))
        trace.append("value = %s" % (e.value,))
    e = StopIteration()
    pex(e)
    e = StopIteration("spam")
    pex(e)
    e.value = "eggs"
    pex(e)
    return trace


def test_exception_value_crash():
    """
    >>> test_exception_value_crash()
    ['g2']
    """
    # There used to be a refcount error in CPython when the return value
    # stored in the StopIteration has a refcount of 1.
    def g1():
        yield from g2()
    def g2():
        yield "g2"
        return [42]
    return list(g1())


def test_return_none():
    """
    >>> test_return_none()
    ['g2']
    """
    # There used to be a refcount error in CPython when the return value
    # stored in the StopIteration has a refcount of 1.
    def g1():
        yield from g2()
    def g2():
        yield "g2"
        return None
    return list(g1())


def test_finally_return_none(raise_exc=None):
    """
    >>> gen = test_finally_return_none()
    >>> next(gen)
    'g2'
    >>> next(gen)
    Traceback (most recent call last):
    StopIteration

    >>> gen = test_finally_return_none()
    >>> next(gen)
    'g2'
    >>> try: gen.throw(ValueError())
    ... except StopIteration: pass
    ... else: print("FAILED")
    """
    # There used to be a refcount error in CPython when the return value
    # stored in the StopIteration has a refcount of 1.
    def g1():
        yield from g2()
    def g2():
        try:
            yield "g2"
        finally:
            return None
    return g1()


def test_generator_return_value():
    """
    >>> _lines(test_generator_return_value())
    Starting g1
    Yielded g1 ham
    Starting g2
    Yielded g2 spam
    Yielded g2 more spam
    Finishing g2
    g2 returned None
    Starting g2
    Yielded g2 spam
    Yielded g2 more spam
    Finishing g2
    g2 returned 42
    Yielded g1 eggs
    Finishing g1
    """
    trace = []
    def g1():
        trace.append("Starting g1")
        yield "g1 ham"
        ret = yield from g2()
        trace.append("g2 returned %s" % (ret,))
        ret = yield from g2(42)
        trace.append("g2 returned %s" % (ret,))
        yield "g1 eggs"
        trace.append("Finishing g1")
    def g2(v = None):
        trace.append("Starting g2")
        yield "g2 spam"
        yield "g2 more spam"
        trace.append("Finishing g2")
        if v:
            return v
    for x in g1():
        trace.append("Yielded %s" % (x,))
    return trace

def test_delegation_of_next_to_non_generator():
    """
    >>> _lines(test_delegation_of_next_to_non_generator())
    Yielded 0
    Yielded 1
    Yielded 2
    """
    trace = []
    def g():
        yield from range(3)
    for x in g():
        trace.append("Yielded %s" % (x,))
    return trace

def test_conversion_of_sendNone_to_next():
    """
    >>> _lines(test_conversion_of_sendNone_to_next())
    Yielded: 0
    Yielded: 1
    Yielded: 2
    """
    trace = []
    def g():
        yield from range(3)
    gi = g()
    for x in range(3):
        y = gi.send(None)
        trace.append("Yielded: %s" % (y,))
    return trace

def test_delegation_of_close_to_non_generator():
    """
    >>> _lines(test_delegation_of_close_to_non_generator())
    starting g
    finishing g
    """
    trace = []
    def g():
        try:
            trace.append("starting g")
            yield from range(3)
            trace.append("g should not be here")
        finally:
            trace.append("finishing g")
    gi = g()
    next(gi)
    gi.close()
    return trace

def test_delegating_throw_to_non_generator():
    """
    >>> _lines(test_delegating_throw_to_non_generator())
    Starting g
    Yielded 0
    Yielded 1
    Yielded 2
    Yielded 3
    Yielded 4
    Finishing g
    """
    trace = []
    def g():
        try:
            trace.append("Starting g")
            yield from range(10)
        finally:
            trace.append("Finishing g")
    try:
        gi = g()
        for i in range(5):
            x = next(gi)
            trace.append("Yielded %s" % (x,))
        e = ValueError("tomato ejected")
        gi.throw(e)
    except ValueError:
        pass
    else:
        trace.append("subgenerator failed to raise ValueError")
    return trace

def test_attempting_to_send_to_non_generator():
    """
    >>> _lines(test_attempting_to_send_to_non_generator())
    starting g
    finishing g
    """
    trace = []
    def g():
        try:
            trace.append("starting g")
            yield from range(3)
            trace.append("g should not be here")
        finally:
            trace.append("finishing g")
    try:
        gi = g()
        next(gi)
        for x in range(3):
            y = gi.send(42)
            trace.append("Should not have yielded: %s" % y)
    except AttributeError:
        pass
    else:
        trace.append("was able to send into non-generator")
    return trace

def test_broken_getattr_handling():
    """
    >>> test_broken_getattr_handling()
    []
    """
    class Broken:
        def __iter__(self):
            return self
        def __next__(self):
            return 1
        next = __next__
        def __getattr__(self, attr):
            1/0

    def g():
        yield from Broken()

    not_raised = []
    try:
        gi = g()
        assert next(gi) == 1
        gi.send(1)
    except ZeroDivisionError:
        pass
    else:
        not_raised.append(1)

    try:
        gi = g()
        assert next(gi) == 1
        gi.throw(AttributeError)
    except ZeroDivisionError:
        pass
    else:
        not_raised.append(2)

    """
    # this currently only calls PyErr_WriteUnraisable() and doesn't raise ...
    try:
        gi = g()
        assert next(gi) == 1
        gi.close()
    except ZeroDivisionError:
        pass
    else:
        not_raised.append(3)
    """
    gi = g()
    assert next(gi) == 1
    gi.close()

    return not_raised

def test_exception_in_initial_next_call():
    """
    >>> _lines(test_exception_in_initial_next_call())
    g1 about to yield from g2
    """
    trace = []
    def g1():
        trace.append("g1 about to yield from g2")
        yield from g2()
        trace.append("g1 should not be here")
    def g2():
        yield 1/0
    def run():
        gi = g1()
        next(gi)
    try:
        run()
    except ZeroDivisionError:
        pass
    else:
        trace.append("ZeroDivisionError not raised")
    return trace

def test_attempted_yield_from_loop():
    """
    >>> _lines(test_attempted_yield_from_loop())
    g1: starting
    Yielded: y1
    g1: about to yield from g2
    g2: starting
    Yielded: y2
    g2: about to yield from g1
    """
    trace = []
    def g1():
        trace.append("g1: starting")
        yield "y1"
        trace.append("g1: about to yield from g2")
        yield from g2()
        trace.append("g1 should not be here")

    def g2():
        trace.append("g2: starting")
        yield "y2"
        trace.append("g2: about to yield from g1")
        yield from gi
        trace.append("g2 should not be here")
    try:
        gi = g1()
        for y in gi:
            trace.append("Yielded: %s" % (y,))
    except ValueError:
        pass # "generator already executing"
    else:
        trace.append("subgenerator didn't raise ValueError")
    return trace

def test_attempted_reentry():
    """
    >>> _lines(test_attempted_reentry())
    g1: starting
    Yielded: y1
    g1: about to yield from g2
    g2: starting
    Yielded: y2
    g2: about to yield from g1
    g2: caught ValueError
    Yielded: y3
    g1: after delegating to g2
    Yielded: y4
    """
    trace = []
    def g1():
        trace.append("g1: starting")
        yield "y1"
        trace.append("g1: about to yield from g2")
        yield from g2()
        trace.append("g1: after delegating to g2")
        yield "y4"

    def g2():
        trace.append("g2: starting")
        yield "y2"
        trace.append("g2: about to yield from g1")
        try:
            yield from gi
        except ValueError:
            trace.append("g2: caught ValueError")
        else:
            trace.append("g1 did not raise ValueError on reentry")
        yield "y3"
    gi = g1()
    for y in gi:
        trace.append("Yielded: %s" % (y,))
    return trace

def test_returning_value_from_delegated_throw():
    """
    >>> _lines(test_returning_value_from_delegated_throw())
    Starting g1
    Yielded g1 ham
    Starting g2
    Yielded g2 spam
    Caught LunchError in g2
    Yielded g2 yet more spam
    Yielded g1 eggs
    Finishing g1
    """
    trace = []
    def g1():
        try:
            trace.append("Starting g1")
            yield "g1 ham"
            yield from g2()
            yield "g1 eggs"
        finally:
            trace.append("Finishing g1")
    def g2():
        try:
            trace.append("Starting g2")
            yield "g2 spam"
            yield "g2 more spam"
        except LunchError:
            trace.append("Caught LunchError in g2")
            yield "g2 lunch saved"
            yield "g2 yet more spam"
    class LunchError(Exception):
        pass
    g = g1()
    for i in range(2):
        x = next(g)
        trace.append("Yielded %s" % (x,))
    e = LunchError("tomato ejected")
    g.throw(e)
    for x in g:
        trace.append("Yielded %s" % (x,))
    return trace

def test_next_and_return_with_value():
    """
    >>> _lines(test_next_and_return_with_value())
    g starting
    f resuming g
    g returning None
    f caught StopIteration
    g starting
    f resuming g
    g returning 42
    f caught StopIteration
    """
    trace = []
    def f(r):
        gi = g(r)
        next(gi)
        try:
            trace.append("f resuming g")
            next(gi)
            trace.append("f SHOULD NOT BE HERE")
        except StopIteration:
            trace.append("f caught StopIteration")
    def g(r):
        trace.append("g starting")
        yield
        trace.append("g returning %s" % (r,))
        return r
    f(None)
    f(42)
    return trace

def test_send_and_return_with_value():
    """
    >>> _lines(test_send_and_return_with_value())
    g starting
    f sending spam to g
    g received spam
    g returning None
    f caught StopIteration
    g starting
    f sending spam to g
    g received spam
    g returning 42
    f caught StopIteration
    """
    trace = []
    def f(r):
        gi = g(r)
        next(gi)
        try:
            trace.append("f sending spam to g")
            gi.send("spam")
            trace.append("f SHOULD NOT BE HERE")
        except StopIteration:
            trace.append("f caught StopIteration")
    def g(r):
        trace.append("g starting")
        x = yield
        trace.append("g received %s" % (x,))
        trace.append("g returning %s" % (r,))
        return r
    f(None)
    f(42)
    return trace

def test_catching_exception_from_subgen_and_returning():
    """
    Test catching an exception thrown into a
    subgenerator and returning a value

    >>> _lines(test_catching_exception_from_subgen_and_returning())
    1
    inner caught ValueError
    inner returned 2 to outer
    2
    """
    trace = []
    def inner():
        try:
            yield 1
        except ValueError:
            trace.append("inner caught ValueError")
        return 2

    def outer():
        v = yield from inner()
        trace.append("inner returned %r to outer" % v)
        yield v
    g = outer()
    trace.append(next(g))
    trace.append(g.throw(ValueError))
    return trace

def test_throwing_GeneratorExit_into_subgen_that_returns():
    """
    Test throwing GeneratorExit into a subgenerator that
    catches it and returns normally.

    >>> _lines(test_throwing_GeneratorExit_into_subgen_that_returns())
    Enter g
    Enter f
    """
    trace = []
    def f():
        try:
            trace.append("Enter f")
            yield
            trace.append("Exit f")
        except GeneratorExit:
            return
    def g():
        trace.append("Enter g")
        yield from f()
        trace.append("Exit g")
    try:
        gi = g()
        next(gi)
        gi.throw(GeneratorExit)
    except GeneratorExit:
        pass
    else:
        trace.append("subgenerator failed to raise GeneratorExit")
    return trace

def test_throwing_GeneratorExit_into_subgenerator_that_yields():
    """
    Test throwing GeneratorExit into a subgenerator that
    catches it and yields.

    >>> _lines(test_throwing_GeneratorExit_into_subgenerator_that_yields())
    Enter g
    Enter f
    """
    trace = []
    def f():
        try:
            trace.append("Enter f")
            yield
            trace.append("Exit f")
        except GeneratorExit:
            yield
    def g():
        trace.append("Enter g")
        yield from f()
        trace.append("Exit g")
    try:
        gi = g()
        next(gi)
        gi.throw(GeneratorExit)
    except RuntimeError:
        pass # "generator ignored GeneratorExit"
    else:
        trace.append("subgenerator failed to raise GeneratorExit")
    return trace

def test_throwing_GeneratorExit_into_subgen_that_raises():
    """
    Test throwing GeneratorExit into a subgenerator that
    catches it and raises a different exception.

    >>> _lines(test_throwing_GeneratorExit_into_subgen_that_raises())
    Enter g
    Enter f
    """
    trace = []
    def f():
        try:
            trace.append("Enter f")
            yield
            trace.append("Exit f")
        except GeneratorExit:
            raise ValueError("Vorpal bunny encountered")
    def g():
        trace.append("Enter g")
        yield from f()
        trace.append("Exit g")
    try:
        gi = g()
        next(gi)
        gi.throw(GeneratorExit)
    except ValueError:
        pass # "Vorpal bunny encountered"
    else:
        trace.append("subgenerator failed to raise ValueError")
    return trace

def test_yield_from_empty():
    """
    >>> test_yield_from_empty()
    """
    def g():
        yield from ()
    try:
        next(g())
    except StopIteration:
        pass
    else:
        return "FAILED"

# test re-entry guards

def _reentering_gen():
    def one():
        yield 0
        yield from two()
        yield 3
    def two():
        yield 1
        try:
            yield from g1
        except ValueError:
            pass
        yield 2
    g1 = one()
    return g1

def test_delegating_generators_claim_to_be_running_next():
    """
    >>> test_delegating_generators_claim_to_be_running_next()
    [0, 1, 2, 3]
    """
    return list(_reentering_gen())

def test_delegating_generators_claim_to_be_running_send():
    """
    >>> test_delegating_generators_claim_to_be_running_send()
    [0, 1, 2, 3]
    """
    g1 = _reentering_gen()
    res = [next(g1)]
    try:
        while True:
            res.append(g1.send(42))
    except StopIteration:
        pass
    return res

def test_delegating_generators_claim_to_be_running_throw():
    """
    >>> test_delegating_generators_claim_to_be_running_throw()
    [0, 1, 2, 3]
    """
    class MyErr(Exception):
        pass
    def one():
        try:
            yield 0
        except MyErr:
            pass
        yield from two()
        try:
            yield 3
        except MyErr:
            pass
    def two():
        try:
            yield 1
        except MyErr:
            pass
        try:
            yield from g1
        except ValueError:
            pass
        try:
            yield 2
        except MyErr:
            pass
    g1 = one()
    res = [next(g1)]
    try:
        while True:
            res.append(g1.throw(MyErr))
    except StopIteration:
        pass
    return res

def test_delegating_generators_claim_to_be_running_close():
    """
    >>> test_delegating_generators_claim_to_be_running_close()
    42
    """
    class MyIt(object):
        def __iter__(self):
            return self
        def __next__(self):
            return 42
        next = __next__
        def close(self):
            assert g1.gi_running
            try:
                next(g1)
            except ValueError:
                pass # guard worked
            else:
                assert False, "re-entry guard failed to bark"
    def one():
        yield from MyIt()
    g1 = one()
    ret = next(g1)
    g1.close()
    return ret


def yield_in_return(x):
    """
    >>> x = yield_in_return(range(3))
    >>> for _ in range(10):
    ...     try:
    ...         print(next(x))
    ...     except StopIteration:
    ...         if sys.version_info >= (3,3):
    ...             print(sys.exc_info()[1].value is None)
    ...         else:
    ...             print(True)
    ...         break
    0
    1
    2
    True
    """
    return (yield from x)


def gi_yieldfrom(it):
    """
    >>> it = iter([1, 2, 3])
    >>> g = gi_yieldfrom(it)
    >>> g.gi_yieldfrom is None or "ERROR: %r" % g.gi_yieldfrom
    True
    >>> next(g)
    1
    >>> g.gi_yieldfrom is it or "ERROR: %r" % g.gi_yieldfrom
    True
    """
    x = yield from it
    return x
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/yield_from_py33.pyx0000644000175100001770000000065500000000000021321 0ustar00runnerdocker00000000000000# mode: run
# tag: generator

def yield_from_gen(values):
    """
    >>> def yf(x): yield from x
    >>> list(yf(yield_from_gen([1, 2, 3, 4])))
    [1, 2, 3, 4]
    """
    for value in values:
        yield value


def yield_from_gen_return(values):
    """
    >>> def yf(x): yield from x
    >>> list(yf(yield_from_gen_return([1, 2, 3, 4])))
    [1, 2, 3, 4]
    """
    for value in values:
        yield value
    return 5
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/run/yield_inside_lambda.py0000644000175100001770000000041200000000000022052 0ustar00runnerdocker00000000000000# mode: run
# tag: generators, lambda


def test_inside_lambda():
    """
    >>> obj = test_inside_lambda()()
    >>> next(obj)
    1
    >>> next(obj)
    2
    >>> try: next(obj)
    ... except StopIteration: pass
    """
    return lambda:((yield 1), (yield 2))
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.2367241
Cython-3.0.8/tests/testsupport/0000755000175100001770000000000000000000000017352 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/testsupport/cythonarrayutil.pxi0000644000175100001770000000135500000000000023341 0ustar00runnerdocker00000000000000from libc.stdlib cimport malloc, free
cimport cython
from cython.view cimport array

cdef void callback(void *data) noexcept:
    print("callback called")
    free(data)

def create_array(shape, mode, use_callback=False):
    cdef array result = array(shape, itemsize=sizeof(int),
                              format='i', mode=mode)
    cdef int *data =  result.data
    cdef int i, j, cidx, fidx

    for i in range(shape[0]):
        for j in range(shape[1]):
            cidx = i * shape[1] + j
            fidx = i + j * shape[0]

            if mode == 'fortran':
                data[fidx] = cidx
            else:
                data[cidx] = cidx

    if use_callback:
        result.callback_free_data = callback

    return result
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/windows_bugs.txt0000644000175100001770000000123500000000000020212 0ustar00runnerdocker00000000000000common_include_dir
cythonize_script
cythonize_script_excludes
cythonize_script_package
initial_file_path
package_compilation

carray_coercion
int_float_builtins_as_casts_T400
int_float_builtins_as_casts_T400_long_double
list_pop
test_coroutines_pep492
type_inference

parallel
numpy_parallel
py_unicode_type

test_grammar

# Those tests don't work because MSVC wants to link to the c-algorithms library
# when compiling and we don't want to download c-algorithms just for those tests.
queue
queue2
queue3
lunch

# "C linkage function cannot return C++ class" (uses public C++ cdef function)
cpp_template_subclasses

# MSVC lacks "complex.h"
complex_numbers_cmath_T2891
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880491.2367241
Cython-3.0.8/tests/wrappers/0000755000175100001770000000000000000000000016601 5ustar00runnerdocker00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/wrappers/cpp_overload_wrapper.pyx0000644000175100001770000000273600000000000023570 0ustar00runnerdocker00000000000000# tag: cpp

cimport cpp_overload_wrapper_lib as cppwrap_lib

cdef class DoubleKeeper:
    """
    >>> d = DoubleKeeper()
    >>> d.get_number()
    1.0
    >>> d.set_number(5.5)
    >>> d.get_number()
    5.5
    >>> d.set_number(0)
    >>> d.get_number()
    0.0
    """
    cdef cppwrap_lib.DoubleKeeper* keeper

    def __cinit__(self, number=None):
        if number is None:
            self.keeper = new cppwrap_lib.DoubleKeeper()
        else:
            self.keeper = new cppwrap_lib.DoubleKeeper(number)

    def __dealloc__(self):
        del self.keeper

    def set_number(self, number=None):
        if number is None:
            self.keeper.set_number()
        else:
            self.keeper.set_number(number)

    def get_number(self):
        return self.keeper.get_number()

    def transmogrify(self, double value):
        """
        >>> d = DoubleKeeper(5.5)
        >>> d.transmogrify(1.0)
        5.5
        >>> d.transmogrify(2.0)
        11.0
        """
        return self.keeper.transmogrify(value)


def voidfunc():
    """
    >>> voidfunc()
    """
    cppwrap_lib.voidfunc()

def doublefunc(double x, double y, double z):
    """
    >>> doublefunc(1.0, 2.0, 3.0) == 1.0 + 2.0 + 3.0
    True
    """
    return cppwrap_lib.doublefunc(x, y, z)

def transmogrify_from_cpp(DoubleKeeper obj not None, double value):
    """
    >>> d = DoubleKeeper(2.0)
    >>> d.transmogrify(3.0) == 6.0
    True
    """
    return cppwrap_lib.transmogrify_from_cpp(obj.keeper, value)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/wrappers/cpp_overload_wrapper_lib.cpp0000644000175100001770000000125400000000000024352 0ustar00runnerdocker00000000000000
#include "cpp_overload_wrapper_lib.h"

void voidfunc (void)
{
}

double doublefunc (double a, double b, double c)
{
    return a + b + c;
}


DoubleKeeper::DoubleKeeper ()
    : number (1.0)
{
}

DoubleKeeper::DoubleKeeper (double factor)
    : number (factor)
{
}

DoubleKeeper::~DoubleKeeper ()
{
}

double DoubleKeeper::get_number () const
{
    return number;
}

void DoubleKeeper::set_number (double f)
{
    number = f;
}

void DoubleKeeper::set_number ()
{
    number = 1.0;
}

double
DoubleKeeper::transmogrify (double value) const
{
    return value*number;
}


double
transmogrify_from_cpp (DoubleKeeper const *obj, double value)
{
    return obj->transmogrify (value);
}

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/wrappers/cpp_overload_wrapper_lib.h0000644000175100001770000000077400000000000024025 0ustar00runnerdocker00000000000000#ifndef CPP_OVERLOAD_WRAPPER_LIB_H
#define CPP_OVERLOAD_WRAPPER_LIB_H
void voidfunc(void);

double doublefunc (double a, double b, double c);


class DoubleKeeper
{
    double number;

public:
    DoubleKeeper ();
    DoubleKeeper (double number);
    virtual ~DoubleKeeper ();

    void set_number (double num);
    void set_number (void);
    double get_number () const;
    virtual double transmogrify (double value) const;
};

double transmogrify_from_cpp (DoubleKeeper const *obj, double value);
#endif
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/wrappers/cpp_overload_wrapper_lib.pxd0000644000175100001770000000072300000000000024363 0ustar00runnerdocker00000000000000cdef extern from "cpp_overload_wrapper_lib.cpp":
    pass
cdef extern from "cpp_overload_wrapper_lib.h":
    void voidfunc()
    double doublefunc(double a, double b, double c)

    cdef cppclass DoubleKeeper:
        DoubleKeeper()
        DoubleKeeper(double factor)
        void set_number()
        void set_number(double f)
        double get_number()
        double transmogrify(double value)

    double transmogrify_from_cpp (DoubleKeeper *obj, double value)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/wrappers/cpp_references.pyx0000644000175100001770000000240500000000000022327 0ustar00runnerdocker00000000000000# tag: cpp

cimport cython


cdef extern from "cpp_references_helper.h":
    cdef int& ref_func(int&)
    cdef int& except_ref_func "ref_func" (int&) except +

    cdef int ref_var_value
    cdef int& ref_var


def test_ref_func(int x):
    """
    >>> test_ref_func(2)
    2
    >>> test_ref_func(3)
    3
    """
    return ref_func(x)

def test_ref_func_address(int x):
    """
    >>> test_ref_func_address(5)
    5
    >>> test_ref_func_address(7)
    7
    """
    cdef int* i_ptr = &ref_func(x)
    return i_ptr[0]

def test_except_ref_func_address(int x):
    """
    >>> test_except_ref_func_address(5)
    5
    >>> test_except_ref_func_address(7)
    7
    """
    cdef int* i_ptr = &except_ref_func(x)
    return i_ptr[0]

def test_ref_var(int x):
    """
    >>> test_ref_func(11)
    11
    >>> test_ref_func(13)
    13
    """
    ref_var = x
    return ref_var_value

def test_ref_assign(int x):
    """
    >>> test_ref_assign(17)
    17.0
    >>> test_ref_assign(19)
    19.0
    """
    cdef double d = ref_func(x)
    return d

@cython.infer_types(True)
def test_ref_inference(int x):
    """
    >>> test_ref_inference(23)
    23
    >>> test_ref_inference(29)
    29
    """
    z = ref_func(x)
    assert cython.typeof(z) == "int", cython.typeof(z)
    return z
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/wrappers/cpp_references_helper.h0000644000175100001770000000013400000000000023272 0ustar00runnerdocker00000000000000
int ref_var_value = 10;
int& ref_var = ref_var_value;

int& ref_func(int& x) { return x; }
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/wrappers/cppwrap.pyx0000644000175100001770000000225300000000000021021 0ustar00runnerdocker00000000000000# tag: cpp

cimport cppwrap_lib

cdef class DoubleKeeper:
    """
    >>> d = DoubleKeeper(1.0)
    >>> d.get_number() == 1.0
    True
    >>> d.get_number() == 2.0
    False
    >>> d.set_number(2.0)
    >>> d.get_number() == 2.0
    True
    >>> d.transmogrify(3.0) == 6.0
    True
    """
    cdef cppwrap_lib.DoubleKeeper* keeper

    def __cinit__(self, double number):
        self.keeper = new cppwrap_lib.DoubleKeeper(number)

    def __dealloc__(self):
        del self.keeper

    def set_number(self, double number):
        self.keeper.set_number(number)

    def get_number(self):
        return self.keeper.get_number()

    def transmogrify(self, double value):
        return self.keeper.transmogrify(value)


def voidfunc():
    """
    >>> voidfunc()
    """
    cppwrap_lib.voidfunc()

def doublefunc(double x, double y, double z):
    """
    >>> doublefunc(1.0, 2.0, 3.0) == 1.0 + 2.0 + 3.0
    True
    """
    return cppwrap_lib.doublefunc(x, y, z)

def transmogrify_from_cpp(DoubleKeeper obj not None, double value):
    """
    >>> d = DoubleKeeper(2.0)
    >>> d.transmogrify(3.0) == 6.0
    True
    """
    return cppwrap_lib.transmogrify_from_cpp(obj.keeper, value)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/wrappers/cppwrap_lib.cpp0000644000175100001770000000106000000000000021604 0ustar00runnerdocker00000000000000
#include "cppwrap_lib.h"

void voidfunc (void)
{
}

double doublefunc (double a, double b, double c)
{
    return a + b + c;
}

DoubleKeeper::DoubleKeeper (double factor)
    : number (factor)
{
}

DoubleKeeper::~DoubleKeeper ()
{
}

double DoubleKeeper::get_number () const
{
    return number;
}

void DoubleKeeper::set_number (double f)
{
    number = f;
}

double
DoubleKeeper::transmogrify (double value) const
{
    return value*number;
}


double
transmogrify_from_cpp (DoubleKeeper const *obj, double value)
{
    return obj->transmogrify (value);
}

././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/wrappers/cppwrap_lib.h0000644000175100001770000000066100000000000021257 0ustar00runnerdocker00000000000000#ifndef CPPWRAP_LIB_H
#define CPPWRAP_LIB_H
void voidfunc(void);

double doublefunc (double a, double b, double c);


class DoubleKeeper
{
    double number;

public:
    DoubleKeeper (double number);
    virtual ~DoubleKeeper ();

    void set_number (double num);
    double get_number () const;
    virtual double transmogrify (double value) const;
};

double transmogrify_from_cpp (DoubleKeeper const *obj, double value);
#endif
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tests/wrappers/cppwrap_lib.pxd0000644000175100001770000000061000000000000021615 0ustar00runnerdocker00000000000000cdef extern from "cppwrap_lib.cpp":
    pass
cdef extern from "cppwrap_lib.h":
    void voidfunc()
    double doublefunc(double a, double b, double c)

    cdef cppclass DoubleKeeper:
        DoubleKeeper(double factor)
        void set_number(double f)
        double get_number()
        double transmogrify(double value)

    double transmogrify_from_cpp (DoubleKeeper *obj, double value)
././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1704880488.4327223
Cython-3.0.8/tox.ini0000644000175100001770000000062000000000000015105 0ustar00runnerdocker00000000000000# Tox (http://tox.testrun.org/) is a tool for running tests
# in multiple virtualenvs. This configuration file will run the
# test suite on all supported python versions. To use it, "pip install tox"
# and then run "tox" from this directory.

[tox]
envlist = py27, py34, py35, py36, py37, py38, py39, py310, py311, pypy

[testenv]
setenv = CFLAGS=-O0 -ggdb
commands =
    {envpython} runtests.py -vv